s3:libsmb: use new simplified smb_signing code for the client side
[jra/samba/.git] / selftest / selftest.pl
1 #!/usr/bin/perl
2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
4 # Copyright (C) 2007-2009 Stefan Metzmacher <metze@samba.org>
5 # Published under the GNU GPL, v3 or later.
6
7 =pod
8
9 =head1 NAME
10
11 selftest - Samba test runner
12
13 =head1 SYNOPSIS
14
15 selftest --help
16
17 selftest [--srcdir=DIR] [--builddir=DIR] [--exeext=EXT][--target=samba4|samba3|win|kvm] [--socket-wrapper] [--quick] [--exclude=FILE] [--include=FILE] [--one] [--prefix=prefix] [--immediate] [--testlist=FILE] [TESTS]
18
19 =head1 DESCRIPTION
20
21 A simple test runner. TESTS is a regular expression with tests to run.
22
23 =head1 OPTIONS
24
25 =over 4
26
27 =item I<--help>
28
29 Show list of available options.
30
31 =item I<--srcdir=DIR>
32
33 Source directory.
34
35 =item I<--builddir=DIR>
36
37 Build directory.
38
39 =item I<--exeext=EXT>
40
41 Executable extention
42
43 =item I<--prefix=DIR>
44
45 Change directory to run tests in. Default is 'st'.
46
47 =item I<--immediate>
48
49 Show errors as soon as they happen rather than at the end of the test run.
50                 
51 =item I<--target samba4|samba3|win|kvm>
52
53 Specify test target against which to run. Default is 'samba4'.
54
55 =item I<--quick>
56
57 Run only a limited number of tests. Intended to run in about 30 seconds on 
58 moderately recent systems.
59                 
60 =item I<--socket-wrapper>
61
62 Use socket wrapper library for communication with server. Only works 
63 when the server is running locally.
64
65 Will prevent TCP and UDP ports being opened on the local host but 
66 (transparently) redirects these calls to use unix domain sockets.
67
68 =item I<--expected-failures>
69
70 Specify a file containing a list of tests that are expected to fail. Failures for 
71 these tests will be counted as successes, successes will be counted as failures.
72
73 The format for the file is, one entry per line:
74
75 TESTSUITE-NAME.TEST-NAME
76
77 The reason for a test can also be specified, by adding a hash sign (#) and the reason 
78 after the test name.
79
80 =item I<--exclude>
81
82 Specify a file containing a list of tests that should be skipped. Possible 
83 candidates are tests that segfault the server, flip or don't end. The format of this file is the same as 
84 for the --expected-failures flag.
85
86 =item I<--include>
87
88 Specify a file containing a list of tests that should be run. Same format 
89 as the --exclude flag.
90
91 Not includes specified means all tests will be run.
92
93 =item I<--one>
94
95 Abort as soon as one test fails.
96
97 =item I<--testlist>
98
99 Load a list of tests from the specified location.
100
101 =back
102
103 =head1 ENVIRONMENT
104
105 =over 4
106
107 =item I<SMBD_VALGRIND>
108
109 =item I<TORTURE_MAXTIME>
110
111 =item I<VALGRIND>
112
113 =item I<TLS_ENABLED>
114
115 =item I<srcdir>
116
117 =back
118
119 =head1 LICENSE
120
121 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
122
123 =head1 AUTHOR
124
125 Jelmer Vernooij
126
127 =cut
128
129 use strict;
130
131 use FindBin qw($RealBin $Script);
132 use File::Spec;
133 use Getopt::Long;
134 use POSIX;
135 use Cwd qw(abs_path);
136 use lib "$RealBin";
137 use Subunit qw(parse_results);
138 use SocketWrapper;
139
140 my $opt_help = 0;
141 my $opt_target = "samba4";
142 my $opt_quick = 0;
143 my $opt_socket_wrapper = 0;
144 my $opt_socket_wrapper_pcap = undef;
145 my $opt_socket_wrapper_keep_pcap = undef;
146 my $opt_one = 0;
147 my $opt_immediate = 0;
148 my $opt_expected_failures = undef;
149 my @opt_exclude = ();
150 my @opt_include = ();
151 my $opt_verbose = 0;
152 my $opt_image = undef;
153 my $opt_testenv = 0;
154 my $ldap = undef;
155 my $opt_analyse_cmd = undef;
156 my $opt_resetup_env = undef;
157 my $opt_bindir = undef;
158 my $opt_no_lazy_setup = undef;
159 my $opt_format = "plain";
160 my @testlists = ();
161
162 my $srcdir = ".";
163 my $builddir = ".";
164 my $exeext = "";
165 my $prefix = "./st";
166
167 my @expected_failures = ();
168 my @includes = ();
169 my @excludes = ();
170
171 my $statistics = {
172         SUITES_FAIL => 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         return find_in_list(\@excludes, $name);
207 }
208
209 sub getlog_env($);
210
211 sub setup_pcap($)
212 {
213         my ($name) = @_;
214
215         return unless ($opt_socket_wrapper_pcap);
216         return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
217
218         my $fname = $name;
219         $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
220
221         my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
222
223         SocketWrapper::setup_pcap($pcap_file);
224
225         return $pcap_file;
226 }
227
228 sub cleanup_pcap($$$)
229 {
230         my ($pcap_file, $expected_ret, $ret) = @_;
231
232         return unless ($opt_socket_wrapper_pcap);
233         return if ($opt_socket_wrapper_keep_pcap);
234         return unless ($expected_ret == $ret);
235         return unless defined($pcap_file);
236
237         unlink($pcap_file);
238 }
239
240 sub run_testsuite($$$$$$)
241 {
242         my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
243         my $pcap_file = setup_pcap($name);
244
245         $msg_ops->start_test([], $name);
246
247         unless (open(RESULT, "$cmd 2>&1|")) {
248                 $statistics->{TESTS_ERROR}++;
249                 $msg_ops->end_test([], $name, "error", 1, "Unable to run $cmd: $!");
250                 $statistics->{SUITES_FAIL}++;
251                 return 0;
252         }
253
254         my $expected_ret = parse_results(
255                 $msg_ops, $statistics, *RESULT, \&expecting_failure, [$name]);
256
257         my $envlog = getlog_env($envname);
258         $msg_ops->output_msg("ENVLOG: $envlog\n") if ($envlog ne "");
259
260         $msg_ops->output_msg("CMD: $cmd\n");
261
262         my $ret = close(RESULT);
263         $ret = 0 unless $ret == 1;
264
265         my $exitcode = $? >> 8;
266
267         if ($ret == 1) {
268                 $msg_ops->end_test([], $name, "success", $expected_ret != $ret, undef); 
269         } else {
270                 $msg_ops->end_test([], $name, "failure", $expected_ret != $ret, "Exit code was $exitcode");
271         }
272
273         cleanup_pcap($pcap_file, $expected_ret, $ret);
274
275         if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
276                 $msg_ops->output_msg("PCAP FILE: $pcap_file\n");
277         }
278
279         if ($ret != $expected_ret) {
280                 $statistics->{SUITES_FAIL}++;
281                 exit(1) if ($opt_one);
282         }
283
284         return ($ret == $expected_ret);
285 }
286
287 sub ShowHelp()
288 {
289         print "Samba test runner
290 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
291 Copyright (C) Stefan Metzmacher <metze\@samba.org>
292
293 Usage: $Script [OPTIONS] TESTNAME-REGEX
294
295 Generic options:
296  --help                     this help page
297  --target=samba[34]|win|kvm Samba version to target
298  --testlist=FILE            file to read available tests from
299
300 Paths:
301  --prefix=DIR               prefix to run tests in [st]
302  --srcdir=DIR               source directory [.]
303  --builddir=DIR             output directory [.]
304  --exeext=EXT               executable extention []
305
306 Target Specific:
307  --socket-wrapper-pcap      save traffic to pcap directories
308  --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that 
309                             failed
310  --socket-wrapper           enable socket wrapper
311  --bindir=PATH              path to target binaries
312  --expected-failures=FILE   specify list of tests that is guaranteed to fail
313
314 Samba4 Specific:
315  --ldap=openldap|fedora-ds  back samba onto specified ldap server
316
317 Kvm Specific:
318  --image=PATH               path to KVM image
319
320 Behaviour:
321  --quick                    run quick overall test
322  --one                      abort when the first test fails
323  --immediate                print test output for failed tests during run
324  --verbose                  be verbose
325  --analyse-cmd CMD          command to run after each test
326 ";
327         exit(0);
328 }
329
330 my $result = GetOptions (
331                 'help|h|?' => \$opt_help,
332                 'target=s' => \$opt_target,
333                 'prefix=s' => \$prefix,
334                 'socket-wrapper' => \$opt_socket_wrapper,
335                 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
336                 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
337                 'quick' => \$opt_quick,
338                 'one' => \$opt_one,
339                 'immediate' => \$opt_immediate,
340                 'expected-failures=s' => \$opt_expected_failures,
341                 'exclude=s' => \@opt_exclude,
342                 'include=s' => \@opt_include,
343                 'srcdir=s' => \$srcdir,
344                 'builddir=s' => \$builddir,
345                 'exeext=s' => \$exeext,
346                 'verbose' => \$opt_verbose,
347                 'testenv' => \$opt_testenv,
348                 'ldap:s' => \$ldap,
349                 'analyse-cmd=s' => \$opt_analyse_cmd,
350                 'no-lazy-setup' => \$opt_no_lazy_setup,
351                 'resetup-environment' => \$opt_resetup_env,
352                 'bindir:s' => \$opt_bindir,
353                 'format=s' => \$opt_format,
354                 'image=s' => \$opt_image,
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 $bindir = ($opt_bindir or "$builddir/bin");
371 my $bindir_abs = abs_path($bindir);
372
373 # Backwards compatibility:
374 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
375         if (defined($ENV{FEDORA_DS_ROOT})) {
376                 $ldap = "fedora-ds";
377         } else {
378                 $ldap = "openldap";
379         }
380 }
381
382 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
383 if ($ldap) {
384         # LDAP is slow
385         $torture_maxtime *= 2;
386 }
387
388 $prefix =~ s+//+/+;
389 $prefix =~ s+/./+/+;
390 $prefix =~ s+/$++;
391
392 die("using an empty prefix isn't allowed") unless $prefix ne "";
393
394 #Ensure we have the test prefix around
395 mkdir($prefix, 0777) unless -d $prefix;
396
397 my $prefix_abs = abs_path($prefix);
398 my $srcdir_abs = abs_path($srcdir);
399 my $builddir_abs = abs_path($builddir);
400
401 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
402 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
403
404 $ENV{PREFIX} = $prefix;
405 $ENV{KRB5CCNAME} = "$prefix/krb5ticket";
406 $ENV{PREFIX_ABS} = $prefix_abs;
407 $ENV{SRCDIR} = $srcdir;
408 $ENV{SRCDIR_ABS} = $srcdir_abs;
409 $ENV{BUILDDIR} = $builddir;
410 $ENV{BUILDDIR_ABS} = $builddir_abs;
411 $ENV{EXEEXT} = $exeext;
412
413 if (defined($ENV{RUN_FROM_BUILD_FARM}) and 
414         ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
415         $opt_format = "buildfarm";
416 }
417
418 my $tls_enabled = not $opt_quick;
419 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
420 $ENV{LDB_MODULES_PATH} = "$bindir_abs/modules/ldb";
421 $ENV{LD_SAMBA_MODULE_PATH} = "$bindir_abs/modules";
422 sub prefix_pathvar($$)
423 {
424         my ($name, $newpath) = @_;
425         if (defined($ENV{$name})) {
426                 $ENV{$name} = "$newpath:$ENV{$name}";
427         } else {
428                 $ENV{$name} = $newpath;
429         }
430 }
431 prefix_pathvar("PKG_CONFIG_PATH", "$bindir_abs/pkgconfig");
432 prefix_pathvar("PYTHONPATH", "$bindir_abs/python");
433
434 if ($opt_socket_wrapper_keep_pcap) {
435         # Socket wrapper keep pcap implies socket wrapper pcap
436         $opt_socket_wrapper_pcap = 1;
437 }
438
439 if ($opt_socket_wrapper_pcap) {
440         # Socket wrapper pcap implies socket wrapper
441         $opt_socket_wrapper = 1;
442 }
443
444 my $socket_wrapper_dir;
445 if ($opt_socket_wrapper) {
446         $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
447         print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
448 } else {
449          unless ($< == 0) { 
450                  print "WARNING: Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports\n";
451          }
452 }
453
454 my $target;
455 my $testenv_default = "none";
456
457 if ($opt_target eq "samba4") {
458         $testenv_default = "member";
459         require target::Samba4;
460         $target = new Samba4($bindir, $ldap, "$srcdir/setup", $exeext);
461 } elsif ($opt_target eq "samba3") {
462         if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
463                 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'.  Exiting....");
464         }
465         $testenv_default = "member";
466         require target::Samba3;
467         $target = new Samba3($bindir);
468 } elsif ($opt_target eq "win") {
469         die("Windows tests will not run with socket wrapper enabled.") 
470                 if ($opt_socket_wrapper);
471         $testenv_default = "dc";
472         require target::Windows;
473         $target = new Windows();
474 } elsif ($opt_target eq "kvm") {
475         die("Kvm tests will not run with socket wrapper enabled.") 
476                 if ($opt_socket_wrapper);
477         require target::Kvm;
478         die("No image specified") unless ($opt_image);
479         $target = new Kvm($opt_image, undef);
480 }
481
482 #
483 # Start a Virtual Distributed Ethernet Switch
484 # Returns the pid of the switch.
485 #
486 sub start_vde_switch($)
487 {
488         my ($path) = @_;
489
490         system("vde_switch --pidfile $path/vde.pid --sock $path/vde.sock --daemon");
491
492         open(PID, "$path/vde.pid");
493         <PID> =~ /([0-9]+)/;
494         my $pid = $1;
495         close(PID);
496
497         return $pid;
498 }
499
500 # Stop a Virtual Distributed Ethernet Switch
501 sub stop_vde_switch($)
502 {
503         my ($pid) = @_;
504         kill 9, $pid;
505 }
506
507 sub read_test_regexes($)
508 {
509         my ($name) = @_;
510         my @ret = ();
511         open(LF, "<$name") or die("unable to read $name: $!");
512         while (<LF>) { 
513                 chomp; 
514                 next if (/^#/);
515                 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
516                         push (@ret, [$1, $4]);
517                 } else {
518                         s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
519                         push (@ret, [$_, undef]); 
520                 }
521         }
522         close(LF);
523         return @ret;
524 }
525
526 if (defined($opt_expected_failures)) {
527         @expected_failures = read_test_regexes($opt_expected_failures);
528 }
529
530 foreach (@opt_exclude) {
531         push (@excludes, read_test_regexes($_));
532 }
533
534 foreach (@opt_include) {
535         push (@includes, read_test_regexes($_));
536 }
537
538 my $interfaces = join(',', ("127.0.0.6/8", 
539                             "127.0.0.7/8",
540                             "127.0.0.8/8",
541                             "127.0.0.9/8",
542                             "127.0.0.10/8",
543                             "127.0.0.11/8"));
544
545 my $conffile = "$prefix_abs/client/client.conf";
546 $ENV{SMB_CONF_PATH} = $conffile;
547
548 sub write_clientconf($$)
549 {
550         my ($conffile, $vars) = @_;
551
552         mkdir("$prefix/client", 0777) unless -d "$prefix/client";
553         
554         if ( -d "$prefix/client/private" ) {
555                 unlink <$prefix/client/private/*>;
556         } else {
557                 mkdir("$prefix/client/private", 0777);
558         }
559
560         if ( -d "$prefix/client/lock" ) {
561                 unlink <$prefix/client/lockdir/*>;
562         } else {
563                 mkdir("$prefix/client/lockdir", 0777);
564         }
565
566         open(CF, ">$conffile");
567         print CF "[global]\n";
568         if (defined($ENV{VALGRIND})) {
569                 print CF "\ticonv:native = true\n";
570         } else {
571                 print CF "\ticonv:native = false\n";
572         }
573         print CF "\tnetbios name = client\n";
574         if (defined($vars->{DOMAIN})) {
575                 print CF "\tworkgroup = $vars->{DOMAIN}\n";
576         }
577         if (defined($vars->{REALM})) {
578                 print CF "\trealm = $vars->{REALM}\n";
579         }
580         if ($opt_socket_wrapper) {
581                 print CF "\tinterfaces = $interfaces\n";
582         }
583         print CF "
584         private dir = $prefix_abs/client/private
585         lock dir = $prefix_abs/client/lockdir
586         name resolve order = bcast
587         panic action = $RealBin/gdb_backtrace \%PID\% \%PROG\%
588         max xmit = 32K
589         notify:inotify = false
590         ldb:nosync = true
591         system:anonymous = true
592         client lanman auth = Yes
593         torture:basedir = $prefix_abs/client
594 #We don't want to pass our self-tests if the PAC code is wrong
595         gensec:require_pac = true
596         modules dir = $ENV{LD_SAMBA_MODULE_PATH}
597 ";
598         close(CF);
599 }
600
601 my @todo = ();
602
603 my $testsdir = "$srcdir/selftest";
604
605 my %required_envs = ();
606
607 sub read_testlist($)
608 {
609         my ($filename) = @_;
610
611         my @ret = ();
612         open(IN, $filename) or die("Unable to open $filename: $!");
613
614         while (<IN>) {
615                 if ($_ eq "-- TEST --\n") {
616                         my $name = <IN>;
617                         $name =~ s/\n//g;
618                         my $env = <IN>;
619                         $env =~ s/\n//g;
620                         my $cmdline = <IN>;
621                         $cmdline =~ s/\n//g;
622                         if (not defined($tests) or $name =~ /$tests/) {
623                                 $required_envs{$env} = 1;
624                                 push (@ret, [$name, $env, $cmdline]);
625                         }
626                 } else {
627                         print;
628                 }
629         }
630         close(IN) or die("Error creating recipe");
631         return @ret;
632 }
633
634 if ($#testlists == -1) {
635         die("No testlists specified");
636 }
637
638 $ENV{SELFTEST_PREFIX} = "$prefix_abs";
639 if ($opt_socket_wrapper) {
640         $ENV{SELFTEST_INTERFACES} = $interfaces;
641 } else {
642         $ENV{SELFTEST_INTERFACES} = "";
643 }
644 if ($opt_verbose) {
645         $ENV{SELFTEST_VERBOSE} = "1";
646 } else {
647         $ENV{SELFTEST_VERBOSE} = "";
648 }
649 if ($opt_quick) {
650         $ENV{SELFTEST_QUICK} = "1";
651 } else {
652         $ENV{SELFTEST_QUICK} = "";
653 }
654 $ENV{SELFTEST_TARGET} = $opt_target;
655 $ENV{SELFTEST_MAXTIME} = $torture_maxtime;
656
657 my @available = ();
658 foreach my $fn (@testlists) {
659         foreach (read_testlist($fn)) {
660                 my $name = $$_[0];
661                 next if (@includes and not find_in_list(\@includes, $name));
662                 push (@available, $_);
663         }
664 }
665
666 my $msg_ops;
667 if ($opt_format eq "buildfarm") {
668         require output::buildfarm;
669         $msg_ops = new output::buildfarm($statistics);
670 } elsif ($opt_format eq "plain") {
671         require output::plain;
672         $msg_ops = new output::plain("$prefix/summary", $opt_verbose, $opt_immediate, $statistics, $#available+1);
673 } elsif ($opt_format eq "html") {
674         require output::html;
675         mkdir("test-results", 0777);
676         $msg_ops = new output::html("test-results", $statistics);
677 } else {
678         die("Invalid output format '$opt_format'");
679 }
680
681
682 foreach (@available) {
683         my $name = $$_[0];
684         my $skipreason = skip($name);
685         if ($skipreason) {
686                 $msg_ops->skip_testsuite($name, $skipreason);
687         } else {
688                 push(@todo, $_); 
689         }
690 }
691
692 if ($#todo == -1) {
693         print STDERR "No tests to run\n";
694         exit(1);
695         }
696
697 my $suitestotal = $#todo + 1;
698 my $i = 0;
699 $| = 1;
700
701 my %running_envs = ();
702
703 sub get_running_env($)
704 {
705         my ($name) = @_;
706
707         my $envname = $name;
708
709         $envname =~ s/:.*//;
710
711         return $running_envs{$envname};
712 }
713
714 my @exported_envvars = (
715         # domain stuff
716         "DOMAIN",
717         "REALM",
718
719         # domain controller stuff
720         "DC_SERVER",
721         "DC_SERVER_IP",
722         "DC_NETBIOSNAME",
723         "DC_NETBIOSALIAS",
724
725         # server stuff
726         "SERVER",
727         "SERVER_IP",
728         "NETBIOSNAME",
729         "NETBIOSALIAS",
730
731         # user stuff
732         "USERNAME",
733         "PASSWORD",
734         "DC_USERNAME",
735         "DC_PASSWORD",
736
737         # misc stuff
738         "KRB5_CONFIG",
739         "WINBINDD_SOCKET_DIR",
740         "WINBINDD_PRIV_PIPE_DIR"
741 );
742
743 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { 
744         my $signame = shift;
745         teardown_env($_) foreach(keys %running_envs);
746         die("Received signal $signame");
747 };
748
749 sub setup_env($)
750 {
751         my ($name) = @_;
752
753         my $testenv_vars = undef;
754
755         my $envname = $name;
756         my $option = $name;
757
758         $envname =~ s/:.*//;
759         $option =~ s/^[^:]*//;
760         $option =~ s/^://;
761
762         $option = "client" if $option eq "";
763
764         if ($envname eq "none") {
765                 $testenv_vars = {};
766         } elsif (defined(get_running_env($envname))) {
767                 $testenv_vars = get_running_env($envname);
768                 if (not $target->check_env($testenv_vars)) {
769                         $testenv_vars = undef;
770                 }
771         } else {
772                 $testenv_vars = $target->setup_env($envname, $prefix);
773         }
774
775         return undef unless defined($testenv_vars);
776
777         $running_envs{$envname} = $testenv_vars;
778
779         if ($option eq "local") {
780                 SocketWrapper::set_default_iface($testenv_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
781                 $ENV{SMB_CONF_PATH} = $testenv_vars->{SERVERCONFFILE};
782         } elsif ($option eq "client") {
783                 SocketWrapper::set_default_iface(6);
784                 write_clientconf($conffile, $testenv_vars);
785                 $ENV{SMB_CONF_PATH} = $conffile;
786         } else {
787                 die("Unknown option[$option] for envname[$envname]");
788         }
789
790         foreach (@exported_envvars) {
791                 if (defined($testenv_vars->{$_})) {
792                         $ENV{$_} = $testenv_vars->{$_};
793                 } else {
794                         delete $ENV{$_};
795                 }
796         }
797
798         return $testenv_vars;
799 }
800
801 sub exported_envvars_str($)
802 {
803         my ($testenv_vars) = @_;
804         my $out = "";
805
806         foreach (@exported_envvars) {
807                 next unless defined($testenv_vars->{$_});
808                 $out .= $_."=".$testenv_vars->{$_}."\n";
809         }
810
811         return $out;
812 }
813
814 sub getlog_env($)
815 {
816         my ($envname) = @_;
817         return "" if ($envname eq "none");
818         return $target->getlog_env(get_running_env($envname));
819 }
820
821 sub check_env($)
822 {
823         my ($envname) = @_;
824         return 1 if ($envname eq "none");
825         return $target->check_env(get_running_env($envname));
826 }
827
828 sub teardown_env($)
829 {
830         my ($envname) = @_;
831         return if ($envname eq "none");
832         $target->teardown_env(get_running_env($envname));
833         delete $running_envs{$envname};
834 }
835
836 if ($opt_no_lazy_setup) {
837         setup_env($_) foreach (keys %required_envs);
838 }
839
840 if ($opt_testenv) {
841         my $testenv_name = $ENV{SELFTEST_TESTENV};
842         $testenv_name = $testenv_default unless defined($testenv_name);
843
844         my $testenv_vars = setup_env($testenv_name);
845
846         $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
847
848         my $envvarstr = exported_envvars_str($testenv_vars);
849
850         my $term = ($ENV{TERM} or "xterm");
851         system("$term -e 'echo -e \"
852 Welcome to the Samba4 Test environment '$testenv_name'
853
854 This matches the client environment used in make test
855 server is pid `cat \$PIDDIR/samba.pid`
856
857 Some useful environment variables:
858 TORTURE_OPTIONS=\$TORTURE_OPTIONS
859 SMB_CONF_PATH=\$SMB_CONF_PATH
860
861 $envvarstr
862 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
863         teardown_env($testenv_name);
864 } else {
865         foreach (@todo) {
866                 $i++;
867                 my $cmd = $$_[2];
868                 $cmd =~ s/([\(\)])/\\$1/g;
869                 my $name = $$_[0];
870                 my $envname = $$_[1];
871                 
872                 my $envvars = setup_env($envname);
873                 if (not defined($envvars)) {
874                         $msg_ops->skip_testsuite($name, "unable to set up environment $envname");
875                         next;
876                 }
877
878                 run_testsuite($envname, $name, $cmd, $i, $suitestotal, 
879                               $msg_ops);
880
881                 if (defined($opt_analyse_cmd)) {
882                         system("$opt_analyse_cmd \"$name\"");
883                 }
884
885                 teardown_env($envname) if ($opt_resetup_env);
886         }
887 }
888
889 print "\n";
890
891 teardown_env($_) foreach (keys %running_envs);
892
893 $target->stop();
894
895 $msg_ops->summary();
896
897 my $failed = 0;
898
899 # if there were any valgrind failures, show them
900 foreach (<$prefix/valgrind.log*>) {
901         next unless (-s $_);
902         system("grep DWARF2.CFI.reader $_ > /dev/null");
903         if ($? >> 8 == 0) {
904             print "VALGRIND FAILURE\n";
905             $failed++;
906             system("cat $_");
907         }
908 }
909
910 if ($opt_format eq "buildfarm") {
911         print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
912 }
913
914 exit $statistics->{SUITES_FAIL};