Completed
Push — inmemory-pool-decoration ( e8b077 )
by André
17:42
created

testClearAndInvalidation()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
declare(strict_types=1);
8
9
namespace eZ\Publish\Core\Persistence\Cache\Tests\Adapter;
10
11
use eZ\Publish\Core\Persistence\Cache\Adapter\InMemoryClearingProxyAdapter;
12
use eZ\Publish\Core\Persistence\Cache\InMemory\InMemoryCache;
13
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
14
use Symfony\Component\Cache\CacheItem;
15
use PHPUnit\Framework\TestCase;
16
17
/**
18
 * Abstract test case for spi cache impl.
19
 */
20
class InMemoryClearingProxyAdapterTest extends TestCase
21
{
22
    /**
23
     * @var \eZ\Publish\Core\Persistence\Cache\Adapter\InMemoryClearingProxyAdapter
24
     */
25
    protected $cache;
26
27
    /**
28
     * @var \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface|\PHPUnit\Framework\MockObject\MockObject
29
     */
30
    protected $innerPool;
31
32
    /**
33
     * @var \eZ\Publish\Core\Persistence\Cache\InMemory\InMemoryCache|\PHPUnit\Framework\MockObject\MockObject
34
     */
35
    protected $inMemory;
36
37
    /**
38
     * @var \Closure
39
     */
40
    private $cacheItemsClosure;
41
42
    /**
43
     * Setup the HandlerTest.
44
     */
45
    final protected function setUp()
46
    {
47
        parent::setUp();
48
49
        $this->innerPool = $this->createMock(TagAwareAdapterInterface::class);
50
        $this->inMemory = $this->createMock(InMemoryCache::class);
51
52
        $this->cache = new InMemoryClearingProxyAdapter(
53
            $this->innerPool,
54
            $this->inMemory
55
        );
56
57
        $this->cacheItemsClosure = \Closure::bind(
58 View Code Duplication
            static function ($key, $value, $isHit, $defaultLifetime = 0, $tags = []) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
59
                $item = new CacheItem();
60
                $item->key = $key;
0 ignored issues
show
Bug introduced by
The property key cannot be accessed from this context as it is declared protected in class Symfony\Component\Cache\CacheItem.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
61
                $item->value = $value;
0 ignored issues
show
Bug introduced by
The property value cannot be accessed from this context as it is declared protected in class Symfony\Component\Cache\CacheItem.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
62
                $item->isHit = $isHit;
0 ignored issues
show
Bug introduced by
The property isHit cannot be accessed from this context as it is declared protected in class Symfony\Component\Cache\CacheItem.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
63
                $item->prevTags = $tags;
0 ignored issues
show
Bug introduced by
The property prevTags cannot be accessed from this context as it is declared protected in class Symfony\Component\Cache\CacheItem.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
64
                $item->defaultLifetime = $defaultLifetime;
0 ignored issues
show
Bug introduced by
The property defaultLifetime cannot be accessed from this context as it is declared protected in class Symfony\Component\Cache\CacheItem.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
65
66
                return $item;
67
            },
68
            null,
69
            CacheItem::class
70
        );
71
    }
72
73
    /**
74
     * Tear down test (properties).
75
     */
76
    final protected function tearDown()
77
    {
78
        unset($this->cache);
79
        unset($this->innerPool);
80
        unset($this->inMemory);
81
82
        parent::tearDown();
83
    }
84
85
    public function testGetItem()
86
    {
87
        $item = $this->createCacheItem('first');
88
89
        $this->innerPool
90
            ->expects($this->once())
91
            ->method('getItem')
92
            ->with('first')
93
            ->willReturn($item);
94
95
        $this->inMemory->expects($this->never())->method($this->anything());
96
97
        $returnedItem = $this->cache->getItem('first');
98
        $this->assertSame($item, $returnedItem);
99
    }
100
101 View Code Duplication
    public function testGetItems()
102
    {
103
        $items = [
104
            'first' => $this->createCacheItem('first'),
105
            'second' => $this->createCacheItem('second'),
106
        ];
107
108
        $this->innerPool
109
            ->expects($this->once())
110
            ->method('getItems')
111
            ->with(['first', 'second'])
112
            ->willReturn($items);
113
114
        $this->inMemory->expects($this->never())->method($this->anything());
115
116
        $returnedItems = $this->cache->getItems(['first', 'second']);
117
        $this->assertSame($items, $returnedItems);
118
    }
119
120
    /**
121
     * Symfony uses generators with getItems() so we need to make sure we handle that.
122
     */
123 View Code Duplication
    public function testGetItemsWithGenerator()
124
    {
125
        $items = [
126
            'first' => $this->createCacheItem('first'),
127
            'second' => $this->createCacheItem('second'),
128
        ];
129
130
        $this->innerPool
131
            ->expects($this->once())
132
            ->method('getItems')
133
            ->with(['first', 'second'])
134
            ->willReturn($this->arrayAsGenerator($items));
135
136
        $this->inMemory->expects($this->never())->method($this->anything());
137
138
        $returnedItems = iterator_to_array($this->cache->getItems(['first', 'second']));
139
        $this->assertSame($items, $returnedItems);
140
    }
141
142
    public function testHasItem()
143
    {
144
        $this->innerPool
145
            ->expects($this->once())
146
            ->method('hasItem')
147
            ->with('first')
148
            ->willReturn(true);
149
150
        $this->inMemory->expects($this->never())->method($this->anything());
151
152
        $this->assertTrue($this->cache->hasItem('first'));
153
    }
154
155
    /**
156
     * @dataProvider providerForDelete
157
     */
158
    public function testDelete(string $method, $argument)
159
    {
160
        $this->innerPool
161
            ->expects($this->once())
162
            ->method($method)
163
            ->with($argument)
164
            ->willReturn(true);
165
166
        $this->inMemory
167
            ->expects($this->once())
168
            ->method('deleteMulti')
169
            ->with(is_array($argument) ? $argument : [$argument]);
170
171
        // invalidate it
172
        $this->assertTrue($this->cache->$method($argument));
173
    }
174
175
    public function providerForDelete(): array
176
    {
177
        return [
178
            ['deleteItem', 'first'],
179
            ['deleteItems', ['first']],
180
            ['deleteItems', ['first', 'second']],
181
        ];
182
    }
183
184
185
    /**
186
     * Test for clear and invalidateTags as both expects a clear to in-memory as it on purpose does not track tags.
187
     *
188
     * @dataProvider providerForClearAndInvalidation
189
     */
190
    public function testClearAndInvalidation(string $method, $argument)
191
    {
192
        if ($argument) {
193
            $this->innerPool
194
                ->expects($this->once())
195
                ->method($method)
196
                ->with($argument)
197
                ->willReturn(true);
198
        } else {
199
            $this->innerPool
200
                ->expects($this->once())
201
                ->method($method)
202
                ->willReturn(true);
203
        }
204
205
206
        $this->inMemory
207
            ->expects($this->once())
208
            ->method('clear');
209
210
        // invalidate it
211
        $this->assertTrue($this->cache->$method($argument));
212
    }
213
214
    public function providerForClearAndInvalidation(): array
215
    {
216
        return [
217
            ['invalidateTags', ['my_tag']],
218
            ['invalidateTags', ['my_tag', 'another_tag']],
219
            ['clear', null],
220
        ];
221
    }
222
223
    /**
224
     * @param $key
225
     * @param null $value If null the cache item will be assumed to be a cache miss here.
226
     * @param int $defaultLifetime
0 ignored issues
show
Bug introduced by
There is no parameter named $defaultLifetime. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
227
     *
228
     * @return CacheItem
229
     */
230
    private function createCacheItem($key, $tags = [], $value = true)
231
    {
232
        $cacheItemsClosure = $this->cacheItemsClosure;
233
234
        return $cacheItemsClosure($key, $value, (bool) $value, 0, $tags);
235
    }
236
237
    private function arrayAsGenerator(array $array)
238
    {
239
        foreach ($array as $key => $item) {
240
            yield $key => $item;
241
        }
242
    }
243
}
244