-
Tim van Dijen authoredTim van Dijen authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
DatabaseTest.php 9.78 KiB
<?php
declare(strict_types=1);
namespace SimpleSAML\Test;
use PHPUnit\Framework\TestCase;
use SimpleSAML\Configuration;
use SimpleSAML\Database;
/**
* This test ensures that the \SimpleSAML\Database class can properly
* query a database.
*
* It currently uses sqlite to test, but an alternate config.php file
* should be created for test cases to ensure that it will work
* in an environment.
*
* @author Tyler Antonio, University of Alberta. <tantonio@ualberta.ca>
* @package SimpleSAMLphp
*/
class DatabaseTest extends TestCase
{
/**
* @var \SimpleSAML\Configuration
*/
protected $config;
/**
* @var \SimpleSAML\Database
*/
protected $db;
/**
* Make protected functions available for testing
*
* @param string $getMethod The method to get.
* @return mixed The method itself.
*/
protected static function getMethod($getMethod)
{
$class = new \ReflectionClass(Database::class);
$method = $class->getMethod($getMethod);
$method->setAccessible(true);
return $method;
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @return void
*/
public function setUp()
{
$config = [
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => [],
];
$this->config = new Configuration($config, "test/SimpleSAML/DatabaseTest.php");
// Ensure that we have a functional configuration class
$this->assertInstanceOf(Configuration::class, $this->config);
$this->assertEquals($config['database.dsn'], $this->config->getString('database.dsn'));
$this->db = Database::getInstance($this->config);
// Ensure that we have a functional database class.
$this->assertInstanceOf(Database::class, $this->db);
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @test
* @return void
*/
public function connectionFailure()
{
$this->expectException(\Exception::class);
$config = [
'database.dsn' => 'mysql:host=localhost;dbname=saml',
'database.username' => 'notauser',
'database.password' => 'notausersinvalidpassword',
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => [],
];
$this->config = new Configuration($config, "test/SimpleSAML/DatabaseTest.php");
Database::getInstance($this->config);
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @test
* @return void
*/
public function instances()
{
$config = [
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => [],
];
$config2 = [
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit2_',
'database.persistent' => true,
'database.slaves' => [],
];
$config1 = new Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$config2 = new Configuration($config2, "test/SimpleSAML/DatabaseTest.php");
$config3 = new Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$db1 = Database::getInstance($config1);
$db2 = Database::getInstance($config2);
$db3 = Database::getInstance($config3);
$generateInstanceId = self::getMethod('generateInstanceId');
$instance1 = $generateInstanceId->invokeArgs($db1, [$config1]);
$instance2 = $generateInstanceId->invokeArgs($db2, [$config2]);
$instance3 = $generateInstanceId->invokeArgs($db3, [$config3]);
// Assert that $instance1 and $instance2 have different instance ids
$this->assertNotEquals(
$instance1,
$instance2,
"Database instances should be different, but returned the same id"
);
// Assert that $instance1 and $instance3 have identical instance ids
$this->assertEquals(
$instance1,
$instance3,
"Database instances should have the same id, but returned different id"
);
// Assert that $db1 and $db2 are different instances
$this->assertNotEquals(
spl_object_hash($db1),
spl_object_hash($db2),
"Database instances should be different, but returned the same spl_object_hash"
);
// Assert that $db1 and $db3 are identical instances
$this->assertEquals(
spl_object_hash($db1),
spl_object_hash($db3),
"Database instances should be the same, but returned different spl_object_hash"
);
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @covers SimpleSAML\Database::getSlave
* @test
* @return void
*/
public function slaves()
{
$getSlave = self::getMethod('getSlave');
$master = spl_object_hash(\PHPUnit\Framework\Assert::readAttribute($this->db, 'dbMaster'));
$slave = spl_object_hash($getSlave->invokeArgs($this->db, []));
$this->assertTrue(($master == $slave), "getSlave should have returned the master database object");
$config = [
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => [
[
'dsn' => 'sqlite::memory:',
'username' => null,
'password' => null,
],
],
];
$sspConfiguration = new Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$msdb = Database::getInstance($sspConfiguration);
$slaves = \PHPUnit\Framework\Assert::readAttribute($msdb, 'dbSlaves');
$gotSlave = spl_object_hash($getSlave->invokeArgs($msdb, []));
$this->assertEquals(
spl_object_hash($slaves[0]),
$gotSlave,
"getSlave should have returned a slave database object"
);
}
/**
* @covers SimpleSAML\Database::applyPrefix
* @test
* @return void
*/
public function prefix()
{
$prefix = $this->config->getString('database.prefix');
$table = "saml20_idp_hosted";
$pftable = $this->db->applyPrefix($table);
$this->assertEquals($prefix . $table, $pftable, "Did not properly apply the table prefix");
}
/**
* @covers SimpleSAML\Database::write
* @covers SimpleSAML\Database::read
* @covers SimpleSAML\Database::exec
* @covers SimpleSAML\Database::query
* @test
* @return void
*/
public function querying()
{
$table = $this->db->applyPrefix("sspdbt");
$this->assertEquals($this->config->getString('database.prefix') . "sspdbt", $table);
$this->db->write(
"CREATE TABLE IF NOT EXISTS $table (ssp_key INT(16) NOT NULL, ssp_value TEXT NOT NULL)"
);
/** @var \PDOStatement $query1 */
$query1 = $this->db->read("SELECT * FROM $table");
$this->assertEquals(0, $query1->fetch(), "Table $table is not empty when it should be.");
$ssp_key = time();
$ssp_value = md5(strval(rand(0, 10000)));
$stmt = $this->db->write(
"INSERT INTO $table (ssp_key, ssp_value) VALUES (:ssp_key, :ssp_value)",
['ssp_key' => [$ssp_key, \PDO::PARAM_INT], 'ssp_value' => $ssp_value]
);
$this->assertEquals(1, $stmt, "Could not insert data into $table.");
/** @var \PDOStatement $query2 */
$query2 = $this->db->read("SELECT * FROM $table WHERE ssp_key = :ssp_key", ['ssp_key' => $ssp_key]);
$data = $query2->fetch();
$this->assertEquals($data['ssp_value'], $ssp_value, "Inserted data doesn't match what is in the database");
}
/**
* @covers SimpleSAML\Database::read
* @covers SimpleSAML\Database::query
* @test
* @return void
*/
public function readFailure()
{
$this->expectException(\Exception::class);
$table = $this->db->applyPrefix("sspdbt");
$this->assertEquals($this->config->getString('database.prefix') . "sspdbt", $table);
$this->db->read("SELECT * FROM $table");
}
/**
* @covers SimpleSAML\Database::write
* @covers SimpleSAML\Database::exec
* @test
* @return void
*/
public function noSuchTable()
{
$this->expectException(\Exception::class);
$this->db->write("DROP TABLE phpunit_nonexistent");
}
/**
* @return void
*/
public function tearDown()
{
$table = $this->db->applyPrefix("sspdbt");
$this->db->write("DROP TABLE IF EXISTS $table");
unset($this->config);
unset($this->db);
}
}