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
105 public function testConstructDatastoreNotWriteable()
107 $this->expectExceptionMessageRegExp('/Error accessing "null"/');
109 new LegacyLinkDB('null/store.db', false, false);
113 * The DB doesn't exist, ensure it is created with dummy content
115 public function testCheckDBNew()
117 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
118 unlink(self
::$testDatastore);
119 $this->assertFileNotExists(self
::$testDatastore);
121 $checkDB = self
::getMethod('check');
122 $checkDB->invokeArgs($linkDB, array());
123 $this->assertFileExists(self
::$testDatastore);
125 // ensure the correct data has been written
126 $this->assertGreaterThan(0, filesize(self
::$testDatastore));
130 * The DB exists, don't do anything
132 public function testCheckDBLoad()
134 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
135 $datastoreSize = filesize(self
::$testDatastore);
136 $this->assertGreaterThan(0, $datastoreSize);
138 $checkDB = self
::getMethod('check');
139 $checkDB->invokeArgs($linkDB, array());
141 // ensure the datastore is left unmodified
144 filesize(self
::$testDatastore)
151 public function testReadEmptyDB()
153 file_put_contents(self
::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
154 $emptyDB = new LegacyLinkDB(self
::$testDatastore, false, false);
155 $this->assertEquals(0, sizeof($emptyDB));
156 $this->assertEquals(0, count($emptyDB));
160 * Load public bookmarks from the DB
162 public function testReadPublicDB()
165 self
::$refDB->countPublicLinks(),
166 sizeof(self
::$publicLinkDB)
171 * Load public and private bookmarks from the DB
173 public function testReadPrivateDB()
176 self
::$refDB->countLinks(),
177 sizeof(self
::$privateLinkDB)
182 * Save the bookmarks to the DB
184 public function testSave()
186 $testDB = new LegacyLinkDB(self
::$testDatastore, true, false);
187 $dbSize = sizeof($testDB);
191 'title' => 'an additional link',
192 'url' => 'http://dum.my',
193 'description' => 'One more',
195 'created' => DateTime
::createFromFormat(Bookmark
::LINK_DATE_FORMAT
, '20150518_190000'),
196 'tags' => 'unit test'
198 $testDB[$link['id']] = $link;
199 $testDB->save('tests');
201 $testDB = new LegacyLinkDB(self
::$testDatastore, true, false);
202 $this->assertEquals($dbSize +
1, sizeof($testDB));
206 * Count existing bookmarks
208 public function testCount()
211 self
::$refDB->countPublicLinks(),
212 self
::$publicLinkDB->count()
215 self
::$refDB->countLinks(),
216 self
::$privateLinkDB->count()
221 * Count existing bookmarks - public bookmarks hidden
223 public function testCountHiddenPublic()
225 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, true);
238 * List the days for which bookmarks have been posted
240 public function testDays()
243 array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'),
244 self
::$publicLinkDB->days()
248 array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'),
249 self
::$privateLinkDB->days()
254 * The URL corresponds to an existing entry in the DB
256 public function testGetKnownLinkFromURL()
258 $link = self
::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
260 $this->assertNotEquals(false, $link);
261 $this->assertContains(
262 'A free software media publishing platform',
268 * The URL is not in the DB
270 public function testGetUnknownLinkFromURL()
274 self
::$publicLinkDB->getLinkFromUrl('http://dev.null')
281 public function testAllTags()
296 // The DB contains a link with `sTuff` and another one with `stuff` tag.
297 // They need to be grouped with the first case found - order by date DESC: `sTuff`.
301 self
::$publicLinkDB->linksCountPerTag()
329 self
::$privateLinkDB->linksCountPerTag()
346 self
::$privateLinkDB->linksCountPerTag(['web'])
356 self
::$privateLinkDB->linksCountPerTag(['web'], 'private')
361 * Test filter with string.
363 public function testFilterString()
365 $tags = 'dev cartoon';
366 $request = array('searchtags' => $tags);
369 count(self
::$privateLinkDB->filterSearch($request, true, false))
374 * Test filter with string.
376 public function testFilterArray()
378 $tags = array('dev', 'cartoon');
379 $request = array('searchtags' => $tags);
382 count(self
::$privateLinkDB->filterSearch($request, true, false))
387 * Test hidden tags feature:
388 * tags starting with a dot '.' are only visible when logged in.
390 public function testHiddenTags()
393 $request = array('searchtags' => $tags);
396 count(self
::$privateLinkDB->filterSearch($request, true, false))
401 count(self
::$publicLinkDB->filterSearch($request, true, false))
406 * Test filterHash() with a valid smallhash.
408 public function testFilterHashValid()
410 $request = smallHash('20150310_114651');
413 count(self
::$publicLinkDB->filterHash($request))
415 $request = smallHash('20150310_114633' . 8);
418 count(self
::$publicLinkDB->filterHash($request))
423 * Test filterHash() with an invalid smallhash.
425 public function testFilterHashInValid1()
427 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException
::class);
430 self
::$publicLinkDB->filterHash($request);
434 * Test filterHash() with an empty smallhash.
436 public function testFilterHashInValid()
438 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException
::class);
440 self
::$publicLinkDB->filterHash('');
444 * Test reorder with asc/desc parameter.
446 public function testReorderLinksDesc()
448 self
::$privateLinkDB->reorder('ASC');
449 $stickyIds = [11, 10];
450 $standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41];
451 $linkIds = array_merge($stickyIds, $standardIds);
453 foreach (self
::$privateLinkDB as $key => $value) {
454 $this->assertEquals($linkIds[$cpt++
], $key);
456 self
::$privateLinkDB->reorder('DESC');
457 $linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds));
459 foreach (self
::$privateLinkDB as $key => $value) {
460 $this->assertEquals($linkIds[$cpt++
], $key);
465 * Test rename tag with a valid value present in multiple bookmarks
467 public function testRenameTagMultiple()
469 self
::$refDB->write(self
::$testDatastore);
470 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
472 $res = $linkDB->renameTag('cartoon', 'Taz');
473 $this->assertEquals(3, count($res));
474 $this->assertContains(' Taz ', $linkDB[4]['tags']);
475 $this->assertContains(' Taz ', $linkDB[1]['tags']);
476 $this->assertContains(' Taz ', $linkDB[0]['tags']);
480 * Test rename tag with a valid value
482 public function testRenameTagCaseSensitive()
484 self
::$refDB->write(self
::$testDatastore);
485 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
487 $res = $linkDB->renameTag('sTuff', 'Taz');
488 $this->assertEquals(1, count($res));
489 $this->assertEquals('Taz', $linkDB[41]['tags']);
493 * Test rename tag with invalid values
495 public function testRenameTagInvalid()
497 $linkDB = new LegacyLinkDB(self
::$testDatastore, false, false);
499 $this->assertFalse($linkDB->renameTag('', 'test'));
500 $this->assertFalse($linkDB->renameTag('', ''));
502 $this->assertEquals([], $linkDB->renameTag('test', ''));
503 $this->assertEquals([], $linkDB->renameTag('test', 'retest'));
507 * Test delete tag with a valid value
509 public function testDeleteTag()
511 self
::$refDB->write(self
::$testDatastore);
512 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
514 $res = $linkDB->renameTag('cartoon', null);
515 $this->assertEquals(3, count($res));
516 $this->assertNotContains('cartoon', $linkDB[4]['tags']);
520 * Test linksCountPerTag all tags without filter.
521 * Equal occurrences should be sorted alphabetically.
523 public function testCountLinkPerTagAllNoFilter()
549 $tags = self
::$privateLinkDB->linksCountPerTag();
551 $this->assertEquals($expected, $tags, var_export($tags, true));
555 * Test linksCountPerTag all tags with filter.
556 * Equal occurrences should be sorted alphabetically.
558 public function testCountLinkPerTagAllWithFilter()
572 $tags = self
::$privateLinkDB->linksCountPerTag(['gnu']);
574 $this->assertEquals($expected, $tags, var_export($tags, true));
578 * Test linksCountPerTag public tags with filter.
579 * Equal occurrences should be sorted alphabetically.
581 public function testCountLinkPerTagPublicWithFilter()
595 $tags = self
::$privateLinkDB->linksCountPerTag(['gnu'], 'public');
597 $this->assertEquals($expected, $tags, var_export($tags, true));
601 * Test linksCountPerTag public tags with filter.
602 * Equal occurrences should be sorted alphabetically.
604 public function testCountLinkPerTagPrivateWithFilter()
614 $tags = self
::$privateLinkDB->linksCountPerTag(['dev'], 'private');
616 $this->assertEquals($expected, $tags, var_export($tags, true));
620 * Make sure that bookmarks with the same timestamp have a consistent order:
621 * if their creation date is equal, bookmarks are sorted by ID DESC.
623 public function testConsistentOrder()
626 $creation = DateTime
::createFromFormat('Ymd_His', '20190807_130444');
627 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
628 for ($i = 0; $i < 4; ++
$i) {
629 $linkDB[$nextId +
$i] = [
630 'id' => $nextId +
$i,
631 'url' => 'http://'. $i,
632 'created' => $creation,
634 'description' => true,
639 // Check 4 new links 4 times
640 for ($i = 0; $i < 4; ++
$i) {
641 $linkDB->save('tests');
642 $linkDB = new LegacyLinkDB(self
::$testDatastore, true, false);
644 foreach ($linkDB as $link) {
645 if ($link['sticky'] === true) {
648 $this->assertEquals($nextId +
$count, $link['id']);
649 $this->assertEquals('http://'. $count, $link['url']);