Further Drupal 8.6.4 changes. Some core files were not committed before a commit...
[yaffs-website] / vendor / symfony / http-kernel / Tests / HttpCache / ResponseCacheStrategyTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * This code is partially based on the Rack-Cache library by Ryan Tomayko,
9  * which is released under the MIT license.
10  * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
11  *
12  * For the full copyright and license information, please view the LICENSE
13  * file that was distributed with this source code.
14  */
15
16 namespace Symfony\Component\HttpKernel\Tests\HttpCache;
17
18 use PHPUnit\Framework\TestCase;
19 use Symfony\Component\HttpFoundation\Response;
20 use Symfony\Component\HttpKernel\HttpCache\ResponseCacheStrategy;
21
22 class ResponseCacheStrategyTest extends TestCase
23 {
24     public function testMinimumSharedMaxAgeWins()
25     {
26         $cacheStrategy = new ResponseCacheStrategy();
27
28         $response1 = new Response();
29         $response1->setSharedMaxAge(60);
30         $cacheStrategy->add($response1);
31
32         $response2 = new Response();
33         $response2->setSharedMaxAge(3600);
34         $cacheStrategy->add($response2);
35
36         $response = new Response();
37         $response->setSharedMaxAge(86400);
38         $cacheStrategy->update($response);
39
40         $this->assertSame('60', $response->headers->getCacheControlDirective('s-maxage'));
41     }
42
43     public function testSharedMaxAgeNotSetIfNotSetInAnyEmbeddedRequest()
44     {
45         $cacheStrategy = new ResponseCacheStrategy();
46
47         $response1 = new Response();
48         $response1->setSharedMaxAge(60);
49         $cacheStrategy->add($response1);
50
51         $response2 = new Response();
52         $cacheStrategy->add($response2);
53
54         $response = new Response();
55         $response->setSharedMaxAge(86400);
56         $cacheStrategy->update($response);
57
58         $this->assertFalse($response->headers->hasCacheControlDirective('s-maxage'));
59     }
60
61     public function testSharedMaxAgeNotSetIfNotSetInMasterRequest()
62     {
63         $cacheStrategy = new ResponseCacheStrategy();
64
65         $response1 = new Response();
66         $response1->setSharedMaxAge(60);
67         $cacheStrategy->add($response1);
68
69         $response2 = new Response();
70         $response2->setSharedMaxAge(3600);
71         $cacheStrategy->add($response2);
72
73         $response = new Response();
74         $cacheStrategy->update($response);
75
76         $this->assertFalse($response->headers->hasCacheControlDirective('s-maxage'));
77     }
78
79     public function testMasterResponseNotCacheableWhenEmbeddedResponseRequiresValidation()
80     {
81         $cacheStrategy = new ResponseCacheStrategy();
82
83         $embeddedResponse = new Response();
84         $embeddedResponse->setLastModified(new \DateTime());
85         $cacheStrategy->add($embeddedResponse);
86
87         $masterResponse = new Response();
88         $masterResponse->setSharedMaxAge(3600);
89         $cacheStrategy->update($masterResponse);
90
91         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
92         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
93         $this->assertFalse($masterResponse->isFresh());
94     }
95
96     public function testValidationOnMasterResponseIsNotPossibleWhenItContainsEmbeddedResponses()
97     {
98         $cacheStrategy = new ResponseCacheStrategy();
99
100         // This master response uses the "validation" model
101         $masterResponse = new Response();
102         $masterResponse->setLastModified(new \DateTime());
103         $masterResponse->setEtag('foo');
104
105         // Embedded response uses "expiry" model
106         $embeddedResponse = new Response();
107         $masterResponse->setSharedMaxAge(3600);
108         $cacheStrategy->add($embeddedResponse);
109
110         $cacheStrategy->update($masterResponse);
111
112         $this->assertFalse($masterResponse->isValidateable());
113         $this->assertFalse($masterResponse->headers->has('Last-Modified'));
114         $this->assertFalse($masterResponse->headers->has('ETag'));
115         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
116         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
117     }
118
119     public function testMasterResponseWithValidationIsUnchangedWhenThereIsNoEmbeddedResponse()
120     {
121         $cacheStrategy = new ResponseCacheStrategy();
122
123         $masterResponse = new Response();
124         $masterResponse->setLastModified(new \DateTime());
125         $cacheStrategy->update($masterResponse);
126
127         $this->assertTrue($masterResponse->isValidateable());
128     }
129
130     public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbeddedResponse()
131     {
132         $cacheStrategy = new ResponseCacheStrategy();
133
134         $masterResponse = new Response();
135         $masterResponse->setSharedMaxAge(3600);
136         $cacheStrategy->update($masterResponse);
137
138         $this->assertTrue($masterResponse->isFresh());
139     }
140
141     public function testMasterResponseIsNotCacheableWhenEmbeddedResponseIsNotCacheable()
142     {
143         $cacheStrategy = new ResponseCacheStrategy();
144
145         $masterResponse = new Response();
146         $masterResponse->setSharedMaxAge(3600); // Public, cacheable
147
148         /* This response has no validation or expiration information.
149            That makes it uncacheable, it is always stale.
150            (It does *not* make this private, though.) */
151         $embeddedResponse = new Response();
152         $this->assertFalse($embeddedResponse->isFresh()); // not fresh, as no lifetime is provided
153
154         $cacheStrategy->add($embeddedResponse);
155         $cacheStrategy->update($masterResponse);
156
157         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
158         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
159         $this->assertFalse($masterResponse->isFresh());
160     }
161
162     public function testEmbeddingPrivateResponseMakesMainResponsePrivate()
163     {
164         $cacheStrategy = new ResponseCacheStrategy();
165
166         $masterResponse = new Response();
167         $masterResponse->setSharedMaxAge(3600); // public, cacheable
168
169         // The embedded response might for example contain per-user data that remains valid for 60 seconds
170         $embeddedResponse = new Response();
171         $embeddedResponse->setPrivate();
172         $embeddedResponse->setMaxAge(60); // this would implicitly set "private" as well, but let's be explicit
173
174         $cacheStrategy->add($embeddedResponse);
175         $cacheStrategy->update($masterResponse);
176
177         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private'));
178         $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public'));
179     }
180
181     public function testEmbeddingPublicResponseDoesNotMakeMainResponsePublic()
182     {
183         $cacheStrategy = new ResponseCacheStrategy();
184
185         $masterResponse = new Response();
186         $masterResponse->setPrivate(); // this is the default, but let's be explicit
187         $masterResponse->setMaxAge(100);
188
189         $embeddedResponse = new Response();
190         $embeddedResponse->setPublic();
191         $embeddedResponse->setSharedMaxAge(100);
192
193         $cacheStrategy->add($embeddedResponse);
194         $cacheStrategy->update($masterResponse);
195
196         $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private'));
197         $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public'));
198     }
199
200     public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation()
201     {
202         /* When "expiration wins over validation" (https://symfony.com/doc/current/http_cache/validation.html)
203          * and both the main and embedded response provide s-maxage, then the more restricting value of both
204          * should be fine, regardless of whether the embedded response can be validated later on or must be
205          * completely regenerated.
206          */
207         $cacheStrategy = new ResponseCacheStrategy();
208
209         $masterResponse = new Response();
210         $masterResponse->setSharedMaxAge(3600);
211
212         $embeddedResponse = new Response();
213         $embeddedResponse->setSharedMaxAge(60);
214         $embeddedResponse->setEtag('foo');
215
216         $cacheStrategy->add($embeddedResponse);
217         $cacheStrategy->update($masterResponse);
218
219         $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage'));
220     }
221
222     public function testResponseIsExpirableButNotValidateableWhenMasterResponseCombinesExpirationAndValidation()
223     {
224         $cacheStrategy = new ResponseCacheStrategy();
225
226         $masterResponse = new Response();
227         $masterResponse->setSharedMaxAge(3600);
228         $masterResponse->setEtag('foo');
229         $masterResponse->setLastModified(new \DateTime());
230
231         $embeddedResponse = new Response();
232         $embeddedResponse->setSharedMaxAge(60);
233
234         $cacheStrategy->add($embeddedResponse);
235         $cacheStrategy->update($masterResponse);
236
237         $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage'));
238         $this->assertFalse($masterResponse->isValidateable());
239     }
240 }