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 PHPUnit_Framework_TestCase
{
14 use MediaWikiCoversValidator
;
17 * Helper to verify emptiness of a cache object.
18 * Compare against an array so we get the cache content difference.
20 protected function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
21 $this->assertAttributeEquals( [], 'cache', $cache, $msg );
25 * Helper to fill a cache object passed by reference
27 protected function fillCache( &$cache, $numEntries ) {
28 // Fill cache with three values
29 for ( $i = 1; $i <= $numEntries; $i++
) {
30 $cache->set( "cache-key-$i", "prop-$i", "value-$i" );
35 * Generates an array of what would be expected in cache for a given cache
36 * size and a number of entries filled in sequentially
38 protected function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
41 if ( $entryToFill === 0 ) {
42 // The cache is empty!
44 } elseif ( $entryToFill <= $cacheMaxEntries ) {
45 // Cache is not fully filled
49 $firstKey = 1 +
$entryToFill - $cacheMaxEntries;
52 $lastKey = $entryToFill;
54 for ( $i = $firstKey; $i <= $lastKey; $i++
) {
55 $expected["cache-key-$i"] = [ "prop-$i" => "value-$i" ];
62 * Highlight diff between assertEquals and assertNotSame
64 public function testPhpUnitArrayEquality() {
65 $one = [ 'A' => 1, 'B' => 2 ];
66 $two = [ 'B' => 2, 'A' => 1 ];
68 $this->assertEquals( $one, $two );
70 $this->assertNotSame( $one, $two );
74 * @dataProvider provideInvalidConstructorArg
75 * @expectedException Wikimedia\Assert\ParameterAssertionException
76 * @covers ProcessCacheLRU::__construct
78 public function testConstructorGivenInvalidValue( $maxSize ) {
79 new ProcessCacheLRUTestable( $maxSize );
83 * Value which are forbidden by the constructor
85 public static function provideInvalidConstructorArg() {
97 * @covers ProcessCacheLRU::get
98 * @covers ProcessCacheLRU::set
99 * @covers ProcessCacheLRU::has
101 public function testAddAndGetAKey() {
102 $oneCache = new ProcessCacheLRUTestable( 1 );
103 $this->assertCacheEmpty( $oneCache );
105 // First set just one value
106 $oneCache->set( 'cache-key', 'prop1', 'value1' );
107 $this->assertEquals( 1, $oneCache->getEntriesCount() );
108 $this->assertTrue( $oneCache->has( 'cache-key', 'prop1' ) );
109 $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
113 * @covers ProcessCacheLRU::set
114 * @covers ProcessCacheLRU::get
116 public function testDeleteOldKey() {
117 $oneCache = new ProcessCacheLRUTestable( 1 );
118 $this->assertCacheEmpty( $oneCache );
120 $oneCache->set( 'cache-key', 'prop1', 'value1' );
121 $oneCache->set( 'cache-key', 'prop1', 'value2' );
122 $this->assertEquals( 'value2', $oneCache->get( 'cache-key', 'prop1' ) );
126 * This test that we properly overflow when filling a cache with
127 * a sequence of always different cache-keys. Meant to verify we correclty
128 * delete the older key.
130 * @covers ProcessCacheLRU::set
131 * @dataProvider provideCacheFilling
132 * @param int $cacheMaxEntries Maximum entry the created cache will hold
133 * @param int $entryToFill Number of entries to insert in the created cache.
135 public function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
136 $cache = new ProcessCacheLRUTestable( $cacheMaxEntries );
137 $this->fillCache( $cache, $entryToFill );
140 $this->getExpectedCache( $cacheMaxEntries, $entryToFill ),
142 "Filling a $cacheMaxEntries entries cache with $entryToFill entries"
147 * Provider for testFillingCache
149 public static function provideCacheFilling() {
150 // ($cacheMaxEntries, $entryToFill, $msg='')
162 * Create a cache with only one remaining entry then update
163 * the first inserted entry. Should bump it to the top.
165 * @covers ProcessCacheLRU::set
167 public function testReplaceExistingKeyShouldBumpEntryToTop() {
170 $cache = new ProcessCacheLRUTestable( $maxEntries );
171 // Fill cache leaving just one remaining slot
172 $this->fillCache( $cache, $maxEntries - 1 );
174 // Set an existing cache key
175 $cache->set( "cache-key-1", "prop-1", "new-value-for-1" );
179 'cache-key-2' => [ 'prop-2' => 'value-2' ],
180 'cache-key-1' => [ 'prop-1' => 'new-value-for-1' ],
187 * @covers ProcessCacheLRU::get
188 * @covers ProcessCacheLRU::set
189 * @covers ProcessCacheLRU::has
191 public function testRecentlyAccessedKeyStickIn() {
192 $cache = new ProcessCacheLRUTestable( 2 );
193 $cache->set( 'first', 'prop1', 'value1' );
194 $cache->set( 'second', 'prop2', 'value2' );
197 $cache->get( 'first', 'prop1' );
198 // Cache a third value, should invalidate the least used one
199 $cache->set( 'third', 'prop3', 'value3' );
201 $this->assertFalse( $cache->has( 'second', 'prop2' ) );
205 * This first create a full cache then update the value for the 2nd
207 * Given a cache having 1,2,3 as key, updating 2 should bump 2 to
208 * the top of the queue with the new value: 1,3,2* (* = updated).
210 * @covers ProcessCacheLRU::set
211 * @covers ProcessCacheLRU::get
213 public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
216 $cache = new ProcessCacheLRUTestable( $maxEntries );
217 $this->fillCache( $cache, $maxEntries );
219 // Set an existing cache key
220 $cache->set( "cache-key-2", "prop-2", "new-value-for-2" );
223 'cache-key-1' => [ 'prop-1' => 'value-1' ],
224 'cache-key-3' => [ 'prop-3' => 'value-3' ],
225 'cache-key-2' => [ 'prop-2' => 'new-value-for-2' ],
229 $this->assertEquals( 'new-value-for-2',
230 $cache->get( 'cache-key-2', 'prop-2' )
235 * @covers ProcessCacheLRU::set
237 public function testBumpExistingKeyToTop() {
238 $cache = new ProcessCacheLRUTestable( 3 );
239 $this->fillCache( $cache, 3 );
241 // Set the very first cache key to a new value
242 $cache->set( "cache-key-1", "prop-1", "new value for 1" );
245 'cache-key-2' => [ 'prop-2' => 'value-2' ],
246 'cache-key-3' => [ 'prop-3' => 'value-3' ],
247 'cache-key-1' => [ 'prop-1' => 'new value for 1' ],
255 * Overrides some ProcessCacheLRU methods and properties accessibility.
257 class ProcessCacheLRUTestable
extends ProcessCacheLRU
{
260 public function getCache() {
264 public function getEntriesCount() {
265 return count( $this->cache
);