Skip to content

Commit 229dcc0

Browse files
committed
test(lock): add lock support to mock cache
- add an in-memory mock lock store for test environments - make MockCache provide the lock store contract used by LockManager - keep service('locks') usable under CIUnitTestCase's mocked cache Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
1 parent bb56765 commit 229dcc0

2 files changed

Lines changed: 99 additions & 1 deletion

File tree

system/Test/Mock/MockCache.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
use Closure;
1717
use CodeIgniter\Cache\CacheInterface;
1818
use CodeIgniter\Cache\Handlers\BaseHandler;
19+
use CodeIgniter\Cache\LockStoreInterface;
20+
use CodeIgniter\Cache\LockStoreProvider;
1921
use CodeIgniter\I18n\Time;
2022
use PHPUnit\Framework\Assert;
2123

22-
class MockCache extends BaseHandler implements CacheInterface
24+
class MockCache extends BaseHandler implements CacheInterface, LockStoreProvider
2325
{
2426
/**
2527
* Mock cache storage.
@@ -42,6 +44,8 @@ class MockCache extends BaseHandler implements CacheInterface
4244
*/
4345
protected $bypass = false;
4446

47+
private ?MockLockStore $lockStore = null;
48+
4549
/**
4650
* Takes care of any handler-specific setup that must be done.
4751
*/
@@ -180,6 +184,7 @@ public function clean(): true
180184
{
181185
$this->cache = [];
182186
$this->expirations = [];
187+
$this->lockStore?->clean();
183188

184189
return true;
185190
}
@@ -227,6 +232,11 @@ public function isSupported(): bool
227232
return true;
228233
}
229234

235+
public function lockStore(): LockStoreInterface
236+
{
237+
return $this->lockStore ??= new MockLockStore();
238+
}
239+
230240
// --------------------------------------------------------------------
231241
// Test Helpers
232242
// --------------------------------------------------------------------

system/Test/Mock/MockLockStore.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\Test\Mock;
15+
16+
use CodeIgniter\Cache\LockStoreInterface;
17+
use CodeIgniter\I18n\Time;
18+
19+
class MockLockStore implements LockStoreInterface
20+
{
21+
/**
22+
* @var array<string, array{owner: string, expires: int}>
23+
*/
24+
private array $locks = [];
25+
26+
public function acquireLock(string $key, string $owner, int $ttl): bool
27+
{
28+
if ($this->getLockOwner($key) !== null) {
29+
return false;
30+
}
31+
32+
$this->locks[$key] = [
33+
'owner' => $owner,
34+
'expires' => Time::now()->getTimestamp() + $ttl,
35+
];
36+
37+
return true;
38+
}
39+
40+
public function releaseLock(string $key, string $owner): bool
41+
{
42+
if ($this->getLockOwner($key) !== $owner) {
43+
return false;
44+
}
45+
46+
unset($this->locks[$key]);
47+
48+
return true;
49+
}
50+
51+
public function forceReleaseLock(string $key): bool
52+
{
53+
unset($this->locks[$key]);
54+
55+
return true;
56+
}
57+
58+
public function refreshLock(string $key, string $owner, int $ttl): bool
59+
{
60+
if ($this->getLockOwner($key) !== $owner) {
61+
return false;
62+
}
63+
64+
$this->locks[$key]['expires'] = Time::now()->getTimestamp() + $ttl;
65+
66+
return true;
67+
}
68+
69+
public function getLockOwner(string $key): ?string
70+
{
71+
if (! isset($this->locks[$key])) {
72+
return null;
73+
}
74+
75+
if ($this->locks[$key]['expires'] <= Time::now()->getTimestamp()) {
76+
unset($this->locks[$key]);
77+
78+
return null;
79+
}
80+
81+
return $this->locks[$key]['owner'];
82+
}
83+
84+
public function clean(): void
85+
{
86+
$this->locks = [];
87+
}
88+
}

0 commit comments

Comments
 (0)