MediaWiki
master
|
00001 <?php 00002 00012 class ProcessCacheLRUTest extends MediaWikiTestCase { 00013 00018 function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) { 00019 $this->assertAttributeEquals( array(), 'cache', $cache, $msg ); 00020 } 00021 00025 function fillCache( &$cache, $numEntries ) { 00026 // Fill cache with three values 00027 for( $i=1; $i<=$numEntries; $i++) { 00028 $cache->set( "cache-key-$i", "prop-$i", "value-$i" ); 00029 } 00030 } 00031 00036 function getExpectedCache( $cacheMaxEntries, $entryToFill ) { 00037 $expected = array(); 00038 00039 if( $entryToFill === 0 ) { 00040 # The cache is empty! 00041 return array(); 00042 } elseif( $entryToFill <= $cacheMaxEntries ) { 00043 # Cache is not fully filled 00044 $firstKey = 1; 00045 } else { 00046 # Cache overflowed 00047 $firstKey = 1 + $entryToFill - $cacheMaxEntries; 00048 } 00049 00050 $lastKey = $entryToFill; 00051 00052 for( $i=$firstKey; $i<=$lastKey; $i++ ) { 00053 $expected["cache-key-$i"] = array( "prop-$i" => "value-$i" ); 00054 } 00055 return $expected; 00056 } 00057 00061 function testPhpUnitArrayEquality() { 00062 $one = array( 'A' => 1, 'B' => 2 ); 00063 $two = array( 'B' => 2, 'A' => 1 ); 00064 $this->assertEquals( $one, $two ); // == 00065 $this->assertNotSame( $one, $two ); // === 00066 } 00067 00072 function testConstructorGivenInvalidValue( $maxSize ) { 00073 $c = new ProcessCacheLRUTestable( $maxSize ); 00074 } 00075 00079 public static function provideInvalidConstructorArg() { 00080 return array( 00081 array( null ), 00082 array( array() ), 00083 array( new stdClass() ), 00084 array( 0 ), 00085 array( '5' ), 00086 array( -1 ), 00087 ); 00088 } 00089 00090 function testAddAndGetAKey() { 00091 $oneCache = new ProcessCacheLRUTestable( 1 ); 00092 $this->assertCacheEmpty( $oneCache ); 00093 00094 // First set just one value 00095 $oneCache->set( 'cache-key', 'prop1', 'value1' ); 00096 $this->assertEquals( 1, $oneCache->getEntriesCount() ); 00097 $this->assertTrue( $oneCache->has( 'cache-key', 'prop1' ) ); 00098 $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) ); 00099 } 00100 00101 function testDeleteOldKey() { 00102 $oneCache = new ProcessCacheLRUTestable( 1 ); 00103 $this->assertCacheEmpty( $oneCache ); 00104 00105 $oneCache->set( 'cache-key', 'prop1', 'value1' ); 00106 $oneCache->set( 'cache-key', 'prop1', 'value2' ); 00107 $this->assertEquals( 'value2', $oneCache->get( 'cache-key', 'prop1' ) ); 00108 } 00109 00119 function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) { 00120 $cache = new ProcessCacheLRUTestable( $cacheMaxEntries ); 00121 $this->fillCache( $cache, $entryToFill); 00122 00123 $this->assertSame( 00124 $this->getExpectedCache( $cacheMaxEntries, $entryToFill ), 00125 $cache->getCache(), 00126 "Filling a $cacheMaxEntries entries cache with $entryToFill entries" 00127 ); 00128 00129 } 00130 00134 public static function provideCacheFilling() { 00135 // ($cacheMaxEntries, $entryToFill, $msg='') 00136 return array( 00137 array( 1, 0 ), 00138 array( 1, 1 ), 00139 array( 1, 2 ), # overflow 00140 array( 5, 33 ), # overflow 00141 ); 00142 00143 } 00144 00149 function testReplaceExistingKeyShouldBumpEntryToTop() { 00150 $maxEntries = 3; 00151 00152 $cache = new ProcessCacheLRUTestable( $maxEntries ); 00153 // Fill cache leaving just one remaining slot 00154 $this->fillCache( $cache, $maxEntries - 1 ); 00155 00156 // Set an existing cache key 00157 $cache->set( "cache-key-1", "prop-1", "new-value-for-1" ); 00158 00159 $this->assertSame( 00160 array( 00161 'cache-key-2' => array( 'prop-2' => 'value-2' ), 00162 'cache-key-1' => array( 'prop-1' => 'new-value-for-1' ), 00163 ), 00164 $cache->getCache() 00165 ); 00166 } 00167 00168 function testRecentlyAccessedKeyStickIn() { 00169 $cache = new ProcessCacheLRUTestable( 2 ); 00170 $cache->set( 'first' , 'prop1', 'value1' ); 00171 $cache->set( 'second', 'prop2', 'value2' ); 00172 00173 // Get first 00174 $cache->get( 'first', 'prop1' ); 00175 // Cache a third value, should invalidate the least used one 00176 $cache->set( 'third', 'prop3', 'value3' ); 00177 00178 $this->assertFalse( $cache->has( 'second', 'prop2' ) ); 00179 } 00180 00187 function testReplaceExistingKeyInAFullCacheShouldBumpToTop() { 00188 $maxEntries = 3; 00189 00190 $cache = new ProcessCacheLRUTestable( $maxEntries ); 00191 $this->fillCache( $cache, $maxEntries ); 00192 00193 // Set an existing cache key 00194 $cache->set( "cache-key-2", "prop-2", "new-value-for-2" ); 00195 $this->assertSame( 00196 array( 00197 'cache-key-1' => array( 'prop-1' => 'value-1' ), 00198 'cache-key-3' => array( 'prop-3' => 'value-3' ), 00199 'cache-key-2' => array( 'prop-2' => 'new-value-for-2' ), 00200 ), 00201 $cache->getCache() 00202 ); 00203 $this->assertEquals( 'new-value-for-2', 00204 $cache->get( 'cache-key-2', 'prop-2' ) 00205 ); 00206 } 00207 00208 function testBumpExistingKeyToTop() { 00209 $cache = new ProcessCacheLRUTestable( 3 ); 00210 $this->fillCache( $cache, 3 ); 00211 00212 // Set the very first cache key to a new value 00213 $cache->set( "cache-key-1", "prop-1", "new value for 1" ); 00214 $this->assertEquals( 00215 array( 00216 'cache-key-2' => array( 'prop-2' => 'value-2' ), 00217 'cache-key-3' => array( 'prop-3' => 'value-3' ), 00218 'cache-key-1' => array( 'prop-1' => 'new value for 1' ), 00219 ), 00220 $cache->getCache() 00221 ); 00222 00223 } 00224 00225 } 00226 00230 class ProcessCacheLRUTestable extends ProcessCacheLRU { 00231 public $cache = array(); 00232 00233 public function getCache() { 00234 return $this->cache; 00235 } 00236 public function getEntriesCount() { 00237 return count( $this->cache ); 00238 } 00239 }