Commit 0d76c733 authored by Dries's avatar Dries

- Patch #274794 by Damien Tournoud et al: make scripts/run-tests.php work again.

parent 2e7dbff6
#!/Applications/MAMP/bin/php5/bin/php
<?php
// $Id$
......@@ -10,11 +9,12 @@
* If no arguments are provided, the help text will print.
*/
$reporter = 'text';
$test_names = array();
$host = 'localhost';
$path = '';
$script = basename(array_shift($_SERVER['argv']));
// XXX: is there a way to get the interpreter path dynamically?
$php = "/usr/bin/php";
if (in_array('--help', $_SERVER['argv']) || empty($_SERVER['argv'])) {
echo <<<EOF
......@@ -37,12 +37,14 @@
need this parameter if Drupal is in a subdirectory on your
localhost and you have not set \$base_url in settings.php.
--reporter Immediatly preceeds the name of the output reporter to use. This
Defaults to "text", while other options include "xml" and "html".
--concurrency [num]
Run tests in parallel, up to [num] tests at a time.
This is not supported under Windows.
--all Run all available tests.
--class Run tests identified by speficic class names.
--class Run tests identified by specific class names, instead of group names.
<test1>[,<test2>[,<test3> ...]]
......@@ -66,8 +68,11 @@
$list = FALSE;
$clean = FALSE;
$all = FALSE;
$concurrency = 1;
$class_names = FALSE;
$test_names = array();
$execute_batch = FALSE;
$test_id = NULL;
while ($param = array_shift($_SERVER['argv'])) {
switch ($param) {
......@@ -89,11 +94,14 @@
case '--clean':
$clean = TRUE;
break;
case '--reporter':
$reporter = array_shift($_SERVER['argv']);
if (!in_array($reporter, array("text", "xml", "html"))) {
$reporter = "text";
}
case '--concurrency':
$concurrency = array_shift($_SERVER['argv']);
break;
case '--test-id':
$test_id = array_shift($_SERVER['argv']);
break;
case '--execute-batch':
$execute_batch = TRUE;
break;
default:
$test_names += explode(',', $param);
......@@ -113,6 +121,68 @@
chdir(realpath(dirname(__FILE__) . '/..'));
require_once './includes/bootstrap.inc';
if ($execute_batch) {
if (is_null($test_id)) {
echo "ERROR: --execute-batch should not be called interactively.\n";
exit;
}
if ($concurrency == 1 || !function_exists('pcntl_fork')) {
// Fallback to mono-threaded execution
if (count($test_names) > 1) {
foreach($test_names as $test_class) {
// Note: we still need to execute each test in its separate Drupal environment
passthru($php . " ./scripts/run-tests.sh --url $url --concurrency 1 --test-id $test_id --execute-batch $test_class");
}
exit;
}
else {
// Execute an individual test
$test_class = array_shift($test_names);
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
simpletest_run_one_test($test_id, $test_class);
exit;
}
}
else {
// Multi-threaded execution
$children = array();
while (!empty($test_names) || !empty($children)) {
// Fork children
// Note: we can safely fork here, because Drupal is not bootstrapped yet
while(count($children) < $concurrency) {
if (empty($test_names)) break;
$child = array();
$child['test_class'] = $test_class = array_shift($test_names);
$child['pid'] = pcntl_fork();
if (!$child['pid']) {
// This is the child process, bootstrap and execute the test
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
simpletest_run_one_test($test_id, $test_class);
exit;
}
else {
// Register our new child
$children[] = $child;
}
}
// Wait for children every 200ms
usleep(200000);
// Check if some children finished
foreach($children as $cid => $child) {
if (pcntl_waitpid($child['pid'], $status, WUNTRACED | WNOHANG)) {
// This particular child exited
unset($children[$cid]);
}
}
}
exit;
}
}
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
if (!module_exists('simpletest')) {
......@@ -126,7 +196,7 @@
// Get the status messages and print them.
$messages = array_pop(drupal_get_messages('status'));
foreach($messages as $text) {
echo("- " . $text . "\n");
echo(" - " . $text . "\n");
}
exit;
}
......@@ -134,92 +204,132 @@
// Run tests as user #1.
$GLOBALS['user'] = user_load(1);
//Load simpletest files
$total_test = &simpletest_get_total_test();
$test_instances = $total_test->getTestInstances();
// Load simpletest files
$all_tests = simpletest_get_all_tests();
$groups = simpletest_categorize_tests($all_tests);
$test_list = array();
if ($list) {
// Display all availabe tests.
echo("Available test groups:\n----------------------\n");
foreach ($test_instances as $group_test) {
echo($group_test->getLabel() . "\n");
echo("\nAvailable test groups\n---------------------\n\n");
foreach ($groups as $group => $tests) {
echo($group . "\n");
foreach ($tests as $class_name => $instance) {
$info = $instance->getInfo();
echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
}
}
exit;
}
if ($all) {
$test_list = NULL;
$test_list = array_keys($all_tests);
}
else {
if ($class_names) {
$test_list = _run_tests_check_classes($test_names, $test_instances);
// Use only valid class names
foreach ($test_names as $class_name) {
if (isset($all_tests[$class_name])) {
$test_list[] = $class_name;
}
}
}
else {
$test_list = _run_tests_find_classes($test_names, $test_instances);
// Resolve group names
foreach ($test_names as $group_name) {
if (isset($groups[$group_name])) {
foreach($groups[$group_name] as $class_name => $instance) {
$test_list[] = $class_name;
}
}
}
}
}
if (empty($test_list) && !$all) {
echo("ERROR: No valid tests were specified.\n");
exit;
}
// If not in 'safe mode', increase the maximum execution time:
if (!ini_get('safe_mode')) {
set_time_limit(360);
set_time_limit(0);
}
echo "\n";
echo "Drupal test run\n";
echo "---------------\n";
echo "\n";
// Tell the user about what tests are to be run.
if (!$all && $reporter == 'text') {
echo("Tests to be run:\n");
foreach ($test_list as $name) {
echo("- " . $name . "\n");
if ($all) {
echo "All tests will run.\n\n";
}
else {
echo "Tests to be run:\n";
foreach ($test_list as $class_name) {
$info = $all_tests[$class_name]->getInfo();
echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n";
}
echo("\n");
echo "\n";
}
simpletest_run_tests(array_keys($test_list), $reporter);
// Utility functions:
/**
* Check that each class name exists as a test, return the list of valid ones.
*/
function _run_tests_check_classes($test_names, $test_instances) {
$test_list = array();
$test_names = array_flip($test_names);
foreach ($test_instances as $group_test) {
$tests = $group_test->getTestInstances();
foreach ($tests as $test) {
$class = get_class($test);
$info = $test->getInfo();
if (isset($test_names[$class])) {
$test_list[$class] = $info['name'];
}
}
echo "Test run started: " . format_date(time(), 'long') . "\n";
echo "\n";
db_query('INSERT INTO {simpletest_test_id} VALUES (default)');
$test_id = db_last_insert_id('simpletest_test_id', 'test_id');
echo "Test summary:\n";
echo "-------------\n";
echo "\n";
// Now execute tests
passthru($php . " ./scripts/run-tests.sh --url $url --test-id $test_id --concurrency $concurrency --execute-batch " . implode(",", $test_list));
echo "\n";
echo "Test run ended: " . format_date(time(), 'long') . "\n";
echo "\n";
// Report results
echo "Detailed test results:\n";
echo "----------------------\n";
echo "\n";
$results_map = array(
'pass' => 'Pass',
'fail' => 'Fail',
'exception' => 'Exception'
);
$results = db_query("SELECT * FROM {simpletest} WHERE test_id = %d ORDER BY test_class, message_id", $test_id);
while($result = db_fetch_object($results)) {
if (isset($results_map[$result->status])) {
$data = array(
'[' . $results_map[$result->status] . ']',
$result->message,
$result->message_group,
basename($result->file),
$result->line,
$result->caller,
);
echo implode("\t", $data) . "\n";
}
return $test_list;
}
// Cleanup our test results
db_query("DELETE FROM {simpletest} WHERE test_id = %d", $test_id);
// Support function:
/**
* Check that each group name exists, return the list of class in valid groups.
* Run a single test (assume a Drupal bootstrapped environnement).
*/
function _run_tests_find_classes($test_names, &$test_instances) {
$test_list = array();
$test_names = array_flip($test_names);
uasort($test_instances, 'simpletest_compare_instances');
foreach ($test_instances as $group_test) {
$group = $group_test->getLabel();
if (isset($test_names[$group])) {
$tests = $group_test->getTestInstances();
foreach ($tests as $test) {
$info = $test->getInfo();
$test_list[get_class($test)] = $info['name'];
}
}
}
return $test_list;
function simpletest_run_one_test($test_id, $test_class) {
simpletest_get_all_tests();
$test = new $test_class($test_id);
$test->run();
$info = $test->getInfo();
echo $info['name'] . ' ' . _simpletest_format_summary_line($test->_results) . "\n";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment