From c5a0fa5bed4c5aafdf0721c1d05978576107bd85 Mon Sep 17 00:00:00 2001 From: Brian Wolff Date: Wed, 15 Mar 2017 22:51:13 +0000 Subject: [PATCH] objectcache: Never use CACHE_NONE for CACHE_ANYTHING If $wgMainCacheType = CACHE_ACCEL, but there is no APC, then its possible that CACHE_ANYTHING will default to CACHE_NONE because that's what CACHE_ACCEL would do. Possibly also T147161 Bug: T160519 Change-Id: I9ac2d071437b35a0f9cd3678e2279628f7b1931e --- includes/objectcache/ObjectCache.php | 8 +- .../includes/objectcache/ObjectCacheTest.php | 82 +++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 tests/phpunit/includes/objectcache/ObjectCacheTest.php diff --git a/includes/objectcache/ObjectCache.php b/includes/objectcache/ObjectCache.php index cf9033b88f..3370e5b9d1 100644 --- a/includes/objectcache/ObjectCache.php +++ b/includes/objectcache/ObjectCache.php @@ -246,8 +246,14 @@ class ObjectCache { global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType; $candidates = [ $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType ]; foreach ( $candidates as $candidate ) { + $cache = false; if ( $candidate !== CACHE_NONE && $candidate !== CACHE_ANYTHING ) { - return self::getInstance( $candidate ); + $cache = self::getInstance( $candidate ); + // CACHE_ACCEL might default to nothing if no APCu + // See includes/ServiceWiring.php + if ( !( $cache instanceof EmptyBagOStuff ) ) { + return $cache; + } } } diff --git a/tests/phpunit/includes/objectcache/ObjectCacheTest.php b/tests/phpunit/includes/objectcache/ObjectCacheTest.php new file mode 100644 index 0000000000..d132183eac --- /dev/null +++ b/tests/phpunit/includes/objectcache/ObjectCacheTest.php @@ -0,0 +1,82 @@ +setCacheConfig(); + $this->setMwGlobals( [ + 'wgMainCacheType' => CACHE_NONE, + 'wgMessageCacheType' => CACHE_NONE, + 'wgParserCacheType' => CACHE_NONE, + ] ); + } + + private function setCacheConfig( $arr = [] ) { + $defaults = [ + CACHE_NONE => [ 'class' => 'EmptyBagOStuff' ], + CACHE_DB => [ 'class' => 'SqlBagOStuff' ], + CACHE_ANYTHING => [ 'factory' => 'ObjectCache::newAnything' ], + // Mock ACCEL with 'hash' as being installed. + // This makes tests deterministic regardless of APC. + CACHE_ACCEL => [ 'class' => 'HashBagOStuff' ], + 'hash' => [ 'class' => 'HashBagOStuff' ], + ]; + $this->setMwGlobals( 'wgObjectCaches', $arr + $defaults ); + } + + /** @covers ObjectCache::newAnything */ + public function testNewAnythingNothing() { + $this->assertInstanceOf( + SqlBagOStuff::class, + ObjectCache::newAnything( [] ), + 'No available types. Fallback to DB' + ); + } + + /** @covers ObjectCache::newAnything */ + public function testNewAnythingHash() { + $this->setMwGlobals( [ + 'wgMainCacheType' => 'hash' + ] ); + + $this->assertInstanceOf( + HashBagOStuff::class, + ObjectCache::newAnything( [] ), + 'Use an available type (hash)' + ); + } + + /** @covers ObjectCache::newAnything */ + public function testNewAnythingAccel() { + $this->setMwGlobals( [ + 'wgMainCacheType' => CACHE_ACCEL + ] ); + + $this->assertInstanceOf( + HashBagOStuff::class, + ObjectCache::newAnything( [] ), + 'Use an available type (CACHE_ACCEL)' + ); + } + + /** @covers ObjectCache::newAnything */ + public function txestNewAnythingNoAccel() { + $this->setMwGlobals( [ + 'wgMainCacheType' => CACHE_ACCEL + ] ); + + $this->setCacheConfig( [ + // Mock APC not being installed (T160519, T147161) + CACHE_ACCEL => [ 'class' => 'EmptyBagOStuff' ] + ] ); + + $this->assertInstanceOf( + SqlBagOStuff::class, + ObjectCache::newAnything( [] ), + 'Fallback to DB if available types fall back to Empty' + ); + } +} -- 2.20.1