setRunClassInSeparateProcess(true); } /** * @return string Abs path to the XML delta to use for the tests of that class */ abstract public function GetDatamodelDeltaAbsPath(): string; /** * @return array : dict extensions folders by their code */ public function GetAdditionalFeaturePaths(): array { return []; } protected function setUp(): void { static::LoadRequiredItopFiles(); if (is_null($this->oEnvironment)) { $this->oEnvironment = new UnitTestRunTimeEnvironment($this->GetTestEnvironment()); } parent::setUp(); } /** * @inheritDoc */ protected function LoadRequiredItopFiles(): void { parent::LoadRequiredItopFiles(); $this->RequireOnceItopFile('setup/setuputils.class.inc.php'); $this->RequireOnceItopFile('setup/runtimeenv.class.inc.php'); } /** * @return string Environment used as a base (conf. file, modules, DB, ...) to prepare the test environment */ protected function GetSourceEnvironment(): string { return 'production'; } /** * @inheritDoc * @warning This should ONLY be overloaded if your test case XML deltas are NOT compatible with the others, as it will create / compile another environment, increasing the global testing time. */ public function GetTestEnvironment(): string { return 'php-unit-tests'; } /** * @return string Absolute path to the {@see \Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase::GetTestEnvironment()} folder */ final protected function GetTestEnvironmentFolderAbsPath(): string { return APPROOT.'env-'.$this->GetTestEnvironment().'/'; } /** * @return bool True if the {@see \Combodo\iTop\Test\UnitTest\ItopDataTestCase::GetTestEnvironment()} is ready (compiled, up-to-date, but not necessarily started) */ final protected function IsEnvironmentReady(): bool { clearstatcache(); if (false === file_exists($this->GetTestEnvironmentFolderAbsPath())) { return false; } return $this->oEnvironment->IsUpToDate(); } /** * @inheritDoc */ protected function PrepareEnvironment(): void { $sSourceEnv = $this->GetSourceEnvironment(); $sTestEnv = $this->GetTestEnvironment(); // Check if test env. is already set and only prepare it if it's not up-to-date // // Note: To improve performances, we compile all XML deltas from test cases derived from this class and make a single environment where everything will be ran at once. // This requires XML deltas to be compatible, but it is a known and accepted trade-off. See PR #457 if (false === $this->IsEnvironmentReady()) { $this->debug("Preparing custom environment '$sTestEnv' with the following datamodel files:"); foreach ($this->oEnvironment->GetCustomDatamodelFiles() as $sCustomDatamodelFile) { $this->debug(" - $sCustomDatamodelFile"); } //---------------------------------------------------- // Clear any previous "$sTestEnv" environment //---------------------------------------------------- // - Configuration file $sConfFile = utils::GetConfigFilePath($sTestEnv); $sConfFolder = dirname($sConfFile); if (is_file($sConfFile)) { SetupUtils::tidydir($sConfFolder); } //---------------------------------------------------- // Prepare "$sTestEnv" environment //---------------------------------------------------- // All the following is greatly inspired by the toolkit's sandbox script // - Prepare config file $oSourceConf = new Config(utils::GetConfigFilePath($sSourceEnv)); if ($oSourceConf->Get('source_dir') === '') { throw new Exception('Missing entry source_dir from the config file'); } $oTestConfig = clone($oSourceConf); $oTestConfig->ChangeModulesPath($sSourceEnv, $sTestEnv); // - Switch DB name to a dedicated one so we don't mess with the original one $sTestEnvSanitizedForDBName = preg_replace('/[^\d\w]/', '', $sTestEnv); $sPreviousDB = $oTestConfig->Get('db_name'); $sNewDB = $sPreviousDB.'_'.$sTestEnvSanitizedForDBName; $oTestConfig->Set('db_name', $sNewDB); // - Compile env. based on the existing 'production' env. //$oEnvironment = new UnitTestRunTimeEnvironment($sSourceEnv, $sTestEnv); $this->oEnvironment->WriteConfigFileSafe($oTestConfig); $this->oEnvironment->CompileFrom($sSourceEnv); // - Force re-creating a fresh DB CMDBSource::InitFromConfig($oTestConfig); if (CMDBSource::IsDB($sNewDB)) { CMDBSource::DropDB(); } CMDBSource::CreateDB($sNewDB); MetaModel::Startup($sConfFile, false /* $bModelOnly */, true /* $bAllowCache */, false /* $bTraceSourceFiles */, $sTestEnv); // N°7446 For some reason we need to create the DB schema before starting the MM, then only we can create the tables. MetaModel::DBCreate(); // Make sure that runtime environment is complete // RunTimeEnvironment::AnalyzeInstallation would not return core modules otherwise... CMDBSource::DropTable("priv_module_install"); CMDBSource::Query("CREATE TABLE $sNewDB.priv_module_install SELECT * FROM $sPreviousDB.priv_module_install"); $this->debug("Custom environment '$sTestEnv' is ready!"); } else { $this->debug("Custom environment '$sTestEnv' READY BUILT:"); } parent::PrepareEnvironment(); } }