diff --git a/tests/cases/Db/TestResult.php b/tests/cases/Db/TestResult.php index eb2e695..d0074bc 100644 --- a/tests/cases/Db/TestResult.php +++ b/tests/cases/Db/TestResult.php @@ -16,37 +16,35 @@ use JKingWeb\Arsse\Db\SQLite3\PDODriver; * @covers \JKingWeb\Arsse\Db\SQLite3\Result */ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { - public function provideDrivers() { + public function provideResults() { $this->setConf(); - $drvSqlite3 = (function() { - if (\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet()) { - $d = new \SQLite3(Arsse::$conf->dbSQLite3File); - $d->enableExceptions(true); - return $d; - } - })(); - $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(); + $interfaces = $this->provideDbInterfaces(); + $constructors = [ + 'SQLite 3' => function(string $query) use($interfaces) { + $drv = $interfaces['SQLite 3']['interface']; + $set = $drv->query($query); + $rows = $drv->changes(); + $id = $drv->lastInsertRowID(); 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) { if (!$driverTestable) { $this->markTestSkipped(); @@ -54,7 +52,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertInstanceOf(Result::class, new $class(...$func("SELECT 1"))); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideResults */ public function testGetChangeCountAndLastInsertId(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -68,7 +66,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame((int) $id, $r->lastId()); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideResults */ public function testIterateOverResults(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -81,7 +79,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame($exp, $rows); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideResults */ public function testIterateOverResultsTwice(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $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) { if (!$driverTestable) { $this->markTestSkipped(); @@ -113,7 +111,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame(null, $test->getValue()); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideResults */ public function testGetFirstValuesOnly(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -127,7 +125,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame(null, $test->getValue()); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideResults */ public function testGetRows(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -142,7 +140,7 @@ class TestResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame(null, $test->getRow()); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideResults */ public function testGetAllRows(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); diff --git a/tests/cases/Db/TestStatement.php b/tests/cases/Db/TestStatement.php index 0b161ad..838ef67 100644 --- a/tests/cases/Db/TestStatement.php +++ b/tests/cases/Db/TestStatement.php @@ -16,47 +16,28 @@ use JKingWeb\Arsse\Db\PDOStatement; * @covers \JKingWeb\Arsse\Db\PDOStatement * @covers \JKingWeb\Arsse\Db\PDOError */ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { - public function provideDrivers() { - $this->setConf(); - $drvSqlite3 = (function() { - if (\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet()) { - $d = new \SQLite3(Arsse::$conf->dbSQLite3File); - $d->enableExceptions(true); - return $d; - } - })(); - $drvPgsql = (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, ""); - $c = new \PDO("pgsql:".$connString, Arsse::$conf->dbPostgreSQLUser, Arsse::$conf->dbPostgreSQLPass, [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]); - foreach (\JKingWeb\Arsse\Db\PostgreSQL\PDODriver::makeSetupQueries(Arsse::$conf->dbPostgreSQLSchema) as $q) { - $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]; - }], + public function provideStatements() { + $interfaces = $this->provideDbInterfaces(); + $constructors = [ + 'SQLite 3' => function(string $query, array $types = []) use($interfaces) { + $s = $interfaces['SQLite 3']['interface']->prepare($query); + return [$interfaces['SQLite 3']['interface'], $s, $types]; + }, + 'PDO SQLite 3' => function(string $query, array $types = []) use($interfaces) { + $s = $interfaces['PDO SQLite 3']['interface']->prepare($query); + return [$interfaces['PDO SQLite 3']['interface'], $s, $types]; + }, + 'PDO PostgreSQL' => function(string $query, array $types = []) use($interfaces) { + $s = $interfaces['PDO PostgreSQL']['interface']->prepare($query); + return [$interfaces['PDO PostgreSQL']['interface'], $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) { if (!$driverTestable) { $this->markTestSkipped(); @@ -98,7 +79,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertTrue((bool) $act); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideStatements */ public function testBindMissingValue(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -108,7 +89,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame(null, $val); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideStatements */ public function testBindMultipleValues(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -123,7 +104,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame($exp, $val); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideStatements */ public function testBindRecursively(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -140,7 +121,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertSame($exp, $val); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideStatements */ public function testBindWithoutType(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -150,7 +131,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $s->runArray([1]); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideStatements */ public function testViolateConstraint(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -161,7 +142,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { $s->runArray([null]); } - /** @dataProvider provideDrivers */ + /** @dataProvider provideStatements */ public function testMismatchTypes(bool $driverTestable, bool $stringCoersion, string $class, \Closure $func) { if (!$driverTestable) { $this->markTestSkipped(); @@ -309,7 +290,7 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { 'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"], ]; $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['']; foreach ($tests as $index => list($value, $type, $exp)) { $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"))."'"], ]; $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['']; if ($drvName=="PDO PostgreSQL") { // skip PostgreSQL for these tests diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index 7ad4c7c..750c6b0 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -125,4 +125,59 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { } 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, + ], + ]; + } }