MediaWiki
REL1_30
BagOStuffTest.php
Go to the documentation of this file.
1
<?php
2
3
use Wikimedia\ScopedCallback;
4
9
class
BagOStuffTest
extends
MediaWikiTestCase
{
11
private
$cache
;
12
13
protected
function
setUp
() {
14
parent::setUp();
15
16
// type defined through parameter
17
if
( $this->
getCliArg
(
'use-bagostuff'
) ) {
18
$name = $this->
getCliArg
(
'use-bagostuff'
);
19
20
$this->
cache
= ObjectCache::newFromId( $name );
21
}
else
{
22
// no type defined - use simple hash
23
$this->
cache
=
new
HashBagOStuff
;
24
}
25
26
$this->
cache
->delete(
wfMemcKey
(
'test'
) );
27
}
28
33
public
function
testMakeKey
() {
34
$cache
= ObjectCache::newFromId(
'hash'
);
35
36
$localKey =
$cache
->
makeKey
(
'first'
,
'second'
,
'third'
);
37
$globalKey =
$cache
->
makeGlobalKey
(
'first'
,
'second'
,
'third'
);
38
39
$this->assertStringMatchesFormat(
40
'%Sfirst%Ssecond%Sthird%S'
,
41
$localKey,
42
'Local key interpolates parameters'
43
);
44
45
$this->assertStringMatchesFormat(
46
'global%Sfirst%Ssecond%Sthird%S'
,
47
$globalKey,
48
'Global key interpolates parameters and contains global prefix'
49
);
50
51
$this->assertNotEquals(
52
$localKey,
53
$globalKey,
54
'Local key and global key with same parameters should not be equal'
55
);
56
57
$this->assertNotEquals(
58
$cache
->
makeKeyInternal
(
'prefix'
, [
'a'
,
'bc:'
,
'de'
] ),
59
$cache
->
makeKeyInternal
(
'prefix'
, [
'a'
,
'bc'
,
':de'
] )
60
);
61
}
62
67
public
function
testMerge
() {
68
$key =
wfMemcKey
(
'test'
);
69
70
$usleep = 0;
71
81
$callback =
function
(
BagOStuff
$cache
, $key, $existingValue ) use ( &$usleep ) {
82
// let's pretend this is an expensive callback to test concurrent merge attempts
83
usleep( $usleep );
84
85
if
( $existingValue ===
false
) {
86
return
'merged'
;
87
}
88
89
return
$existingValue .
'merged'
;
90
};
91
92
// merge on non-existing value
93
$merged = $this->
cache
->merge( $key, $callback, 0 );
94
$this->assertTrue( $merged );
95
$this->assertEquals(
'merged'
, $this->
cache
->get( $key ) );
96
97
// merge on existing value
98
$merged = $this->
cache
->merge( $key, $callback, 0 );
99
$this->assertTrue( $merged );
100
$this->assertEquals(
'mergedmerged'
, $this->
cache
->get( $key ) );
101
102
/*
103
* Test concurrent merges by forking this process, if:
104
* - not manually called with --use-bagostuff
105
* - pcntl_fork is supported by the system
106
* - cache type will correctly support calls over forks
107
*/
108
$fork = (bool)$this->
getCliArg
(
'use-bagostuff'
);
109
$fork &= function_exists(
'pcntl_fork'
);
110
$fork &= !$this->
cache
instanceof
HashBagOStuff
;
111
$fork &= !$this->
cache
instanceof
EmptyBagOStuff
;
112
$fork &= !$this->
cache
instanceof
MultiWriteBagOStuff
;
113
if
( $fork ) {
114
// callback should take awhile now so that we can test concurrent merge attempts
115
$pid = pcntl_fork();
116
if
( $pid == -1 ) {
117
// can't fork, ignore this test...
118
} elseif ( $pid ) {
119
// wait a little, making sure that the child process is calling merge
120
usleep( 3000 );
121
122
// attempt a merge - this should fail
123
$merged = $this->
cache
->merge( $key, $callback, 0, 1 );
124
125
// merge has failed because child process was merging (and we only attempted once)
126
$this->assertFalse( $merged );
127
128
// make sure the child's merge is completed and verify
129
usleep( 3000 );
130
$this->assertEquals( $this->
cache
->get( $key ),
'mergedmergedmerged'
);
131
}
else
{
132
$this->
cache
->merge( $key, $callback, 0, 1 );
133
134
// Note: I'm not even going to check if the merge worked, I'll
135
// compare values in the parent process to test if this merge worked.
136
// I'm just going to exit this child process, since I don't want the
137
// child to output any test results (would be rather confusing to
138
// have test output twice)
139
exit;
140
}
141
}
142
}
143
147
public
function
testChangeTTL
() {
148
$key =
wfMemcKey
(
'test'
);
149
$value
=
'meow'
;
150
151
$this->
cache
->add( $key,
$value
);
152
$this->assertTrue( $this->
cache
->changeTTL( $key, 5 ) );
153
$this->assertEquals( $this->
cache
->get( $key ),
$value
);
154
$this->
cache
->delete( $key );
155
$this->assertFalse( $this->
cache
->changeTTL( $key, 5 ) );
156
}
157
161
public
function
testAdd
() {
162
$key =
wfMemcKey
(
'test'
);
163
$this->assertTrue( $this->
cache
->add( $key,
'test'
) );
164
}
165
166
public
function
testGet
() {
167
$value
= [
'this'
=>
'is'
,
'a'
=>
'test'
];
168
169
$key =
wfMemcKey
(
'test'
);
170
$this->
cache
->add( $key,
$value
);
171
$this->assertEquals( $this->
cache
->get( $key ),
$value
);
172
}
173
177
public
function
testGetWithSetCallback
() {
178
$key =
wfMemcKey
(
'test'
);
179
$value
= $this->
cache
->getWithSetCallback(
180
$key,
181
30,
182
function
() {
183
return
'hello kitty'
;
184
}
185
);
186
187
$this->assertEquals(
'hello kitty'
,
$value
);
188
$this->assertEquals(
$value
, $this->
cache
->get( $key ) );
189
}
190
194
public
function
testIncr
() {
195
$key =
wfMemcKey
(
'test'
);
196
$this->
cache
->add( $key, 0 );
197
$this->
cache
->incr( $key );
198
$expectedValue = 1;
199
$actualValue = $this->
cache
->get( $key );
200
$this->assertEquals( $expectedValue, $actualValue,
'Value should be 1 after incrementing'
);
201
}
202
206
public
function
testIncrWithInit
() {
207
$key =
wfMemcKey
(
'test'
);
208
$val = $this->
cache
->incrWithInit( $key, 0, 1, 3 );
209
$this->assertEquals( 3, $val,
"Correct init value"
);
210
211
$val = $this->
cache
->incrWithInit( $key, 0, 1, 3 );
212
$this->assertEquals( 4, $val,
"Correct init value"
);
213
}
214
218
public
function
testGetMulti
() {
219
$value1 = [
'this'
=>
'is'
,
'a'
=>
'test'
];
220
$value2 = [
'this'
=>
'is'
,
'another'
=>
'test'
];
221
$value3 = [
'testing a key that may be encoded when sent to cache backend'
];
222
$value4 = [
'another test where chars in key will be encoded'
];
223
224
$key1 =
wfMemcKey
(
'test1'
);
225
$key2 =
wfMemcKey
(
'test2'
);
226
// internally, MemcachedBagOStuffs will encode to will-%25-encode
227
$key3 =
wfMemcKey
(
'will-%-encode'
);
228
$key4 =
wfMemcKey
(
229
'flowdb:flow_ref:wiki:by-source:v3:Parser\'s_"broken"_+_(page)_&_grill:testwiki:1:4.7'
230
);
231
232
$this->
cache
->add( $key1, $value1 );
233
$this->
cache
->add( $key2, $value2 );
234
$this->
cache
->add( $key3, $value3 );
235
$this->
cache
->add( $key4, $value4 );
236
237
$this->assertEquals(
238
[ $key1 => $value1, $key2 => $value2, $key3 => $value3, $key4 => $value4 ],
239
$this->
cache
->getMulti( [ $key1, $key2, $key3, $key4 ] )
240
);
241
242
// cleanup
243
$this->
cache
->delete( $key1 );
244
$this->
cache
->delete( $key2 );
245
$this->
cache
->delete( $key3 );
246
$this->
cache
->delete( $key4 );
247
}
248
252
public
function
testGetScopedLock
() {
253
$key =
wfMemcKey
(
'test'
);
254
$value1 = $this->
cache
->getScopedLock( $key, 0 );
255
$value2 = $this->
cache
->getScopedLock( $key, 0 );
256
257
$this->
assertType
( ScopedCallback::class, $value1,
'First call returned lock'
);
258
$this->assertNull( $value2,
'Duplicate call returned no lock'
);
259
260
unset( $value1 );
261
262
$value3 = $this->
cache
->getScopedLock( $key, 0 );
263
$this->
assertType
( ScopedCallback::class, $value3,
'Lock returned callback after release'
);
264
unset( $value3 );
265
266
$value1 = $this->
cache
->getScopedLock( $key, 0, 5,
'reentry'
);
267
$value2 = $this->
cache
->getScopedLock( $key, 0, 5,
'reentry'
);
268
269
$this->
assertType
( ScopedCallback::class, $value1,
'First reentrant call returned lock'
);
270
$this->
assertType
( ScopedCallback::class, $value1,
'Second reentrant call returned lock'
);
271
}
272
277
public
function
testReportDupes
() {
278
$logger = $this->createMock( Psr\Log\NullLogger::class );
279
$logger->expects( $this->once() )
280
->method(
'warning'
)
281
->with(
'Duplicate get(): "{key}" fetched {count} times'
, [
282
'key'
=>
'foo'
,
283
'count'
=> 2,
284
] );
285
286
$cache
=
new
HashBagOStuff
( [
287
'reportDupes'
=>
true
,
288
'asyncHandler'
=>
'DeferredUpdates::addCallableUpdate'
,
289
'logger'
=> $logger,
290
] );
291
$cache
->
get
(
'foo'
);
292
$cache
->
get
(
'bar'
);
293
$cache
->
get
(
'foo'
);
294
295
DeferredUpdates::doUpdates();
296
}
297
}
wfMemcKey
wfMemcKey()
Make a cache key for the local wiki.
Definition
GlobalFunctions.php:2757
BagOStuffTest
Definition
BagOStuffTest.php:9
BagOStuffTest\$cache
BagOStuff $cache
Definition
BagOStuffTest.php:11
BagOStuffTest\testGet
testGet()
Definition
BagOStuffTest.php:166
BagOStuffTest\testAdd
testAdd()
BagOStuff::add.
Definition
BagOStuffTest.php:161
BagOStuffTest\testChangeTTL
testChangeTTL()
BagOStuff::changeTTL.
Definition
BagOStuffTest.php:147
BagOStuffTest\testGetWithSetCallback
testGetWithSetCallback()
BagOStuff::getWithSetCallback.
Definition
BagOStuffTest.php:177
BagOStuffTest\testGetScopedLock
testGetScopedLock()
BagOStuff::getScopedLock.
Definition
BagOStuffTest.php:252
BagOStuffTest\testIncrWithInit
testIncrWithInit()
BagOStuff::incrWithInit.
Definition
BagOStuffTest.php:206
BagOStuffTest\testReportDupes
testReportDupes()
BagOStuff::__construct BagOStuff::trackDuplicateKeys.
Definition
BagOStuffTest.php:277
BagOStuffTest\testGetMulti
testGetMulti()
BagOStuff::getMulti.
Definition
BagOStuffTest.php:218
BagOStuffTest\setUp
setUp()
Definition
BagOStuffTest.php:13
BagOStuffTest\testMakeKey
testMakeKey()
BagOStuff::makeGlobalKey BagOStuff::makeKeyInternal.
Definition
BagOStuffTest.php:33
BagOStuffTest\testIncr
testIncr()
BagOStuff::incr.
Definition
BagOStuffTest.php:194
BagOStuffTest\testMerge
testMerge()
BagOStuff::merge BagOStuff::mergeViaLock.
Definition
BagOStuffTest.php:67
BagOStuff
interface is intended to be more or less compatible with the PHP memcached client.
Definition
BagOStuff.php:47
BagOStuff\get
get( $key, $flags=0, $oldFlags=null)
Get an item with the given key.
Definition
BagOStuff.php:179
BagOStuff\makeGlobalKey
makeGlobalKey()
Make a global cache key.
Definition
BagOStuff.php:753
BagOStuff\makeKey
makeKey()
Make a cache key, scoped to this instance's keyspace.
Definition
BagOStuff.php:764
BagOStuff\makeKeyInternal
makeKeyInternal( $keyspace, $args)
Construct a cache key.
Definition
BagOStuff.php:737
EmptyBagOStuff
A BagOStuff object with no objects in it.
Definition
EmptyBagOStuff.php:29
HashBagOStuff
Simple store for keeping values in an associative array for the current process.
Definition
HashBagOStuff.php:31
MediaWikiTestCase
Definition
MediaWikiTestCase.php:15
MediaWikiTestCase\getCliArg
getCliArg( $offset)
Definition
MediaWikiTestCase.php:1443
MediaWikiTestCase\assertType
assertType( $type, $actual, $message='')
Asserts the type of the provided value.
Definition
MediaWikiTestCase.php:1659
MultiWriteBagOStuff
A cache class that replicates all writes to multiple child caches.
Definition
MultiWriteBagOStuff.php:31
cache
you have access to all of the normal MediaWiki so you can get a DB use the cache
Definition
maintenance.txt:55
$value
$value
Definition
styleTest.css.php:45
tests
phpunit
includes
libs
objectcache
BagOStuffTest.php
Generated on Mon Nov 25 2024 15:43:49 for MediaWiki by
1.10.0