1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* File contains Test class. |
5
|
|
|
* |
6
|
|
|
* @copyright Copyright (C) eZ Systems AS. All rights reserved. |
7
|
|
|
* @license For full copyright and license information view LICENSE file distributed with this source code. |
8
|
|
|
*/ |
9
|
|
|
declare(strict_types=1); |
10
|
|
|
|
11
|
|
|
namespace eZ\Publish\Core\Persistence\Cache\Tests; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Abstract test case for spi cache impl. |
15
|
|
|
*/ |
16
|
|
|
abstract class AbstractCacheHandlerTest extends AbstractBaseHandlerTest |
17
|
|
|
{ |
18
|
|
|
abstract public function getHandlerMethodName(): string; |
19
|
|
|
|
20
|
|
|
abstract public function getHandlerClassName(): string; |
21
|
|
|
|
22
|
|
|
abstract public function providerForUnCachedMethods(): array; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @dataProvider providerForUnCachedMethods |
26
|
|
|
* |
27
|
|
|
* @param string $method |
28
|
|
|
* @param array $arguments |
29
|
|
|
* @param array|null $tags |
30
|
|
|
* @param string|array|null $key |
31
|
|
|
* @param mixed $returnValue |
32
|
|
|
*/ |
33
|
|
|
final public function testUnCachedMethods(string $method, array $arguments, array $tags = null, $key = null, $returnValue = null) |
34
|
|
|
{ |
35
|
|
|
$handlerMethodName = $this->getHandlerMethodName(); |
36
|
|
|
|
37
|
|
|
$this->loggerMock->expects($this->once())->method('logCall'); |
38
|
|
|
$this->loggerMock->expects($this->never())->method('logCacheHit'); |
39
|
|
|
$this->loggerMock->expects($this->never())->method('logCacheMiss'); |
40
|
|
|
|
41
|
|
|
$innerHandler = $this->createMock($this->getHandlerClassName()); |
42
|
|
|
$this->persistenceHandlerMock |
43
|
|
|
->expects($this->once()) |
44
|
|
|
->method($handlerMethodName) |
45
|
|
|
->will($this->returnValue($innerHandler)); |
46
|
|
|
|
47
|
|
|
$innerHandler |
48
|
|
|
->expects($this->once()) |
49
|
|
|
->method($method) |
50
|
|
|
->with(...$arguments) |
51
|
|
|
->will($this->returnValue($returnValue)); |
52
|
|
|
|
53
|
|
|
if ($tags || $key) { |
54
|
|
|
$this->cacheMock |
55
|
|
|
->expects(!empty($tags) ? $this->once() : $this->never()) |
56
|
|
|
->method('invalidateTags') |
57
|
|
|
->with($tags); |
58
|
|
|
|
59
|
|
|
$this->cacheMock |
60
|
|
|
->expects(!empty($key) && is_string($key) ? $this->once() : $this->never()) |
61
|
|
|
->method('deleteItem') |
62
|
|
|
->with($key); |
63
|
|
|
|
64
|
|
|
$this->cacheMock |
65
|
|
|
->expects(!empty($key) && is_array($key) ? $this->once() : $this->never()) |
66
|
|
|
->method('deleteItems') |
67
|
|
|
->with($key); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
$handler = $this->persistenceCacheHandler->$handlerMethodName(); |
71
|
|
|
$actualReturnValue = call_user_func_array([$handler, $method], $arguments); |
72
|
|
|
|
73
|
|
|
$this->assertEquals($returnValue, $actualReturnValue); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
abstract public function providerForCachedLoadMethods(): array; |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @dataProvider providerForCachedLoadMethods |
80
|
|
|
* |
81
|
|
|
* @param string $method |
82
|
|
|
* @param array $arguments |
83
|
|
|
* @param string $key |
84
|
|
|
* @param mixed $data |
85
|
|
|
* @param bool $multi Default false, set to true if method will lookup several cache items. |
86
|
|
|
* @param array $additionalCalls Sets of additional calls being made to handlers, with 4 values (0: handler name, 1: handler class, 2: method, 3: return data) |
87
|
|
|
*/ |
88
|
|
|
final public function testLoadMethodsCacheHit(string $method, array $arguments, string $key, $data = null, bool $multi = false, array $additionalCalls = []) |
89
|
|
|
{ |
90
|
|
|
$cacheItem = $this->getCacheItem($key, $multi ? reset($data) : $data); |
91
|
|
|
$handlerMethodName = $this->getHandlerMethodName(); |
92
|
|
|
|
93
|
|
|
$this->loggerMock->expects($this->never())->method('logCall'); |
94
|
|
|
|
95
|
|
View Code Duplication |
if ($multi) { |
|
|
|
|
96
|
|
|
$this->cacheMock |
97
|
|
|
->expects($this->once()) |
98
|
|
|
->method('getItems') |
99
|
|
|
->with([$cacheItem->getKey()]) |
100
|
|
|
->willReturn([$key => $cacheItem]); |
101
|
|
|
} else { |
102
|
|
|
$this->cacheMock |
103
|
|
|
->expects($this->once()) |
104
|
|
|
->method('getItem') |
105
|
|
|
->with($cacheItem->getKey()) |
106
|
|
|
->willReturn($cacheItem); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$this->persistenceHandlerMock |
110
|
|
|
->expects($this->never()) |
111
|
|
|
->method($handlerMethodName); |
112
|
|
|
|
113
|
|
|
foreach ($additionalCalls as $additionalCall) { |
114
|
|
|
$this->persistenceHandlerMock |
115
|
|
|
->expects($this->never()) |
116
|
|
|
->method($additionalCall[0]); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
$handler = $this->persistenceCacheHandler->$handlerMethodName(); |
120
|
|
|
$return = call_user_func_array([$handler, $method], $arguments); |
121
|
|
|
|
122
|
|
|
$this->assertEquals($data, $return); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @dataProvider providerForCachedLoadMethods |
127
|
|
|
* |
128
|
|
|
* @param string $method |
129
|
|
|
* @param array $arguments |
130
|
|
|
* @param string $key |
131
|
|
|
* @param object $data |
132
|
|
|
* @param bool $multi Default false, set to true if method will lookup several cache items. |
133
|
|
|
* @param array $additionalCalls Sets of additional calls being made to handlers, with 4 values (0: handler name, 1: handler class, 2: method, 3: return data) |
134
|
|
|
*/ |
135
|
|
|
final public function testLoadMethodsCacheMiss(string $method, array $arguments, string $key, $data = null, bool $multi = false, array $additionalCalls = []) |
136
|
|
|
{ |
137
|
|
|
$cacheItem = $this->getCacheItem($key, null); |
138
|
|
|
$handlerMethodName = $this->getHandlerMethodName(); |
139
|
|
|
|
140
|
|
|
$this->loggerMock->expects($this->once())->method('logCall'); |
141
|
|
|
|
142
|
|
View Code Duplication |
if ($multi) { |
|
|
|
|
143
|
|
|
$this->cacheMock |
144
|
|
|
->expects($this->once()) |
145
|
|
|
->method('getItems') |
146
|
|
|
->with([$cacheItem->getKey()]) |
147
|
|
|
->willReturn([$key => $cacheItem]); |
148
|
|
|
} else { |
149
|
|
|
$this->cacheMock |
150
|
|
|
->expects($this->once()) |
151
|
|
|
->method('getItem') |
152
|
|
|
->with($cacheItem->getKey()) |
153
|
|
|
->willReturn($cacheItem); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
$innerHandlerMock = $this->createMock($this->getHandlerClassName()); |
157
|
|
|
$this->persistenceHandlerMock |
158
|
|
|
->expects($this->once()) |
159
|
|
|
->method($handlerMethodName) |
160
|
|
|
->willReturn($innerHandlerMock); |
161
|
|
|
|
162
|
|
|
$innerHandlerMock |
163
|
|
|
->expects($this->once()) |
164
|
|
|
->method($method) |
165
|
|
|
->with(...$arguments) |
166
|
|
|
->willReturn($data); |
167
|
|
|
|
168
|
|
View Code Duplication |
foreach ($additionalCalls as $additionalCall) { |
|
|
|
|
169
|
|
|
$innerHandlerMock = $this->createMock($additionalCall[1]); |
170
|
|
|
$this->persistenceHandlerMock |
171
|
|
|
->expects($this->once()) |
172
|
|
|
->method($additionalCall[0]) |
173
|
|
|
->willReturn($innerHandlerMock); |
174
|
|
|
|
175
|
|
|
$innerHandlerMock |
176
|
|
|
->expects($this->once()) |
177
|
|
|
->method($additionalCall[2]) |
178
|
|
|
->willReturn($additionalCall[3]); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$this->cacheMock |
182
|
|
|
->expects($this->once()) |
183
|
|
|
->method('save') |
184
|
|
|
->with($cacheItem); |
185
|
|
|
|
186
|
|
|
$handler = $this->persistenceCacheHandler->$handlerMethodName(); |
187
|
|
|
$return = call_user_func_array([$handler, $method], $arguments); |
188
|
|
|
|
189
|
|
|
$this->assertEquals($data, $return); |
190
|
|
|
|
191
|
|
|
// Assert use of tags would probably need custom logic as internal property is [$tag => $tag] value and we don't want to know that. |
192
|
|
|
//$this->assertAttributeEquals([], 'tags', $cacheItem); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
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.