MediaWiki
REL1_22
|
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 00056 return $expected; 00057 } 00058 00062 public function testPhpUnitArrayEquality() { 00063 $one = array( 'A' => 1, 'B' => 2 ); 00064 $two = array( 'B' => 2, 'A' => 1 ); 00065 $this->assertEquals( $one, $two ); // == 00066 $this->assertNotSame( $one, $two ); // === 00067 } 00068 00073 public function testConstructorGivenInvalidValue( $maxSize ) { 00074 new ProcessCacheLRUTestable( $maxSize ); 00075 } 00076 00080 public static function provideInvalidConstructorArg() { 00081 return array( 00082 array( null ), 00083 array( array() ), 00084 array( new stdClass() ), 00085 array( 0 ), 00086 array( '5' ), 00087 array( -1 ), 00088 ); 00089 } 00090 00091 public function testAddAndGetAKey() { 00092 $oneCache = new ProcessCacheLRUTestable( 1 ); 00093 $this->assertCacheEmpty( $oneCache ); 00094 00095 // First set just one value 00096 $oneCache->set( 'cache-key', 'prop1', 'value1' ); 00097 $this->assertEquals( 1, $oneCache->getEntriesCount() ); 00098 $this->assertTrue( $oneCache->has( 'cache-key', 'prop1' ) ); 00099 $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) ); 00100 } 00101 00102 public function testDeleteOldKey() { 00103 $oneCache = new ProcessCacheLRUTestable( 1 ); 00104 $this->assertCacheEmpty( $oneCache ); 00105 00106 $oneCache->set( 'cache-key', 'prop1', 'value1' ); 00107 $oneCache->set( 'cache-key', 'prop1', 'value2' ); 00108 $this->assertEquals( 'value2', $oneCache->get( 'cache-key', 'prop1' ) ); 00109 } 00110 00120 public function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) { 00121 $cache = new ProcessCacheLRUTestable( $cacheMaxEntries ); 00122 $this->fillCache( $cache, $entryToFill ); 00123 00124 $this->assertSame( 00125 $this->getExpectedCache( $cacheMaxEntries, $entryToFill ), 00126 $cache->getCache(), 00127 "Filling a $cacheMaxEntries entries cache with $entryToFill entries" 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 00148 public function testReplaceExistingKeyShouldBumpEntryToTop() { 00149 $maxEntries = 3; 00150 00151 $cache = new ProcessCacheLRUTestable( $maxEntries ); 00152 // Fill cache leaving just one remaining slot 00153 $this->fillCache( $cache, $maxEntries - 1 ); 00154 00155 // Set an existing cache key 00156 $cache->set( "cache-key-1", "prop-1", "new-value-for-1" ); 00157 00158 $this->assertSame( 00159 array( 00160 'cache-key-2' => array( 'prop-2' => 'value-2' ), 00161 'cache-key-1' => array( 'prop-1' => 'new-value-for-1' ), 00162 ), 00163 $cache->getCache() 00164 ); 00165 } 00166 00167 public function testRecentlyAccessedKeyStickIn() { 00168 $cache = new ProcessCacheLRUTestable( 2 ); 00169 $cache->set( 'first', 'prop1', 'value1' ); 00170 $cache->set( 'second', 'prop2', 'value2' ); 00171 00172 // Get first 00173 $cache->get( 'first', 'prop1' ); 00174 // Cache a third value, should invalidate the least used one 00175 $cache->set( 'third', 'prop3', 'value3' ); 00176 00177 $this->assertFalse( $cache->has( 'second', 'prop2' ) ); 00178 } 00179 00186 public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() { 00187 $maxEntries = 3; 00188 00189 $cache = new ProcessCacheLRUTestable( $maxEntries ); 00190 $this->fillCache( $cache, $maxEntries ); 00191 00192 // Set an existing cache key 00193 $cache->set( "cache-key-2", "prop-2", "new-value-for-2" ); 00194 $this->assertSame( 00195 array( 00196 'cache-key-1' => array( 'prop-1' => 'value-1' ), 00197 'cache-key-3' => array( 'prop-3' => 'value-3' ), 00198 'cache-key-2' => array( 'prop-2' => 'new-value-for-2' ), 00199 ), 00200 $cache->getCache() 00201 ); 00202 $this->assertEquals( 'new-value-for-2', 00203 $cache->get( 'cache-key-2', 'prop-2' ) 00204 ); 00205 } 00206 00207 public function testBumpExistingKeyToTop() { 00208 $cache = new ProcessCacheLRUTestable( 3 ); 00209 $this->fillCache( $cache, 3 ); 00210 00211 // Set the very first cache key to a new value 00212 $cache->set( "cache-key-1", "prop-1", "new value for 1" ); 00213 $this->assertEquals( 00214 array( 00215 'cache-key-2' => array( 'prop-2' => 'value-2' ), 00216 'cache-key-3' => array( 'prop-3' => 'value-3' ), 00217 'cache-key-1' => array( 'prop-1' => 'new value for 1' ), 00218 ), 00219 $cache->getCache() 00220 ); 00221 } 00222 } 00223 00227 class ProcessCacheLRUTestable extends ProcessCacheLRU { 00228 public $cache = array(); 00229 00230 public function getCache() { 00231 return $this->cache; 00232 } 00233 00234 public function getEntriesCount() { 00235 return count( $this->cache ); 00236 } 00237 }