1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the FOSHttpCacheBundle package. |
5
|
|
|
* |
6
|
|
|
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace FOS\HttpCacheBundle\Tests\Unit\DependencyInjection; |
13
|
|
|
|
14
|
|
|
use FOS\HttpCacheBundle\DependencyInjection\FOSHttpCacheExtension; |
15
|
|
|
use Symfony\Component\DependencyInjection\ContainerBuilder; |
16
|
|
|
use Symfony\Component\DependencyInjection\Definition; |
17
|
|
|
use Symfony\Component\DependencyInjection\DefinitionDecorator; |
18
|
|
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; |
19
|
|
|
use Symfony\Component\DependencyInjection\Reference; |
20
|
|
|
|
21
|
|
|
class FOSHttpCacheExtensionTest extends \PHPUnit_Framework_TestCase |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* @var FOSHttpCacheExtension |
25
|
|
|
*/ |
26
|
|
|
protected $extension; |
27
|
|
|
|
28
|
|
|
protected function setUp() |
29
|
|
|
{ |
30
|
|
|
$this->extension = new FOSHttpCacheExtension(); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
public function testConfigLoadVarnish() |
34
|
|
|
{ |
35
|
|
|
$container = $this->createContainer(); |
36
|
|
|
$this->extension->load(array($this->getBaseConfig()), $container); |
37
|
|
|
|
38
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.proxy_client.varnish')); |
39
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.nginx')); |
40
|
|
|
$this->assertTrue($container->hasAlias('fos_http_cache.default_proxy_client')); |
41
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.event_listener.invalidation')); |
42
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.event_listener.tag')); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
public function testConfigLoadVarnishCustomClient() |
46
|
|
|
{ |
47
|
|
|
$container = $this->createContainer(); |
48
|
|
|
|
49
|
|
|
$config = $this->getBaseConfig(); |
50
|
|
|
$config['proxy_client']['varnish']['http']['http_client'] = 'my_guzzle'; |
51
|
|
|
$this->extension->load(array($config), $container); |
52
|
|
|
|
53
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.proxy_client.varnish.http_dispatcher')); |
54
|
|
|
$def = $container->getDefinition('fos_http_cache.proxy_client.varnish.http_dispatcher'); |
55
|
|
|
$this->assertInstanceOf(Reference::class, $def->getArgument(2)); |
56
|
|
|
$this->assertEquals('my_guzzle', $def->getArgument(2)->__toString()); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException |
61
|
|
|
*/ |
62
|
|
|
public function testConfigLoadVarnishInvalidUrl() |
63
|
|
|
{ |
64
|
|
|
$container = $this->createContainer(); |
65
|
|
|
$config = $this->getBaseConfig(); |
66
|
|
|
$config['proxy_client']['varnish']['http']['base_url'] = 'ftp:not a valid url'; |
67
|
|
|
|
68
|
|
|
$this->extension->load(array($config), $container); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
View Code Duplication |
public function testConfigLoadNginx() |
|
|
|
|
72
|
|
|
{ |
73
|
|
|
$container = $this->createContainer(); |
74
|
|
|
$this->extension->load(array( |
75
|
|
|
array( |
76
|
|
|
'proxy_client' => array( |
77
|
|
|
'nginx' => array( |
78
|
|
|
'http' => [ |
79
|
|
|
'base_url' => 'my_hostname', |
80
|
|
|
'servers' => array( |
81
|
|
|
'127.0.0.1', |
82
|
|
|
), |
83
|
|
|
], |
84
|
|
|
), |
85
|
|
|
), |
86
|
|
|
), |
87
|
|
|
), $container); |
88
|
|
|
|
89
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.varnish')); |
90
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.proxy_client.nginx')); |
91
|
|
|
$this->assertTrue($container->hasAlias('fos_http_cache.default_proxy_client')); |
92
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.event_listener.invalidation')); |
93
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.http.symfony_response_tagger')); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
View Code Duplication |
public function testConfigLoadSymfony() |
|
|
|
|
97
|
|
|
{ |
98
|
|
|
$container = $this->createContainer(); |
99
|
|
|
$this->extension->load(array( |
100
|
|
|
array( |
101
|
|
|
'proxy_client' => array( |
102
|
|
|
'symfony' => array( |
103
|
|
|
'http' => [ |
104
|
|
|
'base_url' => 'my_hostname', |
105
|
|
|
'servers' => array( |
106
|
|
|
'127.0.0.1', |
107
|
|
|
), |
108
|
|
|
], |
109
|
|
|
), |
110
|
|
|
), |
111
|
|
|
), |
112
|
|
|
), $container); |
113
|
|
|
|
114
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.varnish')); |
115
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.nginx')); |
116
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.proxy_client.symfony')); |
117
|
|
|
$this->assertTrue($container->hasAlias('fos_http_cache.default_proxy_client')); |
118
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.event_listener.invalidation')); |
119
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.http.symfony_response_tagger')); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
public function testConfigCustomClient() |
123
|
|
|
{ |
124
|
|
|
$container = $this->createContainer(); |
125
|
|
|
$this->extension->load(array( |
126
|
|
|
array( |
127
|
|
|
'cache_manager' => array( |
128
|
|
|
'custom_proxy_client' => 'app.cache.client', |
129
|
|
|
), |
130
|
|
|
), |
131
|
|
|
), $container); |
132
|
|
|
|
133
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.varnish')); |
134
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.nginx')); |
135
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.proxy_client.symfony')); |
136
|
|
|
$this->assertTrue($container->hasAlias('fos_http_cache.default_proxy_client')); |
137
|
|
|
$this->assertTrue($container->hasDefinition('fos_http_cache.event_listener.invalidation')); |
138
|
|
|
$this->assertFalse($container->hasDefinition('fos_http_cache.http.symfony_response_tagger')); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
public function testEmptyConfig() |
142
|
|
|
{ |
143
|
|
|
$config = array(); |
144
|
|
|
|
145
|
|
|
$container = $this->createContainer(); |
146
|
|
|
$this->extension->load(array($config), $container); |
147
|
|
|
|
148
|
|
|
$this->assertFalse($container->has('fos_http_cache.user_context.logout_handler')); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException |
153
|
|
|
* @expectedExceptionMessage You can not enable cache tagging with the nginx client |
154
|
|
|
*/ |
155
|
|
|
public function testConfigTagNotSupported() |
156
|
|
|
{ |
157
|
|
|
$config = array( |
158
|
|
|
'proxy_client' => array( |
159
|
|
|
'nginx' => array( |
160
|
|
|
'http' => [ |
161
|
|
|
'base_url' => 'my_hostname', |
162
|
|
|
'servers' => array( |
163
|
|
|
'127.0.0.1', |
164
|
|
|
), |
165
|
|
|
], |
166
|
|
|
), |
167
|
|
|
), |
168
|
|
|
'tags' => array( |
169
|
|
|
'enabled' => true, |
170
|
|
|
), |
171
|
|
|
); |
172
|
|
|
|
173
|
|
|
$container = $this->createContainer(); |
174
|
|
|
$this->extension->load(array($config), $container); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
public function testConfigLoadTagRules() |
178
|
|
|
{ |
179
|
|
|
$config = $this->getBaseConfig() + array( |
180
|
|
|
'tags' => array( |
181
|
|
|
'rules' => array( |
182
|
|
|
array( |
183
|
|
|
'match' => array( |
184
|
|
|
'path' => '^/$', |
185
|
|
|
'host' => 'fos.lo', |
186
|
|
|
'methods' => array('GET', 'HEAD'), |
187
|
|
|
'ips' => array('1.1.1.1', '2.2.2.2'), |
188
|
|
|
'attributes' => array( |
189
|
|
|
'_controller' => '^AcmeBundle:Default:index$', |
190
|
|
|
), |
191
|
|
|
), |
192
|
|
|
'tags' => array('tag-a', 'tag-b'), |
193
|
|
|
), |
194
|
|
|
), |
195
|
|
|
), |
196
|
|
|
); |
197
|
|
|
|
198
|
|
|
$container = $this->createContainer(); |
199
|
|
|
$this->extension->load(array($config), $container); |
200
|
|
|
|
201
|
|
|
$this->assertMatcherCreated($container, array('_controller' => '^AcmeBundle:Default:index$')); |
202
|
|
|
$this->assertListenerHasRule($container, 'fos_http_cache.event_listener.tag'); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
public function testConfigLoadInvalidatorRules() |
206
|
|
|
{ |
207
|
|
|
$config = $this->getBaseConfig() + array( |
208
|
|
|
'invalidation' => array( |
209
|
|
|
'rules' => array( |
210
|
|
|
array( |
211
|
|
|
'match' => array( |
212
|
|
|
'attributes' => array( |
213
|
|
|
'_route' => 'my_route', |
214
|
|
|
), |
215
|
|
|
), |
216
|
|
|
'routes' => array( |
217
|
|
|
'invalidate_route1' => array( |
218
|
|
|
), |
219
|
|
|
), |
220
|
|
|
), |
221
|
|
|
), |
222
|
|
|
), |
223
|
|
|
); |
224
|
|
|
|
225
|
|
|
$container = $this->createContainer(); |
226
|
|
|
$this->extension->load(array($config), $container); |
227
|
|
|
|
228
|
|
|
$this->assertMatcherCreated($container, array('_route' => 'my_route')); |
229
|
|
|
$this->assertListenerHasRule($container, 'fos_http_cache.event_listener.invalidation'); |
230
|
|
|
|
231
|
|
|
// Test for runtime errors |
232
|
|
|
$container->compile(); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
public function testConfigLoadCacheControl() |
236
|
|
|
{ |
237
|
|
|
$config = array( |
238
|
|
|
'cache_control' => array( |
239
|
|
|
'rules' => array( |
240
|
|
|
array( |
241
|
|
|
'match' => array( |
242
|
|
|
'path' => '^/$', |
243
|
|
|
'host' => 'fos.lo', |
244
|
|
|
'methods' => array('GET', 'HEAD'), |
245
|
|
|
'ips' => array('1.1.1.1', '2.2.2.2'), |
246
|
|
|
'attributes' => array( |
247
|
|
|
'_controller' => '^AcmeBundle:Default:index$', |
248
|
|
|
), |
249
|
|
|
), |
250
|
|
|
'headers' => array( |
251
|
|
|
'cache_control' => array('public' => true), |
252
|
|
|
'reverse_proxy_ttl' => 42, |
253
|
|
|
'vary' => array('Cookie', 'Accept-Language'), |
254
|
|
|
), |
255
|
|
|
), |
256
|
|
|
), |
257
|
|
|
), |
258
|
|
|
); |
259
|
|
|
|
260
|
|
|
$container = $this->createContainer(); |
261
|
|
|
$this->extension->load(array($config), $container); |
262
|
|
|
|
263
|
|
|
$this->assertMatcherCreated($container, array('_controller' => '^AcmeBundle:Default:index$')); |
264
|
|
|
$this->assertListenerHasRule($container, 'fos_http_cache.event_listener.cache_control'); |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Check if comma separated strings are parsed as expected. |
269
|
|
|
*/ |
270
|
|
|
public function testConfigLoadCacheControlSplit() |
271
|
|
|
{ |
272
|
|
|
$config = array( |
273
|
|
|
'cache_control' => array( |
274
|
|
|
'rules' => array( |
275
|
|
|
array( |
276
|
|
|
'match' => array( |
277
|
|
|
'methods' => 'GET,HEAD', |
278
|
|
|
'ips' => '1.1.1.1,2.2.2.2', |
279
|
|
|
'attributes' => array( |
280
|
|
|
'_controller' => '^AcmeBundle:Default:index$', |
281
|
|
|
), |
282
|
|
|
), |
283
|
|
|
'headers' => array( |
284
|
|
|
'vary' => 'Cookie, Accept-Language', |
285
|
|
|
), |
286
|
|
|
), |
287
|
|
|
), |
288
|
|
|
), |
289
|
|
|
); |
290
|
|
|
|
291
|
|
|
$container = $this->createContainer(); |
292
|
|
|
$this->extension->load(array($config), $container); |
293
|
|
|
|
294
|
|
|
$matcherDefinition = $this->assertMatcherCreated($container, array('_controller' => '^AcmeBundle:Default:index$')); |
295
|
|
|
$this->assertEquals(array('GET', 'HEAD'), $matcherDefinition->getArgument(2)); |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
public function testConfigUserContext() |
299
|
|
|
{ |
300
|
|
|
$config = $this->getBaseConfig() + array( |
301
|
|
|
'user_context' => array( |
302
|
|
|
'match' => array( |
303
|
|
|
'matcher_service' => 'my_request_matcher_id', |
304
|
|
|
'method' => 'AUTHENTICATE', |
305
|
|
|
'accept' => 'application/vnd.test', |
306
|
|
|
), |
307
|
|
|
'user_identifier_headers' => array('X-Foo'), |
308
|
|
|
'user_hash_header' => 'X-Bar', |
309
|
|
|
'hash_cache_ttl' => 30, |
310
|
|
|
'always_vary_on_context_hash' => true, |
311
|
|
|
'role_provider' => true, |
312
|
|
|
), |
313
|
|
|
); |
314
|
|
|
|
315
|
|
|
$container = $this->createContainer(); |
316
|
|
|
$this->extension->load(array($config), $container); |
317
|
|
|
|
318
|
|
|
$this->assertTrue($container->has('fos_http_cache.event_listener.user_context')); |
319
|
|
|
$this->assertTrue($container->has('fos_http_cache.user_context.hash_generator')); |
320
|
|
|
$this->assertTrue($container->has('fos_http_cache.user_context.request_matcher')); |
321
|
|
|
$this->assertTrue($container->has('fos_http_cache.user_context.role_provider')); |
322
|
|
|
$this->assertTrue($container->has('fos_http_cache.user_context.logout_handler')); |
323
|
|
|
|
324
|
|
|
$this->assertEquals(array('fos_http_cache.user_context.role_provider' => array(array())), $container->findTaggedServiceIds('fos_http_cache.user_context_provider')); |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
public function testConfigWithoutUserContext() |
328
|
|
|
{ |
329
|
|
|
$config = array( |
330
|
|
|
array('user_context' => array( |
331
|
|
|
'enabled' => false, |
332
|
|
|
'match' => array( |
333
|
|
|
'matcher_service' => 'my_request_matcher_id', |
334
|
|
|
'method' => 'AUTHENTICATE', |
335
|
|
|
'accept' => 'application/vnd.test', |
336
|
|
|
), |
337
|
|
|
'user_identifier_headers' => array('X-Foo'), |
338
|
|
|
'user_hash_header' => 'X-Bar', |
339
|
|
|
'hash_cache_ttl' => 30, |
340
|
|
|
'always_vary_on_context_hash' => true, |
341
|
|
|
'role_provider' => true, |
342
|
|
|
)), |
343
|
|
|
); |
344
|
|
|
|
345
|
|
|
$container = $this->createContainer(); |
346
|
|
|
$this->extension->load($config, $container); |
347
|
|
|
|
348
|
|
|
$this->assertFalse($container->has('fos_http_cache.event_listener.user_context')); |
349
|
|
|
$this->assertFalse($container->has('fos_http_cache.user_context.hash_generator')); |
350
|
|
|
$this->assertFalse($container->has('fos_http_cache.user_context.request_matcher')); |
351
|
|
|
$this->assertFalse($container->has('fos_http_cache.user_context.role_provider')); |
352
|
|
|
$this->assertFalse($container->has('fos_http_cache.user_context.logout_handler')); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
public function testConfigLoadFlashMessageListener() |
356
|
|
|
{ |
357
|
|
|
$config = array( |
358
|
|
|
array('flash_message' => true, |
359
|
|
|
), |
360
|
|
|
); |
361
|
|
|
|
362
|
|
|
$container = $this->createContainer(); |
363
|
|
|
$this->extension->load($config, $container); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
protected function createContainer() |
367
|
|
|
{ |
368
|
|
|
$container = new ContainerBuilder( |
369
|
|
|
new ParameterBag(array('kernel.debug' => false)) |
370
|
|
|
); |
371
|
|
|
|
372
|
|
|
// The cache_manager service depends on the router service |
373
|
|
|
$container->setDefinition( |
374
|
|
|
'router', |
375
|
|
|
new Definition('\Symfony\Component\Routing\Router') |
376
|
|
|
); |
377
|
|
|
|
378
|
|
|
return $container; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
View Code Duplication |
protected function getBaseConfig() |
|
|
|
|
382
|
|
|
{ |
383
|
|
|
return array( |
384
|
|
|
'proxy_client' => array( |
385
|
|
|
'varnish' => array( |
386
|
|
|
'http' => [ |
387
|
|
|
'base_url' => 'my_hostname', |
388
|
|
|
'servers' => array( |
389
|
|
|
'127.0.0.1', |
390
|
|
|
), |
391
|
|
|
], |
392
|
|
|
), |
393
|
|
|
), |
394
|
|
|
); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* @param ContainerBuilder $container |
399
|
|
|
* @param array $attributes |
400
|
|
|
* |
401
|
|
|
* @return DefinitionDecorator |
|
|
|
|
402
|
|
|
*/ |
403
|
|
|
private function assertMatcherCreated(ContainerBuilder $container, array $attributes) |
404
|
|
|
{ |
405
|
|
|
// Extract the corresponding definition |
406
|
|
|
$matcherDefinition = null; |
407
|
|
|
$matcherId = null; |
408
|
|
|
foreach ($container->getDefinitions() as $id => $definition) { |
409
|
|
|
if ($definition instanceof DefinitionDecorator && |
410
|
|
|
$definition->getParent() === 'fos_http_cache.request_matcher' |
411
|
|
|
) { |
412
|
|
|
if ($matcherDefinition) { |
413
|
|
|
$this->fail('More then one request matcher was created'); |
414
|
|
|
} |
415
|
|
|
$matcherId = $id; |
416
|
|
|
$matcherDefinition = $definition; |
417
|
|
|
} |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
// definition should exist |
421
|
|
|
$this->assertNotNull($matcherDefinition); |
422
|
|
|
|
423
|
|
|
// 5th argument should contain the request attribute criteria |
424
|
|
|
$this->assertEquals($attributes, $matcherDefinition->getArgument(4)); |
425
|
|
|
|
426
|
|
|
$ruleDefinition = null; |
427
|
|
|
foreach ($container->getDefinitions() as $definition) { |
428
|
|
|
if ($definition instanceof DefinitionDecorator && |
429
|
|
|
$definition->getParent() === 'fos_http_cache.rule_matcher' |
430
|
|
|
) { |
431
|
|
|
if ($ruleDefinition) { |
432
|
|
|
$this->fail('More then one rule matcher was created'); |
433
|
|
|
} |
434
|
|
|
$ruleDefinition = $definition; |
435
|
|
|
} |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
// definition should exist |
439
|
|
|
$this->assertNotNull($ruleDefinition); |
440
|
|
|
|
441
|
|
|
// first argument should be the reference to the matcher |
442
|
|
|
$reference = $ruleDefinition->getArgument(0); |
443
|
|
|
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $reference); |
444
|
|
|
$this->assertEquals($matcherId, (string) $reference); |
445
|
|
|
|
446
|
|
|
return $matcherDefinition; |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* Assert that the service $id exists and has a method call mapped onto it. |
451
|
|
|
* |
452
|
|
|
* @param ContainerBuilder $container |
453
|
|
|
* @param string $id The service id to investigate |
454
|
|
|
*/ |
455
|
|
|
private function assertListenerHasRule(ContainerBuilder $container, $id) |
456
|
|
|
{ |
457
|
|
|
$this->assertTrue($container->hasDefinition($id)); |
458
|
|
|
$listener = $container->getDefinition($id); |
459
|
|
|
$this->assertTrue($listener->hasMethodCall('addRule')); |
460
|
|
|
$this->assertCount(1, $listener->getMethodCalls()); |
461
|
|
|
} |
462
|
|
|
} |
463
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.