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