PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/Jyxo/StringUtilTest.php

http://github.com/jyxo/php
PHP | 264 lines | 153 code | 34 blank | 77 comment | 5 complexity | 7b8089818b71523dff18a937a155bb12 MD5 | raw file
  1. <?php declare(strict_types = 1);
  2. /**
  3. * Jyxo PHP Library
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file license.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * https://github.com/jyxo/php/blob/master/license.txt
  11. */
  12. namespace Jyxo;
  13. use PHPUnit\Framework\TestCase;
  14. use function count;
  15. use function html_entity_decode;
  16. use function mb_strlen;
  17. use function preg_quote;
  18. use function preg_split;
  19. use function sprintf;
  20. use function strlen;
  21. use function strtr;
  22. use const ENT_COMPAT;
  23. use const ENT_NOQUOTES;
  24. use const ENT_QUOTES;
  25. /**
  26. * String processing test.
  27. *
  28. * @copyright Copyright (c) 2005-2011 Jyxo, s.r.o.
  29. * @license https://github.com/jyxo/php/blob/master/license.txt
  30. * @author Jakub Tománek
  31. * @author Jaroslav Hanslík
  32. * @author Ondřej Nešpor
  33. */
  34. class StringUtilTest extends TestCase
  35. {
  36. /**
  37. * Tests string trimming.
  38. */
  39. public function testCut(): void
  40. {
  41. // Trim on space
  42. $this->assertEquals('žluťoučký kůň...', $this->checkStringCut('žluťoučký kůň příšerně úpěl ďábelské ódy'));
  43. // Trim on period
  44. $this->assertEquals('žluťoučký kůň...', $this->checkStringCut('žluťoučký kůň.Příšerně úpěl ďábelské ódy'));
  45. // Trim on period and space
  46. $this->assertEquals('žluťoučký kůň...', $this->checkStringCut('žluťoučký kůň. Příšerně úpěl ďábelské ódy'));
  47. // Trim on comma
  48. $this->assertEquals('žluťoučký kůň...', $this->checkStringCut('žluťoučký kůň,příšerně úpěl ďábelské ódy'));
  49. // Trim on semicolon
  50. $this->assertEquals('žluťoučký kůň...', $this->checkStringCut('žluťoučký kůň;příšerně úpěl ďábelské ódy'));
  51. // Word boundary just at the end
  52. $this->assertEquals('abcdefghijklm...', $this->checkStringCut('abcdefghijklmno pqrst'));
  53. $this->assertEquals('abcdefghijklm...', $this->checkStringCut('abcdefghijklmn opqrst'));
  54. $this->assertEquals('abcdefghijklm...', $this->checkStringCut('abcdefghijklm nopqrst'));
  55. // No word boundaries
  56. $this->assertEquals('abcdefghijklm...', $this->checkStringCut('abcdefghijklmnopqrstuvwxyz'));
  57. // Etc as HTML entity
  58. $this->assertEquals(
  59. 'žluťoučký kůň&hellip;',
  60. $this->checkStringCut('žluťoučký kůň příšerně úpěl ďábelské ódy', 14, '&hellip;')
  61. );
  62. // Short
  63. $shorty = '1234567890';
  64. $this->assertEquals($shorty, $this->checkStringCut($shorty));
  65. $this->assertEquals('12...', $this->checkStringCut($shorty, 5));
  66. }
  67. /**
  68. * Tests word trimming.
  69. */
  70. public function testCutWords(): void
  71. {
  72. $this->assertEquals(
  73. 'žluťoučký kůň příšerně úpěl ďábelské ódy',
  74. $this->checkStringWordCut('žluťoučký kůň příšerně úpěl ďábelské ódy', 10)
  75. );
  76. $this->assertEquals(
  77. 'žluťo... kůň příšerně úpěl ďábelské ódy',
  78. $this->checkStringWordCut('žluťoučký kůň příšerně úpěl ďábelské ódy', 8)
  79. );
  80. $this->assertEquals(
  81. 'žl... kůň př... úpěl ďá... ódy',
  82. $this->checkStringWordCut('žluťoučký kůň příšerně úpěl ďábelské ódy', 5)
  83. );
  84. // Word boundary just at the end
  85. $this->assertEquals('abcdefghijk... pqrst', $this->checkStringWordCut('abcdefghijklmno pqrst', 14));
  86. $this->assertEquals('abcdefghijklmn opqrst', $this->checkStringWordCut('abcdefghijklmn opqrst', 14));
  87. $this->assertEquals('abcdefghijklm nopqrst', $this->checkStringWordCut('abcdefghijklm nopqrst', 14));
  88. // Short
  89. $shorty = '12345678';
  90. $this->assertEquals($shorty, $this->checkStringWordCut($shorty));
  91. $this->assertEquals('12...', $this->checkStringWordCut($shorty, 5));
  92. }
  93. /**
  94. * Test the crc generator.
  95. */
  96. public function testCrc(): void
  97. {
  98. $this->assertSame(-662733300, StringUtil::crc('test'));
  99. $this->assertSame(-33591962, StringUtil::crc('žluťoučký kůň příšerně úpěl ďábelské ódy'));
  100. }
  101. /**
  102. * Tests the random string generator.
  103. */
  104. public function testRandom(): void
  105. {
  106. for ($i = 1; $i <= 32; $i++) {
  107. $random = StringUtil::random($i);
  108. $this->assertEquals($i, strlen($random));
  109. $this->assertMatchesRegularExpression('~^[a-z0-9]+$~i', $random);
  110. }
  111. }
  112. /**
  113. * Tests line ending conversions.
  114. */
  115. public function testFixLineEnding(): void
  116. {
  117. $tests = [
  118. "test\r\nžlutý\r\n",
  119. "test\ržlutý\r",
  120. "test\r\nžlutý\r",
  121. "test\nžlutý\r",
  122. "test\nžlutý\r\n",
  123. ];
  124. // No line ending given
  125. foreach ($tests as $test) {
  126. $this->assertEquals("test\nžlutý\n", StringUtil::fixLineEnding($test));
  127. $this->assertNotEquals($test, StringUtil::fixLineEnding($test));
  128. }
  129. $this->assertEquals("test\nžlutý\n", StringUtil::fixLineEnding("test\nžlutý\n"));
  130. // Line ending given
  131. foreach ($tests as $test) {
  132. foreach (["\n", "\r", "\r\n"] as $ending) {
  133. $this->assertEquals(sprintf('test%1$sžlutý%1$s', $ending), StringUtil::fixLineEnding($test, $ending));
  134. $this->assertNotEquals("test\nžlutý\r\n", StringUtil::fixLineEnding($test, $ending));
  135. }
  136. }
  137. }
  138. /**
  139. * Tests email address obfuscation.
  140. */
  141. public function testObfuscateEmail(): void
  142. {
  143. $email = 'example@example.com';
  144. $this->assertEquals('example&#64;example.com', StringUtil::obfuscateEmail($email));
  145. $this->assertEquals('example&#64;<!---->example.com', StringUtil::obfuscateEmail($email, true));
  146. }
  147. /**
  148. * Tests first letter lowercase.
  149. */
  150. public function testLcfirst(): void
  151. {
  152. $this->assertEquals('žlutý kůň', StringUtil::lcfirst('Žlutý kůň'));
  153. $this->assertEquals('žlutý kůň', StringUtil::lcfirst('žlutý kůň'));
  154. }
  155. /**
  156. * Tests special HTML characters escaping.
  157. */
  158. public function testEscape(): void
  159. {
  160. $this->assertEquals('test &amp; test', StringUtil::escape('test & test'));
  161. $this->assertEquals('&quot;test&quot; &amp; &#039;test&#039;', StringUtil::escape('"test" & \'test\''));
  162. $this->assertEquals('&quot;test&quot; &amp; \'test\'', StringUtil::escape('"test" & \'test\'', ENT_COMPAT));
  163. $this->assertEquals('"test" &amp; \'test\'', StringUtil::escape('"test" & \'test\'', ENT_NOQUOTES));
  164. $this->assertEquals('test &amp; test', StringUtil::escape('test &amp; test'));
  165. $this->assertEquals('test &amp;amp; test', StringUtil::escape('test &amp; test', ENT_QUOTES, true));
  166. }
  167. /**
  168. * Tests byte size conversion.
  169. */
  170. public function testFormatBytes(): void
  171. {
  172. $this->assertEquals('11 B', StringUtil::formatBytes(10.5));
  173. $this->assertEquals('11 B', StringUtil::formatBytes(10.5, '.'));
  174. $this->assertEquals('11 B', StringUtil::formatBytes(10.5, '.', ','));
  175. $this->assertEquals('1,0 GB', StringUtil::formatBytes(1073741824));
  176. $this->assertEquals('1.0 GB', StringUtil::formatBytes(1073741824, '.'));
  177. $this->assertEquals('10,240.0 PB', StringUtil::formatBytes(11805916207174113034240, '.', ','));
  178. }
  179. /**
  180. * Checks one string.
  181. *
  182. * @param string $string Input string
  183. * @param int $max Max length
  184. * @param string $etc "Etc" definition
  185. * @return string
  186. */
  187. private function checkStringWordCut(string $string, int $max = 8, string $etc = '...'): string
  188. {
  189. $cut = StringUtil::cutWords($string, $max, $etc);
  190. // &hellip; has length of 1
  191. $cut2 = strtr(html_entity_decode($cut, ENT_COMPAT, 'utf-8'), ['&hellip;' => '.']);
  192. $words = preg_split('~\\s+~', $string);
  193. $trimmedWords = preg_split('~\\s+~', $cut2);
  194. $this->assertEquals(count($trimmedWords), count($words));
  195. foreach ($words as $i => $word) {
  196. if (mb_strlen($word, 'utf-8') <= $max) {
  197. $this->assertEquals($word, $trimmedWords[$i], 'Word trimmed even though it was short enough');
  198. } else {
  199. $this->assertLessThanOrEqual($max, mb_strlen($trimmedWords[$i], 'utf-8'));
  200. $this->assertMatchesRegularExpression(
  201. '~' . preg_quote($etc === '&hellip;' ? '.' : $etc) . '$~',
  202. $trimmedWords[$i],
  203. 'String does not end with ' . $etc
  204. );
  205. }
  206. }
  207. return $cut;
  208. }
  209. /**
  210. * Checks one string.
  211. *
  212. * @param string $string Input string
  213. * @param int $max Max length
  214. * @param string $etc "Etc" definition
  215. * @return string
  216. */
  217. private function checkStringCut(string $string, int $max = 16, string $etc = '...'): string
  218. {
  219. $cut = StringUtil::cut($string, $max, $etc);
  220. // &hellip; has length of 1
  221. $cutLength = mb_strlen(strtr(html_entity_decode($cut, ENT_COMPAT, 'utf-8'), ['&hellip;' => '.']));
  222. $this->assertLessThanOrEqual($max, $cutLength, 'String is longer');
  223. if (mb_strlen($string, 'utf-8') <= $max) {
  224. $this->assertEquals($string, $cut, 'String trimmed even though it was short enough');
  225. } else {
  226. $this->assertMatchesRegularExpression('~' . preg_quote($etc) . '$~', $cut, 'String does not end with ' . $etc);
  227. }
  228. return $cut;
  229. }
  230. }