FunctionsGlobalTest.php 10 KB

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