Completed
Push — master ( 9de1be...100987 )
by David
8s
created

FOSHttpCacheExtensionTest   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 420
Duplicated Lines 13.81 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 9
Bugs 4 Features 3
Metric Value
wmc 27
c 9
b 4
f 3
lcom 1
cbo 5
dl 58
loc 420
rs 10

19 Methods

Rating   Name   Duplication   Size   Complexity  
A testConfigLoadNginx() 22 22 1
A testConfigLoadVarnish() 0 13 1
A testConfigLoadSymfony() 23 23 1
A testEmptyConfig() 0 9 1
A testConfigTagNotSupported() 0 19 1
B testConfigLoadTagRules() 0 27 1
B testConfigLoadInvalidatorRules() 0 29 1
A testConfigLoadVarnishCustomGuzzle() 0 16 1
B testConfigUserContext() 0 28 1
B testConfigWithoutUserContext() 0 27 1
A testConfigLoadFlashMessageSubscriber() 0 10 1
A createContainer() 0 14 1
A getBaseConfig() 13 13 1
A setUp() 0 4 1
A testConfigLoadVarnishInvalidUrl() 0 8 1
B testConfigLoadCacheControl() 0 31 1
B testConfigLoadCacheControlSplit() 0 27 1
D assertMatcherCreated() 0 45 9
A assertListenerHasRule() 0 7 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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