=== modified file 'modules/simpletest/drupal_web_test_case.php'
--- modules/simpletest/drupal_web_test_case.php	2009-05-20 22:16:38 +0000
+++ modules/simpletest/drupal_web_test_case.php	2009-05-21 00:13:56 +0000
@@ -2,10 +2,10 @@
 // $Id: drupal_web_test_case.php,v 1.104 2009/05/20 22:16:38 webchick Exp $
 
 /**
- * Test case for typical Drupal tests.
+ * Base class for Drupal tests. Do not extend this class, use one of the
+ * subclasses in this file.
  */
-class DrupalWebTestCase {
-
+abstract class DrupalTestCase {
   /**
    * The test run ID.
    *
@@ -14,70 +14,6 @@ class DrupalWebTestCase {
   protected $testId;
 
   /**
-   * The URL currently loaded in the internal browser.
-   *
-   * @var string
-   */
-  protected $url;
-
-  /**
-   * The handle of the current cURL connection.
-   *
-   * @var resource
-   */
-  protected $curlHandle;
-
-  /**
-   * The headers of the page currently loaded in the internal browser.
-   *
-   * @var Array
-   */
-  protected $headers;
-
-  /**
-   * The content of the page currently loaded in the internal browser.
-   *
-   * @var string
-   */
-  protected $content;
-
-  /**
-   * The content of the page currently loaded in the internal browser (plain text version).
-   *
-   * @var string
-   */
-  protected $plainTextContent;
-
-  /**
-   * The parsed version of the page.
-   *
-   * @var SimpleXMLElement
-   */
-  protected $elements = NULL;
-
-  /**
-   * The current user logged in using the internal browser.
-   *
-   * @var bool
-   */
-  protected $loggedInUser = FALSE;
-
-  /**
-   * The current cookie file used by cURL.
-   *
-   * We do not reuse the cookies in further runs, so we do not need a file
-   * but we still need cookie handling, so we set the jar to NULL.
-   */
-  protected $cookieFile = NULL;
-
-  /**
-   * Additional cURL options.
-   *
-   * DrupalWebTestCase itself never sets this but always obeys what is set.
-   */
-  protected $additionalCurlOptions = array();
-
-  /**
    * The original database prefix, before it was changed for testing purposes.
    *
    * @var string
@@ -92,11 +28,9 @@ class DrupalWebTestCase {
   protected $originalFileDirectory = NULL;
 
   /**
-   * The original user, before it was changed to a clean uid = 1 for testing purposes.
-   *
-   * @var object
+   * Time limit for the test.
    */
-  protected $originalUser = NULL;
+  protected $timeLimit = 180;
 
   /**
    * Current results of this test case.
@@ -117,17 +51,6 @@ class DrupalWebTestCase {
   protected $assertions = array();
 
   /**
-   * Time limit for the test.
-   */
-  protected $timeLimit = 180;
-
-  /**
-   * HTTP authentication credentials (<username>:<password>).
-   */
-  protected $httpauth_credentials = NULL;
-
-
-  /**
    * Constructor for DrupalWebTestCase.
    *
    * @param $test_id
@@ -475,6 +398,181 @@ class DrupalWebTestCase {
     $this->error($exception->getMessage(), 'Uncaught exception', _drupal_get_last_caller($backtrace));
   }
 
+
+  /**
+   * Generates a random string of ASCII characters of codes 32 to 126.
+   *
+   * The generated string includes alpha-numeric characters and common misc
+   * characters. Use this method when testing general input where the content
+   * is not restricted.
+   *
+   * @param $length
+   *   Length of random string to generate which will be appended to $db_prefix.
+   * @return
+   *   Randomly generated string.
+   */
+  public static function randomString($length = 8) {
+    global $db_prefix;
+
+    $str = '';
+    for ($i = 0; $i < $length; $i++) {
+      $str .= chr(mt_rand(32, 126));
+    }
+    return str_replace('simpletest', 's', $db_prefix) . $str;
+  }
+
+  /**
+   * Generates a random string containing letters and numbers.
+   *
+   * The letters may be upper or lower case. This method is better for
+   * restricted inputs that do not accept certain characters. For example,
+   * when testing input fields that require machine readable values (ie without
+   * spaces and non-standard characters) this method is best.
+   *
+   * @param $length
+   *   Length of random string to generate which will be appended to $db_prefix.
+   * @return
+   *   Randomly generated string.
+   */
+  public static function randomName($length = 8) {
+    global $db_prefix;
+
+    $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
+    $max = count($values) - 1;
+    $str = '';
+    for ($i = 0; $i < $length; $i++) {
+      $str .= chr($values[mt_rand(0, $max)]);
+    }
+    return str_replace('simpletest', 's', $db_prefix) . $str;
+  }
+
+}
+
+/**
+ * Test case for Drupal unit tests.
+ *
+ * These tests can not access the database nor files. Calling any Drupal
+ * function that needs the database will throw exceptions. These include
+ * watchdog(), drupal_function_exists(), module_implements(),
+ * module_invoke_all() etc.
+ */
+class DrupalUnitTestCase extends DrupalTestCase {
+  function setUp() {
+    global $db_prefix, $conf;
+
+    // Store necessary current values before switching to prefixed database.
+    $this->originalPrefix = $db_prefix;
+    $this->originalFileDirectory = file_directory_path();
+
+    // Generate temporary prefixed database to ensure that tests have a clean starting point.
+    $db_prefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
+    $conf['file_directory_path'] = $this->originalFileDirectory . '/' . $db_prefix;
+
+    // If locale is enabled then t() will try to access the database and
+    // subsequently will fail as the database is not accessible.
+    $module_list = module_list();
+    if (isset($module_list['locale'])) {
+      $this->originalModuleList = $module_list;
+      unset($module_list['locale']);
+      module_list(TRUE, FALSE, $module_list);
+    }
+  }
+
+  function tearDown() {
+    global $db_prefix, $conf;
+    if (preg_match('/simpletest\d+/', $db_prefix)) {
+      $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, $this->originalModuleList);
+      }
+    }
+  }
+}
+
+/**
+ * Test case for typical Drupal tests.
+ */
+class DrupalWebTestCase extends DrupalTestCase {
+
+  /**
+   * The URL currently loaded in the internal browser.
+   *
+   * @var string
+   */
+  protected $url;
+
+  /**
+   * The handle of the current cURL connection.
+   *
+   * @var resource
+   */
+  protected $curlHandle;
+
+  /**
+   * The headers of the page currently loaded in the internal browser.
+   *
+   * @var Array
+   */
+  protected $headers;
+
+  /**
+   * The content of the page currently loaded in the internal browser.
+   *
+   * @var string
+   */
+  protected $content;
+
+  /**
+   * The content of the page currently loaded in the internal browser (plain text version).
+   *
+   * @var string
+   */
+  protected $plainTextContent;
+
+  /**
+   * The parsed version of the page.
+   *
+   * @var SimpleXMLElement
+   */
+  protected $elements = NULL;
+
+  /**
+   * The current user logged in using the internal browser.
+   *
+   * @var bool
+   */
+  protected $loggedInUser = FALSE;
+
+  /**
+   * The current cookie file used by cURL.
+   *
+   * We do not reuse the cookies in further runs, so we do not need a file
+   * but we still need cookie handling, so we set the jar to NULL.
+   */
+  protected $cookieFile = NULL;
+
+  /**
+   * Additional cURL options.
+   *
+   * DrupalWebTestCase itself never sets this but always obeys what is set.
+   */
+  protected $additionalCurlOptions = array();
+
+  /**
+   * The original user, before it was changed to a clean uid = 1 for testing purposes.
+   *
+   * @var object
+   */
+  protected $originalUser = NULL;
+
+  /**
+   * HTTP authentication credentials (<username>:<password>).
+   */
+  protected $httpauth_credentials = NULL;
+
   /**
    * Get a node from the database based on its title.
    *
@@ -648,53 +746,6 @@ class DrupalWebTestCase {
   }
 
   /**
-   * Generates a random string of ASCII characters of codes 32 to 126.
-   *
-   * The generated string includes alpha-numeric characters and common misc
-   * characters. Use this method when testing general input where the content
-   * is not restricted.
-   *
-   * @param $length
-   *   Length of random string to generate which will be appended to $db_prefix.
-   * @return
-   *   Randomly generated string.
-   */
-  public static function randomString($length = 8) {
-    global $db_prefix;
-
-    $str = '';
-    for ($i = 0; $i < $length; $i++) {
-      $str .= chr(mt_rand(32, 126));
-    }
-    return str_replace('simpletest', 's', $db_prefix) . $str;
-  }
-
-  /**
-   * Generates a random string containing letters and numbers.
-   *
-   * The letters may be upper or lower case. This method is better for
-   * restricted inputs that do not accept certain characters. For example,
-   * when testing input fields that require machine readable values (ie without
-   * spaces and non-standard characters) this method is best.
-   *
-   * @param $length
-   *   Length of random string to generate which will be appended to $db_prefix.
-   * @return
-   *   Randomly generated string.
-   */
-  public static function randomName($length = 8) {
-    global $db_prefix;
-
-    $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
-    $max = count($values) - 1;
-    $str = '';
-    for ($i = 0; $i < $length; $i++) {
-      $str .= chr($values[mt_rand(0, $max)]);
-    }
-    return str_replace('simpletest', 's', $db_prefix) . $str;
-  }
-
-  /**
    * Create a user with a given set of permissions. The permissions correspond to the
    * names given on the privileges page.
    *

=== modified file 'modules/simpletest/simpletest.module'
--- modules/simpletest/simpletest.module	2009-05-17 10:49:40 +0000
+++ modules/simpletest/simpletest.module	2009-05-20 23:39:13 +0000
@@ -236,7 +236,7 @@ function simpletest_get_all_tests() {
     }
     $classes = array_values(array_diff(get_declared_classes(), $existing_classes));
     foreach ($classes as $key => $class) {
-      if (!method_exists($class, 'getInfo')) {
+      if (!is_subclass_of($class, 'DrupalTestCase') || !method_exists($class, 'getInfo')) {
         unset($classes[$key]);
       }
     }

=== modified file 'modules/simpletest/tests/common.test'
--- modules/simpletest/tests/common.test	2009-05-16 13:26:30 +0000
+++ modules/simpletest/tests/common.test	2009-05-20 23:39:13 +0000
@@ -4,7 +4,7 @@
 /**
  * Tests for the l() function.
  */
-class CommonLUnitTest extends DrupalWebTestCase {
+class CommonLUnitTest extends DrupalUnitTestCase {
 
   public static function getInfo() {
     return array(
@@ -26,7 +26,7 @@ class CommonLUnitTest extends DrupalWebT
   }
 }
 
-class CommonSizeTestCase extends DrupalWebTestCase {
+class CommonSizeTestCase extends DrupalUnitTestCase {
   protected $exact_test_cases;
   protected $rounded_test_cases;
 
@@ -744,7 +744,7 @@ class DrupalErrorHandlerUnitTest extends
 /**
  * Test for valid_url().
  */
-class ValidUrlTestCase extends DrupalWebTestCase {
+class ValidUrlTestCase extends DrupalUnitTestCase {
   public static function getInfo() {
     return array(
       'name' => t('Valid Url'),

=== modified file 'modules/simpletest/tests/form.test'
--- modules/simpletest/tests/form.test	2009-05-06 19:56:21 +0000
+++ modules/simpletest/tests/form.test	2009-05-20 23:39:13 +0000
@@ -77,7 +77,7 @@ class FormsTestCase extends DrupalWebTes
 /**
  * Test form type functions for expected behavior.
  */
-class FormsTestTypeCase extends DrupalWebTestCase {
+class FormsTestTypeCase extends DrupalUnitTestCase {
   public static function getInfo() {
     return array(
       'name' => t('Form type-specific tests'),

=== modified file 'modules/simpletest/tests/graph.test'
--- modules/simpletest/tests/graph.test	2009-04-11 17:58:17 +0000
+++ modules/simpletest/tests/graph.test	2009-05-20 23:39:13 +0000
@@ -9,7 +9,7 @@
 /**
  * Unit tests for the graph handling features.
  */
-class GraphUnitTest extends DrupalWebTestCase {
+class GraphUnitTest extends DrupalUnitTestCase {
   public static function getInfo() {
     return array(
       'name' => t('Graph'),

=== modified file 'modules/simpletest/tests/registry.test'
--- modules/simpletest/tests/registry.test	2009-05-16 16:04:42 +0000
+++ modules/simpletest/tests/registry.test	2009-05-20 23:39:13 +0000
@@ -135,7 +135,7 @@ CONTENTS;
 
 }
 
-class RegistrySkipBodyTestCase extends DrupalWebTestCase {
+class RegistrySkipBodyTestCase extends DrupalUnitTestCase {
   public static function getInfo() {
     return array(
       'name' => t('Skip function body test'),
@@ -148,6 +148,7 @@ class RegistrySkipBodyTestCase extends D
     // This string contains all three kinds of opening braces.
     $function = '<?php function foo () { $x = "{$y}"; $x = "${y}"; }';
     $tokens = token_get_all($function);
+    require_once DRUPAL_ROOT . '/includes/registry.inc';
     _registry_skip_body($tokens);
     // Consume the last }
     each($tokens);

