Passed
Push — master ( eac3f8...2377e1 )
by Alexander
01:46
created

CacheTest::dataProviderSetMultiple()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
namespace Yiisoft\Cache;
3
4
/**
5
 * Mock for the time() function for caching classes.
6
 * @return int
7
 */
8
function time(): int
9
{
10
    return \Yiisoft\Cache\Tests\CacheTest::$time ?: \time();
11
}
12
13
/**
14
 * Mock for the microtime() function for caching classes.
15
 * @param bool $float
16
 * @return float
17
 */
18
function microtime(bool $float = false): float
19
{
20
    return \Yiisoft\Cache\Tests\CacheTest::$microtime ?: \microtime($float);
21
}
22
23
namespace Yiisoft\Cache\Tests;
24
25
use Psr\SimpleCache\InvalidArgumentException;
26
use Yiisoft\Cache\CacheInterface;
27
use Yiisoft\Cache\Dependency\TagDependency;
28
29
/**
30
 * Base class for testing cache backends.
31
 */
32
abstract class CacheTest extends TestCase
33
{
34
    /**
35
     * @var int virtual time to be returned by mocked time() function.
36
     * Null means normal time() behavior.
37
     */
38
    public static $time;
39
    /**
40
     * @var float virtual time to be returned by mocked microtime() function.
41
     * Null means normal microtime() behavior.
42
     */
43
    public static $microtime;
44
45
    abstract protected function createCacheInstance(): CacheInterface;
46
47
    protected function tearDown(): void
48
    {
49
        static::$time = null;
50
        static::$microtime = null;
51
    }
52
53
    /**
54
     * This function configures given cache to match some expectations
55
     */
56
    public function prepare(CacheInterface $cache): CacheInterface
57
    {
58
        $this->assertTrue($cache->clear());
59
        $this->assertTrue($cache->set('string_test', 'string_test'));
60
        $this->assertTrue($cache->set('number_test', 42));
61
        $this->assertTrue($cache->set('array_test', ['array_test' => 'array_test']));
62
63
        return $cache;
64
    }
65
66
    public function testSet(): void
67
    {
68
        $cache = $this->createCacheInstance();
69
        for ($i = 0; $i < 2; $i++) {
70
            $this->assertTrue($cache->set('string_test', 'string_test'));
71
            $this->assertTrue($cache->set('number_test', 42));
72
            $this->assertTrue($cache->set('array_test', ['array_test' => 'array_test']));
73
        }
74
    }
75
76
    public function testGet(): void
77
    {
78
        $cache = $this->createCacheInstance();
79
        $cache = $this->prepare($cache);
80
81
        $this->assertEquals('string_test', $cache->get('string_test'));
82
        $this->assertEquals(42, $cache->get('number_test'));
83
84
        $array = $cache->get('array_test');
85
        $this->assertArrayHasKey('array_test', $array);
86
        $this->assertEquals('array_test', $array['array_test']);
87
    }
88
89
    /**
90
     * @return array testing multiSet with and without expiry
91
     */
92
    public function dataProviderSetMultiple(): array
93
    {
94
        return [[null], [2]];
95
    }
96
97
    /**
98
     * @dataProvider dataProviderSetMultiple
99
     * @param int|null $ttl
100
     * @throws InvalidArgumentException
101
     */
102
    public function testSetMultiple(?int $ttl): void
103
    {
104
        $cache = $this->createCacheInstance();
105
        $cache->clear();
106
107
        $cache->setMultiple(
108
            [
109
                'string_test' => 'string_test',
110
                'number_test' => 42,
111
                'array_test' => ['array_test' => 'array_test'],
112
            ],
113
            $ttl
114
        );
115
116
        $this->assertEquals('string_test', $cache->get('string_test'));
117
118
        $this->assertEquals(42, $cache->get('number_test'));
119
120
        $array = $cache->get('array_test');
121
        $this->assertArrayHasKey('array_test', $array);
122
        $this->assertEquals('array_test', $array['array_test']);
123
    }
124
125
    public function testHas(): void
126
    {
127
        $cache = $this->createCacheInstance();
128
        $cache = $this->prepare($cache);
129
130
        $this->assertTrue($cache->has('string_test'));
131
        // check whether exists affects the value
132
        $this->assertEquals('string_test', $cache->get('string_test'));
133
134
        $this->assertTrue($cache->has('number_test'));
135
        $this->assertFalse($cache->has('not_exists'));
136
    }
137
138
    public function testGetNonExistent(): void
139
    {
140
        $cache = $this->createCacheInstance();
141
        $this->assertNull($cache->get('non_existent_key'));
142
    }
143
144
    public function testStoreSpecialValues(): void
145
    {
146
        $cache = $this->createCacheInstance();
147
148
        $this->assertTrue($cache->set('null_value', null));
149
        $this->assertNull($cache->get('null_value'));
150
151
        $this->assertTrue($cache->set('bool_value', true));
152
        $this->assertTrue($cache->get('bool_value'));
153
    }
154
155
    public function testGetMultiple(): void
156
    {
157
        $cache = $this->createCacheInstance();
158
        $cache = $this->prepare($cache);
159
160
        $this->assertEquals(['string_test' => 'string_test', 'number_test' => 42], $cache->getMultiple(['string_test', 'number_test']));
161
        // ensure that order does not matter
162
        $this->assertEquals(['number_test' => 42, 'string_test' => 'string_test'], $cache->getMultiple(['number_test', 'string_test']));
163
        $this->assertEquals(['number_test' => 42, 'non_existent_key' => null], $cache->getMultiple(['number_test', 'non_existent_key']));
164
    }
165
166
167
    public function testExpire(): void
168
    {
169
        $cache = $this->createCacheInstance();
170
171
        $this->assertTrue($cache->set('expire_test', 'expire_test', 2));
172
        usleep(500000);
173
        $this->assertEquals('expire_test', $cache->get('expire_test'));
174
        usleep(2500000);
175
        $this->assertNull($cache->get('expire_test'));
176
    }
177
178
    public function testDelete(): void
179
    {
180
        $cache = $this->createCacheInstance();
181
        $cache = $this->prepare($cache);
182
183
        $this->assertEquals(42, $cache->get('number_test'));
184
        $this->assertTrue($cache->delete('number_test'));
185
        $this->assertNull($cache->get('number_test'));
186
    }
187
188
    public function testDeleteMultiple(): void
189
    {
190
        $cache = $this->createCacheInstance();
191
        $cache->clear();
192
193
        $cache->setMultiple([
194
            'a' => 1,
195
            'b' => 2,
196
        ]);
197
198
199
        $this->assertEquals(1, $cache->get('a'));
200
        $this->assertEquals(2, $cache->get('b'));
201
202
        $this->assertTrue($cache->deleteMultiple(['a', 'b']));
203
        $this->assertFalse($cache->has('a'));
204
        $this->assertFalse($cache->has('b'));
205
    }
206
207
    public function testClear(): void
208
    {
209
        $cache = $this->createCacheInstance();
210
        $cache = $this->prepare($cache);
211
212
        $this->assertTrue($cache->clear());
213
        $this->assertNull($cache->get('number_test'));
214
    }
215
216
    public function testExpireAdd(): void
217
    {
218
        $cache = $this->createCacheInstance();
219
220
        $this->assertTrue($cache->add('expire_testa', 'expire_testa', 2));
221
        usleep(500000);
222
        $this->assertEquals('expire_testa', $cache->get('expire_testa'));
223
        usleep(2500000);
224
        $this->assertNull($cache->get('expire_testa'));
225
    }
226
227
    public function testAdd(): void
228
    {
229
        $cache = $this->createCacheInstance();
230
        $cache = $this->prepare($cache);
231
232
        // should not change existing keys
233
        $this->assertEquals(42, $cache->get('number_test'));
234
        $this->assertFalse($cache->add('number_test', 13));
235
236
237
        // should store data if it's not there yet
238
        $this->assertNull($cache->get('add_test'));
239
        $this->assertTrue($cache->add('add_test', 13));
240
        $this->assertEquals(13, $cache->get('add_test'));
241
    }
242
243
    public function testAddMultiple(): void
244
    {
245
        $cache = $this->createCacheInstance();
246
        $cache = $this->prepare($cache);
247
248
        $this->assertNull($cache->get('add_test'));
249
250
        $this->assertTrue(
251
            $cache->addMultiple(
252
                [
253
                    'number_test' => 13,
254
                    'add_test' => 13,
255
                ]
256
            )
257
        );
258
259
        $this->assertEquals(42, $cache->get('number_test'));
260
        $this->assertEquals(13, $cache->get('add_test'));
261
    }
262
263
    public function testGetOrSet(): void
264
    {
265
        $cache = $this->createCacheInstance();
266
        $cache = $this->prepare($cache);
267
268
        $expected = get_class($cache);
269
270
        $this->assertEquals(null, $cache->get('something'));
271
        $this->assertEquals($expected, $cache->getOrSet('something', static function (CacheInterface $cache): string {
272
            return get_class($cache);
273
        }));
274
        $this->assertEquals($expected, $cache->get('something'));
275
    }
276
277
    public function testGetOrSetWithDependencies(): void
278
    {
279
        $cache = $this->createCacheInstance();
280
        $cache = $this->prepare($cache);
281
282
        $dependency = new TagDependency('test');
283
284
        $expected = 'SilverFire';
285
        $loginClosure = static function (): string {
286
            return 'SilverFire';
287
        };
288
        $this->assertEquals($expected, $cache->getOrSet('some-login', $loginClosure, null, $dependency));
289
290
        // Call again with another login to make sure that value is cached
291
        $loginClosure = static function (): string {
292
            return 'SamDark';
293
        };
294
        $cache->getOrSet('some-login', $loginClosure, null, $dependency);
295
        $this->assertEquals($expected, $cache->getOrSet('some-login', $loginClosure, null, $dependency));
296
297
        TagDependency::invalidate($cache, 'test');
298
        $expected = 'SamDark';
299
        $this->assertEquals($expected, $cache->getOrSet('some-login', $loginClosure, null, $dependency));
300
    }
301
302
    public function testWithArrayKeys(): void
303
    {
304
        $key = [42];
305
        $cache = $this->createCacheInstance();
306
        $this->assertNull($cache->get($key));
0 ignored issues
show
Bug introduced by
$key of type array<integer,integer> is incompatible with the type string expected by parameter $key of Psr\SimpleCache\CacheInterface::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

306
        $this->assertNull($cache->get(/** @scrutinizer ignore-type */ $key));
Loading history...
307
308
        $cache->set($key, 42);
309
        $this->assertSame(42, $cache->get($key));
310
    }
311
312
    public function testWithObjectKeys(): void
313
    {
314
        $key = new class {
315
            public $value = 42;
316
        };
317
        $cache = $this->createCacheInstance();
318
        $this->assertNull($cache->get($key));
0 ignored issues
show
Bug introduced by
$key of type anonymous//tests/CacheTest.php$0 is incompatible with the type string expected by parameter $key of Psr\SimpleCache\CacheInterface::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

318
        $this->assertNull($cache->get(/** @scrutinizer ignore-type */ $key));
Loading history...
319
320
        $cache->set($key, 42);
321
        $this->assertSame(42, $cache->get($key));
322
    }
323
}
324