@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhutilKeyValueCacheTestCase extends PhutilTestCase {
4
5 public function testInRequestCache() {
6 $cache = new PhutilInRequestKeyValueCache();
7 $this->doCacheTest($cache);
8 $cache->destroyCache();
9 }
10
11 public function testInRequestCacheLimit() {
12 $cache = new PhutilInRequestKeyValueCache();
13 $cache->setLimit(4);
14
15 $cache->setKey(1, 1);
16 $cache->setKey(2, 2);
17 $cache->setKey(3, 3);
18 $cache->setKey(4, 4);
19
20 $this->assertEqual(
21 array(
22 1 => 1,
23 2 => 2,
24 3 => 3,
25 4 => 4,
26 ),
27 $cache->getAllKeys());
28
29
30 $cache->setKey(5, 5);
31
32 $this->assertEqual(
33 array(
34 2 => 2,
35 3 => 3,
36 4 => 4,
37 5 => 5,
38 ),
39 $cache->getAllKeys());
40 }
41
42 public function testOnDiskCache() {
43 $cache = new PhutilOnDiskKeyValueCache();
44 $cache->setCacheFile(new TempFile());
45 $this->doCacheTest($cache);
46 $cache->destroyCache();
47 }
48
49 public function testAPCCache() {
50 $cache = new PhutilAPCKeyValueCache();
51 if (!$cache->isAvailable()) {
52 $this->assertSkipped(pht('Cache not available.'));
53 }
54 $this->doCacheTest($cache);
55 }
56
57 public function testDirectoryCache() {
58 $cache = new PhutilDirectoryKeyValueCache();
59
60 $dir = Filesystem::createTemporaryDirectory();
61 $cache->setCacheDirectory($dir);
62 $this->doCacheTest($cache);
63 $cache->destroyCache();
64 }
65
66 public function testDirectoryCacheSpecialDirectoryRules() {
67 $cache = new PhutilDirectoryKeyValueCache();
68
69 $dir = Filesystem::createTemporaryDirectory();
70 $dir = $dir.'/dircache/';
71 $cache->setCacheDirectory($dir);
72
73 $cache->setKey('a', 1);
74 $this->assertEqual(true, Filesystem::pathExists($dir.'/a.cache'));
75
76 $cache->setKey('a/b', 1);
77 $this->assertEqual(true, Filesystem::pathExists($dir.'/a/'));
78 $this->assertEqual(true, Filesystem::pathExists($dir.'/a/b.cache'));
79
80 $cache->deleteKey('a/b');
81 $this->assertEqual(false, Filesystem::pathExists($dir.'/a/'));
82 $this->assertEqual(false, Filesystem::pathExists($dir.'/a/b.cache'));
83
84 $cache->destroyCache();
85 $this->assertEqual(false, Filesystem::pathExists($dir));
86 }
87
88 public function testNamespaceCache() {
89 $namespace = 'namespace'.mt_rand();
90 $in_request_cache = new PhutilInRequestKeyValueCache();
91 $cache = new PhutilKeyValueCacheNamespace($in_request_cache);
92 $cache->setNamespace($namespace);
93
94 $test_info = get_class($cache);
95 $keys = array(
96 'key1' => mt_rand(),
97 'key2' => '',
98 'key3' => 'Phabricator',
99 );
100 $cache->setKeys($keys);
101 $cached_keys = $in_request_cache->getAllKeys();
102
103 foreach ($keys as $key => $value) {
104 $cached_key = $namespace.':'.$key;
105
106 $this->assertTrue(
107 isset($cached_keys[$cached_key]),
108 $test_info);
109
110 $this->assertEqual(
111 $value,
112 $cached_keys[$cached_key],
113 $test_info);
114 }
115
116 $cache->destroyCache();
117
118 $this->doCacheTest($cache);
119 $cache->destroyCache();
120 }
121
122 public function testCacheStack() {
123 $req_cache = new PhutilInRequestKeyValueCache();
124 $disk_cache = new PhutilOnDiskKeyValueCache();
125 $disk_cache->setCacheFile(new TempFile());
126 $apc_cache = new PhutilAPCKeyValueCache();
127
128 $stack = array(
129 $req_cache,
130 $disk_cache,
131 );
132
133 if ($apc_cache->isAvailable()) {
134 $stack[] = $apc_cache;
135 }
136
137 $cache = new PhutilKeyValueCacheStack();
138 $cache->setCaches($stack);
139
140 $this->doCacheTest($cache);
141
142 $disk_cache->destroyCache();
143 $req_cache->destroyCache();
144 }
145
146 private function doCacheTest(PhutilKeyValueCache $cache) {
147 $key1 = 'test:'.mt_rand();
148 $key2 = 'test:'.mt_rand();
149
150 $default = 'cache-miss';
151 $value1 = 'cache-hit1';
152 $value2 = 'cache-hit2';
153
154 $test_info = get_class($cache);
155
156 // Test that we miss correctly on missing values.
157
158 $this->assertEqual(
159 $default,
160 $cache->getKey($key1, $default),
161 $test_info);
162 $this->assertEqual(
163 array(
164 ),
165 $cache->getKeys(array($key1, $key2)),
166 $test_info);
167
168
169 // Test that we can set individual keys.
170
171 $cache->setKey($key1, $value1);
172 $this->assertEqual(
173 $value1,
174 $cache->getKey($key1, $default),
175 $test_info);
176 $this->assertEqual(
177 array(
178 $key1 => $value1,
179 ),
180 $cache->getKeys(array($key1, $key2)),
181 $test_info);
182
183
184 // Test that we can delete individual keys.
185
186 $cache->deleteKey($key1);
187
188 $this->assertEqual(
189 $default,
190 $cache->getKey($key1, $default),
191 $test_info);
192 $this->assertEqual(
193 array(
194 ),
195 $cache->getKeys(array($key1, $key2)),
196 $test_info);
197
198
199
200 // Test that we can set multiple keys.
201
202 $cache->setKeys(
203 array(
204 $key1 => $value1,
205 $key2 => $value2,
206 ));
207
208 $this->assertEqual(
209 $value1,
210 $cache->getKey($key1, $default),
211 $test_info);
212 $this->assertEqual(
213 array(
214 $key1 => $value1,
215 $key2 => $value2,
216 ),
217 $cache->getKeys(array($key1, $key2)),
218 $test_info);
219
220
221 // Test that we can delete multiple keys.
222
223 $cache->deleteKeys(array($key1, $key2));
224
225 $this->assertEqual(
226 $default,
227 $cache->getKey($key1, $default),
228 $test_info);
229 $this->assertEqual(
230 array(
231 ),
232 $cache->getKeys(array($key1, $key2)),
233 $test_info);
234
235
236 // NOTE: The TTL tests are necessarily slow (we must sleep() through the
237 // TTLs) and did not work with old APC (it does not TTL until the next
238 // request) so they're disabled by default. If you're developing the cache
239 // stack, it may be useful to run them.
240
241 return;
242
243 // Test that keys expire when they TTL.
244
245 $cache->setKey($key1, $value1, 1);
246 $cache->setKey($key2, $value2, 5);
247
248 $this->assertEqual($value1, $cache->getKey($key1, $default));
249 $this->assertEqual($value2, $cache->getKey($key2, $default));
250
251 sleep(2);
252
253 $this->assertEqual($default, $cache->getKey($key1, $default));
254 $this->assertEqual($value2, $cache->getKey($key2, $default));
255
256
257 // Test that setting a 0 TTL overwrites a nonzero TTL.
258
259 $cache->setKey($key1, $value1, 1);
260 $this->assertEqual($value1, $cache->getKey($key1, $default));
261 $cache->setKey($key1, $value1, 0);
262 $this->assertEqual($value1, $cache->getKey($key1, $default));
263 sleep(2);
264 $this->assertEqual($value1, $cache->getKey($key1, $default));
265 }
266
267}