UtilsTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. /**
  3. * Utilities' tests
  4. */
  5. require_once 'application/Utils.php';
  6. require_once 'application/Languages.php';
  7. /**
  8. * Unitary tests for Shaarli utilities
  9. */
  10. class UtilsTest extends PHPUnit_Framework_TestCase
  11. {
  12. // Log file
  13. protected static $testLogFile = 'tests.log';
  14. // Expected log date format
  15. protected static $dateFormat = 'Y/m/d H:i:s';
  16. /**
  17. * @var string Save the current timezone.
  18. */
  19. protected static $defaultTimeZone;
  20. /**
  21. * Assign reference data
  22. */
  23. public static function setUpBeforeClass()
  24. {
  25. self::$defaultTimeZone = date_default_timezone_get();
  26. // Timezone without DST for test consistency
  27. date_default_timezone_set('Africa/Nairobi');
  28. }
  29. /**
  30. * Reset the timezone
  31. */
  32. public static function tearDownAfterClass()
  33. {
  34. date_default_timezone_set(self::$defaultTimeZone);
  35. }
  36. /**
  37. * Resets test data before each test
  38. */
  39. protected function setUp()
  40. {
  41. if (file_exists(self::$testLogFile)) {
  42. unlink(self::$testLogFile);
  43. }
  44. }
  45. /**
  46. * Returns a list of the elements from the last logged entry
  47. *
  48. * @return list (date, ip address, message)
  49. */
  50. protected function getLastLogEntry()
  51. {
  52. $logFile = file(self::$testLogFile);
  53. return explode(' - ', trim(array_pop($logFile), PHP_EOL));
  54. }
  55. /**
  56. * Log a message to a file - IPv4 client address
  57. */
  58. public function testLogmIp4()
  59. {
  60. $logMessage = 'IPv4 client connected';
  61. logm(self::$testLogFile, '127.0.0.1', $logMessage);
  62. list($date, $ip, $message) = $this->getLastLogEntry();
  63. $this->assertInstanceOf(
  64. 'DateTime',
  65. DateTime::createFromFormat(self::$dateFormat, $date)
  66. );
  67. $this->assertTrue(
  68. filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false
  69. );
  70. $this->assertEquals($logMessage, $message);
  71. }
  72. /**
  73. * Log a message to a file - IPv6 client address
  74. */
  75. public function testLogmIp6()
  76. {
  77. $logMessage = 'IPv6 client connected';
  78. logm(self::$testLogFile, '2001:db8::ff00:42:8329', $logMessage);
  79. list($date, $ip, $message) = $this->getLastLogEntry();
  80. $this->assertInstanceOf(
  81. 'DateTime',
  82. DateTime::createFromFormat(self::$dateFormat, $date)
  83. );
  84. $this->assertTrue(
  85. filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false
  86. );
  87. $this->assertEquals($logMessage, $message);
  88. }
  89. /**
  90. * Represent a link by its hash
  91. */
  92. public function testSmallHash()
  93. {
  94. $this->assertEquals('CyAAJw', smallHash('http://test.io'));
  95. $this->assertEquals(6, strlen(smallHash('https://github.com')));
  96. }
  97. /**
  98. * Look for a substring at the beginning of a string
  99. */
  100. public function testStartsWithCaseInsensitive()
  101. {
  102. $this->assertTrue(startsWith('Lorem ipsum', 'lorem', false));
  103. $this->assertTrue(startsWith('Lorem ipsum', 'LoReM i', false));
  104. }
  105. /**
  106. * Look for a substring at the beginning of a string (case-sensitive)
  107. */
  108. public function testStartsWithCaseSensitive()
  109. {
  110. $this->assertTrue(startsWith('Lorem ipsum', 'Lorem', true));
  111. $this->assertFalse(startsWith('Lorem ipsum', 'lorem', true));
  112. $this->assertFalse(startsWith('Lorem ipsum', 'LoReM i', true));
  113. }
  114. /**
  115. * Look for a substring at the beginning of a string (Unicode)
  116. */
  117. public function testStartsWithSpecialChars()
  118. {
  119. $this->assertTrue(startsWith('å!ùµ', 'å!', false));
  120. $this->assertTrue(startsWith('µ$åù', 'µ$', true));
  121. }
  122. /**
  123. * Look for a substring at the end of a string
  124. */
  125. public function testEndsWithCaseInsensitive()
  126. {
  127. $this->assertTrue(endsWith('Lorem ipsum', 'ipsum', false));
  128. $this->assertTrue(endsWith('Lorem ipsum', 'm IpsUM', false));
  129. }
  130. /**
  131. * Look for a substring at the end of a string (case-sensitive)
  132. */
  133. public function testEndsWithCaseSensitive()
  134. {
  135. $this->assertTrue(endsWith('lorem Ipsum', 'Ipsum', true));
  136. $this->assertFalse(endsWith('lorem Ipsum', 'ipsum', true));
  137. $this->assertFalse(endsWith('lorem Ipsum', 'M IPsuM', true));
  138. }
  139. /**
  140. * Look for a substring at the end of a string (Unicode)
  141. */
  142. public function testEndsWithSpecialChars()
  143. {
  144. $this->assertTrue(endsWith('å!ùµ', 'ùµ', false));
  145. $this->assertTrue(endsWith('µ$åù', 'åù', true));
  146. }
  147. /**
  148. * Check valid date strings, according to a DateTime format
  149. */
  150. public function testCheckValidDateFormat()
  151. {
  152. $this->assertTrue(checkDateFormat('Ymd', '20150627'));
  153. $this->assertTrue(checkDateFormat('Y-m-d', '2015-06-27'));
  154. }
  155. /**
  156. * Check erroneous date strings, according to a DateTime format
  157. */
  158. public function testCheckInvalidDateFormat()
  159. {
  160. $this->assertFalse(checkDateFormat('Ymd', '2015'));
  161. $this->assertFalse(checkDateFormat('Y-m-d', '2015-06'));
  162. $this->assertFalse(checkDateFormat('Ymd', 'DeLorean'));
  163. }
  164. /**
  165. * Test generate location with valid data.
  166. */
  167. public function testGenerateLocation()
  168. {
  169. $ref = 'http://localhost/?test';
  170. $this->assertEquals($ref, generateLocation($ref, 'localhost'));
  171. $ref = 'http://localhost:8080/?test';
  172. $this->assertEquals($ref, generateLocation($ref, 'localhost:8080'));
  173. $ref = '?localreferer#hash';
  174. $this->assertEquals($ref, generateLocation($ref, 'localhost:8080'));
  175. }
  176. /**
  177. * Test generate location - anti loop.
  178. */
  179. public function testGenerateLocationLoop()
  180. {
  181. $ref = 'http://localhost/?test';
  182. $this->assertEquals('?', generateLocation($ref, 'localhost', array('test')));
  183. }
  184. /**
  185. * Test generate location - from other domain.
  186. */
  187. public function testGenerateLocationOut()
  188. {
  189. $ref = 'http://somewebsite.com/?test';
  190. $this->assertEquals('?', generateLocation($ref, 'localhost'));
  191. }
  192. /**
  193. * Test generateSecretApi.
  194. */
  195. public function testGenerateSecretApi()
  196. {
  197. $this->assertEquals(12, strlen(generate_api_secret('foo', 'bar')));
  198. }
  199. /**
  200. * Test generateSecretApi with invalid parameters.
  201. */
  202. public function testGenerateSecretApiInvalid()
  203. {
  204. $this->assertFalse(generate_api_secret('', ''));
  205. $this->assertFalse(generate_api_secret(false, false));
  206. }
  207. /**
  208. * Test normalize_spaces.
  209. */
  210. public function testNormalizeSpace()
  211. {
  212. $str = ' foo bar is important ';
  213. $this->assertEquals('foo bar is important', normalize_spaces($str));
  214. $this->assertEquals('foo', normalize_spaces('foo'));
  215. $this->assertEquals('', normalize_spaces(''));
  216. $this->assertEquals(null, normalize_spaces(null));
  217. }
  218. /**
  219. * Test arrays_combine
  220. */
  221. public function testCartesianProductGenerator()
  222. {
  223. $arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']];
  224. $expected = [
  225. ['ab', 'ef', 'ij', 'm'],
  226. ['ab', 'ef', 'kl', 'm'],
  227. ['ab', 'gh', 'ij', 'm'],
  228. ['ab', 'gh', 'kl', 'm'],
  229. ['cd', 'ef', 'ij', 'm'],
  230. ['cd', 'ef', 'kl', 'm'],
  231. ['cd', 'gh', 'ij', 'm'],
  232. ['cd', 'gh', 'kl', 'm'],
  233. ];
  234. $this->assertEquals($expected, iterator_to_array(cartesian_product_generator($arr)));
  235. }
  236. /**
  237. * Test date_format() with invalid parameter.
  238. */
  239. public function testDateFormatInvalid()
  240. {
  241. $this->assertFalse(format_date([]));
  242. $this->assertFalse(format_date(null));
  243. }
  244. /**
  245. * Test is_integer_mixed with valid values
  246. */
  247. public function testIsIntegerMixedValid()
  248. {
  249. $this->assertTrue(is_integer_mixed(12));
  250. $this->assertTrue(is_integer_mixed('12'));
  251. $this->assertTrue(is_integer_mixed(-12));
  252. $this->assertTrue(is_integer_mixed('-12'));
  253. $this->assertTrue(is_integer_mixed(0));
  254. $this->assertTrue(is_integer_mixed('0'));
  255. $this->assertTrue(is_integer_mixed(0x0a));
  256. }
  257. /**
  258. * Test is_integer_mixed with invalid values
  259. */
  260. public function testIsIntegerMixedInvalid()
  261. {
  262. $this->assertFalse(is_integer_mixed(true));
  263. $this->assertFalse(is_integer_mixed(false));
  264. $this->assertFalse(is_integer_mixed([]));
  265. $this->assertFalse(is_integer_mixed(['test']));
  266. $this->assertFalse(is_integer_mixed([12]));
  267. $this->assertFalse(is_integer_mixed(new DateTime()));
  268. $this->assertFalse(is_integer_mixed('0x0a'));
  269. $this->assertFalse(is_integer_mixed('12k'));
  270. $this->assertFalse(is_integer_mixed('k12'));
  271. $this->assertFalse(is_integer_mixed(''));
  272. }
  273. /**
  274. * Test return_bytes
  275. */
  276. public function testReturnBytes()
  277. {
  278. $this->assertEquals(2 * 1024, return_bytes('2k'));
  279. $this->assertEquals(2 * 1024, return_bytes('2K'));
  280. $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2m'));
  281. $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2M'));
  282. $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2g'));
  283. $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2G'));
  284. $this->assertEquals(374, return_bytes('374'));
  285. $this->assertEquals(374, return_bytes(374));
  286. $this->assertEquals(0, return_bytes('0'));
  287. $this->assertEquals(0, return_bytes(0));
  288. $this->assertEquals(-1, return_bytes('-1'));
  289. $this->assertEquals(-1, return_bytes(-1));
  290. $this->assertEquals('', return_bytes(''));
  291. }
  292. /**
  293. * Test human_bytes
  294. */
  295. public function testHumanBytes()
  296. {
  297. $this->assertEquals('2'. t('kiB'), human_bytes(2 * 1024));
  298. $this->assertEquals('2'. t('kiB'), human_bytes(strval(2 * 1024)));
  299. $this->assertEquals('2'. t('MiB'), human_bytes(2 * (pow(1024, 2))));
  300. $this->assertEquals('2'. t('MiB'), human_bytes(strval(2 * (pow(1024, 2)))));
  301. $this->assertEquals('2'. t('GiB'), human_bytes(2 * (pow(1024, 3))));
  302. $this->assertEquals('2'. t('GiB'), human_bytes(strval(2 * (pow(1024, 3)))));
  303. $this->assertEquals('374'. t('B'), human_bytes(374));
  304. $this->assertEquals('374'. t('B'), human_bytes('374'));
  305. $this->assertEquals('232'. t('kiB'), human_bytes(237481));
  306. $this->assertEquals(t('Unlimited'), human_bytes('0'));
  307. $this->assertEquals(t('Unlimited'), human_bytes(0));
  308. $this->assertEquals(t('Setting not set'), human_bytes(''));
  309. }
  310. /**
  311. * Test get_max_upload_size with formatting
  312. */
  313. public function testGetMaxUploadSize()
  314. {
  315. $this->assertEquals('1'. t('MiB'), get_max_upload_size(2097152, '1024k'));
  316. $this->assertEquals('1'. t('MiB'), get_max_upload_size('1m', '2m'));
  317. $this->assertEquals('100'. t('B'), get_max_upload_size(100, 100));
  318. }
  319. /**
  320. * Test get_max_upload_size without formatting
  321. */
  322. public function testGetMaxUploadSizeRaw()
  323. {
  324. $this->assertEquals('1048576', get_max_upload_size(2097152, '1024k', false));
  325. $this->assertEquals('1048576', get_max_upload_size('1m', '2m', false));
  326. $this->assertEquals('100', get_max_upload_size(100, 100, false));
  327. }
  328. /**
  329. * Test alphabetical_sort by value, not reversed, with php-intl.
  330. */
  331. public function testAlphabeticalSortByValue()
  332. {
  333. $arr = [
  334. 'zZz',
  335. 'éee',
  336. 'éae',
  337. 'eee',
  338. 'A',
  339. 'a',
  340. 'zzz',
  341. ];
  342. $expected = [
  343. 'a',
  344. 'A',
  345. 'éae',
  346. 'eee',
  347. 'éee',
  348. 'zzz',
  349. 'zZz',
  350. ];
  351. alphabetical_sort($arr);
  352. $this->assertEquals($expected, $arr);
  353. }
  354. /**
  355. * Test alphabetical_sort by value, reversed, with php-intl.
  356. */
  357. public function testAlphabeticalSortByValueReversed()
  358. {
  359. $arr = [
  360. 'zZz',
  361. 'éee',
  362. 'éae',
  363. 'eee',
  364. 'A',
  365. 'a',
  366. 'zzz',
  367. ];
  368. $expected = [
  369. 'zZz',
  370. 'zzz',
  371. 'éee',
  372. 'eee',
  373. 'éae',
  374. 'A',
  375. 'a',
  376. ];
  377. alphabetical_sort($arr, true);
  378. $this->assertEquals($expected, $arr);
  379. }
  380. /**
  381. * Test alphabetical_sort by keys, not reversed, with php-intl.
  382. */
  383. public function testAlphabeticalSortByKeys()
  384. {
  385. $arr = [
  386. 'zZz' => true,
  387. 'éee' => true,
  388. 'éae' => true,
  389. 'eee' => true,
  390. 'A' => true,
  391. 'a' => true,
  392. 'zzz' => true,
  393. ];
  394. $expected = [
  395. 'a' => true,
  396. 'A' => true,
  397. 'éae' => true,
  398. 'eee' => true,
  399. 'éee' => true,
  400. 'zzz' => true,
  401. 'zZz' => true,
  402. ];
  403. alphabetical_sort($arr, true, true);
  404. $this->assertEquals($expected, $arr);
  405. }
  406. /**
  407. * Test alphabetical_sort by keys, reversed, with php-intl.
  408. */
  409. public function testAlphabeticalSortByKeysReversed()
  410. {
  411. $arr = [
  412. 'zZz' => true,
  413. 'éee' => true,
  414. 'éae' => true,
  415. 'eee' => true,
  416. 'A' => true,
  417. 'a' => true,
  418. 'zzz' => true,
  419. ];
  420. $expected = [
  421. 'zZz' => true,
  422. 'zzz' => true,
  423. 'éee' => true,
  424. 'eee' => true,
  425. 'éae' => true,
  426. 'A' => true,
  427. 'a' => true,
  428. ];
  429. alphabetical_sort($arr, true, true);
  430. $this->assertEquals($expected, $arr);
  431. }
  432. }