aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/LinkDBTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/LinkDBTest.php')
-rw-r--r--tests/LinkDBTest.php509
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
6require_once 'application/LinkDB.php';
7require_once 'application/Utils.php';
8require_once 'tests/utils/ReferenceLinkDB.php';
9
10define('PHPPREFIX', '<?php /* ');
11define('PHPSUFFIX', ' */ ?>');
12
13
14/**
15 * Unitary tests for LinkDB
16 */
17class 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?>