import([ 'userSessionTimeout' => "PT1H", 'userSessionLifetime' => "PT24H", ]); // set up the test data $tz = new \DateTimeZone("UTC"); $nowish = (new Date("now - 1 minute", $tz))->format("Y-m-d H:i:s"); $yesterday = (new Date("now - 1 day", $tz))->format("Y-m-d H:i:s"); $daybefore = (new Date("now - 2 days", $tz))->format("Y-m-d H:i:s"); $daysago = (new Date("now - 7 days", $tz))->format("Y-m-d H:i:s"); $weeksago = (new Date("now - 21 days", $tz))->format("Y-m-d H:i:s"); $soon = (new Date("now + 1 minute", $tz))->format("Y-m-d H:i:s"); $faroff = (new Date("now + 1 hour", $tz))->format("Y-m-d H:i:s"); $this->data = [ 'arsse_users' => [ 'columns' => [ 'id' => 'str', 'password' => 'str', 'num' => 'int', ], 'rows' => [ ["jane.doe@example.com", "",1], ["john.doe@example.com", "",2], ], ], 'arsse_sessions' => [ 'columns' => [ 'id' => "str", 'created' => "datetime", 'expires' => "datetime", 'user' => "str", ], 'rows' => [ ["a", $nowish, $faroff, "jane.doe@example.com"], // not expired and recently created, thus kept ["b", $nowish, $soon, "jane.doe@example.com"], // not expired and recently created, thus kept ["c", $daysago, $soon, "jane.doe@example.com"], // created more than a day ago, thus deleted ["d", $nowish, $nowish, "jane.doe@example.com"], // recently created but expired, thus deleted ["e", $daysago, $nowish, "jane.doe@example.com"], // created more than a day ago and expired, thus deleted ], ], 'arsse_tokens' => [ 'columns' => [ 'id' => "str", 'class' => "str", 'user' => "str", 'expires' => "datetime", ], 'rows' => [ ["80fa94c1a11f11e78667001e673b2560", "fever.login", "jane.doe@example.com", $faroff], ["27c6de8da13311e78667001e673b2560", "fever.login", "jane.doe@example.com", $weeksago], // expired ["ab3b3eb8a13311e78667001e673b2560", "class.class", "jane.doe@example.com", null], ["da772f8fa13c11e78667001e673b2560", "class.class", "john.doe@example.com", $soon], ], ], 'arsse_icons' => [ 'columns' => [ 'id' => "int", 'url' => "str", 'orphaned' => "datetime", ], 'rows' => [ [1,'http://localhost:8000/Icon/PNG',$daybefore], [2,'http://localhost:8000/Icon/GIF',$daybefore], [3,'http://localhost:8000/Icon/SVG1',null], ], ], 'arsse_feeds' => [ 'columns' => [ 'id' => "int", 'url' => "str", 'title' => "str", 'orphaned' => "datetime", 'size' => "int", 'icon' => "int", ], 'rows' => [ [1,"http://example.com/1","",$daybefore,2,null], //latest two articles should be kept [2,"http://example.com/2","",$yesterday,0,2], [3,"http://example.com/3","",null,0,1], [4,"http://example.com/4","",$nowish,0,null], ], ], 'arsse_subscriptions' => [ 'columns' => [ 'id' => "int", 'owner' => "str", 'feed' => "int", ], 'rows' => [ // one feed previously marked for deletion has a subscription again, and so should not be deleted [1,'jane.doe@example.com',1], // other subscriptions exist for article cleanup tests [2,'john.doe@example.com',1], ], ], 'arsse_articles' => [ 'columns' => [ 'id' => "int", 'feed' => "int", 'url_title_hash' => "str", 'url_content_hash' => "str", 'title_content_hash' => "str", 'modified' => "datetime", ], 'rows' => [ [1,1,"","","",$weeksago], // is the latest article, thus is kept [2,1,"","","",$weeksago], // is the second latest article, thus is kept [3,1,"","","",$weeksago], // is starred by one user, thus is kept [4,1,"","","",$weeksago], // does not meet the unread threshold due to a recent mark, thus is kept [5,1,"","","",$daysago], // does not meet the unread threshold due to age, thus is kept [6,1,"","","",$weeksago], // does not meet the read threshold due to a recent mark, thus is kept [7,1,"","","",$weeksago], // meets the unread threshold without marks, thus is deleted [8,1,"","","",$weeksago], // meets the unread threshold even with marks, thus is deleted [9,1,"","","",$weeksago], // meets the read threshold, thus is deleted ], ], 'arsse_editions' => [ 'columns' => [ 'id' => "int", 'article' => "int", ], 'rows' => [ [1,1], [2,2], [3,3], [4,4], [201,1], [102,2], ], ], 'arsse_marks' => [ 'columns' => [ 'article' => "int", 'subscription' => "int", 'read' => "bool", 'starred' => "bool", 'modified' => "datetime", ], 'rows' => [ [3,1,0,1,$weeksago], [4,1,1,0,$daysago], [6,1,1,0,$nowish], [6,2,1,0,$weeksago], [8,1,1,0,$weeksago], [9,1,1,0,$daysago], [9,2,1,0,$daysago], ], ], ]; } protected function tearDownSeriesCleanup(): void { unset($this->data); } public function testCleanUpOrphanedFeeds(): void { Arsse::$db->feedCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ 'arsse_feeds' => ["id","orphaned"], ]); $state['arsse_feeds']['rows'][0][1] = null; unset($state['arsse_feeds']['rows'][1]); $state['arsse_feeds']['rows'][2][1] = $now; $this->compareExpectations(static::$drv, $state); } public function testCleanUpOrphanedFeedsWithUnlimitedRetention(): void { Arsse::$conf->import([ 'purgeFeeds' => null, ]); Arsse::$db->feedCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ 'arsse_feeds' => ["id","orphaned"], ]); $state['arsse_feeds']['rows'][0][1] = null; $state['arsse_feeds']['rows'][2][1] = $now; $this->compareExpectations(static::$drv, $state); } public function testCleanUpOrphanedIcons(): void { Arsse::$db->iconCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ 'arsse_icons' => ["id","orphaned"], ]); $state['arsse_icons']['rows'][0][1] = null; unset($state['arsse_icons']['rows'][1]); $state['arsse_icons']['rows'][2][1] = $now; $this->compareExpectations(static::$drv, $state); } public function testCleanUpOrphanedIconsWithUnlimitedRetention(): void { Arsse::$conf->import([ 'purgeFeeds' => null, ]); Arsse::$db->iconCleanup(); $now = gmdate("Y-m-d H:i:s"); $state = $this->primeExpectations($this->data, [ 'arsse_icons' => ["id","orphaned"], ]); $state['arsse_icons']['rows'][0][1] = null; $state['arsse_icons']['rows'][2][1] = $now; $this->compareExpectations(static::$drv, $state); } public function testCleanUpOldArticlesWithStandardRetention(): void { Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"], ]); foreach ([7,8,9] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); } $this->compareExpectations(static::$drv, $state); } public function testCleanUpOldArticlesWithUnlimitedReadRetention(): void { Arsse::$conf->import([ 'purgeArticlesRead' => null, ]); Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"], ]); foreach ([7,8] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); } $this->compareExpectations(static::$drv, $state); } public function testCleanUpOldArticlesWithUnlimitedUnreadRetention(): void { Arsse::$conf->import([ 'purgeArticlesUnread' => null, ]); Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"], ]); foreach ([9] as $id) { unset($state['arsse_articles']['rows'][$id - 1]); } $this->compareExpectations(static::$drv, $state); } public function testCleanUpOldArticlesWithUnlimitedRetention(): void { Arsse::$conf->import([ 'purgeArticlesRead' => null, 'purgeArticlesUnread' => null, ]); Arsse::$db->articleCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_articles' => ["id"], ]); $this->compareExpectations(static::$drv, $state); } public function testCleanUpExpiredSessions(): void { Arsse::$db->sessionCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_sessions' => ["id"], ]); foreach ([3,4,5] as $id) { unset($state['arsse_sessions']['rows'][$id - 1]); } $this->compareExpectations(static::$drv, $state); } public function testCleanUpExpiredTokens(): void { Arsse::$db->tokenCleanup(); $state = $this->primeExpectations($this->data, [ 'arsse_tokens' => ["id", "class"], ]); foreach ([2] as $id) { unset($state['arsse_tokens']['rows'][$id - 1]); } $this->compareExpectations(static::$drv, $state); } }