MediaWiki  REL1_22
ProcessCacheLRUTest.php
Go to the documentation of this file.
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 }