mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-14 15:37:55 +00:00
496 lines
14 KiB
Perl
496 lines
14 KiB
Perl
#!/usr/bin/perl5
|
|
#
|
|
# simple script that executes JavaScript tests. you have to build the
|
|
# stand-alone, js shell executable (which is not the same as the dll that gets
|
|
# built for mozilla). see the readme at
|
|
# http://lxr.mozilla.org/mozilla/source/js/src/README.html for instructions on
|
|
# how to build the jsshell.
|
|
#
|
|
# this is just a quick-n-dirty script. for full reporting, you need to run
|
|
# the test driver, which requires java and is currently not available on
|
|
# mozilla.org.
|
|
#
|
|
# this test looks for an executable JavaScript shell in
|
|
# %MOZ_SRC/mozilla/js/src/[platform]-[platform-version]-OPT.OBJ/js,
|
|
# which is the default build location when you build using the instructions
|
|
# at http://lxr.mozilla.org/mozilla/source/js/src/README.html
|
|
#
|
|
#
|
|
# christine@netscape.com
|
|
#
|
|
|
|
&parse_args;
|
|
&setup_env;
|
|
&main_test_loop;
|
|
&cleanup_env;
|
|
|
|
#
|
|
# given a main directory, assume that there is a file called 'shell.js'
|
|
# in it. then, open all the subdirectories, and look for js files.
|
|
# for each test.js that is found, execute the shell, and pass shell.js
|
|
# and the test.js as file arguments. redirect all process output to a
|
|
# file.
|
|
#
|
|
sub main_test_loop {
|
|
foreach $suite ( &get_subdirs( $test_dir )) {
|
|
foreach $subdir (&get_subdirs( $suite, $test_dir )) {
|
|
@jsfiles = &get_js_files($subdir);
|
|
execute_js_tests(@jsfiles);
|
|
}
|
|
}
|
|
}
|
|
|
|
#
|
|
# given a directory, return an array of all subdirectories
|
|
#
|
|
sub get_subdirs{
|
|
local ($dir, $path) = @_;
|
|
local @subdirs;
|
|
|
|
local $dir_path = $path . $dir;
|
|
chdir $dir_path;
|
|
|
|
opendir ( DIR, ${dir_path} );
|
|
local @testdir_contents = readdir( DIR );
|
|
closedir( DIR );
|
|
|
|
foreach (@testdir_contents) {
|
|
if ( (-d $_) && ($_ !~ 'CVS') && ( $_ ne '.') && ($_ ne '..')) {
|
|
@subdirs[$#subdirs+1] = $_;
|
|
}
|
|
}
|
|
chdir $path;
|
|
return @subdirs;
|
|
}
|
|
|
|
#
|
|
# given a directory, return an array of all the js files that are in it.
|
|
#
|
|
sub get_js_files {
|
|
( $test_subdir ) = @_;
|
|
local @js_file_array;
|
|
|
|
$current_test_dir = $test_dir ."/". $suite . "/" .$test_subdir;
|
|
chdir $current_test_dir;
|
|
|
|
opendir ( TEST_SUBDIR, ${current_test_dir} );
|
|
@subdir_files = readdir( TEST_SUBDIR );
|
|
closedir( TOP_LEVEL_BUILD_DIR );
|
|
|
|
foreach ( @subdir_files ) {
|
|
if ( $_ =~ /\.js$/ ) {
|
|
$js_file_array[$#js_file_array+1] = $_;
|
|
}
|
|
}
|
|
|
|
return @js_file_array;
|
|
}
|
|
|
|
#
|
|
# given an array of test.js files, execute the shell command and pass
|
|
# the shell.js and test.js files as file arguments. redirect process
|
|
# output to a file. if $js_verbose is set (not recommended), write all
|
|
# testcase output to the output file. if $js_quiet is set, only write
|
|
# failed test case information to the output file. the default setting
|
|
# is to write a line for each test file, and whether each file passed
|
|
# or failed.
|
|
#
|
|
sub execute_js_tests {
|
|
(@js_file_array) = @_;
|
|
|
|
$js_printed_suitename = 0;
|
|
if ( !$js_quiet ) {
|
|
&js_print_suitename;
|
|
}
|
|
|
|
foreach $js_test (@js_file_array) {
|
|
$js_printed_filename = 0;
|
|
$js_test_bugnumber = 0;
|
|
$runtime_error = "";
|
|
|
|
local $passed = -1;
|
|
|
|
# create the test command
|
|
$test_command =
|
|
$shell_command .
|
|
" -f $test_dir/$suite/shell.js " .
|
|
" -f $test_dir/$suite/$subdir/$js_test";
|
|
|
|
if ( !$js_quiet ) {
|
|
&js_print_filename;
|
|
} else {
|
|
print '.';
|
|
}
|
|
|
|
$test_path = $test_dir ."/" . $suite ."/". $test_subdir ."/". $js_test;
|
|
|
|
|
|
if ( !-e $test_path ) {
|
|
&js_print( " FAILED! file not found\n",
|
|
"<font color=#990000>", "</font><br>\n");
|
|
} else {
|
|
open( RUNNING_TEST, "$test_command" . ' 2>&1 |');
|
|
|
|
|
|
# this is where we want the tests to provide a lot more information
|
|
# that this script must parse so that we can
|
|
|
|
while( <RUNNING_TEST> ){
|
|
if ( $js_verbose && !$js_quiet ) {
|
|
&js_print ($_ ."\n", "", "<br>\n");
|
|
}
|
|
if ( $_ =~ /BUGNUMBER/ ) {
|
|
$js_test_bugnumber = $_;
|
|
}
|
|
if ( $_ =~ /PASSED/ && $passed == -1 ) {
|
|
$passed = 1;
|
|
}
|
|
if ( $_ =~ /FAILED/ && $_ =~ /expected/) {
|
|
&js_print_suitename;
|
|
&js_print_filename;
|
|
&js_print_bugnumber;
|
|
|
|
local @msg = split ( "FAILED", $_ );
|
|
&js_print ( $passed ? "\n" : "" );
|
|
&js_print( " " . $msg[0], " <tt>" );
|
|
&js_print( "FAILED", "<font color=#990000>", "</font>");
|
|
&js_print( $msg[1], "", "</tt><br>\n" );
|
|
$passed = 0;
|
|
}
|
|
if ( $_ =~ /$js_test/ ) {
|
|
$runtime_error .= $_;
|
|
}
|
|
}
|
|
close( RUNNING_TEST );
|
|
|
|
#
|
|
# figure out whether the test passed or failed. print out an
|
|
# appropriate level of output based on the value of $js_quiet
|
|
#
|
|
if ( $js_test =~ /-n\.js$/ ) {
|
|
if ( $runtime_error ) {
|
|
if ( !$js_quiet ) {
|
|
&js_print( " PASSED!\n ",
|
|
"<font color=#009900>  ",
|
|
"</font><br>" );
|
|
if ( $js_errors ) {
|
|
&js_print( $runtime_error, "<pre>", "</pre>");
|
|
}
|
|
}
|
|
} else {
|
|
&js_print_suitename;
|
|
&js_print_filename;
|
|
&js_print_bugnumber;
|
|
&js_print( " FAILED! ", " <font color=#990000>",
|
|
"</font>");
|
|
&js_print( " Should have resulted in an error\n",
|
|
"","<br>" );
|
|
}
|
|
} else {
|
|
if ( $passed == 1 && !$js_quiet) {
|
|
&js_print( " PASSED!\n " , " <font color=#009900>",
|
|
"</font><br>" );
|
|
} else {
|
|
if ($passed == -1) {
|
|
&js_print_suitename;
|
|
&js_print_filename;
|
|
&js_print_bugnumber;
|
|
&js_print( " FAILED!\n " , " <font color=#990000>",
|
|
"</font><br>" );
|
|
&js_print( " Missing 'PASSED' in output\n", "","<br>" );
|
|
&js_print( $log, "output:<br><pre>", "</pre>" );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#
|
|
# figure out what os we're on, the default name of the object directory
|
|
#
|
|
sub setup_env {
|
|
# MOZ_SRC must be set, so we can figure out where the
|
|
# JavaScript executable is
|
|
$moz_src = $ENV{"MOZ_SRC"}
|
|
|| die( "You need to set your MOZ_SRC environment variable.\n" );
|
|
$src_dir = $moz_src . '/mozilla/js/src/';
|
|
|
|
# JS_TEST_DIR must be set so we can figure out where the tests are.
|
|
$test_dir = $ENV{"JS_TEST_DIR"};
|
|
|
|
# if it's not set, look for it relative to $moz_src
|
|
if ( !$test_dir ) {
|
|
$test_dir = $moz_src . '/mozilla/js/tests/';
|
|
}
|
|
|
|
# make sure that the test dir exists
|
|
if ( ! -e $test_dir ) {
|
|
die "The JavaScript Test Library could not be found at $test_dir.\n" .
|
|
"Check the tests out from /mozilla/js/tests or\n" .
|
|
"Set the value of your JS_TEST_DIR environment variable\n " .
|
|
"to the location of the test library.\n";
|
|
}
|
|
|
|
# make sure that the test dir ends with a trailing slash
|
|
$test_dir .= '/';
|
|
|
|
chdir $src_dir;
|
|
|
|
# figure out which platform we're on, and figure out where the object
|
|
# directory is
|
|
|
|
$machine_os = `uname -s`;
|
|
|
|
if ( $machine_os =~ /WIN/ ) {
|
|
$machine_os = 'WIN';
|
|
$object_dir = ($js_debug) ? 'Debug' : 'Release';
|
|
$js_exe = 'jsshell.exe';
|
|
} else {
|
|
chop $machine_os;
|
|
$js_exe = 'js';
|
|
|
|
# figure out what the object directory is. on all platforms,
|
|
# it's the directory that ends in OBJ. if $js_debug is set,
|
|
# look the directory that ends with or DBG.OBJ; otherwise
|
|
# look for the directory that ends with OPT.OBJ
|
|
|
|
opendir ( SRC_DIR_FILES, $src_dir );
|
|
@src_dir_files = readdir( SRC_DIR_FILES );
|
|
closedir ( SRC_DIR_FILES );
|
|
|
|
$object_pattern = $js_debug ? 'DBG.OBJ' : 'OPT.OBJ';
|
|
|
|
foreach (@src_dir_files) {
|
|
if ( $_ =~ /$object_pattern/ && $_ =~ $machine_os) {
|
|
$object_dir = $_;
|
|
}
|
|
}
|
|
}
|
|
if ( ! $object_dir ) {
|
|
die( "Couldn't find an object directory in $src_dir.\n" );
|
|
}
|
|
|
|
# figure out what the name of the javascript executable should be, and
|
|
# make sure it's there. if it's not there, give a helpful message so
|
|
# the user can figure out what they need to do next.
|
|
|
|
|
|
if ( ! $js_exe_full_path ) {
|
|
$shell_command = $src_dir . $object_dir .'/'. $js_exe;
|
|
} else {
|
|
$shell_command = $js_exe_full_path;
|
|
}
|
|
|
|
if ( !-e $shell_command ) {
|
|
die ("Could not find JavaScript shell executable $shell_command.\n" .
|
|
"Check the value of your MOZ_SRC environment variable.\n" .
|
|
"Currently, MOZ_SRC is set to $ENV{\"MOZ_SRC\"}\n".
|
|
"See the readme at http://lxr.mozilla.org/mozilla/src/js/src/ " .
|
|
"for instructions on building the JavaScript shell.\n" );
|
|
}
|
|
|
|
# set the output file name. let's base its name on the date and platform,
|
|
# and give it a sequence number.
|
|
|
|
if ( $get_output ) {
|
|
$js_output = &get_output;
|
|
}
|
|
if ($js_output) {
|
|
print( "Writing results to $js_output\n" );
|
|
chdir $test_dir;
|
|
open( JS_OUTPUT, "> ${js_output}" ) ||
|
|
die "Can't open log file $js_output\n";
|
|
close JS_OUTPUT;
|
|
}
|
|
|
|
# get the start time
|
|
$start_time = time;
|
|
|
|
# print out some nice stuff
|
|
$start_date = &get_date;
|
|
&js_print( "JavaScript tests started: " . $start_date, "<p><tt>", "</tt></p>" );
|
|
|
|
&js_print ("Executing all the tests under $test_dir\n against " .
|
|
"$shell_command\n", "<p><tt>", "</tt></p>" );
|
|
}
|
|
|
|
#
|
|
# parse arguments. see usage for what arguments are expected.
|
|
#
|
|
sub parse_args {
|
|
$i = 0;
|
|
while( $i < @ARGV ){
|
|
if ( $ARGV[$i] eq '--threaded' ) {
|
|
$js_threaded = 1;
|
|
} elsif ( $ARGV[$i] eq '--d' ) {
|
|
$js_debug = 1;
|
|
} elsif ( $ARGV[$i] eq '--14' ) {
|
|
$js_version = '14';
|
|
} elsif ( $ARGV[$i] eq '--v' ) {
|
|
$js_verbose = 1;
|
|
} elsif ( $ARGV[$i] eq '-f' ) {
|
|
$js_output = $ARGV[++$i];
|
|
} elsif ( $ARGV[$i] eq '--o' ) {
|
|
$get_output = 1;
|
|
} elsif ($ARGV[$i] eq '--e' ) {
|
|
$js_errors = 1;
|
|
} elsif ($ARGV[$i] eq '--q' ) {
|
|
$js_quiet = 1;
|
|
} elsif ($ARGV[$i] eq '--h' ) {
|
|
die &usage;
|
|
} elsif ( $ARGV[$i] eq '-E' ) {
|
|
$js_exe_full_path = $ARGV[$i+1];
|
|
$i++;
|
|
} else {
|
|
die &usage;
|
|
}
|
|
$i++;
|
|
}
|
|
|
|
#
|
|
# if no output options are provided, show some output and write to file
|
|
#
|
|
if ( !$js_verbose && !$js_output && !$get_output ) {
|
|
$get_output = 1;
|
|
}
|
|
}
|
|
|
|
#
|
|
# print the arguments that this script expects
|
|
#
|
|
sub usage {
|
|
die ("usage: $0\n" .
|
|
"--q Quiet mode -- only show information for tests that failed\n".
|
|
"--e Show runtime error messages for negative tests\n" .
|
|
"--v Verbose output -- show all test cases (not recommended)\n" .
|
|
"--o Send output to file whose generated name is based on date\n".
|
|
"--d Look for a debug JavaScript executable (default is optimized)\n" .
|
|
"-f <file> Redirect output to file named <file>\n"
|
|
);
|
|
}
|
|
|
|
#
|
|
# if $js_output is set, print to file as well as stdout
|
|
#
|
|
sub js_print {
|
|
($string, $start_tag, $end_tag) = @_;
|
|
|
|
if ($js_output) {
|
|
open( JS_OUTPUT, ">> ${js_output}" ) ||
|
|
die "Can't open log file $js_output\n";
|
|
|
|
print JS_OUTPUT "$start_tag $string $end_tag";
|
|
close JS_OUTPUT;
|
|
}
|
|
print $string;
|
|
}
|
|
|
|
#
|
|
# close open files
|
|
#
|
|
sub cleanup_env {
|
|
# print out some nice stuff
|
|
$end_date = &get_date;
|
|
&js_print( "\nTests complete at $end_date", "<hr><tt>", "</tt>" );
|
|
|
|
# print out how long it took to complete
|
|
$end_time = time;
|
|
|
|
$test_seconds = ( $end_time - $start_time );
|
|
|
|
&js_print( "Start Date: $start_date\n", "<tt><br>" );
|
|
&js_print( "End Date: $end_date\n", "<br>" );
|
|
&js_print( "Test Time: $test_seconds seconds\n", "<br>" );
|
|
|
|
if ($js_output ) {
|
|
if ( !$js_verbose) {
|
|
&js_print( "Results were written to " . $js_output ."\n",
|
|
"<br>", "</tt>" );
|
|
}
|
|
close JS_OUTPUT;
|
|
}
|
|
}
|
|
|
|
|
|
#
|
|
# get the current date and time
|
|
#
|
|
sub get_date {
|
|
&get_localtime;
|
|
$now = $year ."/". $mon ."/". $mday ." ". $hour .":".
|
|
$min .":". $sec ."\n";
|
|
return $now;
|
|
|
|
}
|
|
sub get_localtime {
|
|
( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
|
|
localtime;
|
|
$mon++;
|
|
$mon = &zero_pad($mon);
|
|
$year= ($year < 2000) ? "19" . $year : $year;
|
|
$mday= &zero_pad($mday);
|
|
$sec = &zero_pad($sec);
|
|
$min = &zero_pad($min);
|
|
$hour = &zero_pad($hour);
|
|
}
|
|
sub zero_pad {
|
|
local ($string) = @_;
|
|
$string = ($string < 10) ? "0" . $string : $string;
|
|
return $string;
|
|
}
|
|
|
|
#
|
|
# generate an output file name based on the date
|
|
#
|
|
sub get_output {
|
|
&get_localtime;
|
|
|
|
chdir $test_dir;
|
|
|
|
$js_output = $test_dir ."/". $year .'-'. $mon .'-'. $mday ."\.1.html";
|
|
|
|
$output_file_found = 0;
|
|
|
|
while ( !$output_file_found ) {
|
|
if ( -e $js_output ) {
|
|
# get the last sequence number - everything after the dot
|
|
@seq_no = split( /\./, $js_output, 2 );
|
|
$js_output = $seq_no[0] .".". (++$seq_no[1]) . "\.html";
|
|
} else {
|
|
$output_file_found = 1;
|
|
}
|
|
}
|
|
return $js_output;
|
|
}
|
|
|
|
sub js_print_suitename {
|
|
if ( !$js_printed_suitename ) {
|
|
&js_print( "$suite\\$subdir\n", "<hr><font size+=1><b>",
|
|
"</font></b><br>" );
|
|
}
|
|
$js_printed_suitename = 1;
|
|
}
|
|
|
|
sub js_print_filename {
|
|
if ( !$js_printed_filename ) {
|
|
&js_print( "$js_test\n", "<b>", "</b><br>" );
|
|
$js_printed_filename = 1;
|
|
}
|
|
}
|
|
|
|
sub js_print_bugnumber {
|
|
if ( !$js_printed_bugnumber ) {
|
|
if ( $js_bugnumber =~ /^http/ ) {
|
|
&js_print( "$js_bugnumber", "<a href=$js_bugnumber>", "</a>" );
|
|
} else {
|
|
&js_print( "$js_bugnumber",
|
|
"<a href=http://scopus.mcom.com/bugsplat/show_bug.cgi?id=" .
|
|
$js_bugnumber .">",
|
|
"</a>" );
|
|
}
|
|
$js_printed_bugnumber = 1;
|
|
}
|
|
}
|