lockId = $this->getTestLock(); $this->databasePrefix = 'test' . $this->lockId; } else { $this->databasePrefix = $db_prefix; // It is possible that we're running a test inside a test. In which case // $db_prefix will be something like test12345678test90123456 and the // generated lock ID for the running test method would be 90123456. preg_match('/test(\d+)$/', $db_prefix, $matches); if (!isset($matches[1])) { throw new \InvalidArgumentException("Invalid database prefix: $db_prefix"); } $this->lockId = $matches[1]; } } /** * Gets the relative path to the test site directory. * * @return string * The relative path to the test site directory. */ public function getTestSitePath() { return 'sites/simpletest/' . $this->lockId; } /** * Gets the test database prefix. * * @return string * The test database prefix. */ public function getDatabasePrefix() { return $this->databasePrefix; } /** * Generates a unique lock ID for the test method. * * @return int * The unique lock ID for the test method. */ protected function getTestLock() { // Ensure that the generated lock ID is not in use, which may happen when // tests are run concurrently. do { $lock_id = mt_rand(10000000, 99999999); // If we're only running with a concurrency of 1 there's no need to create // a test lock file as there is no chance of the random number generated // clashing. if (getenv('RUN_TESTS_CONCURRENCY') > 1 && @symlink(__FILE__, $this->getLockFile($lock_id)) === FALSE) { $lock_id = NULL; } } while ($lock_id === NULL); return $lock_id; } /** * Releases all test locks. * * This should only be called once all the test fixtures have been cleaned up. */ public static function releaseAllTestLocks() { $tmp = file_directory_os_temp(); $dir = dir($tmp); while (($entry = $dir->read()) !== FALSE) { if ($entry === '.' || $entry === '..') { continue; } $entry_path = $tmp . '/' . $entry; if (preg_match('/^test_\d+/', $entry) && is_link($entry_path)) { unlink($entry_path); } } } /** * Gets the lock file path. * * @param int $lock_id * The test method lock ID. * * @return string * A file path to the symbolic link that prevents the lock ID being re-used. */ protected function getLockFile($lock_id) { return FileSystem::getOsTemporaryDirectory() . '/test_' . $lock_id; } }