Completed
Pull Request — master (#235)
by David
03:36
created

testConfigLoadVarnishCustomClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 0
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()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Should the return type not be DefinitionDecorator|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
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