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