1111
1212namespace Symfony \Component \HttpKernel \Tests \HttpCache ;
1313
14+ use Symfony \Bridge \PhpUnit \ExpectDeprecationTrait ;
15+ use Symfony \Component \EventDispatcher \EventDispatcher ;
1416use Symfony \Component \HttpFoundation \Request ;
1517use Symfony \Component \HttpFoundation \Response ;
18+ use Symfony \Component \HttpKernel \Event \TerminateEvent ;
1619use Symfony \Component \HttpKernel \HttpCache \Esi ;
1720use Symfony \Component \HttpKernel \HttpCache \HttpCache ;
18- use Symfony \Component \HttpKernel \HttpCache \Store ;
1921use Symfony \Component \HttpKernel \HttpCache \StoreInterface ;
2022use Symfony \Component \HttpKernel \HttpKernelInterface ;
2123use Symfony \Component \HttpKernel \Kernel ;
2527 */
2628class HttpCacheTestextends HttpCacheTestCase
2729{
30+ use ExpectDeprecationTrait;
31+
2832public function testTerminateDelegatesTerminationOnlyForTerminableInterface ()
2933 {
3034$ storeMock =$ this ->getMockBuilder (StoreInterface::class)
@@ -33,7 +37,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
3337
3438// does not implement TerminableInterface
3539$ kernel =new TestKernel ();
36- $ httpCache =new HttpCache ($ kernel ,$ storeMock );
40+ $ httpCache =new HttpCache ($ kernel ,$ storeMock, null , [ ' terminate_on_cache_hit ' => false ] );
3741$ httpCache ->terminate (Request::create ('/ ' ),new Response ());
3842
3943$ this ->assertFalse ($ kernel ->terminateCalled ,'terminate() is never called if the kernel class does not implement TerminableInterface ' );
@@ -47,10 +51,108 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
4751$ kernelMock ->expects ($ this ->once ())
4852 ->method ('terminate ' );
4953
50- $ kernel =new HttpCache ($ kernelMock ,$ storeMock );
54+ $ kernel =new HttpCache ($ kernelMock ,$ storeMock, null , [ ' terminate_on_cache_hit ' => false ] );
5155$ kernel ->terminate (Request::create ('/ ' ),new Response ());
5256 }
5357
58+ public function testDoesNotCallTerminateOnFreshResponse ()
59+ {
60+ $ terminateEvents = [];
61+
62+ $ eventDispatcher =$ this ->createMock (EventDispatcher::class);
63+ $ eventDispatcher
64+ ->expects ($ this ->any ())
65+ ->method ('dispatch ' )
66+ ->with ($ this ->callback (function ($ event )use (&$ terminateEvents ) {
67+ if ($ eventinstanceof TerminateEvent) {
68+ $ terminateEvents [] =$ event ;
69+ }
70+
71+ return true ;
72+ }));
73+
74+ $ this ->setNextResponse (
75+ 200 ,
76+ [
77+ 'ETag ' =>'1234 ' ,
78+ 'Cache-Control ' =>'public, s-maxage=60 ' ,
79+ ],
80+ 'Hello World ' ,
81+ null ,
82+ $ eventDispatcher
83+ );
84+
85+ $ this ->request ('GET ' ,'/ ' );
86+ $ this ->assertHttpKernelIsCalled ();
87+ $ this ->assertEquals (200 ,$ this ->response ->getStatusCode ());
88+ $ this ->assertTraceContains ('miss ' );
89+ $ this ->assertTraceContains ('store ' );
90+ $ this ->cache ->terminate ($ this ->request ,$ this ->response );
91+
92+ sleep (2 );
93+
94+ $ this ->request ('GET ' ,'/ ' );
95+ $ this ->assertHttpKernelIsNotCalled ();
96+ $ this ->assertEquals (200 ,$ this ->response ->getStatusCode ());
97+ $ this ->assertTraceContains ('fresh ' );
98+ $ this ->assertEquals (2 ,$ this ->response ->headers ->get ('Age ' ));
99+ $ this ->cache ->terminate ($ this ->request ,$ this ->response );
100+
101+ $ this ->assertCount (1 ,$ terminateEvents );
102+ }
103+
104+ /**
105+ * @group legacy
106+ */
107+ public function testDoesCallTerminateOnFreshResponseIfConfigured ()
108+ {
109+ $ this ->expectDeprecation ('Since symfony/http-kernel 6.2: Setting "terminate_on_cache_hit" to "true" is deprecated and will be changed to "false" in Symfony 7.0. ' );
110+
111+ $ terminateEvents = [];
112+
113+ $ eventDispatcher =$ this ->createMock (EventDispatcher::class);
114+ $ eventDispatcher
115+ ->expects ($ this ->any ())
116+ ->method ('dispatch ' )
117+ ->with ($ this ->callback (function ($ event )use (&$ terminateEvents ) {
118+ if ($ eventinstanceof TerminateEvent) {
119+ $ terminateEvents [] =$ event ;
120+ }
121+
122+ return true ;
123+ }));
124+
125+ $ this ->setNextResponse (
126+ 200 ,
127+ [
128+ 'ETag ' =>'1234 ' ,
129+ 'Cache-Control ' =>'public, s-maxage=60 ' ,
130+ ],
131+ 'Hello World ' ,
132+ null ,
133+ $ eventDispatcher
134+ );
135+ $ this ->cacheConfig ['terminate_on_cache_hit ' ] =true ;
136+
137+ $ this ->request ('GET ' ,'/ ' );
138+ $ this ->assertHttpKernelIsCalled ();
139+ $ this ->assertEquals (200 ,$ this ->response ->getStatusCode ());
140+ $ this ->assertTraceContains ('miss ' );
141+ $ this ->assertTraceContains ('store ' );
142+ $ this ->cache ->terminate ($ this ->request ,$ this ->response );
143+
144+ sleep (2 );
145+
146+ $ this ->request ('GET ' ,'/ ' );
147+ $ this ->assertHttpKernelIsNotCalled ();
148+ $ this ->assertEquals (200 ,$ this ->response ->getStatusCode ());
149+ $ this ->assertTraceContains ('fresh ' );
150+ $ this ->assertEquals (2 ,$ this ->response ->headers ->get ('Age ' ));
151+ $ this ->cache ->terminate ($ this ->request ,$ this ->response );
152+
153+ $ this ->assertCount (2 ,$ terminateEvents );
154+ }
155+
54156public function testPassesOnNonGetHeadRequests ()
55157 {
56158$ this ->setNextResponse (200 );