KernelTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\App\Test\Unit\PageCache;
  7. use \Magento\Framework\App\PageCache\Kernel;
  8. use \Magento\Framework\App\Http\ContextFactory;
  9. use \Magento\Framework\App\Response\HttpFactory;
  10. /**
  11. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  12. */
  13. class KernelTest extends \PHPUnit\Framework\TestCase
  14. {
  15. /** @var Kernel */
  16. protected $kernel;
  17. /** @var \Magento\Framework\App\PageCache\Cache|\PHPUnit_Framework_MockObject_MockObject */
  18. protected $cacheMock;
  19. /** @var \Magento\Framework\App\PageCache\Identifier|\PHPUnit_Framework_MockObject_MockObject */
  20. protected $identifierMock;
  21. /** @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */
  22. protected $requestMock;
  23. /** @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject */
  24. protected $responseMock;
  25. /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Cache\Type */
  26. private $fullPageCacheMock;
  27. /** @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject */
  28. private $httpResponseMock;
  29. /** @var ContextFactory|\PHPUnit_Framework_MockObject_MockObject */
  30. private $contextFactoryMock;
  31. /** @var HttpFactory|\PHPUnit_Framework_MockObject_MockObject */
  32. private $httpFactoryMock;
  33. /** @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */
  34. private $serializer;
  35. /** @var \Magento\Framework\App\Http\Context|\PHPUnit_Framework_MockObject_MockObject */
  36. private $contextMock;
  37. /**
  38. * Setup
  39. */
  40. protected function setUp()
  41. {
  42. $headersMock = $this->createMock(\Zend\Http\Headers::class);
  43. $this->cacheMock = $this->createMock(\Magento\Framework\App\PageCache\Cache::class);
  44. $this->fullPageCacheMock = $this->createMock(\Magento\PageCache\Model\Cache\Type::class);
  45. $this->contextMock = $this->createMock(\Magento\Framework\App\Http\Context::class);
  46. $this->httpResponseMock = $this->createMock(\Magento\Framework\App\Response\Http::class);
  47. $this->identifierMock = $this->createMock(\Magento\Framework\App\PageCache\Identifier::class);
  48. $this->requestMock = $this->createMock(\Magento\Framework\App\Request\Http::class);
  49. $this->serializer = $this->createMock(\Magento\Framework\Serialize\SerializerInterface::class);
  50. $this->responseMock = $this->createMock(\Magento\Framework\App\Response\Http::class);
  51. $this->contextFactoryMock = $this->createPartialMock(ContextFactory::class, ['create']);
  52. $this->httpFactoryMock = $this->createPartialMock(HttpFactory::class, ['create']);
  53. $this->responseMock->expects($this->any())->method('getHeaders')->willReturn($headersMock);
  54. $this->kernel = new Kernel(
  55. $this->cacheMock,
  56. $this->identifierMock,
  57. $this->requestMock,
  58. $this->contextMock,
  59. $this->contextFactoryMock,
  60. $this->httpFactoryMock,
  61. $this->serializer
  62. );
  63. $reflection = new \ReflectionClass(\Magento\Framework\App\PageCache\Kernel::class);
  64. $reflectionProperty = $reflection->getProperty('fullPageCache');
  65. $reflectionProperty->setAccessible(true);
  66. $reflectionProperty->setValue($this->kernel, $this->fullPageCacheMock);
  67. }
  68. /**
  69. * @dataProvider dataProviderForResultWithCachedData
  70. * @param string $id
  71. * @param mixed $cache
  72. * @param bool $isGet
  73. * @param bool $isHead
  74. */
  75. public function testLoadWithCachedData($id, $cache, $isGet, $isHead)
  76. {
  77. $this->serializer->expects($this->once())
  78. ->method('unserialize')
  79. ->willReturnCallback(
  80. function ($value) {
  81. return json_decode($value, true);
  82. }
  83. );
  84. $this->contextFactoryMock
  85. ->expects($this->once())
  86. ->method('create')
  87. ->with(
  88. [
  89. 'data' => ['context_data'],
  90. 'default' => ['context_default_data']
  91. ]
  92. )
  93. ->willReturn($this->contextMock);
  94. $this->httpFactoryMock
  95. ->expects($this->once())
  96. ->method('create')
  97. ->with(['context' => $this->contextMock])
  98. ->willReturn($this->httpResponseMock);
  99. $this->requestMock->expects($this->once())->method('isGet')->will($this->returnValue($isGet));
  100. $this->requestMock->expects($this->any())->method('isHead')->will($this->returnValue($isHead));
  101. $this->fullPageCacheMock->expects(
  102. $this->any()
  103. )->method(
  104. 'load'
  105. )->with(
  106. $this->equalTo($id)
  107. )->will(
  108. $this->returnValue(json_encode($cache))
  109. );
  110. $this->httpResponseMock->expects($this->once())->method('setStatusCode')->with($cache['status_code']);
  111. $this->httpResponseMock->expects($this->once())->method('setContent')->with($cache['content']);
  112. $this->httpResponseMock->expects($this->once())->method('setHeader')->with(0, 'header', true);
  113. $this->identifierMock->expects($this->any())->method('getValue')->will($this->returnValue($id));
  114. $this->assertEquals($this->httpResponseMock, $this->kernel->load());
  115. }
  116. /**
  117. * @return array
  118. */
  119. public function dataProviderForResultWithCachedData()
  120. {
  121. $data = [
  122. 'context' => [
  123. 'data' => ['context_data'],
  124. 'default' => ['context_default_data']
  125. ],
  126. 'status_code' => 'status_code',
  127. 'content' => 'content',
  128. 'headers' => ['header']
  129. ];
  130. return [
  131. ['existing key', $data, true, false],
  132. ['existing key', $data, false, true],
  133. ];
  134. }
  135. /**
  136. * @dataProvider dataProviderForResultWithoutCachedData
  137. * @param string $id
  138. * @param mixed $cache
  139. * @param bool $isGet
  140. * @param bool $isHead
  141. */
  142. public function testLoadWithoutCachedData($id, $cache, $isGet, $isHead)
  143. {
  144. $this->requestMock->expects($this->once())->method('isGet')->will($this->returnValue($isGet));
  145. $this->requestMock->expects($this->any())->method('isHead')->will($this->returnValue($isHead));
  146. $this->fullPageCacheMock->expects(
  147. $this->any()
  148. )->method(
  149. 'load'
  150. )->with(
  151. $this->equalTo($id)
  152. )->will(
  153. $this->returnValue(json_encode($cache))
  154. );
  155. $this->identifierMock->expects($this->any())->method('getValue')->will($this->returnValue($id));
  156. $this->assertEquals(false, $this->kernel->load());
  157. }
  158. /**
  159. * @return array
  160. */
  161. public function dataProviderForResultWithoutCachedData()
  162. {
  163. return [
  164. ['existing key', [], false, false],
  165. ['non existing key', false, true, false],
  166. ['non existing key', false, false, false]
  167. ];
  168. }
  169. /**
  170. * @param $httpCode
  171. * @dataProvider testProcessSaveCacheDataProvider
  172. */
  173. public function testProcessSaveCache($httpCode, $at)
  174. {
  175. $this->serializer->expects($this->once())
  176. ->method('serialize')
  177. ->willReturnCallback(
  178. function ($value) {
  179. return json_encode($value);
  180. }
  181. );
  182. $cacheControlHeader = \Zend\Http\Header\CacheControl::fromString(
  183. 'Cache-Control: public, max-age=100, s-maxage=100'
  184. );
  185. $this->responseMock->expects(
  186. $this->at(0)
  187. )->method(
  188. 'getHeader'
  189. )->with(
  190. 'Cache-Control'
  191. )->will(
  192. $this->returnValue($cacheControlHeader)
  193. );
  194. $this->responseMock->expects(
  195. $this->any()
  196. )->method(
  197. 'getHttpResponseCode'
  198. )->willReturn($httpCode);
  199. $this->requestMock->expects($this->once())
  200. ->method('isGet')
  201. ->willReturn(true);
  202. $this->responseMock->expects($this->once())
  203. ->method('setNoCacheHeaders');
  204. $this->responseMock->expects($this->at($at[0]))
  205. ->method('getHeader')
  206. ->with('X-Magento-Tags');
  207. $this->responseMock->expects($this->at($at[1]))
  208. ->method('clearHeader')
  209. ->with($this->equalTo('Set-Cookie'));
  210. $this->responseMock->expects($this->at($at[2]))
  211. ->method('clearHeader')
  212. ->with($this->equalTo('X-Magento-Tags'));
  213. $this->fullPageCacheMock->expects($this->once())
  214. ->method('save');
  215. $this->kernel->process($this->responseMock);
  216. }
  217. /**
  218. * @return array
  219. */
  220. public function testProcessSaveCacheDataProvider()
  221. {
  222. return [
  223. [200, [3, 4, 5]],
  224. [404, [4, 5, 6]]
  225. ];
  226. }
  227. /**
  228. * @dataProvider processNotSaveCacheProvider
  229. * @param string $cacheControlHeader
  230. * @param int $httpCode
  231. * @param bool $isGet
  232. * @param bool $overrideHeaders
  233. */
  234. public function testProcessNotSaveCache($cacheControlHeader, $httpCode, $isGet, $overrideHeaders)
  235. {
  236. $header = \Zend\Http\Header\CacheControl::fromString("Cache-Control: $cacheControlHeader");
  237. $this->responseMock->expects(
  238. $this->once()
  239. )->method(
  240. 'getHeader'
  241. )->with(
  242. 'Cache-Control'
  243. )->will(
  244. $this->returnValue($header)
  245. );
  246. $this->responseMock->expects($this->any())->method('getHttpResponseCode')->will($this->returnValue($httpCode));
  247. $this->requestMock->expects($this->any())->method('isGet')->will($this->returnValue($isGet));
  248. if ($overrideHeaders) {
  249. $this->responseMock->expects($this->once())->method('setNoCacheHeaders');
  250. }
  251. $this->fullPageCacheMock->expects($this->never())->method('save');
  252. $this->kernel->process($this->responseMock);
  253. }
  254. /**
  255. * @return array
  256. */
  257. public function processNotSaveCacheProvider()
  258. {
  259. return [
  260. ['private, max-age=100', 200, true, false],
  261. ['private, max-age=100', 200, false, false],
  262. ['private, max-age=100', 500, true, false],
  263. ['no-store, no-cache, must-revalidate, max-age=0', 200, true, false],
  264. ['no-store, no-cache, must-revalidate, max-age=0', 200, false, false],
  265. ['no-store, no-cache, must-revalidate, max-age=0', 404, true, false],
  266. ['no-store, no-cache, must-revalidate, max-age=0', 500, true, false],
  267. ['public, max-age=100, s-maxage=100', 500, true, true],
  268. ['public, max-age=100, s-maxage=100', 200, false, true]
  269. ];
  270. }
  271. }