]>
Commit | Line | Data |
---|---|---|
b37bf2e1 A |
1 | #!/tools/ns/bin/perl5 |
2 | # | |
3 | # simple script that executes JavaScript tests. you have to build the | |
4 | # stand-alone, js shell executable (which is not the same as the dll that gets | |
5 | # built for mozilla). see the readme at | |
6 | # http://lxr.mozilla.org/mozilla/source/js/src/README.html for instructions on | |
7 | # how to build the jsshell. | |
8 | # | |
9 | # this is just a quick-n-dirty script. for full reporting, you need to run | |
10 | # the test driver, which requires java and is currently not available on | |
11 | # mozilla.org. | |
12 | # | |
13 | # this test looks for an executable JavaScript shell in | |
14 | # %MOZ_SRC/mozilla/js/src/[platform]-[platform-version]-OPT.OBJ/js, | |
15 | # which is the default build location when you build using the instructions | |
16 | # at http://lxr.mozilla.org/mozilla/source/js/src/README.html | |
17 | # | |
18 | # | |
19 | # christine@netscape.com | |
20 | # | |
21 | ||
22 | &parse_args; | |
23 | &setup_env; | |
24 | &main_test_loop; | |
25 | &cleanup_env; | |
26 | ||
27 | # | |
28 | # given a main directory, assume that there is a file called 'shell.js' | |
29 | # in it. then, open all the subdirectories, and look for js files. | |
30 | # for each test.js that is found, execute the shell, and pass shell.js | |
31 | # and the test.js as file arguments. redirect all process output to a | |
32 | # file. | |
33 | # | |
34 | sub main_test_loop { | |
35 | foreach $suite ( &get_subdirs( $test_dir )) { | |
36 | foreach $subdir (&get_subdirs( $suite, $test_dir )) { | |
37 | @jsfiles = &get_js_files($subdir); | |
38 | execute_js_tests(@jsfiles); | |
39 | } | |
40 | } | |
41 | } | |
42 | ||
43 | # | |
44 | # given a directory, return an array of all subdirectories | |
45 | # | |
46 | sub get_subdirs{ | |
47 | local ($dir, $path) = @_; | |
48 | local @subdirs; | |
49 | ||
50 | local $dir_path = $path . $dir; | |
51 | chdir $dir_path; | |
52 | ||
53 | opendir ( DIR, ${dir_path} ); | |
54 | local @testdir_contents = readdir( DIR ); | |
55 | closedir( DIR ); | |
56 | ||
57 | foreach (@testdir_contents) { | |
58 | if ( (-d $_) && ($_ !~ 'CVS') && ( $_ ne '.') && ($_ ne '..')) { | |
59 | @subdirs[$#subdirs+1] = $_; | |
60 | } | |
61 | } | |
62 | chdir $path; | |
63 | return @subdirs; | |
64 | } | |
65 | ||
66 | # | |
67 | # given a directory, return an array of all the js files that are in it. | |
68 | # | |
69 | sub get_js_files { | |
70 | ( $test_subdir ) = @_; | |
71 | local @js_file_array; | |
72 | ||
73 | $current_test_dir = $test_dir ."/". $suite . "/" .$test_subdir; | |
74 | chdir $current_test_dir; | |
75 | ||
76 | opendir ( TEST_SUBDIR, ${current_test_dir} ); | |
77 | @subdir_files = readdir( TEST_SUBDIR ); | |
78 | closedir( TOP_LEVEL_BUILD_DIR ); | |
79 | ||
80 | foreach ( @subdir_files ) { | |
81 | if ( $_ =~ /\.js$/ ) { | |
82 | $js_file_array[$#js_file_array+1] = $_; | |
83 | } | |
84 | } | |
85 | ||
86 | return @js_file_array; | |
87 | } | |
88 | ||
89 | # | |
90 | # given an array of test.js files, execute the shell command and pass | |
91 | # the shell.js and test.js files as file arguments. redirect process | |
92 | # output to a file. if $js_verbose is set (not recommended), write all | |
93 | # testcase output to the output file. if $js_quiet is set, only write | |
94 | # failed test case information to the output file. the default setting | |
95 | # is to write a line for each test file, and whether each file passed | |
96 | # or failed. | |
97 | # | |
98 | sub execute_js_tests { | |
99 | (@js_file_array) = @_; | |
100 | ||
101 | $js_printed_suitename = 0; | |
102 | if ( !$js_quiet ) { | |
103 | &js_print_suitename; | |
104 | } | |
105 | ||
106 | foreach $js_test (@js_file_array) { | |
107 | $js_printed_filename = 0; | |
108 | $js_test_bugnumber = 0; | |
109 | $runtime_error = ""; | |
110 | ||
111 | local $passed = -1; | |
112 | ||
113 | # create the test command | |
114 | $test_command = | |
115 | $shell_command . | |
116 | " -f $test_dir/$suite/shell.js " . | |
117 | " -f $test_dir/$suite/$subdir/$js_test"; | |
118 | ||
119 | if ( !$js_quiet ) { | |
120 | &js_print_filename; | |
121 | } else { | |
122 | print '.'; | |
123 | } | |
124 | ||
125 | $test_path = $test_dir ."/" . $suite ."/". $test_subdir ."/". $js_test; | |
126 | ||
127 | ||
128 | if ( !-e $test_path ) { | |
129 | &js_print( " FAILED! file not found\n", | |
130 | "<font color=#990000>", "</font><br>\n"); | |
131 | } else { | |
132 | open( RUNNING_TEST, "$test_command" . ' 2>&1 |'); | |
133 | ||
134 | ||
135 | # this is where we want the tests to provide a lot more information | |
136 | # that this script must parse so that we can | |
137 | ||
138 | while( <RUNNING_TEST> ){ | |
139 | if ( $js_verbose && !$js_quiet ) { | |
140 | &js_print ($_ ."\n", "", "<br>\n"); | |
141 | } | |
142 | if ( $_ =~ /BUGNUMBER/ ) { | |
143 | $js_test_bugnumber = $_; | |
144 | } | |
145 | if ( $_ =~ /PASSED/ && $passed == -1 ) { | |
146 | $passed = 1; | |
147 | } | |
148 | if ( $_ =~ /FAILED/ && $_ =~ /expected/) { | |
149 | &js_print_suitename; | |
150 | &js_print_filename; | |
151 | &js_print_bugnumber; | |
152 | ||
153 | local @msg = split ( "FAILED", $_ ); | |
154 | &js_print ( $passed ? "\n" : "" ); | |
155 | &js_print( " " . $msg[0], " <tt>" ); | |
156 | &js_print( "FAILED", "<font color=#990000>", "</font>"); | |
157 | &js_print( $msg[1], "", "</tt><br>\n" ); | |
158 | $passed = 0; | |
159 | } | |
160 | if ( $_ =~ /$js_test/ ) { | |
161 | $runtime_error .= $_; | |
162 | } | |
163 | } | |
164 | close( RUNNING_TEST ); | |
165 | ||
166 | # | |
167 | # figure out whether the test passed or failed. print out an | |
168 | # appropriate level of output based on the value of $js_quiet | |
169 | # | |
170 | if ( $js_test =~ /-n\.js$/ ) { | |
171 | if ( $runtime_error ) { | |
172 | if ( !$js_quiet ) { | |
173 | &js_print( " PASSED!\n ", | |
174 | "<font color=#009900>  ", | |
175 | "</font><br>" ); | |
176 | if ( $js_errors ) { | |
177 | &js_print( $runtime_error, "<pre>", "</pre>"); | |
178 | } | |
179 | } | |
180 | } else { | |
181 | &js_print_suitename; | |
182 | &js_print_filename; | |
183 | &js_print_bugnumber; | |
184 | &js_print( " FAILED! ", " <font color=#990000>", | |
185 | "</font>"); | |
186 | &js_print( " Should have resulted in an error\n", | |
187 | "","<br>" ); | |
188 | } | |
189 | } else { | |
190 | if ( $passed == 1 && !$js_quiet) { | |
191 | &js_print( " PASSED!\n " , " <font color=#009900>", | |
192 | "</font><br>" ); | |
193 | } else { | |
194 | if ($passed == -1) { | |
195 | &js_print_suitename; | |
196 | &js_print_filename; | |
197 | &js_print_bugnumber; | |
198 | &js_print( " FAILED!\n " , " <font color=#990000>", | |
199 | "</font><br>" ); | |
200 | &js_print( " Missing 'PASSED' in output\n", "","<br>" ); | |
201 | &js_print( $log, "output:<br><pre>", "</pre>" ); | |
202 | } | |
203 | } | |
204 | ||
205 | } | |
206 | } | |
207 | } | |
208 | } | |
209 | ||
210 | # | |
211 | # figure out what os we're on, the default name of the object directory | |
212 | # | |
213 | sub setup_env { | |
214 | # MOZ_SRC must be set, so we can figure out where the | |
215 | # JavaScript executable is | |
216 | $moz_src = $ENV{"MOZ_SRC"} | |
217 | || die( "You need to set your MOZ_SRC environment variable.\n" ); | |
218 | $src_dir = $moz_src . '/mozilla/js/src/'; | |
219 | ||
220 | # JS_TEST_DIR must be set so we can figure out where the tests are. | |
221 | $test_dir = $ENV{"JS_TEST_DIR"}; | |
222 | ||
223 | # if it's not set, look for it relative to $moz_src | |
224 | if ( !$test_dir ) { | |
225 | $test_dir = $moz_src . '/mozilla/js/tests/'; | |
226 | } | |
227 | ||
228 | # make sure that the test dir exists | |
229 | if ( ! -e $test_dir ) { | |
230 | die "The JavaScript Test Library could not be found at $test_dir.\n" . | |
231 | "Check the tests out from /mozilla/js/tests or\n" . | |
232 | "Set the value of your JS_TEST_DIR environment variable\n " . | |
233 | "to the location of the test library.\n"; | |
234 | } | |
235 | ||
236 | # make sure that the test dir ends with a trailing slash | |
237 | $test_dir .= '/'; | |
238 | ||
239 | chdir $src_dir; | |
240 | ||
241 | # figure out which platform we're on, and figure out where the object | |
242 | # directory is | |
243 | ||
244 | $machine_os = `uname -s`; | |
245 | ||
246 | if ( $machine_os =~ /WIN/ ) { | |
247 | $machine_os = 'WIN'; | |
248 | $object_dir = ($js_debug) ? 'Debug' : 'Release'; | |
249 | $js_exe = 'jsshell.exe'; | |
250 | } else { | |
251 | chop $machine_os; | |
252 | $js_exe = 'js'; | |
253 | ||
254 | # figure out what the object directory is. on all platforms, | |
255 | # it's the directory that ends in OBJ. if $js_debug is set, | |
256 | # look the directory that ends with or DBG.OBJ; otherwise | |
257 | # look for the directory that ends with OPT.OBJ | |
258 | ||
259 | opendir ( SRC_DIR_FILES, $src_dir ); | |
260 | @src_dir_files = readdir( SRC_DIR_FILES ); | |
261 | closedir ( SRC_DIR_FILES ); | |
262 | ||
263 | $object_pattern = $js_debug ? 'DBG.OBJ' : 'OPT.OBJ'; | |
264 | ||
265 | foreach (@src_dir_files) { | |
266 | if ( $_ =~ /$object_pattern/ && $_ =~ $machine_os) { | |
267 | $object_dir = $_; | |
268 | } | |
269 | } | |
270 | } | |
271 | if ( ! $object_dir ) { | |
272 | die( "Couldn't find an object directory in $src_dir.\n" ); | |
273 | } | |
274 | ||
275 | # figure out what the name of the javascript executable should be, and | |
276 | # make sure it's there. if it's not there, give a helpful message so | |
277 | # the user can figure out what they need to do next. | |
278 | ||
279 | ||
280 | if ( ! $js_exe_full_path ) { | |
281 | $shell_command = $src_dir . $object_dir .'/'. $js_exe; | |
282 | } else { | |
283 | $shell_command = $js_exe_full_path; | |
284 | } | |
285 | ||
286 | if ( !-e $shell_command ) { | |
287 | die ("Could not find JavaScript shell executable $shell_command.\n" . | |
288 | "Check the value of your MOZ_SRC environment variable.\n" . | |
289 | "Currently, MOZ_SRC is set to $ENV{\"MOZ_SRC\"}\n". | |
290 | "See the readme at http://lxr.mozilla.org/mozilla/src/js/src/ " . | |
291 | "for instructions on building the JavaScript shell.\n" ); | |
292 | } | |
293 | ||
294 | # set the output file name. let's base its name on the date and platform, | |
295 | # and give it a sequence number. | |
296 | ||
297 | if ( $get_output ) { | |
298 | $js_output = &get_output; | |
299 | } | |
300 | if ($js_output) { | |
301 | print( "Writing results to $js_output\n" ); | |
302 | chdir $test_dir; | |
303 | open( JS_OUTPUT, "> ${js_output}" ) || | |
304 | die "Can't open log file $js_output\n"; | |
305 | close JS_OUTPUT; | |
306 | } | |
307 | ||
308 | # get the start time | |
309 | $start_time = time; | |
310 | ||
311 | # print out some nice stuff | |
312 | $start_date = &get_date; | |
313 | &js_print( "JavaScript tests started: " . $start_date, "<p><tt>", "</tt></p>" ); | |
314 | ||
315 | &js_print ("Executing all the tests under $test_dir\n against " . | |
316 | "$shell_command\n", "<p><tt>", "</tt></p>" ); | |
317 | } | |
318 | ||
319 | # | |
320 | # parse arguments. see usage for what arguments are expected. | |
321 | # | |
322 | sub parse_args { | |
323 | $i = 0; | |
324 | while( $i < @ARGV ){ | |
325 | if ( $ARGV[$i] eq '--threaded' ) { | |
326 | $js_threaded = 1; | |
327 | } elsif ( $ARGV[$i] eq '--d' ) { | |
328 | $js_debug = 1; | |
329 | } elsif ( $ARGV[$i] eq '--14' ) { | |
330 | $js_version = '14'; | |
331 | } elsif ( $ARGV[$i] eq '--v' ) { | |
332 | $js_verbose = 1; | |
333 | } elsif ( $ARGV[$i] eq '-f' ) { | |
334 | $js_output = $ARGV[++$i]; | |
335 | } elsif ( $ARGV[$i] eq '--o' ) { | |
336 | $get_output = 1; | |
337 | } elsif ($ARGV[$i] eq '--e' ) { | |
338 | $js_errors = 1; | |
339 | } elsif ($ARGV[$i] eq '--q' ) { | |
340 | $js_quiet = 1; | |
341 | } elsif ($ARGV[$i] eq '--h' ) { | |
342 | die &usage; | |
343 | } elsif ( $ARGV[$i] eq '-E' ) { | |
344 | $js_exe_full_path = $ARGV[$i+1]; | |
345 | $i++; | |
346 | } else { | |
347 | die &usage; | |
348 | } | |
349 | $i++; | |
350 | } | |
351 | ||
352 | # | |
353 | # if no output options are provided, show some output and write to file | |
354 | # | |
355 | if ( !$js_verbose && !$js_output && !$get_output ) { | |
356 | $get_output = 1; | |
357 | } | |
358 | } | |
359 | ||
360 | # | |
361 | # print the arguments that this script expects | |
362 | # | |
363 | sub usage { | |
364 | die ("usage: $0\n" . | |
365 | "--q Quiet mode -- only show information for tests that failed\n". | |
366 | "--e Show runtime error messages for negative tests\n" . | |
367 | "--v Verbose output -- show all test cases (not recommended)\n" . | |
368 | "--o Send output to file whose generated name is based on date\n". | |
369 | "--d Look for a debug JavaScript executable (default is optimized)\n" . | |
370 | "-f <file> Redirect output to file named <file>\n" | |
371 | ); | |
372 | } | |
373 | ||
374 | # | |
375 | # if $js_output is set, print to file as well as stdout | |
376 | # | |
377 | sub js_print { | |
378 | ($string, $start_tag, $end_tag) = @_; | |
379 | ||
380 | if ($js_output) { | |
381 | open( JS_OUTPUT, ">> ${js_output}" ) || | |
382 | die "Can't open log file $js_output\n"; | |
383 | ||
384 | print JS_OUTPUT "$start_tag $string $end_tag"; | |
385 | close JS_OUTPUT; | |
386 | } | |
387 | print $string; | |
388 | } | |
389 | ||
390 | # | |
391 | # close open files | |
392 | # | |
393 | sub cleanup_env { | |
394 | # print out some nice stuff | |
395 | $end_date = &get_date; | |
396 | &js_print( "\nTests complete at $end_date", "<hr><tt>", "</tt>" ); | |
397 | ||
398 | # print out how long it took to complete | |
399 | $end_time = time; | |
400 | ||
401 | $test_seconds = ( $end_time - $start_time ); | |
402 | ||
403 | &js_print( "Start Date: $start_date\n", "<tt><br>" ); | |
404 | &js_print( "End Date: $end_date\n", "<br>" ); | |
405 | &js_print( "Test Time: $test_seconds seconds\n", "<br>" ); | |
406 | ||
407 | if ($js_output ) { | |
408 | if ( !$js_verbose) { | |
409 | &js_print( "Results were written to " . $js_output ."\n", | |
410 | "<br>", "</tt>" ); | |
411 | } | |
412 | close JS_OUTPUT; | |
413 | } | |
414 | } | |
415 | ||
416 | ||
417 | # | |
418 | # get the current date and time | |
419 | # | |
420 | sub get_date { | |
421 | &get_localtime; | |
422 | $now = $year ."/". $mon ."/". $mday ." ". $hour .":". | |
423 | $min .":". $sec ."\n"; | |
424 | return $now; | |
425 | ||
426 | } | |
427 | sub get_localtime { | |
428 | ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = | |
429 | localtime; | |
430 | $mon++; | |
431 | $mon = &zero_pad($mon); | |
432 | $year= ($year < 2000) ? "19" . $year : $year; | |
433 | $mday= &zero_pad($mday); | |
434 | $sec = &zero_pad($sec); | |
435 | $min = &zero_pad($min); | |
436 | $hour = &zero_pad($hour); | |
437 | } | |
438 | sub zero_pad { | |
439 | local ($string) = @_; | |
440 | $string = ($string < 10) ? "0" . $string : $string; | |
441 | return $string; | |
442 | } | |
443 | ||
444 | # | |
445 | # generate an output file name based on the date | |
446 | # | |
447 | sub get_output { | |
448 | &get_localtime; | |
449 | ||
450 | chdir $test_dir; | |
451 | ||
452 | $js_output = $test_dir ."/". $year .'-'. $mon .'-'. $mday ."\.1.html"; | |
453 | ||
454 | $output_file_found = 0; | |
455 | ||
456 | while ( !$output_file_found ) { | |
457 | if ( -e $js_output ) { | |
458 | # get the last sequence number - everything after the dot | |
459 | @seq_no = split( /\./, $js_output, 2 ); | |
460 | $js_output = $seq_no[0] .".". (++$seq_no[1]) . "\.html"; | |
461 | } else { | |
462 | $output_file_found = 1; | |
463 | } | |
464 | } | |
465 | return $js_output; | |
466 | } | |
467 | ||
468 | sub js_print_suitename { | |
469 | if ( !$js_printed_suitename ) { | |
470 | &js_print( "$suite\\$subdir\n", "<hr><font size+=1><b>", | |
471 | "</font></b><br>" ); | |
472 | } | |
473 | $js_printed_suitename = 1; | |
474 | } | |
475 | ||
476 | sub js_print_filename { | |
477 | if ( !$js_printed_filename ) { | |
478 | &js_print( "$js_test\n", "<b>", "</b><br>" ); | |
479 | $js_printed_filename = 1; | |
480 | } | |
481 | } | |
482 | ||
483 | sub js_print_bugnumber { | |
484 | if ( !$js_printed_bugnumber ) { | |
485 | if ( $js_bugnumber =~ /^http/ ) { | |
486 | &js_print( "$js_bugnumber", "<a href=$js_bugnumber>", "</a>" ); | |
487 | } else { | |
488 | &js_print( "$js_bugnumber", | |
489 | "<a href=http://scopus.mcom.com/bugsplat/show_bug.cgi?id=" . | |
490 | $js_bugnumber .">", | |
491 | "</a>" ); | |
492 | } | |
493 | $js_printed_bugnumber = 1; | |
494 | } | |
495 | } |