mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2025-01-03 14:32:40 +00:00
Align statement tests with other database driver tests
This commit is contained in:
parent
f22e53fdc9
commit
8c20411359
8 changed files with 194 additions and 114 deletions
|
@ -22,6 +22,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
];
|
];
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
|
$this->clearData();
|
||||||
self::setConf($this->conf);
|
self::setConf($this->conf);
|
||||||
$info = new DatabaseInformation($this->implementation);
|
$info = new DatabaseInformation($this->implementation);
|
||||||
$this->interface = ($info->interfaceConstructor)();
|
$this->interface = ($info->interfaceConstructor)();
|
||||||
|
@ -36,6 +37,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
|
$this->clearData();
|
||||||
unset($this->drv);
|
unset($this->drv);
|
||||||
try {
|
try {
|
||||||
$this->exec("ROLLBACK");
|
$this->exec("ROLLBACK");
|
||||||
|
|
|
@ -18,6 +18,7 @@ abstract class BaseResult extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
abstract protected function makeResult(string $q): array;
|
abstract protected function makeResult(string $q): array;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
|
$this->clearData();
|
||||||
self::setConf();
|
self::setConf();
|
||||||
$info = new DatabaseInformation($this->implementation);
|
$info = new DatabaseInformation($this->implementation);
|
||||||
$this->interface = ($info->interfaceConstructor)();
|
$this->interface = ($info->interfaceConstructor)();
|
||||||
|
@ -30,6 +31,7 @@ abstract class BaseResult extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
|
$this->clearData();
|
||||||
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,53 +6,49 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\TestCase\Db;
|
namespace JKingWeb\Arsse\TestCase\Db;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
|
||||||
use JKingWeb\Arsse\Db\Statement;
|
use JKingWeb\Arsse\Db\Statement;
|
||||||
use JKingWeb\Arsse\Db\PDOStatement;
|
use JKingWeb\Arsse\Test\DatabaseInformation;
|
||||||
|
|
||||||
/**
|
abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
* @covers \JKingWeb\Arsse\Db\SQLite3\Statement<extended>
|
protected $statementClass;
|
||||||
* @covers \JKingWeb\Arsse\Db\SQLite3\ExceptionBuilder
|
protected $stringOutput;
|
||||||
* @covers \JKingWeb\Arsse\Db\PDOStatement<extended>
|
protected $interface;
|
||||||
* @covers \JKingWeb\Arsse\Db\PDOError */
|
|
||||||
class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
abstract protected function exec(string $q);
|
||||||
public function provideStatements() {
|
abstract protected function makeStatement(string $q, array $types = []): array;
|
||||||
$interfaces = $this->provideDbInterfaces();
|
abstract protected function decorateTypeSyntax(string $value, string $type): string;
|
||||||
$constructors = [
|
|
||||||
'SQLite 3' => function(string $query, array $types = []) use($interfaces) {
|
public function setUp() {
|
||||||
$s = $interfaces['SQLite 3']['interface']->prepare($query);
|
$this->clearData();
|
||||||
return [$interfaces['SQLite 3']['interface'], $s, $types];
|
self::setConf();
|
||||||
},
|
$info = new DatabaseInformation($this->implementation);
|
||||||
'PDO SQLite 3' => function(string $query, array $types = []) use($interfaces) {
|
$this->interface = ($info->interfaceConstructor)();
|
||||||
$s = $interfaces['PDO SQLite 3']['interface']->prepare($query);
|
if (!$this->interface) {
|
||||||
return [$interfaces['PDO SQLite 3']['interface'], $s, $types];
|
$this->markTestSkipped("$this->implementation database driver not available");
|
||||||
},
|
|
||||||
'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];
|
|
||||||
}
|
}
|
||||||
|
$this->statementClass = $info->statementClass;
|
||||||
|
$this->stringOutput = $info->stringOutput;
|
||||||
|
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
$this->exec("DROP TABLE IF EXISTS arsse_meta");
|
||||||
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testConstructStatement() {
|
public function testConstructStatement() {
|
||||||
$class = $this->statementClass;
|
$this->assertInstanceOf(Statement::class, new $this->statementClass(...$this->makeStatement("SELECT ? as value")));
|
||||||
$this->assertInstanceOf(Statement::class, new $class(...$func("SELECT ? as value")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideBindings */
|
/** @dataProvider provideBindings */
|
||||||
public function testBindATypedValue(bool $driverTestable, string $class, \Closure $func, $value, string $type, string $exp) {
|
public function testBindATypedValue($value, string $type, string $exp) {
|
||||||
$class = $this->statementClass;
|
|
||||||
if ($exp=="null") {
|
if ($exp=="null") {
|
||||||
$query = "SELECT (cast(? as text) is null) as pass";
|
$query = "SELECT (cast(? as text) is null) as pass";
|
||||||
} else {
|
} else {
|
||||||
$query = "SELECT ($exp = ?) as pass";
|
$query = "SELECT ($exp = ?) as pass";
|
||||||
}
|
}
|
||||||
$typeStr = "'".str_replace("'", "''", $type)."'";
|
$typeStr = "'".str_replace("'", "''", $type)."'";
|
||||||
$s = new $class(...$func($query));
|
$s = new $this->statementClass(...$this->makeStatement($query));
|
||||||
$s->retype(...[$type]);
|
$s->retype(...[$type]);
|
||||||
$act = $s->run(...[$value])->getValue();
|
$act = $s->run(...[$value])->getValue();
|
||||||
$this->assertTrue((bool) $act);
|
$this->assertTrue((bool) $act);
|
||||||
|
@ -60,77 +56,67 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
/** @dataProvider provideBinaryBindings */
|
/** @dataProvider provideBinaryBindings */
|
||||||
public function testHandleBinaryData($value, string $type, string $exp) {
|
public function testHandleBinaryData($value, string $type, string $exp) {
|
||||||
$class = $this->statementClass;
|
if (in_array($this->implementation, ["PostgreSQL", "PDO PostgreSQL"])) {
|
||||||
|
$this->markTestSkipped("Correct handling of binary data with PostgreSQL is currently unknown");
|
||||||
|
}
|
||||||
if ($exp=="null") {
|
if ($exp=="null") {
|
||||||
$query = "SELECT (cast(? as text) is null) as pass";
|
$query = "SELECT (cast(? as text) is null) as pass";
|
||||||
} else {
|
} else {
|
||||||
$query = "SELECT ($exp = ?) as pass";
|
$query = "SELECT ($exp = ?) as pass";
|
||||||
}
|
}
|
||||||
$typeStr = "'".str_replace("'", "''", $type)."'";
|
$typeStr = "'".str_replace("'", "''", $type)."'";
|
||||||
$s = new $class(...$func($query));
|
$s = new $this->statementClass(...$this->makeStatement($query));
|
||||||
$s->retype(...[$type]);
|
$s->retype(...[$type]);
|
||||||
$act = $s->run(...[$value])->getValue();
|
$act = $s->run(...[$value])->getValue();
|
||||||
$this->assertTrue((bool) $act);
|
$this->assertTrue((bool) $act);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testBindMissingValue() {
|
public function testBindMissingValue() {
|
||||||
$class = $this->statementClass;
|
$s = new $this->statementClass(...$this->makeStatement("SELECT ? as value", ["int"]));
|
||||||
$s = new $class(...$func("SELECT ? as value", ["int"]));
|
|
||||||
$val = $s->runArray()->getRow()['value'];
|
$val = $s->runArray()->getRow()['value'];
|
||||||
$this->assertSame(null, $val);
|
$this->assertSame(null, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testBindMultipleValues() {
|
public function testBindMultipleValues() {
|
||||||
$class = $this->statementClass;
|
|
||||||
$exp = [
|
$exp = [
|
||||||
'one' => 1,
|
'one' => 1,
|
||||||
'two' => 2,
|
'two' => 2,
|
||||||
];
|
];
|
||||||
$exp = $stringCoersion ? $this->stringify($exp) : $exp;
|
$exp = $this->stringOutput ? $this->stringify($exp) : $exp;
|
||||||
$s = new $class(...$func("SELECT ? as one, ? as two", ["int", "int"]));
|
$s = new $this->statementClass(...$this->makeStatement("SELECT ? as one, ? as two", ["int", "int"]));
|
||||||
$val = $s->runArray([1,2])->getRow();
|
$val = $s->runArray([1,2])->getRow();
|
||||||
$this->assertSame($exp, $val);
|
$this->assertSame($exp, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testBindRecursively() {
|
public function testBindRecursively() {
|
||||||
$class = $this->statementClass;
|
|
||||||
$exp = [
|
$exp = [
|
||||||
'one' => 1,
|
'one' => 1,
|
||||||
'two' => 2,
|
'two' => 2,
|
||||||
'three' => 3,
|
'three' => 3,
|
||||||
'four' => 4,
|
'four' => 4,
|
||||||
];
|
];
|
||||||
$exp = $stringCoersion ? $this->stringify($exp) : $exp;
|
$exp = $this->stringOutput ? $this->stringify($exp) : $exp;
|
||||||
$s = new $class(...$func("SELECT ? as one, ? as two, ? as three, ? as four", ["int", ["int", "int"], "int"]));
|
$s = new $this->statementClass(...$this->makeStatement("SELECT ? as one, ? as two, ? as three, ? as four", ["int", ["int", "int"], "int"]));
|
||||||
$val = $s->runArray([1, [2, 3], 4])->getRow();
|
$val = $s->runArray([1, [2, 3], 4])->getRow();
|
||||||
$this->assertSame($exp, $val);
|
$this->assertSame($exp, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testBindWithoutType() {
|
public function testBindWithoutType() {
|
||||||
$class = $this->statementClass;
|
|
||||||
$this->assertException("paramTypeMissing", "Db");
|
$this->assertException("paramTypeMissing", "Db");
|
||||||
$s = new $class(...$func("SELECT ? as value", []));
|
$s = new $this->statementClass(...$this->makeStatement("SELECT ? as value", []));
|
||||||
$s->runArray([1]);
|
$s->runArray([1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testViolateConstraint() {
|
public function testViolateConstraint() {
|
||||||
$class = $this->statementClass;
|
(new $this->statementClass(...$this->makeStatement("CREATE TABLE if not exists arsse_meta(key varchar(255) primary key not null, value text)")))->run();
|
||||||
(new $class(...$func("CREATE TABLE if not exists arsse_meta(key varchar(255) primary key not null, value text)")))->run();
|
$s = new $this->statementClass(...$this->makeStatement("INSERT INTO arsse_meta(key) values(?)", ["str"]));
|
||||||
$s = new $class(...$func("INSERT INTO arsse_meta(key) values(?)", ["str"]));
|
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
$s->runArray([null]);
|
$s->runArray([null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideStatements */
|
|
||||||
public function testMismatchTypes() {
|
public function testMismatchTypes() {
|
||||||
$class = $this->statementClass;
|
(new $this->statementClass(...$this->makeStatement("CREATE TABLE if not exists arsse_feeds(id integer primary key not null, url text not null)")))->run();
|
||||||
(new $class(...$func("CREATE TABLE if not exists arsse_feeds(id integer primary key not null, url text not null)")))->run();
|
$s = new $this->statementClass(...$this->makeStatement("INSERT INTO arsse_feeds(id,url) values(?,?)", ["str", "str"]));
|
||||||
$s = new $class(...$func("INSERT INTO arsse_feeds(id,url) values(?,?)", ["str", "str"]));
|
|
||||||
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
||||||
$s->runArray(['ook', 'eek']);
|
$s->runArray(['ook', 'eek']);
|
||||||
}
|
}
|
||||||
|
@ -250,35 +236,32 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
'Arbitrary date string as strict string' => ["Today", "strict string", "'Today'"],
|
'Arbitrary date string as strict string' => ["Today", "strict string", "'Today'"],
|
||||||
'Arbitrary date string as strict datetime' => ["Today", "strict datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"],
|
'Arbitrary date string as strict datetime' => ["Today", "strict datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"],
|
||||||
'Arbitrary date string as strict boolean' => ["Today", "strict boolean", "1"],
|
'Arbitrary date string as strict boolean' => ["Today", "strict boolean", "1"],
|
||||||
'DateTime as integer' => [$dateMutable, "integer", $dateUTC->getTimestamp()],
|
'DateTime as integer' => [$dateMutable, "integer", (string) $dateUTC->getTimestamp()],
|
||||||
'DateTime as float' => [$dateMutable, "float", $dateUTC->getTimestamp().".0"],
|
'DateTime as float' => [$dateMutable, "float", $dateUTC->getTimestamp().".0"],
|
||||||
'DateTime as string' => [$dateMutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTime as string' => [$dateMutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTime as datetime' => [$dateMutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTime as datetime' => [$dateMutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTime as boolean' => [$dateMutable, "boolean", "1"],
|
'DateTime as boolean' => [$dateMutable, "boolean", "1"],
|
||||||
'DateTime as strict integer' => [$dateMutable, "strict integer", $dateUTC->getTimestamp()],
|
'DateTime as strict integer' => [$dateMutable, "strict integer", (string) $dateUTC->getTimestamp()],
|
||||||
'DateTime as strict float' => [$dateMutable, "strict float", $dateUTC->getTimestamp().".0"],
|
'DateTime as strict float' => [$dateMutable, "strict float", $dateUTC->getTimestamp().".0"],
|
||||||
'DateTime as strict string' => [$dateMutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTime as strict string' => [$dateMutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTime as strict datetime' => [$dateMutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTime as strict datetime' => [$dateMutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTime as strict boolean' => [$dateMutable, "strict boolean", "1"],
|
'DateTime as strict boolean' => [$dateMutable, "strict boolean", "1"],
|
||||||
'DateTimeImmutable as integer' => [$dateImmutable, "integer", $dateUTC->getTimestamp()],
|
'DateTimeImmutable as integer' => [$dateImmutable, "integer", (string) $dateUTC->getTimestamp()],
|
||||||
'DateTimeImmutable as float' => [$dateImmutable, "float", $dateUTC->getTimestamp().".0"],
|
'DateTimeImmutable as float' => [$dateImmutable, "float", $dateUTC->getTimestamp().".0"],
|
||||||
'DateTimeImmutable as string' => [$dateImmutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTimeImmutable as string' => [$dateImmutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTimeImmutable as datetime' => [$dateImmutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTimeImmutable as datetime' => [$dateImmutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTimeImmutable as boolean' => [$dateImmutable, "boolean", "1"],
|
'DateTimeImmutable as boolean' => [$dateImmutable, "boolean", "1"],
|
||||||
'DateTimeImmutable as strict integer' => [$dateImmutable, "strict integer", $dateUTC->getTimestamp()],
|
'DateTimeImmutable as strict integer' => [$dateImmutable, "strict integer", (string) $dateUTC->getTimestamp()],
|
||||||
'DateTimeImmutable as strict float' => [$dateImmutable, "strict float", $dateUTC->getTimestamp().".0"],
|
'DateTimeImmutable as strict float' => [$dateImmutable, "strict float", $dateUTC->getTimestamp().".0"],
|
||||||
'DateTimeImmutable as strict string' => [$dateImmutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTimeImmutable as strict string' => [$dateImmutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTimeImmutable as strict datetime' => [$dateImmutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
'DateTimeImmutable as strict datetime' => [$dateImmutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"],
|
||||||
'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"],
|
'DateTimeImmutable as strict boolean' => [$dateImmutable, "strict boolean", "1"],
|
||||||
];
|
];
|
||||||
$decorators = $this->provideSyntaxDecorators();
|
foreach ($tests as $index => list($value, $type, $exp)) {
|
||||||
foreach ($this->provideStatements() as $drvName => list($drv, $stringCoersion, $class, $func)) {
|
$t = preg_replace("<^strict >", "", $type);
|
||||||
$conv = $decorators[$drvName] ?? $conv = $decorators[''];
|
if (gettype($exp) != "string") var_export($index);
|
||||||
foreach ($tests as $index => list($value, $type, $exp)) {
|
$exp = ($exp=="null") ? $exp : $this->decorateTypeSyntax($exp, $t);
|
||||||
$t = preg_replace("<^strict >", "", $type);
|
yield $index => [$value, $type, $exp];
|
||||||
$exp = ($exp=="null") ? $exp : $conv($exp, $t);
|
|
||||||
yield "$index ($drvName)" => [$drv, $class, $func, $value, $type, $exp];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,50 +309,11 @@ class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
'DateTimeImmutable as binary' => [$dateImmutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"],
|
'DateTimeImmutable as binary' => [$dateImmutable, "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"))."'"],
|
'DateTimeImmutable as strict binary' => [$dateImmutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"],
|
||||||
];
|
];
|
||||||
$decorators = $this->provideSyntaxDecorators();
|
foreach ($tests as $index => list($value, $type, $exp)) {
|
||||||
foreach ($this->provideStatements() as $drvName => list($drv, $stringCoersion, $class, $func)) {
|
$t = preg_replace("<^strict >", "", $type);
|
||||||
$conv = $decorators[$drvName] ?? $conv = $decorators[''];
|
if (gettype($exp) != "string") var_export($index);
|
||||||
if ($drvName=="PDO PostgreSQL") {
|
$exp = ($exp=="null") ? $exp : $this->decorateTypeSyntax($exp, $t);
|
||||||
// skip PostgreSQL for these tests
|
yield $index => [$value, $type, $exp];
|
||||||
$drv = false;
|
|
||||||
}
|
|
||||||
foreach ($tests as $index => list($value, $type, $exp)) {
|
|
||||||
$t = preg_replace("<^strict >", "", $type);
|
|
||||||
$exp = ($exp=="null") ? $exp : $conv($exp, $t);
|
|
||||||
yield "$index ($drvName)" => [$drv, $class, $func, $value, $type, $exp];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function provideSyntaxDecorators() {
|
|
||||||
return [
|
|
||||||
'PDO PostgreSQL' => (function($v, $t) {
|
|
||||||
switch ($t) {
|
|
||||||
case "float":
|
|
||||||
return (substr($v, -2)==".0") ? "'".substr($v, 0, strlen($v) - 2)."'" : "'$v'";
|
|
||||||
case "string":
|
|
||||||
if (preg_match("<^char\((\d+)\)$>", $v, $match)) {
|
|
||||||
return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'";
|
|
||||||
} else {
|
|
||||||
return $v;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return $v;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
'PDO SQLite 3' => (function($v, $t) {
|
|
||||||
if ($t=="float") {
|
|
||||||
return (substr($v, -2)==".0") ? "'".substr($v, 0, strlen($v) - 2)."'" : "'$v'";
|
|
||||||
} else {
|
|
||||||
return $v;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
'SQLite 3' => (function($v, $t) {
|
|
||||||
return $v;
|
|
||||||
}),
|
|
||||||
'' => (function($v, $t) {
|
|
||||||
return $v;
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
23
tests/cases/Db/PostgreSQL/TestDriver.php
Normal file
23
tests/cases/Db/PostgreSQL/TestDriver.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?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\PostgreSQL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \JKingWeb\Arsse\Db\PostgreSQL\PDODriver<extended>
|
||||||
|
* @covers \JKingWeb\Arsse\Db\PDODriver
|
||||||
|
* @covers \JKingWeb\Arsse\Db\PDOError */
|
||||||
|
class TestDriver extends \JKingWeb\Arsse\TestCase\Db\BaseDriver {
|
||||||
|
protected $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 $setVersion = "UPDATE arsse_meta set value = '#' where key = 'schema_version'";
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
parent::tearDown();
|
||||||
|
unset($this->interface);
|
||||||
|
}
|
||||||
|
}
|
42
tests/cases/Db/PostgreSQL/TestStatement.php
Normal file
42
tests/cases/Db/PostgreSQL/TestStatement.php
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?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\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 function makeStatement(string $q, array $types = []): array {
|
||||||
|
return [$this->interface, $this->interface->prepare($q), $types];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decorateTypeSyntax(string $value, string $type): string {
|
||||||
|
switch ($type) {
|
||||||
|
case "float":
|
||||||
|
return (substr($value, -2)==".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
|
||||||
|
case "string":
|
||||||
|
if (preg_match("<^char\((\d+)\)$>", $value, $match)) {
|
||||||
|
return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'";
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
tests/cases/Db/SQLite3/TestStatement.php
Normal file
32
tests/cases/Db/SQLite3/TestStatement.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?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\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";
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
parent::tearDown();
|
||||||
|
$this->interface->close();
|
||||||
|
unset($this->interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function exec(string $q) {
|
||||||
|
$this->interface->exec($q);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function makeStatement(string $q, array $types = []): array {
|
||||||
|
return [$this->interface, $this->interface->prepare($q), $types];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decorateTypeSyntax(string $value, string $type): string {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
35
tests/cases/Db/SQLite3PDO/TestStatement.php
Normal file
35
tests/cases/Db/SQLite3PDO/TestStatement.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?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\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 function makeStatement(string $q, array $types = []): array {
|
||||||
|
return [$this->interface, $this->interface->prepare($q), $types];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decorateTypeSyntax(string $value, string $type): string {
|
||||||
|
if ($type=="float") {
|
||||||
|
return (substr($value, -2)==".0") ? "'".substr($value, 0, strlen($value) - 2)."'" : "'$value'";
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setConf(array $conf = []) {
|
public static function setConf(array $conf = [], bool $force = true) {
|
||||||
$defaults = [
|
$defaults = [
|
||||||
'dbSQLite3File' => ":memory:",
|
'dbSQLite3File' => ":memory:",
|
||||||
'dbSQLite3Timeout' => 0,
|
'dbSQLite3Timeout' => 0,
|
||||||
|
@ -48,7 +48,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
||||||
'dbPostgreSQLPass' => "arsse_test",
|
'dbPostgreSQLPass' => "arsse_test",
|
||||||
'dbPostgreSQLDb' => "arsse_test",
|
'dbPostgreSQLDb' => "arsse_test",
|
||||||
];
|
];
|
||||||
Arsse::$conf = Arsse::$conf ?? (new Conf)->import($defaults)->import($conf);
|
Arsse::$conf = ($force ? null : Arsse::$conf) ?? (new Conf)->import($defaults)->import($conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function assertException(string $msg = "", string $prefix = "", string $type = "Exception") {
|
public function assertException(string $msg = "", string $prefix = "", string $type = "Exception") {
|
||||||
|
|
Loading…
Reference in a new issue