Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
77.78% |
7 / 9 |
CRAP | |
58.62% |
17 / 29 |
UserTestingStatus | |
0.00% |
0 / 1 |
|
77.78% |
7 / 9 |
37.48 | |
58.62% |
17 / 29 |
hasInstance | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getInstance | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 11 |
|||
active | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
inactive | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
__construct | |
100.00% |
1 / 1 |
3 | |
100.00% |
5 / 5 |
|||
isActive | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getTestName | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
getBucket | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
getTrigger | |
100.00% |
1 / 1 |
3 | |
100.00% |
3 / 3 |
<?php | |
namespace CirrusSearch; | |
use HashConfig; | |
use RequestContext; | |
use Wikimedia\Assert\Assert; | |
/** | |
* Reports UserTesting bucketing decision | |
* | |
* See UserTestingEngine for initialization. | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License along | |
* with this program; if not, write to the Free Software Foundation, Inc., | |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
* http://www.gnu.org/copyleft/gpl.html | |
*/ | |
class UserTestingStatus { | |
/** @var ?UserTestingStatus Bucketing decision for the main request context */ | |
private static $instance; | |
/** @var ?string The name of the active test, or null if none */ | |
private $testName; | |
/** @var ?string The name of the active bucket, or null if no active test */ | |
private $bucket; | |
/** | |
* @return bool True when a bucketing decision has been made for the main | |
* request context | |
*/ | |
public static function hasInstance(): bool { | |
return self::$instance !== null; | |
} | |
/** | |
* Reports bucketing decision for the main request context | |
* | |
* If not created yet, uses configuration and query string from request context | |
* to make a bucketing decision and activate that decision. This must be | |
* called as early in the request as is sensible to ensure the test configuration | |
* is applied. | |
* | |
* @return UserTestingStatus | |
*/ | |
public static function getInstance(): UserTestingStatus { | |
if ( self::$instance === null ) { | |
$context = RequestContext::getMain(); | |
$trigger = $context->getRequest()->getVal( 'cirrusUserTesting' ); | |
// The current method of ensuring user testing is always initialized is | |
// sloppy, if we used the context config everything that touches | |
// ElasticsearchIntermediary would fail unit testing. | |
if ( defined( 'MW_PHPUNIT_TEST' ) ) { | |
$config = new HashConfig( [ | |
'CirrusSearchUserTesting' => [], | |
'CirrusSearchActiveTest' => false, | |
] ); | |
} else { | |
$config = $context->getConfig(); | |
} | |
$engine = UserTestingEngine::fromConfig( $config ); | |
self::$instance = $engine->decideActiveTest( $trigger ); | |
// The singleton here also doubles as a marker for if we've already | |
// applied the test configuration. This should be the only place | |
// to activate a test outside maintenance scripts. | |
$engine->activateTest( self::$instance ); | |
} | |
return self::$instance; | |
} | |
/** | |
* @param string $testName | |
* @param string $bucket | |
* @return UserTestingStatus status representing a test bucket active for this request | |
*/ | |
public static function active( string $testName, string $bucket ): UserTestingStatus { | |
return new self( $testName, $bucket ); | |
} | |
/** | |
* @return UserTestingStatus status representing user testing as inactive | |
*/ | |
public static function inactive(): UserTestingStatus { | |
return new self( null, null ); | |
} | |
private function __construct( ?string $testName, ?string $bucket ) { | |
Assert::precondition( ( $testName === null ) === ( $bucket === null ), | |
'Either testName and bucket are both null or both strings' ); | |
$this->testName = $testName; | |
$this->bucket = $bucket; | |
} | |
/** | |
* @return bool True when a test is currently active | |
*/ | |
public function isActive(): bool { | |
return $this->testName !== null; | |
} | |
/** | |
* @return string | |
* @throws NoActiveTestException | |
*/ | |
public function getTestName(): string { | |
if ( $this->testName === null ) { | |
throw new NoActiveTestException(); | |
} | |
return $this->testName; | |
} | |
/** | |
* @return string | |
* @throws NoActiveTestException | |
*/ | |
public function getBucket(): string { | |
if ( $this->bucket === null ) { | |
throw new NoActiveTestException(); | |
} | |
return $this->bucket; | |
} | |
/** | |
* @return string When active returns a string that will enable the same | |
* test configuration when provided to UserTestingEngine. | |
*/ | |
public function getTrigger(): string { | |
if ( $this->testName === null || $this->bucket == null ) { | |
throw new NoActiveTestException(); | |
} | |
return "{$this->testName}:{$this->bucket}"; | |
} | |
} |