getPhabricatorTestCaseConfiguration() + array( self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK => true, self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => false, ); if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) { // Fixtures don't make sense with process isolation. $config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK] = false; } return $config; } /** @phutil-external-symbol function init_phabricator_script */ public function willRunTestCases(array $test_cases) { $root = dirname(phutil_get_library_root('phabricator')); if (!function_exists('init_phabricator_script')) { // Run the initialization routines only if nothing else already did require_once $root.'/scripts/init/lib.php'; init_phabricator_script( array( 'config.optional' => false, 'no-extensions' => true, )); } $config = $this->getComputedConfiguration(); if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) { ++self::$storageFixtureReferences; if (!self::$storageFixture) { self::$storageFixture = $this->newStorageFixture(); } } ++self::$testsAreRunning; } public function didRunTestCases(array $test_cases) { if (self::$storageFixture) { self::$storageFixtureReferences--; if (!self::$storageFixtureReferences) { self::$storageFixture = null; } } --self::$testsAreRunning; } protected function willRunTests() { $config = $this->getComputedConfiguration(); if ($config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK]) { LiskDAO::beginIsolateAllLiskEffectsToCurrentProcess(); } $this->env = PhabricatorEnv::beginScopedEnv(); // NOTE: While running unit tests, we act as though all applications are // enabled, regardless of the install's configuration. Tests which need // to disable applications are responsible for adjusting state themselves // (such tests are exceedingly rare). $this->env->overrideEnvConfig( 'phabricator.uninstalled-applications', array()); $this->env->overrideEnvConfig( 'phabricator.show-prototypes', true); // Reset application settings to defaults, particularly policies. $this->env->overrideEnvConfig( 'phabricator.application-settings', array()); // We can't stub this service right now, and it's not generally useful // to publish notifications about test execution. $this->env->overrideEnvConfig( 'notification.servers', array()); $this->env->overrideEnvConfig( 'phabricator.base-uri', 'http://phabricator.example.com'); $this->env->overrideEnvConfig( 'auth.email-domains', array()); // Tests do their own stubbing/voiding for events. $this->env->overrideEnvConfig('phabricator.silent', false); $this->env->overrideEnvConfig('cluster.read-only', false); $this->env->overrideEnvConfig( 'maniphest.custom-field-definitions', array()); } protected function didRunTests() { $config = $this->getComputedConfiguration(); if ($config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK]) { LiskDAO::endIsolateAllLiskEffectsToCurrentProcess(); } try { if (phutil_is_hiphop_runtime()) { $this->env->__destruct(); } unset($this->env); } catch (Exception $ex) { throw new Exception( pht( 'Some test called %s, but is still holding '. 'a reference to the scoped environment!', 'PhabricatorEnv::beginScopedEnv()')); } } protected function willRunOneTest($test) { $config = $this->getComputedConfiguration(); if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) { LiskDAO::beginIsolateAllLiskEffectsToTransactions(); } } protected function didRunOneTest($test) { $config = $this->getComputedConfiguration(); if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) { LiskDAO::endIsolateAllLiskEffectsToTransactions(); } } protected function newStorageFixture() { $bytes = Filesystem::readRandomCharacters(24); $name = self::NAMESPACE_PREFIX.$bytes; return new PhabricatorStorageFixtureScopeGuard($name); } /** * Returns an integer seed to use when building unique identifiers (e.g., * non-colliding usernames). The seed is unstable and its value will change * between test runs, so your tests must not rely on it. * * @return int A unique integer. */ protected function getNextObjectSeed() { self::$storageFixtureObjectSeed += mt_rand(1, 100); return self::$storageFixtureObjectSeed; } protected function generateNewTestUser() { $seed = $this->getNextObjectSeed(); $user = id(new PhabricatorUser()) ->setRealName(pht('Test User %s', $seed)) ->setUserName("test{$seed}") ->setIsApproved(1); $email = id(new PhabricatorUserEmail()) ->setAddress("testuser{$seed}@example.com") ->setIsVerified(1); $editor = new PhabricatorUserEditor(); $editor->setActor($user); $editor->createNewUser($user, $email); // When creating a new test user, we prefill their setting cache as empty. // This is a little more efficient than doing a query to load the empty // settings. $user->attachRawCacheData( array( PhabricatorUserPreferencesCacheType::KEY_PREFERENCES => '[]', )); return $user; } /** * Throws unless tests are currently executing. This method can be used to * guard code which is specific to unit tests and should not normally be * reachable. * * If tests aren't currently being executed, throws an exception. */ public static function assertExecutingUnitTests() { if (!self::$testsAreRunning) { throw new Exception( pht( 'Executing test code outside of test execution! '. 'This code path can only be run during unit tests.')); } } protected function requireBinaryForTest($binary) { if (!Filesystem::binaryExists($binary)) { $this->assertSkipped( pht( 'No binary "%s" found on this system, skipping test.', $binary)); } } protected function newContentSource() { return PhabricatorContentSource::newForSource( PhabricatorUnitTestContentSource::SOURCECONST); } }