From 728bbd5bbad0b5269dcd0a4cb70384291d309e70 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 9 Feb 2016 16:33:54 -0800 Subject: [PATCH] CRM-17860 - CiviTester - Split into separate class files --- CRM/Core/ClassLoader.php | 1 - Civi/Test.php | 150 +++++ Civi/Test/CiviEnvBuilder.php | 166 +++++ Civi/Test/CiviEnvBuilder/CallbackStep.php | 29 + Civi/Test/CiviEnvBuilder/ExtensionStep.php | 28 + Civi/Test/CiviEnvBuilder/SqlFileStep.php | 35 + Civi/Test/CiviEnvBuilder/SqlStep.php | 30 + Civi/Test/CiviEnvBuilder/StepInterface.php | 11 + Civi/Test/Data.php | 52 ++ Civi/Test/HeadlessInterface.php | 4 +- Civi/Test/Schema.php | 128 ++++ tests/phpunit/Civi/Test/ExampleHookTest.php | 2 +- .../Civi/Test/ExampleTransactionalTest.php | 2 +- tests/phpunit/CiviTest/CiviTester.php | 599 ------------------ tests/phpunit/CiviTest/CiviUnitTestCase.php | 4 +- tests/phpunit/CiviTest/bootstrap.php | 2 +- 16 files changed, 636 insertions(+), 607 deletions(-) create mode 100644 Civi/Test.php create mode 100644 Civi/Test/CiviEnvBuilder.php create mode 100644 Civi/Test/CiviEnvBuilder/CallbackStep.php create mode 100644 Civi/Test/CiviEnvBuilder/ExtensionStep.php create mode 100644 Civi/Test/CiviEnvBuilder/SqlFileStep.php create mode 100644 Civi/Test/CiviEnvBuilder/SqlStep.php create mode 100644 Civi/Test/CiviEnvBuilder/StepInterface.php create mode 100644 Civi/Test/Data.php create mode 100644 Civi/Test/Schema.php delete mode 100644 tests/phpunit/CiviTest/CiviTester.php diff --git a/CRM/Core/ClassLoader.php b/CRM/Core/ClassLoader.php index c32ef99000..23117ef69e 100644 --- a/CRM/Core/ClassLoader.php +++ b/CRM/Core/ClassLoader.php @@ -77,7 +77,6 @@ class CRM_Core_ClassLoader { 'CiviMailUtils', 'CiviReportTestCase', 'CiviSeleniumTestCase', - 'CiviTester', 'CiviTestSuite', 'CiviUnitTestCase', 'Contact', diff --git a/Civi/Test.php b/Civi/Test.php new file mode 100644 index 0000000000..e59c1e58a1 --- /dev/null +++ b/Civi/Test.php @@ -0,0 +1,150 @@ + TRUE) + ); + } + catch (PDOException $e) { + echo "Can't connect to MySQL server:" . PHP_EOL . $e->getMessage() . PHP_EOL; + exit(1); + } + } + return self::$singletons['pdo']; + } + + /** + * Get the schema manager. + * + * @return \Civi\Test\CiviEnvBuilder + * + * @code + * \Civi\Test::headless()->apply(); + * \Civi\Test::headless()->sqlFile('ex.sql')->apply(); + * @endCode + */ + public static function headless() { + $civiRoot = dirname(__DIR__); + $builder = new \Civi\Test\CiviEnvBuilder('CiviTesterSchema'); + $builder + ->callback(function ($ctx) { + if (CIVICRM_UF !== 'UnitTests') { + throw new \RuntimeException("\\Civi\\Test::headless() requires CIVICRM_UF=UnitTests"); + } + $dbName = \Civi\Test::dsn('database'); + echo "Installing {$dbName} schema\n"; + \Civi\Test::schema()->dropAll(); + }, 'msg-drop') + ->sqlFile($civiRoot . "/sql/civicrm.mysql") + ->sql("DELETE FROM civicrm_extension") + ->callback(function ($ctx) { + \Civi\Test::data()->populate(); + }, 'populate'); + return $builder; + } + + /** + * @return \Civi\Test\Schema + */ + public static function schema() { + if (!isset(self::$singletons['schema'])) { + self::$singletons['schema'] = new \Civi\Test\Schema(); + } + return self::$singletons['schema']; + } + + + /** + * @return \Civi\Test\Data + */ + public static function data() { + if (!isset(self::$singletons['data'])) { + self::$singletons['data'] = new \Civi\Test\Data('CiviTesterData'); + } + return self::$singletons['data']; + } + + /** + * Prepare and execute a batch of SQL statements. + * + * @param string $query + * @return bool + */ + public static function execute($query) { + $pdo = \Civi\Test::pdo(); + + $string = preg_replace("/^#[^\n]*$/m", "\n", $query); + $string = preg_replace("/^(--[^-]).*/m", "\n", $string); + + $queries = preg_split('/;\s*$/m', $string); + foreach ($queries as $query) { + $query = trim($query); + if (!empty($query)) { + $result = $pdo->query($query); + if ($pdo->errorCode() == 0) { + continue; + } + else { + var_dump($result); + var_dump($pdo->errorInfo()); + // die( "Cannot execute $query: " . $pdo->errorInfo() ); + } + } + } + return TRUE; + } + +} diff --git a/Civi/Test/CiviEnvBuilder.php b/Civi/Test/CiviEnvBuilder.php new file mode 100644 index 0000000000..ce2d496288 --- /dev/null +++ b/Civi/Test/CiviEnvBuilder.php @@ -0,0 +1,166 @@ +name = $name; + } + + public function addStep(StepInterface $step) { + $this->targetSignature = NULL; + $this->steps[] = $step; + return $this; + } + + public function callback($callback, $signature = NULL) { + return $this->addStep(new CallbackStep($callback, $signature)); + } + + public function sql($sql) { + return $this->addStep(new SqlStep($sql)); + } + + public function sqlFile($file) { + return $this->addStep(new SqlFileStep($file)); + } + + /** + * Require an extension (based on its name). + * + * @param string $name + * @return \CiviEnvBuilder + */ + public function ext($name) { + return $this->addStep(new ExtensionStep($name)); + } + + /** + * Require an extension (based on its directory). + * + * @param $dir + * @return \CiviEnvBuilder + * @throws \CRM_Extension_Exception_ParseException + */ + public function extDir($dir) { + while ($dir && dirname($dir) !== $dir && !file_exists("$dir/info.xml")) { + $dir = dirname($dir); + } + if (file_exists("$dir/info.xml")) { + $info = \CRM_Extension_Info::loadFromFile("$dir/info.xml"); + $name = $info->key; + } + return $this->addStep(new ExtensionStep($name)); + } + + protected function assertValid() { + foreach ($this->steps as $step) { + if (!$step->isValid()) { + throw new RuntimeException("Found invalid step: " . var_dump($step, 1)); + } + } + } + + /** + * @return string + */ + protected function getTargetSignature() { + if ($this->targetSignature === NULL) { + $buf = ''; + foreach ($this->steps as $step) { + $buf .= $step->getSig(); + } + $this->targetSignature = md5($buf); + } + + return $this->targetSignature; + } + + /** + * @return string + */ + protected function getSavedSignature() { + $liveSchemaRev = NULL; + $pdo = \Civi\Test::pdo(); + $pdoStmt = $pdo->query(sprintf( + "SELECT rev FROM %s.civitest_revs WHERE name = %s", + \Civi\Test::dsn('database'), + $pdo->quote($this->name) + )); + foreach ($pdoStmt as $row) { + $liveSchemaRev = $row['rev']; + } + return $liveSchemaRev; + } + + /** + * @param $newSignature + */ + protected function setSavedSignature($newSignature) { + $pdo = \Civi\Test::pdo(); + $query = sprintf( + 'INSERT INTO %s.civitest_revs (name,rev) VALUES (%s,%s) ' + . 'ON DUPLICATE KEY UPDATE rev = %s;', + \Civi\Test::dsn('database'), + $pdo->quote($this->name), + $pdo->quote($newSignature), + $pdo->quote($newSignature) + ); + + if (\Civi\Test::execute($query) === FALSE) { + throw new RuntimeException("Failed to flag schema version: $query"); + } + } + + /** + * Determine if the schema is correct. If necessary, destroy and recreate. + * + * @param bool $force + * @return $this + */ + public function apply($force = FALSE) { + $dbName = \Civi\Test::dsn('database'); + $query = "USE {$dbName};" + . "CREATE TABLE IF NOT EXISTS civitest_revs (name VARCHAR(64) PRIMARY KEY, rev VARCHAR(64));"; + + if (\Civi\Test::execute($query) === FALSE) { + throw new \RuntimeException("Failed to flag schema version: $query"); + } + + $this->assertValid(); + + if (!$force && $this->getSavedSignature() === $this->getTargetSignature()) { + return $this; + } + foreach ($this->steps as $step) { + $step->run($this); + } + $this->setSavedSignature($this->getTargetSignature()); + return $this; + } + +} diff --git a/Civi/Test/CiviEnvBuilder/CallbackStep.php b/Civi/Test/CiviEnvBuilder/CallbackStep.php new file mode 100644 index 0000000000..6d0c9f055c --- /dev/null +++ b/Civi/Test/CiviEnvBuilder/CallbackStep.php @@ -0,0 +1,29 @@ +callback = $callback; + $this->sig = $sig === NULL ? md5(var_export($callback, 1)) : $sig; + } + + public function getSig() { + return $this->sig; + } + + public function isValid() { + return is_callable($this->callback); + } + + public function run($ctx) { + call_user_func($this->callback, $ctx); + } + +} diff --git a/Civi/Test/CiviEnvBuilder/ExtensionStep.php b/Civi/Test/CiviEnvBuilder/ExtensionStep.php new file mode 100644 index 0000000000..afc4d6c3f5 --- /dev/null +++ b/Civi/Test/CiviEnvBuilder/ExtensionStep.php @@ -0,0 +1,28 @@ +name = $name; + } + + public function getSig() { + return 'ext:' . $this->name; + } + + public function isValid() { + return is_string($this->name); + } + + public function run($ctx) { + \CRM_Extension_System::singleton()->getManager()->install(array( + $this->name, + )); + } + +} diff --git a/Civi/Test/CiviEnvBuilder/SqlFileStep.php b/Civi/Test/CiviEnvBuilder/SqlFileStep.php new file mode 100644 index 0000000000..c901931721 --- /dev/null +++ b/Civi/Test/CiviEnvBuilder/SqlFileStep.php @@ -0,0 +1,35 @@ +file = $file; + } + + + public function getSig() { + return implode(' ', array( + $this->file, + filemtime($this->file), + filectime($this->file), + )); + } + + public function isValid() { + return is_file($this->file) && is_readable($this->file); + } + + public function run($ctx) { + /** @var $ctx \CiviEnvBuilder */ + if (\Civi\Test::execute(@file_get_contents($this->file)) === FALSE) { + throw new \RuntimeException("Cannot load {$this->file}. Aborting."); + } + } + +} diff --git a/Civi/Test/CiviEnvBuilder/SqlStep.php b/Civi/Test/CiviEnvBuilder/SqlStep.php new file mode 100644 index 0000000000..7a2736b019 --- /dev/null +++ b/Civi/Test/CiviEnvBuilder/SqlStep.php @@ -0,0 +1,30 @@ +sql = $sql; + } + + + public function getSig() { + return md5($this->sql); + } + + public function isValid() { + return TRUE; + } + + public function run($ctx) { + /** @var $ctx \CiviEnvBuilder */ + if (\Civi\Test::execute($this->sql) === FALSE) { + throw new \RuntimeException("Cannot execute: {$this->sql}"); + } + } + +} diff --git a/Civi/Test/CiviEnvBuilder/StepInterface.php b/Civi/Test/CiviEnvBuilder/StepInterface.php new file mode 100644 index 0000000000..3d6dc95cc1 --- /dev/null +++ b/Civi/Test/CiviEnvBuilder/StepInterface.php @@ -0,0 +1,11 @@ +truncateAll(); + + \Civi\Test::schema()->setStrict(FALSE); + $sqlDir = dirname(dirname(__DIR__)) . "/sql"; + + $query2 = file_get_contents("$sqlDir/civicrm_data.mysql"); + $query3 = file_get_contents("$sqlDir/test_data.mysql"); + $query4 = file_get_contents("$sqlDir/test_data_second_domain.mysql"); + if (\Civi\Test::execute($query2) === FALSE) { + throw new RuntimeException("Cannot load civicrm_data.mysql. Aborting."); + } + if (\Civi\Test::execute($query3) === FALSE) { + throw new RuntimeException("Cannot load test_data.mysql. Aborting."); + } + if (\Civi\Test::execute($query4) === FALSE) { + throw new RuntimeException("Cannot load test_data.mysql. Aborting."); + } + + unset($query, $query2, $query3); + + \Civi\Test::schema()->setStrict(TRUE); + + // Rebuild triggers + civicrm_api('system', 'flush', array('version' => 3, 'triggers' => 1)); + + \CRM_Core_BAO_ConfigSetting::setEnabledComponents(array( + 'CiviEvent', + 'CiviContribute', + 'CiviMember', + 'CiviMail', + 'CiviReport', + 'CiviPledge', + )); + + return TRUE; + } + +} diff --git a/Civi/Test/HeadlessInterface.php b/Civi/Test/HeadlessInterface.php index fb1cbf4f54..d9e2c6332e 100644 --- a/Civi/Test/HeadlessInterface.php +++ b/Civi/Test/HeadlessInterface.php @@ -27,11 +27,11 @@ interface HeadlessInterface { * It should perform any necessary steps required for putting the database * in a consistent baseline -- such as loading schema and extensions. * - * The utility class `CiviTester` provides a number of helper functions + * The utility class `\Civi\Test` provides a number of helper functions * for managing this setup, and it includes optimizations to avoid redundant * setup work. * - * @see CiviTester + * @see \Civi\Test */ public function setUpHeadless(); diff --git a/Civi/Test/Schema.php b/Civi/Test/Schema.php new file mode 100644 index 0000000000..706f8482f2 --- /dev/null +++ b/Civi/Test/Schema.php @@ -0,0 +1,128 @@ +quote(\Civi\Test::dsn('database')), + $pdo->quote($type) + ); + $tables = $pdo->query($query); + $result = array(); + foreach ($tables as $table) { + $result[] = $table['table_name']; + } + return $result; + } + + public function setStrict($checks) { + $dbName = \Civi\Test::dsn('database'); + if ($checks) { + $queries = array( + "USE {$dbName};", + "SET global innodb_flush_log_at_trx_commit = 1;", + "SET SQL_MODE='STRICT_ALL_TABLES';", + "SET foreign_key_checks = 1;", + ); + } + else { + $queries = array( + "USE {$dbName};", + "SET foreign_key_checks = 0", + "SET SQL_MODE='STRICT_ALL_TABLES';", + "SET global innodb_flush_log_at_trx_commit = 2;", + ); + } + foreach ($queries as $query) { + if (\Civi\Test::execute($query) === FALSE) { + throw new RuntimeException("Query failed: $query"); + } + } + return $this; + } + + public function dropAll() { + $queries = array(); + foreach ($this->getTables('VIEW') as $table) { + if (preg_match('/^(civicrm_|log_)/', $table)) { + $queries[] = "DROP VIEW $table"; + } + } + + foreach ($this->getTables('BASE TABLE') as $table) { + if (preg_match('/^(civicrm_|log_)/', $table)) { + $queries[] = "DROP TABLE $table"; + } + } + + $this->setStrict(FALSE); + foreach ($queries as $query) { + if (\Civi\Test::execute($query) === FALSE) { + throw new RuntimeException("dropSchema: Query failed: $query"); + } + } + $this->setStrict(TRUE); + + return $this; + } + + /** + * @return array + */ + public function truncateAll() { + $tables = \Civi\Test::schema()->getTables('BASE TABLE'); + + $truncates = array(); + $drops = array(); + foreach ($tables as $table) { + // skip log tables + if (substr($table, 0, 4) == 'log_') { + continue; + } + + // don't change list of installed extensions + if ($table == 'civicrm_extension') { + continue; + } + + if (substr($table, 0, 14) == 'civicrm_value_') { + $drops[] = 'DROP TABLE ' . $table . ';'; + } + elseif (substr($table, 0, 9) == 'civitest_') { + // ignore + } + else { + $truncates[] = 'TRUNCATE ' . $table . ';'; + } + } + + \Civi\Test::schema()->setStrict(FALSE); + $queries = array_merge($truncates, $drops); + foreach ($queries as $query) { + if (\Civi\Test::execute($query) === FALSE) { + throw new RuntimeException("Query failed: $query"); + } + } + \Civi\Test::schema()->setStrict(TRUE); + + return $this; + } + +} diff --git a/tests/phpunit/Civi/Test/ExampleHookTest.php b/tests/phpunit/Civi/Test/ExampleHookTest.php index 0d17eed68d..d7e4ebbb9b 100644 --- a/tests/phpunit/Civi/Test/ExampleHookTest.php +++ b/tests/phpunit/Civi/Test/ExampleHookTest.php @@ -16,7 +16,7 @@ class ExampleHookTest extends \PHPUnit_Framework_TestCase implements HeadlessInt protected $contact; public function setUpHeadless() { - return \CiviTester::headless()->apply(); + return \Civi\Test::headless()->apply(); } protected function setUp() { diff --git a/tests/phpunit/Civi/Test/ExampleTransactionalTest.php b/tests/phpunit/Civi/Test/ExampleTransactionalTest.php index dba1299381..7c54db29d1 100644 --- a/tests/phpunit/Civi/Test/ExampleTransactionalTest.php +++ b/tests/phpunit/Civi/Test/ExampleTransactionalTest.php @@ -18,7 +18,7 @@ class ExampleTransactionalTest extends \PHPUnit_Framework_TestCase implements He static $contactIds = array(); public function setUpHeadless() { - return \CiviTester::headless()->apply(); + return \Civi\Test::headless()->apply(); } protected function setUp() { diff --git a/tests/phpunit/CiviTest/CiviTester.php b/tests/phpunit/CiviTest/CiviTester.php deleted file mode 100644 index 89e68acd9f..0000000000 --- a/tests/phpunit/CiviTest/CiviTester.php +++ /dev/null @@ -1,599 +0,0 @@ - TRUE) - ); - } - catch (PDOException$e) { - echo "Can't connect to MySQL server:" . PHP_EOL . $e->getMessage() . PHP_EOL; - exit(1); - } - } - return self::$singletons['pdo']; - } - - /** - * Get the schema manager. - * - * @return \CiviTesterBuilder - * - * @code - * CiviTester::headless()->apply(); - * CiviTester::headless()->sqlFile('ex.sql')->apply(); - * @endCode - */ - public static function headless() { - $civiRoot = dirname(dirname(dirname(dirname(__FILE__)))); - $builder = new CiviTesterBuilder('CiviTesterSchema'); - $builder - ->callback(function ($ctx) { - if (CIVICRM_UF !== 'UnitTests') { - throw new \RuntimeException("CiviTester::headless() requires CIVICRM_UF=UnitTests"); - } - $dbName = CiviTester::dsn('database'); - echo "Installing {$dbName} schema\n"; - CiviTester::schema()->dropAll(); - }, 'msg-drop') - ->sqlFile($civiRoot . "/sql/civicrm.mysql") - ->sql("DELETE FROM civicrm_extension") - ->callback(function ($ctx) { - CiviTester::data()->populate(); - }, 'populate'); - return $builder; - } - - /** - * @return \CiviTesterSchema - */ - public static function schema() { - if (!isset(self::$singletons['schema'])) { - self::$singletons['schema'] = new CiviTesterSchema(); - } - return self::$singletons['schema']; - } - - - /** - * @return \CiviTesterData - */ - public static function data() { - if (!isset(self::$singletons['data'])) { - self::$singletons['data'] = new CiviTesterData('CiviTesterData'); - } - return self::$singletons['data']; - } - - /** - * Prepare and execute a batch of SQL statements. - * - * @param string $query - * @return bool - */ - public static function execute($query) { - $pdo = CiviTester::pdo(); - - $string = preg_replace("/^#[^\n]*$/m", "\n", $query); - $string = preg_replace("/^(--[^-]).*/m", "\n", $string); - - $queries = preg_split('/;\s*$/m', $string); - foreach ($queries as $query) { - $query = trim($query); - if (!empty($query)) { - $result = $pdo->query($query); - if ($pdo->errorCode() == 0) { - continue; - } - else { - var_dump($result); - var_dump($pdo->errorInfo()); - // die( "Cannot execute $query: " . $pdo->errorInfo() ); - } - } - } - return TRUE; - } - -} - -/** - * Class CiviTesterSchema - * - * Manage the entire database. This is useful for destroying or loading the schema. - */ -class CiviTesterSchema { - - /** - * @param string $type - * 'BASE TABLE' or 'VIEW'. - * @return array - */ - public function getTables($type) { - $pdo = CiviTester::pdo(); - // only consider real tables and not views - $query = sprintf( - "SELECT table_name FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_SCHEMA = %s AND TABLE_TYPE = %s", - $pdo->quote(CiviTester::dsn('database')), - $pdo->quote($type) - ); - $tables = $pdo->query($query); - $result = array(); - foreach ($tables as $table) { - $result[] = $table['table_name']; - } - return $result; - } - - public function setStrict($checks) { - $dbName = CiviTester::dsn('database'); - if ($checks) { - $queries = array( - "USE {$dbName};", - "SET global innodb_flush_log_at_trx_commit = 1;", - "SET SQL_MODE='STRICT_ALL_TABLES';", - "SET foreign_key_checks = 1;", - ); - } - else { - $queries = array( - "USE {$dbName};", - "SET foreign_key_checks = 0", - "SET SQL_MODE='STRICT_ALL_TABLES';", - "SET global innodb_flush_log_at_trx_commit = 2;", - ); - } - foreach ($queries as $query) { - if (CiviTester::execute($query) === FALSE) { - throw new RuntimeException("Query failed: $query"); - } - } - return $this; - } - - public function dropAll() { - $queries = array(); - foreach ($this->getTables('VIEW') as $table) { - if (preg_match('/^(civicrm_|log_)/', $table)) { - $queries[] = "DROP VIEW $table"; - } - } - - foreach ($this->getTables('BASE TABLE') as $table) { - if (preg_match('/^(civicrm_|log_)/', $table)) { - $queries[] = "DROP TABLE $table"; - } - } - - $this->setStrict(FALSE); - foreach ($queries as $query) { - if (CiviTester::execute($query) === FALSE) { - throw new RuntimeException("dropSchema: Query failed: $query"); - } - } - $this->setStrict(TRUE); - - return $this; - } - - /** - * @return array - */ - public function truncateAll() { - $tables = CiviTester::schema()->getTables('BASE TABLE'); - - $truncates = array(); - $drops = array(); - foreach ($tables as $table) { - // skip log tables - if (substr($table, 0, 4) == 'log_') { - continue; - } - - // don't change list of installed extensions - if ($table == 'civicrm_extension') { - continue; - } - - if (substr($table, 0, 14) == 'civicrm_value_') { - $drops[] = 'DROP TABLE ' . $table . ';'; - } - elseif (substr($table, 0, 9) == 'civitest_') { - // ignore - } - else { - $truncates[] = 'TRUNCATE ' . $table . ';'; - } - } - - CiviTester::schema()->setStrict(FALSE); - $queries = array_merge($truncates, $drops); - foreach ($queries as $query) { - if (CiviTester::execute($query) === FALSE) { - throw new RuntimeException("Query failed: $query"); - } - } - CiviTester::schema()->setStrict(TRUE); - - return $this; - } - -} - -/** - * Class CiviTesterData - */ -class CiviTesterData { - - /** - * @return bool - */ - public function populate() { - CiviTester::schema()->truncateAll(); - - CiviTester::schema()->setStrict(FALSE); - // initialize test database - $sql_file2 = dirname(dirname(dirname(dirname(__FILE__)))) . "/sql/civicrm_data.mysql"; - $sql_file3 = dirname(dirname(dirname(dirname(__FILE__)))) . "/sql/test_data.mysql"; - $sql_file4 = dirname(dirname(dirname(dirname(__FILE__)))) . "/sql/test_data_second_domain.mysql"; - - $query2 = file_get_contents($sql_file2); - $query3 = file_get_contents($sql_file3); - $query4 = file_get_contents($sql_file4); - if (CiviTester::execute($query2) === FALSE) { - throw new RuntimeException("Cannot load civicrm_data.mysql. Aborting."); - } - if (CiviTester::execute($query3) === FALSE) { - throw new RuntimeException("Cannot load test_data.mysql. Aborting."); - } - if (CiviTester::execute($query4) === FALSE) { - throw new RuntimeException("Cannot load test_data.mysql. Aborting."); - } - - unset($query, $query2, $query3); - - CiviTester::schema()->setStrict(TRUE); - - // Rebuild triggers - civicrm_api('system', 'flush', array('version' => 3, 'triggers' => 1)); - - CRM_Core_BAO_ConfigSetting::setEnabledComponents(array( - 'CiviEvent', - 'CiviContribute', - 'CiviMember', - 'CiviMail', - 'CiviReport', - 'CiviPledge', - )); - - return TRUE; - } - -} - -/** - * Class CiviTesterBuilder - * - * Provides a fluent interface for tracking a set of steps. - * By computing and storing a signature for the list steps, we can - * determine whether to (a) do nothing with the list or (b) - * reapply all the steps. - */ -class CiviTesterBuilder { - protected $name; - - private $steps = array(); - - /** - * @var string|NULL - * A digest of the values in $steps. - */ - private $targetSignature = NULL; - - public function __construct($name) { - $this->name = $name; - } - - public function addStep(CiviTesterStep $step) { - $this->targetSignature = NULL; - $this->steps[] = $step; - return $this; - } - - public function callback($callback, $signature = NULL) { - return $this->addStep(new CiviTesterCallbackStep($callback, $signature)); - } - - public function sql($sql) { - return $this->addStep(new CiviTesterSqlStep($sql)); - } - - public function sqlFile($file) { - return $this->addStep(new CiviTesterSqlFileStep($file)); - } - - /** - * Require an extension (based on its name). - * - * @param string $name - * @return \CiviTesterBuilder - */ - public function ext($name) { - return $this->addStep(new CiviTesterExtensionStep($name)); - } - - /** - * Require an extension (based on its directory). - * - * @param $dir - * @return \CiviTesterBuilder - * @throws \CRM_Extension_Exception_ParseException - */ - public function extDir($dir) { - while ($dir && dirname($dir) !== $dir && !file_exists("$dir/info.xml")) { - $dir = dirname($dir); - } - if (file_exists("$dir/info.xml")) { - $info = CRM_Extension_Info::loadFromFile("$dir/info.xml"); - $name = $info->key; - } - return $this->addStep(new CiviTesterExtensionStep($name)); - } - - protected function assertValid() { - foreach ($this->steps as $step) { - if (!$step->isValid()) { - throw new RuntimeException("Found invalid step: " . var_dump($step, 1)); - } - } - } - - /** - * @return string - */ - protected function getTargetSignature() { - if ($this->targetSignature === NULL) { - $buf = ''; - foreach ($this->steps as $step) { - $buf .= $step->getSig(); - } - $this->targetSignature = md5($buf); - } - - return $this->targetSignature; - } - - /** - * @return string - */ - protected function getSavedSignature() { - $liveSchemaRev = NULL; - $pdo = CiviTester::pdo(); - $pdoStmt = $pdo->query(sprintf( - "SELECT rev FROM %s.civitest_revs WHERE name = %s", - CiviTester::dsn('database'), - $pdo->quote($this->name) - )); - foreach ($pdoStmt as $row) { - $liveSchemaRev = $row['rev']; - } - return $liveSchemaRev; - } - - /** - * @param $newSignature - */ - protected function setSavedSignature($newSignature) { - $pdo = CiviTester::pdo(); - $query = sprintf( - 'INSERT INTO %s.civitest_revs (name,rev) VALUES (%s,%s) ' - . 'ON DUPLICATE KEY UPDATE rev = %s;', - CiviTester::dsn('database'), - $pdo->quote($this->name), - $pdo->quote($newSignature), - $pdo->quote($newSignature) - ); - - if (CiviTester::execute($query) === FALSE) { - throw new RuntimeException("Failed to flag schema version: $query"); - } - } - - /** - * Determine if the schema is correct. If necessary, destroy and recreate. - * - * @param bool $force - * @return $this - */ - public function apply($force = FALSE) { - $dbName = CiviTester::dsn('database'); - $query = "USE {$dbName};" - . "CREATE TABLE IF NOT EXISTS civitest_revs (name VARCHAR(64) PRIMARY KEY, rev VARCHAR(64));"; - - if (CiviTester::execute($query) === FALSE) { - throw new RuntimeException("Failed to flag schema version: $query"); - } - - $this->assertValid(); - - if (!$force && $this->getSavedSignature() === $this->getTargetSignature()) { - return $this; - } - foreach ($this->steps as $step) { - $step->run($this); - } - $this->setSavedSignature($this->getTargetSignature()); - return $this; - } - -} - -interface CiviTesterStep { - public function getSig(); - - public function isValid(); - - public function run($ctx); - -} - -class CiviTesterSqlFileStep implements CiviTesterStep { - private $file; - - /** - * CiviTesterSqlFileStep constructor. - * @param $file - */ - public function __construct($file) { - $this->file = $file; - } - - - public function getSig() { - return implode(' ', array( - $this->file, - filemtime($this->file), - filectime($this->file), - )); - } - - public function isValid() { - return is_file($this->file) && is_readable($this->file); - } - - public function run($ctx) { - /** @var $ctx CiviTesterBuilder */ - if (CiviTester::execute(@file_get_contents($this->file)) === FALSE) { - throw new RuntimeException("Cannot load {$this->file}. Aborting."); - } - } - -} - -class CiviTesterSqlStep implements CiviTesterStep { - private $sql; - - /** - * CiviTesterSqlFileStep constructor. - * @param $sql - */ - public function __construct($sql) { - $this->sql = $sql; - } - - - public function getSig() { - return md5($this->sql); - } - - public function isValid() { - return TRUE; - } - - public function run($ctx) { - /** @var $ctx CiviTesterBuilder */ - if (CiviTester::execute($this->sql) === FALSE) { - throw new RuntimeException("Cannot execute: {$this->sql}"); - } - } - -} - -class CiviTesterCallbackStep implements CiviTesterStep { - private $callback; - private $sig; - - /** - * CiviTesterCallbackStep constructor. - * @param $callback - * @param $sig - */ - public function __construct($callback, $sig = NULL) { - $this->callback = $callback; - $this->sig = $sig === NULL ? md5(var_export($callback, 1)) : $sig; - } - - public function getSig() { - return $this->sig; - } - - public function isValid() { - return is_callable($this->callback); - } - - public function run($ctx) { - call_user_func($this->callback, $ctx); - } - -} - -class CiviTesterExtensionStep implements CiviTesterStep { - private $name; - - /** - * CiviTesterExtensionStep constructor. - * @param $name - */ - public function __construct($name) { - $this->name = $name; - } - - public function getSig() { - return 'ext:' . $this->name; - } - - public function isValid() { - return is_string($this->name); - } - - public function run($ctx) { - CRM_Extension_System::singleton()->getManager()->install(array( - $this->name, - )); - } - -} diff --git a/tests/phpunit/CiviTest/CiviUnitTestCase.php b/tests/phpunit/CiviTest/CiviUnitTestCase.php index 630ff41c3b..c92568aeb0 100644 --- a/tests/phpunit/CiviTest/CiviUnitTestCase.php +++ b/tests/phpunit/CiviTest/CiviUnitTestCase.php @@ -221,7 +221,7 @@ class CiviUnitTestCase extends PHPUnit_Extensions_Database_TestCase { self::$dbInit = TRUE; } - return $this->createDefaultDBConnection(CiviTester::pdo(), $dbName); + return $this->createDefaultDBConnection(Civi\Test::pdo(), $dbName); } /** @@ -253,7 +253,7 @@ class CiviUnitTestCase extends PHPUnit_Extensions_Database_TestCase { } self::$populateOnce = NULL; - CiviTester::data()->populate(); + Civi\Test::data()->populate(); return TRUE; } diff --git a/tests/phpunit/CiviTest/bootstrap.php b/tests/phpunit/CiviTest/bootstrap.php index e351917383..d50ff31fad 100644 --- a/tests/phpunit/CiviTest/bootstrap.php +++ b/tests/phpunit/CiviTest/bootstrap.php @@ -19,7 +19,7 @@ define('CIVICRM_TEST', 1); eval(cv('php:boot --level=settings', 'phpcode')); if (CIVICRM_UF === 'UnitTests') { - CiviTester::headless()->apply(); + Civi\Test::headless()->apply(); } // ------------------------------------------------------------------------------ -- 2.25.1