Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.196
diff -u -r1.196 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	9 Feb 2010 12:28:39 -0000	1.196
+++ modules/simpletest/drupal_web_test_case.php	16 Feb 2010 22:09:22 -0000
@@ -1132,6 +1132,45 @@
     $conf = array();
     drupal_static_reset();
 
+    $this->setUpInstall(func_get_args());
+
+    // Rebuild caches.
+    node_types_rebuild();
+    actions_synchronize();
+    _drupal_flush_css_js();
+    $this->refreshVariables();
+    $this->checkPermissions(array(), TRUE);
+
+    // Run cron once in that environment, as install.php does at the end of
+    // the installation process.
+    drupal_cron_run();
+
+    // Log in with a clean $user.
+    $this->originalUser = $user;
+    drupal_save_session(FALSE);
+    $user = user_load(1);
+
+    $this->setUpVariables($clean_url_original);
+
+    // Set up English language.
+    unset($GLOBALS['conf']['language_default']);
+    $language = language_default();
+
+    // Set path variables
+    variable_set('file_public_path', $public_files_directory);
+    variable_set('file_private_path', $private_files_directory);
+    variable_set('file_temporary_path', $temp_files_directory);
+
+    // Use the test mail class instead of the default mail handler class.
+    variable_set('mail_system', array('default-system' => 'TestingMailSystem'));
+
+    drupal_set_time_limit($this->timeLimit);
+  }
+
+  /**
+   * Perform Drupal installation.
+   */
+  protected function setUpInstall(array $modules = array()) {
     include_once DRUPAL_ROOT . '/includes/install.inc';
     drupal_install_system();
 
@@ -1146,7 +1185,7 @@
 
     drupal_static_reset('_node_types_build');
 
-    if ($modules = func_get_args()) {
+    if ($modules) {
       // Install modules needed for this test.
       module_enable($modules, TRUE, TRUE);
     }
@@ -1160,40 +1199,16 @@
     // Run default profile tasks.
     $install_state = array();
     module_enable(array('standard'), FALSE, TRUE);
+  }
 
-    // Rebuild caches.
-    node_types_rebuild();
-    actions_synchronize();
-    _drupal_flush_css_js();
-    $this->refreshVariables();
-    $this->checkPermissions(array(), TRUE);
-
-    // Run cron once in that environment, as install.php does at the end of
-    // the installation process.
-    drupal_cron_run();
-
-    // Log in with a clean $user.
-    $this->originalUser = $user;
-    drupal_save_session(FALSE);
-    $user = user_load(1);
-
+  /**
+   * Set post-installation variables.
+   */
+  protected function setUpVariables($clean_url_original) {
     // Restore necessary variables.
     variable_set('install_task', 'done');
     variable_set('clean_url', $clean_url_original);
     variable_set('site_mail', 'simpletest@example.com');
-    // Set up English language.
-    unset($GLOBALS['conf']['language_default']);
-    $language = language_default();
-
-    // Set path variables
-    variable_set('file_public_path', $public_files_directory);
-    variable_set('file_private_path', $private_files_directory);
-    variable_set('file_temporary_path', $temp_files_directory);
-
-    // Use the test mail class instead of the default mail handler class.
-    variable_set('mail_system', array('default-system' => 'TestingMailSystem'));
-
-    drupal_set_time_limit($this->timeLimit);
   }
 
   /**
@@ -2726,7 +2741,80 @@
       $this->error(l(t('Verbose message'), $url, array('attributes' => array('target' => '_blank'))), 'User notice');
     }
   }
+}
+
+/**
+ * Clone an existing database and use it for testing.
+ */
+class DrupalCloneTestCase extends DrupalWebTestCase {
+
+  /**
+   * Tables to exlude during data cloning, only their structure will be cloned.
+   *
+   * @var array
+   */
+  protected $excludeTables = array(
+    'cache',
+    'cache_block',
+    'cache_bootstrap',
+    'cache_field',
+    'cache_filter',
+    'cache_form',
+    'cache_image',
+    'cache_menu',
+    'cache_page',
+    'cache_path',
+    'cache_update',
+    'watchdog',
+  );
+
+  protected function setUpInstall() {
+    global $db_prefix;
+
+    // Store new database prefix.
+    $db_prefix_new = $db_prefix;
+    $db_prefix = $this->originalPrefix;
+
+    // Rebuild schema based on prefixed database and such.
+    $schemas = drupal_get_schema(NULL, TRUE);
+
+    // Create a list of prefixed source table names.
+    $sources = array();
+    foreach ($schemas as $name => $schema) {
+      $sources[$name] = Database::getConnection()->prefixTables('{' . $name . '}');
+    }
+
+    // Return to new prefix before performing cloning.
+    $db_prefix = $db_prefix_new;
+
+    // Clone each table into the new database.
+    foreach ($schemas as $name => $schema) {
+      $this->cloneTable($name, $sources[$name], $schema);
+    }
+  }
+
+  protected function setUpVariables() {
+    // Do nothing.
+  }
 
+  /**
+   * Clone an existing table structure and data.
+   *
+   * @param $name
+   *   Table name.
+   * @param $source
+   *   Source table name.
+   * @param $schema
+   *   A Schema API definition array.
+   */
+  protected function cloneTable($name, $source, $schema) {
+    db_create_table($name, $schema);
+
+    $target = Database::getConnection()->prefixTables('{' . $name . '}');
+    if (!in_array($name, $this->excludeTables)) {
+      db_query('INSERT INTO ' . $target . ' SELECT * FROM ' . $source);
+    }
+  }
 }
 
 /**
