Fix simpletest reporting.

From: Damien Tournoud <damien@tournoud.net>


---

 includes/common.inc                         |    6 ++
 modules/simpletest/drupal_web_test_case.php |   13 +++--
 modules/simpletest/tests/common.test        |   67 +++++++++++++++++++++++++++
 modules/simpletest/tests/system_test.module |   15 ++++++
 4 files changed, 95 insertions(+), 6 deletions(-)


diff --git includes/common.inc includes/common.inc
index 1f1da6f..30789d9 100644
--- includes/common.inc
+++ includes/common.inc
@@ -723,7 +723,11 @@ function _drupal_log_error($error, $fatal = FALSE) {
     $assertion = array(
       $error['%message'],
       $error['%type'],
-      $error['%function'],
+      array(
+        'function' => $error['%function'],
+        'file' => $error['%file'],
+        'line' => $error['%line'],
+      ),
     );
     header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion)));
     $number++;
diff --git modules/simpletest/drupal_web_test_case.php modules/simpletest/drupal_web_test_case.php
index 2c60f05..a41c032 100644
--- modules/simpletest/drupal_web_test_case.php
+++ modules/simpletest/drupal_web_test_case.php
@@ -50,7 +50,7 @@ class DrupalWebTestCase {
    *   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', $caller = NULL) {
+  protected function _assert($status, $message = '', $group = 'Other', Array $caller = NULL) {
     global $db_prefix;
 
     // Convert boolean status to string status.
@@ -283,10 +283,13 @@ class DrupalWebTestCase {
    *   The message to display along with the assertion.
    * @param $group
    *   The type of assertion - examples are "Browser", "PHP".
-   * @param $caller
-   *   The caller of the error.
+   *   By default, the error comes from a function which names start with
+   *   'test'. Instead, you can specify where this error originates from 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 error($message = '', $group = 'Other', $caller = NULL) {
+  protected function error($message = '', $group = 'Other', Array $caller = NULL) {
     return $this->_assert('exception', $message, $group, $caller);
   }
 
@@ -604,7 +607,7 @@ class DrupalWebTestCase {
    * @return
    *   TRUE or FALSE depending on whether the permissions are valid.
    */
-  private function checkPermissions(array $permissions, $reset = FALSE) {
+  private function checkPermissions(Array $permissions, $reset = FALSE) {
     static $available;
 
     if (!isset($available) || $reset) {
diff --git modules/simpletest/tests/common.test modules/simpletest/tests/common.test
index 269c81e..4fa468f 100644
--- modules/simpletest/tests/common.test
+++ modules/simpletest/tests/common.test
@@ -539,3 +539,70 @@ class DrupalErrorHandlerUnitTest extends DrupalWebTestCase {
     $this->assertText($message, t("Found '%message' in error page.", array('%message' => $message)));
   }
 }
+
+/**
+ * Tests Simpletest error and exception collecter.
+ */
+class DrupalErrorCollectionUnitTest extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('SimpleTest error collecter'),
+      'description' => t("Performs tests on the Simpletest error and exception collecter."),
+      'group' => t('SimpleTest'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('system_test');
+  }
+
+  /**
+   * Test that simpletest collect errors from the tested site.
+   */
+  function testErrorCollect() {
+    $this->collected_errors = array();
+    $this->drupalGet('system-test/trigger-internal-errors');
+
+    $this->assertEqual(count($this->collected_errors), 2, t('Two errors were collected'));
+
+    if (count($this->collected_errors) == 2) {
+      $this->assertError($this->collected_errors[0], 'Warning', 'system_test_trigger_internal_errors()', 'system_test.module', 'Division by zero');
+      $this->assertError($this->collected_errors[1], 'PDOException', 'system_test_trigger_internal_errors()', 'system_test.module');
+    }
+    else {
+      // Give back the errors to the log report.
+      if (count($this->collected_errors) != 2) {
+        foreach ($this->collected_errors as $error) {
+          parent::error($error['message'], $error['group'], $error['caller']);
+        }
+      }
+    }
+  }
+
+  /**
+   * Collected errors.
+   */
+  protected $collected_errors;
+
+  /**
+   * Overrides DrupalWebTestCase->error().
+   */
+  protected function error($message = '', $group = 'Other', Array $caller = NULL) {
+    // Collect the error...
+    $this->collected_errors[] = array(
+      'message' => $message,
+      'group' => $group,
+      'caller' => $caller
+    );
+    // And ignore it.
+  }
+
+  function assertError($error, $group, $function, $file, $message = NULL) {
+    $this->assertEqual($error['group'], $group, t("Found '%group'", array('%group' => $group)));
+    $this->assertEqual($error['caller']['function'], $function, t("Found '%function'", array('%function' => $function)));
+    $this->assertEqual(basename($error['caller']['file']), $file, t("Found '%file'", array('%file' => $file)));
+    if (isset($message)) {
+      $this->assertEqual($error['message'], $message, t("Found '%message'", array('%message' => $message)));
+    }
+  }
+}
\ No newline at end of file
diff --git modules/simpletest/tests/system_test.module modules/simpletest/tests/system_test.module
index b155cbc..d076fbe 100644
--- modules/simpletest/tests/system_test.module
+++ modules/simpletest/tests/system_test.module
@@ -69,6 +69,13 @@ function system_test_menu() {
     'type' => MENU_CALLBACK,
   );
 
+  $items['system-test/trigger-internal-errors'] = array(
+    'title' => 'Trigger internal errors to be collected by Simpletest',
+    'page callback' => 'system_test_trigger_internal_errors',
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+
   return $items;
 }
 
@@ -171,3 +178,11 @@ function system_test_trigger_pdo_exception() {
   define('SIMPLETEST_DONT_COLLECT_ERRORS', TRUE);
   db_query("SELECT * FROM bananas_are_awesome");
 }
+
+/**
+ * Menu callback; generate a warning and an exception to test that errors are collected in the testing site.
+ */
+function system_test_trigger_internal_errors() {
+  $awesomely_big = 1/0;
+  db_query("SELECT * FROM bananas_are_awesome");
+}
