6 namespace Shaarli\Legacy
;
12 use Shaarli\Bookmark\Bookmark
;
14 require_once 'application/Utils.php';
15 require_once 'tests/utils/ReferenceLinkDB.php';
19 * Unitary tests for LegacyLinkDBTest
21 class LegacyLinkDBTest
extends \PHPUnit\Framework\TestCase
23 // datastore to test write operations
24 protected static $testDatastore = 'sandbox/datastore.php';
27 * @var ReferenceLinkDB instance.
29 protected static $refDB = null;
32 * @var LegacyLinkDB public LinkDB instance.
34 protected static $publicLinkDB = null;
37 * @var LegacyLinkDB private LinkDB instance.
39 protected static $privateLinkDB = null;
42 * Instantiates public and private LinkDBs with test data
44 * The reference datastore contains public and private bookmarks that
45 * will be used to test LinkDB's methods:
46 * - access filtering (public/private),
53 * Resets test data for each test
55 protected function setUp(): void
57 if (file_exists(self
::$testDatastore)) {
58 unlink(self
::$testDatastore);
61 self
::$refDB = new ReferenceLinkDB(true);
62 self
::$refDB->write(self
::$testDatastore);
63 self
::$publicLinkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
64 self
::$privateLinkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
68 * Allows to test LinkDB's private methods
71 * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
72 * http://stackoverflow.com/a/2798203
74 protected static function getMethod($name)
76 $class = new ReflectionClass('Shaarli\Legacy\LegacyLinkDB');
77 $method = $class->getMethod($name);
78 $method->setAccessible(true);
83 * Instantiate LinkDB objects - logged in user
85 public function testConstructLoggedIn()
87 new LegacyLinkDB(self
::$testDatastore, true, false);
88 $this->assertFileExists(self
::$testDatastore);
92 * Instantiate LinkDB objects - logged out or public instance
94 public function testConstructLoggedOut()
96 new LegacyLinkDB(self
::$testDatastore, false, false);
97 $this->assertFileExists(self
::$testDatastore);
101 * Attempt to instantiate a LinkDB whereas the datastore is not writable
103 * @expectedException Shaarli\Exceptions\IOException
104 * @expectedExceptionMessageRegExp /Error accessing "null"/
106 public function testConstructDatastoreNotWriteable()
108 new LegacyLinkDB('null/store.db', false, false);
112 * The DB doesn't exist, ensure it is created with dummy content
114 public function testCheckDBNew()
116 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
117 unlink(self
::$testDatastore);
118 $this->assertFileNotExists(self
::$testDatastore);
120 $checkDB = self
::getMethod('check');
121 $checkDB->invokeArgs($linkDB, array());
122 $this->assertFileExists(self
::$testDatastore);
124 // ensure the correct data has been written
125 $this->assertGreaterThan(0, filesize(self
::$testDatastore));
129 * The DB exists, don't do anything
131 public function testCheckDBLoad()
133 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
134 $datastoreSize = filesize(self
::$testDatastore);
135 $this->assertGreaterThan(0, $datastoreSize);
137 $checkDB = self
::getMethod('check');
138 $checkDB->invokeArgs($linkDB, array());
140 // ensure the datastore is left unmodified
143 filesize(self
::$testDatastore)
150 public function testReadEmptyDB()
152 file_put_contents(self
::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
153 $emptyDB = new LegacyLinkDB(self
::$testDatastore, false, false);
154 $this->assertEquals(0, sizeof($emptyDB));
155 $this->assertEquals(0, count($emptyDB));
159 * Load public bookmarks from the DB
161 public function testReadPublicDB()
164 self
::$refDB->countPublicLinks(),
165 sizeof(self
::$publicLinkDB)
170 * Load public and private bookmarks from the DB
172 public function testReadPrivateDB()
175 self
::$refDB->countLinks(),
176 sizeof(self
::$privateLinkDB)
181 * Save the bookmarks to the DB
183 public function testSave()
185 $testDB = new LegacyLinkDB(self
::$testDatastore, true, false);
186 $dbSize = sizeof($testDB);
190 'title' => 'an additional link',
191 'url' => 'http://dum.my',
192 'description' => 'One more',
194 'created' => DateTime
::createFromFormat(Bookmark
::LINK_DATE_FORMAT
, '20150518_190000'),
195 'tags' => 'unit test'
197 $testDB[$link['id']] = $link;
198 $testDB->save('tests');
200 $testDB = new LegacyLinkDB(self
::$testDatastore, true, false);
201 $this->assertEquals($dbSize +
1, sizeof($testDB));
205 * Count existing bookmarks
207 public function testCount()
210 self
::$refDB->countPublicLinks(),
211 self
::$publicLinkDB->count()
214 self
::$refDB->countLinks(),
215 self
::$privateLinkDB->count()
220 * Count existing bookmarks - public bookmarks hidden
222 public function testCountHiddenPublic()
224 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, true);
237 * List the days for which bookmarks have been posted
239 public function testDays()
242 array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'),
243 self
::$publicLinkDB->days()
247 array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'),
248 self
::$privateLinkDB->days()
253 * The URL corresponds to an existing entry in the DB
255 public function testGetKnownLinkFromURL()
257 $link = self
::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
259 $this->assertNotEquals(false, $link);
260 $this->assertContains(
261 'A free software media publishing platform',
267 * The URL is not in the DB
269 public function testGetUnknownLinkFromURL()
273 self
::$publicLinkDB->getLinkFromUrl('http://dev.null')
280 public function testAllTags()
295 // The DB contains a link with `sTuff` and another one with `stuff` tag.
296 // They need to be grouped with the first case found - order by date DESC: `sTuff`.
300 self
::$publicLinkDB->linksCountPerTag()
328 self
::$privateLinkDB->linksCountPerTag()
345 self
::$privateLinkDB->linksCountPerTag(['web'])
355 self
::$privateLinkDB->linksCountPerTag(['web'], 'private')
360 * Test filter with string.
362 public function testFilterString()
364 $tags = 'dev cartoon';
365 $request = array('searchtags' => $tags);
368 count(self
::$privateLinkDB->filterSearch($request, true, false))
373 * Test filter with string.
375 public function testFilterArray()
377 $tags = array('dev', 'cartoon');
378 $request = array('searchtags' => $tags);
381 count(self
::$privateLinkDB->filterSearch($request, true, false))
386 * Test hidden tags feature:
387 * tags starting with a dot '.' are only visible when logged in.
389 public function testHiddenTags()
392 $request = array('searchtags' => $tags);
395 count(self
::$privateLinkDB->filterSearch($request, true, false))
400 count(self
::$publicLinkDB->filterSearch($request, true, false))
405 * Test filterHash() with a valid smallhash.
407 public function testFilterHashValid()
409 $request = smallHash('20150310_114651');
412 count(self
::$publicLinkDB->filterHash($request))
414 $request = smallHash('20150310_114633' . 8);
417 count(self
::$publicLinkDB->filterHash($request))
422 * Test filterHash() with an invalid smallhash.
424 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
426 public function testFilterHashInValid1()
429 self
::$publicLinkDB->filterHash($request);
433 * Test filterHash() with an empty smallhash.
435 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
437 public function testFilterHashInValid()
439 self
::$publicLinkDB->filterHash('');
443 * Test reorder with asc/desc parameter.
445 public function testReorderLinksDesc()
447 self
::$privateLinkDB->reorder('ASC');
448 $stickyIds = [11, 10];
449 $standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41];
450 $linkIds = array_merge($stickyIds, $standardIds);
452 foreach (self
::$privateLinkDB as $key => $value) {
453 $this->assertEquals($linkIds[$cpt++
], $key);
455 self
::$privateLinkDB->reorder('DESC');
456 $linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds));
458 foreach (self
::$privateLinkDB as $key => $value) {
459 $this->assertEquals($linkIds[$cpt++
], $key);
464 * Test rename tag with a valid value present in multiple bookmarks
466 public function testRenameTagMultiple()
468 self
::$refDB->write(self
::$testDatastore);
469 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
471 $res = $linkDB->renameTag('cartoon', 'Taz');
472 $this->assertEquals(3, count($res));
473 $this->assertContains(' Taz ', $linkDB[4]['tags']);
474 $this->assertContains(' Taz ', $linkDB[1]['tags']);
475 $this->assertContains(' Taz ', $linkDB[0]['tags']);
479 * Test rename tag with a valid value
481 public function testRenameTagCaseSensitive()
483 self
::$refDB->write(self
::$testDatastore);
484 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
486 $res = $linkDB->renameTag('sTuff', 'Taz');
487 $this->assertEquals(1, count($res));
488 $this->assertEquals('Taz', $linkDB[41]['tags']);
492 * Test rename tag with invalid values
494 public function testRenameTagInvalid()
496 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
498 $this->assertFalse($linkDB->renameTag('', 'test'));
499 $this->assertFalse($linkDB->renameTag('', ''));
501 $this->assertEquals([], $linkDB->renameTag('test', ''));
502 $this->assertEquals([], $linkDB->renameTag('test', 'retest'));
506 * Test delete tag with a valid value
508 public function testDeleteTag()
510 self
::$refDB->write(self
::$testDatastore);
511 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
513 $res = $linkDB->renameTag('cartoon', null);
514 $this->assertEquals(3, count($res));
515 $this->assertNotContains('cartoon', $linkDB[4]['tags']);
519 * Test linksCountPerTag all tags without filter.
520 * Equal occurrences should be sorted alphabetically.
522 public function testCountLinkPerTagAllNoFilter()
548 $tags = self
::$privateLinkDB->linksCountPerTag();
550 $this->assertEquals($expected, $tags, var_export($tags, true));
554 * Test linksCountPerTag all tags with filter.
555 * Equal occurrences should be sorted alphabetically.
557 public function testCountLinkPerTagAllWithFilter()
571 $tags = self
::$privateLinkDB->linksCountPerTag(['gnu']);
573 $this->assertEquals($expected, $tags, var_export($tags, true));
577 * Test linksCountPerTag public tags with filter.
578 * Equal occurrences should be sorted alphabetically.
580 public function testCountLinkPerTagPublicWithFilter()
594 $tags = self
::$privateLinkDB->linksCountPerTag(['gnu'], 'public');
596 $this->assertEquals($expected, $tags, var_export($tags, true));
600 * Test linksCountPerTag public tags with filter.
601 * Equal occurrences should be sorted alphabetically.
603 public function testCountLinkPerTagPrivateWithFilter()
613 $tags = self
::$privateLinkDB->linksCountPerTag(['dev'], 'private');
615 $this->assertEquals($expected, $tags, var_export($tags, true));
619 * Make sure that bookmarks with the same timestamp have a consistent order:
620 * if their creation date is equal, bookmarks are sorted by ID DESC.
622 public function testConsistentOrder()
625 $creation = DateTime
::createFromFormat('Ymd_His', '20190807_130444');
626 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
627 for ($i = 0; $i < 4; ++
$i) {
628 $linkDB[$nextId +
$i] = [
629 'id' => $nextId +
$i,
630 'url' => 'http://'. $i,
631 'created' => $creation,
633 'description' => true,
638 // Check 4 new links 4 times
639 for ($i = 0; $i < 4; ++
$i) {
640 $linkDB->save('tests');
641 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
643 foreach ($linkDB as $link) {
644 if ($link['sticky'] === true) {
647 $this->assertEquals($nextId +
$count, $link['id']);
648 $this->assertEquals('http://'. $count, $link['url']);