mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Use common cleanup code for all database-related tests
This commit is contained in:
parent
925560d4ba
commit
8a49202036
13 changed files with 203 additions and 206 deletions
|
@ -11,51 +11,69 @@ use JKingWeb\Arsse\Db\Result;
|
|||
use JKingWeb\Arsse\Test\DatabaseInformation;
|
||||
|
||||
abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
protected static $dbInfo;
|
||||
protected static $interface;
|
||||
protected $drv;
|
||||
protected $interface;
|
||||
protected $create;
|
||||
protected $lock;
|
||||
protected $setVersion;
|
||||
protected $conf = [
|
||||
protected static $conf = [
|
||||
'dbTimeoutExec' => 0.5,
|
||||
'dbSQLite3Timeout' => 0,
|
||||
//'dbSQLite3File' => "(temporary file)",
|
||||
];
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
// establish a clean baseline
|
||||
static::clearData();
|
||||
static::$dbInfo = new DatabaseInformation(static::$implementation);
|
||||
static::setConf(static::$conf);
|
||||
static::$interface = (static::$dbInfo->interfaceConstructor)();
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
self::clearData();
|
||||
self::setConf($this->conf);
|
||||
$info = new DatabaseInformation($this->implementation);
|
||||
$this->interface = ($info->interfaceConstructor)();
|
||||
if (!$this->interface) {
|
||||
$this->markTestSkipped("$this->implementation database driver not available");
|
||||
self::setConf(static::$conf);
|
||||
if (!static::$interface) {
|
||||
$this->markTestSkipped(static::$implementation." database driver not available");
|
||||
}
|
||||
$this->drv = new $info->driverClass;
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_test");
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
$this->exec("CREATE TABLE arsse_meta(key varchar(255) primary key not null, value text)");
|
||||
$this->exec("INSERT INTO arsse_meta(key,value) values('schema_version','0')");
|
||||
// completely clear the database and ensure the schema version can easily be altered
|
||||
(static::$dbInfo->razeFunction)(static::$interface, [
|
||||
"CREATE TABLE arsse_meta(key varchar(255) primary key not null, value text)",
|
||||
"INSERT INTO arsse_meta(key,value) values('schema_version','0')",
|
||||
]);
|
||||
// construct a fresh driver for each test
|
||||
$this->drv = new static::$dbInfo->driverClass;
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
self::clearData();
|
||||
// deconstruct the driver
|
||||
unset($this->drv);
|
||||
try {
|
||||
$this->exec("ROLLBACK");
|
||||
} catch(\Throwable $e) {
|
||||
if (static::$interface) {
|
||||
// completely clear the database
|
||||
(static::$dbInfo->razeFunction)(static::$interface);
|
||||
}
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_test");
|
||||
self::clearData();
|
||||
}
|
||||
|
||||
protected function exec(string $q): bool {
|
||||
public static function tearDownAfterClass() {
|
||||
static::$implementation = null;
|
||||
static::$dbInfo = null;
|
||||
self::clearData();
|
||||
}
|
||||
|
||||
protected function exec($q): bool {
|
||||
// PDO implementation
|
||||
$this->interface->exec($q);
|
||||
$q = (!is_array($q)) ? [$q] : $q;
|
||||
foreach ($q as $query) {
|
||||
static::$interface->exec((string) $query);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function query(string $q) {
|
||||
// PDO implementation
|
||||
return $this->interface->query($q)->fetchColumn();
|
||||
return static::$interface->query($q)->fetchColumn();
|
||||
}
|
||||
|
||||
# TESTS
|
||||
|
@ -87,7 +105,8 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->exec($this->create);
|
||||
$this->exec($this->lock);
|
||||
$this->assertException("general", "Db", "ExceptionTimeout");
|
||||
$this->drv->exec($this->lock);
|
||||
$lock = is_array($this->lock) ? implode("; ",$this->lock) : $this->lock;
|
||||
$this->drv->exec($lock);
|
||||
}
|
||||
|
||||
public function testExecConstraintViolation() {
|
||||
|
@ -115,7 +134,8 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->exec($this->create);
|
||||
$this->exec($this->lock);
|
||||
$this->assertException("general", "Db", "ExceptionTimeout");
|
||||
$this->drv->exec($this->lock);
|
||||
$lock = is_array($this->lock) ? implode("; ",$this->lock) : $this->lock;
|
||||
$this->drv->exec($lock);
|
||||
}
|
||||
|
||||
public function testQueryConstraintViolation() {
|
||||
|
@ -342,12 +362,20 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->assertSame(1, $this->drv->schemaVersion());
|
||||
$this->drv->exec(str_replace("#", "2", $this->setVersion));
|
||||
$this->assertSame(2, $this->drv->schemaVersion());
|
||||
// SQLite is unaffected by the removal of the metadata table; other backends are
|
||||
// in neither case should a query for the schema version produce an error, however
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
$exp = (static::$dbInfo->backend == "SQLite 3") ? 2 : 0;
|
||||
$this->assertSame($exp, $this->drv->schemaVersion());
|
||||
}
|
||||
|
||||
public function testLockTheDatabase() {
|
||||
// PostgreSQL doesn't actually lock the whole database, only the metadata table
|
||||
// normally the application will first query this table to ensure the schema version is correct,
|
||||
// so the effect is usually the same
|
||||
$this->drv->savepointCreate(true);
|
||||
$this->assertException();
|
||||
$this->exec($this->create);
|
||||
$this->exec(str_replace("#", "3", $this->setVersion));
|
||||
}
|
||||
|
||||
public function testUnlockTheDatabase() {
|
||||
|
@ -355,6 +383,6 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->drv->savepointRelease();
|
||||
$this->drv->savepointCreate(true);
|
||||
$this->drv->savepointUndo();
|
||||
$this->assertTrue($this->exec($this->create));
|
||||
$this->assertTrue($this->exec(str_replace("#", "3", $this->setVersion)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,29 +10,45 @@ use JKingWeb\Arsse\Db\Result;
|
|||
use JKingWeb\Arsse\Test\DatabaseInformation;
|
||||
|
||||
abstract class BaseResult extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
protected static $dbInfo;
|
||||
protected static $interface;
|
||||
protected $resultClass;
|
||||
protected $stringOutput;
|
||||
protected $interface;
|
||||
|
||||
abstract protected function exec(string $q);
|
||||
abstract protected function makeResult(string $q): array;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
// establish a clean baseline
|
||||
static::clearData();
|
||||
static::$dbInfo = new DatabaseInformation(static::$implementation);
|
||||
static::setConf();
|
||||
static::$interface = (static::$dbInfo->interfaceConstructor)();
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
self::clearData();
|
||||
self::setConf();
|
||||
$info = new DatabaseInformation($this->implementation);
|
||||
$this->interface = ($info->interfaceConstructor)();
|
||||
if (!$this->interface) {
|
||||
$this->markTestSkipped("$this->implementation database driver not available");
|
||||
if (!static::$interface) {
|
||||
$this->markTestSkipped(static::$implementation." database driver not available");
|
||||
}
|
||||
$this->resultClass = $info->resultClass;
|
||||
$this->stringOutput = $info->stringOutput;
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
// completely clear the database
|
||||
(static::$dbInfo->razeFunction)(static::$interface);
|
||||
$this->resultClass = static::$dbInfo->resultClass;
|
||||
$this->stringOutput = static::$dbInfo->stringOutput;
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
if (static::$interface) {
|
||||
// completely clear the database
|
||||
(static::$dbInfo->razeFunction)(static::$interface);
|
||||
}
|
||||
self::clearData();
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
static::$implementation = null;
|
||||
static::$dbInfo = null;
|
||||
self::clearData();
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
}
|
||||
|
||||
public function testConstructResult() {
|
||||
|
|
|
@ -10,29 +10,45 @@ use JKingWeb\Arsse\Db\Statement;
|
|||
use JKingWeb\Arsse\Test\DatabaseInformation;
|
||||
|
||||
abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||
protected static $dbInfo;
|
||||
protected static $interface;
|
||||
protected $statementClass;
|
||||
protected $stringOutput;
|
||||
protected $interface;
|
||||
|
||||
abstract protected function exec(string $q);
|
||||
abstract protected function makeStatement(string $q, array $types = []): array;
|
||||
abstract protected function decorateTypeSyntax(string $value, string $type): string;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
// establish a clean baseline
|
||||
static::clearData();
|
||||
static::$dbInfo = new DatabaseInformation(static::$implementation);
|
||||
static::setConf();
|
||||
static::$interface = (static::$dbInfo->interfaceConstructor)();
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
self::clearData();
|
||||
self::setConf();
|
||||
$info = new DatabaseInformation($this->implementation);
|
||||
$this->interface = ($info->interfaceConstructor)();
|
||||
if (!$this->interface) {
|
||||
$this->markTestSkipped("$this->implementation database driver not available");
|
||||
if (!static::$interface) {
|
||||
$this->markTestSkipped(static::$implementation." database driver not available");
|
||||
}
|
||||
$this->statementClass = $info->statementClass;
|
||||
$this->stringOutput = $info->stringOutput;
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
// completely clear the database
|
||||
(static::$dbInfo->razeFunction)(static::$interface);
|
||||
$this->statementClass = static::$dbInfo->statementClass;
|
||||
$this->stringOutput = static::$dbInfo->stringOutput;
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||
if (static::$interface) {
|
||||
// completely clear the database
|
||||
(static::$dbInfo->razeFunction)(static::$interface);
|
||||
}
|
||||
self::clearData();
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
static::$implementation = null;
|
||||
static::$dbInfo = null;
|
||||
self::clearData();
|
||||
}
|
||||
|
||||
|
@ -56,7 +72,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
|
||||
/** @dataProvider provideBinaryBindings */
|
||||
public function testHandleBinaryData($value, string $type, string $exp) {
|
||||
if (in_array($this->implementation, ["PostgreSQL", "PDO PostgreSQL"])) {
|
||||
if (in_array(static::$implementation, ["PostgreSQL", "PDO PostgreSQL"])) {
|
||||
$this->markTestSkipped("Correct handling of binary data with PostgreSQL is currently unknown");
|
||||
}
|
||||
if ($exp=="null") {
|
||||
|
|
19
tests/cases/Db/PostgreSQL/TestDatabase.php
Normal file
19
tests/cases/Db/PostgreSQL/TestDatabase.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\TestCase\Db\PosgreSQL;
|
||||
|
||||
/**
|
||||
* @covers \JKingWeb\Arsse\Database<extended>
|
||||
* @covers \JKingWeb\Arsse\Misc\Query<extended>
|
||||
*/
|
||||
class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\Base {
|
||||
protected static $implementation = "PDO PostgreSQL";
|
||||
|
||||
protected function nextID(string $table): int {
|
||||
return static::$drv->query("SELECT select cast(last_value as bigint) + 1 from pg_sequences where sequencename = '{$table}_id_seq'")->getValue();
|
||||
}
|
||||
}
|
|
@ -11,13 +11,8 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQL;
|
|||
* @covers \JKingWeb\Arsse\Db\PDODriver
|
||||
* @covers \JKingWeb\Arsse\Db\PDOError */
|
||||
class TestDriver extends \JKingWeb\Arsse\TestCase\Db\BaseDriver {
|
||||
protected $implementation = "PDO PostgreSQL";
|
||||
protected static $implementation = "PDO PostgreSQL";
|
||||
protected $create = "CREATE TABLE arsse_test(id bigserial primary key)";
|
||||
protected $lock = "BEGIN; LOCK TABLE arsse_test IN EXCLUSIVE MODE NOWAIT";
|
||||
protected $lock = ["BEGIN", "LOCK TABLE arsse_test IN EXCLUSIVE MODE NOWAIT"];
|
||||
protected $setVersion = "UPDATE arsse_meta set value = '#' where key = 'schema_version'";
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->interface);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,19 +10,10 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQL;
|
|||
* @covers \JKingWeb\Arsse\Db\PDOStatement<extended>
|
||||
* @covers \JKingWeb\Arsse\Db\PDOError */
|
||||
class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
|
||||
protected $implementation = "PDO PostgreSQL";
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->interface);
|
||||
}
|
||||
|
||||
protected function exec(string $q) {
|
||||
$this->interface->exec($q);
|
||||
}
|
||||
protected static $implementation = "PDO PostgreSQL";
|
||||
|
||||
protected function makeStatement(string $q, array $types = []): array {
|
||||
return [$this->interface, $this->interface->prepare($q), $types];
|
||||
return [static::$interface, static::$interface->prepare($q), $types];
|
||||
}
|
||||
|
||||
protected function decorateTypeSyntax(string $value, string $type): string {
|
||||
|
|
|
@ -10,92 +10,39 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3;
|
|||
* @covers \JKingWeb\Arsse\Db\SQLite3\Driver<extended>
|
||||
* @covers \JKingWeb\Arsse\Db\SQLite3\ExceptionBuilder */
|
||||
class TestDriver extends \JKingWeb\Arsse\TestCase\Db\BaseDriver {
|
||||
protected $implementation = "SQLite 3";
|
||||
protected static $implementation = "SQLite 3";
|
||||
protected $create = "CREATE TABLE arsse_test(id integer primary key)";
|
||||
protected $lock = "BEGIN EXCLUSIVE TRANSACTION";
|
||||
protected $setVersion = "PRAGMA user_version=#";
|
||||
protected static $file;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
self::$file = tempnam(sys_get_temp_dir(), 'ook');
|
||||
// create a temporary database file rather than using a memory database
|
||||
// some tests require one connection to block another, so a memory database is not suitable
|
||||
static::$file = tempnam(sys_get_temp_dir(), 'ook');
|
||||
static::$conf['dbSQLite3File'] = static::$file;
|
||||
parent::setUpBeforeclass();
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
@unlink(self::$file);
|
||||
self::$file = null;
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->conf['dbSQLite3File'] = self::$file;
|
||||
parent::setUp();
|
||||
$this->exec("PRAGMA user_version=0");
|
||||
if (static::$interface) {
|
||||
static::$interface->close();
|
||||
}
|
||||
parent::tearDownAfterClass();
|
||||
@unlink(static::$file);
|
||||
static::$file = null;
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
$this->exec("PRAGMA user_version=0");
|
||||
$this->interface->close();
|
||||
unset($this->interface);
|
||||
}
|
||||
|
||||
protected function exec(string $q): bool {
|
||||
$this->interface->exec($q);
|
||||
protected function exec($q): bool {
|
||||
// SQLite's implementation coincidentally matches PDO's, but we reproduce it here for correctness' sake
|
||||
$q = (!is_array($q)) ? [$q] : $q;
|
||||
foreach ($q as $query) {
|
||||
static::$interface->exec((string) $query);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function query(string $q) {
|
||||
return $this->interface->querySingle($q);
|
||||
}
|
||||
|
||||
public function provideDrivers() {
|
||||
self::clearData();
|
||||
self::setConf([
|
||||
'dbTimeoutExec' => 0.5,
|
||||
'dbSQLite3Timeout' => 0,
|
||||
'dbSQLite3File' => tempnam(sys_get_temp_dir(), 'ook'),
|
||||
]);
|
||||
$i = $this->provideDbInterfaces();
|
||||
$d = $this->provideDbDrivers();
|
||||
$pdoExec = function (string $q) {
|
||||
$this->interface->exec($q);
|
||||
return true;
|
||||
};
|
||||
$pdoQuery = function (string $q) {
|
||||
return $this->interface->query($q)->fetchColumn();
|
||||
};
|
||||
return [
|
||||
'SQLite 3' => [
|
||||
$i['SQLite 3']['interface'],
|
||||
$d['SQLite 3'],
|
||||
"CREATE TABLE arsse_test(id integer primary key)",
|
||||
"BEGIN EXCLUSIVE TRANSACTION",
|
||||
"PRAGMA user_version=#",
|
||||
function (string $q) {
|
||||
$this->interface->exec($q);
|
||||
return true;
|
||||
},
|
||||
function (string $q) {
|
||||
return $this->interface->querySingle($q);
|
||||
},
|
||||
],
|
||||
'PDO SQLite 3' => [
|
||||
$i['PDO SQLite 3']['interface'],
|
||||
$d['PDO SQLite 3'],
|
||||
"CREATE TABLE arsse_test(id integer primary key)",
|
||||
"BEGIN EXCLUSIVE TRANSACTION",
|
||||
"PRAGMA user_version=#",
|
||||
$pdoExec,
|
||||
$pdoQuery,
|
||||
],
|
||||
'PDO PostgreSQL' => [
|
||||
$i['PDO PostgreSQL']['interface'],
|
||||
$d['PDO PostgreSQL'],
|
||||
"CREATE TABLE arsse_test(id bigserial primary key)",
|
||||
"BEGIN; LOCK TABLE arsse_test IN EXCLUSIVE MODE NOWAIT",
|
||||
"UPDATE arsse_meta set value = '#' where key = 'schema_version'",
|
||||
$pdoExec,
|
||||
$pdoQuery,
|
||||
],
|
||||
];
|
||||
return static::$interface->querySingle($q);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,22 +12,19 @@ use JKingWeb\Arsse\Test\DatabaseInformation;
|
|||
* @covers \JKingWeb\Arsse\Db\SQLite3\Result<extended>
|
||||
*/
|
||||
class TestResult extends \JKingWeb\Arsse\TestCase\Db\BaseResult {
|
||||
protected $implementation = "SQLite 3";
|
||||
protected static $implementation = "SQLite 3";
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
$this->interface->close();
|
||||
unset($this->interface);
|
||||
}
|
||||
|
||||
protected function exec(string $q) {
|
||||
$this->interface->exec($q);
|
||||
public static function tearDownAfterClass() {
|
||||
if (static::$interface) {
|
||||
static::$interface->close();
|
||||
}
|
||||
parent::tearDownAfterClass();
|
||||
}
|
||||
|
||||
protected function makeResult(string $q): array {
|
||||
$set = $this->interface->query($q);
|
||||
$rows = $this->interface->changes();
|
||||
$id = $this->interface->lastInsertRowID();
|
||||
$set = static::$interface->query($q);
|
||||
$rows = static::$interface->changes();
|
||||
$id = static::$interface->lastInsertRowID();
|
||||
return [$set, [$rows, $id]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,20 +10,15 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3;
|
|||
* @covers \JKingWeb\Arsse\Db\SQLite3\Statement<extended>
|
||||
* @covers \JKingWeb\Arsse\Db\SQLite3\ExceptionBuilder */
|
||||
class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
|
||||
protected $implementation = "SQLite 3";
|
||||
protected static $implementation = "SQLite 3";
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
$this->interface->close();
|
||||
unset($this->interface);
|
||||
}
|
||||
|
||||
protected function exec(string $q) {
|
||||
$this->interface->exec($q);
|
||||
public static function tearDownAfterClass() {
|
||||
static::$interface->close();
|
||||
parent::tearDownAfterClass();
|
||||
}
|
||||
|
||||
protected function makeStatement(string $q, array $types = []): array {
|
||||
return [$this->interface, $this->interface->prepare($q), $types];
|
||||
return [static::$interface, static::$interface->prepare($q), $types];
|
||||
}
|
||||
|
||||
protected function decorateTypeSyntax(string $value, string $type): string {
|
||||
|
|
|
@ -11,30 +11,23 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3PDO;
|
|||
* @covers \JKingWeb\Arsse\Db\PDODriver
|
||||
* @covers \JKingWeb\Arsse\Db\PDOError */
|
||||
class TestDriver extends \JKingWeb\Arsse\TestCase\Db\BaseDriver {
|
||||
protected $implementation = "PDO SQLite 3";
|
||||
protected static $implementation = "PDO SQLite 3";
|
||||
protected $create = "CREATE TABLE arsse_test(id integer primary key)";
|
||||
protected $lock = "BEGIN EXCLUSIVE TRANSACTION";
|
||||
protected $setVersion = "PRAGMA user_version=#";
|
||||
protected static $file;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
self::$file = tempnam(sys_get_temp_dir(), 'ook');
|
||||
// create a temporary database file rather than using a memory database
|
||||
// some tests require one connection to block another, so a memory database is not suitable
|
||||
static::$file = tempnam(sys_get_temp_dir(), 'ook');
|
||||
static::$conf['dbSQLite3File'] = static::$file;
|
||||
parent::setUpBeforeclass();
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
parent::tearDownAfterClass();
|
||||
@unlink(self::$file);
|
||||
self::$file = null;
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->conf['dbSQLite3File'] = self::$file;
|
||||
parent::setUp();
|
||||
$this->exec("PRAGMA user_version=0");
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
$this->exec("PRAGMA user_version=0");
|
||||
unset($this->interface);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,19 +10,10 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3PDO;
|
|||
* @covers \JKingWeb\Arsse\Db\PDOStatement<extended>
|
||||
* @covers \JKingWeb\Arsse\Db\PDOError */
|
||||
class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
|
||||
protected $implementation = "PDO SQLite 3";
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->interface);
|
||||
}
|
||||
|
||||
protected function exec(string $q) {
|
||||
$this->interface->exec($q);
|
||||
}
|
||||
protected static $implementation = "PDO SQLite 3";
|
||||
|
||||
protected function makeStatement(string $q, array $types = []): array {
|
||||
return [$this->interface, $this->interface->prepare($q), $types];
|
||||
return [static::$interface, static::$interface->prepare($q), $types];
|
||||
}
|
||||
|
||||
protected function decorateTypeSyntax(string $value, string $type): string {
|
||||
|
|
|
@ -12,41 +12,30 @@ use JKingWeb\Arsse\Test\DatabaseInformation;
|
|||
* @covers \JKingWeb\Arsse\Db\PDOResult<extended>
|
||||
*/
|
||||
class TestResultPDO extends \JKingWeb\Arsse\TestCase\Db\BaseResult {
|
||||
protected static $firstAvailableDriver;
|
||||
protected static $implementation;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
self::setConf();
|
||||
// we only need to test one PDO implementation (they all use the same result class), so we find the first usable one
|
||||
$drivers = DatabaseInformation::listPDO();
|
||||
self::$firstAvailableDriver = $drivers[0];
|
||||
self::$implementation = $drivers[0];
|
||||
foreach ($drivers as $driver) {
|
||||
$info = new DatabaseInformation($driver);
|
||||
$interface = ($info->interfaceConstructor)();
|
||||
if ($interface) {
|
||||
self::$firstAvailableDriver = $driver;
|
||||
self::$implementation = $driver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->implementation = self::$firstAvailableDriver;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->interface);
|
||||
}
|
||||
|
||||
protected function exec(string $q) {
|
||||
$this->interface->exec($q);
|
||||
unset($interface);
|
||||
unset($info);
|
||||
parent::setUpBeforeClass();
|
||||
}
|
||||
|
||||
protected function makeResult(string $q): array {
|
||||
$set = $this->interface->query($q);
|
||||
$set = static::$interface->query($q);
|
||||
$rows = $set->rowCount();
|
||||
$id = $this->interface->lastInsertID();
|
||||
$id = static::$interface->lastInsertID();
|
||||
return [$set, [$rows, $id]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,12 @@ class DatabaseInformation {
|
|||
$tables = $db->query($listTables)->getAll();
|
||||
$tables = sizeof($tables) ? array_column($tables, "name") : [];
|
||||
} elseif ($db instanceof \PDO) {
|
||||
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
|
||||
retry:
|
||||
try {
|
||||
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
|
||||
} catch (\PDOException $e) {
|
||||
goto retry;
|
||||
}
|
||||
$tables = sizeof($tables) ? array_column($tables, "name") : [];
|
||||
} else {
|
||||
$tables = [];
|
||||
|
@ -72,6 +77,11 @@ class DatabaseInformation {
|
|||
return $tables;
|
||||
};
|
||||
$sqlite3TruncateFunction = function($db, array $afterStatements = []) use ($sqlite3TableList) {
|
||||
// rollback any pending transaction
|
||||
try {
|
||||
$db->exec("ROLLBACK");
|
||||
} catch(\Throwable $e) {
|
||||
}
|
||||
foreach ($sqlite3TableList($db) as $table) {
|
||||
if ($table == "arsse_meta") {
|
||||
$db->exec("DELETE FROM $table where key <> 'schema_version'");
|
||||
|
@ -84,6 +94,11 @@ class DatabaseInformation {
|
|||
}
|
||||
};
|
||||
$sqlite3RazeFunction = function($db, array $afterStatements = []) use ($sqlite3TableList) {
|
||||
// rollback any pending transaction
|
||||
try {
|
||||
$db->exec("ROLLBACK");
|
||||
} catch(\Throwable $e) {
|
||||
}
|
||||
$db->exec("PRAGMA foreign_keys=0");
|
||||
foreach ($sqlite3TableList($db) as $table) {
|
||||
$db->exec("DROP TABLE IF EXISTS $table");
|
||||
|
@ -163,7 +178,12 @@ class DatabaseInformation {
|
|||
return $d;
|
||||
},
|
||||
'truncateFunction' => function($db, array $afterStatements = []) use ($pgObjectList) {
|
||||
foreach ($objectList($db) as $obj) {
|
||||
// rollback any pending transaction
|
||||
try {
|
||||
$db->exec("ROLLBACK");
|
||||
} catch(\Throwable $e) {
|
||||
}
|
||||
foreach ($pgObjectList($db) as $obj) {
|
||||
if ($obj['type'] != "TABLE") {
|
||||
continue;
|
||||
} elseif ($obj['name'] == "arsse_meta") {
|
||||
|
@ -177,8 +197,8 @@ class DatabaseInformation {
|
|||
}
|
||||
},
|
||||
'razeFunction' => function($db, array $afterStatements = []) use ($pgObjectList) {
|
||||
foreach ($objectList($db) as $obj) {
|
||||
$db->exec("DROP {$obj['type']} {$obj['name']} IF EXISTS cascade");
|
||||
foreach ($pgObjectList($db) as $obj) {
|
||||
$db->exec("DROP {$obj['type']} IF EXISTS {$obj['name']} cascade");
|
||||
|
||||
}
|
||||
foreach ($afterStatements as $st) {
|
||||
|
|
Loading…
Reference in a new issue