#329177: implements a simpletest_id() function to cut some crappy regexp.

From: Damien Tournoud <damien@tournoud.net>


---

 includes/bootstrap.inc                      |   26 +++++++++++
 includes/common.inc                         |    4 +-
 includes/database/database.inc              |    5 --
 install.php                                 |   10 ++--
 modules/simpletest/drupal_web_test_case.php |   62 ++++++++++++++-------------
 modules/simpletest/simpletest.module        |    2 -
 modules/simpletest/simpletest.test          |   14 +++---
 7 files changed, 74 insertions(+), 49 deletions(-)


diff --git includes/bootstrap.inc includes/bootstrap.inc
index 36ad36d..50a236c 100644
--- includes/bootstrap.inc
+++ includes/bootstrap.inc
@@ -504,6 +504,15 @@ function conf_init() {
     ini_set('session.cookie_domain', $cookie_domain);
   }
   session_name('SESS' . md5($session_name));
+
+
+  // Use the simpletest database prefix passed by the user agent header.
+  if (preg_match("/^simpletest\d+$/", $_SERVER['HTTP_USER_AGENT'])) {
+    // Set the simpletest_id for other part of Drupal to use.
+    simpletest_id($_SERVER['HTTP_USER_AGENT']);
+    // Extend the database prefix.
+    $db_prefix .= $_SERVER['HTTP_USER_AGENT'];
+  }
 }
 
 /**
@@ -1329,6 +1338,23 @@ function ip_address($reset = FALSE) {
 }
 
 /**
+ * If running as a testing instance, returns the id of the currently running simpletest.
+ *
+ * @param $new_simpletest_id
+ *   Internal use: set the simpletest id.
+ * @return
+ *   The id of the currently running simpletest or NULL if running
+ *   outside the simpletest environment.
+ */
+function simpletest_id($new_simpletest_id = FALSE) {
+  static $simpletest_id = FALSE;
+  if ($new_simpletest_id !== FALSE) {
+    $simpletest_id = $new_simpletest_id;
+  }
+  return $simpletest_id;
+}
+
+/**
  * @ingroup schemaapi
  * @{
  */
diff --git includes/common.inc includes/common.inc
index cd4966a..e0b8add 100644
--- includes/common.inc
+++ includes/common.inc
@@ -526,8 +526,8 @@ function drupal_http_request($url, $headers = array(), $method = 'GET', $data =
   // user-agent is used to ensure that multiple testing sessions running at the
   // same time won't interfere with each other as they would if the database
   // prefix were stored statically in a file or database variable.
-  if (preg_match("/simpletest\d+/", $db_prefix, $matches)) {
-    $headers['User-Agent'] = $matches[0];
+  if ($simpletest_id = simpletest_id()) {
+    $headers['User-Agent'] = $simpletest_id;
   }
 
   foreach ($headers as $header => $value) {
diff --git includes/database/database.inc includes/database/database.inc
index 23f14b9..835e9cb 100644
--- includes/database/database.inc
+++ includes/database/database.inc
@@ -1064,11 +1064,6 @@ abstract class Database {
         self::$connections[$key][$target]->setLogger(self::$logs[$key]);
       }
 
-      // We need to pass around the simpletest database prefix in the request
-      // and we put that in the user_agent header.
-      if (preg_match("/^simpletest\d+$/", $_SERVER['HTTP_USER_AGENT'])) {
-        $db_prefix .= $_SERVER['HTTP_USER_AGENT'];
-      }
     }
     catch (Exception $e) {
       // It is extremely rare that an exception will be generated here other
diff --git install.php install.php
index 92078e2..71fd6a5 100644
--- install.php
+++ install.php
@@ -25,17 +25,17 @@ define('MAINTENANCE_MODE', 'install');
  *   The installation phase we should proceed to.
  */
 function install_main() {
-  // The user agent header is used to pass a database prefix in the request when
+  require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+
+  // The simpletest id is passed by the way of the user agent header when
   // running tests.  However, for security reasons, it is imperative that no
   // installation be permitted using such a prefix.
-  if (preg_match("/^simpletest\d+$/", $_SERVER['HTTP_USER_AGENT'])) {
+  if (simpletest_id()) {
     header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
     exit;
   }
 
-  require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
-  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
-
   // This must go after drupal_bootstrap(), which unsets globals!
   global $profile, $install_locale, $conf;
 
diff --git modules/simpletest/drupal_web_test_case.php modules/simpletest/drupal_web_test_case.php
index 41ec085..e5866bc 100644
--- modules/simpletest/drupal_web_test_case.php
+++ modules/simpletest/drupal_web_test_case.php
@@ -19,6 +19,8 @@ class DrupalWebTestCase {
   protected $curl_options = array();
   protected $db_prefix_original;
   protected $original_file_directory;
+  protected $simpletest_id;
+  protected $simpletest_db_prefix;
 
   var $_results = array('#pass' => 0, '#fail' => 0, '#exception' => 0);
   var $_assertions = array();
@@ -705,7 +707,11 @@ class DrupalWebTestCase {
     $clean_url_original = variable_get('clean_url', 0);
 
     // Generate temporary prefixed database to ensure that tests have a clean starting point.
-    $db_prefix = Database::getActiveConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
+    $this->simpletest_id = 'simpletest' . mt_rand(1000, 1000000);
+    $db_prefix = $this->simpletest_db_prefix = Database::getActiveConnection()->prefixTables('{' . $this->simpletest_id . '}');
+
+    // Set the simpletest id for use in other systems.
+    simpletest_id($this->simpletest_id);
 
     include_once DRUPAL_ROOT . '/includes/install.inc';
     drupal_install_system();
@@ -768,35 +774,35 @@ class DrupalWebTestCase {
    */
   function tearDown() {
     global $db_prefix;
-    if (preg_match('/simpletest\d+/', $db_prefix)) {
-      // Delete temporary files directory and reset files directory path.
-      simpletest_clean_temporary_directory(file_directory_path());
-      variable_set('file_directory_path', $this->original_file_directory);
-
-      // 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->db_prefix_original;
+    // Reset $db_prefix in case it changed during the test.
+    $db_prefix = $this->simpletest_db_prefix;
+
+    // Delete temporary files directory and reset files directory path.
+    simpletest_clean_temporary_directory(file_directory_path());
+    variable_set('file_directory_path', $this->original_file_directory);
 
-      // Ensure that the internal logged in variable is reset.
-      $this->_logged_in = FALSE;
+    // 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);
+    }
 
-      // 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);
+    // Return the database prefix to the original.
+    $db_prefix = $this->db_prefix_original;
 
-      // Rebuild caches.
-      $this->refreshVariables();
+    // Ensure that the internal logged in variable is reset.
+    $this->_logged_in = FALSE;
 
-      // Close the CURL handler.
-      $this->curlClose();
-    }
+    // Reload module list to ensure that test module hooks aren't called after tests.
+    module_list(TRUE);
+
+    // Rebuild caches.
+    $this->refreshVariables();
+
+    // Close the CURL handler.
+    $this->curlClose();
   }
 
   /**
@@ -807,7 +813,7 @@ class DrupalWebTestCase {
    * see the description of $curl_options among the properties.
    */
   protected function curlInitialize() {
-    global $base_url, $db_prefix;
+    global $base_url;
     if (!isset($this->ch)) {
       $this->ch = curl_init();
       $curl_options = $this->curl_options + array(
@@ -818,10 +824,8 @@ class DrupalWebTestCase {
         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 => $this->simpletest_id,
       );
-      if (preg_match('/simpletest\d+/', $db_prefix, $matches)) {
-        $curl_options[CURLOPT_USERAGENT] = $matches[0];
-      }
       if (!isset($curl_options[CURLOPT_USERPWD]) && ($auth = variable_get('simpletest_httpauth_username', ''))) {
         if ($pass = variable_get('simpletest_httpauth_pass', '')) {
           $auth .= ':' . $pass;
diff --git modules/simpletest/simpletest.module modules/simpletest/simpletest.module
index fa98249..4a0c8a8 100644
--- modules/simpletest/simpletest.module
+++ modules/simpletest/simpletest.module
@@ -532,7 +532,7 @@ function simpletest_clean_database() {
   $ret = array();
   foreach (array_diff_key($tables, $schema) as $table) {
     // Strip $db_prefix and skip tables without digits following "simpletest",
-    // e.g. {simpletest_tets_id}.
+    // e.g. {simpletest_test_id}.
     if (preg_match('/simpletest\d+.*/', $table, $matches)) {
       db_drop_table($ret, $matches[0]);
     }
diff --git modules/simpletest/simpletest.test modules/simpletest/simpletest.test
index 9da0f0e..78f6ebe 100644
--- modules/simpletest/simpletest.test
+++ modules/simpletest/simpletest.test
@@ -31,7 +31,7 @@ class SimpleTestTestCase extends DrupalWebTestCase {
    * Implementation of setUp().
    */
   function setUp() {
-    if (!$this->inCURL()) {
+    if (!$this->inTestingSite()) {
       parent::setUp('simpletest');
 
       // Create and login user
@@ -48,7 +48,7 @@ class SimpleTestTestCase extends DrupalWebTestCase {
    */
   function testInternalBrowser() {
     global $conf;
-    if (!$this->inCURL()) {
+    if (!$this->inTestingSite()) {
       $this->drupalGet('node');
       $this->assertTitle(variable_get('site_name', 'Drupal'), t('Site title matches.'));
       // Make sure that we are locked out of the installer when prefixing
@@ -70,7 +70,7 @@ class SimpleTestTestCase extends DrupalWebTestCase {
     $this->valid_permission = 'access content';
     $this->invalid_permission = 'invalid permission';
 
-    if ($this->inCURL()) {
+    if ($this->inTestingSite()) {
       // Only run following code if this test is running itself through a CURL request.
       $this->stubTest();
     }
@@ -249,11 +249,11 @@ class SimpleTestTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Check if the test is being run from inside a CURL request.
-   *
-   * @return The test is being run from inside a CURL request.
+   * Check if the test is being run from the tested site.
    */
-  function inCURL() {
+  function inTestingSite() {
+    // We cannot use simpletest_id() directly here, because it makes no difference
+    // between the tested site and the testing site.
     return preg_match("/^simpletest\d+/", $_SERVER['HTTP_USER_AGENT']);
   }
 }
