jsDriver.pl 37.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#!/usr/bin/perl
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is JavaScript Core Tests.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation.  Portions created by Netscape are
# Copyright (C) 1997-1999 Netscape Communications Corporation. All
# Rights Reserved.
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL.  If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#
# Contributers:
#  Robert Ginda <rginda@netscape.com>
#
# Second cut at runtests.pl script originally by
# Christine Begle (cbegle@netscape.com)
# Branched 11/01/99
#

use strict;
use Getopt::Mixed "nextOption";

my $os_type = &get_os_type;
my $unixish = (($os_type ne "WIN") && ($os_type ne "MAC"));
my $path_sep = ($os_type eq "MAC") ? ":" : "/";
my $win_sep  = ($os_type eq "WIN")? &get_win_sep : "";
my $redirect_command = ($os_type ne "MAC") ? " 2>&1" : "";

# command line option defaults
my $opt_suite_path;
my $opt_trace = 0;
my $opt_classpath = "";
my $opt_rhino_opt = 0;
my $opt_rhino_ms = 0;
my @opt_engine_list;
my $opt_engine_type = "";
my $opt_engine_params = "";
my $opt_user_output_file = 0;
my $opt_output_file = "";
my @opt_test_list_files;
my @opt_neg_list_files;
my $opt_shell_path = "";
my $opt_java_path = "";
my $opt_bug_url = "http://bugzilla.mozilla.org/show_bug.cgi?id=";
my $opt_console_failures = 0;
darin's avatar
darin committed
65
my $opt_lxr_url = "./"; # "http://lxr.mozilla.org/mozilla/source/js/tests/";
66 67 68 69
my $opt_exit_munge = ($os_type ne "MAC") ? 1 : 0;

# command line option definition
my $options = "b=s bugurl>b c=s classpath>c e=s engine>e f=s file>f " .
kdecker's avatar
 
kdecker committed
70 71 72
"h help>h i j=s javapath>j k confail>k l=s list>l L=s neglist>L " .
"o=s opt>o p=s testpath>p s=s shellpath>s t trace>t u=s lxrurl>u " .
"x noexitmunge>x";
73 74 75 76

if ($os_type eq "MAC") {
    $opt_suite_path = `directory`;
    $opt_suite_path =~ s/[\n\r]//g;
kdecker's avatar
 
kdecker committed
77
        $opt_suite_path .= ":";
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
} else {
    $opt_suite_path = "./";
}

&parse_args;

my $user_exit = 0;
my ($engine_command, $html, $failures_reported, $tests_completed,
    $exec_time_string); 
my @failed_tests;
my @test_list = &get_test_list;

if ($#test_list == -1) {
    die ("Nothing to test.\n");
}

if ($unixish) {
kdecker's avatar
 
kdecker committed
95 96 97 98 99
# on unix, ^C pauses the tests, and gives the user a chance to quit but 
# report on what has been done, to just quit, or to continue (the
# interrupted test will still be skipped.)
# windows doesn't handle the int handler they way we want it to,
# so don't even pretend to let the user continue.
100 101 102 103 104 105 106 107 108
    $SIG{INT} = 'int_handler';
}

&main;

#End.

sub main {
    my $start_time;
kdecker's avatar
 
kdecker committed
109
    
110 111
    while ($opt_engine_type = pop (@opt_engine_list)) {
        dd ("Testing engine '$opt_engine_type'");
kdecker's avatar
 
kdecker committed
112
        
113 114 115 116 117 118
        $engine_command = &get_engine_command;
        $html = "";
        @failed_tests = ();
        $failures_reported = 0;
        $tests_completed = 0;
        $start_time = time;
kdecker's avatar
 
kdecker committed
119 120
        
        
121
        &execute_tests (@test_list);
kdecker's avatar
 
kdecker committed
122
        
123 124 125 126 127 128
        my $exec_time = (time - $start_time);
        my $exec_hours = int($exec_time / 60 / 60);
        $exec_time -= $exec_hours * 60 * 60;
        my $exec_mins = int($exec_time / 60);
        $exec_time -= $exec_mins * 60;
        my $exec_secs = ($exec_time % 60);
kdecker's avatar
 
kdecker committed
129
        
130 131
        if ($exec_hours > 0) {
            $exec_time_string = "$exec_hours hours, $exec_mins minutes, " .
kdecker's avatar
 
kdecker committed
132
            "$exec_secs seconds";
133 134 135 136 137
        } elsif ($exec_mins > 0) {
            $exec_time_string = "$exec_mins minutes, $exec_secs seconds";
        } else {
            $exec_time_string = "$exec_secs seconds";
        }
kdecker's avatar
 
kdecker committed
138
        
139 140 141
        if (!$opt_user_output_file) {
            $opt_output_file = &get_tempfile_name;
        }
kdecker's avatar
 
kdecker committed
142
        
143
        &write_results;
kdecker's avatar
 
kdecker committed
144
        
145 146 147 148 149 150 151 152
    }
}

sub execute_tests {
    my (@test_list) = @_;
    my ($test, $shell_command, $line, @output, $path);
    my $file_param = " -f ";
    my ($last_suite, $last_test_dir);
kdecker's avatar
 
kdecker committed
153 154 155 156
    
# Don't run any shell.js files as tests; they are only utility files
    @test_list = grep (!/shell\.js$/, @test_list);
    
157 158 159
    &status ("Executing " . ($#test_list + 1) . " test(s).");
    foreach $test (@test_list) {
        my ($suite, $test_dir, $test_file) = split($path_sep, $test);
kdecker's avatar
 
kdecker committed
160
# *-n.js is a negative test, expect exit code 3 (runtime error)
161 162 163 164 165
        my $expected_exit = ($test =~ /\-n\.js$/) ? 3 : 0;
        my ($got_exit, $exit_signal);
        my $failure_lines;
        my $bug_number;
        my $status_lines;
kdecker's avatar
 
kdecker committed
166 167
        
# user selected [Q]uit from ^C handler.
168 169 170
        if ($user_exit) {
            return;
        }
kdecker's avatar
 
kdecker committed
171 172 173 174
        
# Append the shell.js files to the shell_command if they're there.
# (only check for their existance if the suite or test_dir has changed
# since the last time we looked.)
175 176
        if ($last_suite ne $suite || $last_test_dir ne $test_dir) {
            $shell_command = &xp_path($engine_command);
kdecker's avatar
 
kdecker committed
177
            
178 179 180 181
            $path = &xp_path($opt_suite_path . $suite . "/shell.js");
            if (-f $path) {
                $shell_command .= $file_param . $path;
            }
kdecker's avatar
 
kdecker committed
182
            
183 184 185 186 187
            $path = &xp_path($opt_suite_path . $suite . "/" .
                             $test_dir . "/shell.js");
            if (-f $path) {
                $shell_command .= $file_param . $path;
            }
kdecker's avatar
 
kdecker committed
188
            
189 190 191
            $last_suite = $suite;
            $last_test_dir = $test_dir;
        }
kdecker's avatar
 
kdecker committed
192
        
193
        $path = &xp_path($opt_suite_path . $test);
kdecker's avatar
kdecker committed
194
        &status ("executing: " . $shell_command . $file_param . $path);
195
        &dd ("executing: " . $shell_command . $file_param . $path);
kdecker's avatar
 
kdecker committed
196
        
197 198 199 200
        open (OUTPUT, $shell_command . $file_param . $path .
              $redirect_command . " |");
        @output = <OUTPUT>;
        close (OUTPUT);
kdecker's avatar
 
kdecker committed
201
        
202
        @output = grep (!/js\>/, @output);
kdecker's avatar
 
kdecker committed
203
        
204
        if ($opt_exit_munge == 1) {
kdecker's avatar
 
kdecker committed
205
# signal information in the lower 8 bits, exit code above that
206 207 208
            $got_exit = ($? >> 8);
            $exit_signal = ($? & 255);
        } else {
kdecker's avatar
 
kdecker committed
209
# user says not to munge the exit code
210 211 212
            $got_exit = $?;
            $exit_signal = 0;
        }
kdecker's avatar
 
kdecker committed
213
        
214 215 216
        $failure_lines = "";
        $bug_number = "";
        $status_lines = "";
kdecker's avatar
 
kdecker committed
217
        
218
        foreach $line (@output) {
kdecker's avatar
 
kdecker committed
219 220 221
            
# watch for testcase to proclaim what exit code it expects to
# produce (0 by default)
222 223 224 225
            if ($line =~ /expect(ed)?\s*exit\s*code\s*\:?\s*(\d+)/i) {
                $expected_exit = $2;
                &dd ("Test case expects exit code $expected_exit");
            }
kdecker's avatar
 
kdecker committed
226 227
            
# watch for failures
228 229 230
            if ($line =~ /failed!/i) {
                $failure_lines .= $line;
            }
kdecker's avatar
 
kdecker committed
231 232 233 234
            
# and watch for bugnumbers
# XXX This only allows 1 bugnumber per testfile, should be
# XXX modified to allow for multiple.
235 236 237 238
            if ($line =~ /bugnumber\s*\:?\s*(.*)/i) {
                $1 =~ /(\n+)/;
                $bug_number = $1;
            }
kdecker's avatar
 
kdecker committed
239 240
            
# and watch for status
241 242 243
            if ($line =~ /status/i) {
                $status_lines .= $line;
            }
kdecker's avatar
 
kdecker committed
244
            
245
        }
kdecker's avatar
 
kdecker committed
246
        
247 248 249
        if (!@output) {
            @output = ("Testcase produced no output!");
        }
kdecker's avatar
 
kdecker committed
250
        
251
        if ($got_exit != $expected_exit) {
kdecker's avatar
 
kdecker committed
252
# full testcase output dumped on mismatched exit codes,
253 254 255 256 257 258
            &report_failure ($test, "Expected exit code " .
                             "$expected_exit, got $got_exit\n" .
                             "Testcase terminated with signal $exit_signal\n" .
                             "Complete testcase output was:\n" .
                             join ("\n",@output), $bug_number);
        } elsif ($failure_lines) {
kdecker's avatar
 
kdecker committed
259
# only offending lines if exit codes matched
260 261 262 263
            &report_failure ($test, "$status_lines\n".
                             "Failure messages were:\n$failure_lines",
                             $bug_number);
        }
kdecker's avatar
 
kdecker committed
264
        
265
        &dd ("exit code $got_exit, exit signal $exit_signal.");
kdecker's avatar
 
kdecker committed
266
        
267 268 269 270 271 272 273 274
        $tests_completed++;
    }
}

sub write_results {
    my ($list_name, $neglist_name);
    my $completion_date = localtime;
    my $failure_pct = int(($failures_reported / $tests_completed) * 10000) /
kdecker's avatar
 
kdecker committed
275
        100;
276
    &dd ("Writing output to $opt_output_file.");
kdecker's avatar
 
kdecker committed
277
    
278 279 280 281 282 283 284
    if ($#opt_test_list_files == -1) {
        $list_name = "All tests";
    } elsif ($#opt_test_list_files < 10) {
        $list_name = join (", ", @opt_test_list_files);
    } else {
        $list_name = "($#opt_test_list_files test files specified)";
    }
kdecker's avatar
 
kdecker committed
285
    
286 287 288 289 290 291 292
    if ($#opt_neg_list_files == -1) {
        $neglist_name = "(none)";
    } elsif ($#opt_test_list_files < 10) {
        $neglist_name = join (", ", @opt_neg_list_files);
    } else {
        $neglist_name = "($#opt_neg_list_files skip files specified)";
    }
kdecker's avatar
 
kdecker committed
293
    
294
    open (OUTPUT, "> $opt_output_file") ||
kdecker's avatar
 
kdecker committed
295 296
        die ("Could not create output file $opt_output_file");
    
297
    print OUTPUT 
kdecker's avatar
 
kdecker committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
        ("<html><head>\n" .
         "<title>Test results, $opt_engine_type</title>\n" .
         "</head>\n" .
         "<body bgcolor='white'>\n" .
         "<a name='tippy_top'></a>\n" .
         "<h2>Test results, $opt_engine_type</h2><br>\n" .
         "<p class='results_summary'>\n" .
         "Test List: $list_name<br>\n" .
         "Skip List: $neglist_name<br>\n" .
         ($#test_list + 1) . " test(s) selected, $tests_completed test(s) " .
         "completed, $failures_reported failures reported " .
         "($failure_pct% failed)<br>\n" .
         "Engine command line: $engine_command<br>\n" .
         "OS type: $os_type<br>\n");
    
313 314 315 316 317 318 319
    if ($opt_engine_type =~ /^rhino/) {
        open (JAVAOUTPUT, $opt_java_path . "java -fullversion " .
              $redirect_command . " |");
        print OUTPUT <JAVAOUTPUT>;
        print OUTPUT "<BR>";
        close (JAVAOUTPUT);
    }
kdecker's avatar
 
kdecker committed
320
    
321
    print OUTPUT 
kdecker's avatar
 
kdecker committed
322 323 324
        ("Testcase execution time: $exec_time_string.<br>\n" .
         "Tests completed on $completion_date.<br><br>\n");
    
325 326
    if ($failures_reported > 0) {
        print OUTPUT
kdecker's avatar
 
kdecker committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
        ("[ <a href='#fail_detail'>Failure Details</a> | " .
         "<a href='#retest_list'>Retest List</a> | " .
         "<a href='menu.html'>Test Selection Page</a> ]<br>\n" .
         "<hr>\n" .
         "<a name='fail_detail'></a>\n" .
         "<h2>Failure Details</h2><br>\n<dl>" .
         $html .
         "</dl>\n[ <a href='#tippy_top'>Top of Page</a> | " .
         "<a href='#fail_detail'>Top of Failures</a> ]<br>\n" .
         "<hr>\n<pre>\n" .
         "<a name='retest_list'></a>\n" .
         "<h2>Retest List</h2><br>\n" .
         "# Retest List, $opt_engine_type, " .
         "generated $completion_date.\n" .
         "# Original test base was: $list_name.\n" .
         "# $tests_completed of " . ($#test_list + 1) .
         " test(s) were completed, " .
         "$failures_reported failures reported.\n" .
         join ("\n", @failed_tests) );
#"</pre>\n" .
#          "[ <a href='#tippy_top'>Top of Page</a> | " .
#          "<a href='#retest_list'>Top of Retest List</a> ]<br>\n");
349 350
    } else {
        print OUTPUT 
kdecker's avatar
 
kdecker committed
351
        ("<h1>Whoop-de-doo, nothing failed!</h1>\n");
352 353
    }

kdecker's avatar
 
kdecker committed
354
#print OUTPUT "</body>";
355

kdecker's avatar
 
kdecker committed
356
close (OUTPUT);
357

kdecker's avatar
 
kdecker committed
358
&status ("Wrote results to '$opt_output_file'.");
359

kdecker's avatar
 
kdecker committed
360 361 362
if ($opt_console_failures) {
    &status ("$failures_reported test(s) failed");
}
363 364 365 366 367

}

sub parse_args {
    my ($option, $value, $lastopt);
kdecker's avatar
 
kdecker committed
368
    
369
    &dd ("checking command line options.");
kdecker's avatar
 
kdecker committed
370
    
371 372
    Getopt::Mixed::init ($options);
    $Getopt::Mixed::order = $Getopt::Mixed::RETURN_IN_ORDER;
kdecker's avatar
 
kdecker committed
373
    
374
    while (($option, $value) = nextOption()) {
kdecker's avatar
 
kdecker committed
375
        
376 377 378
        if ($option eq "b") {
            &dd ("opt: setting bugurl to '$value'.");
            $opt_bug_url = $value;
kdecker's avatar
 
kdecker committed
379
            
380 381 382
        } elsif ($option eq "c") {
            &dd ("opt: setting classpath to '$value'.");
            $opt_classpath = $value;
kdecker's avatar
 
kdecker committed
383
            
384 385 386
        } elsif (($option eq "e") || (($option eq "") && ($lastopt eq "e"))) {
            &dd ("opt: adding engine $value.");
            push (@opt_engine_list, $value);
kdecker's avatar
 
kdecker committed
387
            
388 389 390 391 392 393 394
        } elsif ($option eq "f") {
            if (!$value) {
                die ("Output file cannot be null.\n");
            }
            &dd ("opt: setting output file to '$value'.");
            $opt_user_output_file = 1;
            $opt_output_file = $value;
kdecker's avatar
 
kdecker committed
395
            
396 397
        } elsif ($option eq "h") {
            &usage;
kdecker's avatar
 
kdecker committed
398
            
399 400 401 402 403 404
        } elsif ($option eq "j") {
            if (!($value =~ /[\/\\]$/)) {
                $value .= "/";
            }
            &dd ("opt: setting java path to '$value'.");
            $opt_java_path = $value;
kdecker's avatar
 
kdecker committed
405
            
406 407 408
        } elsif ($option eq "k") {
            &dd ("opt: displaying failures on console.");
            $opt_console_failures=1;
kdecker's avatar
 
kdecker committed
409
            
410 411 412 413
        } elsif ($option eq "l" || (($option eq "") && ($lastopt eq "l"))) {
            $option = "l";
            &dd ("opt: adding test list '$value'.");
            push (@opt_test_list_files, $value);
kdecker's avatar
 
kdecker committed
414
            
415 416 417 418
        } elsif ($option eq "L" || (($option eq "") && ($lastopt eq "L"))) {
            $option = "L";
            &dd ("opt: adding negative list '$value'.");
            push (@opt_neg_list_files, $value);
kdecker's avatar
 
kdecker committed
419
            
420 421 422
        } elsif ($option eq "o") {
            $opt_engine_params = $value;
            &dd ("opt: setting engine params to '$opt_engine_params'.");
kdecker's avatar
 
kdecker committed
423
            
424 425
        } elsif ($option eq "p") {
            $opt_suite_path = $value;
kdecker's avatar
 
kdecker committed
426
            
427 428 429 430 431 432 433 434 435
            if ($os_type eq "MAC") {
                if (!($opt_suite_path =~ /\:$/)) {
                    $opt_suite_path .= ":";
                }
            } else {
                if (!($opt_suite_path =~ /[\/\\]$/)) {
                    $opt_suite_path .= "/";
                }
            }
kdecker's avatar
 
kdecker committed
436
            
437
            &dd ("opt: setting suite path to '$opt_suite_path'.");
kdecker's avatar
 
kdecker committed
438
            
439 440 441
        } elsif ($option eq "s") {
            $opt_shell_path = $value;
            &dd ("opt: setting shell path to '$opt_shell_path'.");
kdecker's avatar
 
kdecker committed
442
            
443 444 445 446
        } elsif ($option eq "t") {
            &dd ("opt: tracing output.  (console failures at no extra charge.)");
            $opt_console_failures = 1;
            $opt_trace = 1;
kdecker's avatar
 
kdecker committed
447
            
448 449 450
        } elsif ($option eq "u") {
            &dd ("opt: setting lxr url to '$value'.");
            $opt_lxr_url = $value;
kdecker's avatar
 
kdecker committed
451
            
452 453 454
        } elsif ($option eq "x") {
            &dd ("opt: turning off exit munging.");
            $opt_exit_munge = 0;
kdecker's avatar
 
kdecker committed
455
            
456 457 458
        } else {
            &usage;
        }
kdecker's avatar
 
kdecker committed
459
        
460
        $lastopt = $option;
kdecker's avatar
 
kdecker committed
461
        
462
    }
kdecker's avatar
 
kdecker committed
463
    
464
    Getopt::Mixed::cleanup();
kdecker's avatar
 
kdecker committed
465
    
466 467 468
    if ($#opt_engine_list == -1) {
        die "You must select a shell to test in.\n";
    }
kdecker's avatar
 
kdecker committed
469
    
470 471 472 473 474 475 476
}

#
# print the arguments that this script expects
#
sub usage {
    print STDERR 
kdecker's avatar
 
kdecker committed
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
    ("\nusage: $0 [<options>] \n" .
     "(-b|--bugurl)             Bugzilla URL.\n" .
     "                          (default is $opt_bug_url)\n" .
     "(-c|--classpath)          Classpath (Rhino only.)\n" .
     "(-e|--engine) <type> ...  Specify the type of engine(s) to test.\n" .
     "                          <type> is one or more of\n" .
     "                          (kjs|smopt|smdebug|lcopt|lcdebug|xpcshell|" .
     "rhino|rhinoi|rhinoms|rhinomsi|rhino9|rhinoms9).\n" .
     "(-f|--file) <file>        Redirect output to file named <file>.\n" .
     "                          (default is " .
     "results-<engine-type>-<date-stamp>.html)\n" .
     "(-h|--help)               Print this message.\n" .
     "(-j|--javapath)           Location of java executable.\n" .
     "(-k|--confail)            Log failures to console (also.)\n" . 
     "(-l|--list) <file> ...    List of tests to execute.\n" . 
     "(-L|--neglist) <file> ... List of tests to skip.\n" . 
     "(-o|--opt) <options>      Options to pass to the JavaScript engine.\n" .
     "                          (Make sure to quote them!)\n" .
     "(-p|--testpath) <path>    Root of the test suite. (default is ./)\n" .
     "(-s|--shellpath) <path>   Location of JavaScript shell.\n" .
     "(-t|--trace)              Trace script execution.\n" .
     "(-u|--lxrurl) <url>       Complete URL to tests subdirectory on lxr.\n" .
     "                          (default is $opt_lxr_url)\n" .
     "(-x|--noexitmunge)        Don't do exit code munging (try this if it\n" .
     "                          seems like your exit codes are turning up\n" .
     "                          as exit signals.)\n");
503
    exit (1);
kdecker's avatar
 
kdecker committed
504
    
505 506 507 508 509 510
}

#
# get the shell command used to start the (either) engine
#
sub get_engine_command {
kdecker's avatar
 
kdecker committed
511
    
512
    my $retval;
kdecker's avatar
 
kdecker committed
513
    
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    if ($opt_engine_type eq "rhino") {
        &dd ("getting rhino engine command.");
        $opt_rhino_opt = 0;
        $opt_rhino_ms = 0;
        $retval = &get_rhino_engine_command;
    } elsif ($opt_engine_type eq "rhinoi") {
        &dd ("getting rhinoi engine command.");
        $opt_rhino_opt = -1;
        $opt_rhino_ms = 0;
        $retval = &get_rhino_engine_command;
    } elsif ($opt_engine_type eq "rhino9") {
        &dd ("getting rhino engine command.");
        $opt_rhino_opt = 9;
        $opt_rhino_ms = 0;
        $retval = &get_rhino_engine_command;
    } elsif ($opt_engine_type eq "rhinoms") {
        &dd ("getting rhinoms engine command.");
        $opt_rhino_opt = 0;
        $opt_rhino_ms = 1;
        $retval = &get_rhino_engine_command;
    } elsif ($opt_engine_type eq "rhinomsi") {
        &dd ("getting rhinomsi engine command.");
        $opt_rhino_opt = -1;
        $opt_rhino_ms = 1;
        $retval = &get_rhino_engine_command;
    } elsif ($opt_engine_type eq "rhinoms9") {
        &dd ("getting rhinomsi engine command.");
        $opt_rhino_opt = 9;
        $opt_rhino_ms = 1;
        $retval = &get_rhino_engine_command;
    } elsif ($opt_engine_type eq "xpcshell") {
        &dd ("getting xpcshell engine command.");
        $retval = &get_xpc_engine_command;
    } elsif ($opt_engine_type =~ /^lc(opt|debug)$/) {
        &dd ("getting liveconnect engine command.");
        $retval = &get_lc_engine_command;   
    } elsif ($opt_engine_type =~ /^sm(opt|debug)$/) {
        &dd ("getting spidermonkey engine command.");
        $retval = &get_sm_engine_command;
    }  elsif ($opt_engine_type =~ /^ep(opt|debug)$/) {
        &dd ("getting epimetheus engine command.");
        $retval = &get_ep_engine_command;
ggaren's avatar
ggaren committed
556
    } elsif ($opt_engine_type eq "kjs") {
kdecker's avatar
 
kdecker committed
557 558 559
        &dd ("getting kjs engine command.");
        $retval = &get_kjs_engine_command;
        
560 561 562
    } else {
        die ("Unknown engine type selected, '$opt_engine_type'.\n");
    }
kdecker's avatar
 
kdecker committed
563
    
564
    $retval .= " $opt_engine_params";
kdecker's avatar
 
kdecker committed
565
    
566
    &dd ("got '$retval'");
kdecker's avatar
 
kdecker committed
567
    
568
    return $retval;
kdecker's avatar
 
kdecker committed
569
    
570 571 572 573 574 575 576
}

#
# get the shell command used to run rhino
#
sub get_rhino_engine_command {
    my $retval = $opt_java_path . ($opt_rhino_ms ? "jview " : "java ");
kdecker's avatar
 
kdecker committed
577
    
578 579
    if ($opt_shell_path) {
        $opt_classpath = ($opt_classpath) ?
kdecker's avatar
 
kdecker committed
580 581
        $opt_classpath . ":" . $opt_shell_path :
        $opt_shell_path;
582
    }
kdecker's avatar
 
kdecker committed
583
    
584 585 586
    if ($opt_classpath) {
        $retval .= ($opt_rhino_ms ? "/cp:p" : "-classpath") . " $opt_classpath ";
    }
kdecker's avatar
 
kdecker committed
587
    
588
    $retval .= "org.mozilla.javascript.tools.shell.Main";
kdecker's avatar
 
kdecker committed
589
    
590 591 592
    if ($opt_rhino_opt) {
        $retval .= " -opt $opt_rhino_opt";
    }
kdecker's avatar
 
kdecker committed
593
    
594
    return $retval;
kdecker's avatar
 
kdecker committed
595
    
596 597 598 599 600 601 602 603
}

#
# get the shell command used to run xpcshell
#
sub get_xpc_engine_command {
    my $retval;
    my $m5_home = @ENV{"MOZILLA_FIVE_HOME"} ||
kdecker's avatar
 
kdecker committed
604 605 606 607 608
        die ("You must set MOZILLA_FIVE_HOME to use the xpcshell" ,
             (!$unixish) ? "." : ", also " .
             "setting LD_LIBRARY_PATH to the same directory may get rid of " .
             "any 'library not found' errors.\n");
    
609 610
    if (($unixish) && (!@ENV{"LD_LIBRARY_PATH"})) {
        print STDERR "-#- WARNING: LD_LIBRARY_PATH is not set, xpcshell may " .
kdecker's avatar
 
kdecker committed
611
        "not be able to find the required components.\n";
612
    }
kdecker's avatar
 
kdecker committed
613
    
614 615 616
    if (!($m5_home =~ /[\/\\]$/)) {
        $m5_home .= "/";
    }
kdecker's avatar
 
kdecker committed
617
    
618
    $retval = $m5_home . "xpcshell";
kdecker's avatar
 
kdecker committed
619
    
620 621 622
    if ($os_type eq "WIN") {
        $retval .= ".exe";
    }
kdecker's avatar
 
kdecker committed
623
    
624
    $retval = &xp_path($retval);
kdecker's avatar
 
kdecker committed
625
    
626
    if (($os_type ne "MAC") && !(-x $retval)) {
kdecker's avatar
 
kdecker committed
627
# mac doesn't seem to deal with -x correctly
628 629
        die ($retval . " is not a valid executable on this system.\n");
    }
kdecker's avatar
 
kdecker committed
630
    
631
    return $retval;
kdecker's avatar
 
kdecker committed
632 633
    
}
634

kdecker's avatar
 
kdecker committed
635 636 637 638
#
# get the shell command used to run kjs
#
sub get_kjs_engine_command {
ggaren's avatar
ggaren committed
639 640 641 642 643 644 645 646 647
    my $retval;
    
    if ($opt_shell_path) {
        $retval = $opt_shell_path;
    } else {
        die "Please specify a full path to the kjs testing engine";
    }
    
    return $retval;
648 649 650 651 652 653 654
}

#
# get the shell command used to run spidermonkey
#
sub get_sm_engine_command {
    my $retval;
kdecker's avatar
 
kdecker committed
655 656 657 658 659
    
# Look for Makefile.ref style make first.
# (On Windows, spidermonkey can be made by two makefiles, each putting the
# executable in a diferent directory, under a different name.)
    
660
    if ($opt_shell_path) {
kdecker's avatar
 
kdecker committed
661
# if the user provided a path to the shell, return that.
662
        $retval = $opt_shell_path;
kdecker's avatar
 
kdecker committed
663
        
664
    } else {
kdecker's avatar
 
kdecker committed
665
        
666 667 668 669 670 671 672
        if ($os_type eq "MAC") {
            $retval = $opt_suite_path . ":src:macbuild:JS";
        } else {
            $retval = $opt_suite_path . "../src/";
            opendir (SRC_DIR_FILES, $retval);
            my @src_dir_files = readdir(SRC_DIR_FILES);
            closedir (SRC_DIR_FILES);
kdecker's avatar
 
kdecker committed
673
            
674 675
            my ($dir, $object_dir);
            my $pattern = ($opt_engine_type eq "smdebug") ?
kdecker's avatar
 
kdecker committed
676 677 678 679
                'DBG.OBJ' : 'OPT.OBJ';
            
# scan for the first directory matching
# the pattern expected to hold this type (debug or opt) of engine
680 681 682 683 684 685
            foreach $dir (@src_dir_files) {
                if ($dir =~ $pattern) {
                    $object_dir = $dir;
                    last;
                }
            }
kdecker's avatar
 
kdecker committed
686
            
687 688 689 690 691
            if (!$object_dir && $os_type ne "WIN") {
                die ("Could not locate an object directory in $retval " .
                     "matching the pattern *$pattern.  Have you built the " .
                     "engine?\n");
            }
kdecker's avatar
 
kdecker committed
692
            
693
            if (!(-x $retval . $object_dir . "/js.exe") && ($os_type eq "WIN")) {
kdecker's avatar
 
kdecker committed
694 695 696 697
# On windows, you can build with js.mak as well as Makefile.ref
# (Can you say WTF boys and girls?  I knew you could.)
# So, if the exe the would have been built by Makefile.ref isn't 
# here, check for the js.mak version before dying.
698 699 700 701 702 703 704 705 706 707 708 709
                if ($opt_shell_path) {
                    $retval = $opt_shell_path;
                    if (!($retval =~ /[\/\\]$/)) {
                        $retval .= "/";
                    }
                } else {
                    if ($opt_engine_type eq "smopt") {
                        $retval = "../src/Release/";
                    } else {
                        $retval = "../src/Debug/";
                    }
                }
kdecker's avatar
 
kdecker committed
710
                
711
                $retval .= "jsshell.exe";
kdecker's avatar
 
kdecker committed
712
                
713 714 715 716 717 718 719
            } else {
                $retval .= $object_dir . "/js";
                if ($os_type eq "WIN") {
                    $retval .= ".exe";
                }
            }
        } # mac/ not mac
kdecker's avatar
 
kdecker committed
720
        
721
        $retval = &xp_path($retval);
kdecker's avatar
 
kdecker committed
722
        
723
    } # (user provided a path)
kdecker's avatar
 
kdecker committed
724 725 726 727 728 729 730
        
        
        if (($os_type ne "MAC") && !(-x $retval)) {
# mac doesn't seem to deal with -x correctly
            die ($retval . " is not a valid executable on this system.\n");
        }
    
731
    return $retval;
kdecker's avatar
 
kdecker committed
732
    
733 734 735 736 737 738 739
}

#
# get the shell command used to run epimetheus
#
sub get_ep_engine_command {
    my $retval;
kdecker's avatar
 
kdecker committed
740
    
741
    if ($opt_shell_path) {
kdecker's avatar
 
kdecker committed
742
# if the user provided a path to the shell, return that -
743
        $retval = $opt_shell_path;
kdecker's avatar
 
kdecker committed
744
        
745 746 747 748 749 750
    } else {
        my $dir;
        my $os;
        my $debug;
        my $opt;
        my $exe;
kdecker's avatar
 
kdecker committed
751
        
752
        $dir = $opt_suite_path . "../../js2/src/";
kdecker's avatar
 
kdecker committed
753
        
754
        if ($os_type eq "MAC") {
kdecker's avatar
 
kdecker committed
755 756 757
#
# On the Mac, the debug and opt builds lie in the same directory -
#
758 759 760 761 762 763 764 765 766 767 768 769 770
            $os = "macbuild:";
            $debug = "";
            $opt = "";
            $exe = "JS2";
        } elsif ($os_type eq "WIN") {
            $os = "winbuild/Epimetheus/";
            $debug = "Debug/";
            $opt = "Release/";
            $exe = "Epimetheus.exe";
        } else {
            $os = "";
            $debug = "";
            $opt = "";    # <<<----- XXX THIS IS NOT RIGHT! CHANGE IT!
kdecker's avatar
 
kdecker committed
771
                $exe = "epimetheus";
772
        }
kdecker's avatar
 
kdecker committed
773 774
        
        
775 776 777 778 779
        if ($opt_engine_type eq "epdebug") {
            $retval = $dir . $os . $debug . $exe;
        } else {
            $retval = $dir . $os . $opt . $exe;
        }
kdecker's avatar
 
kdecker committed
780
        
781
        $retval = &xp_path($retval);
kdecker's avatar
 
kdecker committed
782
        
783
    }# (user provided a path)
kdecker's avatar
 
kdecker committed
784 785 786 787 788 789 790
        
        
        if (($os_type ne "MAC") && !(-x $retval)) {
# mac doesn't seem to deal with -x correctly
            die ($retval . " is not a valid executable on this system.\n");
        }
    
791 792 793 794 795 796 797 798
    return $retval;
}

#
# get the shell command used to run the liveconnect shell
#
sub get_lc_engine_command {
    my $retval;
kdecker's avatar
 
kdecker committed
799
    
800 801 802 803 804 805 806 807 808 809
    if ($opt_shell_path) {
        $retval = $opt_shell_path;
    } else {
        if ($os_type eq "MAC") {
            die "Don't know how to run the lc shell on the mac yet.\n";
        } else {
            $retval = $opt_suite_path . "../src/liveconnect/";
            opendir (SRC_DIR_FILES, $retval);
            my @src_dir_files = readdir(SRC_DIR_FILES);
            closedir (SRC_DIR_FILES);
kdecker's avatar
 
kdecker committed
810
            
811 812
            my ($dir, $object_dir);
            my $pattern = ($opt_engine_type eq "lcdebug") ?
kdecker's avatar
 
kdecker committed
813 814
                'DBG.OBJ' : 'OPT.OBJ';
            
815 816 817 818 819 820
            foreach $dir (@src_dir_files) {
                if ($dir =~ $pattern) {
                    $object_dir = $dir;
                    last;
                }
            }
kdecker's avatar
 
kdecker committed
821
            
822 823 824 825 826
            if (!$object_dir) {
                die ("Could not locate an object directory in $retval " .
                     "matching the pattern *$pattern.  Have you built the " .
                     "engine?\n");
            }
kdecker's avatar
 
kdecker committed
827
            
828
            $retval .= $object_dir . "/";
kdecker's avatar
 
kdecker committed
829
            
830 831 832 833 834 835
            if ($os_type eq "WIN") {
                $retval .= "lcshell.exe";
            } else {
                $retval .= "lcshell";
            }
        } # mac/ not mac
kdecker's avatar
 
kdecker committed
836
        
837
        $retval = &xp_path($retval);
kdecker's avatar
 
kdecker committed
838
        
839
    } # (user provided a path)
kdecker's avatar
 
kdecker committed
840 841 842 843 844 845 846
        
        
        if (($os_type ne "MAC") && !(-x $retval)) {
# mac doesn't seem to deal with -x correctly
            die ("$retval is not a valid executable on this system.\n");
        }
    
847
    return $retval;
kdecker's avatar
 
kdecker committed
848
    
849 850 851
}

sub get_os_type {
kdecker's avatar
 
kdecker committed
852
    
853 854 855
    if ("\n" eq "\015") {
        return "MAC";
    }
kdecker's avatar
 
kdecker committed
856
    
857
    my $uname = `uname -a`;
kdecker's avatar
 
kdecker committed
858
    
859 860 861 862 863
    if ($uname =~ /WIN/) {
        $uname = "WIN";
    } else {
        chop $uname;
    }
kdecker's avatar
 
kdecker committed
864
    
865 866
    &dd ("get_os_type returning '$uname'.");
    return $uname;
kdecker's avatar
 
kdecker committed
867
    
868 869 870 871 872
}

sub get_test_list {
    my @test_list;
    my @neg_list;
kdecker's avatar
 
kdecker committed
873
    
874 875
    if ($#opt_test_list_files > -1) {
        my $list_file;
kdecker's avatar
 
kdecker committed
876
        
877
        &dd ("getting test list from user specified source.");
kdecker's avatar
 
kdecker committed
878
        
879 880 881 882 883
        foreach $list_file (@opt_test_list_files) {
            push (@test_list, &expand_user_test_list($list_file));
        }
    } else {
        &dd ("no list file, groveling in '$opt_suite_path'.");
kdecker's avatar
 
kdecker committed
884
        
885 886
        @test_list = &get_default_test_list($opt_suite_path);
    }
kdecker's avatar
 
kdecker committed
887
    
888 889 890 891
    if ($#opt_neg_list_files > -1) {
        my $list_file;
        my $orig_size = $#test_list + 1;
        my $actually_skipped;
kdecker's avatar
 
kdecker committed
892
        
893
        &dd ("getting negative list from user specified source.");
kdecker's avatar
 
kdecker committed
894
        
895 896 897
        foreach $list_file (@opt_neg_list_files) {
            push (@neg_list, &expand_user_test_list($list_file));
        }
kdecker's avatar
 
kdecker committed
898
        
899
        @test_list = &subtract_arrays (\@test_list, \@neg_list);
kdecker's avatar
 
kdecker committed
900
        
901
        $actually_skipped = $orig_size - ($#test_list + 1);
kdecker's avatar
 
kdecker committed
902
        
903 904 905 906
        &dd ($actually_skipped . " of " . $orig_size .
             " tests will be skipped.");
        &dd ((($#neg_list + 1) - $actually_skipped) . " skip tests were " .
             "not actually part of the test list.");
kdecker's avatar
 
kdecker committed
907 908
        
        
909
    }
kdecker's avatar
 
kdecker committed
910
    
911
    return @test_list;
kdecker's avatar
 
kdecker committed
912
    
913 914 915 916 917 918 919 920 921 922
}

#
# reads $list_file, storing non-comment lines into an array.
# lines in the form suite_dir/[*] or suite_dir/test_dir/[*] are expanded
# to include all test files under the specified directory
#
sub expand_user_test_list {
    my ($list_file) = @_;
    my @retval = ();
kdecker's avatar
 
kdecker committed
923 924 925 926 927 928 929 930 931 932
    
#
# Trim off the leading path separator that begins relative paths on the Mac.
# Each path will get concatenated with $opt_suite_path, which ends in one.
#
# Also note:
#
# We will call expand_test_list_entry(), which does pattern-matching on $list_file.
# This will make the pattern-matching the same as it would be on Linux/Windows -
#
933 934 935
    if ($os_type eq "MAC") {
        $list_file =~ s/^$path_sep//;
    }
kdecker's avatar
 
kdecker committed
936
    
937
    if ($list_file =~ /\.js$/ || -d $opt_suite_path . $list_file) {
kdecker's avatar
 
kdecker committed
938
        
939
        push (@retval, &expand_test_list_entry($list_file));
kdecker's avatar
 
kdecker committed
940
        
941
    } else {
kdecker's avatar
 
kdecker committed
942
        
943
        open (TESTLIST, $list_file) ||
kdecker's avatar
 
kdecker committed
944 945
        die("Error opening test list file '$list_file': $!\n");
        
946 947 948
        while (<TESTLIST>) {
            s/\r*\n*$//;
            if (!(/\s*\#/)) {
kdecker's avatar
 
kdecker committed
949
# It's not a comment, so process it
950 951 952
                push (@retval, &expand_test_list_entry($_));
            }
        }
kdecker's avatar
 
kdecker committed
953
        
954
        close (TESTLIST);
kdecker's avatar
 
kdecker committed
955
        
956
    }
kdecker's avatar
 
kdecker committed
957
    
958
    return @retval;
kdecker's avatar
 
kdecker committed
959
    
960 961 962 963 964 965 966 967 968 969
}


#
# Currently expect all paths to be RELATIVE to the top-level tests directory.
# One day, this should be improved to allow absolute paths as well -
#
sub expand_test_list_entry {
    my ($entry) = @_;
    my @retval;
kdecker's avatar
 
kdecker committed
970
    
971
    if ($entry =~ /\.js$/) {
kdecker's avatar
 
kdecker committed
972
# it's a regular entry, add it to the list
973 974 975 976 977 978
        if (-f $opt_suite_path . $entry) {
            push (@retval, $entry);
        } else {
            status ("testcase '$entry' not found.");
        }
    } elsif ($entry =~ /(.*$path_sep[^\*][^$path_sep]*)$path_sep?\*?$/) {
kdecker's avatar
 
kdecker committed
979 980 981 982 983 984 985 986 987 988 989 990 991 992
# Entry is in the form suite_dir/test_dir[/*]
# so iterate all tests under it
 my