Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.37
diff -u -p -r1.37 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	6 Sep 2008 08:36:20 -0000	1.37
+++ modules/simpletest/drupal_web_test_case.php	7 Sep 2008 01:48:12 -0000
@@ -43,54 +43,95 @@ class DrupalWebTestCase {
    *   The message string.
    * @param $group
    *   WHich group this assert belongs to.
-   * @param $custom_caller
+   * @param $caller
    *   By default, the assert comes from a function which names start with
    *   'test'. Instead, you can specify where this assert originates from
-   *   by passing in an associative array as $custom_caller. Key 'file' is
+   *   by passing in an associative array as $caller. Key 'file' is
    *   the name of the source file, 'line' is the line number and 'function'
    *   is the caller function itself.
    */
-  protected function _assert($status, $message = '', $group = 'Other', $custom_caller = NULL) {
+  protected function _assert($status, $message = '', $group = 'Other', $caller = NULL) {
     global $db_prefix;
+
+    // Convert boolean status to string status.
     if (is_bool($status)) {
       $status = $status ? 'pass' : 'fail';
     }
+
+    // Increment summary result counter.
     $this->_results['#' . $status]++;
-    if (!isset($custom_caller)) {
-      $callers = debug_backtrace();
-      array_shift($callers);
-      foreach ($callers as $function) {
-        if (substr($function['function'], 0, 6) != 'assert' && $function['function'] != 'pass' && $function['function'] != 'fail') {
-          break;
-        }
-      }
-    }
-    else {
-      $function = $custom_caller;
+
+    // Get the function information about the call to the assertion method.
+    if (!$caller) {
+      $caller = $this->getAssertionCall();
     }
+
+    // Switch to non-testing database to store results in.
     $current_db_prefix = $db_prefix;
     $db_prefix = $this->db_prefix_original;
-    db_insert('simpletest')->fields(array(
+
+    // Creation assertion array that can be displayed while tests are running.
+    $this->_assertions[] = $assertion = array(
       'test_id' => $this->test_id,
-    'test_class' => get_class($this), 
-    'status' => $status, 
-    'message' => substr($message, 0, 255),  // Some messages are too long for the database.
-    'message_group' => $group, 
-    'caller' => $function['function'], 
-    'line' => $function['line'], 
-    'file' => $function['file'],
-    ))->execute();
-    $this->_assertions[] = array(
+      'test_class' => get_class($this),
       'status' => $status,
       'message' => $message,
-      'group' => $group,
-      'function' => $function['function'],
-      'line' => $function['line'],
-      'file' => $function['file'],
+      'message_group' => $group,
+      'function' => $caller['function'],
+      'line' => $caller['line'],
+      'file' => $caller['file'],
     );
+
+    // Store assertion for display after the test has completed.
+    db_insert('simpletest')->fields($assertion)->execute();
+
+    // Return to testing prefix.
     $db_prefix = $current_db_prefix;
     return $status;
   }
+  
+  /**
+   * Gets the caller context (file name, line, function where the call originated), from a backtrace.
+   */
+  protected function getCallerContext($backtrace) {
+    // The first trace is the call itself.
+    // It gives us the line and the file of the call.
+    $call = reset($backtrace);
+    // The second call give us the function where the call originated.
+    $caller = next($backtrace);
+
+    return array(
+      'line' => $call['line'],
+      'file' => $call['file'],
+      'function' => isset($caller['function']) ? (isset($caller['class']) ? $caller['class'] . $caller['type'] : '') . $caller['function'] . '()' : 'main()',
+    );
+  }
+
+  /**
+   * Cycles through backtrace until the first non-assertion method is found.
+   *
+   * @return
+   *   Array representing the true caller.
+   */
+  protected function getAssertionCall() {
+    $backtrace = debug_backtrace();
+    array_shift($backtrace); // Remove call to getAssertionCall().
+    array_shift($backtrace); // Remove call to _assert().
+
+    // The first element in the stack is the call.
+    // We check if that call occured in one of the assertion functions,
+    // which is the second element in the stack.
+    while (($caller = $backtrace[1]) &&
+         (substr($caller['function'], 0, 6) == 'assert' ||
+             $caller['function'] == 'pass' ||
+             $caller['function'] == 'fail' ||
+             $caller['function'] == 'error')) {
+      // We remove that call.
+      array_shift($backtrace);
+    }
+
+    return $this->getCallerContext($backtrace);
+  }
 
   /**
    * Check to see if a value is not false (not an empty string, 0, NULL, or FALSE).
@@ -263,11 +304,11 @@ class DrupalWebTestCase {
    *   The message to display along with the assertion.
    * @param $group
    *   The type of assertion - examples are "Browser", "PHP".
-   * @param $custom_caller
+   * @param $caller
    *   The caller of the error.
    */
-  protected function error($message = '', $group = 'Other', $custom_caller = NULL) {
-    return $this->_assert('exception', $message, $group, $custom_caller);
+  protected function error($message = '', $group = 'Other', $caller = NULL) {
+    return $this->_assert('exception', $message, $group, $caller);
   }
 
   /**
@@ -308,11 +349,9 @@ class DrupalWebTestCase {
         E_USER_NOTICE => 'User notice',
         E_RECOVERABLE_ERROR => 'Recoverable error',
       );
-      $this->error($message, $error_map[$severity], array(
-        'function' => '',
-        'line' => $line,
-        'file' => $file,
-      ));
+
+      $backtrace = debug_backtrace();
+      $this->error($message, $error_map[$severity], $this->getCallerContext($backtrace));
     }
     return TRUE;
   }
@@ -732,7 +771,6 @@ class DrupalWebTestCase {
 
       // Close the CURL handler.
       $this->curlClose();
-      restore_error_handler();
     }
   }
 
@@ -807,7 +845,7 @@ class DrupalWebTestCase {
       // them.
       @$htmlDom = DOMDocument::loadHTML($this->_content);
       if ($htmlDom) {
-        $this->assertTrue(TRUE, t('Valid HTML found on "@path"', array('@path' => $this->getUrl())), t('Browser'));
+        $this->pass(t('Valid HTML found on "@path"', array('@path' => $this->getUrl())), t('Browser'));
         // It's much easier to work with simplexml than DOM, luckily enough
         // we can just simply import our DOM tree.
         $this->elements = simplexml_import_dom($htmlDom);
@@ -1290,7 +1328,7 @@ class DrupalWebTestCase {
    *   TRUE on pass, FALSE on fail.
    */
   function assertText($text, $message = '', $group = 'Other') {
-    return $this->assertTextHelper($text, $message, $group = 'Other', FALSE);
+    return $this->assertTextHelper($text, $message, $group, FALSE);
   }
 
   /**
Index: modules/simpletest/simpletest.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.install,v
retrieving revision 1.7
diff -u -p -r1.7 simpletest.install
--- modules/simpletest/simpletest.install	16 Aug 2008 20:57:14 -0000	1.7
+++ modules/simpletest/simpletest.install	6 Sep 2008 23:42:22 -0000
@@ -177,25 +177,25 @@ function simpletest_schema() {
         'default' => '',
         'description' => t('The message group this message belongs to. For example: warning, browser, user.'),
       ),
-      'caller' => array(
+      'function' => array(
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
         'default' => '',
-        'description' => t('Name of the caller function or method that created this message.'),
+        'description' => t('Name of the assertion function or method that created this message.'),
       ),
       'line' => array(
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
-        'description' => t('Line number of the caller.'),
+        'description' => t('Line number on which the function is called.'),
       ),
       'file' => array(
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
         'default' => '',
-        'description' => t('Name of the file where the caller is.'),
+        'description' => t('Name of the file where the function is called.'),
       ),
     ),
     'primary key' => array('message_id'),
Index: modules/simpletest/simpletest.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.module,v
retrieving revision 1.11
diff -u -p -r1.11 simpletest.module
--- modules/simpletest/simpletest.module	21 Aug 2008 19:36:38 -0000	1.11
+++ modules/simpletest/simpletest.module	7 Sep 2008 01:01:16 -0000
@@ -106,7 +106,7 @@ function simpletest_test_form() {
             $result->message_group,
             basename($result->file),
             $result->line,
-            $result->caller,
+            $result->function,
             $map[$status],
           ),
           'class' => "simpletest-$status",
