4 # Script to supervise the execution of wvtest-based tests.
6 # It takes care of killing test (qemu or serial reader) when the test
9 # Copyright (C) 2011, 2012, Michal Sojka <sojka@os.inf.tu-dresden.de>
10 # Economic rights: Technische Universitaet Dresden (Germany)
12 # This file is part of NUL (NOVA user land).
14 # NUL is free software: you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License version
16 # 2 as published by the Free Software Foundation.
18 # NUL is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # General Public License version 2 for more details.
30 my $istty = -t STDOUT && $ENV{'TERM'} ne "dumb";
31 my $pty = new IO::Pty;
34 die "Cannot fork" if not defined $pid;
37 $pty->make_slave_controlling_terminal();
38 # setpgrp(); # Terminal won't send signals to the child
39 my $slave = $pty->slave();
41 $slave->clone_winsize_from(\*STDIN) if $istty;
44 open(STDIN,"<&". $slave->fileno())
45 or die "Couldn't reopen STDIN for reading, $!\n";
46 open(STDOUT,">&". $slave->fileno())
47 or die "Couldn't reopen STDOUT for writing, $!\n";
48 open(STDERR,">&". $slave->fileno())
49 or die "Couldn't reopen STDERR for writing, $!\n";
54 die "Cannot exec(@ARGV): $!";
58 #$pty->set_raw(); # from IO::Pty "try" script. Do we need this?
61 $pty->slave->clone_winsize_from(\*STDIN);
62 kill WINCH => $pid if $pid;
63 $SIG{WINCH} = \&winch;
66 $SIG{WINCH} = \&winch if $istty;
71 ($pid > 0) || die("pid is '$pid'?!\n");
73 local $SIG{CHLD} = sub { }; # this will wake us from sleep() faster
74 $count = kill -15, $pid;
77 kill -9, $pid if ($pid > 1);
85 local $SIG{INT} = sub { bigkill($pid); };
86 local $SIG{TERM} = sub { bigkill($pid); };
87 local $SIG{ALRM} = sub {
88 print STDERR "! $0: Alarm timed out! No test output for $timeout seconds. FAILED\n";
92 my $allstart = time();
94 my $tests_executed = 0;
96 my $waits_for_child = 0;
98 my $ignore_exit_patterns = 0;
99 my $expected_test_count = 0;
100 my $expected_test_base = 0;
102 sub matches_exit_pattern($)
104 return 0 if $ignore_exit_patterns;
105 if ($ENV{WVTEST_EXIT_PATTERN}) {
106 return /$ENV{WVTEST_EXIT_PATTERN}/
109 (/sc: done.$/ && $waits_for_child) ||
110 /resetting machine via method/ ||
111 /wvtest: done\s*$/ ||
112 / # .*System halted. *$/
117 sub check_number_of_tests()
119 if ($expected_test_count) {
120 my $executed = $tests_executed - $expected_test_base;
122 if ($executed == $expected_test_count) {
127 print "Expected $expected_test_count tests, executed $executed tests.\n"
129 print "! $0: tests_expected == tests_executed $result\n";
134 if ($ENV{WVTEST_OUTPUT}) {
135 open $wvtest_output, ">", $ENV{WVTEST_OUTPUT};
143 print $wvtest_output $_ if $wvtest_output;
147 if (/^(\([0-9]+\) (# )?)?!\s*(.*?)\s+(\S+)\s*$/) {
149 $tests_failed++ if ($4 ne "ok");
151 elsif (/wvtest: timeout (\d+)\s*$/) {
155 elsif (/sc: wait for child/) { $waits_for_child = 1; }
156 elsif (/wvtest: ignore exit patterns/) { $ignore_exit_patterns = 1; }
157 elsif (/wvtest: expect ([0-9]+) tests/) {
158 check_number_of_tests();
159 $expected_test_count = $1;
160 $expected_test_base = $tests_executed;
162 elsif (matches_exit_pattern($_))
164 if (!$ENV{WVTEST_NOKILL}) {
165 kill 15, $pid; # Kill novaboot or qemu
171 print "Keeping PID $pid alive\n";
172 print $wvtest_output "Keeping PID $pid alive\n" if $wvtest_output;
173 close($wvtest_output) if $wvtest_output;
176 # Continue printing on background
177 close($wvtest_output) if $wvtest_output;
178 while (<$pty>) { print; }
184 my $newpid = waitpid($pid, 0);
185 if ($newpid != $pid) {
186 die("waitpid returned '$newpid', expected '$pid'\n");
190 my $ret = ($code >> 8);
192 if ($code && !$ret) {
193 if ($kill_ok && $code == 15) {
194 # We have killed the child - it is OK
197 # return death-from-signal exits as >128. This is what bash does if you ran
198 # the program directly.
204 print "! $0: Program '", join(" ", @ARGV), "' returned non-zero exit code ($ret) FAILED\n";
207 if (!$ENV{WVTEST_EXIT_PATTERN}) {
208 printf "! $0: \$tests_executed > 0 %s\n", ($tests_executed > 0) ? "ok" : "FAILED";
210 check_number_of_tests();
212 if ($tests_failed > 0) { $ret = 1; }
213 if ($ret == 0 && $tests_executed == 0) { $ret = 1; }