4 * Test for ProcessCacheLRU class.
6 * Note that it uses the ProcessCacheLRUTestable class which extends some
7 * properties and methods visibility. That class is defined at the end of the
8 * file containing this class.
12 class ProcessCacheLRUTest
extends MediaWikiTestCase
{
15 * Helper to verify emptiness of a cache object.
16 * Compare against an array so we get the cache content difference.
18 function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
19 $this->assertAttributeEquals( array(), 'cache', $cache, $msg );
23 * Helper to fill a cache object passed by reference
25 function fillCache( &$cache, $numEntries ) {
26 // Fill cache with three values
27 for ( $i = 1; $i <= $numEntries; $i++
) {
28 $cache->set( "cache-key-$i", "prop-$i", "value-$i" );
33 * Generates an array of what would be expected in cache for a given cache
34 * size and a number of entries filled in sequentially
36 function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
39 if ( $entryToFill === 0 ) {
42 } elseif ( $entryToFill <= $cacheMaxEntries ) {
43 # Cache is not fully filled
47 $firstKey = 1 +
$entryToFill - $cacheMaxEntries;
50 $lastKey = $entryToFill;
52 for ( $i = $firstKey; $i <= $lastKey; $i++
) {
53 $expected["cache-key-$i"] = array( "prop-$i" => "value-$i" );
60 * Highlight diff between assertEquals and assertNotSame
62 function testPhpUnitArrayEquality() {
63 $one = array( 'A' => 1, 'B' => 2 );
64 $two = array( 'B' => 2, 'A' => 1 );
65 $this->assertEquals( $one, $two ); // ==
66 $this->assertNotSame( $one, $two ); // ===
70 * @dataProvider provideInvalidConstructorArg
71 * @expectedException MWException
73 function testConstructorGivenInvalidValue( $maxSize ) {
74 new ProcessCacheLRUTestable( $maxSize );
78 * Value which are forbidden by the constructor
80 public static function provideInvalidConstructorArg() {
84 array( new stdClass() ),
91 function testAddAndGetAKey() {
92 $oneCache = new ProcessCacheLRUTestable( 1 );
93 $this->assertCacheEmpty( $oneCache );
95 // First set just one value
96 $oneCache->set( 'cache-key', 'prop1', 'value1' );
97 $this->assertEquals( 1, $oneCache->getEntriesCount() );
98 $this->assertTrue( $oneCache->has( 'cache-key', 'prop1' ) );
99 $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
102 function testDeleteOldKey() {
103 $oneCache = new ProcessCacheLRUTestable( 1 );
104 $this->assertCacheEmpty( $oneCache );
106 $oneCache->set( 'cache-key', 'prop1', 'value1' );
107 $oneCache->set( 'cache-key', 'prop1', 'value2' );
108 $this->assertEquals( 'value2', $oneCache->get( 'cache-key', 'prop1' ) );
112 * This test that we properly overflow when filling a cache with
113 * a sequence of always different cache-keys. Meant to verify we correclty
114 * delete the older key.
116 * @dataProvider provideCacheFilling
117 * @param $cacheMaxEntries Maximum entry the created cache will hold
118 * @param $entryToFill Number of entries to insert in the created cache.
120 function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
121 $cache = new ProcessCacheLRUTestable( $cacheMaxEntries );
122 $this->fillCache( $cache, $entryToFill );
125 $this->getExpectedCache( $cacheMaxEntries, $entryToFill ),
127 "Filling a $cacheMaxEntries entries cache with $entryToFill entries"
132 * Provider for testFillingCache
134 public static function provideCacheFilling() {
135 // ($cacheMaxEntries, $entryToFill, $msg='')
139 array( 1, 2 ), # overflow
140 array( 5, 33 ), # overflow
145 * Create a cache with only one remaining entry then update
146 * the first inserted entry. Should bump it to the top.
148 function testReplaceExistingKeyShouldBumpEntryToTop() {
151 $cache = new ProcessCacheLRUTestable( $maxEntries );
152 // Fill cache leaving just one remaining slot
153 $this->fillCache( $cache, $maxEntries - 1 );
155 // Set an existing cache key
156 $cache->set( "cache-key-1", "prop-1", "new-value-for-1" );
160 'cache-key-2' => array( 'prop-2' => 'value-2' ),
161 'cache-key-1' => array( 'prop-1' => 'new-value-for-1' ),
167 function testRecentlyAccessedKeyStickIn() {
168 $cache = new ProcessCacheLRUTestable( 2 );
169 $cache->set( 'first', 'prop1', 'value1' );
170 $cache->set( 'second', 'prop2', 'value2' );
173 $cache->get( 'first', 'prop1' );
174 // Cache a third value, should invalidate the least used one
175 $cache->set( 'third', 'prop3', 'value3' );
177 $this->assertFalse( $cache->has( 'second', 'prop2' ) );
181 * This first create a full cache then update the value for the 2nd
183 * Given a cache having 1,2,3 as key, updating 2 should bump 2 to
184 * the top of the queue with the new value: 1,3,2* (* = updated).
186 function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
189 $cache = new ProcessCacheLRUTestable( $maxEntries );
190 $this->fillCache( $cache, $maxEntries );
192 // Set an existing cache key
193 $cache->set( "cache-key-2", "prop-2", "new-value-for-2" );
196 'cache-key-1' => array( 'prop-1' => 'value-1' ),
197 'cache-key-3' => array( 'prop-3' => 'value-3' ),
198 'cache-key-2' => array( 'prop-2' => 'new-value-for-2' ),
202 $this->assertEquals( 'new-value-for-2',
203 $cache->get( 'cache-key-2', 'prop-2' )
207 function testBumpExistingKeyToTop() {
208 $cache = new ProcessCacheLRUTestable( 3 );
209 $this->fillCache( $cache, 3 );
211 // Set the very first cache key to a new value
212 $cache->set( "cache-key-1", "prop-1", "new value for 1" );
215 'cache-key-2' => array( 'prop-2' => 'value-2' ),
216 'cache-key-3' => array( 'prop-3' => 'value-3' ),
217 'cache-key-1' => array( 'prop-1' => 'new value for 1' ),
225 * Overrides some ProcessCacheLRU methods and properties accessibility.
227 class ProcessCacheLRUTestable
extends ProcessCacheLRU
{
228 public $cache = array();
230 public function getCache() {
234 public function getEntriesCount() {
235 return count( $this->cache
);