public function run($request) { $db = DB::getConn(); if (!$db instanceof MySQLDatabase) { echo '<h3>This task only appies to MySQL databases. This installation is using a ' . get_class($db) . '</h3>'; return; } $oldschema = array(); $newschema = array(); $renamed = 0; $current = DB::getConn()->currentDatabase(); foreach (DB::getConn()->tableList() as $lowercase => $dbtablename) { $oldschema[] = $dbtablename; } DB::getConn()->selectDatabase('tmpdb'); $test = new SapphireTest(); $test->create_temp_db(); foreach (DB::getConn()->tableList() as $lowercase => $dbtablename) { $newschema[] = $dbtablename; } $test->kill_temp_db(); DB::getConn()->selectDatabase($current); echo "<ul>\n"; foreach ($newschema as $table) { if (in_array(strtolower($table), $oldschema)) { echo "<li>renaming {$table}</li>"; $db->renameTable(strtolower($table), $table); $renamed++; } } echo "</ul>\n"; echo "<p>{$renamed} tables renamed.</p>\n"; }
/** * @return array */ private function artefacts() { $oldschema = []; $newschema = []; $current = DB::get_conn()->getSelectedDatabase(); foreach (DB::table_list() as $lowercase => $dbtablename) { $oldschema[$dbtablename] = DB::field_list($dbtablename); } $test = new SapphireTest(); $test->create_temp_db(); foreach (DB::table_list() as $lowercase => $dbtablename) { $newschema[$lowercase] = DB::field_list($dbtablename); } $test->kill_temp_db(); DB::get_conn()->selectDatabase($current); $artefacts = []; foreach ($oldschema as $table => $fields) { if (!isset($newschema[strtolower($table)])) { $artefacts[$table] = $table; continue; } foreach ($fields as $field => $spec) { if (!isset($newschema[strtolower($table)][$field])) { $artefacts[$table][$field] = $field; } } } return $artefacts; }
function Artefacts() { $oldschema = array(); $newschema = array(); $current = DB::getConn()->currentDatabase(); foreach (DB::getConn()->tableList() as $lowercase => $dbtablename) { $oldschema[$dbtablename] = DB::getConn()->fieldList($dbtablename); } DB::getConn()->selectDatabase('tmpdb'); $test = new SapphireTest(); $test->create_temp_db(); foreach (DB::getConn()->tableList() as $lowercase => $dbtablename) { $newschema[$lowercase] = DB::getConn()->fieldList($dbtablename); } $test->kill_temp_db(); DB::getConn()->selectDatabase($current); $artefacts = array(); foreach ($oldschema as $table => $fields) { if (!isset($newschema[strtolower($table)])) { $artefacts[$table] = $table; continue; } foreach ($fields as $field => $spec) { if (!isset($newschema[strtolower($table)][$field])) { $artefacts[$table][$field] = $field; } } } return $artefacts; }
/** * Start a test session. * Usage: visit dev/tests/startsession?fixture=(fixturefile). A test database will be constructed, and your browser session will be amended * to use this database. This can only be run on dev and test sites. */ function startsession() { if (!Director::isLive()) { if (SapphireTest::using_temp_db()) { $endLink = Director::baseURL() . "/dev/tests/endsession"; return "<p><a id=\"end-session\" href=\"{$endLink}\">You're in the middle of a test session; click here to end it.</a></p>"; } else { if (!isset($_GET['fixture'])) { $me = Director::baseURL() . "/dev/tests/startsession"; return <<<HTML <form action="{$me}">\t\t\t\t \t<p>Enter a fixture file name to start a new test session. Don't forget to visit dev/tests/endsession when you're done!</p> \t<p>Fixture file (leave blank to start with default set-up): <input id="fixture-file" name="fixture" /></p> \t<input type="hidden" name="flush" value="1"> \t<p><input id="start-session" value="Start test session" type="submit" /></p> </form> HTML; } else { $fixtureFile = $_GET['fixture']; if ($fixtureFile) { // Validate fixture file $realFile = realpath(BASE_PATH . '/' . $fixtureFile); $baseDir = realpath(Director::baseFolder()); if (!$realFile || !file_exists($realFile)) { return "<p>Fixture file doesn't exist</p>"; } else { if (substr($realFile, 0, strlen($baseDir)) != $baseDir) { return "<p>Fixture file must be inside {$baseDir}</p>"; } else { if (substr($realFile, -4) != '.yml') { return "<p>Fixture file must be a .yml file</p>"; } else { if (!preg_match('/^([^\\/.][^\\/]+)\\/tests\\//', $fixtureFile)) { return "<p>Fixture file must be inside the tests subfolder of one of your modules.</p>"; } } } } } $dbname = SapphireTest::create_temp_db(); DB::set_alternative_database_name($dbname); // Fixture if ($fixtureFile) { $fixture = new YamlFixture($fixtureFile); $fixture->saveIntoDatabase(); // If no fixture, then use defaults } else { $dataClasses = ClassInfo::subclassesFor('DataObject'); array_shift($dataClasses); foreach ($dataClasses as $dataClass) { singleton($dataClass)->requireDefaultRecords(); } } return "<p>Started testing session with fixture '{$fixtureFile}'. Time to start testing; where would you like to start?</p>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li><a id=\"home-link\" href=\"" . Director::baseURL() . "\">Homepage - published site</a></li>\n\t\t\t\t\t\t<li><a id=\"draft-link\" href=\"" . Director::baseURL() . "?stage=Stage\">Homepage - draft site</a></li>\n\t\t\t\t\t\t<li><a id=\"admin-link\" href=\"" . Director::baseURL() . "admin/\">CMS Admin</a></li>\n\t\t\t\t\t\t<li><a id=\"endsession-link\" href=\"" . Director::baseURL() . "dev/tests/endsession\">End your test session</a></li>\n\t\t\t\t\t</ul>"; } } } else { return "<p>startession can only be used on dev and test sites</p>"; } }
/** * Assumes the database has already been created in startTestSession(), as this method can be called from * _config.php where we don't yet have a DB connection. * * Persists the state to the filesystem. * * You can extend this by creating an Extension object and implementing either onBeforeApplyState() or * onAfterApplyState() to add your own test state handling in. * * @throws LogicException * @throws InvalidArgumentException */ public function applyState($state) { $this->extend('onBeforeApplyState', $state); $database = isset($state->database) ? $state->database : null; // back up source global $databaseConfig; $this->oldDatabaseName = $databaseConfig['database']; // Load existing state from $this->state into $state, if there is any $oldState = $this->getState(); if ($oldState) { foreach ($oldState as $k => $v) { if (!isset($state->{$k})) { $state->{$k} = $v; // Don't overwrite stuff in $state, as that's the new state } } } // ensure we have a connection to the database if (isset($state->database) && $state->database) { if (!DB::get_conn()) { // No connection, so try and connect to tmpdb if it exists if (isset($state->database)) { $this->oldDatabaseName = $databaseConfig['database']; $databaseConfig['database'] = $state->database; } // Connect to database DB::connect($databaseConfig); } else { // We've already connected to the database, do a fast check to see what database we're currently using $db = DB::get_conn()->getSelectedDatabase(); if (isset($state->database) && $db != $state->database) { $this->oldDatabaseName = $databaseConfig['database']; $databaseConfig['database'] = $state->database; DB::connect($databaseConfig); } } } // Database if (!$this->isRunningTests()) { $dbName = isset($state->database) ? $state->database : null; if ($dbName) { $dbExists = DB::get_conn()->databaseExists($dbName); } else { $dbExists = false; } if (!$dbExists) { // Create a new one with a randomized name $dbName = SapphireTest::create_temp_db(); $state->database = $dbName; // In case it's changed by the call to SapphireTest::create_temp_db(); // Set existing one, assumes it already has been created $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_'; $pattern = strtolower(sprintf('#^%stmpdb\\d{7}#', $prefix)); if (!preg_match($pattern, $dbName)) { throw new InvalidArgumentException("Invalid database name format"); } $this->oldDatabaseName = $databaseConfig['database']; $databaseConfig['database'] = $dbName; // Instead of calling DB::set_alternative_db_name(); // Connect to the new database, overwriting the old DB connection (if any) DB::connect($databaseConfig); } } // Mailer $mailer = isset($state->mailer) ? $state->mailer : null; if ($mailer) { if (!class_exists($mailer) || !is_subclass_of($mailer, 'Mailer')) { throw new InvalidArgumentException(sprintf('Class "%s" is not a valid class, or subclass of Mailer', $mailer)); } } // Date and time if (isset($state->datetime)) { require_once 'Zend/Date.php'; // Convert DatetimeField format if (!Zend_Date::isDate($state->datetime, 'yyyy-MM-dd HH:mm:ss')) { throw new LogicException(sprintf('Invalid date format "%s", use yyyy-MM-dd HH:mm:ss', $state->datetime)); } } $this->saveState($state); $this->extend('onAfterApplyState'); }
function setUp() { SapphireTest::create_temp_db(); SSViewer::flush_template_cache(); }