Browse Source

Generic database interface creation in tests

microsub
J. King 6 years ago
parent
commit
4e444fd86c
  1. 64
      tests/cases/Db/TestResult.php
  2. 73
      tests/cases/Db/TestStatement.php
  3. 55
      tests/lib/AbstractTest.php

64
tests/cases/Db/TestResult.php

@ -16,37 +16,35 @@ use JKingWeb\Arsse\Db\SQLite3\PDODriver;
* @covers \JKingWeb\Arsse\Db\SQLite3\Result<extended> * @covers \JKingWeb\Arsse\Db\SQLite3\Result<extended>
*/ */
class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
public function provideDrivers() { public function provideResults() {
$this->setConf(); $this->setConf();
$drvSqlite3 = (function() { $interfaces = $this->provideDbInterfaces();
if (\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet()) { $constructors = [
$d = new \SQLite3(Arsse::$conf->dbSQLite3File); 'SQLite 3' => function(string $query) use($interfaces) {
$d->enableExceptions(true); $drv = $interfaces['SQLite 3']['interface'];
return $d; $set = $drv->query($query);
} $rows = $drv->changes();
})(); $id = $drv->lastInsertRowID();
$drvPdo = (function() {
if (\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) {
return new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
}
})();
return [
'SQLite 3' => [isset($drvSqlite3), false, \JKingWeb\Arsse\Db\SQLite3\Result::class, function(string $query) use($drvSqlite3) {
$set = $drvSqlite3->query($query);
$rows = $drvSqlite3->changes();
$id = $drvSqlite3->lastInsertRowID();
return [$set, [$rows, $id]]; return [$set, [$rows, $id]];
}], },
'PDO' => [isset($drvPdo), true, \JKingWeb\Arsse\Db\PDOResult::class, function(string $query) use($drvPdo) {
$set = $drvPdo->query($query);
$rows = $set->rowCount();
$id = $drvPdo->lastInsertID();
return [$set, [$rows, $id]];
}],
]; ];
foreach ($constructors as $drv => $func) {
yield $drv => [isset($interfaces[$drv]['interface']), $interfaces[$drv]['stringOutput'], $interfaces[$drv]['result'], $func];
}
// there is only one PDO result implementation, so we test the first implementation we find
$pdo = array_reduce($interfaces, function ($carry, $item) {
return $carry ?? ($item['interface'] instanceof \PDO ? $item : null);
}) ?? $interfaces['PDO SQLite 3'];
yield "PDO" => [isset($pdo['interface']), $pdo['stringOutput'], $pdo['result'], function(string $query) use($pdo) {
$drv = $pdo['interface'];
$set = $drv->query($query);
$rows = $set->rowCount();
$id = $drv->lastInsertID();
return [$set, [$rows, $id]];
}];
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testConstructResult(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testConstructResult(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -54,7 +52,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertInstanceOf(Result::class, new $class(...$func("SELECT 1"))); $this->assertInstanceOf(Result::class, new $class(...$func("SELECT 1")));
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testGetChangeCountAndLastInsertId(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testGetChangeCountAndLastInsertId(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -68,7 +66,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame((int) $id, $r->lastId()); $this->assertSame((int) $id, $r->lastId());
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testIterateOverResults(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testIterateOverResults(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -81,7 +79,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame($exp, $rows); $this->assertSame($exp, $rows);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testIterateOverResultsTwice(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testIterateOverResultsTwice(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -99,7 +97,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
} }
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testGetSingleValues(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testGetSingleValues(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -113,7 +111,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame(null, $test->getValue()); $this->assertSame(null, $test->getValue());
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testGetFirstValuesOnly(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testGetFirstValuesOnly(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -127,7 +125,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame(null, $test->getValue()); $this->assertSame(null, $test->getValue());
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testGetRows(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testGetRows(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -142,7 +140,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame(null, $test->getRow()); $this->assertSame(null, $test->getRow());
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideResults */
public function testGetAllRows(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testGetAllRows(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();

73
tests/cases/Db/TestStatement.php

@ -16,47 +16,28 @@ use JKingWeb\Arsse\Db\PDOStatement;
* @covers \JKingWeb\Arsse\Db\PDOStatement<extended> * @covers \JKingWeb\Arsse\Db\PDOStatement<extended>
* @covers \JKingWeb\Arsse\Db\PDOError */ * @covers \JKingWeb\Arsse\Db\PDOError */
class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
public function provideDrivers() { public function provideStatements() {
$this->setConf(); $interfaces = $this->provideDbInterfaces();
$drvSqlite3 = (function() { $constructors = [
if (\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet()) { 'SQLite 3' => function(string $query, array $types = []) use($interfaces) {
$d = new \SQLite3(Arsse::$conf->dbSQLite3File); $s = $interfaces['SQLite 3']['interface']->prepare($query);
$d->enableExceptions(true); return [$interfaces['SQLite 3']['interface'], $s, $types];
return $d; },
} 'PDO SQLite 3' => function(string $query, array $types = []) use($interfaces) {
})(); $s = $interfaces['PDO SQLite 3']['interface']->prepare($query);
$drvPgsql = (function() { return [$interfaces['PDO SQLite 3']['interface'], $s, $types];
if (\JKingWeb\Arsse\Db\PostgreSQL\PDODriver::requirementsMet()) { },
$connString = \JKingWeb\Arsse\Db\PostgreSQL\Driver::makeConnectionString(true, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, Arsse::$conf->dbPostgreSQLDb, Arsse::$conf->dbPostgreSQLHost, Arsse::$conf->dbPostgreSQLPort, ""); 'PDO PostgreSQL' => function(string $query, array $types = []) use($interfaces) {
$c = new \PDO("pgsql:".$connString, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]); $s = $interfaces['PDO PostgreSQL']['interface']->prepare($query);
foreach (\JKingWeb\Arsse\Db\PostgreSQL\PDODriver::makeSetupQueries(Arsse::$conf->dbPostgreSQLSchema) as $q) { return [$interfaces['PDO PostgreSQL']['interface'], $s, $types];
$c->exec($q); },
}
return $c;
}
})();
$drvPdo = (function() {
if (\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) {
return new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
}
})();
return [
'SQLite 3' => [isset($drvSqlite3), false, \JKingWeb\Arsse\Db\SQLite3\Statement::class, function(string $query, array $types = []) use($drvSqlite3) {
$s = $drvSqlite3->prepare($query);
return [$drvSqlite3, $s, $types];
}],
'PDO SQLite 3' => [isset($drvPdo), true, \JKingWeb\Arsse\Db\PDOStatement::class, function(string $query, array $types = []) use($drvPdo) {
$s = $drvPdo->prepare($query);
return [$drvPdo, $s, $types];
}],
'PDO PostgreSQL' => [isset($drvPgsql), true, \JKingWeb\Arsse\Db\PDOStatement::class, function(string $query, array $types = []) use($drvPgsql) {
$s = $drvPgsql->prepare($query);
return [$drvPgsql, $s, $types];
}],
]; ];
foreach ($constructors as $drv => $func) {
yield $drv => [isset($interfaces[$drv]['interface']), $interfaces[$drv]['stringOutput'], $interfaces[$drv]['statement'], $func];
}
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testConstructStatement(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testConstructStatement(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -98,7 +79,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertTrue((bool) $act); $this->assertTrue((bool) $act);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testBindMissingValue(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testBindMissingValue(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -108,7 +89,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame(null, $val); $this->assertSame(null, $val);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testBindMultipleValues(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testBindMultipleValues(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -123,7 +104,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame($exp, $val); $this->assertSame($exp, $val);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testBindRecursively(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testBindRecursively(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -140,7 +121,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame($exp, $val); $this->assertSame($exp, $val);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testBindWithoutType(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testBindWithoutType(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -150,7 +131,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
$s->runArray([1]); $s->runArray([1]);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testViolateConstraint(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testViolateConstraint(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -161,7 +142,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
$s->runArray([null]); $s->runArray([null]);
} }
/** @dataProvider provideDrivers */ /** @dataProvider provideStatements */
public function testMismatchTypes(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { public function testMismatchTypes(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) {
if (!$driverTestable) { if (!$driverTestable) {
$this->markTestSkipped(); $this->markTestSkipped();
@ -309,7 +290,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"], 'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"],
]; ];
$decorators = $this->provideSyntaxDecorators(); $decorators = $this->provideSyntaxDecorators();
foreach ($this->provideDrivers() as $drvName => list($drv, $stringCoersion, $class, $func)) { foreach ($this->provideStatements() as $drvName => list($drv, $stringCoersion, $class, $func)) {
$conv = $decorators[$drvName] ?? $conv = $decorators['']; $conv = $decorators[$drvName] ?? $conv = $decorators[''];
foreach ($tests as $index => list($value, $type, $exp)) { foreach ($tests as $index => list($value, $type, $exp)) {
$t = preg_replace("<^strict >", "", $type); $t = preg_replace("<^strict >", "", $type);
@ -364,7 +345,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
'DateTimeImmutable as strict binary' => [$dateImmutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], 'DateTimeImmutable as strict binary' => [$dateImmutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"],
]; ];
$decorators = $this->provideSyntaxDecorators(); $decorators = $this->provideSyntaxDecorators();
foreach ($this->provideDrivers() as $drvName => list($drv, $stringCoersion, $class, $func)) { foreach ($this->provideStatements() as $drvName => list($drv, $stringCoersion, $class, $func)) {
$conv = $decorators[$drvName] ?? $conv = $decorators['']; $conv = $decorators[$drvName] ?? $conv = $decorators[''];
if ($drvName=="PDO PostgreSQL") { if ($drvName=="PDO PostgreSQL") {
// skip PostgreSQL for these tests // skip PostgreSQL for these tests

55
tests/lib/AbstractTest.php

@ -125,4 +125,59 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
} }
return $value; return $value;
} }
public function provideDbInterfaces(array $conf = []): array {
$this->setConf($conf);
return [
'SQLite 3' => [
'interface' => (function() {
if (\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet()) {
try {
$d = new \SQLite3(Arsse::$conf->dbSQLite3File);
} catch (\Exception $e) {
return;
}
$d->enableExceptions(true);
return $d;
}
})(),
'statement' => \JKingWeb\Arsse\Db\SQLite3\Statement::class,
'result' => \JKingWeb\Arsse\Db\SQLite3\Result::class,
'stringOutput' => false,
],
'PDO SQLite 3' => [
'interface' => (function() {
if (\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) {
try {
return new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
} catch (\PDOException $e) {
return;
}
}
})(),
'statement' => \JKingWeb\Arsse\Db\PDOStatement::class,
'result' => \JKingWeb\Arsse\Db\PDOResult::class,
'stringOutput' => true,
],
'PDO PostgreSQL' => [
'interface' => (function() {
if (\JKingWeb\Arsse\Db\PostgreSQL\PDODriver::requirementsMet()) {
$connString = \JKingWeb\Arsse\Db\PostgreSQL\Driver::makeConnectionString(true, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, Arsse::$conf->dbPostgreSQLDb, Arsse::$conf->dbPostgreSQLHost, Arsse::$conf->dbPostgreSQLPort, "");
try {
$c = new \PDO("pgsql:".$connString, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
} catch (\PDOException $e) {
return;
}
foreach (\JKingWeb\Arsse\Db\PostgreSQL\PDODriver::makeSetupQueries(Arsse::$conf->dbPostgreSQLSchema) as $q) {
$c->exec($q);
}
return $c;
}
})(),
'statement' => \JKingWeb\Arsse\Db\PDOStatement::class,
'result' => \JKingWeb\Arsse\Db\PDOResult::class,
'stringOutput' => true,
],
];
}
} }

Loading…
Cancel
Save