]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tests/bookmark/BookmarkFileServiceTest.php
Add mutex on datastore I/O operations
[github/shaarli/Shaarli.git] / tests / bookmark / BookmarkFileServiceTest.php
CommitLineData
e26e2060
A
1<?php
2/**
3 * Link datastore tests
4 */
5
6namespace Shaarli\Bookmark;
7
8use DateTime;
fd1ddad9 9use malkusch\lock\mutex\NoMutex;
e26e2060
A
10use ReferenceLinkDB;
11use ReflectionClass;
12use Shaarli;
13use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
14use Shaarli\Config\ConfigManager;
a39acb25 15use Shaarli\Formatter\BookmarkMarkdownFormatter;
e26e2060 16use Shaarli\History;
a5a9cf23 17use Shaarli\TestCase;
e26e2060
A
18
19/**
20 * Unitary tests for LegacyLinkDBTest
21 */
22class BookmarkFileServiceTest extends TestCase
23{
24 // datastore to test write operations
25 protected static $testDatastore = 'sandbox/datastore.php';
26
27 protected static $testConf = 'sandbox/config';
28
29 protected static $testUpdates = 'sandbox/updates.txt';
30
31 /**
32 * @var ConfigManager instance.
33 */
34 protected $conf;
35
36 /**
37 * @var History instance.
38 */
39 protected $history;
40
41 /**
42 * @var ReferenceLinkDB instance.
43 */
44 protected $refDB = null;
45
46 /**
47 * @var BookmarkFileService public LinkDB instance.
48 */
49 protected $publicLinkDB = null;
50
51 /**
52 * @var BookmarkFileService private LinkDB instance.
53 */
54 protected $privateLinkDB = null;
55
fd1ddad9
A
56 /** @var NoMutex */
57 protected $mutex;
58
e26e2060
A
59 /**
60 * Instantiates public and private LinkDBs with test data
61 *
62 * The reference datastore contains public and private bookmarks that
63 * will be used to test LinkDB's methods:
64 * - access filtering (public/private),
65 * - link searches:
66 * - by day,
67 * - by tag,
68 * - by text,
69 * - etc.
70 *
71 * Resets test data for each test
72 */
8f60e120 73 protected function setUp(): void
e26e2060 74 {
fd1ddad9
A
75 $this->mutex = new NoMutex();
76
e26e2060
A
77 if (file_exists(self::$testDatastore)) {
78 unlink(self::$testDatastore);
79 }
80
81 if (file_exists(self::$testConf .'.json.php')) {
82 unlink(self::$testConf .'.json.php');
83 }
84
85 if (file_exists(self::$testUpdates)) {
86 unlink(self::$testUpdates);
87 }
88
89 copy('tests/utils/config/configJson.json.php', self::$testConf .'.json.php');
90 $this->conf = new ConfigManager(self::$testConf);
91 $this->conf->set('resource.datastore', self::$testDatastore);
92 $this->conf->set('resource.updates', self::$testUpdates);
93 $this->refDB = new \ReferenceLinkDB();
94 $this->refDB->write(self::$testDatastore);
95 $this->history = new History('sandbox/history.php');
fd1ddad9
A
96 $this->publicLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false);
97 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
98 }
99
100 /**
101 * Test migrate() method with a legacy datastore.
102 */
103 public function testDatabaseMigration()
104 {
105 if (!defined('SHAARLI_VERSION')) {
106 define('SHAARLI_VERSION', 'dev');
107 }
108
109 $this->refDB = new \ReferenceLinkDB(true);
110 $this->refDB->write(self::$testDatastore);
111 $db = self::getMethod('migrate');
112 $db->invokeArgs($this->privateLinkDB, []);
113
fd1ddad9 114 $db = new \FakeBookmarkService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
115 $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks());
116 $this->assertEquals($this->refDB->countLinks(), $db->count());
117 }
118
119 /**
120 * Test get() method for a defined and saved bookmark
121 */
122 public function testGetDefinedSaved()
123 {
124 $bookmark = $this->privateLinkDB->get(42);
125 $this->assertEquals(42, $bookmark->getId());
126 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
127 }
128
129 /**
130 * Test get() method for a defined and not saved bookmark
131 */
132 public function testGetDefinedNotSaved()
133 {
134 $bookmark = new Bookmark();
135 $this->privateLinkDB->add($bookmark);
136 $createdBookmark = $this->privateLinkDB->get(43);
137 $this->assertEquals(43, $createdBookmark->getId());
138 $this->assertEmpty($createdBookmark->getDescription());
139 }
140
141 /**
142 * Test get() method for an undefined bookmark
e26e2060
A
143 */
144 public function testGetUndefined()
145 {
b1baca99
A
146 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
147
e26e2060
A
148 $this->privateLinkDB->get(666);
149 }
150
151 /**
152 * Test add() method for a bookmark fully built
153 */
154 public function testAddFull()
155 {
156 $bookmark = new Bookmark();
157 $bookmark->setUrl($url = 'https://domain.tld/index.php');
158 $bookmark->setShortUrl('abc');
159 $bookmark->setTitle($title = 'This a brand new bookmark');
160 $bookmark->setDescription($desc = 'It should be created and written');
161 $bookmark->setTags($tags = ['tag1', 'tagssss']);
162 $bookmark->setThumbnail($thumb = 'http://thumb.tld/dle.png');
163 $bookmark->setPrivate(true);
164 $bookmark->setSticky(true);
165 $bookmark->setCreated($created = DateTime::createFromFormat('Ymd_His', '20190518_140354'));
166 $bookmark->setUpdated($updated = DateTime::createFromFormat('Ymd_His', '20190518_150354'));
167
168 $this->privateLinkDB->add($bookmark);
169 $bookmark = $this->privateLinkDB->get(43);
170 $this->assertEquals(43, $bookmark->getId());
171 $this->assertEquals($url, $bookmark->getUrl());
172 $this->assertEquals('abc', $bookmark->getShortUrl());
173 $this->assertEquals($title, $bookmark->getTitle());
174 $this->assertEquals($desc, $bookmark->getDescription());
175 $this->assertEquals($tags, $bookmark->getTags());
176 $this->assertEquals($thumb, $bookmark->getThumbnail());
177 $this->assertTrue($bookmark->isPrivate());
178 $this->assertTrue($bookmark->isSticky());
179 $this->assertEquals($created, $bookmark->getCreated());
180 $this->assertEquals($updated, $bookmark->getUpdated());
181
182 // reload from file
fd1ddad9 183 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
184
185 $bookmark = $this->privateLinkDB->get(43);
186 $this->assertEquals(43, $bookmark->getId());
187 $this->assertEquals($url, $bookmark->getUrl());
188 $this->assertEquals('abc', $bookmark->getShortUrl());
189 $this->assertEquals($title, $bookmark->getTitle());
190 $this->assertEquals($desc, $bookmark->getDescription());
191 $this->assertEquals($tags, $bookmark->getTags());
192 $this->assertEquals($thumb, $bookmark->getThumbnail());
193 $this->assertTrue($bookmark->isPrivate());
194 $this->assertTrue($bookmark->isSticky());
195 $this->assertEquals($created, $bookmark->getCreated());
196 $this->assertEquals($updated, $bookmark->getUpdated());
197 }
198
199 /**
200 * Test add() method for a bookmark without any field set
201 */
202 public function testAddMinimal()
203 {
204 $bookmark = new Bookmark();
205 $this->privateLinkDB->add($bookmark);
206
207 $bookmark = $this->privateLinkDB->get(43);
208 $this->assertEquals(43, $bookmark->getId());
301c7ab1 209 $this->assertRegExp('#/shaare/[\w\-]{6}#', $bookmark->getUrl());
e26e2060
A
210 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl());
211 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle());
212 $this->assertEmpty($bookmark->getDescription());
213 $this->assertEmpty($bookmark->getTags());
214 $this->assertEmpty($bookmark->getThumbnail());
215 $this->assertFalse($bookmark->isPrivate());
216 $this->assertFalse($bookmark->isSticky());
217 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getCreated());
218 $this->assertNull($bookmark->getUpdated());
219
220 // reload from file
fd1ddad9 221 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
222
223 $bookmark = $this->privateLinkDB->get(43);
224 $this->assertEquals(43, $bookmark->getId());
301c7ab1 225 $this->assertRegExp('#/shaare/[\w\-]{6}#', $bookmark->getUrl());
e26e2060
A
226 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl());
227 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle());
228 $this->assertEmpty($bookmark->getDescription());
229 $this->assertEmpty($bookmark->getTags());
230 $this->assertEmpty($bookmark->getThumbnail());
231 $this->assertFalse($bookmark->isPrivate());
232 $this->assertFalse($bookmark->isSticky());
233 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getCreated());
234 $this->assertNull($bookmark->getUpdated());
235 }
236
237 /**
238 * Test add() method for a bookmark without any field set and without writing the data store
e26e2060
A
239 */
240 public function testAddMinimalNoWrite()
241 {
b1baca99
A
242 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
243
e26e2060 244 $bookmark = new Bookmark();
b1baca99 245 $this->privateLinkDB->add($bookmark, false);
e26e2060
A
246
247 $bookmark = $this->privateLinkDB->get(43);
248 $this->assertEquals(43, $bookmark->getId());
249
250 // reload from file
fd1ddad9 251 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
252
253 $this->privateLinkDB->get(43);
254 }
255
256 /**
257 * Test add() method while logged out
e26e2060
A
258 */
259 public function testAddLoggedOut()
260 {
b1baca99
A
261 $this->expectException(\Exception::class);
262 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
263
e26e2060
A
264 $this->publicLinkDB->add(new Bookmark());
265 }
266
267 /**
268 * Test add() method with an entry which is not a bookmark instance
e26e2060
A
269 */
270 public function testAddNotABookmark()
271 {
b1baca99
A
272 $this->expectException(\Exception::class);
273 $this->expectExceptionMessage('Provided data is invalid');
274
e26e2060
A
275 $this->privateLinkDB->add(['title' => 'hi!']);
276 }
277
278 /**
279 * Test add() method with a Bookmark already containing an ID
e26e2060
A
280 */
281 public function testAddWithId()
282 {
b1baca99
A
283 $this->expectException(\Exception::class);
284 $this->expectExceptionMessage('This bookmarks already exists');
285
e26e2060
A
286 $bookmark = new Bookmark();
287 $bookmark->setId(43);
288 $this->privateLinkDB->add($bookmark);
289 }
290
291 /**
292 * Test set() method for a bookmark fully built
293 */
294 public function testSetFull()
295 {
296 $bookmark = $this->privateLinkDB->get(42);
297 $bookmark->setUrl($url = 'https://domain.tld/index.php');
298 $bookmark->setShortUrl('abc');
299 $bookmark->setTitle($title = 'This a brand new bookmark');
300 $bookmark->setDescription($desc = 'It should be created and written');
301 $bookmark->setTags($tags = ['tag1', 'tagssss']);
302 $bookmark->setThumbnail($thumb = 'http://thumb.tld/dle.png');
303 $bookmark->setPrivate(true);
304 $bookmark->setSticky(true);
305 $bookmark->setCreated($created = DateTime::createFromFormat('Ymd_His', '20190518_140354'));
306 $bookmark->setUpdated($updated = DateTime::createFromFormat('Ymd_His', '20190518_150354'));
307
308 $this->privateLinkDB->set($bookmark);
309 $bookmark = $this->privateLinkDB->get(42);
310 $this->assertEquals(42, $bookmark->getId());
311 $this->assertEquals($url, $bookmark->getUrl());
312 $this->assertEquals('abc', $bookmark->getShortUrl());
313 $this->assertEquals($title, $bookmark->getTitle());
314 $this->assertEquals($desc, $bookmark->getDescription());
315 $this->assertEquals($tags, $bookmark->getTags());
316 $this->assertEquals($thumb, $bookmark->getThumbnail());
317 $this->assertTrue($bookmark->isPrivate());
318 $this->assertTrue($bookmark->isSticky());
319 $this->assertEquals($created, $bookmark->getCreated());
320 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated());
321
322 // reload from file
fd1ddad9 323 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
324
325 $bookmark = $this->privateLinkDB->get(42);
326 $this->assertEquals(42, $bookmark->getId());
327 $this->assertEquals($url, $bookmark->getUrl());
328 $this->assertEquals('abc', $bookmark->getShortUrl());
329 $this->assertEquals($title, $bookmark->getTitle());
330 $this->assertEquals($desc, $bookmark->getDescription());
331 $this->assertEquals($tags, $bookmark->getTags());
332 $this->assertEquals($thumb, $bookmark->getThumbnail());
333 $this->assertTrue($bookmark->isPrivate());
334 $this->assertTrue($bookmark->isSticky());
335 $this->assertEquals($created, $bookmark->getCreated());
336 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated());
337 }
338
339 /**
340 * Test set() method for a bookmark without any field set
341 */
342 public function testSetMinimal()
343 {
344 $bookmark = $this->privateLinkDB->get(42);
345 $this->privateLinkDB->set($bookmark);
346
347 $bookmark = $this->privateLinkDB->get(42);
348 $this->assertEquals(42, $bookmark->getId());
f7f08cee 349 $this->assertEquals('/shaare/WDWyig', $bookmark->getUrl());
e26e2060
A
350 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl());
351 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
352 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription());
353 $this->assertEquals(['ut'], $bookmark->getTags());
354 $this->assertFalse($bookmark->getThumbnail());
355 $this->assertFalse($bookmark->isPrivate());
356 $this->assertFalse($bookmark->isSticky());
357 $this->assertEquals(
358 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100310_101010'),
359 $bookmark->getCreated()
360 );
361 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated());
362
363 // reload from file
fd1ddad9 364 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
365
366 $bookmark = $this->privateLinkDB->get(42);
367 $this->assertEquals(42, $bookmark->getId());
f7f08cee 368 $this->assertEquals('/shaare/WDWyig', $bookmark->getUrl());
e26e2060
A
369 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl());
370 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
371 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription());
372 $this->assertEquals(['ut'], $bookmark->getTags());
373 $this->assertFalse($bookmark->getThumbnail());
374 $this->assertFalse($bookmark->isPrivate());
375 $this->assertFalse($bookmark->isSticky());
376 $this->assertEquals(
377 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100310_101010'),
378 $bookmark->getCreated()
379 );
380 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated());
381 }
382
383 /**
384 * Test set() method for a bookmark without any field set and without writing the data store
385 */
386 public function testSetMinimalNoWrite()
387 {
388 $bookmark = $this->privateLinkDB->get(42);
389 $bookmark->setTitle($title = 'hi!');
390 $this->privateLinkDB->set($bookmark, false);
391
392 $bookmark = $this->privateLinkDB->get(42);
393 $this->assertEquals(42, $bookmark->getId());
394 $this->assertEquals($title, $bookmark->getTitle());
395
396 // reload from file
fd1ddad9 397 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
398
399 $bookmark = $this->privateLinkDB->get(42);
400 $this->assertEquals(42, $bookmark->getId());
401 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
402 }
403
404 /**
405 * Test set() method while logged out
e26e2060
A
406 */
407 public function testSetLoggedOut()
408 {
b1baca99
A
409 $this->expectException(\Exception::class);
410 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
411
e26e2060
A
412 $this->publicLinkDB->set(new Bookmark());
413 }
414
415 /**
416 * Test set() method with an entry which is not a bookmark instance
e26e2060
A
417 */
418 public function testSetNotABookmark()
419 {
b1baca99
A
420 $this->expectException(\Exception::class);
421 $this->expectExceptionMessage('Provided data is invalid');
422
e26e2060
A
423 $this->privateLinkDB->set(['title' => 'hi!']);
424 }
425
426 /**
427 * Test set() method with a Bookmark without an ID defined.
e26e2060
A
428 */
429 public function testSetWithoutId()
430 {
b1baca99
A
431 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
432
e26e2060
A
433 $bookmark = new Bookmark();
434 $this->privateLinkDB->set($bookmark);
435 }
436
437 /**
438 * Test set() method with a Bookmark with an unknow ID
e26e2060
A
439 */
440 public function testSetWithUnknownId()
441 {
b1baca99
A
442 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
443
e26e2060
A
444 $bookmark = new Bookmark();
445 $bookmark->setId(666);
446 $this->privateLinkDB->set($bookmark);
447 }
448
449 /**
450 * Test addOrSet() method with a new ID
451 */
452 public function testAddOrSetNew()
453 {
454 $bookmark = new Bookmark();
455 $this->privateLinkDB->addOrSet($bookmark);
456
457 $bookmark = $this->privateLinkDB->get(43);
458 $this->assertEquals(43, $bookmark->getId());
459
460 // reload from file
fd1ddad9 461 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
462
463 $bookmark = $this->privateLinkDB->get(43);
464 $this->assertEquals(43, $bookmark->getId());
465 }
466
467 /**
468 * Test addOrSet() method with an existing ID
469 */
470 public function testAddOrSetExisting()
471 {
472 $bookmark = $this->privateLinkDB->get(42);
473 $bookmark->setTitle($title = 'hi!');
474 $this->privateLinkDB->addOrSet($bookmark);
475
476 $bookmark = $this->privateLinkDB->get(42);
477 $this->assertEquals(42, $bookmark->getId());
478 $this->assertEquals($title, $bookmark->getTitle());
479
480 // reload from file
fd1ddad9 481 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
482
483 $bookmark = $this->privateLinkDB->get(42);
484 $this->assertEquals(42, $bookmark->getId());
485 $this->assertEquals($title, $bookmark->getTitle());
486 }
487
488 /**
489 * Test addOrSet() method while logged out
e26e2060
A
490 */
491 public function testAddOrSetLoggedOut()
492 {
b1baca99
A
493 $this->expectException(\Exception::class);
494 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
495
e26e2060
A
496 $this->publicLinkDB->addOrSet(new Bookmark());
497 }
498
499 /**
500 * Test addOrSet() method with an entry which is not a bookmark instance
e26e2060
A
501 */
502 public function testAddOrSetNotABookmark()
503 {
b1baca99
A
504 $this->expectException(\Exception::class);
505 $this->expectExceptionMessage('Provided data is invalid');
506
e26e2060
A
507 $this->privateLinkDB->addOrSet(['title' => 'hi!']);
508 }
509
510 /**
511 * Test addOrSet() method for a bookmark without any field set and without writing the data store
512 */
513 public function testAddOrSetMinimalNoWrite()
514 {
515 $bookmark = $this->privateLinkDB->get(42);
516 $bookmark->setTitle($title = 'hi!');
517 $this->privateLinkDB->addOrSet($bookmark, false);
518
519 $bookmark = $this->privateLinkDB->get(42);
520 $this->assertEquals(42, $bookmark->getId());
521 $this->assertEquals($title, $bookmark->getTitle());
522
523 // reload from file
fd1ddad9 524 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
525
526 $bookmark = $this->privateLinkDB->get(42);
527 $this->assertEquals(42, $bookmark->getId());
528 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
529 }
530
531 /**
532 * Test remove() method with an existing Bookmark
e26e2060
A
533 */
534 public function testRemoveExisting()
535 {
b1baca99
A
536 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
537
e26e2060
A
538 $bookmark = $this->privateLinkDB->get(42);
539 $this->privateLinkDB->remove($bookmark);
540
541 $exception = null;
542 try {
543 $this->privateLinkDB->get(42);
544 } catch (BookmarkNotFoundException $e) {
545 $exception = $e;
546 }
547 $this->assertInstanceOf(BookmarkNotFoundException::class, $exception);
548
549 // reload from file
fd1ddad9 550 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
551
552 $this->privateLinkDB->get(42);
553 }
554
555 /**
556 * Test remove() method while logged out
e26e2060
A
557 */
558 public function testRemoveLoggedOut()
559 {
b1baca99
A
560 $this->expectException(\Exception::class);
561 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
562
e26e2060
A
563 $bookmark = $this->privateLinkDB->get(42);
564 $this->publicLinkDB->remove($bookmark);
565 }
566
567 /**
568 * Test remove() method with an entry which is not a bookmark instance
e26e2060
A
569 */
570 public function testRemoveNotABookmark()
571 {
b1baca99
A
572 $this->expectException(\Exception::class);
573 $this->expectExceptionMessage('Provided data is invalid');
574
e26e2060
A
575 $this->privateLinkDB->remove(['title' => 'hi!']);
576 }
577
578 /**
579 * Test remove() method with a Bookmark with an unknown ID
e26e2060
A
580 */
581 public function testRemoveWithUnknownId()
582 {
b1baca99
A
583 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
584
e26e2060
A
585 $bookmark = new Bookmark();
586 $bookmark->setId(666);
587 $this->privateLinkDB->remove($bookmark);
588 }
589
590 /**
591 * Test exists() method
592 */
593 public function testExists()
594 {
595 $this->assertTrue($this->privateLinkDB->exists(42)); // public
596 $this->assertTrue($this->privateLinkDB->exists(6)); // private
597
598 $this->assertTrue($this->privateLinkDB->exists(42, BookmarkFilter::$ALL));
599 $this->assertTrue($this->privateLinkDB->exists(6, BookmarkFilter::$ALL));
600
601 $this->assertTrue($this->privateLinkDB->exists(42, BookmarkFilter::$PUBLIC));
602 $this->assertFalse($this->privateLinkDB->exists(6, BookmarkFilter::$PUBLIC));
603
604 $this->assertFalse($this->privateLinkDB->exists(42, BookmarkFilter::$PRIVATE));
605 $this->assertTrue($this->privateLinkDB->exists(6, BookmarkFilter::$PRIVATE));
606
607 $this->assertTrue($this->publicLinkDB->exists(42));
608 $this->assertFalse($this->publicLinkDB->exists(6));
609
610 $this->assertTrue($this->publicLinkDB->exists(42, BookmarkFilter::$PUBLIC));
611 $this->assertFalse($this->publicLinkDB->exists(6, BookmarkFilter::$PUBLIC));
612
613 $this->assertFalse($this->publicLinkDB->exists(42, BookmarkFilter::$PRIVATE));
614 $this->assertTrue($this->publicLinkDB->exists(6, BookmarkFilter::$PRIVATE));
615 }
616
617 /**
618 * Test initialize() method
619 */
620 public function testInitialize()
621 {
622 $dbSize = $this->privateLinkDB->count();
623 $this->privateLinkDB->initialize();
da7acb98
A
624 $this->assertEquals($dbSize + 3, $this->privateLinkDB->count());
625 $this->assertStringStartsWith(
626 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
627 $this->privateLinkDB->get(43)->getDescription()
e26e2060 628 );
da7acb98
A
629 $this->assertStringStartsWith(
630 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
631 $this->privateLinkDB->get(44)->getDescription()
632 );
633 $this->assertStringStartsWith(
634 'Welcome to Shaarli!',
635 $this->privateLinkDB->get(45)->getDescription()
e26e2060
A
636 );
637 }
638
639 /*
640 * The following tests have been taken from the legacy LinkDB test and adapted
641 * to make sure that nothing have been broken in the migration process.
642 * They mostly cover search/filters. Some of them might be redundant with the previous ones.
643 */
e26e2060
A
644 /**
645 * Attempt to instantiate a LinkDB whereas the datastore is not writable
e26e2060
A
646 */
647 public function testConstructDatastoreNotWriteable()
648 {
f447edb7 649 $this->expectException(\Shaarli\Bookmark\Exception\NotWritableDataStoreException::class);
b1baca99
A
650 $this->expectExceptionMessageRegExp('#Couldn\'t load data from the data store file "null".*#');
651
e26e2060
A
652 $conf = new ConfigManager('tests/utils/config/configJson');
653 $conf->set('resource.datastore', 'null/store.db');
fd1ddad9 654 new BookmarkFileService($conf, $this->history, $this->mutex, true);
e26e2060
A
655 }
656
657 /**
658 * The DB doesn't exist, ensure it is created with an empty datastore
659 */
660 public function testCheckDBNewLoggedIn()
661 {
662 unlink(self::$testDatastore);
663 $this->assertFileNotExists(self::$testDatastore);
fd1ddad9 664 new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
665 $this->assertFileExists(self::$testDatastore);
666
667 // ensure the correct data has been written
668 $this->assertGreaterThan(0, filesize(self::$testDatastore));
669 }
670
671 /**
672 * The DB doesn't exist, but not logged in, ensure it initialized, but the file is not written
673 */
674 public function testCheckDBNewLoggedOut()
675 {
676 unlink(self::$testDatastore);
677 $this->assertFileNotExists(self::$testDatastore);
fd1ddad9 678 $db = new \FakeBookmarkService($this->conf, $this->history, $this->mutex, false);
e26e2060
A
679 $this->assertFileNotExists(self::$testDatastore);
680 $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks());
681 $this->assertCount(0, $db->getBookmarks());
682 }
683
684 /**
685 * Load public bookmarks from the DB
686 */
687 public function testReadPublicDB()
688 {
689 $this->assertEquals(
690 $this->refDB->countPublicLinks(),
691 $this->publicLinkDB->count()
692 );
693 }
694
695 /**
696 * Load public and private bookmarks from the DB
697 */
698 public function testReadPrivateDB()
699 {
700 $this->assertEquals(
701 $this->refDB->countLinks(),
702 $this->privateLinkDB->count()
703 );
704 }
705
706 /**
707 * Save the bookmarks to the DB
708 */
709 public function testSave()
710 {
fd1ddad9 711 $testDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
712 $dbSize = $testDB->count();
713
714 $bookmark = new Bookmark();
715 $testDB->add($bookmark);
716
fd1ddad9 717 $testDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
e26e2060
A
718 $this->assertEquals($dbSize + 1, $testDB->count());
719 }
720
721 /**
722 * Count existing bookmarks - public bookmarks hidden
723 */
724 public function testCountHiddenPublic()
725 {
726 $this->conf->set('privacy.hide_public_links', true);
fd1ddad9 727 $linkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false);
e26e2060
A
728
729 $this->assertEquals(0, $linkDB->count());
730 }
731
732 /**
733 * List the days for which bookmarks have been posted
734 */
735 public function testDays()
736 {
737 $this->assertEquals(
738 ['20100309', '20100310', '20121206', '20121207', '20130614', '20150310'],
739 $this->publicLinkDB->days()
740 );
741
742 $this->assertEquals(
743 ['20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'],
744 $this->privateLinkDB->days()
745 );
746 }
747
748 /**
749 * The URL corresponds to an existing entry in the DB
750 */
751 public function testGetKnownLinkFromURL()
752 {
753 $link = $this->publicLinkDB->findByUrl('http://mediagoblin.org/');
754
755 $this->assertNotEquals(false, $link);
a5a9cf23 756 $this->assertContainsPolyfill(
e26e2060
A
757 'A free software media publishing platform',
758 $link->getDescription()
759 );
760 }
761
762 /**
763 * The URL is not in the DB
764 */
765 public function testGetUnknownLinkFromURL()
766 {
767 $this->assertEquals(
768 false,
769 $this->publicLinkDB->findByUrl('http://dev.null')
770 );
771 }
772
773 /**
774 * Lists all tags
775 */
776 public function testAllTags()
777 {
778 $this->assertEquals(
779 [
780 'web' => 3,
781 'cartoon' => 2,
782 'gnu' => 2,
783 'dev' => 1,
784 'samba' => 1,
785 'media' => 1,
786 'software' => 1,
787 'stallman' => 1,
788 'free' => 1,
789 '-exclude' => 1,
790 'hashtag' => 2,
791 // The DB contains a link with `sTuff` and another one with `stuff` tag.
792 // They need to be grouped with the first case found - order by date DESC: `sTuff`.
793 'sTuff' => 2,
794 'ut' => 1,
795 ],
796 $this->publicLinkDB->bookmarksCountPerTag()
797 );
798
799 $this->assertEquals(
800 [
801 'web' => 4,
802 'cartoon' => 3,
803 'gnu' => 2,
804 'dev' => 2,
805 'samba' => 1,
806 'media' => 1,
807 'software' => 1,
808 'stallman' => 1,
809 'free' => 1,
810 'html' => 1,
811 'w3c' => 1,
812 'css' => 1,
813 'Mercurial' => 1,
814 'sTuff' => 2,
815 '-exclude' => 1,
816 '.hidden' => 1,
817 'hashtag' => 2,
818 'tag1' => 1,
819 'tag2' => 1,
820 'tag3' => 1,
821 'tag4' => 1,
822 'ut' => 1,
823 ],
824 $this->privateLinkDB->bookmarksCountPerTag()
825 );
826 $this->assertEquals(
827 [
e26e2060
A
828 'cartoon' => 2,
829 'gnu' => 1,
830 'dev' => 1,
831 'samba' => 1,
832 'media' => 1,
833 'html' => 1,
834 'w3c' => 1,
835 'css' => 1,
836 'Mercurial' => 1,
837 '.hidden' => 1,
838 'hashtag' => 1,
839 ],
840 $this->privateLinkDB->bookmarksCountPerTag(['web'])
841 );
842 $this->assertEquals(
843 [
e26e2060
A
844 'html' => 1,
845 'w3c' => 1,
846 'css' => 1,
847 'Mercurial' => 1,
848 ],
849 $this->privateLinkDB->bookmarksCountPerTag(['web'], 'private')
850 );
851 }
852
853 /**
854 * Test filter with string.
855 */
856 public function testFilterString()
857 {
858 $tags = 'dev cartoon';
859 $request = ['searchtags' => $tags];
860 $this->assertEquals(
861 2,
862 count($this->privateLinkDB->search($request, null, true))
863 );
864 }
865
866 /**
867 * Test filter with array.
868 */
869 public function testFilterArray()
870 {
871 $tags = ['dev', 'cartoon'];
872 $request = ['searchtags' => $tags];
873 $this->assertEquals(
874 2,
875 count($this->privateLinkDB->search($request, null, true))
876 );
877 }
878
879 /**
880 * Test hidden tags feature:
881 * tags starting with a dot '.' are only visible when logged in.
882 */
883 public function testHiddenTags()
884 {
885 $tags = '.hidden';
886 $request = ['searchtags' => $tags];
887 $this->assertEquals(
888 1,
889 count($this->privateLinkDB->search($request, 'all', true))
890 );
891
892 $this->assertEquals(
893 0,
894 count($this->publicLinkDB->search($request, 'public', true))
895 );
896 }
897
898 /**
899 * Test filterHash() with a valid smallhash.
900 */
901 public function testFilterHashValid()
902 {
903 $request = smallHash('20150310_114651');
1a8ac737
A
904 $this->assertSame(
905 $request,
906 $this->publicLinkDB->findByHash($request)->getShortUrl()
e26e2060
A
907 );
908 $request = smallHash('20150310_114633' . 8);
1a8ac737
A
909 $this->assertSame(
910 $request,
911 $this->publicLinkDB->findByHash($request)->getShortUrl()
e26e2060
A
912 );
913 }
914
915 /**
916 * Test filterHash() with an invalid smallhash.
e26e2060
A
917 */
918 public function testFilterHashInValid1()
919 {
1a8ac737
A
920 $this->expectException(BookmarkNotFoundException::class);
921
e26e2060
A
922 $request = 'blabla';
923 $this->publicLinkDB->findByHash($request);
924 }
925
926 /**
927 * Test filterHash() with an empty smallhash.
e26e2060
A
928 */
929 public function testFilterHashInValid()
930 {
1a8ac737
A
931 $this->expectException(BookmarkNotFoundException::class);
932
e26e2060
A
933 $this->publicLinkDB->findByHash('');
934 }
935
936 /**
937 * Test linksCountPerTag all tags without filter.
938 * Equal occurrences should be sorted alphabetically.
939 */
940 public function testCountLinkPerTagAllNoFilter()
941 {
942 $expected = [
943 'web' => 4,
944 'cartoon' => 3,
945 'dev' => 2,
946 'gnu' => 2,
947 'hashtag' => 2,
948 'sTuff' => 2,
949 '-exclude' => 1,
950 '.hidden' => 1,
951 'Mercurial' => 1,
952 'css' => 1,
953 'free' => 1,
954 'html' => 1,
955 'media' => 1,
956 'samba' => 1,
957 'software' => 1,
958 'stallman' => 1,
959 'tag1' => 1,
960 'tag2' => 1,
961 'tag3' => 1,
962 'tag4' => 1,
963 'ut' => 1,
964 'w3c' => 1,
965 ];
966 $tags = $this->privateLinkDB->bookmarksCountPerTag();
967
968 $this->assertEquals($expected, $tags, var_export($tags, true));
969 }
970
971 /**
972 * Test linksCountPerTag all tags with filter.
973 * Equal occurrences should be sorted alphabetically.
974 */
975 public function testCountLinkPerTagAllWithFilter()
976 {
977 $expected = [
e26e2060
A
978 'hashtag' => 2,
979 '-exclude' => 1,
980 '.hidden' => 1,
981 'free' => 1,
982 'media' => 1,
983 'software' => 1,
984 'stallman' => 1,
985 'stuff' => 1,
986 'web' => 1,
987 ];
988 $tags = $this->privateLinkDB->bookmarksCountPerTag(['gnu']);
989
990 $this->assertEquals($expected, $tags, var_export($tags, true));
991 }
992
993 /**
994 * Test linksCountPerTag public tags with filter.
995 * Equal occurrences should be sorted alphabetically.
996 */
997 public function testCountLinkPerTagPublicWithFilter()
998 {
999 $expected = [
e26e2060
A
1000 'hashtag' => 2,
1001 '-exclude' => 1,
1002 '.hidden' => 1,
1003 'free' => 1,
1004 'media' => 1,
1005 'software' => 1,
1006 'stallman' => 1,
1007 'stuff' => 1,
1008 'web' => 1,
1009 ];
1010 $tags = $this->privateLinkDB->bookmarksCountPerTag(['gnu'], 'public');
1011
1012 $this->assertEquals($expected, $tags, var_export($tags, true));
1013 }
1014
1015 /**
1016 * Test linksCountPerTag public tags with filter.
1017 * Equal occurrences should be sorted alphabetically.
1018 */
1019 public function testCountLinkPerTagPrivateWithFilter()
1020 {
1021 $expected = [
1022 'cartoon' => 1,
e26e2060
A
1023 'tag1' => 1,
1024 'tag2' => 1,
1025 'tag3' => 1,
1026 'tag4' => 1,
1027 ];
1028 $tags = $this->privateLinkDB->bookmarksCountPerTag(['dev'], 'private');
1029
1030 $this->assertEquals($expected, $tags, var_export($tags, true));
1031 }
1032
a39acb25
A
1033 /**
1034 * Test linksCountPerTag public tags with filter.
1035 * Equal occurrences should be sorted alphabetically.
1036 */
1037 public function testCountTagsNoMarkdown()
1038 {
1039 $expected = [
1040 'cartoon' => 3,
1041 'dev' => 2,
1042 'tag1' => 1,
1043 'tag2' => 1,
1044 'tag3' => 1,
1045 'tag4' => 1,
1046 'web' => 4,
1047 'gnu' => 2,
1048 'hashtag' => 2,
1049 'sTuff' => 2,
1050 '-exclude' => 1,
1051 '.hidden' => 1,
1052 'Mercurial' => 1,
1053 'css' => 1,
1054 'free' => 1,
1055 'html' => 1,
1056 'media' => 1,
1057 'newTagToCount' => 1,
1058 'samba' => 1,
1059 'software' => 1,
1060 'stallman' => 1,
1061 'ut' => 1,
1062 'w3c' => 1,
1063 ];
1064 $bookmark = new Bookmark();
1065 $bookmark->setTags(['newTagToCount', BookmarkMarkdownFormatter::NO_MD_TAG]);
1066 $this->privateLinkDB->add($bookmark);
1067
1068 $tags = $this->privateLinkDB->bookmarksCountPerTag();
1069
1070 $this->assertEquals($expected, $tags, var_export($tags, true));
1071 }
1072
27ddfec3
A
1073 /**
1074 * Test filterDay while logged in
1075 */
1076 public function testFilterDayLoggedIn(): void
1077 {
1078 $bookmarks = $this->privateLinkDB->filterDay('20121206');
1079 $expectedIds = [4, 9, 1, 0];
1080
1081 static::assertCount(4, $bookmarks);
1082 foreach ($bookmarks as $bookmark) {
1083 $i = ($i ?? -1) + 1;
1084 static::assertSame($expectedIds[$i], $bookmark->getId());
1085 }
1086 }
1087
1088 /**
1089 * Test filterDay while logged out
1090 */
1091 public function testFilterDayLoggedOut(): void
1092 {
1093 $bookmarks = $this->publicLinkDB->filterDay('20121206');
1094 $expectedIds = [4, 9, 1];
1095
1096 static::assertCount(3, $bookmarks);
1097 foreach ($bookmarks as $bookmark) {
1098 $i = ($i ?? -1) + 1;
1099 static::assertSame($expectedIds[$i], $bookmark->getId());
1100 }
1101 }
1102
e26e2060
A
1103 /**
1104 * Allows to test LinkDB's private methods
1105 *
1106 * @see
1107 * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
1108 * http://stackoverflow.com/a/2798203
1109 */
1110 protected static function getMethod($name)
1111 {
1112 $class = new ReflectionClass('Shaarli\Bookmark\BookmarkFileService');
1113 $method = $class->getMethod($name);
1114 $method->setAccessible(true);
1115 return $method;
1116 }
1117}