SimpleCacheTestCase   F
last analyzed

Complexity

Total Complexity 104

Size/Duplication

Total Lines 713
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 104
lcom 1
cbo 1
dl 0
loc 713
rs 1.887
c 0
b 0
f 0

52 Methods

Rating   Name   Duplication   Size   Complexity  
createSimpleCache() 0 1 ?
A advanceTime() 0 3 1
A setUp() 0 5 1
A tearDown() 0 7 2
A invalidKeys() 0 8 1
A invalidArrayKeys() 0 21 1
A invalidTtl() 0 14 1
A validKeys() 0 6 1
A validData() 0 11 1
A testSet() 0 9 2
A testSetTtl() 0 16 2
A testSetExpiredTtl() 0 14 2
A testGet() 0 11 2
A testDelete() 0 10 2
A testClear() 0 10 2
A testSetMultiple() 0 10 2
A testSetMultipleWithIntegerArrayKey() 0 9 2
A testSetMultipleTtl() 0 17 2
A testSetMultipleExpiredTtl() 0 9 2
A testSetMultipleWithGenerator() 0 14 2
A testGetMultiple() 0 28 5
A testGetMultipleWithGenerator() 0 28 5
A testDeleteMultiple() 0 14 2
A testDeleteMultipleGenerator() 0 15 2
A testHas() 0 9 2
A testBasicUsageWithLongKey() 0 17 2
A testGetInvalidKeys() 0 8 2
A testGetMultipleInvalidKeys() 0 8 2
A testGetMultipleNoIterable() 0 8 2
A testSetInvalidKeys() 0 8 2
A testSetMultipleInvalidKeys() 0 13 2
A testSetMultipleNoIterable() 0 8 2
A testHasInvalidKeys() 0 8 2
A testDeleteInvalidKeys() 0 8 2
A testDeleteMultipleInvalidKeys() 0 8 2
A testDeleteMultipleNoIterable() 0 8 2
A testSetInvalidTtl() 0 8 2
A testSetMultipleInvalidTtl() 0 8 2
A testNullOverwrite() 0 10 2
A testDataTypeString() 0 10 2
A testDataTypeInteger() 0 10 2
A testDataTypeFloat() 0 11 2
A testDataTypeBoolean() 0 11 2
A testDataTypeArray() 0 11 2
A testDataTypeObject() 0 12 2
A testBinaryData() 0 15 3
A testSetValidKeys() 0 8 2
A testSetMultipleValidKeys() 0 15 3
A testSetValidData() 0 8 2
A testSetMultipleValidData() 0 14 3
A testObjectAsDefaultValue() 0 9 2
A testObjectDoesNotChangeInCache() 0 13 2

How to fix   Complexity   

Complex Class

Complex classes like SimpleCacheTestCase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SimpleCacheTestCase, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Wikibase\Lib\Tests;
4
5
/*
6
 * This file was originally part of php-cache organization. It was copied in context of
7
 * https://phabricator.wikimedia.org/T237164#6234226.
8
 *
9
 * The original from which this file was copied is
10
 * https://github.com/php-cache/integration-tests/blob/e023fbe54c9821dfefbe04db0074ee8682f7f577/src/SimpleCacheTest.php
11
 *
12
 * See there for the original version of this comment.
13
 */
14
15
use PHPUnit\Framework\TestCase;
16
use Psr\SimpleCache\CacheInterface;
17
18
/**
19
 * All modifications to the original MIT-licensed file are made under
20
 * @license GPL-2.0-or-later
21
 */
22
abstract class SimpleCacheTestCase extends TestCase {
23
24
	/**
25
	 * @var array with functionName => reason.
26
	 */
27
	protected $skippedTests = [];
28
29
	/**
30
	 * @var CacheInterface
31
	 */
32
	protected $cache;
33
34
	/**
35
	 * @return CacheInterface that is used in the tests
36
	 */
37
	abstract public function createSimpleCache();
38
39
	/**
40
	 * Advance time perceived by the cache for the purposes of testing TTL.
41
	 *
42
	 * The default implementation sleeps for the specified duration,
43
	 * but subclasses are encouraged to override this,
44
	 * adjusting a mocked time possibly set up in {@link createSimpleCache()},
45
	 * to speed up the tests.
46
	 *
47
	 * @param int $seconds
48
	 */
49
	public function advanceTime( $seconds ) {
50
		sleep( $seconds );
51
	}
52
53
	protected function setUp(): void {
54
		parent::setUp();
55
56
		$this->cache = $this->createSimpleCache();
57
	}
58
59
	protected function tearDown(): void {
60
		parent::tearDown();
61
62
		if ( $this->cache !== null ) {
63
			$this->cache->clear();
64
		}
65
	}
66
67
	/**
68
	 * Data provider for invalid cache keys.
69
	 *
70
	 * @return array
71
	 */
72
	public static function invalidKeys() {
73
		return array_merge(
74
			self::invalidArrayKeys(),
75
			[
76
				[ 2 ],
77
			]
78
		);
79
	}
80
81
	/**
82
	 * Data provider for invalid array keys.
83
	 *
84
	 * @return array
85
	 */
86
	public static function invalidArrayKeys() {
87
		return [
88
			[ '' ],
89
			[ true ],
90
			[ false ],
91
			[ null ],
92
			[ 2.5 ],
93
			[ '{str' ],
94
			[ 'rand{' ],
95
			[ 'rand{str' ],
96
			[ 'rand}str' ],
97
			[ 'rand(str' ],
98
			[ 'rand)str' ],
99
			[ 'rand/str' ],
100
			[ 'rand\\str' ],
101
			[ 'rand@str' ],
102
			[ 'rand:str' ],
103
			[ new \stdClass() ],
104
			[ [ 'array' ] ],
105
		];
106
	}
107
108
	/**
109
	 * @return array
110
	 */
111
	public static function invalidTtl() {
112
		return [
113
			[ '' ],
114
			[ true ],
115
			[ false ],
116
			[ 'abc' ],
117
			[ 2.5 ],
118
			[ ' 1' ], // can be casted to a int
119
			[ '12foo' ], // can be casted to a int
120
			[ '025' ], // can be interpreted as hex
121
			[ new \stdClass() ],
122
			[ [ 'array' ] ],
123
		];
124
	}
125
126
	/**
127
	 * Data provider for valid keys.
128
	 *
129
	 * @return array
130
	 */
131
	public static function validKeys() {
132
		return [
133
			[ 'AbC19_.' ],
134
			[ '1234567890123456789012345678901234567890123456789012345678901234' ],
135
		];
136
	}
137
138
	/**
139
	 * Data provider for valid data to store.
140
	 *
141
	 * @return array
142
	 */
143
	public static function validData() {
144
		return [
145
			[ 'AbC19_.' ],
146
			[ 4711 ],
147
			[ 47.11 ],
148
			[ true ],
149
			[ null ],
150
			[ [ 'key' => 'value' ] ],
151
			[ new \stdClass() ],
152
		];
153
	}
154
155
	public function testSet() {
156
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
157
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
158
		}
159
160
		$result = $this->cache->set( 'key', 'value' );
161
		$this->assertTrue( $result, 'set() must return true if success' );
162
		$this->assertEquals( 'value', $this->cache->get( 'key' ) );
163
	}
164
165
	public function testSetTtl() {
166
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
167
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
168
		}
169
170
		$result = $this->cache->set( 'key1', 'value', 1 );
171
		$this->assertTrue( $result, 'set() must return true if success' );
172
		$this->assertEquals( 'value', $this->cache->get( 'key1' ) );
173
		$this->advanceTime( 2 );
174
		$this->assertNull( $this->cache->get( 'key1' ), 'Value must expire after ttl.' );
175
176
		$this->cache->set( 'key2', 'value', new \DateInterval( 'PT1S' ) );
177
		$this->assertEquals( 'value', $this->cache->get( 'key2' ) );
178
		$this->advanceTime( 2 );
179
		$this->assertNull( $this->cache->get( 'key2' ), 'Value must expire after ttl.' );
180
	}
181
182
	public function testSetExpiredTtl() {
183
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
184
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
185
		}
186
187
		$this->cache->set( 'key0', 'value' );
188
		$this->cache->set( 'key0', 'value', 0 );
189
		$this->assertNull( $this->cache->get( 'key0' ) );
190
		$this->assertFalse( $this->cache->has( 'key0' ) );
191
192
		$this->cache->set( 'key1', 'value', -1 );
193
		$this->assertNull( $this->cache->get( 'key1' ) );
194
		$this->assertFalse( $this->cache->has( 'key1' ) );
195
	}
196
197
	public function testGet() {
198
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
199
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
200
		}
201
202
		$this->assertNull( $this->cache->get( 'key' ) );
203
		$this->assertEquals( 'foo', $this->cache->get( 'key', 'foo' ) );
204
205
		$this->cache->set( 'key', 'value' );
206
		$this->assertEquals( 'value', $this->cache->get( 'key', 'foo' ) );
207
	}
208
209
	public function testDelete() {
210
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
211
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
212
		}
213
214
		$this->assertTrue( $this->cache->delete( 'key' ), 'Deleting a value that does not exist should return true' );
215
		$this->cache->set( 'key', 'value' );
216
		$this->assertTrue( $this->cache->delete( 'key' ), 'Delete must return true on success' );
217
		$this->assertNull( $this->cache->get( 'key' ), 'Values must be deleted on delete()' );
218
	}
219
220
	public function testClear() {
221
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
222
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
223
		}
224
225
		$this->assertTrue( $this->cache->clear(), 'Clearing an empty cache should return true' );
226
		$this->cache->set( 'key', 'value' );
227
		$this->assertTrue( $this->cache->clear(), 'Delete must return true on success' );
228
		$this->assertNull( $this->cache->get( 'key' ), 'Values must be deleted on clear()' );
229
	}
230
231
	public function testSetMultiple() {
232
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
233
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
234
		}
235
236
		$result = $this->cache->setMultiple( [ 'key0' => 'value0', 'key1' => 'value1' ] );
0 ignored issues
show
Documentation introduced by
array('key0' => 'value0', 'key1' => 'value1') is of type array<string,string,{"ke...ring","key1":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
237
		$this->assertTrue( $result, 'setMultiple() must return true if success' );
238
		$this->assertEquals( 'value0', $this->cache->get( 'key0' ) );
239
		$this->assertEquals( 'value1', $this->cache->get( 'key1' ) );
240
	}
241
242
	public function testSetMultipleWithIntegerArrayKey() {
243
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
244
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
245
		}
246
247
		$result = $this->cache->setMultiple( [ '0' => 'value0' ] );
0 ignored issues
show
Documentation introduced by
array('0' => 'value0') is of type array<string,string,{"0":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
248
		$this->assertTrue( $result, 'setMultiple() must return true if success' );
249
		$this->assertEquals( 'value0', $this->cache->get( '0' ) );
250
	}
251
252
	public function testSetMultipleTtl() {
253
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
254
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
255
		}
256
257
		$this->cache->setMultiple( [ 'key2' => 'value2', 'key3' => 'value3' ], 1 );
0 ignored issues
show
Documentation introduced by
array('key2' => 'value2', 'key3' => 'value3') is of type array<string,string,{"ke...ring","key3":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
258
		$this->assertEquals( 'value2', $this->cache->get( 'key2' ) );
259
		$this->assertEquals( 'value3', $this->cache->get( 'key3' ) );
260
		$this->advanceTime( 2 );
261
		$this->assertNull( $this->cache->get( 'key2' ), 'Value must expire after ttl.' );
262
		$this->assertNull( $this->cache->get( 'key3' ), 'Value must expire after ttl.' );
263
264
		$this->cache->setMultiple( [ 'key4' => 'value4' ], new \DateInterval( 'PT1S' ) );
0 ignored issues
show
Documentation introduced by
array('key4' => 'value4') is of type array<string,string,{"key4":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
265
		$this->assertEquals( 'value4', $this->cache->get( 'key4' ) );
266
		$this->advanceTime( 2 );
267
		$this->assertNull( $this->cache->get( 'key4' ), 'Value must expire after ttl.' );
268
	}
269
270
	public function testSetMultipleExpiredTtl() {
271
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
272
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
273
		}
274
275
		$this->cache->setMultiple( [ 'key0' => 'value0', 'key1' => 'value1' ], 0 );
0 ignored issues
show
Documentation introduced by
array('key0' => 'value0', 'key1' => 'value1') is of type array<string,string,{"ke...ring","key1":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
276
		$this->assertNull( $this->cache->get( 'key0' ) );
277
		$this->assertNull( $this->cache->get( 'key1' ) );
278
	}
279
280
	public function testSetMultipleWithGenerator() {
281
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
282
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
283
		}
284
285
		$gen = function () {
286
			yield 'key0' => 'value0';
287
			yield 'key1' => 'value1';
288
		};
289
290
		$this->cache->setMultiple( $gen() );
291
		$this->assertEquals( 'value0', $this->cache->get( 'key0' ) );
292
		$this->assertEquals( 'value1', $this->cache->get( 'key1' ) );
293
	}
294
295
	public function testGetMultiple() {
296
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
297
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
298
		}
299
300
		$result = $this->cache->getMultiple( [ 'key0', 'key1' ] );
0 ignored issues
show
Documentation introduced by
array('key0', 'key1') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
301
		$keys = [];
302
		foreach ( $result as $i => $r ) {
303
			$keys[] = $i;
304
			$this->assertNull( $r );
305
		}
306
		sort( $keys );
307
		$this->assertSame( [ 'key0', 'key1' ], $keys );
308
309
		$this->cache->set( 'key3', 'value' );
310
		$result = $this->cache->getMultiple( [ 'key2', 'key3', 'key4' ], 'foo' );
0 ignored issues
show
Documentation introduced by
array('key2', 'key3', 'key4') is of type array<integer,string,{"0..."string","2":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
311
		$keys = [];
312
		foreach ( $result as $key => $r ) {
313
			$keys[] = $key;
314
			if ( $key === 'key3' ) {
315
				$this->assertEquals( 'value', $r );
316
			} else {
317
				$this->assertEquals( 'foo', $r );
318
			}
319
		}
320
		sort( $keys );
321
		$this->assertSame( [ 'key2', 'key3', 'key4' ], $keys );
322
	}
323
324
	public function testGetMultipleWithGenerator() {
325
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
326
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
327
		}
328
329
		$gen = function () {
330
			yield 1 => 'key0';
331
			yield 1 => 'key1';
332
		};
333
334
		$this->cache->set( 'key0', 'value0' );
335
		$result = $this->cache->getMultiple( $gen() );
336
		$keys = [];
337
		foreach ( $result as $key => $r ) {
338
			$keys[] = $key;
339
			if ( $key === 'key0' ) {
340
				$this->assertEquals( 'value0', $r );
341
			} elseif ( $key === 'key1' ) {
342
				$this->assertNull( $r );
343
			} else {
344
				$this->assertFalse( true, 'This should not happend' );
345
			}
346
		}
347
		sort( $keys );
348
		$this->assertSame( [ 'key0', 'key1' ], $keys );
349
		$this->assertEquals( 'value0', $this->cache->get( 'key0' ) );
350
		$this->assertNull( $this->cache->get( 'key1' ) );
351
	}
352
353
	public function testDeleteMultiple() {
354
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
355
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
356
		}
357
358
		$this->assertTrue( $this->cache->deleteMultiple( [] ), 'Deleting a empty array should return true' );
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
359
		$this->assertTrue( $this->cache->deleteMultiple( [ 'key' ] ), 'Deleting a value that does not exist should return true' );
0 ignored issues
show
Documentation introduced by
array('key') is of type array<integer,string,{"0":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
360
361
		$this->cache->set( 'key0', 'value0' );
362
		$this->cache->set( 'key1', 'value1' );
363
		$this->assertTrue( $this->cache->deleteMultiple( [ 'key0', 'key1' ] ), 'Delete must return true on success' );
0 ignored issues
show
Documentation introduced by
array('key0', 'key1') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
364
		$this->assertNull( $this->cache->get( 'key0' ), 'Values must be deleted on deleteMultiple()' );
365
		$this->assertNull( $this->cache->get( 'key1' ), 'Values must be deleted on deleteMultiple()' );
366
	}
367
368
	public function testDeleteMultipleGenerator() {
369
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
370
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
371
		}
372
373
		$gen = function () {
374
			yield 1 => 'key0';
375
			yield 1 => 'key1';
376
		};
377
		$this->cache->set( 'key0', 'value0' );
378
		$this->assertTrue( $this->cache->deleteMultiple( $gen() ), 'Deleting a generator should return true' );
379
380
		$this->assertNull( $this->cache->get( 'key0' ), 'Values must be deleted on deleteMultiple()' );
381
		$this->assertNull( $this->cache->get( 'key1' ), 'Values must be deleted on deleteMultiple()' );
382
	}
383
384
	public function testHas() {
385
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
386
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
387
		}
388
389
		$this->assertFalse( $this->cache->has( 'key0' ) );
390
		$this->cache->set( 'key0', 'value0' );
391
		$this->assertTrue( $this->cache->has( 'key0' ) );
392
	}
393
394
	public function testBasicUsageWithLongKey() {
395
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
396
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
397
		}
398
399
		$key = str_repeat( 'a', 300 );
400
401
		$this->assertFalse( $this->cache->has( $key ) );
402
		$this->assertTrue( $this->cache->set( $key, 'value' ) );
403
404
		$this->assertTrue( $this->cache->has( $key ) );
405
		$this->assertSame( 'value', $this->cache->get( $key ) );
406
407
		$this->assertTrue( $this->cache->delete( $key ) );
408
409
		$this->assertFalse( $this->cache->has( $key ) );
410
	}
411
412
	/**
413
	 * @dataProvider invalidKeys
414
	 */
415
	public function testGetInvalidKeys( $key ) {
416
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
417
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
418
		}
419
420
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
421
		$this->cache->get( $key );
422
	}
423
424
	/**
425
	 * @dataProvider invalidKeys
426
	 */
427
	public function testGetMultipleInvalidKeys( $key ) {
428
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
429
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
430
		}
431
432
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
433
		$result = $this->cache->getMultiple( [ 'key1', $key, 'key2' ] );
0 ignored issues
show
Documentation introduced by
array('key1', $key, 'key2') is of type array<integer,?,{"0":"st...,"1":"?","2":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
434
	}
435
436
	public function testGetMultipleNoIterable() {
437
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
438
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
439
		}
440
441
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
442
		$result = $this->cache->getMultiple( 'key' );
0 ignored issues
show
Documentation introduced by
'key' is of type string, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
443
	}
444
445
	/**
446
	 * @dataProvider invalidKeys
447
	 */
448
	public function testSetInvalidKeys( $key ) {
449
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
450
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
451
		}
452
453
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
454
		$this->cache->set( $key, 'foobar' );
455
	}
456
457
	/**
458
	 * @dataProvider invalidArrayKeys
459
	 */
460
	public function testSetMultipleInvalidKeys( $key ) {
461
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
462
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
463
		}
464
465
		$values = function () use ( $key ) {
466
			yield 'key1' => 'foo';
467
			yield $key => 'bar';
468
			yield 'key2' => 'baz';
469
		};
470
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
471
		$this->cache->setMultiple( $values() );
472
	}
473
474
	public function testSetMultipleNoIterable() {
475
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
476
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
477
		}
478
479
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
480
		$this->cache->setMultiple( 'key' );
0 ignored issues
show
Documentation introduced by
'key' is of type string, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
481
	}
482
483
	/**
484
	 * @dataProvider invalidKeys
485
	 */
486
	public function testHasInvalidKeys( $key ) {
487
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
488
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
489
		}
490
491
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
492
		$this->cache->has( $key );
493
	}
494
495
	/**
496
	 * @dataProvider invalidKeys
497
	 */
498
	public function testDeleteInvalidKeys( $key ) {
499
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
500
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
501
		}
502
503
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
504
		$this->cache->delete( $key );
505
	}
506
507
	/**
508
	 * @dataProvider invalidKeys
509
	 */
510
	public function testDeleteMultipleInvalidKeys( $key ) {
511
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
512
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
513
		}
514
515
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
516
		$this->cache->deleteMultiple( [ 'key1', $key, 'key2' ] );
0 ignored issues
show
Documentation introduced by
array('key1', $key, 'key2') is of type array<integer,?,{"0":"st...,"1":"?","2":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
517
	}
518
519
	public function testDeleteMultipleNoIterable() {
520
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
521
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
522
		}
523
524
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
525
		$this->cache->deleteMultiple( 'key' );
0 ignored issues
show
Documentation introduced by
'key' is of type string, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
526
	}
527
528
	/**
529
	 * @dataProvider invalidTtl
530
	 */
531
	public function testSetInvalidTtl( $ttl ) {
532
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
533
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
534
		}
535
536
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
537
		$this->cache->set( 'key', 'value', $ttl );
538
	}
539
540
	/**
541
	 * @dataProvider invalidTtl
542
	 */
543
	public function testSetMultipleInvalidTtl( $ttl ) {
544
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
545
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
546
		}
547
548
		$this->expectException( 'Psr\SimpleCache\InvalidArgumentException' );
549
		$this->cache->setMultiple( [ 'key' => 'value' ], $ttl );
0 ignored issues
show
Documentation introduced by
array('key' => 'value') is of type array<string,string,{"key":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
550
	}
551
552
	public function testNullOverwrite() {
553
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
554
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
555
		}
556
557
		$this->cache->set( 'key', 5 );
558
		$this->cache->set( 'key', null );
559
560
		$this->assertNull( $this->cache->get( 'key' ), 'Setting null to a key must overwrite previous value' );
561
	}
562
563
	public function testDataTypeString() {
564
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
565
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
566
		}
567
568
		$this->cache->set( 'key', '5' );
569
		$result = $this->cache->get( 'key' );
570
		$this->assertTrue( '5' === $result, 'Wrong data type. If we store a string we must get an string back.' );
571
		$this->assertTrue( is_string( $result ), 'Wrong data type. If we store a string we must get an string back.' );
572
	}
573
574
	public function testDataTypeInteger() {
575
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
576
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
577
		}
578
579
		$this->cache->set( 'key', 5 );
580
		$result = $this->cache->get( 'key' );
581
		$this->assertTrue( 5 === $result, 'Wrong data type. If we store an int we must get an int back.' );
582
		$this->assertTrue( is_int( $result ), 'Wrong data type. If we store an int we must get an int back.' );
583
	}
584
585
	public function testDataTypeFloat() {
586
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
587
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
588
		}
589
590
		$float = 1.23456789;
591
		$this->cache->set( 'key', $float );
592
		$result = $this->cache->get( 'key' );
593
		$this->assertTrue( is_float( $result ), 'Wrong data type. If we store float we must get an float back.' );
594
		$this->assertEquals( $float, $result );
595
	}
596
597
	public function testDataTypeBoolean() {
598
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
599
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
600
		}
601
602
		$this->cache->set( 'key', false );
603
		$result = $this->cache->get( 'key' );
604
		$this->assertTrue( is_bool( $result ), 'Wrong data type. If we store boolean we must get an boolean back.' );
605
		$this->assertFalse( $result );
606
		$this->assertTrue( $this->cache->has( 'key' ), 'has() should return true when true are stored. ' );
607
	}
608
609
	public function testDataTypeArray() {
610
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
611
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
612
		}
613
614
		$array = [ 'a' => 'foo', 2 => 'bar' ];
615
		$this->cache->set( 'key', $array );
616
		$result = $this->cache->get( 'key' );
617
		$this->assertTrue( is_array( $result ), 'Wrong data type. If we store array we must get an array back.' );
618
		$this->assertEquals( $array, $result );
619
	}
620
621
	public function testDataTypeObject() {
622
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
623
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
624
		}
625
626
		$object = new \stdClass();
627
		$object->a = 'foo';
628
		$this->cache->set( 'key', $object );
629
		$result = $this->cache->get( 'key' );
630
		$this->assertTrue( is_object( $result ), 'Wrong data type. If we store object we must get an object back.' );
631
		$this->assertEquals( $object, $result );
632
	}
633
634
	public function testBinaryData() {
635
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
636
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
637
		}
638
639
		$data = '';
640
		for ( $i = 0; $i < 256; $i++ ) {
641
			$data .= chr( $i );
642
		}
643
644
		$array = [ 'a' => 'foo', 2 => 'bar' ];
0 ignored issues
show
Unused Code introduced by
$array is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
645
		$this->cache->set( 'key', $data );
646
		$result = $this->cache->get( 'key' );
647
		$this->assertTrue( $data === $result, 'Binary data must survive a round trip.' );
648
	}
649
650
	/**
651
	 * @dataProvider validKeys
652
	 */
653
	public function testSetValidKeys( $key ) {
654
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
655
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
656
		}
657
658
		$this->cache->set( $key, 'foobar' );
659
		$this->assertEquals( 'foobar', $this->cache->get( $key ) );
660
	}
661
662
	/**
663
	 * @dataProvider validKeys
664
	 */
665
	public function testSetMultipleValidKeys( $key ) {
666
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
667
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
668
		}
669
670
		$this->cache->setMultiple( [ $key => 'foobar' ] );
0 ignored issues
show
Documentation introduced by
array($key => 'foobar') is of type array<?,string>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
671
		$result = $this->cache->getMultiple( [ $key ] );
0 ignored issues
show
Documentation introduced by
array($key) is of type array<integer,?,{"0":"?"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
672
		$keys = [];
673
		foreach ( $result as $i => $r ) {
674
			$keys[] = $i;
675
			$this->assertEquals( $key, $i );
676
			$this->assertEquals( 'foobar', $r );
677
		}
678
		$this->assertSame( [ $key ], $keys );
679
	}
680
681
	/**
682
	 * @dataProvider validData
683
	 */
684
	public function testSetValidData( $data ) {
685
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
686
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
687
		}
688
689
		$this->cache->set( 'key', $data );
690
		$this->assertEquals( $data, $this->cache->get( 'key' ) );
691
	}
692
693
	/**
694
	 * @dataProvider validData
695
	 */
696
	public function testSetMultipleValidData( $data ) {
697
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
698
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
699
		}
700
701
		$this->cache->setMultiple( [ 'key' => $data ] );
0 ignored issues
show
Documentation introduced by
array('key' => $data) is of type array<string,?,{"key":"?"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
702
		$result = $this->cache->getMultiple( [ 'key' ] );
0 ignored issues
show
Documentation introduced by
array('key') is of type array<integer,string,{"0":"string"}>, but the function expects a object<Psr\SimpleCache\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
703
		$keys = [];
704
		foreach ( $result as $i => $r ) {
705
			$keys[] = $i;
706
			$this->assertEquals( $data, $r );
707
		}
708
		$this->assertSame( [ 'key' ], $keys );
709
	}
710
711
	public function testObjectAsDefaultValue() {
712
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
713
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
714
		}
715
716
		$obj = new \stdClass();
717
		$obj->foo = 'value';
718
		$this->assertEquals( $obj, $this->cache->get( 'key', $obj ) );
719
	}
720
721
	public function testObjectDoesNotChangeInCache() {
722
		if ( isset( $this->skippedTests[__FUNCTION__] ) ) {
723
			$this->markTestSkipped( $this->skippedTests[__FUNCTION__] );
724
		}
725
726
		$obj = new \stdClass();
727
		$obj->foo = 'value';
728
		$this->cache->set( 'key', $obj );
729
		$obj->foo = 'changed';
730
731
		$cacheObject = $this->cache->get( 'key' );
732
		$this->assertEquals( 'value', $cacheObject->foo, 'Object in cache should not have their values changed.' );
733
	}
734
}
735