LinkFilterTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. <?php
  2. require_once 'application/LinkFilter.php';
  3. /**
  4. * Class LinkFilterTest.
  5. */
  6. class LinkFilterTest extends PHPUnit_Framework_TestCase
  7. {
  8. /**
  9. * @var string Test datastore path.
  10. */
  11. protected static $testDatastore = 'sandbox/datastore.php';
  12. /**
  13. * @var LinkFilter instance.
  14. */
  15. protected static $linkFilter;
  16. /**
  17. * @var ReferenceLinkDB instance
  18. */
  19. protected static $refDB;
  20. /**
  21. * @var LinkDB instance
  22. */
  23. protected static $linkDB;
  24. /**
  25. * Instanciate linkFilter with ReferenceLinkDB data.
  26. */
  27. public static function setUpBeforeClass()
  28. {
  29. self::$refDB = new ReferenceLinkDB();
  30. self::$refDB->write(self::$testDatastore);
  31. self::$linkDB = new LinkDB(self::$testDatastore, true, false);
  32. self::$linkFilter = new LinkFilter(self::$linkDB);
  33. }
  34. /**
  35. * Blank filter.
  36. */
  37. public function testFilter()
  38. {
  39. $this->assertEquals(
  40. self::$refDB->countLinks(),
  41. count(self::$linkFilter->filter('', ''))
  42. );
  43. $this->assertEquals(
  44. self::$refDB->countLinks(),
  45. count(self::$linkFilter->filter('', '', 'all'))
  46. );
  47. $this->assertEquals(
  48. self::$refDB->countLinks(),
  49. count(self::$linkFilter->filter('', '', 'randomstr'))
  50. );
  51. // Private only.
  52. $this->assertEquals(
  53. self::$refDB->countPrivateLinks(),
  54. count(self::$linkFilter->filter('', '', false, 'private'))
  55. );
  56. // Public only.
  57. $this->assertEquals(
  58. self::$refDB->countPublicLinks(),
  59. count(self::$linkFilter->filter('', '', false, 'public'))
  60. );
  61. $this->assertEquals(
  62. ReferenceLinkDB::$NB_LINKS_TOTAL,
  63. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, ''))
  64. );
  65. $this->assertEquals(
  66. self::$refDB->countUntaggedLinks(),
  67. count(
  68. self::$linkFilter->filter(
  69. LinkFilter::$FILTER_TAG,
  70. /*$request=*/'',
  71. /*$casesensitive=*/false,
  72. /*$visibility=*/'all',
  73. /*$untaggedonly=*/true
  74. )
  75. )
  76. );
  77. $this->assertEquals(
  78. ReferenceLinkDB::$NB_LINKS_TOTAL,
  79. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, ''))
  80. );
  81. }
  82. /**
  83. * Filter links using a tag
  84. */
  85. public function testFilterOneTag()
  86. {
  87. $this->assertEquals(
  88. 4,
  89. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false))
  90. );
  91. $this->assertEquals(
  92. 4,
  93. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'all'))
  94. );
  95. $this->assertEquals(
  96. 4,
  97. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'default-blabla'))
  98. );
  99. // Private only.
  100. $this->assertEquals(
  101. 1,
  102. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'private'))
  103. );
  104. // Public only.
  105. $this->assertEquals(
  106. 3,
  107. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'public'))
  108. );
  109. }
  110. /**
  111. * Filter links using a tag - case-sensitive
  112. */
  113. public function testFilterCaseSensitiveTag()
  114. {
  115. $this->assertEquals(
  116. 0,
  117. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'mercurial', true))
  118. );
  119. $this->assertEquals(
  120. 1,
  121. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'Mercurial', true))
  122. );
  123. }
  124. /**
  125. * Filter links using a tag combination
  126. */
  127. public function testFilterMultipleTags()
  128. {
  129. $this->assertEquals(
  130. 2,
  131. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'dev cartoon', false))
  132. );
  133. }
  134. /**
  135. * Filter links using a non-existent tag
  136. */
  137. public function testFilterUnknownTag()
  138. {
  139. $this->assertEquals(
  140. 0,
  141. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'null', false))
  142. );
  143. }
  144. /**
  145. * Return links for a given day
  146. */
  147. public function testFilterDay()
  148. {
  149. $this->assertEquals(
  150. 4,
  151. count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20121206'))
  152. );
  153. }
  154. /**
  155. * 404 - day not found
  156. */
  157. public function testFilterUnknownDay()
  158. {
  159. $this->assertEquals(
  160. 0,
  161. count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '19700101'))
  162. );
  163. }
  164. /**
  165. * Use an invalid date format
  166. * @expectedException Exception
  167. * @expectedExceptionMessageRegExp /Invalid date format/
  168. */
  169. public function testFilterInvalidDayWithChars()
  170. {
  171. self::$linkFilter->filter(LinkFilter::$FILTER_DAY, 'Rainy day, dream away');
  172. }
  173. /**
  174. * Use an invalid date format
  175. * @expectedException Exception
  176. * @expectedExceptionMessageRegExp /Invalid date format/
  177. */
  178. public function testFilterInvalidDayDigits()
  179. {
  180. self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20');
  181. }
  182. /**
  183. * Retrieve a link entry with its hash
  184. */
  185. public function testFilterSmallHash()
  186. {
  187. $links = self::$linkFilter->filter(LinkFilter::$FILTER_HASH, 'IuWvgA');
  188. $this->assertEquals(
  189. 1,
  190. count($links)
  191. );
  192. $this->assertEquals(
  193. 'MediaGoblin',
  194. $links[7]['title']
  195. );
  196. }
  197. /**
  198. * No link for this hash
  199. *
  200. * @expectedException LinkNotFoundException
  201. */
  202. public function testFilterUnknownSmallHash()
  203. {
  204. self::$linkFilter->filter(LinkFilter::$FILTER_HASH, 'Iblaah');
  205. }
  206. /**
  207. * Full-text search - no result found.
  208. */
  209. public function testFilterFullTextNoResult()
  210. {
  211. $this->assertEquals(
  212. 0,
  213. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'azertyuiop'))
  214. );
  215. }
  216. /**
  217. * Full-text search - result from a link's URL
  218. */
  219. public function testFilterFullTextURL()
  220. {
  221. $this->assertEquals(
  222. 2,
  223. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars.userfriendly.org'))
  224. );
  225. $this->assertEquals(
  226. 2,
  227. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars org'))
  228. );
  229. }
  230. /**
  231. * Full-text search - result from a link's title only
  232. */
  233. public function testFilterFullTextTitle()
  234. {
  235. // use miscellaneous cases
  236. $this->assertEquals(
  237. 2,
  238. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'userfriendly -'))
  239. );
  240. $this->assertEquals(
  241. 2,
  242. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'UserFriendly -'))
  243. );
  244. $this->assertEquals(
  245. 2,
  246. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'uSeRFrIendlY -'))
  247. );
  248. // use miscellaneous case and offset
  249. $this->assertEquals(
  250. 2,
  251. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'RFrIendL'))
  252. );
  253. }
  254. /**
  255. * Full-text search - result from the link's description only
  256. */
  257. public function testFilterFullTextDescription()
  258. {
  259. $this->assertEquals(
  260. 1,
  261. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'publishing media'))
  262. );
  263. $this->assertEquals(
  264. 1,
  265. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'mercurial w3c'))
  266. );
  267. $this->assertEquals(
  268. 3,
  269. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '"free software"'))
  270. );
  271. }
  272. /**
  273. * Full-text search - result from the link's tags only
  274. */
  275. public function testFilterFullTextTags()
  276. {
  277. $this->assertEquals(
  278. 6,
  279. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web'))
  280. );
  281. $this->assertEquals(
  282. 6,
  283. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'all'))
  284. );
  285. $this->assertEquals(
  286. 6,
  287. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'bla'))
  288. );
  289. // Private only.
  290. $this->assertEquals(
  291. 1,
  292. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'private'))
  293. );
  294. // Public only.
  295. $this->assertEquals(
  296. 5,
  297. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'public'))
  298. );
  299. }
  300. /**
  301. * Full-text search - result set from mixed sources
  302. */
  303. public function testFilterFullTextMixed()
  304. {
  305. $this->assertEquals(
  306. 3,
  307. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'free software'))
  308. );
  309. }
  310. /**
  311. * Full-text search - test exclusion with '-'.
  312. */
  313. public function testExcludeSearch()
  314. {
  315. $this->assertEquals(
  316. 1,
  317. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'free -gnu'))
  318. );
  319. $this->assertEquals(
  320. ReferenceLinkDB::$NB_LINKS_TOTAL - 1,
  321. count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '-revolution'))
  322. );
  323. }
  324. /**
  325. * Full-text search - test AND, exact terms and exclusion combined, across fields.
  326. */
  327. public function testMultiSearch()
  328. {
  329. $this->assertEquals(
  330. 2,
  331. count(self::$linkFilter->filter(
  332. LinkFilter::$FILTER_TEXT,
  333. '"Free Software " stallman "read this" @website stuff'
  334. ))
  335. );
  336. $this->assertEquals(
  337. 1,
  338. count(self::$linkFilter->filter(
  339. LinkFilter::$FILTER_TEXT,
  340. '"free software " stallman "read this" -beard @website stuff'
  341. ))
  342. );
  343. }
  344. /**
  345. * Full-text search - make sure that exact search won't work across fields.
  346. */
  347. public function testSearchExactTermMultiFieldsKo()
  348. {
  349. $this->assertEquals(
  350. 0,
  351. count(self::$linkFilter->filter(
  352. LinkFilter::$FILTER_TEXT,
  353. '"designer naming"'
  354. ))
  355. );
  356. $this->assertEquals(
  357. 0,
  358. count(self::$linkFilter->filter(
  359. LinkFilter::$FILTER_TEXT,
  360. '"designernaming"'
  361. ))
  362. );
  363. }
  364. /**
  365. * Tag search with exclusion.
  366. */
  367. public function testTagFilterWithExclusion()
  368. {
  369. $this->assertEquals(
  370. 1,
  371. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'gnu -free'))
  372. );
  373. $this->assertEquals(
  374. ReferenceLinkDB::$NB_LINKS_TOTAL - 1,
  375. count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free'))
  376. );
  377. }
  378. /**
  379. * Test crossed search (terms + tags).
  380. */
  381. public function testFilterCrossedSearch()
  382. {
  383. $terms = '"Free Software " stallman "read this" @website stuff';
  384. $tags = 'free';
  385. $this->assertEquals(
  386. 1,
  387. count(self::$linkFilter->filter(
  388. LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
  389. array($tags, $terms)
  390. ))
  391. );
  392. $this->assertEquals(
  393. 2,
  394. count(self::$linkFilter->filter(
  395. LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
  396. array('', $terms)
  397. ))
  398. );
  399. $this->assertEquals(
  400. 1,
  401. count(self::$linkFilter->filter(
  402. LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
  403. array(false, 'PSR-2')
  404. ))
  405. );
  406. $this->assertEquals(
  407. 1,
  408. count(self::$linkFilter->filter(
  409. LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
  410. array($tags, '')
  411. ))
  412. );
  413. $this->assertEquals(
  414. ReferenceLinkDB::$NB_LINKS_TOTAL,
  415. count(self::$linkFilter->filter(
  416. LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
  417. ''
  418. ))
  419. );
  420. }
  421. /**
  422. * Filter links by #hashtag.
  423. */
  424. public function testFilterByHashtag()
  425. {
  426. $hashtag = 'hashtag';
  427. $this->assertEquals(
  428. 3,
  429. count(self::$linkFilter->filter(
  430. LinkFilter::$FILTER_TAG,
  431. $hashtag
  432. ))
  433. );
  434. $hashtag = 'private';
  435. $this->assertEquals(
  436. 1,
  437. count(self::$linkFilter->filter(
  438. LinkFilter::$FILTER_TAG,
  439. $hashtag,
  440. false,
  441. 'private'
  442. ))
  443. );
  444. }
  445. }