Browse Source

Convert one database function test series (articles) to a common harness

Also revert the dropping of tables in the schema files. This was for the
convenience of tests, but the risk of data loss is too great
microsub
J. King 5 years ago
parent
commit
dccd4caede
  1. 12
      sql/PostgreSQL/0.sql
  2. 4
      sql/PostgreSQL/1.sql
  3. 1
      sql/PostgreSQL/2.sql
  4. 13
      sql/SQLite3/0.sql
  5. 5
      sql/SQLite3/1.sql
  6. 95
      tests/cases/Database/Base.php
  7. 823
      tests/cases/Database/SeriesArticle.php
  8. 19
      tests/cases/Db/SQLite3/TestDatabase.php
  9. 19
      tests/cases/Db/SQLite3PDO/TestDatabase.php
  10. 82
      tests/lib/DatabaseInformation.php

12
sql/PostgreSQL/0.sql

@ -4,18 +4,6 @@
-- Please consult the SQLite 3 schemata for commented version
drop table if exists arsse_meta cascade;
drop table if exists arsse_users cascade;
drop table if exists arsse_users_meta cascade;
drop table if exists arsse_folders cascade;
drop table if exists arsse_feeds cascade;
drop table if exists arsse_subscriptions cascade;
drop table if exists arsse_articles cascade;
drop table if exists arsse_enclosures cascade;
drop table if exists arsse_marks cascade;
drop table if exists arsse_editions cascade;
drop table if exists arsse_categories cascade;
create table arsse_meta(
key text primary key,
value text

4
sql/PostgreSQL/1.sql

@ -4,10 +4,6 @@
-- Please consult the SQLite 3 schemata for commented version
drop table if exists arsse_sessions cascade;
drop table if exists arsse_labels cascade;
drop table if exists arsse_label_members cascade;
create table arsse_sessions (
id text primary key,
created timestamp(0) with time zone not null default CURRENT_TIMESTAMP,

1
sql/PostgreSQL/2.sql

@ -7,7 +7,6 @@
-- create a case-insensitive generic collation sequence
-- this collation is Unicode-aware, whereas SQLite's built-in nocase
-- collation is ASCII-only
drop collation if exists nocase cascade;
create collation nocase(
provider = icu,
locale = '@kf=false'

13
sql/SQLite3/0.sql

@ -5,19 +5,6 @@
-- Make the database WAL-journalled; this is persitent
PRAGMA journal_mode = wal;
-- drop any existing tables, just in case
drop table if exists arsse_meta;
drop table if exists arsse_users;
drop table if exists arsse_users_meta;
drop table if exists arsse_folders;
drop table if exists arsse_feeds;
drop table if exists arsse_subscriptions;
drop table if exists arsse_articles;
drop table if exists arsse_enclosures;
drop table if exists arsse_marks;
drop table if exists arsse_editions;
drop table if exists arsse_categories;
create table arsse_meta(
-- application metadata
key text primary key not null, -- metadata key

5
sql/SQLite3/1.sql

@ -2,11 +2,6 @@
-- Copyright 2017 J. King, Dustin Wilson et al.
-- See LICENSE and AUTHORS files for details
-- drop any existing tables, just in case
drop table if exists arsse_sessions;
drop table if exists arsse_labels;
drop table if exists arsse_label_members;
create table arsse_sessions (
-- sessions for Tiny Tiny RSS (and possibly others)
id text primary key, -- UUID of session

95
tests/cases/Database/Base.php

@ -6,37 +6,72 @@
declare(strict_types=1);
namespace JKingWeb\Arsse\TestCase\Database;
use JKingWeb\Arsse\User\Driver as UserDriver;
use JKingWeb\Arsse\Test\Database;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Conf;
use JKingWeb\Arsse\User;
use JKingWeb\Arsse\Misc\ValueInfo;
use JKingWeb\Arsse\Database;
use JKingWeb\Arsse\Db\Result;
use JKingWeb\Arsse\Test\DatabaseInformation;
use Phake;
abstract class Base {
protected $drv;
abstract class Base extends \JKingWeb\Arsse\Test\AbstractTest{
use SeriesArticle;
/** @var \JKingWeb\Arsse\Test\DatabaseInformation */
protected static $dbInfo;
/** @var \JKingWeb\Arsse\Db\Driver */
protected static $drv;
protected static $failureReason = "";
protected $primed = false;
protected abstract function nextID(string $table): int;
public function setUp() {
protected function findTraitOfTest(string $test): string {
$class = new \ReflectionClass(self::class);
foreach ($class->getTraits() as $trait) {
if ($trait->hasMethod($test)) {
return $trait->getShortName();
}
}
return $class->getShortName();
}
public static function setUpBeforeClass() {
// establish a clean baseline
self::clearData();
self::setConf();
// configure and create the relevant database driver
$this->setUpDriver();
// create the database interface with the suitable driver
Arsse::$db = new Database;
static::clearData();
// perform an initial connection to the database to reset its version to zero
// in the case of SQLite this will always be the case (we use a memory database),
// but other engines should clean up from potentially interrupted prior tests
static::$dbInfo = new DatabaseInformation(static::$implementation);
static::setConf();
try {
static::$drv = new static::$dbInfo->driverClass;
} catch (\JKingWeb\Arsse\Db\Exception $e) {
static::$failureReason = $e->getMessage();
return;
}
// wipe the database absolutely clean
(static::$dbInfo->razeFunction)(static::$drv);
// create the database interface with the suitable driver and apply the latest schema
Arsse::$db = new Database(static::$drv);
Arsse::$db->driverSchemaUpdate();
}
public function setUp() {
// get the name of the test's test series
$this->series = $this->findTraitofTest($this->getName());
static::clearData();
if (strlen(static::$failureReason)) {
$this->markTestSkipped(static::$failureReason);
}
Arsse::$db = new Database(static::$drv);
// 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();
}
// call the series-specific setup method
$setUp = "setUp".$this->series;
$this->$setUp();
// prime the database with series data if it hasn't already been done
if (!$this->primed && isset($this->data)) {
$this->primeDatabase($this->data);
@ -44,18 +79,30 @@ abstract class Base {
}
public function tearDown() {
// call the additional teardiwn method if it exists
if (method_exists($this, "tearDownSeries")) {
$this->tearDownSeries();
}
// call the series-specific teardown method
$this->series = $this->findTraitofTest($this->getName());
$tearDown = "tearDown".$this->series;
$this->$tearDown();
// clean up
$this->primed = false;
$this->drv = null;
self::clearData();
// call the database-specific table cleanup function
(static::$dbInfo->truncateFunction)(static::$drv);
// clear state
static::clearData();
}
public static function tearDownAfterClass() {
// wipe the database absolutely clean
(static::$dbInfo->razeFunction)(static::$drv);
// clean up
static::$drv = null;
static::$dbInfo = null;
static::$failureReason = "";
static::clearData();
}
public function primeDatabase(array $data, \JKingWeb\Arsse\Db\Driver $drv = null): bool {
$drv = $drv ?? $this->drv;
public function primeDatabase(array $data): bool {
$drv = static::$drv;
$tr = $drv->begin();
foreach ($data as $table => $info) {
$cols = implode(",", array_keys($info['columns']));
@ -75,7 +122,7 @@ abstract class Base {
foreach ($expected as $table => $info) {
$cols = implode(",", array_keys($info['columns']));
$types = $info['columns'];
$data = $this->drv->prepare("SELECT $cols from $table")->run()->getAll();
$data = static::$drv->prepare("SELECT $cols from $table")->run()->getAll();
$cols = array_keys($info['columns']);
foreach ($info['rows'] as $index => $row) {
$this->assertCount(sizeof($cols), $row, "The number of values for array index $index does not match the number of fields");

823
tests/cases/Database/SeriesArticle.php

@ -13,463 +13,464 @@ use JKingWeb\Arsse\Misc\Date;
use Phake;
trait SeriesArticle {
protected $data = [
'arsse_users' => [
'columns' => [
'id' => 'str',
'password' => 'str',
'name' => 'str',
protected function setUpSeriesArticle() {
$this->data = [
'arsse_users' => [
'columns' => [
'id' => 'str',
'password' => 'str',
'name' => 'str',
],
'rows' => [
["jane.doe@example.com", "", "Jane Doe"],
["john.doe@example.com", "", "John Doe"],
["john.doe@example.org", "", "John Doe"],
["john.doe@example.net", "", "John Doe"],
],
],
'rows' => [
["jane.doe@example.com", "", "Jane Doe"],
["john.doe@example.com", "", "John Doe"],
["john.doe@example.org", "", "John Doe"],
["john.doe@example.net", "", "John Doe"],
'arsse_folders' => [
'columns' => [
'id' => "int",
'owner' => "str",
'parent' => "int",
'name' => "str",
],
'rows' => [
[1, "john.doe@example.com", null, "Technology"],
[2, "john.doe@example.com", 1, "Software"],
[3, "john.doe@example.com", 1, "Rocketry"],
[4, "jane.doe@example.com", null, "Politics"],
[5, "john.doe@example.com", null, "Politics"],
[6, "john.doe@example.com", 2, "Politics"],
[7, "john.doe@example.net", null, "Technology"],
[8, "john.doe@example.net", 7, "Software"],
[9, "john.doe@example.net", null, "Politics"],
]
],
],
'arsse_folders' => [
'columns' => [
'id' => "int",
'owner' => "str",
'parent' => "int",
'name' => "str",
'arsse_feeds' => [
'columns' => [
'id' => "int",
'url' => "str",
'title' => "str",
],
'rows' => [
[1,"http://example.com/1", "Feed 1"],
[2,"http://example.com/2", "Feed 2"],
[3,"http://example.com/3", "Feed 3"],
[4,"http://example.com/4", "Feed 4"],
[5,"http://example.com/5", "Feed 5"],
[6,"http://example.com/6", "Feed 6"],
[7,"http://example.com/7", "Feed 7"],
[8,"http://example.com/8", "Feed 8"],
[9,"http://example.com/9", "Feed 9"],
[10,"http://example.com/10", "Feed 10"],
[11,"http://example.com/11", "Feed 11"],
[12,"http://example.com/12", "Feed 12"],
[13,"http://example.com/13", "Feed 13"],
]
],
'rows' => [
[1, "john.doe@example.com", null, "Technology"],
[2, "john.doe@example.com", 1, "Software"],
[3, "john.doe@example.com", 1, "Rocketry"],
[4, "jane.doe@example.com", null, "Politics"],
[5, "john.doe@example.com", null, "Politics"],
[6, "john.doe@example.com", 2, "Politics"],
[7, "john.doe@example.net", null, "Technology"],
[8, "john.doe@example.net", 7, "Software"],
[9, "john.doe@example.net", null, "Politics"],
]
],
'arsse_feeds' => [
'columns' => [
'id' => "int",
'url' => "str",
'title' => "str",
'arsse_subscriptions' => [
'columns' => [
'id' => "int",
'owner' => "str",
'feed' => "int",
'folder' => "int",
'title' => "str",
],
'rows' => [
[1, "john.doe@example.com",1, null,"Subscription 1"],
[2, "john.doe@example.com",2, null,null],
[3, "john.doe@example.com",3, 1,"Subscription 3"],
[4, "john.doe@example.com",4, 6,null],
[5, "john.doe@example.com",10, 5,"Subscription 5"],
[6, "jane.doe@example.com",1, null,null],
[7, "jane.doe@example.com",10,null,"Subscription 7"],
[8, "john.doe@example.org",11,null,null],
[9, "john.doe@example.org",12,null,"Subscription 9"],
[10,"john.doe@example.org",13,null,null],
[11,"john.doe@example.net",10,null,"Subscription 11"],
[12,"john.doe@example.net",2, 9,null],
[13,"john.doe@example.net",3, 8,"Subscription 13"],
[14,"john.doe@example.net",4, 7,null],
]
],
'rows' => [
[1,"http://example.com/1", "Feed 1"],
[2,"http://example.com/2", "Feed 2"],
[3,"http://example.com/3", "Feed 3"],
[4,"http://example.com/4", "Feed 4"],
[5,"http://example.com/5", "Feed 5"],
[6,"http://example.com/6", "Feed 6"],
[7,"http://example.com/7", "Feed 7"],
[8,"http://example.com/8", "Feed 8"],
[9,"http://example.com/9", "Feed 9"],
[10,"http://example.com/10", "Feed 10"],
[11,"http://example.com/11", "Feed 11"],
[12,"http://example.com/12", "Feed 12"],
[13,"http://example.com/13", "Feed 13"],
]
],
'arsse_subscriptions' => [
'columns' => [
'id' => "int",
'owner' => "str",
'feed' => "int",
'folder' => "int",
'title' => "str",
'arsse_articles' => [
'columns' => [
'id' => "int",
'feed' => "int",
'url' => "str",
'title' => "str",
'author' => "str",
'published' => "datetime",
'edited' => "datetime",
'content' => "str",
'guid' => "str",
'url_title_hash' => "str",
'url_content_hash' => "str",
'title_content_hash' => "str",
'modified' => "datetime",
],
'rows' => [
[1,1,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[2,1,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[3,2,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[4,2,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[5,3,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[6,3,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[7,4,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[8,4,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[9,5,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[10,5,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[11,6,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[12,6,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[13,7,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[14,7,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[15,8,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[16,8,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[17,9,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[18,9,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[19,10,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[20,10,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[101,11,'http://example.com/1','Article title 1','','2000-01-01 00:00:00','2000-01-01 00:00:01','<p>Article content 1</p>','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207','2000-01-01 01:00:00'],
[102,11,'http://example.com/2','Article title 2','','2000-01-02 00:00:00','2000-01-02 00:00:02','<p>Article content 2</p>','5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7','0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153','13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9','2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e','2000-01-02 02:00:00'],
[103,12,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:03','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b','2000-01-03 03:00:00'],
[104,12,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:04','<p>Article content 4</p>','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9','2000-01-04 04:00:00'],
[105,13,'http://example.com/5','Article title 5','','2000-01-05 00:00:00','2000-01-05 00:00:05','<p>Article content 5</p>','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41','d40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022','834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900','43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba','2000-01-05 05:00:00'],
]
],
'rows' => [
[1, "john.doe@example.com",1, null,"Subscription 1"],
[2, "john.doe@example.com",2, null,null],
[3, "john.doe@example.com",3, 1,"Subscription 3"],
[4, "john.doe@example.com",4, 6,null],
[5, "john.doe@example.com",10, 5,"Subscription 5"],
[6, "jane.doe@example.com",1, null,null],
[7, "jane.doe@example.com",10,null,"Subscription 7"],
[8, "john.doe@example.org",11,null,null],
[9, "john.doe@example.org",12,null,"Subscription 9"],
[10,"john.doe@example.org",13,null,null],
[11,"john.doe@example.net",10,null,"Subscription 11"],
[12,"john.doe@example.net",2, 9,null],
[13,"john.doe@example.net",3, 8,"Subscription 13"],
[14,"john.doe@example.net",4, 7,null],
]
],
'arsse_articles' => [
'columns' => [
'id' => "int",
'feed' => "int",
'url' => "str",
'title' => "str",
'author' => "str",
'published' => "datetime",
'edited' => "datetime",
'content' => "str",
'guid' => "str",
'url_title_hash' => "str",
'url_content_hash' => "str",
'title_content_hash' => "str",
'modified' => "datetime",
'arsse_enclosures' => [
'columns' => [
'article' => "int",
'url' => "str",
'type' => "str",
],
'rows' => [
[102,"http://example.com/text","text/plain"],
[103,"http://example.com/video","video/webm"],
[104,"http://example.com/image","image/svg+xml"],
[105,"http://example.com/audio","audio/ogg"],
]
],
'rows' => [
[1,1,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[2,1,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[3,2,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[4,2,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[5,3,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[6,3,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[7,4,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[8,4,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[9,5,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[10,5,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[11,6,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[12,6,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[13,7,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[14,7,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[15,8,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[16,8,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[17,9,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[18,9,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[19,10,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[20,10,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[101,11,'http://example.com/1','Article title 1','','2000-01-01 00:00:00','2000-01-01 00:00:01','<p>Article content 1</p>','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207','2000-01-01 01:00:00'],
[102,11,'http://example.com/2','Article title 2','','2000-01-02 00:00:00','2000-01-02 00:00:02','<p>Article content 2</p>','5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7','0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153','13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9','2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e','2000-01-02 02:00:00'],
[103,12,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:03','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b','2000-01-03 03:00:00'],
[104,12,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:04','<p>Article content 4</p>','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9','2000-01-04 04:00:00'],
[105,13,'http://example.com/5','Article title 5','','2000-01-05 00:00:00','2000-01-05 00:00:05','<p>Article content 5</p>','db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41','d40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022','834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900','43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba','2000-01-05 05:00:00'],
]
],
'arsse_enclosures' => [
'columns' => [
'article' => "int",
'url' => "str",
'type' => "str",
'arsse_editions' => [
'columns' => [
'id' => "int",
'article' => "int",
],
'rows' => [
[1,1],
[2,2],
[3,3],
[4,4],
[5,5],
[6,6],
[7,7],
[8,8],
[9,9],
[10,10],
[11,11],
[12,12],
[13,13],
[14,14],
[15,15],
[16,16],
[17,17],
[18,18],
[19,19],
[20,20],
[101,101],
[102,102],
[103,103],
[104,104],
[105,105],
[202,102],
[203,103],
[204,104],
[205,105],
[305,105],
[1001,20],
]
],
'rows' => [
[102,"http://example.com/text","text/plain"],
[103,"http://example.com/video","video/webm"],
[104,"http://example.com/image","image/svg+xml"],
[105,"http://example.com/audio","audio/ogg"],
]
],
'arsse_editions' => [
'columns' => [
'id' => "int",
'article' => "int",
'arsse_marks' => [
'columns' => [
'subscription' => "int",
'article' => "int",
'read' => "bool",
'starred' => "bool",
'modified' => "datetime",
'note' => "str",
],
'rows' => [
[1, 1,1,1,'2000-01-01 00:00:00',''],
[5, 19,1,0,'2016-01-01 00:00:00',''],
[5, 20,0,1,'2005-01-01 00:00:00',''],
[7, 20,1,0,'2010-01-01 00:00:00',''],
[8, 102,1,0,'2000-01-02 02:00:00','Note 2'],
[9, 103,0,1,'2000-01-03 03:00:00','Note 3'],
[9, 104,1,1,'2000-01-04 04:00:00','Note 4'],
[10,105,0,0,'2000-01-05 05:00:00',''],
[11, 19,0,0,'2017-01-01 00:00:00','ook'],
[11, 20,1,0,'2017-01-01 00:00:00','eek'],
[12, 3,0,1,'2017-01-01 00:00:00','ack'],
[12, 4,1,1,'2017-01-01 00:00:00','ach'],
[1, 2,0,0,'2010-01-01 00:00:00','Some Note'],
]
],
'rows' => [
[1,1],
[2,2],
[3,3],
[4,4],
[5,5],
[6,6],
[7,7],
[8,8],
[9,9],
[10,10],
[11,11],
[12,12],
[13,13],
[14,14],
[15,15],
[16,16],
[17,17],
[18,18],
[19,19],
[20,20],
[101,101],
[102,102],
[103,103],
[104,104],
[105,105],
[202,102],
[203,103],
[204,104],
[205,105],
[305,105],
[1001,20],
]
],
'arsse_marks' => [
'columns' => [
'subscription' => "int",
'article' => "int",
'read' => "bool",
'starred' => "bool",
'modified' => "datetime",
'note' => "str",
'arsse_categories' => [ // author-supplied categories
'columns' => [
'article' => "int",
'name' => "str",
],
'rows' => [
[19,"Fascinating"],
[19,"Logical"],
[20,"Interesting"],
[20,"Logical"],
],
],
'rows' => [
[1, 1,1,1,'2000-01-01 00:00:00',''],
[5, 19,1,0,'2016-01-01 00:00:00',''],
[5, 20,0,1,'2005-01-01 00:00:00',''],
[7, 20,1,0,'2010-01-01 00:00:00',''],
[8, 102,1,0,'2000-01-02 02:00:00','Note 2'],
[9, 103,0,1,'2000-01-03 03:00:00','Note 3'],
[9, 104,1,1,'2000-01-04 04:00:00','Note 4'],
[10,105,0,0,'2000-01-05 05:00:00',''],
[11, 19,0,0,'2017-01-01 00:00:00','ook'],
[11, 20,1,0,'2017-01-01 00:00:00','eek'],
[12, 3,0,1,'2017-01-01 00:00:00','ack'],
[12, 4,1,1,'2017-01-01 00:00:00','ach'],
[1, 2,0,0,'2010-01-01 00:00:00','Some Note'],
]
],
'arsse_categories' => [ // author-supplied categories
'columns' => [
'article' => "int",
'name' => "str",
'arsse_labels' => [
'columns' => [
'id' => "int",
'owner' => "str",
'name' => "str",
],
'rows' => [
[1,"john.doe@example.com","Interesting"],
[2,"john.doe@example.com","Fascinating"],
[3,"jane.doe@example.com","Boring"],
[4,"john.doe@example.com","Lonely"],
],
],
'rows' => [
[19,"Fascinating"],
[19,"Logical"],
[20,"Interesting"],
[20,"Logical"],
'arsse_label_members' => [
'columns' => [
'label' => "int",
'article' => "int",
'subscription' => "int",
'assigned' => "bool",
'modified' => "datetime",
],
'rows' => [
[1, 1,1,1,'2000-01-01 00:00:00'],
[2, 1,1,1,'2000-01-01 00:00:00'],
[1,19,5,1,'2000-01-01 00:00:00'],
[2,20,5,1,'2000-01-01 00:00:00'],
[1, 5,3,0,'2000-01-01 00:00:00'],
[2, 5,3,1,'2000-01-01 00:00:00'],
[4, 7,4,0,'2000-01-01 00:00:00'],
[4, 8,4,1,'2015-01-01 00:00:00'],
],
],
],
'arsse_labels' => [
'columns' => [
'id' => "int",
'owner' => "str",
'name' => "str",
];
$this->matches = [
[
'id' => 101,
'url' => 'http://example.com/1',
'title' => 'Article title 1',
'subscription_title' => "Feed 11",
'author' => '',
'content' => '<p>Article content 1</p>',
'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda',
'published_date' => '2000-01-01 00:00:00',
'edited_date' => '2000-01-01 00:00:01',
'modified_date' => '2000-01-01 01:00:00',
'unread' => 1,
'starred' => 0,
'edition' => 101,
'subscription' => 8,
'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207',
'media_url' => null,
'media_type' => null,
'note' => "",
],
'rows' => [
[1,"john.doe@example.com","Interesting"],
[2,"john.doe@example.com","Fascinating"],
[3,"jane.doe@example.com","Boring"],
[4,"john.doe@example.com","Lonely"],
[
'id' => 102,
'url' => 'http://example.com/2',
'title' => 'Article title 2',
'subscription_title' => "Feed 11",
'author' => '',
'content' => '<p>Article content 2</p>',
'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7',
'published_date' => '2000-01-02 00:00:00',
'edited_date' => '2000-01-02 00:00:02',
'modified_date' => '2000-01-02 02:00:00',
'unread' => 0,
'starred' => 0,
'edition' => 202,
'subscription' => 8,
'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e',
'media_url' => "http://example.com/text",
'media_type' => "text/plain",
'note' => "Note 2",
],
],
'arsse_label_members' => [
'columns' => [
'label' => "int",
'article' => "int",
'subscription' => "int",
'assigned' => "bool",
'modified' => "datetime",
[
'id' => 103,
'url' => 'http://example.com/3',
'title' => 'Article title 3',
'subscription_title' => "Subscription 9",
'author' => '',
'content' => '<p>Article content 3</p>',
'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92',
'published_date' => '2000-01-03 00:00:00',
'edited_date' => '2000-01-03 00:00:03',
'modified_date' => '2000-01-03 03:00:00',
'unread' => 1,
'starred' => 1,
'edition' => 203,
'subscription' => 9,
'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b',
'media_url' => "http://example.com/video",
'media_type' => "video/webm",
'note' => "Note 3",
],
'rows' => [
[1, 1,1,1,'2000-01-01 00:00:00'],
[2, 1,1,1,'2000-01-01 00:00:00'],
[1,19,5,1,'2000-01-01 00:00:00'],
[2,20,5,1,'2000-01-01 00:00:00'],
[1, 5,3,0,'2000-01-01 00:00:00'],
[2, 5,3,1,'2000-01-01 00:00:00'],
[4, 7,4,0,'2000-01-01 00:00:00'],
[4, 8,4,1,'2015-01-01 00:00:00'],
[
'id' => 104,
'url' => 'http://example.com/4',
'title' => 'Article title 4',
'subscription_title' => "Subscription 9",
'author' => '',
'content' => '<p>Article content 4</p>',
'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180',
'published_date' => '2000-01-04 00:00:00',
'edited_date' => '2000-01-04 00:00:04',
'modified_date' => '2000-01-04 04:00:00',
'unread' => 0,
'starred' => 1,
'edition' => 204,
'subscription' => 9,
'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9',
'media_url' => "http://example.com/image",
'media_type' => "image/svg+xml",
'note' => "Note 4",
],
],
];
protected $matches = [
[
'id' => 101,
'url' => 'http://example.com/1',
'title' => 'Article title 1',
'subscription_title' => "Feed 11",
'author' => '',
'content' => '<p>Article content 1</p>',
'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda',
'published_date' => '2000-01-01 00:00:00',
'edited_date' => '2000-01-01 00:00:01',
'modified_date' => '2000-01-01 01:00:00',
'unread' => 1,
'starred' => 0,
'edition' => 101,
'subscription' => 8,
'fingerprint' => 'f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6:fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4:18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207',
'media_url' => null,
'media_type' => null,
'note' => "",
],
[
'id' => 102,
'url' => 'http://example.com/2',
'title' => 'Article title 2',
'subscription_title' => "Feed 11",
'author' => '',
'content' => '<p>Article content 2</p>',
'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7',
'published_date' => '2000-01-02 00:00:00',
'edited_date' => '2000-01-02 00:00:02',
'modified_date' => '2000-01-02 02:00:00',
'unread' => 0,
'starred' => 0,
'edition' => 202,
'subscription' => 8,
'fingerprint' => '0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153:13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9:2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e',
'media_url' => "http://example.com/text",
'media_type' => "text/plain",
'note' => "Note 2",
],
[
'id' => 103,
'url' => 'http://example.com/3',
'title' => 'Article title 3',
'subscription_title' => "Subscription 9",
'author' => '',
'content' => '<p>Article content 3</p>',
'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92',
'published_date' => '2000-01-03 00:00:00',
'edited_date' => '2000-01-03 00:00:03',
'modified_date' => '2000-01-03 03:00:00',
'unread' => 1,
'starred' => 1,
'edition' => 203,
'subscription' => 9,
'fingerprint' => 'f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b:b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406:ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b',
'media_url' => "http://example.com/video",
'media_type' => "video/webm",
'note' => "Note 3",
],
[
'id' => 104,
'url' => 'http://example.com/4',
'title' => 'Article title 4',
'subscription_title' => "Subscription 9",
'author' => '',
'content' => '<p>Article content 4</p>',
'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180',
'published_date' => '2000-01-04 00:00:00',
'edited_date' => '2000-01-04 00:00:04',
'modified_date' => '2000-01-04 04:00:00',
'unread' => 0,
'starred' => 1,
'edition' => 204,
'subscription' => 9,
'fingerprint' => 'f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8:f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3:ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9',
'media_url' => "http://example.com/image",
'media_type' => "image/svg+xml",
'note' => "Note 4",
],
[
'id' => 105,
'url' => 'http://example.com/5',
'title' => 'Article title 5',
'subscription_title' => "Feed 13",
'author' => '',
'content' => '<p>Article content 5</p>',
'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41',
'published_date' => '2000-01-05 00:00:00',
'edited_date' => '2000-01-05 00:00:05',
'modified_date' => '2000-01-05 05:00:00',
'unread' => 1,
'starred' => 0,
'edition' => 305,
'subscription' => 10,
'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba',
'media_url' => "http://example.com/audio",
'media_type' => "audio/ogg",
'note' => "",
],
];
protected $fields = [
Database::LIST_MINIMAL => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
],
Database::LIST_CONSERVATIVE => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
"url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint",
],
Database::LIST_TYPICAL => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
"url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint",
"content", "media_url", "media_type",
],
Database::LIST_FULL => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
"url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint",
"content", "media_url", "media_type",
"note",
],
];
public function setUpSeries() {
[
'id' => 105,
'url' => 'http://example.com/5',
'title' => 'Article title 5',
'subscription_title' => "Feed 13",
'author' => '',
'content' => '<p>Article content 5</p>',
'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41',
'published_date' => '2000-01-05 00:00:00',
'edited_date' => '2000-01-05 00:00:05',
'modified_date' => '2000-01-05 05:00:00',
'unread' => 1,
'starred' => 0,
'edition' => 305,
'subscription' => 10,
'fingerprint' => 'd40da96e39eea6c55948ccbe9b3d275b5f931298288dbe953990c5f496097022:834240f84501b5341d375414718204ec421561f3825d34c22bf9182203e42900:43b970ac6ec5f8a9647b2c7e4eed8b1d7f62e154a95eed748b0294c1256764ba',
'media_url' => "http://example.com/audio",
'media_type' => "audio/ogg",
'note' => "",
],
];
$this->fields = [
Database::LIST_MINIMAL => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
],
Database::LIST_CONSERVATIVE => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
"url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint",
],
Database::LIST_TYPICAL => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
"url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint",
"content", "media_url", "media_type",
],
Database::LIST_FULL => [
"id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date",
"url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint",
"content", "media_url", "media_type",
"note",
],
];
$this->checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified","note"],];
$this->user = "john.doe@example.net";
}
protected function compareIds(array $exp, Context $c) {
$ids = array_column($ids = Arsse::$db->articleList($this->user, $c)->getAll(), "id");
sort($ids);
sort($exp);
$this->assertEquals($exp, $ids);
protected function tearDownSeriesArticle() {
unset($this->data, $this->matches, $this->fields, $this->checkTables, $this->user);
}
public function testListArticlesCheckingContext() {
$this->user = "john.doe@example.com";
$compareIds = function(array $exp, Context $c) {
$ids = array_column($ids = Arsse::$db->articleList("john.doe@example.com", $c)->getAll(), "id");
sort($ids);
sort($exp);
$this->assertEquals($exp, $ids);
};
// get all items for user
$exp = [1,2,3,4,5,6,7,8,19,20];
$this->compareIds($exp, new Context);
$this->compareIds($exp, (new Context)->articles(range(1, Database::LIMIT_ARTICLES * 3)));
$compareIds($exp, new Context);
$compareIds($exp, (new Context)->articles(range(1, Database::LIMIT_ARTICLES * 3)));
// get items from a folder tree
$this->compareIds([5,6,7,8], (new Context)->folder(1));
$compareIds([5,6,7,8], (new Context)->folder(1));
// get items from a leaf folder
$this->compareIds([7,8], (new Context)->folder(6));
$compareIds([7,8], (new Context)->folder(6));
// get items from a non-leaf folder without descending
$this->compareIds([1,2,3,4], (new Context)->folderShallow(0));
$this->compareIds([5,6], (new Context)->folderShallow(1));
$compareIds([1,2,3,4], (new Context)->folderShallow(0));
$compareIds([5,6], (new Context)->folderShallow(1));
// get items from a single subscription
$exp = [19,20];
$this->compareIds($exp, (new Context)->subscription(5));
$compareIds($exp, (new Context)->subscription(5));
// get un/read items from a single subscription
$this->compareIds([20], (new Context)->subscription(5)->unread(true));
$this->compareIds([19], (new Context)->subscription(5)->unread(false));
$compareIds([20], (new Context)->subscription(5)->unread(true));
$compareIds([19], (new Context)->subscription(5)->unread(false));
// get starred articles
$this->compareIds([1,20], (new Context)->starred(true));
$this->compareIds([2,3,4,5,6,7,8,19], (new Context)->starred(false));
$this->compareIds([1], (new Context)->starred(true)->unread(false));
$this->compareIds([], (new Context)->starred(true)->unread(false)->subscription(5));
$compareIds([1,20], (new Context)->starred(true));
$compareIds([2,3,4,5,6,7,8,19], (new Context)->starred(false));
$compareIds([1], (new Context)->starred(true)->unread(false));
$compareIds([], (new Context)->starred(true)->unread(false)->subscription(5));
// get items relative to edition
$this->compareIds([19], (new Context)->subscription(5)->latestEdition(999));
$this->compareIds([19], (new Context)->subscription(5)->latestEdition(19));
$this->compareIds([20], (new Context)->subscription(5)->oldestEdition(999));
$this->compareIds([20], (new Context)->subscription(5)->oldestEdition(1001));
$compareIds([19], (new Context)->subscription(5)->latestEdition(999));
$compareIds([19], (new Context)->subscription(5)->latestEdition(19));
$compareIds([20], (new Context)->subscription(5)->oldestEdition(999));
$compareIds([20], (new Context)->subscription(5)->oldestEdition(1001));
// get items relative to article ID
$this->compareIds([1,2,3], (new Context)->latestArticle(3));
$this->compareIds([19,20], (new Context)->oldestArticle(19));
$compareIds([1,2,3], (new Context)->latestArticle(3));
$compareIds([19,20], (new Context)->oldestArticle(19));
// get items relative to (feed) modification date
$exp = [2,4,6,8,20];
$this->compareIds($exp, (new Context)->modifiedSince("2005-01-01T00:00:00Z"));
$this->compareIds($exp, (new Context)->modifiedSince("2010-01-01T00:00:00Z"));
$compareIds($exp, (new Context)->modifiedSince("2005-01-01T00:00:00Z"));
$compareIds($exp, (new Context)->modifiedSince("2010-01-01T00:00:00Z"));
$exp = [1,3,5,7,19];
$this->compareIds($exp, (new Context)->notModifiedSince("2005-01-01T00:00:00Z"));
$this->compareIds($exp, (new Context)->notModifiedSince("2000-01-01T00:00:00Z"));
$compareIds($exp, (new Context)->notModifiedSince("2005-01-01T00:00:00Z"));
$compareIds($exp, (new Context)->notModifiedSince("2000-01-01T00:00:00Z"));
// get items relative to (user) modification date (both marks and labels apply)
$this->compareIds([8,19], (new Context)->markedSince("2014-01-01T00:00:00Z"));
$this->compareIds([2,4,6,8,19,20], (new Context)->markedSince("2010-01-01T00:00:00Z"));
$this->compareIds([1,2,3,4,5,6,7,20], (new Context)->notMarkedSince("2014-01-01T00:00:00Z"));
$this->compareIds([1,3,5,7], (new Context)->notMarkedSince("2005-01-01T00:00:00Z"));
$compareIds([8,19], (new Context)->markedSince("2014-01-01T00:00:00Z"));
$compareIds([2,4,6,8,19,20], (new Context)->markedSince("2010-01-01T00:00:00Z"));
$compareIds([1,2,3,4,5,6,7,20], (new Context)->notMarkedSince("2014-01-01T00:00:00Z"));
$compareIds([1,3,5,7], (new Context)->notMarkedSince("2005-01-01T00:00:00Z"));
// paged results
$this->compareIds([1], (new Context)->limit(1));
$this->compareIds([2], (new Context)->limit(1)->oldestEdition(1+1));
$this->compareIds([3], (new Context)->limit(1)->oldestEdition(2+1));
$this->compareIds([4,5], (new Context)->limit(2)->oldestEdition(3+1));
$compareIds([1], (new Context)->limit(1));
$compareIds([2], (new Context)->limit(1)->oldestEdition(1+1));
$compareIds([3], (new Context)->limit(1)->oldestEdition(2+1));
$compareIds([4,5], (new Context)->limit(2)->oldestEdition(3+1));
// reversed results
$this->compareIds([20], (new Context)->reverse(true)->limit(1));
$this->compareIds([19], (new Context)->reverse(true)->limit(1)->latestEdition(1001-1));
$this->compareIds([8], (new Context)->reverse(true)->limit(1)->latestEdition(19-1));
$this->compareIds([7,6], (new Context)->reverse(true)->limit(2)->latestEdition(8-1));
$compareIds([20], (new Context)->reverse(true)->limit(1));
$compareIds([19], (new Context)->reverse(true)->limit(1)->latestEdition(1001-1));
$compareIds([8], (new Context)->reverse(true)->limit(1)->latestEdition(19-1));
$compareIds([7,6], (new Context)->reverse(true)->limit(2)->latestEdition(8-1));
// get articles by label ID
$this->compareIds([1,19], (new Context)->label(1));
$this->compareIds([1,5,20], (new Context)->label(2));
$compareIds([1,19], (new Context)->label(1));
$compareIds([1,5,20], (new Context)->label(2));
// get articles by label name
$this->compareIds([1,19], (new Context)->labelName("Interesting"));
$this->compareIds([1,5,20], (new Context)->labelName("Fascinating"));
$compareIds([1,19], (new Context)->labelName("Interesting"));
$compareIds([1,5,20], (new Context)->labelName("Fascinating"));
// get articles with any or no label
$this->compareIds([1,5,8,19,20], (new Context)->labelled(true));
$this->compareIds([2,3,4,6,7], (new Context)->labelled(false));
$compareIds([1,5,8,19,20], (new Context)->labelled(true));
$compareIds([2,3,4,6,7], (new Context)->labelled(false));
// get a specific article or edition
$this->compareIds([20], (new Context)->article(20));
$this->compareIds([20], (new Context)->edition(1001));
$compareIds([20], (new Context)->article(20));
$compareIds([20], (new Context)->edition(1001));
// get multiple specific articles or editions
$this->compareIds([1,20], (new Context)->articles([1,20,50]));
$this->compareIds([1,20], (new Context)->editions([1,1001,50]));
$compareIds([1,20], (new Context)->articles([1,20,50]));
$compareIds([1,20], (new Context)->editions([1,1001,50]));
// get articles base on whether or not they have notes
$this->compareIds([1,3,4,5,6,7,8,19,20], (new Context)->annotated(false));
$this->compareIds([2], (new Context)->annotated(true));
$compareIds([1,3,4,5,6,7,8,19,20], (new Context)->annotated(false));
$compareIds([2], (new Context)->annotated(true));
// get specific starred articles
$this->compareIds([1], (new Context)->articles([1,2,3])->starred(true));
$this->compareIds([2,3], (new Context)->articles([1,2,3])->starred(false));
$compareIds([1], (new Context)->articles([1,2,3])->starred(true));
$compareIds([2,3], (new Context)->articles([1,2,3])->starred(false));
}
public function testListArticlesOfAMissingFolder() {

19
tests/cases/Db/SQLite3/TestDatabase.php

@ -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\SQLite3;
/**
* @covers \JKingWeb\Arsse\Database<extended>
* @covers \JKingWeb\Arsse\Misc\Query<extended>
*/
class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\Base {
protected static $implementation = "SQLite 3";
protected function nextID(string $table): int {
return static::$drv->query("SELECT (case when max(id) then max(id) else 0 end)+1 from $table")->getValue();
}
}

19
tests/cases/Db/SQLite3PDO/TestDatabase.php

@ -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\SQLite3PDO;
/**
* @covers \JKingWeb\Arsse\Database<extended>
* @covers \JKingWeb\Arsse\Misc\Query<extended>
*/
class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\Base {
protected static $implementation = "PDO SQLite 3";
protected function nextID(string $table): int {
return (int) static::$drv->query("SELECT (case when max(id) then max(id) else 0 end)+1 from $table")->getValue();
}
}

82
tests/lib/DatabaseInformation.php

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace JKingWeb\Arsse\Test;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
class DatabaseInformation {
public $name;
@ -17,6 +18,8 @@ class DatabaseInformation {
public $driverClass;
public $stringOutput;
public $interfaceConstructor;
public $truncateFunction;
public $razeFunction;
protected static $data;
@ -50,6 +53,57 @@ class DatabaseInformation {
}
protected static function getData() {
$sqlite3TableList = function($db): array {
$listTables = "SELECT name from sqlite_master where type = 'table' and name like 'arsse_%'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} elseif ($db instanceof \PDO) {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} else {
$tables = [];
$result = $db->query($listTables);
while ($r = $result->fetchArray(\SQLITE3_ASSOC)) {
$tables[] = $r['name'];
}
$result->finalize();
}
return $tables;
};
$sqlite3TruncateFunction = function($db, array $afterStatements = []) use ($sqlite3TableList) {
foreach ($sqlite3TableList($db) as $table) {
if ($table == "arsse_meta") {
$db->exec("DELETE FROM $table where key <> 'schema_version'");
} else {
$db->exec("DELETE FROM $table");
}
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
};
$sqlite3RazeFunction = function($db, array $afterStatements = []) use ($sqlite3TableList) {
$db->exec("PRAGMA foreign_keys=0");
foreach ($sqlite3TableList($db) as $table) {
$db->exec("DROP TABLE IF EXISTS $table");
}
$db->exec("PRAGMA user_version=0");
$db->exec("PRAGMA foreign_keys=1");
foreach ($afterStatements as $st) {
$db->exec($st);
}
};
$pgObjectList = function($db): array {
$listObjects = "SELECT table_name as name, 'TABLE' as type from information_schema.tables where table_schema = current_schema() and table_name like 'arsse_%' union SELECT collation_name as name, 'COLLATION' as type from information_schema.collations where collation_schema = current_schema()";
if ($db instanceof Driver) {
return $db->query($listObjects)->getAll();
} elseif ($db instanceof \PDO) {
return $db->query($listObjects)->fetchAll(\PDO::FETCH_ASSOC);
} else {
throw \Exception("Native PostgreSQL interface not implemented");
}
};
return [
'SQLite 3' => [
'pdo' => false,
@ -67,7 +121,8 @@ class DatabaseInformation {
$d->enableExceptions(true);
return $d;
},
'truncateFunction' => $sqlite3TruncateFunction,
'razeFunction' => $sqlite3RazeFunction,
],
'PDO SQLite 3' => [
'pdo' => true,
@ -85,6 +140,8 @@ class DatabaseInformation {
return;
}
},
'truncateFunction' => $sqlite3TruncateFunction,
'razeFunction' => $sqlite3RazeFunction,
],
'PDO PostgreSQL' => [
'pdo' => true,
@ -105,6 +162,29 @@ class DatabaseInformation {
}
return $d;
},
'truncateFunction' => function($db, array $afterStatements = []) use ($pgObjectList) {
foreach ($objectList($db) as $obj) {
if ($obj['type'] != "TABLE") {
continue;
} elseif ($obj['name'] == "arsse_meta") {
$db->exec("DELETE FROM {$obj['name']} where key <> 'schema_version'");
} else {
$db->exec("TRUNCATE TABLE {$obj['name']} restart identity cascade");
}
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
},
'razeFunction' => function($db, array $afterStatements = []) use ($pgObjectList) {
foreach ($objectList($db) as $obj) {
$db->exec("DROP {$obj['type']} {$obj['name']} IF EXISTS cascade");
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
},
],
];
}

Loading…
Cancel
Save