Index: index.php =================================================================== RCS file: /cvs/drupal/drupal/index.php,v retrieving revision 1.98 diff -u -r1.98 index.php --- index.php 8 Feb 2009 20:27:51 -0000 1.98 +++ index.php 1 Apr 2009 08:26:07 -0000 @@ -19,6 +19,77 @@ require_once DRUPAL_ROOT . '/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); + +if (TRUE) { +// http://drupal.d7x.loc/scripts/run-test.php?test=BlockTestCase&test_id=13370 +ini_set('display_errors', 1); +header('Content-Type: text/plain'); +module_load_include('environment.inc', 'simpletest'); + +class SampleTestCase extends DrupalWebTestCase { + + public static function getInfo() { + return array( + 'name' => 'Sample', + 'description' => 'Sample test', + 'group' => 'Sample group', + ); + } + + public function testSomething() { + $this->assertTrue(TRUE, 'works!'); + } +} + +// Remove left over simpletest tables. +$tables = db_find_tables('simpletest%'); +$ret = array(); +foreach ($tables as $table) { + if ($table != 'simpletest' && $table != 'simpletest_test_id') { + db_drop_table($ret, $table); + } +} + +d('Removed ' . count($ret) . ' of ' . count($tables) . ' tables'); + +// Start of test suite. +d('init()'); +simpletest_environment_init(); + +$classes = array('SampleTestCase'); + +foreach ($classes as $class) { + $info = call_user_func(array($class, 'getInfo')); + d("new $class()"); + $tests = array('testSomething'); //, 'testBlock'); + foreach ($tests as $test) { + d("$test()"); + $prefix = simpletest_environment_setup($info); + print_r(variable_get('simpletest_environment_prefixes', array())); + $instance = new $class(13370); + $instance->$test(); + + $db_prefix = $prefix; // Fake so we get the header. +// echo '-> ' . drupal_http_request(url('scripts/run-test.php', array('absolute' => TRUE, +// 'query' => array('class' => $class, 'method' => $test, 'test_id' => 13370)))); +// $db_prefix = SIMPLETEST_ENVIRONMENT_PREFIX_ORIGINAL; + // TODO Call run-test.php. + simpletest_environment_teardown($info, $prefix); + print_r(variable_get('simpletest_environment_prefixes', array())); + } +} + +d('deinit()'); +simpletest_environment_deinit(); +d('exit()'); + +exit; +} + +function d($message) { + echo "$message...\n"; +} + $return = menu_execute_active_handler(); // Menu status constants are integers; page content is a string or array. Index: modules/simpletest/drupal_web_test_case.php =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v retrieving revision 1.92 diff -u -r1.92 drupal_web_test_case.php --- modules/simpletest/drupal_web_test_case.php 30 Mar 2009 05:35:35 -0000 1.92 +++ modules/simpletest/drupal_web_test_case.php 1 Apr 2009 08:26:08 -0000 @@ -78,27 +78,6 @@ protected $additionalCurlOptions = array(); /** - * The original database prefix, before it was changed for testing purposes. - * - * @var string - */ - protected $originalPrefix = NULL; - - /** - * The original file directory, before it was changed for testing purposes. - * - * @var string - */ - protected $originalFileDirectory = NULL; - - /** - * The original user, before it was changed to a clean uid = 1 for testing purposes. - * - * @var object - */ - protected $originalUser = NULL; - - /** * Current results of this test case. * * @var Array @@ -394,11 +373,11 @@ /** * Run all tests in this class. */ - public function run() { + public function run($method) { set_error_handler(array($this, 'errorHandler')); - $methods = array(); +// $methods = array(); // Iterate through all the methods in this class. - foreach (get_class_methods(get_class($this)) as $method) { +// foreach (get_class_methods(get_class($this)) as $method) { // If the current method starts with "test", run it - it's a test. if (strtolower(substr($method, 0, 4)) == 'test') { $this->setUp(); @@ -411,7 +390,7 @@ } $this->tearDown(); } - } +// } // Clear out the error messages and restore error handler. drupal_get_messages(); restore_error_handler(); @@ -811,128 +790,16 @@ * List of modules to enable for the duration of the test. */ protected function setUp() { - global $db_prefix, $user; - - // Store necessary current values before switching to prefixed database. - $this->originalPrefix = $db_prefix; - $clean_url_original = variable_get('clean_url', 0); - - // Generate temporary prefixed database to ensure that tests have a clean starting point. - $db_prefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}'); - - include_once DRUPAL_ROOT . '/includes/install.inc'; - drupal_install_system(); - - $this->preloadRegistry(); - - // Add the specified modules to the list of modules in the default profile. - $args = func_get_args(); - $modules = array_unique(array_merge(drupal_get_profile_modules('default', 'en'), $args)); - drupal_install_modules($modules, TRUE); - - // Because the schema is static cached, we need to flush - // it between each run. If we don't, then it will contain - // stale data for the previous run's database prefix and all - // calls to it will fail. - drupal_get_schema(NULL, TRUE); - - // Run default profile tasks. - $task = 'profile'; - default_profile_tasks($task, ''); - - // Rebuild caches. - actions_synchronize(); - _drupal_flush_css_js(); - $this->refreshVariables(); - $this->checkPermissions(array(), TRUE); - - // Log in with a clean $user. - $this->originalUser = $user; - drupal_save_session(FALSE); - $user = user_load(1); - - // Restore necessary variables. - variable_set('install_profile', 'default'); - variable_set('install_task', 'profile-finished'); - variable_set('clean_url', $clean_url_original); - variable_set('site_mail', 'simpletest@example.com'); - - // Use temporary files directory with the same prefix as database. - $this->originalFileDirectory = file_directory_path(); - variable_set('file_directory_path', file_directory_path() . '/' . $db_prefix); - $directory = file_directory_path(); - file_check_directory($directory, FILE_CREATE_DIRECTORY); // Create the files directory. set_time_limit($this->timeLimit); } /** - * This method is called by DrupalWebTestCase::setUp, and preloads the - * registry from the testing site to cut down on the time it takes to - * setup a clean environment for the current test run. - */ - protected function preloadRegistry() { - db_query('INSERT INTO {registry} SELECT * FROM ' . $this->originalPrefix . 'registry'); - db_query('INSERT INTO {registry_file} SELECT * FROM ' . $this->originalPrefix . 'registry_file'); - } - - /** - * Refresh the in-memory set of variables. Useful after a page request is made - * that changes a variable in a different thread. - * - * In other words calling a settings page with $this->drupalPost() with a changed - * value would update a variable to reflect that change, but in the thread that - * made the call (thread running the test) the changed variable would not be - * picked up. - * - * This method clears the variables cache and loads a fresh copy from the database - * to ensure that the most up-to-date set of variables is loaded. - */ - protected function refreshVariables() { - global $conf; - cache_clear_all('variables', 'cache'); - $conf = variable_init(); - } - - /** * Delete created files and temporary files directory, delete the tables created by setUp(), * and reset the database prefix. */ protected function tearDown() { global $db_prefix, $user; if (preg_match('/simpletest\d+/', $db_prefix)) { - // Delete temporary files directory and reset files directory path. - file_unmanaged_delete_recursive(file_directory_path()); - variable_set('file_directory_path', $this->originalFileDirectory); - - // Remove all prefixed tables (all the tables in the schema). - $schema = drupal_get_schema(NULL, TRUE); - $ret = array(); - foreach ($schema as $name => $table) { - db_drop_table($ret, $name); - } - - // Return the database prefix to the original. - $db_prefix = $this->originalPrefix; - - // Return the user to the original one. - $user = $this->originalUser; - drupal_save_session(TRUE); - - // Ensure that internal logged in variable and cURL options are reset. - $this->isLoggedIn = FALSE; - $this->additionalCurlOptions = array(); - - // Reload module list and implementations to ensure that test module hooks - // aren't called after tests. - module_list(TRUE); - module_implements(MODULE_IMPLEMENTS_CLEAR_CACHE); - - // Reset the Field API. - field_cache_clear(); - - // Rebuild caches. - $this->refreshVariables(); - // Close the CURL handler. $this->curlClose(); } Index: modules/simpletest/simpletest.environment.inc =================================================================== RCS file: modules/simpletest/simpletest.environment.inc diff -N modules/simpletest/simpletest.environment.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/simpletest.environment.inc 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,274 @@ + 0'); + continue; + } + db_query('INSERT INTO ' . $destination_table . ' SELECT * FROM ' . $source_table); + } +} + +function simpletest_environment_install_modules($prefix, array $modules) { + global $db_prefix; + + $db_prefix = $prefix; + + require_once DRUPAL_ROOT . '/includes/install.inc'; + drupal_install_modules($modules); + + $db_prefix = SIMPLETEST_ENVIRONMENT_PREFIX_ORIGINAL; +} + +function simpletest_environment_uninstall_modules($prefix, array $modules) { + global $db_prefix; + + $db_prefix = $prefix; + + require_once DRUPAL_ROOT . '/includes/install.inc'; + drupal_uninstall_modules($modules); + + $db_prefix = SIMPLETEST_ENVIRONMENT_PREFIX_ORIGINAL; +} + +function simpletest_environment_teardown(array $info, $prefix) { + $base = isset($info['base']) ? $info['base'] : SIMPLETEST_ENVIRONMENT_BASE_DEFAULT; + $modules = isset($info['modules']) ? $info['modules'] : array(); + + $altered = FALSE; + foreach ($modules as $module) { + module_load_install($module); + if (function_exists($module . 'schema_alter')) { + $altered = TRUE; + break; + } + } + + if (!$altered) { + simpletest_environment_uninstall_modules($prefix, $modules); + simpletest_environment_release($base, $prefix); + } + else { + echo "free($prefix)\n"; + } +} + +function simpletest_environment_flush_statics() { + // Because the schema is static cached, we need to flush + // it between each run. If we don't, then it will contain + // stale data for the previous run's database prefix and all + // calls to it will fail. + drupal_get_schema(NULL, TRUE); + + // Rebuild caches. + actions_synchronize(); + _drupal_flush_css_js(); + $this->refreshVariables(); + $this->checkPermissions(array(), TRUE); + + // Reload module list and implementations to ensure that test module hooks + // aren't called after tests. + module_list(TRUE); + module_implements(MODULE_IMPLEMENTS_CLEAR_CACHE); + + // Reset the Field API. + field_cache_clear(); +} + +function simpletest_environment_request($base) { + $prefixes = variable_get('simpletest_environment_prefixes', array()); + + if (isset($prefixes[$base]) && $prefixes[$base]) { + // Use an existing database as a starting shell. + $prefix = array_pop($prefixes[$base]); + variable_set('simpletest_environment_prefixes', $prefixes); + return $prefix; + } + + // Ensure that base exists. + if (!simpletest_environment_base_exists($base)) { + // Create base database using default install profile. + simpletest_environment_base_create($base); + } + + // Create test database from base. TODO comment is old. + $prefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}'); + simpletest_environment_copy_schema($base, $prefix); + return $prefix; +} + +function simpletest_environment_copy_schema($base, $prefix) { + global $db_prefix; + + $db_prefix = $base; + $result = db_query('SELECT name + FROM {system} + WHERE type = :type + AND status = :status', array(':type' => 'module', ':status' => TRUE)); + + $db_prefix = $prefix; + + $modules = array(); + $ret = array(); + while ($module = db_result($result)) { + module_load_install($module); + // Ensure that module implements hook_schema, as drupal_install_schem() + // crashes if called on a module that does not have schema. + if (function_exists($module . '_schema')) { + $ret[] = drupal_install_schema($module); + } + $modules[] = $module; + } + // TODO Check $ret. + + $db_prefix = SIMPLETEST_ENVIRONMENT_PREFIX_ORIGINAL; + return $modules; +} + +function simpletest_environment_release($base, $prefix) { + $prefixes = variable_get('simpletest_environment_prefixes', array()); + + if (!isset($prefixes[$base])) { + $prefixes[$base] = array(); + } + + $prefixes[$base][] = $prefix; + variable_set('simpletest_environment_prefixes', $prefixes); +} + +function simpletest_environment_base_exists($base) { + return (bool) db_find_tables($base . '%'); +} + +function simpletest_environment_base_create($base) { + global $db_prefix; + + $clean_url_original = variable_get('clean_url', 0); + + $prefixOriginal = $db_prefix; + $db_prefix = $base; + + require_once DRUPAL_ROOT . '/includes/install.inc'; + drupal_install_system(); + + simpletest_environment_preload_registry(); + + $modules = drupal_get_profile_modules('default', 'en'); + drupal_install_modules($modules, TRUE); + + // Add the specified modules to the list of modules in the default profile. + $args = func_get_args(); + $modules = array_unique(array_merge(drupal_get_profile_modules('default', 'en'), $args)); + drupal_install_modules($modules, TRUE); + + // Run default profile tasks. + $task = 'profile'; + default_profile_tasks($task, ''); + + // Restore necessary variables. + variable_set('install_profile', 'default'); + variable_set('install_task', 'profile-finished'); + variable_set('clean_url', $clean_url_original); + variable_set('site_mail', 'simpletest@example.com'); + + $db_prefix = $prefixOriginal; +} + +/** + * This method is called by DrupalWebTestCase::setUp, and preloads the + * registry from the testing site to cut down on the time it takes to + * setup a clean environment for the current test run. + */ +function simpletest_environment_preload_registry() { + db_query('INSERT INTO {registry} SELECT * FROM ' . SIMPLETEST_ENVIRONMENT_PREFIX_ORIGINAL . 'registry'); // TODO + db_query('INSERT INTO {registry_file} SELECT * FROM ' . SIMPLETEST_ENVIRONMENT_PREFIX_ORIGINAL . 'registry_file'); +} + +/** + * Refresh the in-memory set of variables. Useful after a page request is made + * that changes a variable in a different thread. + * + * In other words calling a settings page with $this->drupalPost() with a changed + * value would update a variable to reflect that change, but in the thread that + * made the call (thread running the test) the changed variable would not be + * picked up. + * + * This method clears the variables cache and loads a fresh copy from the database + * to ensure that the most up-to-date set of variables is loaded. + */ +function simpletest_environment_refresh_variables() { + global $conf; + cache_clear_all('variables', 'cache'); + $conf = variable_init(); +} + +function simpletest_environment_deinit() { + $prefixes = variable_get('simpletest_environment_prefixes', array()); + foreach ($prefixes as $base => $base_prefixes) { + simpletest_environment_destroy($base); + foreach ($base_prefixes as $prefix) { + simpletest_environment_destroy($prefix); + } + } +} + +function simpletest_environment_destroy($prefix) { + // Remove test database tables due to hook_schema_alter() implementation. + $tables = db_find_tables($prefix . '%'); + $ret = array(); + foreach ($tables as $table) { + db_drop_table($ret, $table); + } + + // Delete temporary files directory and reset files directory path. + file_unmanaged_delete_recursive(file_directory_path() . '/' . $prefix); +} + +//function simpletest_environment_() { +// +//}