]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/LinkDBTest.php
Unit Test for the new ID system
[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/FileUtils.php';
8 require_once 'application/LinkDB.php';
9 require_once 'application/Utils.php';
10 require_once 'tests/utils/ReferenceLinkDB.php';
11
12
13 /**
14 * Unitary tests for LinkDB
15 */
16 class LinkDBTest extends PHPUnit_Framework_TestCase
17 {
18 // datastore to test write operations
19 protected static $testDatastore = 'sandbox/datastore.php';
20
21 /**
22 * @var ReferenceLinkDB instance.
23 */
24 protected static $refDB = null;
25
26 /**
27 * @var LinkDB public LinkDB instance.
28 */
29 protected static $publicLinkDB = null;
30
31 /**
32 * @var LinkDB private LinkDB instance.
33 */
34 protected static $privateLinkDB = null;
35
36 /**
37 * Instantiates public and private LinkDBs with test data
38 *
39 * The reference datastore contains public and private links that
40 * will be used to test LinkDB's methods:
41 * - access filtering (public/private),
42 * - link searches:
43 * - by day,
44 * - by tag,
45 * - by text,
46 * - etc.
47 */
48 public static function setUpBeforeClass()
49 {
50 self::$refDB = new ReferenceLinkDB();
51 self::$refDB->write(self::$testDatastore);
52
53 self::$publicLinkDB = new LinkDB(self::$testDatastore, false, false);
54 self::$privateLinkDB = new LinkDB(self::$testDatastore, true, false);
55 }
56
57 /**
58 * Resets test data for each test
59 */
60 protected function setUp()
61 {
62 if (file_exists(self::$testDatastore)) {
63 unlink(self::$testDatastore);
64 }
65 }
66
67 /**
68 * Allows to test LinkDB's private methods
69 *
70 * @see
71 * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
72 * http://stackoverflow.com/a/2798203
73 */
74 protected static function getMethod($name)
75 {
76 $class = new ReflectionClass('LinkDB');
77 $method = $class->getMethod($name);
78 $method->setAccessible(true);
79 return $method;
80 }
81
82 /**
83 * Instantiate LinkDB objects - logged in user
84 */
85 public function testConstructLoggedIn()
86 {
87 new LinkDB(self::$testDatastore, true, false);
88 $this->assertFileExists(self::$testDatastore);
89 }
90
91 /**
92 * Instantiate LinkDB objects - logged out or public instance
93 */
94 public function testConstructLoggedOut()
95 {
96 new LinkDB(self::$testDatastore, false, false);
97 $this->assertFileExists(self::$testDatastore);
98 }
99
100 /**
101 * Attempt to instantiate a LinkDB whereas the datastore is not writable
102 *
103 * @expectedException IOException
104 * @expectedExceptionMessageRegExp /Error accessing\nnull/
105 */
106 public function testConstructDatastoreNotWriteable()
107 {
108 new LinkDB('null/store.db', false, false);
109 }
110
111 /**
112 * The DB doesn't exist, ensure it is created with dummy content
113 */
114 public function testCheckDBNew()
115 {
116 $linkDB = new LinkDB(self::$testDatastore, false, false);
117 unlink(self::$testDatastore);
118 $this->assertFileNotExists(self::$testDatastore);
119
120 $checkDB = self::getMethod('check');
121 $checkDB->invokeArgs($linkDB, array());
122 $this->assertFileExists(self::$testDatastore);
123
124 // ensure the correct data has been written
125 $this->assertGreaterThan(0, filesize(self::$testDatastore));
126 }
127
128 /**
129 * The DB exists, don't do anything
130 */
131 public function testCheckDBLoad()
132 {
133 $linkDB = new LinkDB(self::$testDatastore, false, false);
134 $datastoreSize = filesize(self::$testDatastore);
135 $this->assertGreaterThan(0, $datastoreSize);
136
137 $checkDB = self::getMethod('check');
138 $checkDB->invokeArgs($linkDB, array());
139
140 // ensure the datastore is left unmodified
141 $this->assertEquals(
142 $datastoreSize,
143 filesize(self::$testDatastore)
144 );
145 }
146
147 /**
148 * Load an empty DB
149 */
150 public function testReadEmptyDB()
151 {
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));
156 }
157
158 /**
159 * Load public links from the DB
160 */
161 public function testReadPublicDB()
162 {
163 $this->assertEquals(
164 self::$refDB->countPublicLinks(),
165 sizeof(self::$publicLinkDB)
166 );
167 }
168
169 /**
170 * Load public and private links from the DB
171 */
172 public function testReadPrivateDB()
173 {
174 $this->assertEquals(
175 self::$refDB->countLinks(),
176 sizeof(self::$privateLinkDB)
177 );
178 }
179
180 /**
181 * Save the links to the DB
182 */
183 public function testSave()
184 {
185 $testDB = new LinkDB(self::$testDatastore, true, false);
186 $dbSize = sizeof($testDB);
187
188 $link = array(
189 'id' => 42,
190 'title'=>'an additional link',
191 'url'=>'http://dum.my',
192 'description'=>'One more',
193 'private'=>0,
194 'created'=> DateTime::createFromFormat('Ymd_His', '20150518_190000'),
195 'tags'=>'unit test'
196 );
197 $testDB[$link['id']] = $link;
198 $testDB->save('tests');
199
200 $testDB = new LinkDB(self::$testDatastore, true, false);
201 $this->assertEquals($dbSize + 1, sizeof($testDB));
202 }
203
204 /**
205 * Count existing links
206 */
207 public function testCount()
208 {
209 $this->assertEquals(
210 self::$refDB->countPublicLinks(),
211 self::$publicLinkDB->count()
212 );
213 $this->assertEquals(
214 self::$refDB->countLinks(),
215 self::$privateLinkDB->count()
216 );
217 }
218
219 /**
220 * Count existing links - public links hidden
221 */
222 public function testCountHiddenPublic()
223 {
224 $linkDB = new LinkDB(self::$testDatastore, false, true);
225
226 $this->assertEquals(
227 0,
228 $linkDB->count()
229 );
230 $this->assertEquals(
231 0,
232 $linkDB->count()
233 );
234 }
235
236 /**
237 * List the days for which links have been posted
238 */
239 public function testDays()
240 {
241 $this->assertEquals(
242 array('20100310', '20121206', '20130614', '20150310'),
243 self::$publicLinkDB->days()
244 );
245
246 $this->assertEquals(
247 array('20100310', '20121206', '20130614', '20141125', '20150310'),
248 self::$privateLinkDB->days()
249 );
250 }
251
252 /**
253 * The URL corresponds to an existing entry in the DB
254 */
255 public function testGetKnownLinkFromURL()
256 {
257 $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
258
259 $this->assertNotEquals(false, $link);
260 $this->assertContains(
261 'A free software media publishing platform',
262 $link['description']
263 );
264 }
265
266 /**
267 * The URL is not in the DB
268 */
269 public function testGetUnknownLinkFromURL()
270 {
271 $this->assertEquals(
272 false,
273 self::$publicLinkDB->getLinkFromUrl('http://dev.null')
274 );
275 }
276
277 /**
278 * Lists all tags
279 */
280 public function testAllTags()
281 {
282 $this->assertEquals(
283 array(
284 'web' => 3,
285 'cartoon' => 2,
286 'gnu' => 2,
287 'dev' => 1,
288 'samba' => 1,
289 'media' => 1,
290 'software' => 1,
291 'stallman' => 1,
292 'free' => 1,
293 '-exclude' => 1,
294 'hashtag' => 2,
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`.
297 'sTuff' => 2,
298 'ut' => 1,
299 ),
300 self::$publicLinkDB->allTags()
301 );
302
303 $this->assertEquals(
304 array(
305 'web' => 4,
306 'cartoon' => 3,
307 'gnu' => 2,
308 'dev' => 2,
309 'samba' => 1,
310 'media' => 1,
311 'software' => 1,
312 'stallman' => 1,
313 'free' => 1,
314 'html' => 1,
315 'w3c' => 1,
316 'css' => 1,
317 'Mercurial' => 1,
318 'sTuff' => 2,
319 '-exclude' => 1,
320 '.hidden' => 1,
321 'hashtag' => 2,
322 'tag1' => 1,
323 'tag2' => 1,
324 'tag3' => 1,
325 'tag4' => 1,
326 'ut' => 1,
327 ),
328 self::$privateLinkDB->allTags()
329 );
330 }
331
332 /**
333 * Test real_url without redirector.
334 */
335 public function testLinkRealUrlWithoutRedirector()
336 {
337 $db = new LinkDB(self::$testDatastore, false, false);
338 foreach($db as $link) {
339 $this->assertEquals($link['url'], $link['real_url']);
340 }
341 }
342
343 /**
344 * Test real_url with redirector.
345 */
346 public function testLinkRealUrlWithRedirector()
347 {
348 $redirector = 'http://redirector.to?';
349 $db = new LinkDB(self::$testDatastore, false, false, $redirector);
350 foreach($db as $link) {
351 $this->assertStringStartsWith($redirector, $link['real_url']);
352 $this->assertNotFalse(strpos($link['real_url'], urlencode('://')));
353 }
354
355 $db = new LinkDB(self::$testDatastore, false, false, $redirector, false);
356 foreach($db as $link) {
357 $this->assertStringStartsWith($redirector, $link['real_url']);
358 $this->assertFalse(strpos($link['real_url'], urlencode('://')));
359 }
360 }
361
362 /**
363 * Test filter with string.
364 */
365 public function testFilterString()
366 {
367 $tags = 'dev cartoon';
368 $request = array('searchtags' => $tags);
369 $this->assertEquals(
370 2,
371 count(self::$privateLinkDB->filterSearch($request, true, false))
372 );
373 }
374
375 /**
376 * Test filter with string.
377 */
378 public function testFilterArray()
379 {
380 $tags = array('dev', 'cartoon');
381 $request = array('searchtags' => $tags);
382 $this->assertEquals(
383 2,
384 count(self::$privateLinkDB->filterSearch($request, true, false))
385 );
386 }
387
388 /**
389 * Test hidden tags feature:
390 * tags starting with a dot '.' are only visible when logged in.
391 */
392 public function testHiddenTags()
393 {
394 $tags = '.hidden';
395 $request = array('searchtags' => $tags);
396 $this->assertEquals(
397 1,
398 count(self::$privateLinkDB->filterSearch($request, true, false))
399 );
400
401 $this->assertEquals(
402 0,
403 count(self::$publicLinkDB->filterSearch($request, true, false))
404 );
405 }
406
407 /**
408 * Test filterHash() with a valid smallhash.
409 */
410 public function testFilterHashValid()
411 {
412 $request = smallHash('20150310_114651');
413 $this->assertEquals(
414 1,
415 count(self::$publicLinkDB->filterHash($request))
416 );
417 $request = smallHash('20150310_114633' . 8);
418 $this->assertEquals(
419 1,
420 count(self::$publicLinkDB->filterHash($request))
421 );
422 }
423
424 /**
425 * Test filterHash() with an invalid smallhash.
426 *
427 * @expectedException LinkNotFoundException
428 */
429 public function testFilterHashInValid1()
430 {
431 $request = 'blabla';
432 self::$publicLinkDB->filterHash($request);
433 }
434
435 /**
436 * Test filterHash() with an empty smallhash.
437 *
438 * @expectedException LinkNotFoundException
439 */
440 public function testFilterHashInValid()
441 {
442 self::$publicLinkDB->filterHash('');
443 }
444
445 /**
446 * Test reorder with asc/desc parameter.
447 */
448 public function testReorderLinksDesc()
449 {
450 self::$publicLinkDB->reorder('ASC');
451 $linkIdToTest = 42;
452 foreach (self::$publicLinkDB as $key => $value) {
453 $this->assertEquals($linkIdToTest, $key);
454 break;
455 }
456 self::$publicLinkDB->reorder('DESC');
457 $linkIdToTest = 41;
458 foreach (self::$publicLinkDB as $key => $value) {
459 $this->assertEquals($linkIdToTest, $key);
460 break;
461 }
462 }
463 }