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