SymfonyCacheTest   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 264
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 4
dl 0
loc 264
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A testInitCache() 0 17 1
A setUp() 0 21 1
A testCacheAction() 0 37 1
A testCacheActionWithInvalidToken() 0 8 1
A testCacheActionWithInvalidType() 0 9 1
A testFlushThrowsExceptionWithWrongIP() 0 24 1
A testFlushWithIPv4() 0 50 3
A testFlushWithIPv6() 0 50 3
A testCacheActionWithoutEventDispatcher() 0 15 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\CacheBundle\Tests\Adapter;
15
16
use phpmock\MockBuilder;
17
use PHPUnit\Framework\TestCase;
18
use Sonata\Cache\Exception\UnsupportedException;
19
use Sonata\CacheBundle\Adapter\SymfonyCache;
20
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
21
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
22
use Symfony\Component\Filesystem\Filesystem;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
25
use Symfony\Component\Routing\RouterInterface;
26
27
/**
28
 * @author Vincent Composieux <[email protected]>
29
 */
30
class SymfonyCacheTest extends TestCase
31
{
32
    /**
33
     * @var SymfonyCache
34
     */
35
    protected $cache;
36
37
    protected $router;
38
39
    protected $filesystem;
40
41
    private $eventDispatcher;
42
43
    /**
44
     * Sets up cache adapter.
45
     */
46
    protected function setUp(): void
47
    {
48
        $this->router = $this->createMock(RouterInterface::class);
49
        $this->filesystem = $this->createMock(Filesystem::class);
50
        $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
51
52
        $this->cache = new SymfonyCache(
53
            $this->router,
54
            $this->filesystem,
55
            '/cache/dir',
56
            'token',
57
            false,
58
            ['all', 'translations'],
59
            [],
60
            [
61
                'RCV' => ['sec' => 2, 'usec' => 0],
62
                'SND' => ['sec' => 2, 'usec' => 0],
63
            ],
64
            $this->eventDispatcher
65
        );
66
    }
67
68
    public function testInitCache(): void
69
    {
70
        $this->assertTrue($this->cache->flush([]));
71
        $this->assertTrue($this->cache->flushAll());
72
73
        $this->expectException(UnsupportedException::class);
74
        $this->expectExceptionMessage('SymfonyCache set() method does not exist.');
75
        $this->cache->set(['id' => 5], 'data');
76
77
        $this->expectException(UnsupportedException::class);
78
        $this->expectExceptionMessage('SymfonyCache get() method does not exist.');
79
        $this->cache->get(['id' => 5]);
80
81
        $this->expectException(UnsupportedException::class);
82
        $this->expectExceptionMessage('SymfonyCache has() method does not exist.');
83
        $this->cache->has(['id' => 5]);
84
    }
85
86
    public function testCacheAction(): void
87
    {
88
        $eventSubscriber = $this->createMock(EventSubscriberInterface::class);
89
        $listener = new \stdClass();
90
        $listeners = ['console.terminate' => [
91
            [
92
                $eventSubscriber,
93
                'onCommandTerminate',
94
            ],
95
            [
96
                $listener,
97
                'onTerminate',
98
            ],
99
        ]];
100
101
        // Given
102
        $this->filesystem->expects($this->once())->method('exists')->willReturn(true);
103
        $this->filesystem->expects($this->once())->method('remove');
104
        $this->eventDispatcher->expects($this->once())->method('getListeners')->willReturn($listeners);
105
        $this->eventDispatcher->expects($this->once())->method('removeSubscriber')->with($eventSubscriber);
106
        $this->eventDispatcher->expects($this->once())->method('removeListener')->with('console.terminate', [
107
            $listener,
108
            'onTerminate',
109
        ]);
110
111
        // When
112
        $response = $this->cache->cacheAction('token', 'translations');
113
114
        // Then
115
        $this->assertInstanceOf(Response::class, $response);
116
117
        $this->assertSame(200, $response->getStatusCode(), 'Response should be 200');
118
        $this->assertSame('ok', $response->getContent(), 'Response should return "OK"');
119
120
        $this->assertSame('2', $response->headers->get('Content-Length'));
121
        $this->assertSame('must-revalidate, no-cache, private', $response->headers->get('Cache-Control'));
122
    }
123
124
    public function testCacheActionWithInvalidToken(): void
125
    {
126
        // Given
127
        // When - Then expect exception
128
        $this->expectException(AccessDeniedHttpException::class);
129
130
        $this->cache->cacheAction('invalid-token', 'type');
131
    }
132
133
    public function testCacheActionWithInvalidType(): void
134
    {
135
        // Given
136
        // When - Then expect exception
137
        $this->expectException(\RuntimeException::class);
138
        $this->expectExceptionMessage('Type "invalid-type" is not defined, allowed types are: "all, translations"');
139
140
        $this->cache->cacheAction('token', 'invalid-type');
141
    }
142
143
    public function testFlushThrowsExceptionWithWrongIP(): void
144
    {
145
        $cache = new SymfonyCache(
146
            $this->router,
147
            $this->filesystem,
148
            '/cache/dir',
149
            'token',
150
            false,
151
            ['all', 'translations'],
152
            [
153
                ['ip' => 'wrong ip'],
154
            ],
155
            [
156
                'RCV' => ['sec' => 2, 'usec' => 0],
157
                'SND' => ['sec' => 2, 'usec' => 0],
158
            ],
159
            $this->eventDispatcher
160
        );
161
162
        $this->expectException(\InvalidArgumentException::class);
163
        $this->expectExceptionMessage('"wrong ip" is not a valid ip address');
164
165
        $cache->flush();
166
    }
167
168
    public function testFlushWithIPv4(): void
169
    {
170
        $cache = new SymfonyCache(
171
            $this->router,
172
            $this->filesystem,
173
            '/cache/dir',
174
            'token',
175
            false,
176
            ['all', 'translations'],
177
            [
178
                ['ip' => '213.186.35.9', 'domain' => 'www.example.com', 'basic' => false, 'port' => 80],
179
            ],
180
            [
181
                'RCV' => ['sec' => 2, 'usec' => 0],
182
                'SND' => ['sec' => 2, 'usec' => 0],
183
            ],
184
            $this->eventDispatcher
185
        );
186
187
        $mocks = [];
188
189
        $builder = new MockBuilder();
190
        $mock = $builder->setNamespace('Sonata\CacheBundle\Adapter')
191
            ->setName('socket_create')
192
            ->setFunction(function (): void {
193
                $this->assertSame([AF_INET, SOCK_STREAM, SOL_TCP], \func_get_args());
194
            })
195
            ->build();
196
        $mock->enable();
197
198
        $mocks[] = $mock;
199
200
        foreach (['socket_set_option', 'socket_connect', 'socket_write', 'socket_read'] as $function) {
201
            $builder = new MockBuilder();
202
            $mock = $builder->setNamespace('Sonata\CacheBundle\Adapter')
203
                ->setName($function)
204
                ->setFunction(static function (): void {
205
                })
206
                ->build();
207
            $mock->enable();
208
209
            $mocks[] = $mock;
210
        }
211
212
        $cache->flush();
213
214
        foreach ($mocks as $mock) {
215
            $mock->disable();
216
        }
217
    }
218
219
    /**
220
     * Tests the flush method with IPv6.
221
     */
222
    public function testFlushWithIPv6(): void
223
    {
224
        $cache = new SymfonyCache(
225
            $this->router,
226
            $this->filesystem,
227
            '/cache/dir',
228
            'token',
229
            false,
230
            ['all', 'translations'],
231
            [
232
                ['ip' => '2001:41d0:1:209:FF:FF:FF:FF', 'domain' => 'www.example.com', 'basic' => false, 'port' => 80],
233
            ],
234
            [
235
                'RCV' => ['sec' => 2, 'usec' => 0],
236
                'SND' => ['sec' => 2, 'usec' => 0],
237
            ],
238
            $this->eventDispatcher
239
        );
240
241
        $mocks = [];
242
243
        $builder = new MockBuilder();
244
        $mock = $builder->setNamespace('Sonata\CacheBundle\Adapter')
245
            ->setName('socket_create')
246
            ->setFunction(function (): void {
247
                $this->assertSame([AF_INET6, SOCK_STREAM, SOL_TCP], \func_get_args());
248
            })
249
            ->build();
250
        $mock->enable();
251
252
        $mocks[] = $mock;
253
254
        foreach (['socket_set_option', 'socket_connect', 'socket_write', 'socket_read'] as $function) {
255
            $builder = new MockBuilder();
256
            $mock = $builder->setNamespace('Sonata\CacheBundle\Adapter')
257
                ->setName($function)
258
                ->setFunction(static function (): void {
259
                })
260
                ->build();
261
            $mock->enable();
262
263
            $mocks[] = $mock;
264
        }
265
266
        $cache->flush();
267
268
        foreach ($mocks as $mock) {
269
            $mock->disable();
270
        }
271
    }
272
273
    /**
274
     * @group legacy
275
     * @expectedDeprecation Passing no 9th argument to Sonata\CacheBundle\Adapter\SymfonyCache is deprecated since version sonata-project/cache-bundle 3.x and will be mandatory in 4.0.
276
     * Pass Symfony\Component\EventDispatcher\EventDispatcherInterface as 9th argument.
277
     */
278
    public function testCacheActionWithoutEventDispatcher(): void
279
    {
280
        $cache = new SymfonyCache(
281
            $this->router,
282
            $this->filesystem,
283
            '/cache/dir',
284
            'token',
285
            false,
286
            ['all', 'translations'],
287
            [],
288
            []
289
        );
290
291
        $cache->cacheAction('token', 'translations');
292
    }
293
}
294