mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
aa1b65b5d4
Tests for different drivers will have their own files, but all derive from a common prototype test series where applicable, similar to the existing arrangement for database function tests. However, the prototype will reside with other test cases rather than in the library path. The database function test series will hopefully be moved as well in time.
290 lines
12 KiB
PHP
290 lines
12 KiB
PHP
<?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\Test;
|
|
|
|
use JKingWeb\Arsse\Exception;
|
|
use JKingWeb\Arsse\Arsse;
|
|
use JKingWeb\Arsse\Conf;
|
|
use JKingWeb\Arsse\CLI;
|
|
use JKingWeb\Arsse\Misc\Date;
|
|
use Psr\Http\Message\MessageInterface;
|
|
use Psr\Http\Message\RequestInterface;
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use Zend\Diactoros\Response\JsonResponse;
|
|
use Zend\Diactoros\Response\EmptyResponse;
|
|
|
|
/** @coversNothing */
|
|
abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
|
public function setUp() {
|
|
$this->clearData();
|
|
}
|
|
|
|
public function tearDown() {
|
|
$this->clearData();
|
|
}
|
|
|
|
public function clearData(bool $loadLang = true) {
|
|
date_default_timezone_set("America/Toronto");
|
|
$r = new \ReflectionClass(\JKingWeb\Arsse\Arsse::class);
|
|
$props = array_keys($r->getStaticProperties());
|
|
foreach ($props as $prop) {
|
|
Arsse::$$prop = null;
|
|
}
|
|
if ($loadLang) {
|
|
Arsse::$lang = new \JKingWeb\Arsse\Lang();
|
|
}
|
|
}
|
|
|
|
public function setConf(array $conf = []) {
|
|
$defaults = [
|
|
'dbSQLite3File' => ":memory:",
|
|
'dbSQLite3Timeout' => 0,
|
|
'dbPostgreSQLUser' => "arsse_test",
|
|
'dbPostgreSQLPass' => "arsse_test",
|
|
'dbPostgreSQLDb' => "arsse_test",
|
|
];
|
|
Arsse::$conf = Arsse::$conf ?? (new Conf)->import($defaults)->import($conf);
|
|
}
|
|
|
|
public function assertException(string $msg = "", string $prefix = "", string $type = "Exception") {
|
|
if (func_num_args()) {
|
|
$class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
|
$msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg";
|
|
if (array_key_exists($msgID, Exception::CODES)) {
|
|
$code = Exception::CODES[$msgID];
|
|
} else {
|
|
$code = 0;
|
|
}
|
|
$this->expectException($class);
|
|
$this->expectExceptionCode($code);
|
|
} else {
|
|
// expecting a standard PHP exception
|
|
$this->expectException(\Exception::class);
|
|
}
|
|
}
|
|
|
|
protected function assertMessage(MessageInterface $exp, MessageInterface $act, string $text = null) {
|
|
if ($exp instanceof ResponseInterface) {
|
|
$this->assertInstanceOf(ResponseInterface::class, $act, $text);
|
|
$this->assertEquals($exp->getStatusCode(), $act->getStatusCode(), $text);
|
|
} elseif ($exp instanceof RequestInterface) {
|
|
if ($exp instanceof ServerRequestInterface) {
|
|
$this->assertInstanceOf(ServerRequestInterface::class, $act, $text);
|
|
$this->assertEquals($exp->getAttributes(), $act->getAttributes(), $text);
|
|
}
|
|
$this->assertInstanceOf(RequestInterface::class, $act, $text);
|
|
$this->assertSame($exp->getMethod(), $act->getMethod(), $text);
|
|
$this->assertSame($exp->getRequestTarget(), $act->getRequestTarget(), $text);
|
|
}
|
|
if ($exp instanceof JsonResponse) {
|
|
$this->assertEquals($exp->getPayload(), $act->getPayload(), $text);
|
|
$this->assertSame($exp->getPayload(), $act->getPayload(), $text);
|
|
} else {
|
|
$this->assertEquals((string) $exp->getBody(), (string) $act->getBody(), $text);
|
|
}
|
|
$this->assertEquals($exp->getHeaders(), $act->getHeaders(), $text);
|
|
}
|
|
|
|
public function assertTime($exp, $test, string $msg = null) {
|
|
$test = $this->approximateTime($exp, $test);
|
|
$exp = Date::transform($exp, "iso8601");
|
|
$test = Date::transform($test, "iso8601");
|
|
$this->assertSame($exp, $test, $msg);
|
|
}
|
|
|
|
public function approximateTime($exp, $act) {
|
|
if (is_null($act)) {
|
|
return null;
|
|
} elseif (is_null($exp)) {
|
|
return $act;
|
|
}
|
|
$target = Date::normalize($exp)->getTimeStamp();
|
|
$value = Date::normalize($act)->getTimeStamp();
|
|
if ($value >= ($target - 1) && $value <= ($target + 1)) {
|
|
// if the actual time is off by no more than one second, it's acceptable
|
|
return $exp;
|
|
} else {
|
|
return $act;
|
|
}
|
|
}
|
|
|
|
public function stringify($value) {
|
|
if (!is_array($value)) {
|
|
return $value;
|
|
}
|
|
foreach ($value as $k => $v) {
|
|
if (is_array($v)) {
|
|
$value[$k] = $this->v($v);
|
|
} elseif (is_int($v) || is_float($v)) {
|
|
$value[$k] = (string) $v;
|
|
}
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
public function provideDbDrivers(array $conf = []): array {
|
|
$this->setConf($conf);
|
|
return [
|
|
'SQLite 3' => (function() {
|
|
try {
|
|
return new \JKingWeb\Arsse\Db\SQLite3\Driver;
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
})(),
|
|
'PDO SQLite 3' => (function() {
|
|
try {
|
|
return new \JKingWeb\Arsse\Db\SQLite3\PDODriver;
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
})(),
|
|
'PDO PostgreSQL' => (function() {
|
|
try {
|
|
return new \JKingWeb\Arsse\Db\PostgreSQL\PDODriver;
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
})(),
|
|
];
|
|
}
|
|
|
|
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,
|
|
],
|
|
];
|
|
}
|
|
|
|
public function getDbDriver(string $name, array $conf = []) {
|
|
$this->setConf($conf);
|
|
switch ($name) {
|
|
case 'SQLite 3':
|
|
return (function() {
|
|
try {
|
|
return new \JKingWeb\Arsse\Db\SQLite3\Driver;
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
})();
|
|
case 'PDO SQLite 3':
|
|
return (function() {
|
|
try {
|
|
return new \JKingWeb\Arsse\Db\SQLite3\PDODriver;
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
})();
|
|
case 'PDO PostgreSQL':
|
|
return (function() {
|
|
try {
|
|
return new \JKingWeb\Arsse\Db\PostgreSQL\PDODriver;
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
})();
|
|
default:
|
|
throw new \Exception("Invalid database driver name");
|
|
}
|
|
}
|
|
|
|
public function getDbInterface(string $name, array $conf = []) {
|
|
$this->setConf($conf);
|
|
switch ($name) {
|
|
case 'SQLite 3':
|
|
return (function() {
|
|
if (\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet()) {
|
|
try {
|
|
$d = new \SQLite3(Arsse::$conf->dbSQLite3File);
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
$d->enableExceptions(true);
|
|
return $d;
|
|
}
|
|
})();
|
|
case 'PDO SQLite 3':
|
|
return (function() {
|
|
if (\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) {
|
|
try {
|
|
$d = new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
|
|
$d->exec("PRAGMA busy_timeout=0");
|
|
return $d;
|
|
} catch (\PDOException $e) {
|
|
return;
|
|
}
|
|
}
|
|
})();
|
|
case 'PDO PostgreSQL':
|
|
return (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;
|
|
}
|
|
})();
|
|
default:
|
|
throw new \Exception("Invalid database driver name");
|
|
}
|
|
}
|
|
}
|