diff --git a/core/model/DB.php b/core/model/DB.php index f1e5d932c..66da913ea 100755 --- a/core/model/DB.php +++ b/core/model/DB.php @@ -35,6 +35,15 @@ class DB { static function getConn() { return DB::$globalConn; } + + /** + * Set an alternative database to use for this browser session. + * This is useful when using testing systems other than SapphireTest; for example, Windmill. + * Set it to null to revert to the main database. + */ + static function set_alternative_database_name($dbname) { + $_SESSION["alternativeDatabaseName"] = $dbname; + } /** * Connect to a database. @@ -43,6 +52,9 @@ class DB { * @param array $database A map of options. The 'type' is the name of the subclass of Database to use. For the rest of the options, see the specific class. */ static function connect($databaseConfig) { + // This is used by TestRunner::startsession() to test up a test session using an alt + if(isset($_SESSION["alternativeDatabaseName"]) && $dbname = $_SESSION["alternativeDatabaseName"]) $databaseConfig['database'] = $dbname; + if(!isset($databaseConfig['type']) || empty($databaseConfig['type'])) { user_error("DB::connect: Not passed a valid database config", E_USER_ERROR); } diff --git a/dev/SapphireTest.php b/dev/SapphireTest.php index f3488de49..05aa26e53 100644 --- a/dev/SapphireTest.php +++ b/dev/SapphireTest.php @@ -163,10 +163,18 @@ class SapphireTest extends PHPUnit_Framework_TestCase { } } + /** + * Returns true if we are currently using a temporary database + */ + static function using_temp_db() { + $dbConn = DB::getConn(); + return $dbConn && (substr($dbConn->currentDatabase(),0,5) == 'tmpdb'); + } + static function kill_temp_db() { // Delete our temporary database - $dbConn = DB::getConn(); - if($dbConn && substr($dbConn->currentDatabase(),0,5) == 'tmpdb') { + if(self::using_temp_db()) { + $dbConn = DB::getConn(); $dbName = $dbConn->currentDatabase(); if($dbName && DB::query("SHOW DATABASES LIKE '$dbName'")->value()) { // echo "Deleted temp database " . $dbConn->currentDatabase() . "\n"; @@ -188,6 +196,8 @@ class SapphireTest extends PHPUnit_Framework_TestCase { $dbadmin = new DatabaseAdmin(); $dbadmin->doBuild(true, false, true); + + return $dbname; } } diff --git a/dev/TestRunner.php b/dev/TestRunner.php index 8aa319272..b57fa08ed 100644 --- a/dev/TestRunner.php +++ b/dev/TestRunner.php @@ -34,6 +34,8 @@ class TestRunner extends Controller { static $url_handlers = array( '' => 'browse', 'coverage' => 'coverage', + 'startsession' => 'startsession', + 'endsession' => 'endsession', '$TestCase' => 'only', ); @@ -176,6 +178,69 @@ class TestRunner extends Controller { if(Director::is_cli() && ($results->failureCount() + $results->errorCount()) > 0) exit(2); } + /** + * 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 "

You're in the middle of a test session; click here to end it.

"; + + } else if(!isset($_GET['fixture'])) { + $me = Director::baseURL() . "/dev/tests/startsession"; + return << +

Enter a fixture file name to start a new test session. Don't forget to visit dev/tests/endsession when you're done!

+

Fixture file:

+ +

+ +HTML; + } else { + $fixtureFile = $_GET['fixture']; + + // Validate fixture file + $realFile = realpath('../' . $fixtureFile); + $baseDir = realpath(Director::baseFolder()); + if(!$realFile || !file_exists($realFile)) { + return "

Fixture file doesn't exist

"; + } else if(substr($realFile,0,strlen($baseDir)) != $baseDir) { + return "

Fixture file must be inside $baseDir

"; + } else if(substr($realFile,-4) != '.yml') { + return "

Fixture file must be a .yml file

"; + } else if(!preg_match('/^([^\/.][^\/]+)\/tests\//', $fixtureFile)) { + return "

Fixture file must be inside the tests subfolder of one of your modules.

"; + } + + $dbname = SapphireTest::create_temp_db(); + DB::set_alternative_database_name($dbname); + + $fixture = new YamlFixture($_GET['fixture']); + $fixture->saveIntoDatabase(); + + return "

Started testing session with fixture '$fixtureFile'. Time to start testing; where would you like to start?

+ "; + } + + } else { + return "

startession can only be used on dev and test sites

"; + } + } + + function endsession() { + SapphireTest::kill_temp_db(); + DB::set_alternative_database_name(null); + + return "

Test session ended.

"; + } + function setUp() { SapphireTest::create_temp_db(); }