? 970564-simpletest-files
? patches
Index: drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/simpletest/Attic/drupal_web_test_case.php,v
retrieving revision 1.2.2.3.2.55
diff -u -p -r1.2.2.3.2.55 drupal_web_test_case.php
--- drupal_web_test_case.php	30 Nov 2010 20:02:06 -0000	1.2.2.3.2.55
+++ drupal_web_test_case.php	1 Dec 2010 00:48:43 -0000
@@ -22,6 +22,13 @@ abstract class DrupalTestCase {
   protected $originalPrefix = NULL;
 
   /**
+   * The database prefix of this test run.
+   *
+   * @var string
+   */
+  protected $databasePrefix = NULL;
+
+  /**
    * The original file directory, before it was changed for testing purposes.
    *
    * @var string
@@ -90,8 +97,6 @@ abstract class DrupalTestCase {
    *   is the caller function itself.
    */
   protected function assert($status, $message = '', $group = 'Other', array $caller = NULL) {
-    global $db_prefix;
-
     // Convert boolean status to string status.
     if (is_bool($status)) {
       $status = $status ? 'pass' : 'fail';
@@ -105,10 +110,6 @@ abstract class DrupalTestCase {
       $caller = $this->getAssertionCall();
     }
 
-    // Switch to non-testing database to store results in.
-    $current_db_prefix = $db_prefix;
-    $db_prefix = $this->originalPrefix;
-
     // Creation assertion array that can be displayed while tests are running.
     $this->assertions[] = $assertion = array(
       'test_id' => $this->testId,
@@ -122,15 +123,13 @@ abstract class DrupalTestCase {
     );
 
     // Store assertion for display after the test has completed.
-//    db_insert('simpletest')
-//      ->fields($assertion)
-//      ->execute();
+    $current_db_prefix = $GLOBALS['db_prefix'];
+    $GLOBALS['db_prefix'] = $this->originalPrefix;
     db_query("INSERT INTO {simpletest}
               (test_id, test_class, status, message, message_group, function, line, file)
               VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d, '%s')", array_values($assertion));
+    $GLOBALS['db_prefix'] = $current_db_prefix;
 
-    // Return to testing prefix.
-    $db_prefix = $current_db_prefix;
     // We do not use a ternary operator here to allow a breakpoint on
     // test failure.
     if ($status == 'pass') {
@@ -411,11 +410,29 @@ abstract class DrupalTestCase {
   }
 
   /**
+   * Logs verbose message in a text file.
+   *
+   * The a link to the vebose message will be placed in the test results via
+   * as a passing assertion with the text '[verbose message]'.
+   *
+   * @param $message
+   *   The verbose message to be stored.
+   *
+   * @see simpletest_verbose()
+   */
+  protected function verbose($message) {
+    if ($id = simpletest_verbose($message)) {
+      $url = $GLOBALS['base_url'] . '/' . $this->originalFileDirectory . '/simpletest/verbose/' . get_class($this) . '-' . $id . '.html';
+      $this->error(l(t('Verbose message'), $url, array('attributes' => array('target' => '_blank'))), 'User notice');
+    }
+  }
+
+  /**
    * Run all tests in this class.
    */
   public function run() {
     // Initialize verbose debugging.
-    simpletest_verbose(NULL, file_directory_path(), get_class($this));
+    simpletest_verbose(NULL, variable_get('file_directory_path', conf_path() . '/files'), get_class($this));
 
     // HTTP auth settings (<username>:<password>) for the simpletest browser
     // when sending requests to the test site.
@@ -562,18 +579,31 @@ class DrupalUnitTestCase extends DrupalT
     $this->skipClasses[__CLASS__] = TRUE;
   }
 
-  function setUp() {
-    global $db_prefix, $conf;
+  /**
+   * Sets up unit test environment.
+   *
+   * Unlike DrupalWebTestCase::setUp(), DrupalUnitTestCase::setUp() does not
+   * install modules because tests are performed without accessing the database.
+   * Any required files must be explicitly included by the child class setUp()
+   * method.
+   */
+  protected function setUp() {
+    global $conf;
 
-    // Store necessary current values before switching to prefixed database.
-    $this->originalPrefix = $db_prefix;
-    $this->originalFileDirectory = file_directory_path();
+    // Store necessary current values before switching to the test environment.
+    $this->originalPrefix = $GLOBALS['db_prefix'];
+    $this->originalFileDirectory =  variable_get('file_directory_path', conf_path() . '/files');
 
     // Generate temporary prefixed database to ensure that tests have a clean starting point.
-//    $db_prefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
-    $db_prefix = $db_prefix . 'simpletest' . mt_rand(1000, 1000000);
-//    $conf['file_public_path'] = $this->originalFileDirectory . '/' . $db_prefix;
-    $conf['file_directory_path'] = $this->originalFileDirectory . '/simpletest/' . substr($db_prefix, 10);
+    $this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000);
+
+    // Create test directory.
+    $public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
+    file_check_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    $conf['file_directory_path'] = $public_files_directory;
+
+    // Clone the current connection and replace the current prefix.
+    $GLOBALS['db_prefix'] = $GLOBALS['db_prefix'] . $this->databasePrefix;
 
     // If locale is enabled then t() will try to access the database and
     // subsequently will fail as the database is not accessible.
@@ -585,17 +615,16 @@ class DrupalUnitTestCase extends DrupalT
     }
   }
 
-  function tearDown() {
-    global $db_prefix, $conf;
-    if (preg_match('/simpletest\d+/', $db_prefix)) {
-//      $conf['file_public_path'] = $this->originalFileDirectory;
-      $conf['file_directory_path'] = $this->originalFileDirectory;
-      // Return the database prefix to the original.
-      $db_prefix = $this->originalPrefix;
-      // Restore modules if necessary.
-      if (isset($this->originalModuleList)) {
-        module_list(TRUE, FALSE, FALSE, $this->originalModuleList);
-      }
+  protected function tearDown() {
+    global $conf;
+
+    // Get back to the original connection.
+    $GLOBALS['db_prefix'] = $this->originalPrefix;
+
+    $conf['file_directory_path'] = $this->originalFileDirectory;
+    // Restore modules if necessary.
+    if (isset($this->originalModuleList)) {
+      module_list(TRUE, FALSE, FALSE, $this->originalModuleList);
     }
   }
 }
@@ -605,6 +634,13 @@ class DrupalUnitTestCase extends DrupalT
  */
 class DrupalWebTestCase extends DrupalTestCase {
   /**
+   * The profile to install as a basis for testing.
+   *
+   * @var string
+   */
+  protected $profile = 'default';
+
+  /**
    * The URL currently loaded in the internal browser.
    *
    * @var string
@@ -703,6 +739,11 @@ class DrupalWebTestCase extends DrupalTe
   protected $session_id = NULL;
 
   /**
+   * Whether the files were copied to the test files directory.
+   */
+  protected $generatedTestFiles = FALSE;
+
+  /**
    * The number of redirects followed during the handling of a request.
    */
   protected $redirect_count;
@@ -843,14 +884,35 @@ class DrupalWebTestCase extends DrupalTe
    *   List of files that match filter.
    */
   protected function drupalGetTestFiles($type, $size = NULL) {
-    $files = array();
+    if (empty($this->generatedTestFiles)) {
+      // Generate binary test files.
+      $lines = array(64, 1024);
+      $count = 0;
+      foreach ($lines as $line) {
+        simpletest_generate_file('binary-' . $count++, 64, $line, 'binary');
+      }
 
+      // Generate text test files.
+      $lines = array(16, 256, 1024, 2048, 20480);
+      $count = 0;
+      foreach ($lines as $line) {
+        simpletest_generate_file('text-' . $count++, 64, $line);
+      }
+
+      // Copy other test files from simpletest.
+      $original = drupal_get_path('module', 'simpletest') . '/files';
+      $files = file_scan_directory($original, '(html|image|javascript|php|sql)-.*');
+      foreach ($files as $file) {
+        file_copy($file->filename, variable_get('file_directory_path', conf_path() . '/files'));
+      }
+
+      $this->generatedTestFiles = TRUE;
+    }
+
+    $files = array();
     // Make sure type is valid.
     if (in_array($type, array('binary', 'html', 'image', 'javascript', 'php', 'sql', 'text'))) {
-      // Use original file directory instead of one created during setUp().
-      $path = $this->originalFileDirectory . '/simpletest';
-//      $files = file_scan_directory($path, '/' . $type . '\-.*/');
-      $files = file_scan_directory($path, '' . $type . '\-.*');
+      $files = file_scan_directory(variable_get('file_directory_path', conf_path() . '/files'), '' . $type . '\-.*');
 
       // If size is set then remove any files that are not of that size.
       if ($size !== NULL) {
@@ -1061,17 +1123,23 @@ class DrupalWebTestCase extends DrupalTe
    * is created with the same name as the database prefix.
    *
    * @param ...
-   *   List of modules to enable for the duration of the test.
+   *   List of modules to enable for the duration of the test. This can be
+   *   either a single array or a variable number of string arguments.
    */
   protected function setUp() {
-    global $db_prefix, $user, $language;
+    global $user, $language, $conf;
+
+    // Generate a temporary prefixed database to ensure that tests have a clean starting point.
+    $this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000);
+    $db_prefix_new = $GLOBALS['db_prefix'] . $this->databasePrefix;
+    db_query("UPDATE {simpletest_test_id} SET last_prefix = '%s' WHERE test_id = %d", $db_prefix_new, $this->testId);
 
     // Store necessary current values before switching to prefixed database.
+    $this->originalPrefix = $GLOBALS['db_prefix'];
     $this->originalLanguage = $language;
-//    $this->originalLanguageDefault = variable_get('language_default');
-    $this->originalPrefix = $db_prefix;
-    $this->originalFileDirectory = file_directory_path();
-//    $this->originalProfile = drupal_get_profile();
+    $this->originalLanguageDefault = variable_get('language_default', (object) array('language' => 'en', 'name' => 'English', 'native' => 'English', 'direction' => 0, 'enabled' => 1, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => '', 'weight' => 0, 'javascript' => ''));
+    $this->originalFileDirectory = variable_get('file_directory_path', conf_path() . '/files');
+    $this->originalProfile = variable_get('install_profile', 'default');
     $clean_url_original = variable_get('clean_url', 0);
 
     // Must reset locale here, since schema calls t(). (Drupal 6)
@@ -1080,49 +1148,44 @@ class DrupalWebTestCase extends DrupalTe
       locale(NULL, NULL, TRUE);
     }
 
-    // Generate temporary prefixed database to ensure that tests have a clean starting point.
-//    $db_prefix_new = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
-    $db_prefix_new = $db_prefix . 'simpletest' . mt_rand(1000, 1000000);
-
     // Workaround to insure we init the theme layer before going into prefixed
     // environment. (Drupal 6)
     $this->pass(t('Starting run with db_prefix %prefix', array('%prefix' => $db_prefix_new)), 'System');
 
-//    db_update('simpletest_test_id')
-//      ->fields(array('last_prefix' => $db_prefix_new))
-//      ->condition('test_id', $this->testId)
-//      ->execute();
-    db_query("UPDATE {simpletest_test_id}
-              SET last_prefix = '%s'
-              WHERE test_id = %d", $db_prefix_new, $this->testId);
-    $db_prefix = $db_prefix_new;
+    // Clone the current connection and replace the current prefix.
+    $GLOBALS['db_prefix'] = $db_prefix_new;
 
     // Create test directory ahead of installation so fatal errors and debug
     // information can be logged during installation process.
-    $directory = $this->originalFileDirectory . '/simpletest/' . substr($db_prefix, 10);
-//    file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-    file_check_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    // Use temporary files directory with the same prefix as the database.
+    $public_files_directory  = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
+    $temp_files_directory    = $public_files_directory . '/tmp';
+
+    // Create the directories
+    file_check_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    file_check_directory($temp_files_directory, FILE_CREATE_DIRECTORY);
+    $this->generatedTestFiles = FALSE;
 
     // Log fatal errors.
     ini_set('log_errors', 1);
-    ini_set('error_log', $directory . '/error.log');
+    ini_set('error_log', $public_files_directory . '/error.log');
+
+    // Reset all statics and variables to perform tests in a clean environment.
+    $conf = array();
 
-//    include_once DRUPAL_ROOT . '/includes/install.inc';
     include_once './includes/install.inc';
     drupal_install_system();
 
-//    $this->preloadRegistry();
-
-//    // Include the default profile
-//    variable_set('install_profile', 'default');
-//    $profile_details = install_profile_info('default', 'en');
-
-    // Add the specified modules to the list of modules in the default profile.
-    // Install the modules specified by the default profile.
-//    drupal_install_modules($profile_details['dependencies'], TRUE);
-    drupal_install_modules(drupal_verify_profile('default', 'en'));
+    // Set path variables.
+    variable_set('file_directory_path', $public_files_directory);
+    variable_set('file_directory_temp', $temp_files_directory);
+
+    // Include the testing profile.
+    variable_set('install_profile', $this->profile);
+    $profile_modules = drupal_verify_profile($this->profile, 'en');
 
-//    node_type_clear();
+    // Install the modules specified by the testing profile.
+    drupal_install_modules($profile_modules);
 
     // Install modules needed for this test. This could have been passed in as
     // either a single array argument or a variable number of string arguments.
@@ -1136,76 +1199,60 @@ class DrupalWebTestCase extends DrupalTe
       drupal_install_modules($modules);
     }
 
-    // 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.
-//    $install_state = array();
-//    drupal_install_modules(array('default'), TRUE);
+    // Run the profile tasks.
     $task = 'profile';
-    default_profile_tasks($task, '');
+    $function = $this->profile . '_profile_tasks';
+    if (function_exists($function)) {
+      $function($task, '');
+    }
 
-    // Rebuild caches.
-//    node_types_rebuild();
-    actions_synchronize();
-    _drupal_flush_css_js();
-    $this->refreshVariables();
-    $this->checkPermissions(array(), TRUE);
-    user_access(NULL, NULL, TRUE); // Drupal 6.
+    // Reset/rebuild all data structures after enabling the modules.
+    $this->resetAll();
+
+    // 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);
     session_save_session(FALSE);
     $user = user_load(array('uid' => 1));
 
     // Restore necessary variables.
-    variable_set('install_profile', 'default');
-//    variable_set('install_task', 'done');
-    variable_set('install_task', 'profile-finished');
+    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 up English language.
+    unset($GLOBALS['conf']['language_default']);
+    $language = language_default();
 
     // Use the test mail class instead of the default mail handler class.
-//    variable_set('mail_sending_system', array('default-system' => 'TestingMailSystem'));
     variable_set('smtp_library', drupal_get_path('module', 'simpletest') . '/simpletest.mail.inc');
 
-    // Use temporary files directory with the same prefix as the database.
-//    $public_files_directory  = $this->originalFileDirectory . '/' . $db_prefix;
-//    $private_files_directory = $public_files_directory . '/private';
-    $directory = $this->originalFileDirectory . '/' . $db_prefix;
-
-    // Set path variables
-//    variable_set('file_public_path', $public_files_directory);
-//    variable_set('file_private_path', $private_files_directory);
-    variable_set('file_directory_path', $directory);
-
-    // Create the directories
-//    $directory = file_directory_path('public');
-//    file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-//    file_prepare_directory($private_files_directory, FILE_CREATE_DIRECTORY);
-    file_check_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-
-//    drupal_set_time_limit($this->timeLimit);
     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');
-//  }
+  /**
+   * Reset all data structures after having enabled new modules.
+   *
+   * This method is called by DrupalWebTestCase::setUp() after enabling
+   * the requested modules. It must be called again when additional modules
+   * are enabled later.
+   */
+  protected function resetAll() {
+    // Rebuild caches.
+    drupal_flush_all_caches();
+    actions_synchronize();
+    user_access(NULL, NULL, TRUE);
+
+    // Reload global $conf array and permissions.
+    $this->refreshVariables();
+    $this->checkPermissions(array(), TRUE);
+
+    // Reset statically cached schema for new database prefix.
+    drupal_get_schema(NULL, TRUE);
+  }
 
   /**
    * Refresh the in-memory set of variables. Useful after a page request is made
@@ -1230,72 +1277,68 @@ class DrupalWebTestCase extends DrupalTe
    * and reset the database prefix.
    */
   protected function tearDown() {
-    global $db_prefix, $user, $language;
+    global $user, $language;
 
     // In case a fatal error occured that was not in the test process read the
     // log to pick up any fatal errors.
-    $db_prefix_temp = $db_prefix;
-    $db_prefix = $this->originalPrefix;
-    simpletest_log_read($this->testId, $db_prefix, get_class($this), TRUE);
-    $db_prefix = $db_prefix_temp;
+    $current_db_prefix = $GLOBALS['db_prefix'];
+    $GLOBALS['db_prefix'] = $this->originalPrefix;
+    simpletest_log_read($this->testId, $this->databasePrefix, get_class($this), TRUE);
+    $GLOBALS['db_prefix'] = $current_db_prefix;
 
     $emailCount = count(variable_get('drupal_test_email_collector', array()));
     if ($emailCount) {
-      $message = format_plural($emailCount, t('!count e-mail was sent during this test.'), t('!count e-mails were sent during this test.'), array('!count' => $emailCount));
+      $message = format_plural($emailCount, '1 e-mail was sent during this test.', '@count e-mails were sent during this test.');
       $this->pass($message, t('E-mail'));
     }
 
-    if (preg_match('/simpletest\d+/', $db_prefix)) {
-      // Delete temporary files directory.
-//      file_unmanaged_delete_recursive(file_directory_path());
-      simpletest_clean_temporary_directory(file_directory_path());
+    if (!preg_match('/simpletest\d+/', $GLOBALS['db_prefix'])) {
+      return;
+    }
 
-      // 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);
-      }
+    // Delete temporary files directory.
+    simpletest_file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
 
-      // Return the database prefix to the original.
-      $db_prefix = $this->originalPrefix;
+    // 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 user to the original one.
-      $user = $this->originalUser;
-//      drupal_save_session(TRUE);
-      session_save_session(TRUE);
+    // Get back to the original connection.
+    $GLOBALS['db_prefix'] = $this->originalPrefix;
 
-      // Bring back default language. (Drupal 6)
-      if (module_exists('locale')) {
-        drupal_init_language();
-        locale(NULL, NULL, TRUE);
-      }
+    // Return the user to the original one.
+    $user = $this->originalUser;
+    session_save_session(TRUE);
 
-      // Ensure that internal logged in variable and cURL options are reset.
-      $this->loggedInUser = FALSE;
-      $this->additionalCurlOptions = array();
+    // Bring back default language. (Drupal 6)
+    if (module_exists('locale')) {
+      drupal_init_language();
+      locale(NULL, NULL, TRUE);
+    }
+
+    // Ensure that internal logged in variable and cURL options are reset.
+    $this->loggedInUser = 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('', '', TRUE);
 
-      // Reload module list and implementations to ensure that test module hooks
-      // aren't called after tests.
-      module_list(TRUE);
-//      module_implements('', FALSE, TRUE);
-      module_implements('', '', TRUE);
-
-      // Reset the Field API.
-//      field_cache_clear();
-
-      // Rebuild caches.
-      $this->refreshVariables();
-
-//      // Reset language.
-//      $language = $this->originalLanguage;
-//      if ($this->originalLanguageDefault) {
-//        $GLOBALS['conf']['language_default'] = $this->originalLanguageDefault;
-//      }
+    // Rebuild caches.
+    $this->refreshVariables();
 
-      // Close the CURL handler.
-      $this->curlClose();
+    // Reset language.
+    $language = $this->originalLanguage;
+    if ($this->originalLanguageDefault) {
+      $GLOBALS['conf']['language_default'] = $this->originalLanguageDefault;
     }
+
+    // Close the CURL handler.
+    $this->curlClose();
   }
 
   /**
@@ -1307,7 +1350,7 @@ class DrupalWebTestCase extends DrupalTe
    * See the description of $curl_options for other options.
    */
   protected function curlInitialize() {
-    global $base_url, $db_prefix;
+    global $base_url;
 
     if (!isset($this->curlHandle)) {
       $this->curlHandle = curl_init();
@@ -1319,6 +1362,7 @@ class DrupalWebTestCase extends DrupalTe
         CURLOPT_SSL_VERIFYPEER => FALSE, // Required to make the tests run on https.
         CURLOPT_SSL_VERIFYHOST => FALSE, // Required to make the tests run on https.
         CURLOPT_HEADERFUNCTION => array(&$this, 'curlHeaderCallback'),
+        //CURLOPT_USERAGENT => $GLOBALS['db_prefix'],
       );
       if (isset($this->httpauth_credentials)) {
         $curl_options[CURLOPT_HTTPAUTH] = $this->httpauth_method;
@@ -1331,7 +1375,7 @@ class DrupalWebTestCase extends DrupalTe
     }
     // We set the user agent header on each request so as to use the current
     // time and a new uniqid.
-    if (preg_match('/simpletest\d+/', $db_prefix, $matches)) {
+    if (preg_match('/simpletest\d+/', $GLOBALS['db_prefix'], $matches)) {
       curl_setopt($this->curlHandle, CURLOPT_USERAGENT, drupal_generate_test_ua($matches[0]));
     }
   }
@@ -1517,13 +1561,6 @@ class DrupalWebTestCase extends DrupalTe
     return $out;
   }
 
-  ///**
-  // * Retrieve a Drupal path or an absolute path and JSON decode the result.
-  // */
-  //protected function drupalGetAJAX($path, array $options = array(), array $headers = array()) {
-  //  return drupal_json_decode($this->drupalGet($path, $options, $headers));
-  //}
-
   /**
    * Execute a POST request on a Drupal page.
    * It will be done as usual POST request with SimpleBrowser.
@@ -1907,7 +1944,11 @@ class DrupalWebTestCase extends DrupalTe
   protected function xpath($xpath, array $arguments = array()) {
     if ($this->parse()) {
       $xpath = $this->buildXPathQuery($xpath, $arguments);
-      return $this->elements->xpath($xpath);
+      $result = $this->elements->xpath($xpath);
+      // Some combinations of PHP / libxml versions return an empty array
+      // instead of the documented FALSE. Forcefully convert any falsish values
+      // to an empty array to allow foreach(...) constructions.
+      return $result ? $result : array();
     }
     else {
       return FALSE;
@@ -2204,7 +2245,7 @@ class DrupalWebTestCase extends DrupalTe
 
     foreach ($captured_emails as $message) {
       foreach ($filter as $key => $value) {
-        if (!isset($message['params'][$key]) || $message['params'][$key] != $value) {
+        if ((!isset($message[$key]) || $message[$key] != $value) && (!isset($message['params'][$key]) || $message['params'][$key] != $value)) {
           continue 2;
         }
       }
@@ -2898,29 +2939,68 @@ class DrupalWebTestCase extends DrupalTe
   protected function assertMail($name, $value = '', $message = '') {
     $captured_emails = variable_get('drupal_test_email_collector', array());
     $email = end($captured_emails);
-//    return $this->assertTrue($email && isset($email[$name]) && $email[$name] == $value, $message, t('E-mail'));
-    return $this->assertTrue(
-      ($email && isset($email[$name]) && $email[$name] == $value) ||
-      ($email && isset($email['params'][$name]) && $email['params'][$name] == $value),
-      $message,
-      t('E-mail'));
+    return $this->assertTrue($email && (isset($email[$name]) && $email[$name] == $value || isset($email['params'][$name]) && $email['params'][$name] == $value), $message, t('E-mail'));
   }
 
   /**
-   * Logs verbose message in a text file.
+   * Asserts that the most recently sent e-mail message has the string in it.
    *
-   * The a link to the vebose message will be placed in the test results via
-   * as a passing assertion with the text '[verbose message]'.
+   * @param $field_name
+   *   Name of field or message property to assert: subject, body, id, ...
+   * @param $string
+   *   String to search for.
+   * @param $email_depth
+   *   Number of emails to search for string, starting with most recent.
    *
-   * @param $message
-   *   The verbose message to be stored.
+   * @return
+   *   TRUE on pass, FALSE on fail.
+   */
+  protected function assertMailString($field_name, $string, $email_depth) {
+    $mails = $this->drupalGetMails();
+    $string_found = FALSE;
+    for ($i = sizeof($mails) -1; $i >= sizeof($mails) - $email_depth && $i >= 0; $i--) {
+      $mail = $mails[$i];
+      // Normalize whitespace, as we don't know what the mail system might have
+      // done. Any run of whitespace becomes a single space.
+      $normalized_mail = preg_replace('/\s+/', ' ', $mail[$field_name]);
+      $normalized_string = preg_replace('/\s+/', ' ', $string);
+      $string_found = (FALSE !== strpos($normalized_mail, $normalized_string));
+      if ($string_found) {
+        break;
+      }
+    }
+    return $this->assertTrue($string_found, t('Expected text found in @field of email message: "@expected".', array('@field' => $field_name, '@expected' => $string)));
+  }
+
+  /**
+   * Asserts that the most recently sent e-mail message has the pattern in it.
    *
-   * @see simpletest_verbose()
+   * @param $field_name
+   *   Name of field or message property to assert: subject, body, id, ...
+   * @param $regex
+   *   Pattern to search for.
+   *
+   * @return
+   *   TRUE on pass, FALSE on fail.
    */
-  protected function verbose($message) {
-    if ($id = simpletest_verbose($message)) {
-      $file_path = $GLOBALS['base_url'] . '/' . $this->originalFileDirectory . '/simpletest/verbose/' . get_class($this) . '-' . $id . '.html';
-      $this->pass(l(t('Verbose message'), $file_path, array('attributes' => array('target' => '_blank'))), 'Debug');
+  protected function assertMailPattern($field_name, $regex, $message) {
+    $mails = $this->drupalGetMails();
+    $mail = end($mails);
+    $regex_found = preg_match("/$regex/", $mail[$field_name]);
+    return $this->assertTrue($regex_found, t('Expected text found in @field of email message: "@expected".', array('@field' => $field_name, '@expected' => $regex)));
+  }
+
+  /**
+   * Outputs to verbose the most recent $count emails sent.
+   *
+   * @param $count
+   *   Optional number of emails to output.
+   */
+  protected function verboseEmail($count = 1) {
+    $mails = $this->drupalGetMails();
+    for ($i = sizeof($mails) -1; $i >= sizeof($mails) - $count && $i >= 0; $i--) {
+      $mail = $mails[$i];
+      $this->verbose(t('Email:') . '<pre>' . print_r($mail, TRUE) . '</pre>');
     }
   }
 }
Index: simpletest.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/simpletest/Attic/simpletest.install,v
retrieving revision 1.4.2.3.2.25
diff -u -p -r1.4.2.3.2.25 simpletest.install
--- simpletest.install	13 Nov 2010 01:03:47 -0000	1.4.2.3.2.25
+++ simpletest.install	1 Dec 2010 00:48:43 -0000
@@ -7,130 +7,6 @@
  */
 
 /**
- * Implements hook_install().
- */
-function simpletest_install() {
-  // Install schema.
-  drupal_install_schema('simpletest');
-
-  // Check for files directory.
-//  $path = 'public://simpletest';
-//  if (file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
-  $path = file_directory_path() . '/simpletest';
-  if (file_check_directory($path, FILE_CREATE_DIRECTORY)) {
-    // Generate binary and text test files.
-    $generated = FALSE;
-    if (simpletest_get_file_count($path, 'binary') == 0) {
-      $lines = array(64, 1024);
-      foreach ($lines as $line) {
-        simpletest_generate_file('binary', 64, $line, 'binary');
-      }
-      $generated = TRUE;
-    }
-
-    if (simpletest_get_file_count($path, 'text') == 0) {
-      $lines = array(16, 256, 1024, 2048, 20480);
-      foreach ($lines as $line) {
-        simpletest_generate_file('text', 64, $line);
-      }
-      $generated = TRUE;
-    }
-
-    // Copy other test files for consistency.
-    $original = drupal_get_path('module', 'simpletest') . '/files';
-//    $files = file_scan_directory($original, '/(html|image|javascript|php|sql)-.*/');
-    $files = file_scan_directory($original, '(html|image|javascript|php|sql)-.*');
-
-    // If there are more files in SimpleTest's files directory than the site's
-    // files directory, restore all the files. This situation might occur when
-    // an errant test deletes one or more files from the site's files
-    // directory. It serves a convenience to developers so that they can get
-    // the test files back easily.
-//    if (count($files) > count(file_scan_directory($path, '/(html|image|javascript|php|sql)-.*/'))) {
-    if (count($files) > count(file_scan_directory($path, '(html|image|javascript|php|sql)-.*'))) {
-      foreach ($files as $file) {
-//        file_unmanaged_copy($file->uri, $path, FILE_EXISTS_REPLACE);
-        copy($file->filename, $path . '/' . $file->basename);
-      }
-      $generated = TRUE;
-    }
-
-    if ($generated) {
-      drupal_set_message('Extra test files generated/copied.');
-    }
-  }
-}
-
-/**
- * Generate test file.
- */
-function simpletest_generate_file($filename, $width, $lines, $type = 'binary-text') {
-  $size = $width * $lines - $lines;
-
-  // Generate random text
-  $text = '';
-  for ($i = 0; $i < $size; $i++) {
-    switch ($type) {
-      case 'text':
-        $text .= chr(rand(32, 126));
-        break;
-      case 'binary':
-        $text .= chr(rand(0, 31));
-        break;
-      case 'binary-text':
-      default:
-        $text .= rand(0, 1);
-        break;
-    }
-  }
-  $text = wordwrap($text, $width - 1, "\n", TRUE) . "\n"; // Add \n for symetrical file.
-
-  // Create filename.
-  $path = file_directory_path() . '/simpletest/';
-  $count = simpletest_get_file_count($path, $filename);
-  file_put_contents($path . $filename . '-' . ($count + 1) . '.txt', $text);
-}
-
-/**
- * Get the number of files that have the specified filename base.
- */
-function simpletest_get_file_count($directory, $filename) {
-  $files = scandir($directory);
-  $count = 0;
-  foreach ($files as $file) {
-    if (preg_match('/' . $filename . '.*?/', $file)) {
-      $count++;
-    }
-  }
-  return $count;
-}
-
-/**
- * Implements hook_uninstall().
- */
-function simpletest_uninstall() {
-  simpletest_clean_environment();
-
-  // Remove settings variables.
-  variable_del('simpletest_httpauth_method');
-  variable_del('simpletest_httpauth_username');
-  variable_del('simpletest_httpauth_password');
-  variable_del('simpletest_clear_results');
-  variable_del('simpletest_verbose');
-
-  // Uninstall schema.
-  drupal_uninstall_schema('simpletest');
-
-  // Remove generated files.
-  $path = file_directory_path() . '/simpletest';
-  $files = file_scan_directory($path, '.*');
-  foreach ($files as $file) {
-    unlink($file->filename);
-  }
-  rmdir($path);
-}
-
-/**
  * Implements hook_requirements().
  *
  * Check that the cURL extension exists for PHP.
@@ -290,6 +166,38 @@ function simpletest_schema() {
 }
 
 /**
+ * Implements hook_install().
+ */
+function simpletest_install() {
+  // Install schema.
+  drupal_install_schema('simpletest');
+
+  // Create the SimpleTest directory.
+  $path = file_directory_path() . '/simpletest';
+  file_check_directory($path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function simpletest_uninstall() {
+  simpletest_clean_environment();
+
+  // Remove settings variables.
+  variable_del('simpletest_httpauth_method');
+  variable_del('simpletest_httpauth_username');
+  variable_del('simpletest_httpauth_password');
+  variable_del('simpletest_clear_results');
+  variable_del('simpletest_verbose');
+
+  // Uninstall schema.
+  drupal_uninstall_schema('simpletest');
+
+  // Remove generated files.
+  simpletest_file_unmanaged_delete_recursive(file_directory_path() . '/simpletest');
+}
+
+/**
  * Upgrade simpletest 5.x-1.x and 6.x-1.x to 6.x-2.1 release.
  *
  * Provides a basic upgrade path for initial switch to 2.x branch. The update
Index: simpletest.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/simpletest/Attic/simpletest.module,v
retrieving revision 1.33.2.4.2.26
diff -u -p -r1.33.2.4.2.26 simpletest.module
--- simpletest.module	13 Nov 2010 01:03:47 -0000	1.33.2.4.2.26
+++ simpletest.module	1 Dec 2010 00:48:43 -0000
@@ -117,7 +117,7 @@ function simpletest_run_tests($test_list
   $test_id = db_last_insert_id('simpletest_test_id', 'test_id');
 
   // Clear out the previous verbose files.
-  simpletest_clean_temporary_directory(file_directory_path() . '/simpletest/verbose');
+  simpletest_file_unmanaged_delete_recursive(file_directory_path() . '/simpletest/verbose');
 
   // Get the info for the first test being run.
   $first_test = array_shift($test_list);
@@ -172,8 +172,8 @@ function _simpletest_batch_operation($te
 
   require_once drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php';
   $classes = simpletest_test_get_all_classes();
-  if (!empty($classes[$test_class]['file'])) {
-    require_once $classes[$test_class]['file'];
+  if (!empty($classes[$test_class]->file)) {
+    require_once $classes[$test_class]->file;
   }
 
   $test = new $test_class($test_id);
@@ -261,10 +261,10 @@ function simpletest_last_test_get($test_
  *   Found any entries in log.
  */
 function simpletest_log_read($test_id, $prefix, $test_class, $during_test = FALSE) {
-  require_once drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php';
   $log = file_directory_path() . ($during_test ? '' : '/simpletest/' . substr($prefix, 10)) . '/error.log';
   $found = FALSE;
   if (file_exists($log)) {
+    require_once drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php';
     foreach (file($log) as $line) {
       if (preg_match('/\[.*?\] (.*?): (.*?) in (.*) on line (\d+)/', $line, $match)) {
         // Parse PHP fatal errors for example: PHP Fatal error: Call to
@@ -320,14 +320,12 @@ function simpletest_test_get_all() {
     }
     else {
       // Select all clases in files ending with .test.
-      $classes = simpletest_test_get_all_classes();
-
+      $classes = array_keys(simpletest_test_get_all_classes());
 
       // Check that each class has a getInfo() method and store the information
       // in an array keyed with the group specified in the test information.
       $groups = array();
       foreach ($classes as $class) {
-        $class = $class['class'];
         // Test classes need to implement getInfo() to be valid.
         if (class_exists($class) && method_exists($class, 'getInfo')) {
           $info = call_user_func(array($class, 'getInfo'));
@@ -359,31 +357,33 @@ function simpletest_test_get_all() {
   return $groups;
 }
 
-function simpletest_test_get_all_classes() {
-  // Must load DrupalWebTestCase before loading any other test classes which
-  // will extend it.
-  require_once 'drupal_web_test_case.php';
-
-  $classes = array();
-  $files = module_rebuild_cache();
-  foreach ($files as $file) {
-    $directory = dirname($file->filename);
-    $test_files = file_scan_directory($directory, '\.test$', array('.', '..', 'CVS'), FALSE, FALSE);
-    $test_files += file_scan_directory($directory . '/tests', '\.test$');
-
-    foreach ($test_files as $test_file) {
-      $pre = get_declared_classes();
-      require_once $test_file->filename;
-      $post = get_declared_classes();
-
-      $classes_new = array_values(array_diff($post, $pre));
-      foreach ($classes_new as $class) {
-        $classes[$class] = array('file' => $test_file->filename, 'class' => $class);
-      }
-    }
-  }
+/**
+ * Generate test file.
+ */
+function simpletest_generate_file($filename, $width, $lines, $type = 'binary-text') {
+  $size = $width * $lines - $lines;
 
-  return $classes;
+  // Generate random text
+  $text = '';
+  for ($i = 0; $i < $size; $i++) {
+    switch ($type) {
+      case 'text':
+        $text .= chr(rand(32, 126));
+        break;
+      case 'binary':
+        $text .= chr(rand(0, 31));
+        break;
+      case 'binary-text':
+      default:
+        $text .= rand(0, 1);
+        break;
+    }
+  }
+  $text = wordwrap($text, $width - 1, "\n", TRUE) . "\n"; // Add \n for symetrical file.
+
+  // Create filename.
+  file_put_contents(file_directory_path() . '/' . $filename . '.txt', $text);
+  return $filename;
 }
 
 /**
@@ -408,10 +408,10 @@ function simpletest_clean_environment() 
  * Removed prefixed tables from the database that are left over from crashed tests.
  */
 function simpletest_clean_database() {
-//  $tables = db_find_tables(Database::getConnection()->prefixTables('{simpletest}') . '%');
-  $tables = simpletest_get_like_tables();
+  $tables = simpletest_db_find_tables(db_prefix_tables('{simpletest}') . '%%');
   $schema = drupal_get_schema_unprocessed('simpletest');
   $count = 0;
+  $ret = array();
   foreach (array_diff_key($tables, $schema) as $table) {
     // Strip the prefix and skip tables without digits following "simpletest",
     // e.g. {simpletest_test_id}.
@@ -430,38 +430,15 @@ function simpletest_clean_database() {
 }
 
 /**
- * Find all tables that are like the specified base table name. (Drupal 6)
- *
- * @param string $base_table Base table name.
- * @param boolean $count Return the table count instead of list of tables.
- * @return mixed Array of matching tables or count of tables.
- */
-function simpletest_get_like_tables($base_table = 'simpletest', $count = FALSE) {
-  global $db_url, $db_prefix;
-  $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
-  $database = substr($url['path'], 1);
-  $result = db_query("SELECT table_name FROM information_schema.tables WHERE (table_schema = '$database' OR table_catalog = '$database') AND table_name LIKE '$db_prefix$base_table%'");
-  $schema = drupal_get_schema_unprocessed('simpletest');
-
-  $tables = array();
-  while ($table = db_result($result)) {
-    if (!isset($schema[$table])) {
-      $tables[] = $table;
-    }
-  }
-  return ($count) ? count($tables) : $tables;
-}
-
-/**
  * Find all leftover temporary directories and remove them.
  */
 function simpletest_clean_temporary_directories() {
   $files = scandir(file_directory_path());
   $count = 0;
   foreach ($files as $file) {
-    $path = file_directory_path() . '/' . $file;
-    if (is_dir($path) && preg_match('/^simpletest\d+/', $file)) {
-      simpletest_clean_temporary_directory($path);
+    $path = file_directory_path() . '/simpletest/' . $file;
+    if (is_dir($path) && is_numeric($file)) {
+      simpletest_file_unmanaged_delete_recursive($path);
       $count++;
     }
   }
@@ -475,33 +452,6 @@ function simpletest_clean_temporary_dire
 }
 
 /**
- * Remove all files from specified directory and then remove directory. (Drupal 6)
- *
- * @param string $path Directory path.
- */
-function simpletest_clean_temporary_directory($path) {
-  // Drupal 6.
-  if (!is_dir($path)) {
-    return;
-  }
-
-  $files = scandir($path);
-  foreach ($files as $file) {
-    if ($file != '.' && $file != '..') {
-      $file_path = "$path/$file";
-      if (is_dir($file_path)) {
-        simpletest_clean_temporary_directory($file_path);
-      }
-      else {
-//        file_unmanaged_delete($file_path);
-        unlink($file_path);
-      }
-    }
-  }
-  rmdir($path);
-}
-
-/**
  * Clear the test result tables.
  *
  * @param $test_id
@@ -547,3 +497,105 @@ function simpletest_form_system_modules_
     }
   }
 }
+
+function simpletest_test_get_all_classes() {
+  // Must load DrupalWebTestCase before loading any other test classes which
+  // will extend it.
+  require_once drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php';
+
+  $classes = array();
+  $files = module_rebuild_cache();
+  foreach ($files as $file) {
+    $directory = dirname($file->filename);
+    $test_files = file_scan_directory($directory, '\.test$', array('.', '..', 'CVS'), FALSE, FALSE);
+    $test_files += file_scan_directory($directory . '/tests', '\.test$');
+
+    foreach ($test_files as $test_file) {
+      $pre = get_declared_classes();
+      require_once $test_file->filename;
+      $post = get_declared_classes();
+
+      $classes_new = array_values(array_diff($post, $pre));
+      foreach ($classes_new as $class) {
+        $classes[$class] = (object) array('file' => $test_file->filename, 'class' => $class);
+      }
+    }
+  }
+
+  return $classes;
+}
+
+/**
+ * Finds all tables that are like the specified base table name.
+ *
+ * @param $table_expression
+ *   An SQL expression, for example "simpletest%%" (without the quotes).
+ *   BEWARE: this is not prefixed, the caller should take care of that.
+ *
+ * @return
+ *   Array, both the keys and the values are the matching tables.
+ */
+function simpletest_db_find_tables($table_expression) {
+  global $db_url;
+
+  // Get the database name.
+  $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
+  $database = substr($url['path'], 1);
+
+  switch ($GLOBALS['db_type']) {
+    default:
+      $query = db_query("SELECT table_name FROM information_schema.tables WHERE (table_schema = '%s' OR table_catalog = '%s') AND table_name LIKE '%s'", array(
+        ':table_schema' => $database,
+        ':table_catelog' => $database,
+        ':table_name' => $table_expression,
+      ));
+      break;
+  }
+
+  $tables = array();
+  if (isset($query)) {
+    while ($table = db_result($query)) {
+      $tables[] = $table;
+    }
+  }
+  return $tables;
+}
+
+/**
+ * Recursively delete all files and directories in the specified filepath.
+ *
+ * If the specified path is a directory then the function will call itself
+ * recursively to process the contents. Once the contents have been removed the
+ * directory will also be removed.
+ *
+ * If the specified path is a file then it will be passed to
+ * file_unmanaged_delete().
+ *
+ * Note that this only deletes visible files with write permission.
+ *
+ * @param $path
+ *   A string containing either an URI or a file or directory path.
+ *
+ * @return
+ *   TRUE for success or if path does not exist, FALSE in the event of an
+ *   error.
+ *
+ * @see file_unmanaged_delete()
+ */
+function simpletest_file_unmanaged_delete_recursive($path) {
+  if (is_dir($path)) {
+    $dir = dir($path);
+    while (($entry = $dir->read()) !== FALSE) {
+      if ($entry == '.' || $entry == '..') {
+        continue;
+      }
+      $entry_path = $path . '/' . $entry;
+      simpletest_file_unmanaged_delete_recursive($entry_path);
+    }
+    $dir->close();
+    return rmdir($path);
+  }
+  elseif (is_file($path)) {
+    return unlink($path);
+  }
+}
Index: simpletest.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/simpletest/Attic/simpletest.pages.inc,v
retrieving revision 1.1.2.4
diff -u -p -r1.1.2.4 simpletest.pages.inc
--- simpletest.pages.inc	13 Nov 2010 01:03:48 -0000	1.1.2.4
+++ simpletest.pages.inc	1 Dec 2010 00:48:43 -0000
@@ -194,8 +194,8 @@ function simpletest_test_form_submit($fo
   $tests_list = array();
   $classes = simpletest_test_get_all_classes();
   foreach ($form_state['values'] as $class_name => $value) {
-    if (isset($classes[$class_name]['file'])) {
-      require_once $classes[$class_name]['file'];
+    if (isset($classes[$class_name]->file)) {
+      require_once $classes[$class_name]->file;
     }
 
     // Since class_exists() will likely trigger an autoload lookup,
@@ -255,7 +255,7 @@ function simpletest_result_form(&$form_s
   $classes = simpletest_test_get_all_classes();
 
   foreach ($results as $group => $assertions) {
-    require_once $classes[$group]['file'];
+    require_once $classes[$group]->file;
 
     // Create group fieldset with summary information.
     $info = call_user_func(array($group, 'getInfo'));
Index: simpletest.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/simpletest/Attic/simpletest.test,v
retrieving revision 1.1.2.21
diff -u -p -r1.1.2.21 simpletest.test
--- simpletest.test	13 Nov 2010 01:03:48 -0000	1.1.2.21
+++ simpletest.test	1 Dec 2010 00:48:43 -0000
@@ -421,6 +421,28 @@ class SimpleTestMailCaptureTestCase exte
 }
 
 /**
+ * Test Folder creation
+ */
+class SimpleTestFolderTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Testing SimpleTest setUp',
+      'description' => "This test will check SimpleTest's treatment of hook_install during setUp.",
+      'group' => 'SimpleTest',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('simpletest'));
+  }
+
+  function testFolderSetup() {
+    $path = file_directory_path() . '/simpletest';
+    $this->assertTrue(file_check_directory($path, FALSE), "Directory $path created.");
+  }
+}
+
+/**
  * Test required modules for tests.
  */
 class SimpleTestMissingDependentModuleUnitTest extends DrupalUnitTestCase {
