1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Tests\Cache; |
4
|
|
|
|
5
|
|
|
use Ds\Cache\Cache; |
6
|
|
|
use Ds\Cache\CacheStorageInterface; |
7
|
|
|
use Ds\Cache\NullStorage; |
8
|
|
|
use Psr\SimpleCache\InvalidArgumentException; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Class CacheTest |
12
|
|
|
* @package Tests\Cache |
13
|
|
|
*/ |
14
|
|
|
class CacheTest extends \PHPUnit_Framework_TestCase |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var Cache |
18
|
|
|
*/ |
19
|
|
|
public $cache; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var CacheStorageInterface |
23
|
|
|
*/ |
24
|
|
|
public $storageMock; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* |
28
|
|
|
*/ |
29
|
|
|
public function setUp() |
30
|
|
|
{ |
31
|
|
|
$this->storageMock = $this->getMockBuilder(CacheStorageInterface::class)->getMock(); |
32
|
|
|
$this->cache = new Cache($this->storageMock); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Test that CacheStorageInterface::set() invalid key exception |
37
|
|
|
*/ |
38
|
|
|
public function testSetInvalidKey() |
39
|
|
|
{ |
40
|
|
|
$key = 21021000; |
41
|
|
|
$this->expectException(InvalidArgumentException::class); |
42
|
|
|
$this->cache->set($key,'value'); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Test that CacheStorageInterface::set() is called |
47
|
|
|
*/ |
48
|
|
View Code Duplication |
public function testSet() |
|
|
|
|
49
|
|
|
{ |
50
|
|
|
$key = 'key'; |
51
|
|
|
$value = 'value'; |
52
|
|
|
$expires = 10; |
53
|
|
|
|
54
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
55
|
|
|
->method('set') |
56
|
|
|
->with( |
57
|
|
|
$this->equalTo($key), |
58
|
|
|
$this->equalTo($value), |
59
|
|
|
$this->equalTo($expires) |
60
|
|
|
); |
61
|
|
|
$this->cache->set($key, $value, $expires); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Test that CacheStorageInterface::set() is called |
66
|
|
|
*/ |
67
|
|
|
public function testSetDateInterval() |
68
|
|
|
{ |
69
|
|
|
$key = 'key'; |
70
|
|
|
$value = 'value'; |
71
|
|
|
$expires = new \DateInterval('PT1H'); |
72
|
|
|
$oneHour = 60 * 60 * 1; |
73
|
|
|
|
74
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
75
|
|
|
->method('set') |
76
|
|
|
->with( |
77
|
|
|
$this->equalTo($key), |
78
|
|
|
$this->equalTo($value), |
79
|
|
|
$this->equalTo($oneHour) |
80
|
|
|
); |
81
|
|
|
|
82
|
|
|
$this->cache->set($key, $value, $expires); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Test that CacheStorageInterface::has() invalid key exception |
87
|
|
|
*/ |
88
|
|
|
public function testHasInvalidKey() |
89
|
|
|
{ |
90
|
|
|
$key = 21021000; |
91
|
|
|
$this->expectException(InvalidArgumentException::class); |
92
|
|
|
$this->cache->has($key); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Test that CacheStorageInterface::has() is called and returns true on finding key |
98
|
|
|
*/ |
99
|
|
View Code Duplication |
public function testHasFoundWithKey() |
|
|
|
|
100
|
|
|
{ |
101
|
|
|
$key = 'key'; |
102
|
|
|
$expected = true; |
103
|
|
|
|
104
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
105
|
|
|
->method('has') |
106
|
|
|
->with( |
107
|
|
|
$this->equalTo($key) |
108
|
|
|
) |
109
|
|
|
->willReturn($expected); |
110
|
|
|
|
111
|
|
|
$actual = $this->cache->has($key); |
112
|
|
|
$this->assertEquals($expected, $actual); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Test that CacheStorageInterface::has() is called and returns false on failing to find key |
117
|
|
|
*/ |
118
|
|
View Code Duplication |
public function testHasFoundNoKey() |
|
|
|
|
119
|
|
|
{ |
120
|
|
|
$key = 'key'; |
121
|
|
|
$expected = false; |
122
|
|
|
|
123
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
124
|
|
|
->method('has') |
125
|
|
|
->with( |
126
|
|
|
$this->equalTo($key) |
127
|
|
|
) |
128
|
|
|
->willReturn($expected); |
129
|
|
|
|
130
|
|
|
$actual = $this->cache->has($key); |
131
|
|
|
$this->assertEquals($expected, $actual); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Test that CacheStorageInterface::has() is called and returns false on failing to find key |
137
|
|
|
*/ |
138
|
|
|
public function testGetInvalidKey() |
139
|
|
|
{ |
140
|
|
|
$key = 21021000; |
141
|
|
|
$this->expectException(InvalidArgumentException::class); |
142
|
|
|
$this->cache->get($key); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Test that CacheStorageInterface::get() returns values when key is present. |
147
|
|
|
*/ |
148
|
|
|
public function testGetFoundValue() |
149
|
|
|
{ |
150
|
|
|
$key = 'key'; |
151
|
|
|
$expected = 'cacheValue'; |
152
|
|
|
$default = 'default value'; |
153
|
|
|
|
154
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
155
|
|
|
->method('has') |
156
|
|
|
->with( |
157
|
|
|
$this->equalTo($key) |
158
|
|
|
) |
159
|
|
|
->willReturn(true); |
160
|
|
|
|
161
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
162
|
|
|
->method('get') |
163
|
|
|
->with( |
164
|
|
|
$this->equalTo($key) |
165
|
|
|
) |
166
|
|
|
->willReturn($expected); |
167
|
|
|
|
168
|
|
|
$actual = $this->cache->get($key, $default); |
169
|
|
|
$this->assertEquals($expected, $actual); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* Test that CacheStorageInterface::get() doesn't return values and default is returned. |
174
|
|
|
*/ |
175
|
|
|
public function testGetDefaultValue() |
176
|
|
|
{ |
177
|
|
|
$key = 'key'; |
178
|
|
|
$default = 'default value'; |
179
|
|
|
|
180
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
181
|
|
|
->method('has') |
182
|
|
|
->with( |
183
|
|
|
$this->equalTo($key) |
184
|
|
|
) |
185
|
|
|
->willReturn(false); |
186
|
|
|
|
187
|
|
|
$actual = $this->cache->get($key, $default); |
188
|
|
|
$this->assertEquals($default, $actual); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Test that CacheStorageInterface::delete() is called |
193
|
|
|
*/ |
194
|
|
|
public function testDelete() |
195
|
|
|
{ |
196
|
|
|
$key = 'key'; |
197
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
198
|
|
|
->method('delete') |
199
|
|
|
->with( |
200
|
|
|
$this->equalTo($key) |
201
|
|
|
); |
202
|
|
|
$this->cache->delete($key); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* |
207
|
|
|
*/ |
208
|
|
|
public function testGetMultiple(){ |
209
|
|
|
|
210
|
|
|
$expected = [ |
211
|
|
|
'foo' => 'fooValue', |
212
|
|
|
'bar' => 'barValue', |
213
|
|
|
'baz' => 'bazValue' |
214
|
|
|
]; |
215
|
|
|
|
216
|
|
|
$i = 0; |
217
|
|
|
|
218
|
|
|
foreach ($expected as $key => $value){ |
219
|
|
|
|
220
|
|
|
$this->storageMock->expects($this->at($i)) |
|
|
|
|
221
|
|
|
->method('get') |
222
|
|
|
->with( |
223
|
|
|
$this->equalTo($key) |
224
|
|
|
) |
225
|
|
|
->willReturn($value); |
226
|
|
|
$i++; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
$actual = $this->cache->getMultiple(\array_keys($expected)); |
|
|
|
|
230
|
|
|
|
231
|
|
|
$this->assertEquals($expected, $actual); |
232
|
|
|
|
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* |
237
|
|
|
*/ |
238
|
|
|
public function testSetMultiple(){ |
239
|
|
|
|
240
|
|
|
$keys = [ |
241
|
|
|
'foo' => 'fooValue', |
242
|
|
|
'bar' => 'barValue', |
243
|
|
|
'baz' => 'bazValue' |
244
|
|
|
]; |
245
|
|
|
|
246
|
|
|
$addStatus = true; |
247
|
|
|
$expected = true; |
248
|
|
|
|
249
|
|
|
$i = 0; |
250
|
|
|
$expires = 60 * 60; |
251
|
|
|
|
252
|
|
|
foreach ($keys as $key => $value){ |
253
|
|
|
$this->storageMock->expects($this->at($i)) |
|
|
|
|
254
|
|
|
->method('set') |
255
|
|
|
->with( |
256
|
|
|
$this->equalTo($key), |
257
|
|
|
$this->equalTo($value), |
258
|
|
|
$this->equalTo($expires) |
259
|
|
|
) |
260
|
|
|
->willReturn($addStatus); |
261
|
|
|
$i++; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$actual = $this->cache->setMultiple($keys,$expires); |
|
|
|
|
265
|
|
|
$this->assertEquals($expected, $actual); |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* |
270
|
|
|
*/ |
271
|
|
|
public function testDeleteMultiple(){ |
272
|
|
|
|
273
|
|
|
$keys = ['foo','bar','baz']; |
274
|
|
|
$deleteStatus = true; |
275
|
|
|
$expected = true; |
276
|
|
|
|
277
|
|
|
foreach ($keys as $i => $key){ |
278
|
|
|
$this->storageMock->expects($this->at($i)) |
|
|
|
|
279
|
|
|
->method('delete') |
280
|
|
|
->with( |
281
|
|
|
$this->equalTo($key) |
282
|
|
|
) |
283
|
|
|
->willReturn($deleteStatus); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
$actual = $this->cache->deleteMultiple($keys); |
|
|
|
|
287
|
|
|
$this->assertEquals($expected, $actual); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* |
292
|
|
|
*/ |
293
|
|
|
public function testDeleteMultipleFailure(){ |
294
|
|
|
|
295
|
|
|
$keys = ['foo','bar','baz']; |
296
|
|
|
$expected = false; |
297
|
|
|
$deleteStatus = true; |
298
|
|
|
|
299
|
|
|
foreach ($keys as $i => $key){ |
300
|
|
|
|
301
|
|
|
if ($i === 1){ |
302
|
|
|
$deleteStatus = false; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
$this->storageMock->expects($this->at($i)) |
|
|
|
|
306
|
|
|
->method('delete') |
307
|
|
|
->with( |
308
|
|
|
$this->equalTo($key) |
309
|
|
|
) |
310
|
|
|
->willReturn($deleteStatus); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
$actual = $this->cache->deleteMultiple($keys); |
|
|
|
|
314
|
|
|
$this->assertEquals($expected, $actual); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Test that storage clear is called. |
319
|
|
|
*/ |
320
|
|
|
public function testclear(){ |
321
|
|
|
$this->storageMock->expects($this->once()) |
|
|
|
|
322
|
|
|
->method('clear'); |
323
|
|
|
$this->cache->clear(); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Test that array has keys. |
328
|
|
|
*/ |
329
|
|
View Code Duplication |
public function testArrayHasKeys(){ |
|
|
|
|
330
|
|
|
$data = ['a' => 'foo', 'b' => 'bar']; |
331
|
|
|
|
332
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
333
|
|
|
$method = $reflector->getMethod('_hasKeys'); |
334
|
|
|
$method->setAccessible(true); |
335
|
|
|
$actual = $method->invokeArgs($this->cache, [$data]); |
336
|
|
|
|
337
|
|
|
$this->assertEquals(true, $actual); |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Test exception thrown when array is missing keys. |
342
|
|
|
*/ |
343
|
|
View Code Duplication |
public function testArrayHasNoKeys(){ |
|
|
|
|
344
|
|
|
$this->expectException(InvalidArgumentException::class); |
345
|
|
|
$data = ['foo','bar']; |
346
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
347
|
|
|
$method = $reflector->getMethod('_hasKeys'); |
348
|
|
|
$method->setAccessible(true); |
349
|
|
|
$method->invokeArgs($this->cache, [$data]); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* Test array contains a failure. |
354
|
|
|
*/ |
355
|
|
View Code Duplication |
public function testHasFailure(){ |
|
|
|
|
356
|
|
|
$results = [true,true,true,false,true]; |
357
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
358
|
|
|
$method = $reflector->getMethod('_hasFailure'); |
359
|
|
|
$method->setAccessible(true); |
360
|
|
|
$actual = $method->invokeArgs($this->cache, [$results]); |
361
|
|
|
$expected = true; |
362
|
|
|
$this->assertEquals($expected, $actual); |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* Test array doesn't contain a failure. |
367
|
|
|
*/ |
368
|
|
View Code Duplication |
public function testHasNoFailure(){ |
|
|
|
|
369
|
|
|
$results = [true,true,true,true,true]; |
370
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
371
|
|
|
$method = $reflector->getMethod('_hasFailure'); |
372
|
|
|
$method->setAccessible(true); |
373
|
|
|
$actual = $method->invokeArgs($this->cache, [$results]); |
374
|
|
|
$expected = false; |
375
|
|
|
$this->assertEquals($expected, $actual); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* Test that array is Traversable |
380
|
|
|
*/ |
381
|
|
View Code Duplication |
public function testIsTraversable(){ |
|
|
|
|
382
|
|
|
$data = ['a','b','c','d']; |
383
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
384
|
|
|
$method = $reflector->getMethod('_isTraversable'); |
385
|
|
|
$method->setAccessible(true); |
386
|
|
|
$actual = $method->invokeArgs($this->cache, [$data]); |
387
|
|
|
$expected = true; |
388
|
|
|
$this->assertEquals($expected, $actual); |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Test that string is not Traversable |
393
|
|
|
*/ |
394
|
|
View Code Duplication |
public function testIsNotTraversable(){ |
|
|
|
|
395
|
|
|
$this->expectException(InvalidArgumentException::class); |
396
|
|
|
$data = 'some-random-string'; |
397
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
398
|
|
|
$method = $reflector->getMethod('_isTraversable'); |
399
|
|
|
$method->setAccessible(true); |
400
|
|
|
$method->invokeArgs($this->cache, [$data]); |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
/** |
404
|
|
|
* Test that instance of Iterator is traversable |
405
|
|
|
*/ |
406
|
|
|
public function testIsTraversableIterator(){ |
407
|
|
|
$iterator = new class implements \Iterator { |
408
|
|
|
public function current(){} |
409
|
|
|
public function next(){} |
410
|
|
|
public function key(){} |
411
|
|
|
public function valid(){} |
412
|
|
|
public function rewind(){} |
413
|
|
|
}; |
414
|
|
|
$reflector = new \ReflectionClass(Cache::class); |
415
|
|
|
$method = $reflector->getMethod('_isTraversable'); |
416
|
|
|
$method->setAccessible(true); |
417
|
|
|
$actual = $method->invokeArgs($this->cache, [$iterator]); |
418
|
|
|
$expected = true; |
419
|
|
|
$this->assertEquals($expected, $actual); |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Private functions |
425
|
|
|
*/ |
426
|
|
|
public function test_isValidKeyValid(){} |
427
|
|
|
public function test_isValidKeyInvalid(){} |
428
|
|
|
public function test_checkTraversableArray(){} |
429
|
|
|
public function test_checkTraversableTraversable(){} |
430
|
|
|
public function test_checkTraversableException(){} |
431
|
|
|
public function test_hasFailureNoFailure(){} |
432
|
|
|
public function test_hasFailureException(){} |
433
|
|
|
} |
434
|
|
|
|
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.