6 require_once 'application/Cache.php';
7 require_once 'application/FileUtils.php';
8 require_once 'application/LinkDB.php';
9 require_once 'application/Utils.php';
10 require_once 'tests/utils/ReferenceLinkDB.php';
14 * Unitary tests for LinkDB
16 class LinkDBTest
extends PHPUnit_Framework_TestCase
18 // datastore to test write operations
19 protected static $testDatastore = 'sandbox/datastore.php';
22 * @var ReferenceLinkDB instance.
24 protected static $refDB = null;
27 * @var LinkDB public LinkDB instance.
29 protected static $publicLinkDB = null;
32 * @var LinkDB private LinkDB instance.
34 protected static $privateLinkDB = null;
37 * Instantiates public and private LinkDBs with test data
39 * The reference datastore contains public and private links that
40 * will be used to test LinkDB's methods:
41 * - access filtering (public/private),
48 public static function setUpBeforeClass()
50 self
::$refDB = new ReferenceLinkDB();
51 self
::$refDB->write(self
::$testDatastore);
53 self
::$publicLinkDB = new LinkDB(self
::$testDatastore, false, false);
54 self
::$privateLinkDB = new LinkDB(self
::$testDatastore, true, false);
58 * Resets test data for each test
60 protected function setUp()
62 if (file_exists(self
::$testDatastore)) {
63 unlink(self
::$testDatastore);
68 * Allows to test LinkDB's private methods
71 * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
72 * http://stackoverflow.com/a/2798203
74 protected static function getMethod($name)
76 $class = new ReflectionClass('LinkDB');
77 $method = $class->getMethod($name);
78 $method->setAccessible(true);
83 * Instantiate LinkDB objects - logged in user
85 public function testConstructLoggedIn()
87 new LinkDB(self
::$testDatastore, true, false);
88 $this->assertFileExists(self
::$testDatastore);
92 * Instantiate LinkDB objects - logged out or public instance
94 public function testConstructLoggedOut()
96 new LinkDB(self
::$testDatastore, false, false);
97 $this->assertFileExists(self
::$testDatastore);
101 * Attempt to instantiate a LinkDB whereas the datastore is not writable
103 * @expectedException IOException
104 * @expectedExceptionMessageRegExp /Error accessing "null"/
106 public function testConstructDatastoreNotWriteable()
108 new LinkDB('null/store.db', false, false);
112 * The DB doesn't exist, ensure it is created with dummy content
114 public function testCheckDBNew()
116 $linkDB = new LinkDB(self
::$testDatastore, false, false);
117 unlink(self
::$testDatastore);
118 $this->assertFileNotExists(self
::$testDatastore);
120 $checkDB = self
::getMethod('check');
121 $checkDB->invokeArgs($linkDB, array());
122 $this->assertFileExists(self
::$testDatastore);
124 // ensure the correct data has been written
125 $this->assertGreaterThan(0, filesize(self
::$testDatastore));
129 * The DB exists, don't do anything
131 public function testCheckDBLoad()
133 $linkDB = new LinkDB(self
::$testDatastore, false, false);
134 $datastoreSize = filesize(self
::$testDatastore);
135 $this->assertGreaterThan(0, $datastoreSize);
137 $checkDB = self
::getMethod('check');
138 $checkDB->invokeArgs($linkDB, array());
140 // ensure the datastore is left unmodified
143 filesize(self
::$testDatastore)
150 public function testReadEmptyDB()
152 file_put_contents(self
::$testDatastore, '<?php /* S7QysKquBQA= */ ?>');
153 $emptyDB = new LinkDB(self
::$testDatastore, false, false);
154 $this->assertEquals(0, sizeof($emptyDB));
155 $this->assertEquals(0, count($emptyDB));
159 * Load public links from the DB
161 public function testReadPublicDB()
164 self
::$refDB->countPublicLinks(),
165 sizeof(self
::$publicLinkDB)
170 * Load public and private links from the DB
172 public function testReadPrivateDB()
175 self
::$refDB->countLinks(),
176 sizeof(self
::$privateLinkDB)
181 * Save the links to the DB
183 public function testSave()
185 $testDB = new LinkDB(self
::$testDatastore, true, false);
186 $dbSize = sizeof($testDB);
190 'title'=>'an additional link',
191 'url'=>'http://dum.my',
192 'description'=>'One more',
194 'created'=> DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20150518_190000'),
197 $testDB[$link['id']] = $link;
198 $testDB->save('tests');
200 $testDB = new LinkDB(self
::$testDatastore, true, false);
201 $this->assertEquals($dbSize +
1, sizeof($testDB));
205 * Count existing links
207 public function testCount()
210 self
::$refDB->countPublicLinks(),
211 self
::$publicLinkDB->count()
214 self
::$refDB->countLinks(),
215 self
::$privateLinkDB->count()
220 * Count existing links - public links hidden
222 public function testCountHiddenPublic()
224 $linkDB = new LinkDB(self
::$testDatastore, false, true);
237 * List the days for which links have been posted
239 public function testDays()
242 array('20100310', '20121206', '20130614', '20150310'),
243 self
::$publicLinkDB->days()
247 array('20100310', '20121206', '20130614', '20141125', '20150310'),
248 self
::$privateLinkDB->days()
253 * The URL corresponds to an existing entry in the DB
255 public function testGetKnownLinkFromURL()
257 $link = self
::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
259 $this->assertNotEquals(false, $link);
260 $this->assertContains(
261 'A free software media publishing platform',
267 * The URL is not in the DB
269 public function testGetUnknownLinkFromURL()
273 self
::$publicLinkDB->getLinkFromUrl('http://dev.null')
280 public function testAllTags()
295 // The DB contains a link with `sTuff` and another one with `stuff` tag.
296 // They need to be grouped with the first case found - order by date DESC: `sTuff`.
300 self
::$publicLinkDB->linksCountPerTag()
328 self
::$privateLinkDB->linksCountPerTag()
345 self
::$privateLinkDB->linksCountPerTag(['web'])
355 self
::$privateLinkDB->linksCountPerTag(['web'], 'private')
360 * Test real_url without redirector.
362 public function testLinkRealUrlWithoutRedirector()
364 $db = new LinkDB(self
::$testDatastore, false, false);
365 foreach($db as $link) {
366 $this->assertEquals($link['url'], $link['real_url']);
371 * Test real_url with redirector.
373 public function testLinkRealUrlWithRedirector()
375 $redirector = 'http://redirector.to?';
376 $db = new LinkDB(self
::$testDatastore, false, false, $redirector);
377 foreach($db as $link) {
378 $this->assertStringStartsWith($redirector, $link['real_url']);
379 $this->assertNotFalse(strpos($link['real_url'], urlencode('://')));
382 $db = new LinkDB(self
::$testDatastore, false, false, $redirector, false);
383 foreach($db as $link) {
384 $this->assertStringStartsWith($redirector, $link['real_url']);
385 $this->assertFalse(strpos($link['real_url'], urlencode('://')));
390 * Test filter with string.
392 public function testFilterString()
394 $tags = 'dev cartoon';
395 $request = array('searchtags' => $tags);
398 count(self
::$privateLinkDB->filterSearch($request, true, false))
403 * Test filter with string.
405 public function testFilterArray()
407 $tags = array('dev', 'cartoon');
408 $request = array('searchtags' => $tags);
411 count(self
::$privateLinkDB->filterSearch($request, true, false))
416 * Test hidden tags feature:
417 * tags starting with a dot '.' are only visible when logged in.
419 public function testHiddenTags()
422 $request = array('searchtags' => $tags);
425 count(self
::$privateLinkDB->filterSearch($request, true, false))
430 count(self
::$publicLinkDB->filterSearch($request, true, false))
435 * Test filterHash() with a valid smallhash.
437 public function testFilterHashValid()
439 $request = smallHash('20150310_114651');
442 count(self
::$publicLinkDB->filterHash($request))
444 $request = smallHash('20150310_114633' . 8);
447 count(self
::$publicLinkDB->filterHash($request))
452 * Test filterHash() with an invalid smallhash.
454 * @expectedException LinkNotFoundException
456 public function testFilterHashInValid1()
459 self
::$publicLinkDB->filterHash($request);
463 * Test filterHash() with an empty smallhash.
465 * @expectedException LinkNotFoundException
467 public function testFilterHashInValid()
469 self
::$publicLinkDB->filterHash('');
473 * Test reorder with asc/desc parameter.
475 public function testReorderLinksDesc()
477 self
::$privateLinkDB->reorder('ASC');
478 $linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41);
480 foreach (self
::$privateLinkDB as $key => $value) {
481 $this->assertEquals($linkIds[$cpt++
], $key);
483 self
::$privateLinkDB->reorder('DESC');
484 $linkIds = array_reverse($linkIds);
486 foreach (self
::$privateLinkDB as $key => $value) {
487 $this->assertEquals($linkIds[$cpt++
], $key);
492 * Test rename tag with a valid value present in multiple links
494 public function testRenameTagMultiple()
496 self
::$refDB->write(self
::$testDatastore);
497 $linkDB = new LinkDB(self
::$testDatastore, true, false);
499 $res = $linkDB->renameTag('cartoon', 'Taz');
500 $this->assertEquals(3, count($res));
501 $this->assertContains(' Taz ', $linkDB[4]['tags']);
502 $this->assertContains(' Taz ', $linkDB[1]['tags']);
503 $this->assertContains(' Taz ', $linkDB[0]['tags']);
507 * Test rename tag with a valid value
509 public function testRenameTagCaseSensitive()
511 self
::$refDB->write(self
::$testDatastore);
512 $linkDB = new LinkDB(self
::$testDatastore, true, false, '');
514 $res = $linkDB->renameTag('sTuff', 'Taz');
515 $this->assertEquals(1, count($res));
516 $this->assertEquals('Taz', $linkDB[41]['tags']);
520 * Test rename tag with invalid values
522 public function testRenameTagInvalid()
524 $linkDB = new LinkDB(self
::$testDatastore, false, false);
526 $this->assertFalse($linkDB->renameTag('', 'test'));
527 $this->assertFalse($linkDB->renameTag('', ''));
529 $this->assertEquals([], $linkDB->renameTag('test', ''));
530 $this->assertEquals([], $linkDB->renameTag('test', 'retest'));
534 * Test delete tag with a valid value
536 public function testDeleteTag()
538 self
::$refDB->write(self
::$testDatastore);
539 $linkDB = new LinkDB(self
::$testDatastore, true, false);
541 $res = $linkDB->renameTag('cartoon', null);
542 $this->assertEquals(3, count($res));
543 $this->assertNotContains('cartoon', $linkDB[4]['tags']);