]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/LinkDBTest.php
f67d4d9bdde93d80a582d80644a2e6e493c0876d
[github/shaarli/Shaarli.git] / tests / LinkDBTest.php
1 <?php
2 /**
3 * Link datastore tests
4 */
5
6 require_once 'application/LinkDB.php';
7 require_once 'application/Utils.php';
8 require_once 'tests/utils/ReferenceLinkDB.php';
9
10 define('PHPPREFIX', '<?php /* ');
11 define('PHPSUFFIX', ' */ ?>');
12
13
14 /**
15 * Unitary tests for LinkDB
16 */
17 class LinkDBTest extends PHPUnit_Framework_TestCase
18 {
19 // datastore to test write operations
20 protected static $testDatastore = 'tests/datastore.php';
21 protected static $dummyDatastoreSHA1 = 'e3edea8ea7bb50be4bcb404df53fbb4546a7156e';
22 protected static $refDB = null;
23 protected static $publicLinkDB = null;
24 protected static $privateLinkDB = null;
25
26 /**
27 * Instantiates public and private LinkDBs with test data
28 *
29 * The reference datastore contains public and private links that
30 * will be used to test LinkDB's methods:
31 * - access filtering (public/private),
32 * - link searches:
33 * - by day,
34 * - by tag,
35 * - by text,
36 * - etc.
37 */
38 public static function setUpBeforeClass()
39 {
40 self::$refDB = new ReferenceLinkDB();
41 self::$refDB->write(self::$testDatastore, PHPPREFIX, PHPSUFFIX);
42
43 $GLOBALS['config']['DATASTORE'] = self::$testDatastore;
44 self::$publicLinkDB = new LinkDB(false, false);
45 self::$privateLinkDB = new LinkDB(true, false);
46 }
47
48 /**
49 * Resets test data for each test
50 */
51 protected function setUp()
52 {
53 $GLOBALS['config']['DATASTORE'] = self::$testDatastore;
54 if (file_exists(self::$testDatastore)) {
55 unlink(self::$testDatastore);
56 }
57 }
58
59 /**
60 * Allows to test LinkDB's private methods
61 *
62 * @see
63 * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
64 * http://stackoverflow.com/a/2798203
65 */
66 protected static function getMethod($name)
67 {
68 $class = new ReflectionClass('LinkDB');
69 $method = $class->getMethod($name);
70 $method->setAccessible(true);
71 return $method;
72 }
73
74 /**
75 * Instantiate LinkDB objects - logged in user
76 */
77 public function testConstructLoggedIn()
78 {
79 new LinkDB(true, false);
80 $this->assertFileExists(self::$testDatastore);
81 }
82
83 /**
84 * Instantiate LinkDB objects - logged out or public instance
85 */
86 public function testConstructLoggedOut()
87 {
88 new LinkDB(false, false);
89 $this->assertFileExists(self::$testDatastore);
90 }
91
92 /**
93 * Attempt to instantiate a LinkDB whereas the datastore is not writable
94 *
95 * @expectedException PHPUnit_Framework_Error_Warning
96 * @expectedExceptionMessageRegExp /failed to open stream: No such file or directory/
97 */
98 public function testConstructDatastoreNotWriteable()
99 {
100 $GLOBALS['config']['DATASTORE'] = 'null/store.db';
101 new LinkDB(false, false);
102 }
103
104 /**
105 * The DB doesn't exist, ensure it is created with dummy content
106 */
107 public function testCheckDBNew()
108 {
109 $linkDB = new LinkDB(false, false);
110 unlink(self::$testDatastore);
111 $this->assertFileNotExists(self::$testDatastore);
112
113 $checkDB = self::getMethod('checkDB');
114 $checkDB->invokeArgs($linkDB, array());
115 $this->assertFileExists(self::$testDatastore);
116
117 // ensure the correct data has been written
118 $this->assertEquals(
119 self::$dummyDatastoreSHA1,
120 sha1_file(self::$testDatastore)
121 );
122 }
123
124 /**
125 * The DB exists, don't do anything
126 */
127 public function testCheckDBLoad()
128 {
129 $linkDB = new LinkDB(false, false);
130 $this->assertEquals(
131 self::$dummyDatastoreSHA1,
132 sha1_file(self::$testDatastore)
133 );
134
135 $checkDB = self::getMethod('checkDB');
136 $checkDB->invokeArgs($linkDB, array());
137
138 // ensure the datastore is left unmodified
139 $this->assertEquals(
140 self::$dummyDatastoreSHA1,
141 sha1_file(self::$testDatastore)
142 );
143 }
144
145 /**
146 * Load an empty DB
147 */
148 public function testReadEmptyDB()
149 {
150 file_put_contents(self::$testDatastore, PHPPREFIX.'S7QysKquBQA='.PHPSUFFIX);
151 $emptyDB = new LinkDB(false, false);
152 $this->assertEquals(0, sizeof($emptyDB));
153 $this->assertEquals(0, count($emptyDB));
154 }
155
156 /**
157 * Load public links from the DB
158 */
159 public function testReadPublicDB()
160 {
161 $this->assertEquals(
162 self::$refDB->countPublicLinks(),
163 sizeof(self::$publicLinkDB)
164 );
165 }
166
167 /**
168 * Load public and private links from the DB
169 */
170 public function testReadPrivateDB()
171 {
172 $this->assertEquals(
173 self::$refDB->countLinks(),
174 sizeof(self::$privateLinkDB)
175 );
176 }
177
178 /**
179 * Save the links to the DB
180 */
181 public function testSaveDB()
182 {
183 $testDB = new LinkDB(true, false);
184 $dbSize = sizeof($testDB);
185
186 $link = array(
187 'title'=>'an additional link',
188 'url'=>'http://dum.my',
189 'description'=>'One more',
190 'private'=>0,
191 'linkdate'=>'20150518_190000',
192 'tags'=>'unit test'
193 );
194 $testDB[$link['linkdate']] = $link;
195
196 // TODO: move PageCache to a proper class/file
197 function invalidateCaches() {}
198
199 $testDB->savedb();
200
201 $testDB = new LinkDB(true, false);
202 $this->assertEquals($dbSize + 1, sizeof($testDB));
203 }
204
205 /**
206 * Count existing links
207 */
208 public function testCount()
209 {
210 $this->assertEquals(
211 self::$refDB->countPublicLinks(),
212 self::$publicLinkDB->count()
213 );
214 $this->assertEquals(
215 self::$refDB->countLinks(),
216 self::$privateLinkDB->count()
217 );
218 }
219
220 /**
221 * Count existing links - public links hidden
222 */
223 public function testCountHiddenPublic()
224 {
225 $linkDB = new LinkDB(false, true);
226
227 $this->assertEquals(
228 0,
229 $linkDB->count()
230 );
231 $this->assertEquals(
232 0,
233 $linkDB->count()
234 );
235 }
236
237 /**
238 * List the days for which links have been posted
239 */
240 public function testDays()
241 {
242 $this->assertEquals(
243 ['20121206', '20130614', '20150310'],
244 self::$publicLinkDB->days()
245 );
246
247 $this->assertEquals(
248 ['20121206', '20130614', '20141125', '20150310'],
249 self::$privateLinkDB->days()
250 );
251 }
252
253 /**
254 * The URL corresponds to an existing entry in the DB
255 */
256 public function testGetKnownLinkFromURL()
257 {
258 $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
259
260 $this->assertNotEquals(false, $link);
261 $this->assertEquals(
262 'A free software media publishing platform',
263 $link['description']
264 );
265 }
266
267 /**
268 * The URL is not in the DB
269 */
270 public function testGetUnknownLinkFromURL()
271 {
272 $this->assertEquals(
273 false,
274 self::$publicLinkDB->getLinkFromUrl('http://dev.null')
275 );
276 }
277
278 /**
279 * Lists all tags
280 */
281 public function testAllTags()
282 {
283 $this->assertEquals(
284 [
285 'web' => 3,
286 'cartoon' => 2,
287 'gnu' => 2,
288 'dev' => 1,
289 'samba' => 1,
290 'media' => 1,
291 'software' => 1,
292 'stallman' => 1,
293 'free' => 1
294 ],
295 self::$publicLinkDB->allTags()
296 );
297
298 $this->assertEquals(
299 [
300 'web' => 4,
301 'cartoon' => 3,
302 'gnu' => 2,
303 'dev' => 2,
304 'samba' => 1,
305 'media' => 1,
306 'software' => 1,
307 'stallman' => 1,
308 'free' => 1,
309 'html' => 1,
310 'w3c' => 1,
311 'css' => 1,
312 'Mercurial' => 1
313 ],
314 self::$privateLinkDB->allTags()
315 );
316 }
317
318 /**
319 * Filter links using a tag
320 */
321 public function testFilterOneTag()
322 {
323 $this->assertEquals(
324 3,
325 sizeof(self::$publicLinkDB->filterTags('web', false))
326 );
327
328 $this->assertEquals(
329 4,
330 sizeof(self::$privateLinkDB->filterTags('web', false))
331 );
332 }
333
334 /**
335 * Filter links using a tag - case-sensitive
336 */
337 public function testFilterCaseSensitiveTag()
338 {
339 $this->assertEquals(
340 0,
341 sizeof(self::$privateLinkDB->filterTags('mercurial', true))
342 );
343
344 $this->assertEquals(
345 1,
346 sizeof(self::$privateLinkDB->filterTags('Mercurial', true))
347 );
348 }
349
350 /**
351 * Filter links using a tag combination
352 */
353 public function testFilterMultipleTags()
354 {
355 $this->assertEquals(
356 1,
357 sizeof(self::$publicLinkDB->filterTags('dev cartoon', false))
358 );
359
360 $this->assertEquals(
361 2,
362 sizeof(self::$privateLinkDB->filterTags('dev cartoon', false))
363 );
364 }
365
366 /**
367 * Filter links using a non-existent tag
368 */
369 public function testFilterUnknownTag()
370 {
371 $this->assertEquals(
372 0,
373 sizeof(self::$publicLinkDB->filterTags('null', false))
374 );
375 }
376
377 /**
378 * Return links for a given day
379 */
380 public function testFilterDay()
381 {
382 $this->assertEquals(
383 2,
384 sizeof(self::$publicLinkDB->filterDay('20121206'))
385 );
386
387 $this->assertEquals(
388 3,
389 sizeof(self::$privateLinkDB->filterDay('20121206'))
390 );
391 }
392
393 /**
394 * 404 - day not found
395 */
396 public function testFilterUnknownDay()
397 {
398 $this->assertEquals(
399 0,
400 sizeof(self::$publicLinkDB->filterDay('19700101'))
401 );
402
403 $this->assertEquals(
404 0,
405 sizeof(self::$privateLinkDB->filterDay('19700101'))
406 );
407 }
408
409 /**
410 * Use an invalid date format
411 */
412 public function testFilterInvalidDay()
413 {
414 $this->assertEquals(
415 0,
416 sizeof(self::$privateLinkDB->filterDay('Rainy day, dream away'))
417 );
418
419 // TODO: check input format
420 $this->assertEquals(
421 6,
422 sizeof(self::$privateLinkDB->filterDay('20'))
423 );
424 }
425
426 /**
427 * Retrieve a link entry with its hash
428 */
429 public function testFilterSmallHash()
430 {
431 $links = self::$privateLinkDB->filterSmallHash('IuWvgA');
432
433 $this->assertEquals(
434 1,
435 sizeof($links)
436 );
437
438 $this->assertEquals(
439 'MediaGoblin',
440 $links['20130614_184135']['title']
441 );
442
443 }
444
445 /**
446 * No link for this hash
447 */
448 public function testFilterUnknownSmallHash()
449 {
450 $this->assertEquals(
451 0,
452 sizeof(self::$privateLinkDB->filterSmallHash('Iblaah'))
453 );
454 }
455
456 /**
457 * Full-text search - result from a link's URL
458 */
459 public function testFilterFullTextURL()
460 {
461 $this->assertEquals(
462 2,
463 sizeof(self::$publicLinkDB->filterFullText('ars.userfriendly.org'))
464 );
465 }
466
467 /**
468 * Full-text search - result from a link's title only
469 */
470 public function testFilterFullTextTitle()
471 {
472 // use miscellaneous cases
473 $this->assertEquals(
474 2,
475 sizeof(self::$publicLinkDB->filterFullText('userfriendly -'))
476 );
477 $this->assertEquals(
478 2,
479 sizeof(self::$publicLinkDB->filterFullText('UserFriendly -'))
480 );
481 $this->assertEquals(
482 2,
483 sizeof(self::$publicLinkDB->filterFullText('uSeRFrIendlY -'))
484 );
485
486 // use miscellaneous case and offset
487 $this->assertEquals(
488 2,
489 sizeof(self::$publicLinkDB->filterFullText('RFrIendL'))
490 );
491 }
492
493 /**
494 * Full-text search - result from the link's description only
495 */
496 public function testFilterFullTextDescription()
497 {
498 $this->assertEquals(
499 1,
500 sizeof(self::$publicLinkDB->filterFullText('media publishing'))
501 );
502 }
503
504 /**
505 * Full-text search - result from the link's tags only
506 */
507 public function testFilterFullTextTags()
508 {
509 $this->assertEquals(
510 2,
511 sizeof(self::$publicLinkDB->filterFullText('gnu'))
512 );
513 }
514
515 /**
516 * Full-text search - result set from mixed sources
517 */
518 public function testFilterFullTextMixed()
519 {
520 $this->assertEquals(
521 2,
522 sizeof(self::$publicLinkDB->filterFullText('free software'))
523 );
524 }
525 }
526 ?>