Bug 435739 Poor performance of Firefox 3 with no X RENDER extension
[wine-gecko.git] / testing / tinderbox-standalone-tests / Util.pm
blob2a1d960f71d02e1d6d70b771a6ca264b0e28a074
1 package Util;
3 use Sys::Hostname;
4 use File::Copy;
5 use POSIX qw(sys_wait_h strftime);
7 sub print_log {
8 my ($text) = @_;
9 #print LOG $text;
10 print $text;
13 sub print_logfile {
14 my ($logfile, $test_name) = @_;
15 print "DEBUG: $logfile\n";
16 print_log "----------- Output from $test_name ------------- \n";
17 open READRUNLOG, "$logfile" or die "Can't open log $logfile: $!\n";
18 print_log " $_" while <READRUNLOG>;
19 close READRUNLOG or die "Can't close log $logfile: $!\n";
20 print_log "----------- End Output from $test_name --------- \n";
23 sub print_test_errors {
24 my ($result, $name) = @_;
26 if (not $result->{timed_out} and $result->{exit_value} != 0) {
27 if ($result->{sig_name} ne '') {
28 print_log "Error: $name: received SIG$result->{sig_name}\n";
30 print_log "Error: $name: exited with status $result->{exit_value}\n";
31 if ($result->{dumped_core}) {
32 print_log "Error: $name: dumped core.\n";
37 # Parse a file for $token, return the token.
38 # Look for the line "<token><delimiter><return-value>", e.g.
39 # for "__startuptime,5501"
40 # token = "__startuptime"
41 # delimiter = ","
42 # return-value = "5501";
44 sub extract_token {
45 my ($output, $token, $delimiter) = @_;
46 use Data::Dumper;
47 print Dumper("extract_token: @_");
48 my $token_value = 0;
49 if ($output =~ /$token/) {
50 $token_value = substr($output, index($output, $delimiter) + 1);
51 chomp($token_value);
53 return $token_value;
56 sub run_cmd {
57 my ($home_dir, $binary_dir, $args, $timeout_secs) = @_;
58 my $now = localtime();
59 my $pid = 0;
60 my $shell_command = join(' ', @{$args});
62 my $exit_value = 1;
63 my $signal_num;
64 my $sig_name;
65 my $dumped_core;
66 my $timed_out;
67 my $output;
69 print_log "Begin: $now\n";
70 print_log "cmd = $shell_command\n";
72 eval{
73 # Set XRE_NO_WINDOWS_CRASH_DIALOG to disable showing
74 # the windows crash dialog in case the child process
75 # crashes
76 $ENV{XRE_NO_WINDOWS_CRASH_DIALOG} = 1;
78 # Now cd to dir where binary is..
79 chdir $binary_dir or die "chdir($binary_dir): $!\n";
81 local $SIG{ALRM} = sub { die "alarm" };
82 alarm $timeout_secs;
83 $pid = open CMD, "$shell_command |"
84 or die "Could not run command: $!";
86 while (<CMD>) {
87 $output .= $_;
88 print_log $_;
90 close CMD or die "Could not close command: $!";
91 $exit_value = $? >> 8;
92 $signal_num = $? >> 127;
93 $sig_name = signal_name($signal_num);
94 $dumped_core = $? & 128;
95 $timed_out = 0;
96 alarm 0;
98 if($@){
99 if($@ =~ /alarm/){
100 $timed_out = 1;
101 kill_process($pid);
102 }else{
103 print_log("Error running $shell_command: $@\n");
104 $output = $@;
108 $now = localtime();
109 print_log "End: $now\n";
111 if ($exit_value || $timed_out || $dumped_core || $signal_num){
112 print_log("Error running $shell_command\n");
113 if($output){
114 print_log("Output: $output\n");
116 if ($exit_value) {
117 print_log("Exit value: $exit_value\n");
119 if ($timed_out) {
120 print_log("Timed out\n");
121 # callers expect exit_value to be non-zero if request timed out
122 $exit_value = 1;
124 if ($dumped_core) {
125 print_log("Segfault (core dumped)\n");
127 if ($signal_num) {
128 print_log("Received signal: $sig_name\n");
132 return { timed_out=>$timed_out,
133 exit_value=>$exit_value,
134 sig_name=>$sig_name,
135 output=>$output,
136 dumped_core=>$dumped_core };
140 sub get_system_cwd {
141 my $a = Cwd::getcwd()||`pwd`;
142 chomp($a);
143 return $a;
146 sub get_graph_tbox_name {
147 if ($Settings::GraphNameOverride ne '') {
148 return $Settings::GraphNameOverride;
151 my $name = hostname();
152 if ($Settings::BuildTag ne '') {
153 $name .= '_' . $Settings::BuildTag;
155 return $name;
158 sub print_log_test_result {
159 my ($test_name, $test_title, $num_result, $units, $print_name, $print_result) = @_;
161 print_log "\nTinderboxPrint:";
162 if ($Settings::TestsPhoneHome) {
163 my $time = POSIX::strftime "%Y:%m:%d:%H:%M:%S", localtime;
164 print_log "<a title=\"$test_title\" href=\"http://$Settings::results_server/graph/query.cgi?testname=" . $test_name . "&units=$units&tbox=" . get_graph_tbox_name() . "&autoscale=1&days=7&avg=1&showpoint=$time,$num_result\">";
165 } else {
166 print_log "<abbr title=\"$test_title\">";
168 print_log $print_name;
169 if (!$Settings::TestsPhoneHome) {
170 print_log "</abbr>";
172 print_log ':' . $print_result;
173 if ($Settings::TestsPhoneHome) {
174 print_log "</a>";
176 print_log "\n";
180 sub print_log_test_result_ms {
181 my ($test_name, $test_title, $result, $print_name) = @_;
182 print_log_test_result($test_name, $test_title, $result, 'ms',
183 $print_name, $result . 'ms');
186 sub print_log_test_result_bytes {
187 my ($test_name, $test_title, $result, $print_name, $sig_figs) = @_;
189 print_log_test_result($test_name, $test_title, $result, 'bytes',
190 $print_name, PrintSize($result, $sig_figs) . 'B');
193 sub print_log_test_result_count {
194 my ($test_name, $test_title, $result, $print_name, $sig_figs) = @_;
195 print_log_test_result($test_name, $test_title, $result, 'count',
196 $print_name, PrintSize($result, $sig_figs));
200 # Report test results back to a server.
201 # Netscape-internal now, will push to mozilla.org, ask
202 # mcafee or jrgm for details.
204 # Needs the following perl stubs, installed for rh7.1:
205 # perl-Digest-MD5-2.13-1.i386.rpm
206 # perl-MIME-Base64-2.12-6.i386.rpm
207 # perl-libnet-1.0703-6.noarch.rpm
208 # perl-HTML-Tagset-3.03-3.i386.rpm
209 # perl-HTML-Parser-3.25-2.i386.rpm
210 # perl-URI-1.12-5.noarch.rpm
211 # perl-libwww-perl-5.53-3.noarch.rpm
213 sub send_results_to_server {
214 my ($value, $raw_data, $testname) = @_;
216 # Prepend raw data with cvs checkout date, performance
217 # Use MOZ_CO_DATE, but with same graph/collect.cgi format. (server)
218 #my $data_plus_co_time = "MOZ_CO_DATE=$co_time_str\t$raw_data";
219 my $data_plus_co_time = "MOZ_CO_DATE=test";
220 my $tbox = get_graph_tbox_name();
222 my $tmpurl = "http://$Settings::results_server/graph/collect.cgi";
223 $tmpurl .= "?value=$value&data=$data_plus_co_time&testname=$testname&tbox=$tbox";
225 print_log "send_results_to_server(): \n";
226 print_log "tmpurl = $tmpurl\n";
228 # libwww-perl has process control problems on windows,
229 # spawn wget instead.
230 if ($Settings::OS =~ /^WIN/) {
231 system ("wget", "-O", "/dev/null", $tmpurl);
232 print_log "send_results_to_server() succeeded.\n";
233 } else {
234 my $res = eval q{
235 use LWP::UserAgent;
236 use HTTP::Request;
237 my $ua = LWP::UserAgent->new;
238 $ua->timeout(10); # seconds
239 my $req = HTTP::Request->new(GET => $tmpurl);
240 my $res = $ua->request($req);
241 return $res;
243 if ($@) {
244 warn "Failed to submit startup results: $@";
245 print_log "send_results_to_server() failed.\n";
246 } else {
247 print_log "Results submitted to server: \n" .
248 $res->status_line . "\n" . $res->content . "\n";
249 print_log "send_results_to_server() succeeded.\n";
254 sub kill_process {
255 my ($target_pid) = @_;
256 my $start_time = time;
258 # Try to kill and wait 10 seconds, then try a kill -9
259 my $sig;
260 for $sig ('TERM', 'KILL') {
261 print "kill $sig $target_pid\n";
262 kill $sig => $target_pid;
263 my $interval_start = time;
264 while (time - $interval_start < 10) {
265 # the following will work with 'cygwin' perl on win32, but not
266 # with 'MSWin32' (ActiveState) perl
267 my $pid = waitpid($target_pid, POSIX::WNOHANG());
268 if (($pid == $target_pid and POSIX::WIFEXITED($?)) or $pid == -1) {
269 my $secs = time - $start_time;
270 $secs = $secs == 1 ? '1 second' : "$secs seconds";
271 print_log "Process killed. Took $secs to die.\n";
272 return;
274 sleep 1;
277 die "Unable to kill process: $target_pid";
280 BEGIN {
281 my %sig_num = ();
282 my @sig_name = ();
284 sub signal_name {
285 # Find the name of a signal number
286 my ($number) = @_;
288 unless (@sig_name) {
289 unless($Config::Config{sig_name} && $Config::Config{sig_num}) {
290 die "No sigs?";
291 } else {
292 my @names = split ' ', $Config::Config{sig_name};
293 @sig_num{@names} = split ' ', $Config::Config{sig_num};
294 foreach (@names) {
295 $sig_name[$sig_num{$_}] ||= $_;
299 return $sig_name[$number];
303 sub PercentChange($$) {
304 my ($old, $new) = @_;
305 if ($old == 0) {
306 return 0;
308 return ($new - $old) / $old;
311 # Print a value of bytes out in a reasonable
312 # KB, MB, or GB form. Sig figs should probably
313 # be 3, 4, or 5 for most purposes here. This used
314 # to default to 3 sig figs, but I wanted 4 so I
315 # generalized here. -mcafee
317 # Usage: PrintSize(valueAsInteger, numSigFigs)
319 sub PrintSize($$) {
321 # print a number with 3 significant figures
322 sub PrintNum($$) {
323 my ($num, $sigs) = @_;
324 my $rv;
326 # Figure out how many decimal places to show.
327 # Only doing a few cases here, for normal range
328 # of test numbers.
330 # Handle zero case first.
331 if ($num == 0) {
332 $rv = "0";
333 } elsif ($num < 10**($sigs-5)) {
334 $rv = sprintf "%.5f", ($num);
335 } elsif ($num < 10**($sigs-4)) {
336 $rv = sprintf "%.4f", ($num);
337 } elsif ($num < 10**($sigs-3)) {
338 $rv = sprintf "%.3f", ($num);
339 } elsif ($num < 10**($sigs-2)) {
340 $rv = sprintf "%.2f", ($num);
341 } elsif ($num < 10**($sigs-1)) {
342 $rv = sprintf "%.1f", ($num);
343 } else {
344 $rv = sprintf "%d", ($num);
349 my ($size, $sigfigs) = @_;
351 # 1K = 1024, previously this was approximated as 1000.
352 my $rv;
353 if ($size > 1073741824) { # 1024^3
354 $rv = PrintNum($size / 1073741824.0, $sigfigs) . "G";
355 } elsif ($size > 1048576) { # 1024^2
356 $rv = PrintNum($size / 1048576.0, $sigfigs) . "M";
357 } elsif ($size > 1024) {
358 $rv = PrintNum($size / 1024.0, $sigfigs) . "K";
359 } else {
360 $rv = PrintNum($size, $sigfigs);
364 # Page loader (-f option):
365 # If you are building optimized, you need to add
366 # --enable-trace-malloc --enable-perf-metrics
367 # to turn the pageloader code on. If you are building debug you only
368 # need
369 # --enable-trace-malloc
372 sub ReadLeakstatsLog($) {
373 my ($filename) = @_;
374 my $leaks = 0;
375 my $leaked_allocs = 0;
376 my $mhs = 0;
377 my $bytes = 0;
378 my $allocs = 0;
380 open LEAKSTATS, "$filename"
381 or die "unable to open $filename";
382 while (<LEAKSTATS>) {
383 chop;
384 my $line = $_;
385 if ($line =~ /Leaks: (\d+) bytes, (\d+) allocations/) {
386 $leaks = $1;
387 $leaked_allocs = $2;
388 } elsif ($line =~ /Maximum Heap Size: (\d+) bytes/) {
389 $mhs = $1;
390 } elsif ($line =~ /(\d+) bytes were allocated in (\d+) allocations./) {
391 $bytes = $1;
392 $allocs = $2;
396 return {
397 'leaks' => $leaks,
398 'leaked_allocs' => $leaked_allocs,
399 'mhs' => $mhs,
400 'bytes' => $bytes,
401 'allocs' => $allocs