$this->assertFalse( $this->cache->get( $key ), "Stale set() value ignored" );
}
+ /**
+ * @covers WANObjectCache::getWithSetCallback
+ */
+ public function testProcessCacheTTL() {
+ $cache = $this->cache;
+ $mockWallClock = 1549343530.2053;
+ $cache->setMockTime( $mockWallClock );
+
+ $key = "mykey-" . wfRandomString();
+
+ $hits = 0;
+ $callback = function ( $oldValue, &$ttl, &$setOpts ) use ( &$hits ) {
+ ++$hits;
+ return 42;
+ };
+
+ $cache->getWithSetCallback( $key, 100, $callback, [ 'pcTTL' => 5 ] );
+ $cache->delete( $key, $cache::HOLDOFF_NONE ); // clear persistent cache
+ $cache->getWithSetCallback( $key, 100, $callback, [ 'pcTTL' => 5 ] );
+ $this->assertEquals( 1, $hits, "Value process cached" );
+
+ $mockWallClock += 6;
+ $cache->getWithSetCallback( $key, 100, $callback, [ 'pcTTL' => 5 ] );
+ $this->assertEquals( 2, $hits, "Value expired in process cache" );
+ }
+
/**
* @covers WANObjectCache::getWithSetCallback
*/
$v = $cache->getWithSetCallback(
$key, 30, $func, [ 'lowTTL' => 0, 'lockTSE' => 5 ] + $extOpts );
$this->assertEquals( $value, $v, "Value returned" );
- $this->assertEquals( 0, $wasSet, "Value not regenerated" );
+ $this->assertSame( 0, $wasSet, "Value not regenerated" );
$mockWallClock += 1;
$asycList[0](); // run the refresh callback
$asycList = [];
$this->assertEquals( 2, $wasSet, "Value calculated at later time" );
- $this->assertEquals( 0, count( $asycList ), "No deferred refreshes added." );
+ $this->assertSame( 0, count( $asycList ), "No deferred refreshes added." );
$v = $cache->getWithSetCallback( $key, 300, $func, $opts );
$this->assertEquals( $value, $v, "New value stored" );
$keyedIds, 30, $genFunc, [ 'lowTTL' => 0, 'lockTSE' => 5 ] + $extOpts );
$this->assertEquals( $value, $v[$keyB], "Value returned" );
$this->assertEquals( 1, $wasSet, "Value regenerated" );
- $this->assertEquals( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
+ $this->assertSame( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
$v = $cache->getMultiWithSetCallback(
$keyedIds, 30, $genFunc, [ 'lowTTL' => 0, 'lockTSE' => 5 ] + $extOpts );
$this->assertEquals( $value, $v[$keyB], "Value returned" );
$this->assertEquals( 1, $wasSet, "Value not regenerated" );
- $this->assertEquals( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
+ $this->assertSame( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
$mockWallClock += 1;
$keyedIds, 30, $genFunc, [ 'lowTTL' => 0 ] + $extOpts );
$this->assertEquals( $value, $v[$keyB], "Value returned" );
$this->assertEquals( 1, $wasSet, "Value regenerated" );
- $this->assertEquals( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
+ $this->assertSame( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
$v = $cache->getMultiWithUnionSetCallback(
$keyedIds, 30, $genFunc, [ 'lowTTL' => 0 ] + $extOpts );
$this->assertEquals( $value, $v[$keyB], "Value returned" );
$this->assertEquals( 1, $wasSet, "Value not regenerated" );
- $this->assertEquals( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
+ $this->assertSame( 0, $cache->getWarmupKeyMisses(), "Keys warmed in warmup cache" );
$mockWallClock += 1;
* @covers WANObjectCache::getWithSetCallback()
* @covers WANObjectCache::fetchOrRegenerate()
*/
- public function testBusyValue() {
+ public function testBusyValueBasic() {
$cache = $this->cache;
$key = wfRandomString();
$value = wfRandomString();
$cache->setMockTime( $mockWallClock );
$calls = 0;
- $func = function () use ( &$calls, $value, $cache, $key ) {
+ $func = function () use ( &$calls, $value ) {
++$calls;
return $value;
};
$this->assertEquals( 3, $calls, 'Callback was not used; used interim' );
}
+ public function getBusyValues_Provider() {
+ $hash = new HashBagOStuff( [] );
+
+ return [
+ [
+ function () {
+ return "Saint Oliver Plunckett";
+ },
+ 'Saint Oliver Plunckett'
+ ],
+ [ 'strlen', 'strlen' ],
+ [ 'WANObjectCache::newEmpty', 'WANObjectCache::newEmpty' ],
+ [ [ 'WANObjectCache', 'newEmpty' ], [ 'WANObjectCache', 'newEmpty' ] ],
+ [ [ $hash, 'getLastError' ], [ $hash, 'getLastError' ] ],
+ [ [ 1, 2, 3 ], [ 1, 2, 3 ] ]
+ ];
+ }
+
+ /**
+ * @covers WANObjectCache::getWithSetCallback()
+ * @covers WANObjectCache::fetchOrRegenerate()
+ * @dataProvider getBusyValues_Provider
+ * @param mixed $busyValue
+ * @param mixed $expected
+ */
+ public function testBusyValueTypes( $busyValue, $expected ) {
+ $cache = $this->cache;
+ $key = wfRandomString();
+
+ $mockWallClock = 1549343530.2053;
+ $cache->setMockTime( $mockWallClock );
+
+ $calls = 0;
+ $func = function () use ( &$calls ) {
+ ++$calls;
+ return 418;
+ };
+
+ // Acquire a lock to verify that getWithSetCallback uses busyValue properly
+ $this->internalCache->add( 'WANCache:m:' . $key, 1, 0 );
+
+ $ret = $cache->getWithSetCallback( $key, 30, $func, [ 'busyValue' => $busyValue ] );
+ $this->assertSame( $expected, $ret, 'busyValue used as expected' );
+ $this->assertSame( 0, $calls, 'busyValue was used' );
+ }
+
/**
* @covers WANObjectCache::getMulti()
*/
}
}
+ /**
+ * @covers WANObjectCache::get()
+ * @covers WANObjectCache::processCheckKeys()
+ */
+ public function testCheckKeyHoldoff() {
+ $cache = $this->cache;
+ $key = wfRandomString();
+ $checkKey = wfRandomString();
+
+ $mockWallClock = 1549343530.2053;
+ $cache->setMockTime( $mockWallClock );
+ $cache->touchCheckKey( $checkKey, 8 );
+
+ $mockWallClock += 1;
+ $cache->set( $key, 1, 60 );
+ $this->assertEquals( 1, $cache->get( $key, $curTTL, [ $checkKey ] ) );
+ $this->assertLessThan( 0, $curTTL, "Key in hold-off due to check key" );
+
+ $mockWallClock += 3;
+ $cache->set( $key, 1, 60 );
+ $this->assertEquals( 1, $cache->get( $key, $curTTL, [ $checkKey ] ) );
+ $this->assertLessThan( 0, $curTTL, "Key in hold-off due to check key" );
+
+ $mockWallClock += 10;
+ $cache->set( $key, 1, 60 );
+ $this->assertEquals( 1, $cache->get( $key, $curTTL, [ $checkKey ] ) );
+ $this->assertGreaterThan( 0, $curTTL, "Key not in hold-off due to check key" );
+ }
+
/**
* @covers WANObjectCache::delete
* @covers WANObjectCache::relayDelete
$wasSet = 0;
$v = $cache->getWithSetCallback( $key, 30, $funcV2, $verOpts + $extOpts );
$this->assertEquals( $valueV2, $v, "Value not regenerated (secondary key)" );
- $this->assertEquals( 0, $wasSet, "Value not regenerated (secondary key)" );
+ $this->assertSame( 0, $wasSet, "Value not regenerated (secondary key)" );
// Clear out the older or unversioned key
$cache->delete( $key, 0 );
[ 'domain:page:5', 'page' ],
[ 'domain:main-key', 'main-key' ],
[ 'domain:page:history', 'page' ],
+ // Regression test for T232907
+ [ 'domain:foo-bar-1.2:abc:v2', 'foo-bar-1_2' ],
[ 'missingdomainkey', 'missingdomainkey' ]
];
}