MiddlewareQueueTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  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.3.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Http;
  17. use Cake\Core\Container;
  18. use Cake\Http\MiddlewareQueue;
  19. use Cake\TestSuite\TestCase;
  20. use InvalidArgumentException;
  21. use LogicException;
  22. use OutOfBoundsException;
  23. use TestApp\Middleware\DumbMiddleware;
  24. use TestApp\Middleware\SampleMiddleware;
  25. /**
  26. * Test case for the MiddlewareQueue
  27. */
  28. class MiddlewareQueueTest extends TestCase
  29. {
  30. /**
  31. * @var string
  32. */
  33. protected $previousNamespace;
  34. /**
  35. * setUp
  36. */
  37. public function setUp(): void
  38. {
  39. parent::setUp();
  40. $this->previousNamespace = static::setAppNamespace('TestApp');
  41. }
  42. /**
  43. * tearDown
  44. */
  45. public function tearDown(): void
  46. {
  47. parent::tearDown();
  48. static::setAppNamespace($this->previousNamespace);
  49. }
  50. public function testConstructorAddingMiddleware(): void
  51. {
  52. $cb = function (): void {
  53. };
  54. $queue = new MiddlewareQueue([$cb]);
  55. $this->assertCount(1, $queue);
  56. $this->assertSame($cb, $queue->current()->getCallable());
  57. }
  58. /**
  59. * Test get()
  60. */
  61. public function testGet(): void
  62. {
  63. $queue = new MiddlewareQueue();
  64. $cb = function (): void {
  65. };
  66. $queue->add($cb);
  67. $this->assertSame($cb, $queue->current()->getCallable());
  68. }
  69. /**
  70. * Test that current() throws exception for invalid current position.
  71. */
  72. public function testGetException(): void
  73. {
  74. $this->expectException(OutOfBoundsException::class);
  75. $this->expectExceptionMessage('Invalid current position (0)');
  76. $queue = new MiddlewareQueue();
  77. $queue->current();
  78. }
  79. /**
  80. * Test the return value of add()
  81. */
  82. public function testAddReturn(): void
  83. {
  84. $queue = new MiddlewareQueue();
  85. $cb = function (): void {
  86. };
  87. $this->assertSame($queue, $queue->add($cb));
  88. }
  89. /**
  90. * Test the add orders correctly
  91. */
  92. public function testAddOrdering(): void
  93. {
  94. $one = function (): void {
  95. };
  96. $two = function (): void {
  97. };
  98. $queue = new MiddlewareQueue();
  99. $this->assertCount(0, $queue);
  100. $queue->add($one);
  101. $this->assertCount(1, $queue);
  102. $queue->add($two);
  103. $this->assertCount(2, $queue);
  104. $this->assertSame($one, $queue->current()->getCallable());
  105. $queue->next();
  106. $this->assertSame($two, $queue->current()->getCallable());
  107. }
  108. /**
  109. * Test the prepend can be chained
  110. */
  111. public function testPrependReturn(): void
  112. {
  113. $cb = function (): void {
  114. };
  115. $queue = new MiddlewareQueue();
  116. $this->assertSame($queue, $queue->prepend($cb));
  117. }
  118. /**
  119. * Test the prepend orders correctly.
  120. */
  121. public function testPrependOrdering(): void
  122. {
  123. $one = function (): void {
  124. };
  125. $two = function (): void {
  126. };
  127. $queue = new MiddlewareQueue();
  128. $this->assertCount(0, $queue);
  129. $queue->add($one);
  130. $this->assertCount(1, $queue);
  131. $queue->prepend($two);
  132. $this->assertCount(2, $queue);
  133. $this->assertSame($two, $queue->current()->getCallable());
  134. $queue->next();
  135. $this->assertSame($one, $queue->current()->getCallable());
  136. }
  137. /**
  138. * Test updating queue using class name
  139. */
  140. public function testAddingPrependingUsingString(): void
  141. {
  142. $queue = new MiddlewareQueue();
  143. $queue->add('Sample');
  144. $queue->prepend('TestApp\Middleware\SampleMiddleware');
  145. $this->assertInstanceOf('TestApp\Middleware\SampleMiddleware', $queue->current());
  146. $this->assertInstanceOf('TestApp\Middleware\SampleMiddleware', $queue->current());
  147. }
  148. /**
  149. * Test updating queue using array
  150. */
  151. public function testAddingPrependingUsingArray(): void
  152. {
  153. $one = function (): void {
  154. };
  155. $queue = new MiddlewareQueue();
  156. $queue->add([$one]);
  157. $queue->prepend(['TestApp\Middleware\SampleMiddleware']);
  158. $this->assertInstanceOf('TestApp\Middleware\SampleMiddleware', $queue->current());
  159. $queue->next();
  160. $this->assertSame($one, $queue->current()->getCallable());
  161. }
  162. /**
  163. * Test insertAt ordering
  164. */
  165. public function testInsertAt(): void
  166. {
  167. $one = function (): void {
  168. };
  169. $two = function (): void {
  170. };
  171. $three = function (): void {
  172. };
  173. $four = new SampleMiddleware();
  174. $queue = new MiddlewareQueue();
  175. $queue->add($one)->add($two)->insertAt(0, $three)->insertAt(2, $four);
  176. $this->assertSame($three, $queue->current()->getCallable());
  177. $queue->next();
  178. $this->assertSame($one, $queue->current()->getCallable());
  179. $queue->next();
  180. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  181. $queue->next();
  182. $this->assertSame($two, $queue->current()->getCallable());
  183. $queue = new MiddlewareQueue();
  184. $queue->add($one)->add($two)->insertAt(1, $three);
  185. $this->assertSame($one, $queue->current()->getCallable());
  186. $queue->next();
  187. $this->assertSame($three, $queue->current()->getCallable());
  188. $queue->next();
  189. $this->assertSame($two, $queue->current()->getCallable());
  190. }
  191. /**
  192. * Test insertAt out of the existing range
  193. */
  194. public function testInsertAtOutOfBounds(): void
  195. {
  196. $one = function (): void {
  197. };
  198. $two = function (): void {
  199. };
  200. $queue = new MiddlewareQueue();
  201. $queue->add($one)->insertAt(99, $two);
  202. $this->assertCount(2, $queue);
  203. $this->assertSame($one, $queue->current()->getCallable());
  204. $queue->next();
  205. $this->assertSame($two, $queue->current()->getCallable());
  206. }
  207. /**
  208. * Test insertAt with a negative index
  209. */
  210. public function testInsertAtNegative(): void
  211. {
  212. $one = function (): void {
  213. };
  214. $two = function (): void {
  215. };
  216. $three = new SampleMiddleware();
  217. $queue = new MiddlewareQueue();
  218. $queue->add($one)->insertAt(-1, $two)->insertAt(-1, $three);
  219. $this->assertCount(3, $queue);
  220. $this->assertSame($two, $queue->current()->getCallable());
  221. $queue->next();
  222. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  223. $queue->next();
  224. $this->assertSame($one, $queue->current()->getCallable());
  225. }
  226. /**
  227. * Test insertBefore
  228. */
  229. public function testInsertBefore(): void
  230. {
  231. $one = function (): void {
  232. };
  233. $two = new SampleMiddleware();
  234. $three = function (): void {
  235. };
  236. $four = new DumbMiddleware();
  237. $queue = new MiddlewareQueue();
  238. $queue->add($one)->add($two)->insertBefore(SampleMiddleware::class, $three)->insertBefore(SampleMiddleware::class, $four);
  239. $this->assertCount(4, $queue);
  240. $this->assertSame($one, $queue->current()->getCallable());
  241. $queue->next();
  242. $this->assertSame($three, $queue->current()->getCallable());
  243. $queue->next();
  244. $this->assertInstanceOf(DumbMiddleware::class, $queue->current());
  245. $queue->next();
  246. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  247. $two = SampleMiddleware::class;
  248. $queue = new MiddlewareQueue();
  249. $queue
  250. ->add($one)
  251. ->add($two)
  252. ->insertBefore(SampleMiddleware::class, $three);
  253. $this->assertCount(3, $queue);
  254. $this->assertSame($one, $queue->current()->getCallable());
  255. $queue->next();
  256. $this->assertSame($three, $queue->current()->getCallable());
  257. $queue->next();
  258. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  259. }
  260. /**
  261. * Test insertBefore an invalid classname
  262. */
  263. public function testInsertBeforeInvalid(): void
  264. {
  265. $this->expectException(LogicException::class);
  266. $this->expectExceptionMessage('No middleware matching `InvalidClassName` could be found.');
  267. $one = function (): void {
  268. };
  269. $two = new SampleMiddleware();
  270. $three = function (): void {
  271. };
  272. $queue = new MiddlewareQueue();
  273. $queue->add($one)->add($two)->insertBefore('InvalidClassName', $three);
  274. }
  275. /**
  276. * Test insertAfter
  277. */
  278. public function testInsertAfter(): void
  279. {
  280. $one = new SampleMiddleware();
  281. $two = function (): void {
  282. };
  283. $three = function (): void {
  284. };
  285. $four = new DumbMiddleware();
  286. $queue = new MiddlewareQueue();
  287. $queue
  288. ->add($one)
  289. ->add($two)
  290. ->insertAfter(SampleMiddleware::class, $three)
  291. ->insertAfter(SampleMiddleware::class, $four);
  292. $this->assertCount(4, $queue);
  293. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  294. $queue->next();
  295. $this->assertInstanceOf(DumbMiddleware::class, $queue->current());
  296. $queue->next();
  297. $this->assertSame($three, $queue->current()->getCallable());
  298. $queue->next();
  299. $this->assertSame($two, $queue->current()->getCallable());
  300. $one = 'Sample';
  301. $queue = new MiddlewareQueue();
  302. $queue
  303. ->add($one)
  304. ->add($two)
  305. ->insertAfter('Sample', $three);
  306. $this->assertCount(3, $queue);
  307. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  308. $queue->next();
  309. $this->assertSame($three, $queue->current()->getCallable());
  310. $queue->next();
  311. $this->assertSame($two, $queue->current()->getCallable());
  312. }
  313. /**
  314. * Test insertAfter an invalid classname
  315. */
  316. public function testInsertAfterInvalid(): void
  317. {
  318. $one = new SampleMiddleware();
  319. $two = function (): void {
  320. };
  321. $three = function (): void {
  322. };
  323. $queue = new MiddlewareQueue();
  324. $queue->add($one)->add($two)->insertAfter('InvalidClass', $three);
  325. $this->assertCount(3, $queue);
  326. $this->assertInstanceOf(SampleMiddleware::class, $queue->current());
  327. $queue->next();
  328. $this->assertSame($two, $queue->current()->getCallable());
  329. $queue->next();
  330. $this->assertSame($three, $queue->current()->getCallable());
  331. }
  332. /**
  333. * Make sure middlewares provided via DI are the same object
  334. */
  335. public function testDIContainer(): void
  336. {
  337. $container = new Container();
  338. $middleware = new SampleMiddleware();
  339. $container->add(SampleMiddleware::class, $middleware);
  340. $queue = new MiddlewareQueue([], $container);
  341. $queue->add(SampleMiddleware::class);
  342. $this->assertSame($middleware, $queue->current());
  343. }
  344. /**
  345. * Make sure an exception is thrown for unknown middlewares
  346. */
  347. public function testDIContainerNotResolvable(): void
  348. {
  349. $container = new Container();
  350. $queue = new MiddlewareQueue([], $container);
  351. $this->expectException(InvalidArgumentException::class);
  352. $this->expectExceptionMessage('Middleware `UnresolvableMiddleware` was not found.');
  353. $queue->add('UnresolvableMiddleware');
  354. $queue->current();
  355. }
  356. }