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