Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.132
diff -u -p -r1.132 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	30 Jul 2009 10:46:53 -0000	1.132
+++ modules/simpletest/drupal_web_test_case.php	1 Aug 2009 18:57:55 -0000
@@ -30,8 +30,12 @@ abstract class DrupalTestCase {
 
   /**
    * Time limit for the test.
+   *
+   * The value is initialized in the constructor from a settings variable.
+   *
+   * @var integer
    */
-  protected $timeLimit = 180;
+  protected $timeLimit;
 
   /**
    * Current results of this test case.
@@ -69,6 +73,7 @@ abstract class DrupalTestCase {
    */
   public function __construct($test_id = NULL) {
     $this->testId = $test_id;
+    $this->timeLimit = variable_get('simpletest_time_limit', 180);
   }
 
   /**
Index: modules/simpletest/simpletest.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.install,v
retrieving revision 1.25
diff -u -p -r1.25 simpletest.install
--- modules/simpletest/simpletest.install	22 Jul 2009 04:45:35 -0000	1.25
+++ modules/simpletest/simpletest.install	1 Aug 2009 18:57:55 -0000
@@ -1,252 +1,263 @@
-<?php
-// $Id: simpletest.install,v 1.25 2009/07/22 04:45:35 dries Exp $
-
-/**
- * @file
- * Install, update and uninstall functions for the simpletest module.
- */
-
-/**
- * Implement hook_install().
- */
-function simpletest_install() {
-  drupal_install_schema('simpletest');
-  // Check for files 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)-.*/');
-
-    // 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)-.*/'))) {
-      foreach ($files as $file) {
-        file_unmanaged_copy($file->filepath, $path, FILE_EXISTS_REPLACE);
-      }
-      $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;
-}
-
-/**
- * Implement hook_uninstall().
- */
-function simpletest_uninstall() {
-  simpletest_clean_environment();
-
-  // Remove settings variables.
-  variable_del('simpletest_username');
-  variable_del('simpletest_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) {
-    file_unmanaged_delete($file->filepath);
-  }
-  rmdir($path);
-}
-
-/**
- * Check that the cURL extension exists for PHP.
- */
-function simpletest_requirements($phase) {
-  $requirements = array();
-  $t = get_t();
-
-  $has_curl = function_exists('curl_init');
-  $has_hash = function_exists('hash_hmac');
-  $has_domdocument = class_exists('DOMDocument');
-
-  $requirements['curl'] = array(
-    'title' => $t('cURL'),
-    'value' => $has_curl ? $t('Enabled') : $t('Not found'),
-  );
-  if (!$has_curl) {
-    $requirements['curl']['severity'] = REQUIREMENT_ERROR;
-    $requirements['curl']['description'] = $t('Simpletest could not be installed because the PHP <a href="@curl_url">cURL</a> library is not available.', array('@curl_url' => 'http://php.net/manual/en/curl.setup.php'));
-  }
-  $requirements['hash'] = array(
-    'title' => $t('hash'),
-    'value' => $has_hash ? $t('Enabled') : $t('Not found'),
-  );
-  if (!$has_hash) {
-    $requirements['hash']['severity'] = REQUIREMENT_ERROR;
-    $requirements['hash']['description'] = $t('Simpletest could not be installed because the PHP <a href="@hash_url">hash</a> extension is disabled.', array('@hash_url' => 'http://php.net/manual/en/book.hash.php'));
-  }
-
-  $requirements['php_domdocument'] = array(
-    'title' => $t('PHP DOMDocument class'),
-    'value' => $has_domdocument ? $t('Enabled') : $t('Not found'),
-  );
-  if (!$has_domdocument) {
-    $requirements['php_domdocument']['severity'] = REQUIREMENT_ERROR;
-    $requirements['php_domdocument']['description'] =t('SimpleTest requires the DOMDocument class to be available. Please check the configure command at the <a href="@link-phpinfo">PHP info page</a>.', array('@link-phpinfo' => url('admin/reports/status/php')));
-  }
-
-  return $requirements;
-}
-
-function simpletest_schema() {
-  $schema['simpletest'] = array(
-    'description' => 'Stores simpletest messages',
-    'fields' => array(
-      'message_id'  => array(
-        'type' => 'serial',
-        'not null' => TRUE,
-        'description' => 'Primary Key: Unique simpletest message ID.',
-      ),
-      'test_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Test ID, messages belonging to the same ID are reported together',
-      ),
-      'test_class' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'The name of the class that created this message.',
-      ),
-      'status' => array(
-        'type' => 'varchar',
-        'length' => 9,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Message status. Core understands pass, fail, exception.',
-      ),
-      'message' => array(
-        'type' => 'text',
-        'not null' => TRUE,
-        'description' => 'The message itself.',
-      ),
-      'message_group' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'The message group this message belongs to. For example: warning, browser, user.',
-      ),
-      'function' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Name of the assertion function or method that created this message.',
-      ),
-      'line' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Line number on which the function is called.',
-      ),
-      'file' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Name of the file where the function is called.',
-      ),
-    ),
-    'primary key' => array('message_id'),
-    'indexes' => array(
-      'reporter' => array('test_class', 'message_id'),
-    ),
-  );
-  $schema['simpletest_test_id'] = array(
-    'description' => 'Stores simpletest test IDs, used to auto-incrament the test ID so that a fresh test ID is used.',
-    'fields' => array(
-      'test_id'  => array(
-        'type' => 'serial',
-        'not null' => TRUE,
-        'description' => 'Primary Key: Unique simpletest ID used to group test results together. Each time a set of tests
-                            are run a new test ID is used.',
-      ),
-      'last_prefix' => array(
-        'type' => 'varchar',
-        'length' => 60,
-        'not null' => FALSE,
-        'default' => '',
-        'description' => 'The last database prefix used during testing.',
-      ),
-    ),
-    'primary key' => array('test_id'),
-  );
-  return $schema;
-}
+<?php
+// $Id: simpletest.install,v 1.25 2009/07/22 04:45:35 dries Exp $
+
+/**
+ * @file
+ * Install, update and uninstall functions for the simpletest module.
+ */
+
+/**
+ * Implement hook_install().
+ */
+function simpletest_install() {
+  drupal_install_schema('simpletest');
+  // Check for files 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)-.*/');
+
+    // 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)-.*/'))) {
+      foreach ($files as $file) {
+        file_unmanaged_copy($file->filepath, $path, FILE_EXISTS_REPLACE);
+      }
+      $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;
+}
+
+/**
+ * Implement hook_uninstall().
+ */
+function simpletest_uninstall() {
+  simpletest_clean_environment();
+
+  // Remove settings variables.
+  variable_del('simpletest_username');
+  variable_del('simpletest_password');
+  variable_del('simpletest_clear_results');
+  variable_del('simpletest_verbose');
+  variable_del('simpletest_time_limit');
+
+  // Uninstall schema.
+  drupal_uninstall_schema('simpletest');
+
+  // Remove generated files.
+  $path = file_directory_path() . '/simpletest';
+  $files = file_scan_directory($path, '/.*/');
+  foreach ($files as $file) {
+    file_unmanaged_delete($file->filepath);
+  }
+  rmdir($path);
+}
+
+/**
+ * Check that the cURL extension exists for PHP.
+ */
+function simpletest_requirements($phase) {
+  $requirements = array();
+  $t = get_t();
+
+  $has_curl = function_exists('curl_init');
+  $has_hash = function_exists('hash_hmac');
+  $has_domdocument = class_exists('DOMDocument');
+  $can_set_time_limit = !ini_get('safe_mode') && strpos(ini_get('disable_functions'), 'set_time_limit') === FALSE;
+
+  $requirements['curl'] = array(
+    'title' => $t('cURL'),
+    'value' => $has_curl ? $t('Enabled') : $t('Not found'),
+  );
+  if (!$has_curl) {
+    $requirements['curl']['severity'] = REQUIREMENT_ERROR;
+    $requirements['curl']['description'] = $t('Simpletest could not be installed because the PHP <a href="@curl_url">cURL</a> library is not available.', array('@curl_url' => 'http://php.net/manual/en/curl.setup.php'));
+  }
+  $requirements['hash'] = array(
+    'title' => $t('hash'),
+    'value' => $has_hash ? $t('Enabled') : $t('Not found'),
+  );
+  if (!$has_hash) {
+    $requirements['hash']['severity'] = REQUIREMENT_ERROR;
+    $requirements['hash']['description'] = $t('Simpletest could not be installed because the PHP <a href="@hash_url">hash</a> extension is disabled.', array('@hash_url' => 'http://php.net/manual/en/book.hash.php'));
+  }
+
+  $requirements['php_domdocument'] = array(
+    'title' => $t('PHP DOMDocument class'),
+    'value' => $has_domdocument ? $t('Enabled') : $t('Not found'),
+  );
+  if (!$has_domdocument) {
+    $requirements['php_domdocument']['severity'] = REQUIREMENT_ERROR;
+    $requirements['php_domdocument']['description'] = $t('SimpleTest requires the DOMDocument class to be available. Please check the configure command at the <a href="@link-phpinfo">PHP info page</a>.', array('@link-phpinfo' => url('admin/reports/status/php')));
+  }
+
+  $requirements['php_set_time_limit'] = array(
+    'title' => $t('Can call %f', array('%f' => 'set_time_limit()')),
+    'value' => $can_set_time_limit ? $t('Yes') : $t('No'),
+  );
+  if (!$can_set_time_limit) {
+    $requirements['php_set_time_limit']['severity'] = REQUIREMENT_ERROR;
+    $requirements['php_set_time_limit']['description'] = $t('Simpletest cannot run in safe_mode or with function set_time_limit() disable. Correct this in php.ini');
+  }
+
+  return $requirements;
+}
+
+function simpletest_schema() {
+  $schema['simpletest'] = array(
+    'description' => 'Stores simpletest messages',
+    'fields' => array(
+      'message_id'  => array(
+        'type' => 'serial',
+        'not null' => TRUE,
+        'description' => 'Primary Key: Unique simpletest message ID.',
+      ),
+      'test_id' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Test ID, messages belonging to the same ID are reported together',
+      ),
+      'test_class' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'The name of the class that created this message.',
+      ),
+      'status' => array(
+        'type' => 'varchar',
+        'length' => 9,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Message status. Core understands pass, fail, exception.',
+      ),
+      'message' => array(
+        'type' => 'text',
+        'not null' => TRUE,
+        'description' => 'The message itself.',
+      ),
+      'message_group' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'The message group this message belongs to. For example: warning, browser, user.',
+      ),
+      'function' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Name of the assertion function or method that created this message.',
+      ),
+      'line' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Line number on which the function is called.',
+      ),
+      'file' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Name of the file where the function is called.',
+      ),
+    ),
+    'primary key' => array('message_id'),
+    'indexes' => array(
+      'reporter' => array('test_class', 'message_id'),
+    ),
+  );
+  $schema['simpletest_test_id'] = array(
+    'description' => 'Stores simpletest test IDs, used to auto-incrament the test ID so that a fresh test ID is used.',
+    'fields' => array(
+      'test_id'  => array(
+        'type' => 'serial',
+        'not null' => TRUE,
+        'description' => 'Primary Key: Unique simpletest ID used to group test results together. Each time a set of tests
+                            are run a new test ID is used.',
+      ),
+      'last_prefix' => array(
+        'type' => 'varchar',
+        'length' => 60,
+        'not null' => FALSE,
+        'default' => '',
+        'description' => 'The last database prefix used during testing.',
+      ),
+    ),
+    'primary key' => array('test_id'),
+  );
+  return $schema;
+}
Index: modules/simpletest/simpletest.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.pages.inc,v
retrieving revision 1.10
diff -u -p -r1.10 simpletest.pages.inc
--- modules/simpletest/simpletest.pages.inc	29 Jul 2009 06:39:34 -0000	1.10
+++ modules/simpletest/simpletest.pages.inc	1 Aug 2009 18:57:55 -0000
@@ -430,6 +430,13 @@ function simpletest_settings_form(&$form
     '#description' => t('The verbose data will be printed along with the standard assertions. Useful for debugging.'),
     '#default_value' => variable_get('simpletest_verbose', FALSE),
   );
+  $form['general']['simpletest_time_limit'] = array(
+    '#type' => 'textfield',
+    '#title' => t('PHP script execution time limit'),
+    '#description' => t('Simpletest calls set_time_limit() with this value to increase the PHP script execution time limit to avoid possible timeout error, adjust this value upward if timeout error occur during test run. Set to zero for no limit.'),
+    '#default_value' => variable_get('simpletest_time_limit', 180),
+    '#size' => 5,
+  );
 
   $form['httpauth'] = array(
     '#type' => 'fieldset',
@@ -449,3 +456,11 @@ function simpletest_settings_form(&$form
 
   return system_settings_form($form);
 }
+
+
+function simpletest_settings_form_validate($form, $form_state) {
+  $value = $form_state['values']['simpletest_time_limit'];
+  if ($value !== (string)(int)$value || $value < 0) {
+    form_error($form['general']['simpletest_time_limit'], t('Must be an integer >= 0.'));
+  }
+}
\ No newline at end of file
