MediaWiki  master
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                 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 }