MediaWiki
REL1_21
|
00001 <?php 00007 class BagOStuffTest extends MediaWikiTestCase { 00008 private $cache; 00009 00010 protected function setUp() { 00011 parent::setUp(); 00012 00013 // type defined through parameter 00014 if ( $this->getCliArg( 'use-bagostuff=' ) ) { 00015 $name = $this->getCliArg( 'use-bagostuff=' ); 00016 00017 $this->cache = ObjectCache::newFromId( $name ); 00018 00019 } else { 00020 // no type defined - use simple hash 00021 $this->cache = new HashBagOStuff; 00022 } 00023 00024 $this->cache->delete( wfMemcKey( 'test' ) ); 00025 } 00026 00027 protected function tearDown() { 00028 } 00029 00030 public function testMerge() { 00031 $key = wfMemcKey( 'test' ); 00032 00033 $usleep = 0; 00034 00044 $callback = function ( BagOStuff $cache, $key, $existingValue ) use ( &$usleep ) { 00045 // let's pretend this is an expensive callback to test concurrent merge attempts 00046 usleep( $usleep ); 00047 00048 if ( $existingValue === false ) { 00049 return 'merged'; 00050 } 00051 00052 return $existingValue . 'merged'; 00053 }; 00054 00055 // merge on non-existing value 00056 $merged = $this->cache->merge( $key, $callback, 0 ); 00057 $this->assertTrue( $merged ); 00058 $this->assertEquals( $this->cache->get( $key ), 'merged' ); 00059 00060 // merge on existing value 00061 $merged = $this->cache->merge( $key, $callback, 0 ); 00062 $this->assertTrue( $merged ); 00063 $this->assertEquals( $this->cache->get( $key ), 'mergedmerged' ); 00064 00065 /* 00066 * Test concurrent merges by forking this process, if: 00067 * - not manually called with --use-bagostuff 00068 * - pcntl_fork is supported by the system 00069 * - cache type will correctly support calls over forks 00070 */ 00071 $fork = (bool)$this->getCliArg( 'use-bagostuff=' ); 00072 $fork &= function_exists( 'pcntl_fork' ); 00073 $fork &= !$this->cache instanceof HashBagOStuff; 00074 $fork &= !$this->cache instanceof EmptyBagOStuff; 00075 $fork &= !$this->cache instanceof MultiWriteBagOStuff; 00076 if ( $fork ) { 00077 // callback should take awhile now so that we can test concurrent merge attempts 00078 $usleep = 5000; 00079 00080 $pid = pcntl_fork(); 00081 if ( $pid == -1 ) { 00082 // can't fork, ignore this test... 00083 } elseif ( $pid ) { 00084 // wait a little, making sure that the child process is calling merge 00085 usleep( 3000 ); 00086 00087 // attempt a merge - this should fail 00088 $merged = $this->cache->merge( $key, $callback, 0, 1 ); 00089 00090 // merge has failed because child process was merging (and we only attempted once) 00091 $this->assertFalse( $merged ); 00092 00093 // make sure the child's merge is completed and verify 00094 usleep( 3000 ); 00095 $this->assertEquals( $this->cache->get( $key ), 'mergedmergedmerged' ); 00096 } else { 00097 $this->cache->merge( $key, $callback, 0, 1 ); 00098 00099 // Note: I'm not even going to check if the merge worked, I'll 00100 // compare values in the parent process to test if this merge worked. 00101 // I'm just going to exit this child process, since I don't want the 00102 // child to output any test results (would be rather confusing to 00103 // have test output twice) 00104 exit; 00105 } 00106 } 00107 } 00108 00109 public function testAdd() { 00110 $key = wfMemcKey( 'test' ); 00111 $this->assertTrue( $this->cache->add( $key, 'test' ) ); 00112 } 00113 00114 public function testGet() { 00115 $value = array( 'this' => 'is', 'a' => 'test' ); 00116 00117 $key = wfMemcKey( 'test' ); 00118 $this->cache->add( $key, $value ); 00119 $this->assertEquals( $this->cache->get( $key ), $value ); 00120 } 00121 00122 public function testGetMulti() { 00123 $value1 = array( 'this' => 'is', 'a' => 'test' ); 00124 $value2 = array( 'this' => 'is', 'another' => 'test' ); 00125 00126 $key1 = wfMemcKey( 'test1' ); 00127 $key2 = wfMemcKey( 'test2' ); 00128 00129 $this->cache->add( $key1, $value1 ); 00130 $this->cache->add( $key2, $value2 ); 00131 00132 $this->assertEquals( $this->cache->getMulti( array( $key1, $key2 ) ), array( $key1 => $value1, $key2 => $value2 ) ); 00133 00134 // cleanup 00135 $this->cache->delete( $key1 ); 00136 $this->cache->delete( $key2 ); 00137 } 00138 }