r24887: Support reading testlists from other locations (e.g. Samba3)
[samba.git] / source4 / selftest / selftest.pl
1 #!/usr/bin/perl
2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org>
4 # Published under the GNU GPL, v3 or later.
5
6 =pod
7
8 =head1 NAME
9
10 selftest - Samba test runner
11
12 =head1 SYNOPSIS
13
14 selftest --help
15
16 selftest [--srcdir=DIR] [--builddir=DIR] [--target=samba4|samba3|win] [--socket-wrapper] [--quick] [--one] [--prefix=prefix] [--immediate] [TESTS]
17
18 =head1 DESCRIPTION
19
20 A simple test runner. TESTS is a regular expression with tests to run.
21
22 =head1 OPTIONS
23
24 =over 4
25
26 =item I<--help>
27
28 Show list of available options.
29
30 =item I<--srcdir=DIR>
31
32 Source directory.
33
34 =item I<--builddir=DIR>
35
36 Build directory.
37
38 =item I<--prefix=DIR>
39
40 Change directory to run tests in. Default is 'st'.
41
42 =item I<--immediate>
43
44 Show errors as soon as they happen rather than at the end of the test run.
45                 
46 =item I<--target samba4|samba3|win>
47
48 Specify test target against which to run. Default is 'samba4'.
49
50 =item I<--quick>
51
52 Run only a limited number of tests. Intended to run in about 30 seconds on 
53 moderately recent systems.
54                 
55 =item I<--socket-wrapper>
56
57 Use socket wrapper library for communication with server. Only works 
58 when the server is running locally.
59
60 Will prevent TCP and UDP ports being opened on the local host but 
61 (transparently) redirects these calls to use unix domain sockets.
62
63 =item I<--expected-failures>
64
65 Specify a file containing a list of tests that are expected to fail. Failures for 
66 these tests will be counted as successes, successes will be counted as failures.
67
68 The format for the file is, one entry per line:
69
70 TESTSUITE-NAME/TEST-NAME
71
72 =item I<--skip>
73
74 Specify a file containing a list of tests that should be skipped. Possible candidates are
75 tests that segfault the server, flip or don't end.
76
77 =item I<--one>
78
79 Abort as soon as one test fails.
80
81 =back
82
83 =head1 ENVIRONMENT
84
85 =over 4
86
87 =item I<SMBD_VALGRIND>
88
89 =item I<TORTURE_MAXTIME>
90
91 =item I<VALGRIND>
92
93 =item I<TLS_ENABLED>
94
95 =item I<srcdir>
96
97 =back
98
99 =head1 LICENSE
100
101 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
102
103 =head1 AUTHOR
104
105 Jelmer Vernooij
106
107 =cut
108
109 use strict;
110
111 use FindBin qw($RealBin $Script);
112 use File::Spec;
113 use Getopt::Long;
114 use POSIX;
115 use Cwd qw(abs_path);
116 use lib "$RealBin";
117 use Subunit qw(parse_results);
118 use env::Samba3;
119 use env::Samba4;
120 use env::Windows;
121 use SocketWrapper;
122
123 my $opt_help = 0;
124 my $opt_target = "samba4";
125 my $opt_quick = 0;
126 my $opt_socket_wrapper = 0;
127 my $opt_socket_wrapper_pcap = undef;
128 my $opt_socket_wrapper_keep_pcap = undef;
129 my $opt_one = 0;
130 my $opt_immediate = 0;
131 my $opt_expected_failures = undef;
132 my $opt_skip = undef;
133 my $opt_verbose = 0;
134 my $opt_testenv = 0;
135 my $ldap = undef;
136 my $opt_analyse_cmd = undef;
137 my $opt_resetup_env = undef;
138 my $opt_bindir = undef;
139 my $opt_no_lazy_setup = undef;
140 my $opt_format = "plain";
141 my @opt_testlists = ();
142
143 my $srcdir = ".";
144 my $builddir = ".";
145 my $prefix = "./st";
146
147 my @expected_failures = ();
148 my @skips = ();
149
150 my $statistics = {
151         START_TIME => time(),
152
153         SUITES_FAIL => 0,
154         SUITES_OK => 0,
155         SUITES_SKIPPED => 0,
156
157         TESTS_UNEXPECTED_OK => 0,
158         TESTS_EXPECTED_OK => 0,
159         TESTS_UNEXPECTED_FAIL => 0,
160         TESTS_EXPECTED_FAIL => 0,
161         TESTS_ERROR => 0,
162         TESTS_SKIP => 0,
163 };
164
165 sub find_in_list($$)
166 {
167         my ($list, $fullname) = @_;
168
169         foreach (@$list) {
170                 if ($fullname =~ /$$_[0]/) {
171                          return ($$_[1]) if ($$_[1]);
172                          return "NO REASON SPECIFIED";
173                 }
174         }
175
176         return undef;
177 }
178
179 sub expecting_failure($)
180 {
181         my ($name) = @_;
182         return find_in_list(\@expected_failures, $name);
183 }
184
185 sub skip($)
186 {
187         my ($name) = @_;
188         return find_in_list(\@skips, $name);
189 }
190
191 sub getlog_env($);
192
193 sub setup_pcap($)
194 {
195         my ($state) = @_;
196
197         return unless ($opt_socket_wrapper_pcap);
198         return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
199
200         my $fname = sprintf("t%03u_%s", $state->{INDEX}, $state->{NAME});
201         $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
202
203         $state->{PCAP_FILE} = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
204
205         SocketWrapper::setup_pcap($state->{PCAP_FILE});
206 }
207
208 sub cleanup_pcap($$$)
209 {
210         my ($state, $expected_ret, $ret) = @_;
211
212         return unless ($opt_socket_wrapper_pcap);
213         return if ($opt_socket_wrapper_keep_pcap);
214         return unless ($expected_ret == $ret);
215         return unless defined($state->{PCAP_FILE});
216
217         unlink($state->{PCAP_FILE});
218         $state->{PCAP_FILE} = undef;
219 }
220
221 sub run_testsuite($$$$$$)
222 {
223         my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
224         my $msg_state = {
225                 ENVNAME => $envname,
226                 NAME    => $name,
227                 CMD     => $cmd,
228                 INDEX   => $i,
229                 TOTAL   => $totalsuites,
230                 START_TIME      => time()
231         };
232
233         setup_pcap($msg_state);
234
235         open(RESULT, "$cmd 2>&1|");
236         $msg_ops->start_testsuite($msg_state);
237
238         my $expected_ret = parse_results(
239                 $msg_ops, $msg_state, $statistics, *RESULT, \&expecting_failure);
240
241         my $ret = close(RESULT);
242
243         cleanup_pcap($msg_state, $expected_ret, $ret);
244
245         $msg_ops->end_testsuite($msg_state, $expected_ret, $ret,
246                                                         getlog_env($msg_state->{ENVNAME}));
247
248         if (not $opt_socket_wrapper_keep_pcap and 
249                 defined($msg_state->{PCAP_FILE})) {
250                 $msg_ops->output_msg($msg_state, 
251                         "PCAP FILE: $msg_state->{PCAP_FILE}\n");
252         }
253
254         if ($ret != $expected_ret) {
255                 $statistics->{SUITES_FAIL}++;
256                 exit(1) if ($opt_one);
257         } else {
258                 $statistics->{SUITES_OK}++;
259         }
260
261         return ($ret == $expected_ret);
262 }
263
264 sub ShowHelp()
265 {
266         print "Samba test runner
267 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
268
269 Usage: $Script [OPTIONS] PREFIX
270
271 Generic options:
272  --help                     this help page
273  --target=samba4|samba3|win Samba version to target
274  --testlist=FILE                        file to read available tests from
275
276 Paths:
277  --prefix=DIR               prefix to run tests in [st]
278  --srcdir=DIR               source directory [.]
279  --builddir=DIR             output directory [.]
280
281 Target Specific:
282  --socket-wrapper-pcap=DIR      save traffic to pcap directories
283  --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that 
284                             failed
285  --socket-wrapper           enable socket wrapper
286  --expected-failures=FILE   specify list of tests that is guaranteed to fail
287
288 Samba4 Specific:
289  --ldap=openldap|fedora-ds     back smbd onto specified ldap server
290
291 Samba3 Specific:
292  --bindir=PATH              path to binaries
293
294 Behaviour:
295  --quick                    run quick overall test
296  --one                      abort when the first test fails
297  --immediate                print test output for failed tests during run
298  --verbose                  be verbose
299  --analyse-cmd CMD          command to run after each test
300 ";
301         exit(0);
302 }
303
304 my $result = GetOptions (
305                 'help|h|?' => \$opt_help,
306                 'target=s' => \$opt_target,
307                 'prefix=s' => \$prefix,
308                 'socket-wrapper' => \$opt_socket_wrapper,
309                 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
310                 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
311                 'quick' => \$opt_quick,
312                 'one' => \$opt_one,
313                 'immediate' => \$opt_immediate,
314                 'expected-failures=s' => \$opt_expected_failures,
315                 'skip=s' => \$opt_skip,
316                 'srcdir=s' => \$srcdir,
317                 'builddir=s' => \$builddir,
318                 'verbose' => \$opt_verbose,
319                 'testenv' => \$opt_testenv,
320                 'ldap:s' => \$ldap,
321                 'analyse-cmd=s' => \$opt_analyse_cmd,
322                 'no-lazy-setup' => \$opt_no_lazy_setup,
323                 'resetup-environment' => \$opt_resetup_env,
324                 'bindir:s' => \$opt_bindir,
325                 'format=s' => \$opt_format,
326                 'testlist=s' => \@opt_testlists
327             );
328
329 exit(1) if (not $result);
330
331 ShowHelp() if ($opt_help);
332
333 my $tests = shift;
334
335 # quick hack to disable rpc validation when using valgrind - its way too slow
336 unless (defined($ENV{VALGRIND})) {
337         $ENV{VALIDATE} = "validate";
338         $ENV{MALLOC_CHECK_} = 2;
339 }
340
341 my $old_pwd = "$RealBin/..";
342
343 # Backwards compatibility:
344 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
345         if (defined($ENV{FEDORA_DS_PREFIX})) {
346                 $ldap = "fedora-ds";
347         } else {
348                 $ldap = "openldap";
349         }
350 }
351
352 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
353 if ($ldap) {
354         # LDAP is slow
355         $torture_maxtime *= 2;
356 }
357
358 $prefix =~ s+//+/+;
359 $prefix =~ s+/./+/+;
360 $prefix =~ s+/$++;
361
362 die("using an empty prefix isn't allowed") unless $prefix ne "";
363
364 #Ensure we have the test prefix around
365 mkdir($prefix, 0777) unless -d $prefix;
366
367 my $prefix_abs = abs_path($prefix);
368 my $srcdir_abs = abs_path($srcdir);
369
370 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
371 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
372
373 $ENV{PREFIX} = $prefix;
374 $ENV{PREFIX_ABS} = $prefix_abs;
375 $ENV{SRCDIR} = $srcdir;
376 $ENV{SRCDIR_ABS} = $srcdir_abs;
377
378 my $tls_enabled = not $opt_quick;
379 if (defined($ENV{RUN_FROM_BUILD_FARM}) and 
380         ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
381         $opt_format = "buildfarm";
382 }
383
384 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
385 $ENV{LD_LDB_MODULE_PATH} = "$old_pwd/bin/modules/ldb";
386 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules";
387 if (defined($ENV{LD_LIBRARY_PATH})) {
388         $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared:$ENV{LD_LIBRARY_PATH}";
389 } else {
390         $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared";
391 }
392 if (defined($ENV{PKG_CONFIG_PATH})) {
393         $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}";
394 } else { 
395         $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig";
396 }
397 # Required for smbscript:
398 $ENV{PATH} = "$old_pwd/bin:$old_pwd:$ENV{PATH}";
399
400
401 if ($opt_socket_wrapper_pcap) {
402         # Socket wrapper pcap implies socket wrapper
403         $opt_socket_wrapper = 1;
404 }
405
406 my $socket_wrapper_dir;
407 if ($opt_socket_wrapper) {
408         $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
409         print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
410 } else {
411         warn("Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports") unless $< == 0;
412 }
413
414 my $target;
415
416 if ($opt_target eq "samba4") {
417         $target = new Samba4($opt_bindir or "$srcdir/bin", $ldap, "$srcdir/setup");
418 } elsif ($opt_target eq "samba3") {
419         if ($opt_socket_wrapper and `$opt_bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
420                 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'.  Exiting....");
421         }
422
423         $target = new Samba3($opt_bindir);
424 } elsif ($opt_target eq "win") {
425         die("Windows tests will not run with socket wrapper enabled.") 
426                 if ($opt_socket_wrapper);
427         $target = new Windows();
428 }
429
430 sub read_test_regexes($)
431 {
432         my ($name) = @_;
433         my @ret = ();
434         open(LF, "<$name") or die("unable to read $name: $!");
435         while (<LF>) { 
436                 chomp; 
437                 if (/^(.*?)([ \t]+)\#(.*)$/) {
438                         push (@ret, [$1, $3]);
439                 } else {
440                         s/^(.*?)([ \t]+)\#(.*)$//;
441                         push (@ret, [$_, undef]); 
442                 }
443         }
444         close(LF);
445         return @ret;
446 }
447
448 if (defined($opt_expected_failures)) {
449         @expected_failures = read_test_regexes($opt_expected_failures);
450 }
451
452 if (defined($opt_skip)) {
453         @skips = read_test_regexes($opt_skip);
454 }
455
456 my $interfaces = join(',', ("127.0.0.6/8", 
457                             "127.0.0.7/8",
458                             "127.0.0.8/8",
459                             "127.0.0.9/8",
460                             "127.0.0.10/8",
461                             "127.0.0.11/8"));
462
463 my $conffile = "$prefix_abs/client/client.conf";
464
465 sub write_clientconf($$)
466 {
467         my ($conffile, $vars) = @_;
468
469         mkdir("$prefix/client", 0777) unless -d "$prefix/client";
470         
471         if ( -d "$prefix/client/private" ) {
472                 unlink <$prefix/client/private/*>;
473         } else {
474                 mkdir("$prefix/client/private", 0777);
475         }
476
477         open(CF, ">$conffile");
478         print CF "[global]\n";
479         if (defined($ENV{VALGRIND})) {
480                 print CF "\ticonv:native = true\n";
481         } else {
482                 print CF "\ticonv:native = false\n";
483         }
484         print CF "\tnetbios name = client\n";
485         if (defined($vars->{DOMAIN})) {
486                 print CF "\tworkgroup = $vars->{DOMAIN}\n";
487         }
488         if (defined($vars->{REALM})) {
489                 print CF "\trealm = $vars->{REALM}\n";
490         }
491         if (defined($vars->{NCALRPCDIR})) {
492                 print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n";
493         }
494         if (defined($vars->{PIDDIR})) {
495                 print CF "\tpid directory = $vars->{PIDDIR}\n";
496         }
497         if (defined($vars->{WINBINDD_SOCKET_DIR})) {
498                 print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n";
499         }
500         print CF "
501         private dir = $prefix_abs/client/private
502         js include = $srcdir_abs/scripting/libjs
503         name resolve order = bcast
504         interfaces = $interfaces
505         panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\%
506         max xmit = 32K
507         notify:inotify = false
508         ldb:nosync = true
509         system:anonymous = true
510         torture:basedir = $prefix_abs/client
511 #We don't want to pass our self-tests if the PAC code is wrong
512         gensec:require_pac = true
513 ";
514         close(CF);
515 }
516
517
518 my @torture_options = ();
519 push (@torture_options, "--configfile=$conffile");
520 # ensure any one smbtorture call doesn't run too long
521 push (@torture_options, "--maximum-runtime=$torture_maxtime");
522 push (@torture_options, "--target=$opt_target");
523 push (@torture_options, "--basedir=$prefix");
524 push (@torture_options, "--option=torture:progress=no") if ($opt_format eq "buildfarm");
525 push (@torture_options, "--format=subunit");
526 push (@torture_options, "--option=torture:quick=yes") if ($opt_quick);
527
528 $ENV{TORTURE_OPTIONS} = join(' ', @torture_options);
529 print "OPTIONS $ENV{TORTURE_OPTIONS}\n";
530
531 my @todo = ();
532
533 my $testsdir = "$srcdir/selftest";
534 $ENV{SMB_CONF_PATH} = "$conffile";
535 $ENV{CONFIGURATION} = "--configfile=$conffile";
536
537 my %required_envs = ();
538
539 sub read_testlist($)
540 {
541         my ($filename) = @_;
542
543         my @ret = ();
544         open(IN, $filename) or die("Unable to open $filename: $!");
545
546         while (<IN>) {
547                 if ($_ eq "-- TEST --\n") {
548                         my $name = <IN>;
549                         $name =~ s/\n//g;
550                         my $env = <IN>;
551                         $env =~ s/\n//g;
552                         my $cmdline = <IN>;
553                         $cmdline =~ s/\n//g;
554                         if (not defined($tests) or $name =~ /$tests/) {
555                                 $required_envs{$env} = 1;
556                                 push (@ret, [$name, $env, $cmdline]);
557                         }
558                 } else {
559                         print;
560                 }
561         }
562         close(IN) or die("Error creating recipe");
563         return @ret;
564 }
565
566 if ($opt_quick) {
567         @todo = read_testlist("$testsdir/tests_quick.sh|");
568 } else {
569         @todo = read_testlist("$testsdir/tests_all.sh|");
570 }
571
572 foreach (@opt_testlists) {
573         push(@todo, read_testlist($_));
574 }
575
576 my $suitestotal = $#todo + 1;
577 my $i = 0;
578 $| = 1;
579
580 my %running_envs = ();
581
582 my @exported_envvars = (
583         # domain stuff
584         "DOMAIN",
585         "REALM",
586
587         # domain controller stuff
588         "DC_SERVER",
589         "DC_SERVER_IP",
590         "DC_NETBIOSNAME",
591         "DC_NETBIOSALIAS",
592
593         # server stuff
594         "SERVER",
595         "SERVER_IP",
596         "NETBIOSNAME",
597         "NETBIOSALIAS",
598
599         # user stuff
600         "USERNAME",
601         "PASSWORD",
602         "DC_USERNAME",
603         "DC_PASSWORD",
604
605         # misc stuff
606         "KRB5_CONFIG",
607         "WINBINDD_SOCKET_DIR"
608 );
609
610 sub setup_env($)
611 {
612         my ($envname) = @_;
613
614         my $testenv_vars;
615         if ($envname eq "none") {
616                 $testenv_vars = {};
617         } elsif (defined($running_envs{$envname})) {
618                 $testenv_vars = $running_envs{$envname};
619                 if (not $target->check_env($testenv_vars)) {
620                         $testenv_vars = undef;
621                 }
622         } else {
623                 $testenv_vars = $target->setup_env($envname, $prefix);
624         }
625
626         return undef unless defined($testenv_vars);
627
628         SocketWrapper::set_default_iface(6);
629         write_clientconf($conffile, $testenv_vars);
630
631         foreach (@exported_envvars) {
632                 if (defined($testenv_vars->{$_})) {
633                         $ENV{$_} = $testenv_vars->{$_};
634                 } else {
635                         delete $ENV{$_};
636                 }
637         }
638
639         $running_envs{$envname} = $testenv_vars;
640         return $testenv_vars;
641 }
642
643 sub exported_envvars_str($)
644 {
645         my ($testenv_vars) = @_;
646         my $out = "";
647
648         foreach (@exported_envvars) {
649                 next unless defined($testenv_vars->{$_});
650                 $out .= $_."=".$testenv_vars->{$_}."\n";
651         }
652
653         return $out;
654 }
655
656 sub getlog_env($)
657 {
658         my ($envname) = @_;
659         return "" if ($envname eq "none");
660         return $target->getlog_env($running_envs{$envname});
661 }
662
663 sub check_env($)
664 {
665         my ($envname) = @_;
666         return 1 if ($envname eq "none");
667         return $target->check_env($running_envs{$envname});
668 }
669
670 sub teardown_env($)
671 {
672         my ($envname) = @_;
673         return if ($envname eq "none");
674         $target->teardown_env($running_envs{$envname});
675         delete $running_envs{$envname};
676 }
677
678 my $msg_ops;
679 if ($opt_format eq "buildfarm") {
680         require output::buildfarm;
681         $msg_ops = new output::buildfarm();
682 } elsif ($opt_format eq "plain") {
683         require output::plain;
684         $msg_ops = new output::plain($opt_verbose, $opt_immediate, $statistics);
685 } elsif ($opt_format eq "html") {
686         require output::html;
687         mkdir("test-results", 0777);
688         $msg_ops = new output::html("test-results", $statistics);
689 } else {
690         die("Invalid output format '$opt_format'");
691 }
692
693 if ($opt_no_lazy_setup) {
694         setup_env($_) foreach (keys %required_envs);
695 }
696
697 if ($opt_testenv) {
698         my $testenv_name = $ENV{SELFTEST_TESTENV};
699         $testenv_name = "member" unless defined($testenv_name);
700
701         my $testenv_vars = setup_env($testenv_name);
702
703         $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
704
705         my $envvarstr = exported_envvars_str($testenv_vars);
706
707         my $term = ($ENV{TERM} or "xterm");
708         system("$term -e 'echo -e \"
709 Welcome to the Samba4 Test environment '$testenv_name'
710
711 This matches the client environment used in make test
712 smbd is pid `cat \$PIDDIR/smbd.pid`
713
714 Some useful environment variables:
715 TORTURE_OPTIONS=\$TORTURE_OPTIONS
716 CONFIGURATION=\$CONFIGURATION
717
718 $envvarstr
719 \" && bash'");
720         teardown_env($testenv_name);
721 } else {
722         foreach (@todo) {
723                 $i++;
724                 my $cmd = $$_[2];
725                 $cmd =~ s/([\(\)])/\\$1/g;
726                 my $name = $$_[0];
727                 my $envname = $$_[1];
728                 
729                 my $skipreason = skip($name);
730                 if ($skipreason) {
731                         $msg_ops->skip_testsuite($envname, $name, $skipreason);
732                         $statistics->{SUITES_SKIPPED}++;
733                         next;
734                 }
735
736                 my $envvars = setup_env($envname);
737                 if (not defined($envvars)) {
738                         $statistics->{SUITES_SKIPPED}++;
739                         $msg_ops->missing_env($name, $envname);
740                         next;
741                 }
742
743                 run_testsuite($envname, $name, $cmd, $i, $suitestotal, $msg_ops);
744
745                 if (defined($opt_analyse_cmd)) {
746                         system("$opt_analyse_cmd \"$name\"");
747                 }
748
749                 teardown_env($envname) if ($opt_resetup_env);
750         }
751 }
752
753 print "\n";
754
755 teardown_env($_) foreach (keys %running_envs);
756
757 $target->stop();
758
759 $statistics->{END_TIME} = time();
760 my $duration = ($statistics->{END_TIME}-$statistics->{START_TIME});
761 $msg_ops->summary();
762 print "DURATION: $duration seconds\n";
763
764 my $failed = 0;
765
766 # if there were any valgrind failures, show them
767 foreach (<$prefix/valgrind.log*>) {
768         next unless (-s $_);
769         system("grep DWARF2.CFI.reader $_ > /dev/null");
770         if ($? >> 8 == 0) {
771             print "VALGRIND FAILURE\n";
772             $failed++;
773             system("cat $_");
774         }
775 }
776
777 if ($opt_format eq "buildfarm") {
778         print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
779 }
780
781 exit $statistics->{SUITES_FAIL};