diff options
author | VirtualTam <virtualtam@flibidi.org> | 2015-03-12 00:43:02 +0100 |
---|---|---|
committer | VirtualTam <virtualtam@flibidi.net> | 2015-06-11 00:45:45 +0200 |
commit | ca74886f30da323f42aa4bd70461003f46ef299b (patch) | |
tree | 3714895c25d80bdb472211a564f83d3744d90f34 /tests/LinkDBTest.php | |
parent | cbecab773526b0c39f3cffa1d4595b5caa781bda (diff) | |
download | Shaarli-ca74886f30da323f42aa4bd70461003f46ef299b.tar.gz Shaarli-ca74886f30da323f42aa4bd70461003f46ef299b.tar.zst Shaarli-ca74886f30da323f42aa4bd70461003f46ef299b.zip |
LinkDB: move to a proper file, add test coverage
Relates to #71
LinkDB
- move to application/LinkDB.php
- code cleanup
- indentation
- whitespaces
- formatting
- comment cleanup
- add missing documentation
- unify formatting
Test coverage for LinkDB
- constructor
- public / private access
- link-related methods
Shaarli utilities (LinkDB dependencies)
- move startsWith() and endsWith() functions to application/Utils.php
- add test coverage
Dev utilities
- Composer: add PHPUnit to dev dependencies
- Makefile:
- update lint targets
- add test targets
- generate coverage reports
Signed-off-by: VirtualTam <virtualtam@flibidi.net>
Diffstat (limited to 'tests/LinkDBTest.php')
-rw-r--r-- | tests/LinkDBTest.php | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php new file mode 100644 index 00000000..bbe4e026 --- /dev/null +++ b/tests/LinkDBTest.php | |||
@@ -0,0 +1,509 @@ | |||
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); | ||
45 | self::$privateLinkDB = new LinkDB(true); | ||
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); | ||
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); | ||
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); | ||
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); | ||
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); | ||
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); | ||
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); | ||
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); | ||
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 | * List the days for which links have been posted | ||
222 | */ | ||
223 | public function testDays() | ||
224 | { | ||
225 | $this->assertEquals( | ||
226 | ['20121206', '20130614', '20150310'], | ||
227 | self::$publicLinkDB->days() | ||
228 | ); | ||
229 | |||
230 | $this->assertEquals( | ||
231 | ['20121206', '20130614', '20141125', '20150310'], | ||
232 | self::$privateLinkDB->days() | ||
233 | ); | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * The URL corresponds to an existing entry in the DB | ||
238 | */ | ||
239 | public function testGetKnownLinkFromURL() | ||
240 | { | ||
241 | $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/'); | ||
242 | |||
243 | $this->assertNotEquals(false, $link); | ||
244 | $this->assertEquals( | ||
245 | 'A free software media publishing platform', | ||
246 | $link['description'] | ||
247 | ); | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * The URL is not in the DB | ||
252 | */ | ||
253 | public function testGetUnknownLinkFromURL() | ||
254 | { | ||
255 | $this->assertEquals( | ||
256 | false, | ||
257 | self::$publicLinkDB->getLinkFromUrl('http://dev.null') | ||
258 | ); | ||
259 | } | ||
260 | |||
261 | /** | ||
262 | * Lists all tags | ||
263 | */ | ||
264 | public function testAllTags() | ||
265 | { | ||
266 | $this->assertEquals( | ||
267 | [ | ||
268 | 'web' => 3, | ||
269 | 'cartoon' => 2, | ||
270 | 'gnu' => 2, | ||
271 | 'dev' => 1, | ||
272 | 'samba' => 1, | ||
273 | 'media' => 1, | ||
274 | 'software' => 1, | ||
275 | 'stallman' => 1, | ||
276 | 'free' => 1 | ||
277 | ], | ||
278 | self::$publicLinkDB->allTags() | ||
279 | ); | ||
280 | |||
281 | $this->assertEquals( | ||
282 | [ | ||
283 | 'web' => 4, | ||
284 | 'cartoon' => 3, | ||
285 | 'gnu' => 2, | ||
286 | 'dev' => 2, | ||
287 | 'samba' => 1, | ||
288 | 'media' => 1, | ||
289 | 'software' => 1, | ||
290 | 'stallman' => 1, | ||
291 | 'free' => 1, | ||
292 | 'html' => 1, | ||
293 | 'w3c' => 1, | ||
294 | 'css' => 1, | ||
295 | 'Mercurial' => 1 | ||
296 | ], | ||
297 | self::$privateLinkDB->allTags() | ||
298 | ); | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * Filter links using a tag | ||
303 | */ | ||
304 | public function testFilterOneTag() | ||
305 | { | ||
306 | $this->assertEquals( | ||
307 | 3, | ||
308 | sizeof(self::$publicLinkDB->filterTags('web', false)) | ||
309 | ); | ||
310 | |||
311 | $this->assertEquals( | ||
312 | 4, | ||
313 | sizeof(self::$privateLinkDB->filterTags('web', false)) | ||
314 | ); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * Filter links using a tag - case-sensitive | ||
319 | */ | ||
320 | public function testFilterCaseSensitiveTag() | ||
321 | { | ||
322 | $this->assertEquals( | ||
323 | 0, | ||
324 | sizeof(self::$privateLinkDB->filterTags('mercurial', true)) | ||
325 | ); | ||
326 | |||
327 | $this->assertEquals( | ||
328 | 1, | ||
329 | sizeof(self::$privateLinkDB->filterTags('Mercurial', true)) | ||
330 | ); | ||
331 | } | ||
332 | |||
333 | /** | ||
334 | * Filter links using a tag combination | ||
335 | */ | ||
336 | public function testFilterMultipleTags() | ||
337 | { | ||
338 | $this->assertEquals( | ||
339 | 1, | ||
340 | sizeof(self::$publicLinkDB->filterTags('dev cartoon', false)) | ||
341 | ); | ||
342 | |||
343 | $this->assertEquals( | ||
344 | 2, | ||
345 | sizeof(self::$privateLinkDB->filterTags('dev cartoon', false)) | ||
346 | ); | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * Filter links using a non-existent tag | ||
351 | */ | ||
352 | public function testFilterUnknownTag() | ||
353 | { | ||
354 | $this->assertEquals( | ||
355 | 0, | ||
356 | sizeof(self::$publicLinkDB->filterTags('null', false)) | ||
357 | ); | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * Return links for a given day | ||
362 | */ | ||
363 | public function testFilterDay() | ||
364 | { | ||
365 | $this->assertEquals( | ||
366 | 2, | ||
367 | sizeof(self::$publicLinkDB->filterDay('20121206')) | ||
368 | ); | ||
369 | |||
370 | $this->assertEquals( | ||
371 | 3, | ||
372 | sizeof(self::$privateLinkDB->filterDay('20121206')) | ||
373 | ); | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * 404 - day not found | ||
378 | */ | ||
379 | public function testFilterUnknownDay() | ||
380 | { | ||
381 | $this->assertEquals( | ||
382 | 0, | ||
383 | sizeof(self::$publicLinkDB->filterDay('19700101')) | ||
384 | ); | ||
385 | |||
386 | $this->assertEquals( | ||
387 | 0, | ||
388 | sizeof(self::$privateLinkDB->filterDay('19700101')) | ||
389 | ); | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * Use an invalid date format | ||
394 | */ | ||
395 | public function testFilterInvalidDay() | ||
396 | { | ||
397 | $this->assertEquals( | ||
398 | 0, | ||
399 | sizeof(self::$privateLinkDB->filterDay('Rainy day, dream away')) | ||
400 | ); | ||
401 | |||
402 | // TODO: check input format | ||
403 | $this->assertEquals( | ||
404 | 6, | ||
405 | sizeof(self::$privateLinkDB->filterDay('20')) | ||
406 | ); | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * Retrieve a link entry with its hash | ||
411 | */ | ||
412 | public function testFilterSmallHash() | ||
413 | { | ||
414 | $links = self::$privateLinkDB->filterSmallHash('IuWvgA'); | ||
415 | |||
416 | $this->assertEquals( | ||
417 | 1, | ||
418 | sizeof($links) | ||
419 | ); | ||
420 | |||
421 | $this->assertEquals( | ||
422 | 'MediaGoblin', | ||
423 | $links['20130614_184135']['title'] | ||
424 | ); | ||
425 | |||
426 | } | ||
427 | |||
428 | /** | ||
429 | * No link for this hash | ||
430 | */ | ||
431 | public function testFilterUnknownSmallHash() | ||
432 | { | ||
433 | $this->assertEquals( | ||
434 | 0, | ||
435 | sizeof(self::$privateLinkDB->filterSmallHash('Iblaah')) | ||
436 | ); | ||
437 | } | ||
438 | |||
439 | /** | ||
440 | * Full-text search - result from a link's URL | ||
441 | */ | ||
442 | public function testFilterFullTextURL() | ||
443 | { | ||
444 | $this->assertEquals( | ||
445 | 2, | ||
446 | sizeof(self::$publicLinkDB->filterFullText('ars.userfriendly.org')) | ||
447 | ); | ||
448 | } | ||
449 | |||
450 | /** | ||
451 | * Full-text search - result from a link's title only | ||
452 | */ | ||
453 | public function testFilterFullTextTitle() | ||
454 | { | ||
455 | // use miscellaneous cases | ||
456 | $this->assertEquals( | ||
457 | 2, | ||
458 | sizeof(self::$publicLinkDB->filterFullText('userfriendly -')) | ||
459 | ); | ||
460 | $this->assertEquals( | ||
461 | 2, | ||
462 | sizeof(self::$publicLinkDB->filterFullText('UserFriendly -')) | ||
463 | ); | ||
464 | $this->assertEquals( | ||
465 | 2, | ||
466 | sizeof(self::$publicLinkDB->filterFullText('uSeRFrIendlY -')) | ||
467 | ); | ||
468 | |||
469 | // use miscellaneous case and offset | ||
470 | $this->assertEquals( | ||
471 | 2, | ||
472 | sizeof(self::$publicLinkDB->filterFullText('RFrIendL')) | ||
473 | ); | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * Full-text search - result from the link's description only | ||
478 | */ | ||
479 | public function testFilterFullTextDescription() | ||
480 | { | ||
481 | $this->assertEquals( | ||
482 | 1, | ||
483 | sizeof(self::$publicLinkDB->filterFullText('media publishing')) | ||
484 | ); | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * Full-text search - result from the link's tags only | ||
489 | */ | ||
490 | public function testFilterFullTextTags() | ||
491 | { | ||
492 | $this->assertEquals( | ||
493 | 2, | ||
494 | sizeof(self::$publicLinkDB->filterFullText('gnu')) | ||
495 | ); | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * Full-text search - result set from mixed sources | ||
500 | */ | ||
501 | public function testFilterFullTextMixed() | ||
502 | { | ||
503 | $this->assertEquals( | ||
504 | 2, | ||
505 | sizeof(self::$publicLinkDB->filterFullText('free software')) | ||
506 | ); | ||
507 | } | ||
508 | } | ||
509 | ?> | ||