FunctionsTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Core;
  17. use Cake\Core\Configure;
  18. use Cake\Http\Response;
  19. use Cake\TestSuite\TestCase;
  20. use stdClass;
  21. use function Cake\Core\deprecationWarning;
  22. use function Cake\Core\env;
  23. use function Cake\Core\getTypeName;
  24. use function Cake\Core\h;
  25. use function Cake\Core\namespaceSplit;
  26. use function Cake\Core\pluginSplit;
  27. use function Cake\Core\triggerWarning;
  28. /**
  29. * Test cases for functions in Core\functions.php
  30. */
  31. class FunctionsTest extends TestCase
  32. {
  33. /**
  34. * Test cases for env()
  35. */
  36. public function testEnv(): void
  37. {
  38. $_ENV['DOES_NOT_EXIST'] = null;
  39. $this->assertNull(env('DOES_NOT_EXIST'));
  40. $this->assertSame('default', env('DOES_NOT_EXIST', 'default'));
  41. $_ENV['DOES_EXIST'] = 'some value';
  42. $this->assertSame('some value', env('DOES_EXIST'));
  43. $this->assertSame('some value', env('DOES_EXIST', 'default'));
  44. $_ENV['EMPTY_VALUE'] = '';
  45. $this->assertSame('', env('EMPTY_VALUE'));
  46. $this->assertSame('', env('EMPTY_VALUE', 'default'));
  47. $_ENV['ZERO'] = '0';
  48. $this->assertSame('0', env('ZERO'));
  49. $this->assertSame('0', env('ZERO', '1'));
  50. $this->assertSame('', env('DOCUMENT_ROOT'));
  51. $this->assertStringContainsString('phpunit', env('PHP_SELF'));
  52. }
  53. public function testEnv2(): void
  54. {
  55. $this->skipIf(!function_exists('ini_get') || ini_get('safe_mode') === '1', 'Safe mode is on.');
  56. $server = $_SERVER;
  57. $env = $_ENV;
  58. $_SERVER = $_ENV = [];
  59. $_SERVER['SCRIPT_NAME'] = '/a/test/test.php';
  60. $this->assertSame(env('SCRIPT_NAME'), '/a/test/test.php');
  61. $_SERVER = $_ENV = [];
  62. $_ENV['CGI_MODE'] = 'BINARY';
  63. $_ENV['SCRIPT_URL'] = '/a/test/test.php';
  64. $this->assertSame(env('SCRIPT_NAME'), '/a/test/test.php');
  65. $_SERVER = $_ENV = [];
  66. $this->assertFalse(env('HTTPS'));
  67. $_SERVER['HTTPS'] = 'on';
  68. $this->assertTrue(env('HTTPS'));
  69. $_SERVER['HTTPS'] = '1';
  70. $this->assertTrue(env('HTTPS'));
  71. $_SERVER['HTTPS'] = 'I am not empty';
  72. $this->assertTrue(env('HTTPS'));
  73. $_SERVER['HTTPS'] = 1;
  74. $this->assertTrue(env('HTTPS'));
  75. $_SERVER['HTTPS'] = 'off';
  76. $this->assertFalse(env('HTTPS'));
  77. $_SERVER['HTTPS'] = false;
  78. $this->assertFalse(env('HTTPS'));
  79. $_SERVER['HTTPS'] = '';
  80. $this->assertFalse(env('HTTPS'));
  81. $_SERVER = [];
  82. $_ENV['SCRIPT_URI'] = 'https://domain.test/a/test.php';
  83. $this->assertTrue(env('HTTPS'));
  84. $_ENV['SCRIPT_URI'] = 'http://domain.test/a/test.php';
  85. $this->assertFalse(env('HTTPS'));
  86. $_SERVER = $_ENV = [];
  87. $this->assertNull(env('TEST_ME'));
  88. $_ENV['TEST_ME'] = 'a';
  89. $this->assertSame(env('TEST_ME'), 'a');
  90. $_SERVER['TEST_ME'] = 'b';
  91. $this->assertSame(env('TEST_ME'), 'b');
  92. unset($_ENV['TEST_ME']);
  93. $this->assertSame(env('TEST_ME'), 'b');
  94. $_SERVER = $server;
  95. $_ENV = $env;
  96. }
  97. /**
  98. * Test cases for h()
  99. *
  100. * @dataProvider hInputProvider
  101. * @param mixed $value
  102. * @param mixed $expected
  103. */
  104. public function testH($value, $expected): void
  105. {
  106. $result = h($value);
  107. $this->assertSame($expected, $result);
  108. }
  109. public function hInputProvider(): array
  110. {
  111. return [
  112. ['i am clean', 'i am clean'],
  113. ['i "need" escaping', 'i &quot;need&quot; escaping'],
  114. [null, null],
  115. [1, 1],
  116. [1.1, 1.1],
  117. [new stdClass(), '(object)stdClass'],
  118. [new Response(), ''],
  119. [['clean', '"clean-me'], ['clean', '&quot;clean-me']],
  120. ];
  121. }
  122. public function testH2(): void
  123. {
  124. $string = '<foo>';
  125. $result = h($string);
  126. $this->assertSame('&lt;foo&gt;', $result);
  127. $in = ['this & that', '<p>Which one</p>'];
  128. $result = h($in);
  129. $expected = ['this &amp; that', '&lt;p&gt;Which one&lt;/p&gt;'];
  130. $this->assertSame($expected, $result);
  131. $string = '<foo> & &nbsp;';
  132. $result = h($string);
  133. $this->assertSame('&lt;foo&gt; &amp; &amp;nbsp;', $result);
  134. $string = '<foo> & &nbsp;';
  135. $result = h($string, false);
  136. $this->assertSame('&lt;foo&gt; &amp; &nbsp;', $result);
  137. $string = "An invalid\x80string";
  138. $result = h($string);
  139. $this->assertStringContainsString('string', $result);
  140. $arr = ['<foo>', '&nbsp;'];
  141. $result = h($arr);
  142. $expected = [
  143. '&lt;foo&gt;',
  144. '&amp;nbsp;',
  145. ];
  146. $this->assertSame($expected, $result);
  147. $arr = ['<foo>', '&nbsp;'];
  148. $result = h($arr, false);
  149. $expected = [
  150. '&lt;foo&gt;',
  151. '&nbsp;',
  152. ];
  153. $this->assertSame($expected, $result);
  154. $arr = ['f' => '<foo>', 'n' => '&nbsp;'];
  155. $result = h($arr, false);
  156. $expected = [
  157. 'f' => '&lt;foo&gt;',
  158. 'n' => '&nbsp;',
  159. ];
  160. $this->assertSame($expected, $result);
  161. $arr = ['invalid' => "\x99An invalid\x80string", 'good' => 'Good string'];
  162. $result = h($arr);
  163. $this->assertStringContainsString('An invalid', $result['invalid']);
  164. $this->assertSame('Good string', $result['good']);
  165. // Test that boolean values are not converted to strings
  166. $result = h(false);
  167. $this->assertFalse($result);
  168. $arr = ['foo' => false, 'bar' => true];
  169. $result = h($arr);
  170. $this->assertFalse($result['foo']);
  171. $this->assertTrue($result['bar']);
  172. $obj = new stdClass();
  173. $result = h($obj);
  174. $this->assertSame('(object)stdClass', $result);
  175. $obj = new Response(['body' => 'Body content']);
  176. $result = h($obj);
  177. $this->assertSame('Body content', $result);
  178. }
  179. /**
  180. * Test splitting plugin names.
  181. */
  182. public function testPluginSplit(): void
  183. {
  184. $result = pluginSplit('Something.else');
  185. $this->assertSame(['Something', 'else'], $result);
  186. $result = pluginSplit('Something.else.more.dots');
  187. $this->assertSame(['Something', 'else.more.dots'], $result);
  188. $result = pluginSplit('Somethingelse');
  189. $this->assertSame([null, 'Somethingelse'], $result);
  190. $result = pluginSplit('Something.else', true);
  191. $this->assertSame(['Something.', 'else'], $result);
  192. $result = pluginSplit('Something.else.more.dots', true);
  193. $this->assertSame(['Something.', 'else.more.dots'], $result);
  194. $result = pluginSplit('Post', false, 'Blog');
  195. $this->assertSame(['Blog', 'Post'], $result);
  196. $result = pluginSplit('Blog.Post', false, 'Ultimate');
  197. $this->assertSame(['Blog', 'Post'], $result);
  198. }
  199. /**
  200. * test namespaceSplit
  201. */
  202. public function testNamespaceSplit(): void
  203. {
  204. $result = namespaceSplit('Something');
  205. $this->assertSame(['', 'Something'], $result);
  206. $result = namespaceSplit('\Something');
  207. $this->assertSame(['', 'Something'], $result);
  208. $result = namespaceSplit('Cake\Something');
  209. $this->assertSame(['Cake', 'Something'], $result);
  210. $result = namespaceSplit('Cake\Test\Something');
  211. $this->assertSame(['Cake\Test', 'Something'], $result);
  212. }
  213. /**
  214. * Test error messages coming out when deprecated level is on, manually setting the stack frame
  215. */
  216. public function testDeprecationWarningEnabled(): void
  217. {
  218. $error = $this->captureError(E_ALL, function (): void {
  219. deprecationWarning('This is going away', 2);
  220. });
  221. $this->assertMatchesRegularExpression(
  222. '/This is going away\n(.*?)[\/\\\]FunctionsTest.php, line\: \d+/',
  223. $error->getMessage()
  224. );
  225. }
  226. /**
  227. * Test error messages coming out when deprecated level is on, not setting the stack frame manually
  228. */
  229. public function testDeprecationWarningEnabledDefaultFrame(): void
  230. {
  231. $error = $this->captureError(E_ALL, function (): void {
  232. deprecationWarning('This is going away too');
  233. });
  234. $this->assertMatchesRegularExpression(
  235. '/This is going away too\n(.*?)[\/\\\]TestCase.php, line\: \d+/',
  236. $error->getMessage()
  237. );
  238. }
  239. /**
  240. * Test no error when deprecation matches ignore paths.
  241. */
  242. public function testDeprecationWarningPathDisabled(): void
  243. {
  244. $this->expectNotToPerformAssertions();
  245. Configure::write('Error.ignoredDeprecationPaths', ['src/TestSuite/*']);
  246. $this->withErrorReporting(E_ALL, function (): void {
  247. deprecationWarning('This will be gone soon');
  248. });
  249. }
  250. /**
  251. * Test no error when deprecated level is off.
  252. */
  253. public function testDeprecationWarningLevelDisabled(): void
  254. {
  255. $this->expectNotToPerformAssertions();
  256. $this->withErrorReporting(E_ALL ^ E_USER_DEPRECATED, function (): void {
  257. deprecationWarning('This is leaving');
  258. });
  259. }
  260. /**
  261. * Test error messages coming out when warning level is on.
  262. */
  263. public function testTriggerWarningEnabled(): void
  264. {
  265. $error = $this->captureError(E_ALL, function (): void {
  266. triggerWarning('This will be gone one day ' . uniqid());
  267. });
  268. $this->assertMatchesRegularExpression(
  269. '/This will be gone one day \w+ - (.*?)[\/\\\]TestCase.php, line\: \d+/',
  270. $error->getMessage()
  271. );
  272. }
  273. /**
  274. * Test no error when warning level is off.
  275. */
  276. public function testTriggerWarningLevelDisabled(): void
  277. {
  278. $this->withErrorReporting(E_ALL ^ E_USER_WARNING, function (): void {
  279. triggerWarning('This was a mistake.');
  280. $this->assertTrue(true);
  281. });
  282. }
  283. /**
  284. * testing getTypeName()
  285. */
  286. public function testgetTypeName(): void
  287. {
  288. $this->assertSame('stdClass', getTypeName(new \stdClass()));
  289. $this->assertSame('array', getTypeName([]));
  290. $this->assertSame('string', getTypeName(''));
  291. }
  292. }