Merge "Omit 'external' changes from ChangesFeed"
[lhc/web/wiklou.git] / tests / phpunit / includes / objectcache / BagOStuffTest.php
1 <?php
2 /**
3 * @author Matthias Mullie <mmullie@wikimedia.org>
4 */
5 class BagOStuffTest extends MediaWikiTestCase {
6 private $cache;
7
8 protected function setUp() {
9 parent::setUp();
10
11 // type defined through parameter
12 if ( $this->getCliArg( 'use-bagostuff' ) ) {
13 $name = $this->getCliArg( 'use-bagostuff' );
14
15 $this->cache = ObjectCache::newFromId( $name );
16 } else {
17 // no type defined - use simple hash
18 $this->cache = new HashBagOStuff;
19 }
20
21 $this->cache->delete( wfMemcKey( 'test' ) );
22 }
23
24 /**
25 * @covers BagOStuff::merge
26 * @covers BagOStuff::mergeViaLock
27 */
28 public function testMerge() {
29 $key = wfMemcKey( 'test' );
30
31 $usleep = 0;
32
33 /**
34 * Callback method: append "merged" to whatever is in cache.
35 *
36 * @param BagOStuff $cache
37 * @param string $key
38 * @param int $existingValue
39 * @use int $usleep
40 * @return int
41 */
42 $callback = function ( BagOStuff $cache, $key, $existingValue ) use ( &$usleep ) {
43 // let's pretend this is an expensive callback to test concurrent merge attempts
44 usleep( $usleep );
45
46 if ( $existingValue === false ) {
47 return 'merged';
48 }
49
50 return $existingValue . 'merged';
51 };
52
53 // merge on non-existing value
54 $merged = $this->cache->merge( $key, $callback, 0 );
55 $this->assertTrue( $merged );
56 $this->assertEquals( $this->cache->get( $key ), 'merged' );
57
58 // merge on existing value
59 $merged = $this->cache->merge( $key, $callback, 0 );
60 $this->assertTrue( $merged );
61 $this->assertEquals( $this->cache->get( $key ), 'mergedmerged' );
62
63 /*
64 * Test concurrent merges by forking this process, if:
65 * - not manually called with --use-bagostuff
66 * - pcntl_fork is supported by the system
67 * - cache type will correctly support calls over forks
68 */
69 $fork = (bool)$this->getCliArg( 'use-bagostuff' );
70 $fork &= function_exists( 'pcntl_fork' );
71 $fork &= !$this->cache instanceof HashBagOStuff;
72 $fork &= !$this->cache instanceof EmptyBagOStuff;
73 $fork &= !$this->cache instanceof MultiWriteBagOStuff;
74 if ( $fork ) {
75 // callback should take awhile now so that we can test concurrent merge attempts
76 $pid = pcntl_fork();
77 if ( $pid == -1 ) {
78 // can't fork, ignore this test...
79 } elseif ( $pid ) {
80 // wait a little, making sure that the child process is calling merge
81 usleep( 3000 );
82
83 // attempt a merge - this should fail
84 $merged = $this->cache->merge( $key, $callback, 0, 1 );
85
86 // merge has failed because child process was merging (and we only attempted once)
87 $this->assertFalse( $merged );
88
89 // make sure the child's merge is completed and verify
90 usleep( 3000 );
91 $this->assertEquals( $this->cache->get( $key ), 'mergedmergedmerged' );
92 } else {
93 $this->cache->merge( $key, $callback, 0, 1 );
94
95 // Note: I'm not even going to check if the merge worked, I'll
96 // compare values in the parent process to test if this merge worked.
97 // I'm just going to exit this child process, since I don't want the
98 // child to output any test results (would be rather confusing to
99 // have test output twice)
100 exit;
101 }
102 }
103 }
104
105 /**
106 * @covers BagOStuff::add
107 */
108 public function testAdd() {
109 $key = wfMemcKey( 'test' );
110 $this->assertTrue( $this->cache->add( $key, 'test' ) );
111 }
112
113 public function testGet() {
114 $value = array( 'this' => 'is', 'a' => 'test' );
115
116 $key = wfMemcKey( 'test' );
117 $this->cache->add( $key, $value );
118 $this->assertEquals( $this->cache->get( $key ), $value );
119 }
120
121 /**
122 * @covers BagOStuff::incr
123 */
124 public function testIncr() {
125 $key = wfMemcKey( 'test' );
126 $this->cache->add( $key, 0 );
127 $this->cache->incr( $key );
128 $expectedValue = 1;
129 $actualValue = $this->cache->get( $key );
130 $this->assertEquals( $expectedValue, $actualValue, 'Value should be 1 after incrementing' );
131 }
132
133 /**
134 * @covers BagOStuff::getMulti
135 */
136 public function testGetMulti() {
137 $value1 = array( 'this' => 'is', 'a' => 'test' );
138 $value2 = array( 'this' => 'is', 'another' => 'test' );
139
140 $key1 = wfMemcKey( 'test1' );
141 $key2 = wfMemcKey( 'test2' );
142
143 $this->cache->add( $key1, $value1 );
144 $this->cache->add( $key2, $value2 );
145
146 $this->assertEquals(
147 $this->cache->getMulti( array( $key1, $key2 ) ),
148 array( $key1 => $value1, $key2 => $value2 )
149 );
150
151 // cleanup
152 $this->cache->delete( $key1 );
153 $this->cache->delete( $key2 );
154 }
155 }