Browse Source

Tests for Database::meta*() functions

Improves #49
microsub
J. King 7 years ago
parent
commit
3a26c75044
  1. 21
      lib/Database.php
  2. 12
      lib/Feed.php
  3. 13
      lib/Service.php
  4. 2
      lib/User.php
  5. 9
      tests/Db/SQLite3/Database/TestDatabaseMetaSQLite3.php
  6. 70
      tests/lib/Database/SeriesMeta.php
  7. 9
      tests/lib/Database/Setup.php
  8. 1
      tests/phpunit.xml

21
lib/Database.php

@ -8,10 +8,6 @@ use JKingWeb\Arsse\Misc\Date;
class Database {
const SCHEMA_VERSION = 1;
const FORMAT_TS = "Y-m-d h:i:s";
const FORMAT_DATE = "Y-m-d";
const FORMAT_TIME = "h:i:s";
/** @var Db\Driver */
public $db;
@ -29,7 +25,7 @@ class Database {
return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
}
static public function listDrivers(): array {
static public function driverList(): array {
$sep = \DIRECTORY_SEPARATOR;
$path = __DIR__.$sep."Db".$sep;
$classes = [];
@ -41,11 +37,11 @@ class Database {
return $classes;
}
public function schemaVersion(): int {
public function driverSchemaVersion(): int {
return $this->db->schemaVersion();
}
public function schemaUpdate(): bool {
public function driverSchemaUpdate(): bool {
if($this->db->schemaVersion() < self::SCHEMA_VERSION) return $this->db->schemaUpdate(self::SCHEMA_VERSION);
return false;
}
@ -86,17 +82,16 @@ class Database {
return $this->db->prepare("SELECT value from arsse_meta where key is ?", "str")->run($key)->getValue();
}
public function metaSet(string $key, string $value, string $type = "str"): bool {
$out = !$this->db->prepare("UPDATE arsse_meta set value = ? where key is ?", $type, "str")->run($value, $key)->changes();
public function metaSet(string $key, $value, string $type = "str"): bool {
$out = $this->db->prepare("UPDATE arsse_meta set value = ? where key is ?", $type, "str")->run($value, $key)->changes();
if(!$out) {
$out = $this->db->prepare("INSERT INTO arsse_meta(key,value)", "str", $type)->run($key, $value)->changes();
$out = $this->db->prepare("INSERT INTO arsse_meta(key,value) values(?,?)", "str", $type)->run($key, $value)->changes();
}
return (bool) $out;
}
public function metaRemove(string $key): bool {
$this->db->prepare("DELETE from arsse_meta where key is ?", "str")->run($key);
return true;
return (bool) $this->db->prepare("DELETE from arsse_meta where key is ?", "str")->run($key)->changes();
}
public function userExists(string $user): bool {
@ -776,7 +771,7 @@ class Database {
return (bool) $out;
}
public function articleValidateId(string $user, int $id): array {
protected function articleValidateId(string $user, int $id): array {
$out = $this->db->prepare(
"SELECT
arsse_articles.id as article,

12
lib/Feed.php

@ -52,7 +52,7 @@ class Feed {
$this->nextFetch = $this->computeNextFetch();
}
public function download(string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = ''): bool {
protected function download(string $url, string $lastModified = '', string $etag = '', string $username = '', string $password = ''): bool {
try {
$this->reader = new Reader($this->config);
$this->resource = $this->reader->download($url, $lastModified, $etag, $username, $password);
@ -62,7 +62,7 @@ class Feed {
return true;
}
public function parse(): bool {
protected function parse(): bool {
try {
$this->parser = $this->reader->getParser(
$this->resource->getUrl(),
@ -192,7 +192,7 @@ class Feed {
return $out;
}
public function matchToDatabase(int $feedID = null): bool {
protected function matchToDatabase(int $feedID = null): bool {
// first perform deduplication on items
$items = $this->deduplicateItems($this->data->items);
// if we haven't been given a database feed ID to check against, all items are new
@ -221,7 +221,7 @@ class Feed {
return true;
}
public function matchItems(array $items, array $articles): array {
protected function matchItems(array $items, array $articles): array {
$new = $edited = [];
// iterate through the articles and for each determine whether it is existing, edited, or entirely new
foreach($items as $i) {
@ -260,7 +260,7 @@ class Feed {
return [$new, $edited];
}
public function computeNextFetch(): \DateTime {
protected function computeNextFetch(): \DateTime {
$now = Date::normalize(time());
if(!$this->modified) {
$diff = $now->getTimestamp() - $this->lastModified->getTimestamp();
@ -318,7 +318,7 @@ class Feed {
return $offset;
}
public function computeLastModified() {
protected function computeLastModified() {
if(!$this->modified) return $this->lastModified;
$dates = $this->gatherDates();
if(sizeof($dates)) {

13
lib/Service.php

@ -9,6 +9,18 @@ class Service {
protected $drv;
/** @var \DateInterval */
protected $interval;
static public function driverList(): array {
$sep = \DIRECTORY_SEPARATOR;
$path = __DIR__.$sep."Service".$sep;
$classes = [];
foreach(glob($path."*".$sep."Driver.php") as $file) {
$name = basename(dirname($file));
$class = NS_BASE."User\\$name\\Driver";
$classes[$class] = $class::driverName();
}
return $classes;
}
protected static function interval(): \DateInterval {
return new \DateInterval(Arsse::$conf->serviceFrequency); // FIXME: this needs to fall back in case of incorrect input
@ -32,6 +44,7 @@ class Service {
$this->drv->exec();
$this->drv->clean();
static::cleanupPost();
unset($list);
}
$t->add($this->interval);
do {

2
lib/User.php

@ -19,7 +19,7 @@ class User {
protected $authzSupported = 0;
protected $actor = [];
static public function listDrivers(): array {
static public function driverList(): array {
$sep = \DIRECTORY_SEPARATOR;
$path = __DIR__.$sep."User".$sep;
$classes = [];

9
tests/Db/SQLite3/Database/TestDatabaseMetaSQLite3.php

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace JKingWeb\Arsse;
class TestDatabaseMetaSQLite3 extends Test\AbstractTest {
use Test\Database\Setup;
use Test\Database\DriverSQLite3;
use Test\Database\SeriesMeta;
}

70
tests/lib/Database/SeriesMeta.php

@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace JKingWeb\Arsse\Test\Database;
use JKingWeb\Arsse\Test\Database;
use JKingWeb\Arsse\Arsse;
trait SeriesMeta {
protected $dataBare = [
'arsse_meta' => [
'columns' => [
'key' => 'str',
'value' => 'str',
],
'rows' => [
//['schema_version', "".\JKingWeb\Arsse\Database::SCHEMA_VERSION],
['album',"A Farewell to Kings"],
],
],
];
function setUpSeries() {
// the schema_version key is a special case, and to avoid jumping through hoops for every test we deal with it now
$this->data = $this->dataBare;
// as far as tests are concerned the schema version is part of the expectations primed into the database
array_unshift($this->data['arsse_meta']['rows'], ['schema_version', "".Database::SCHEMA_VERSION]);
// but it's already been inserted by the driver, so we prime without it
$this->primeDatabase($this->dataBare);
}
function testAddANewValue() {
$this->assertTrue(Arsse::$db->metaSet("favourite", "Cygnus X-1"));
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
$state['arsse_meta']['rows'][] = ["favourite","Cygnus X-1"];
$this->compareExpectations($state);
}
function testAddANewTypedValue() {
$this->assertTrue(Arsse::$db->metaSet("answer", 42, "int"));
$this->assertTrue(Arsse::$db->metaSet("true", true, "bool"));
$this->assertTrue(Arsse::$db->metaSet("false", false, "bool"));
$this->assertTrue(Arsse::$db->metaSet("millennium", new \DateTime("2000-01-01T00:00:00Z"), "datetime"));
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
$state['arsse_meta']['rows'][] = ["answer","42"];
$state['arsse_meta']['rows'][] = ["true","1"];
$state['arsse_meta']['rows'][] = ["false","0"];
$state['arsse_meta']['rows'][] = ["millennium","2000-01-01 00:00:00"];
$this->compareExpectations($state);
}
function testChangeAnExistingValue() {
$this->assertTrue(Arsse::$db->metaSet("album", "Hemispheres"));
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
$state['arsse_meta']['rows'][1][1] = "Hemispheres";
$this->compareExpectations($state);
}
function testRemoveAValue() {
$this->assertTrue(Arsse::$db->metaRemove("album"));
$this->assertFalse(Arsse::$db->metaRemove("album"));
$state = $this->primeExpectations($this->data, ['arsse_meta' => ['key','value']]);
unset($state['arsse_meta']['rows'][1]);
$this->compareExpectations($state);
}
function testRetrieveAValue() {
$this->assertSame("".Database::SCHEMA_VERSION, Arsse::$db->metaGet("schema_version"));
$this->assertSame("A Farewell to Kings", Arsse::$db->metaGet("album"));
$this->assertSame(null, Arsse::$db->metaGet("this_key_does_not_exist"));
}
}

9
tests/lib/Database/Setup.php

@ -11,6 +11,7 @@ use Phake;
trait Setup {
protected $drv;
protected $primed = false;
function setUp() {
// establish a clean baseline
@ -21,20 +22,21 @@ trait Setup {
$this->setUpDriver();
// create the database interface with the suitable driver
Arsse::$db = new Database($this->drv);
Arsse::$db->schemaUpdate();
Arsse::$db->driverSchemaUpdate();
// create a mock user manager
Arsse::$user = Phake::mock(User::class);
Phake::when(Arsse::$user)->authorize->thenReturn(true);
// call the additional setup method if it exists
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
// prime the database with series data
if(isset($this->data)) $this->primeDatabase($this->data);
// prime the database with series data if it hasn't already been done
if(!$this->primed && isset($this->data)) $this->primeDatabase($this->data);
}
function tearDown() {
// call the additional teardiwn method if it exists
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
// clean up
$this->primed = false;
$this->drv = null;
$this->clearData();
}
@ -51,6 +53,7 @@ trait Setup {
}
}
$tr->commit();
$this->primed = true;
return true;
}

1
tests/phpunit.xml

@ -42,6 +42,7 @@
<file>Db/SQLite3/TestDbUpdateSQLite3.php</file>
</testsuite>
<testsuite name="Database functions">
<file>Db/SQLite3/Database/TestDatabaseMetaSQLite3.php</file>
<file>Db/SQLite3/Database/TestDatabaseUserSQLite3.php</file>
<file>Db/SQLite3/Database/TestDatabaseFolderSQLite3.php</file>
<file>Db/SQLite3/Database/TestDatabaseFeedSQLite3.php</file>

Loading…
Cancel
Save