[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/infrastructure/testing/ -> PhabricatorTestCase.php (source)

   1  <?php
   2  
   3  abstract class PhabricatorTestCase extends ArcanistPhutilTestCase {
   4  
   5    const NAMESPACE_PREFIX = 'phabricator_unittest_';
   6  
   7    /**
   8     * If true, put Lisk in process-isolated mode for the duration of the tests so
   9     * that it will establish only isolated, side-effect-free database
  10     * connections. Defaults to true.
  11     *
  12     * NOTE: You should disable this only in rare circumstances. Unit tests should
  13     * not rely on external resources like databases, and should not produce
  14     * side effects.
  15     */
  16    const PHABRICATOR_TESTCONFIG_ISOLATE_LISK           = 'isolate-lisk';
  17  
  18    /**
  19     * If true, build storage fixtures before running tests, and connect to them
  20     * during test execution. This will impose a performance penalty on test
  21     * execution (currently, it takes roughly one second to build the fixture)
  22     * but allows you to perform tests which require data to be read from storage
  23     * after writes. The fixture is shared across all test cases in this process.
  24     * Defaults to false.
  25     *
  26     * NOTE: All connections to fixture storage open transactions when established
  27     * and roll them back when tests complete. Each test must independently
  28     * write data it relies on; data will not persist across tests.
  29     *
  30     * NOTE: Enabling this implies disabling process isolation.
  31     */
  32    const PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES = 'storage-fixtures';
  33  
  34    private $configuration;
  35    private $env;
  36  
  37    private static $storageFixtureReferences = 0;
  38    private static $storageFixture;
  39    private static $storageFixtureObjectSeed = 0;
  40    private static $testsAreRunning = 0;
  41  
  42    protected function getPhabricatorTestCaseConfiguration() {
  43      return array();
  44    }
  45  
  46    private function getComputedConfiguration() {
  47      $config = $this->getPhabricatorTestCaseConfiguration() + array(
  48        self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK             => true,
  49        self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES   => false,
  50      );
  51  
  52      if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) {
  53        // Fixtures don't make sense with process isolation.
  54        $config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK] = false;
  55      }
  56  
  57      return $config;
  58    }
  59  
  60    public function willRunTestCases(array $test_cases) {
  61      $root = dirname(phutil_get_library_root('phabricator'));
  62      require_once $root.'/scripts/__init_script__.php';
  63  
  64      $config = $this->getComputedConfiguration();
  65  
  66      if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) {
  67        ++self::$storageFixtureReferences;
  68        if (!self::$storageFixture) {
  69          self::$storageFixture = $this->newStorageFixture();
  70        }
  71      }
  72  
  73      ++self::$testsAreRunning;
  74    }
  75  
  76    public function didRunTestCases(array $test_cases) {
  77      if (self::$storageFixture) {
  78        self::$storageFixtureReferences--;
  79        if (!self::$storageFixtureReferences) {
  80          self::$storageFixture = null;
  81        }
  82      }
  83  
  84      --self::$testsAreRunning;
  85    }
  86  
  87    protected function willRunTests() {
  88      $config = $this->getComputedConfiguration();
  89  
  90      if ($config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK]) {
  91        LiskDAO::beginIsolateAllLiskEffectsToCurrentProcess();
  92      }
  93  
  94      $this->env = PhabricatorEnv::beginScopedEnv();
  95  
  96      // NOTE: While running unit tests, we act as though all applications are
  97      // installed, regardless of the install's configuration. Tests which need
  98      // to uninstall applications are responsible for adjusting state themselves
  99      // (such tests are exceedingly rare).
 100  
 101      $this->env->overrideEnvConfig(
 102        'phabricator.uninstalled-applications',
 103        array());
 104      $this->env->overrideEnvConfig(
 105        'phabricator.show-prototypes',
 106        true);
 107  
 108      // Reset application settings to defaults, particularly policies.
 109      $this->env->overrideEnvConfig(
 110        'phabricator.application-settings',
 111        array());
 112  
 113      // We can't stub this service right now, and it's not generally useful
 114      // to publish notifications about test execution.
 115      $this->env->overrideEnvConfig(
 116        'notification.enabled',
 117        false);
 118  
 119      $this->env->overrideEnvConfig(
 120        'phabricator.base-uri',
 121        'http://phabricator.example.com');
 122    }
 123  
 124    protected function didRunTests() {
 125      $config = $this->getComputedConfiguration();
 126  
 127      if ($config[self::PHABRICATOR_TESTCONFIG_ISOLATE_LISK]) {
 128        LiskDAO::endIsolateAllLiskEffectsToCurrentProcess();
 129      }
 130  
 131      try {
 132        if (phutil_is_hiphop_runtime()) {
 133          $this->env->__destruct();
 134        }
 135        unset($this->env);
 136      } catch (Exception $ex) {
 137        throw new Exception(
 138          'Some test called PhabricatorEnv::beginScopedEnv(), but is still '.
 139          'holding a reference to the scoped environment!');
 140      }
 141    }
 142  
 143    protected function willRunOneTest($test) {
 144      $config = $this->getComputedConfiguration();
 145  
 146      if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) {
 147        LiskDAO::beginIsolateAllLiskEffectsToTransactions();
 148      }
 149    }
 150  
 151    protected function didRunOneTest($test) {
 152      $config = $this->getComputedConfiguration();
 153  
 154      if ($config[self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES]) {
 155        LiskDAO::endIsolateAllLiskEffectsToTransactions();
 156      }
 157    }
 158  
 159    protected function newStorageFixture() {
 160      $bytes = Filesystem::readRandomCharacters(24);
 161      $name = self::NAMESPACE_PREFIX.$bytes;
 162  
 163      return new PhabricatorStorageFixtureScopeGuard($name);
 164    }
 165  
 166    protected function getLink($method) {
 167      $phabricator_project = 'PHID-APRJ-3f1fc779edeab89b2171';
 168      return
 169        'https://secure.phabricator.com/diffusion/symbol/'.$method.
 170        '/?lang=php&projects='.$phabricator_project.
 171        '&jump=true&context='.get_class($this);
 172    }
 173  
 174    /**
 175     * Returns an integer seed to use when building unique identifiers (e.g.,
 176     * non-colliding usernames). The seed is unstable and its value will change
 177     * between test runs, so your tests must not rely on it.
 178     *
 179     * @return int A unique integer.
 180     */
 181    protected function getNextObjectSeed() {
 182      self::$storageFixtureObjectSeed += mt_rand(1, 100);
 183      return self::$storageFixtureObjectSeed;
 184    }
 185  
 186    protected function generateNewTestUser() {
 187      $seed = $this->getNextObjectSeed();
 188  
 189      $user = id(new PhabricatorUser())
 190        ->setRealName("Test User {$seed}}")
 191        ->setUserName("test{$seed}")
 192        ->setIsApproved(1);
 193  
 194      $email = id(new PhabricatorUserEmail())
 195        ->setAddress("testuser{$seed}@example.com")
 196        ->setIsVerified(1);
 197  
 198      $editor = new PhabricatorUserEditor();
 199      $editor->setActor($user);
 200      $editor->createNewUser($user, $email);
 201  
 202      return $user;
 203    }
 204  
 205  
 206    /**
 207     * Throws unless tests are currently executing. This method can be used to
 208     * guard code which is specific to unit tests and should not normally be
 209     * reachable.
 210     *
 211     * If tests aren't currently being executed, throws an exception.
 212     */
 213    public static function assertExecutingUnitTests() {
 214      if (!self::$testsAreRunning) {
 215        throw new Exception(
 216          'Executing test code outside of test execution! This code path can '.
 217          'only be run during unit tests.');
 218      }
 219    }
 220  
 221  
 222  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1