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