lib: Make async_sock includable on its own
[kai/samba.git] / selftest / selftest.pl
1 #!/usr/bin/perl
2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2010 Jelmer Vernooij <jelmer@samba.org>
4 # Copyright (C) 2007-2009 Stefan Metzmacher <metze@samba.org>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 use strict;
20
21 use FindBin qw($RealBin $Script);
22 use File::Spec;
23 use File::Temp qw(tempfile);
24 use Getopt::Long;
25 use POSIX;
26 use Cwd qw(abs_path);
27 use lib "$RealBin";
28 use Subunit;
29 use SocketWrapper;
30
31 eval {
32 require Time::HiRes;
33 Time::HiRes->import("time");
34 };
35 if ($@) {
36         print "You don't have Time::Hires installed !\n";
37 }
38
39 my $opt_help = 0;
40 my $opt_target = "samba";
41 my $opt_quick = 0;
42 my $opt_socket_wrapper = 0;
43 my $opt_socket_wrapper_pcap = undef;
44 my $opt_socket_wrapper_keep_pcap = undef;
45 my $opt_one = 0;
46 my @opt_exclude = ();
47 my @opt_include = ();
48 my $opt_testenv = 0;
49 my $opt_list = 0;
50 my $ldap = undef;
51 my $opt_resetup_env = undef;
52 my $opt_binary_mapping = "";
53 my $opt_load_list = undef;
54 my @testlists = ();
55
56 my $srcdir = ".";
57 my $bindir = "./bin";
58 my $prefix = "./st";
59
60 my @includes = ();
61 my @excludes = ();
62
63 sub pipe_handler {
64         my $sig = shift @_;
65         print STDERR "Exiting early because of SIGPIPE.\n";
66         exit(1);
67 }
68
69 $SIG{PIPE} = \&pipe_handler;
70
71 sub find_in_list($$)
72 {
73         my ($list, $fullname) = @_;
74
75         foreach (@$list) {
76                 if ($fullname =~ /$$_[0]/) {
77                          return ($$_[1]) if ($$_[1]);
78                          return "";
79                 }
80         }
81
82         return undef;
83 }
84
85 sub skip($)
86 {
87         my ($name) = @_;
88
89         return find_in_list(\@excludes, $name);
90 }
91
92 sub getlog_env($);
93
94 sub setup_pcap($)
95 {
96         my ($name) = @_;
97
98         return unless ($opt_socket_wrapper_pcap);
99         return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
100
101         my $fname = $name;
102         $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
103
104         my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
105
106         SocketWrapper::setup_pcap($pcap_file);
107
108         return $pcap_file;
109 }
110
111 sub cleanup_pcap($$)
112 {
113         my ($pcap_file, $exitcode) = @_;
114
115         return unless ($opt_socket_wrapper_pcap);
116         return if ($opt_socket_wrapper_keep_pcap);
117         return unless ($exitcode == 0);
118         return unless defined($pcap_file);
119
120         unlink($pcap_file);
121 }
122
123 # expand strings from %ENV
124 sub expand_environment_strings($)
125 {
126         my $s = shift;
127         # we use a reverse sort so we do the longer ones first
128         foreach my $k (sort { $b cmp $a } keys %ENV) {
129                 $s =~ s/\$$k/$ENV{$k}/g;
130         }
131         return $s;
132 }
133
134 sub run_testsuite($$$$$)
135 {
136         my ($envname, $name, $cmd, $i, $totalsuites) = @_;
137         my $pcap_file = setup_pcap($name);
138
139         Subunit::start_testsuite($name);
140         Subunit::progress_push();
141         Subunit::report_time(time());
142         system($cmd);
143         Subunit::report_time(time());
144         Subunit::progress_pop();
145
146         if ($? == -1) {
147                 Subunit::progress_pop();
148                 Subunit::end_testsuite($name, "error", "Unable to run $cmd: $!");
149                 exit(1);
150         } elsif ($? & 127) {
151                 Subunit::end_testsuite($name, "error",
152                         sprintf("%s died with signal %d, %s coredump\n", $cmd, ($? & 127),  ($? & 128) ? 'with' : 'without'));
153                 exit(1);
154         }
155
156         my $exitcode = $? >> 8;
157
158         my $envlog = getlog_env($envname);
159         if ($envlog ne "") {
160                 print "envlog: $envlog\n";
161         }
162
163         print "command: $cmd\n";
164         printf "expanded command: %s\n", expand_environment_strings($cmd);
165
166         if ($exitcode == 0) {
167                 Subunit::end_testsuite($name, "success");
168         } else {
169                 Subunit::end_testsuite($name, "failure", "Exit code was $exitcode");
170         }
171
172         cleanup_pcap($pcap_file, $exitcode);
173
174         if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
175                 print "PCAP FILE: $pcap_file\n";
176         }
177
178         if ($exitcode != 0) {
179                 exit(1) if ($opt_one);
180         }
181
182         return $exitcode;
183 }
184
185 sub ShowHelp()
186 {
187         print "Samba test runner
188 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
189 Copyright (C) Stefan Metzmacher <metze\@samba.org>
190
191 Usage: $Script [OPTIONS] TESTNAME-REGEX
192
193 Generic options:
194  --help                     this help page
195  --target=samba[3]|win      Samba version to target
196  --testlist=FILE            file to read available tests from
197
198 Paths:
199  --prefix=DIR               prefix to run tests in [st]
200  --srcdir=DIR               source directory [.]
201  --bindir=DIR               binaries directory [./bin]
202
203 Target Specific:
204  --socket-wrapper-pcap      save traffic to pcap directories
205  --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that 
206                             failed
207  --socket-wrapper           enable socket wrapper
208
209 Samba4 Specific:
210  --ldap=openldap|fedora-ds  back samba onto specified ldap server
211
212 Behaviour:
213  --quick                    run quick overall test
214  --one                      abort when the first test fails
215  --testenv                  run a shell in the requested test environment
216  --list                     list available tests
217 ";
218         exit(0);
219 }
220
221 my $result = GetOptions (
222                 'help|h|?' => \$opt_help,
223                 'target=s' => \$opt_target,
224                 'prefix=s' => \$prefix,
225                 'socket-wrapper' => \$opt_socket_wrapper,
226                 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
227                 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
228                 'quick' => \$opt_quick,
229                 'one' => \$opt_one,
230                 'exclude=s' => \@opt_exclude,
231                 'include=s' => \@opt_include,
232                 'srcdir=s' => \$srcdir,
233                 'bindir=s' => \$bindir,
234                 'testenv' => \$opt_testenv,
235                 'list' => \$opt_list,
236                 'ldap:s' => \$ldap,
237                 'resetup-environment' => \$opt_resetup_env,
238                 'testlist=s' => \@testlists,
239                 'load-list=s' => \$opt_load_list,
240                 'binary-mapping=s' => \$opt_binary_mapping
241             );
242
243 exit(1) if (not $result);
244
245 ShowHelp() if ($opt_help);
246
247 die("--list and --testenv are mutually exclusive") if ($opt_list and $opt_testenv);
248
249 # we want unbuffered output
250 $| = 1;
251
252 my @tests = @ARGV;
253
254 # quick hack to disable rpc validation when using valgrind - its way too slow
255 unless (defined($ENV{VALGRIND})) {
256         $ENV{VALIDATE} = "validate";
257         $ENV{MALLOC_CHECK_} = 2;
258 }
259
260 # make all our python scripts unbuffered
261 $ENV{PYTHONUNBUFFERED} = 1;
262
263 my $bindir_abs = abs_path($bindir);
264
265 # Backwards compatibility:
266 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
267         if (defined($ENV{FEDORA_DS_ROOT})) {
268                 $ldap = "fedora-ds";
269         } else {
270                 $ldap = "openldap";
271         }
272 }
273
274 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
275 if ($ldap) {
276         # LDAP is slow
277         $torture_maxtime *= 2;
278 }
279
280 $prefix =~ s+//+/+;
281 $prefix =~ s+/./+/+;
282 $prefix =~ s+/$++;
283
284 die("using an empty prefix isn't allowed") unless $prefix ne "";
285
286 # Ensure we have the test prefix around.
287 #
288 # We need restrictive
289 # permissions on this as some subdirectories in this tree will have
290 # wider permissions (ie 0777) and this would allow other users on the
291 # host to subvert the test process.
292 mkdir($prefix, 0700) unless -d $prefix;
293 chmod 0700, $prefix;
294
295 my $prefix_abs = abs_path($prefix);
296 my $tmpdir_abs = abs_path("$prefix/tmp");
297 mkdir($tmpdir_abs, 0777) unless -d $tmpdir_abs;
298
299 my $srcdir_abs = abs_path($srcdir);
300
301 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
302 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
303
304 $ENV{PREFIX} = $prefix;
305 $ENV{KRB5CCNAME} = "$prefix/krb5ticket";
306 $ENV{PREFIX_ABS} = $prefix_abs;
307 $ENV{SRCDIR} = $srcdir;
308 $ENV{SRCDIR_ABS} = $srcdir_abs;
309 $ENV{BINDIR} = $bindir_abs;
310
311 my $tls_enabled = not $opt_quick;
312 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
313
314 sub prefix_pathvar($$)
315 {
316         my ($name, $newpath) = @_;
317         if (defined($ENV{$name})) {
318                 $ENV{$name} = "$newpath:$ENV{$name}";
319         } else {
320                 $ENV{$name} = $newpath;
321         }
322 }
323 prefix_pathvar("PKG_CONFIG_PATH", "$bindir_abs/pkgconfig");
324 prefix_pathvar("PYTHONPATH", "$bindir_abs/python");
325
326 if ($opt_socket_wrapper_keep_pcap) {
327         # Socket wrapper keep pcap implies socket wrapper pcap
328         $opt_socket_wrapper_pcap = 1;
329 }
330
331 if ($opt_socket_wrapper_pcap) {
332         # Socket wrapper pcap implies socket wrapper
333         $opt_socket_wrapper = 1;
334 }
335
336 my $socket_wrapper_dir;
337 if ($opt_socket_wrapper) {
338         $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix_abs/w", $opt_socket_wrapper_pcap);
339         print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
340 } elsif (not $opt_list) {
341          unless ($< == 0) { 
342                  warn("not using socket wrapper, but also not running as root. Will not be able to listen on proper ports");
343          }
344 }
345
346 my $target;
347 my $testenv_default = "none";
348
349 my %binary_mapping = ();
350 if ($opt_binary_mapping) {
351     my @binmapping_list = split(/,/, $opt_binary_mapping);
352     foreach my $mapping (@binmapping_list) {
353         my ($bin, $map) = split(/\:/, $mapping);
354         $binary_mapping{$bin} = $map;
355     }
356 }
357
358 $ENV{BINARY_MAPPING} = $opt_binary_mapping;
359
360 # After this many seconds, the server will self-terminate.  All tests
361 # must terminate in this time, and testenv will only stay alive this
362 # long
363
364 my $server_maxtime = 7500;
365 if (defined($ENV{SMBD_MAXTIME}) and $ENV{SMBD_MAXTIME} ne "") {
366     $server_maxtime = $ENV{SMBD_MAXTIME};
367 }
368
369 unless ($opt_list) {
370         if ($opt_target eq "samba") {
371                 if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
372                         die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'.  Exiting....");
373                 }
374                 $testenv_default = "dc";
375                 require target::Samba;
376                 $target = new Samba($bindir, \%binary_mapping, $ldap, $srcdir, $server_maxtime);
377         } elsif ($opt_target eq "samba3") {
378                 if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
379                         die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'.  Exiting....");
380                 }
381                 $testenv_default = "member";
382                 require target::Samba3;
383                 $target = new Samba3($bindir, \%binary_mapping, $srcdir_abs, $server_maxtime);
384         }
385 }
386
387 sub read_test_regexes($)
388 {
389         my ($name) = @_;
390         my @ret = ();
391         open(LF, "<$name") or die("unable to read $name: $!");
392         while (<LF>) { 
393                 chomp; 
394                 next if (/^#/);
395                 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
396                         push (@ret, [$1, $4]);
397                 } else {
398                         s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
399                         push (@ret, [$_, undef]); 
400                 }
401         }
402         close(LF);
403         return @ret;
404 }
405
406 foreach (@opt_exclude) {
407         push (@excludes, read_test_regexes($_));
408 }
409
410 foreach (@opt_include) {
411         push (@includes, read_test_regexes($_));
412 }
413
414 my $interfaces = join(',', ("127.0.0.11/8",
415                             "127.0.0.12/8",
416                             "127.0.0.13/8",
417                             "127.0.0.14/8",
418                             "127.0.0.15/8",
419                             "127.0.0.16/8"));
420
421 my $clientdir = "$prefix_abs/client";
422
423 my $conffile = "$clientdir/client.conf";
424 $ENV{SMB_CONF_PATH} = $conffile;
425
426 sub write_clientconf($$$)
427 {
428         my ($conffile, $clientdir, $vars) = @_;
429
430         mkdir("$clientdir", 0777) unless -d "$clientdir";
431
432         if ( -d "$clientdir/private" ) {
433                 unlink <$clientdir/private/*>;
434         } else {
435                 mkdir("$clientdir/private", 0777);
436         }
437
438         if ( -d "$clientdir/lockdir" ) {
439                 unlink <$clientdir/lockdir/*>;
440         } else {
441                 mkdir("$clientdir/lockdir", 0777);
442         }
443
444         if ( -d "$clientdir/statedir" ) {
445                 unlink <$clientdir/statedir/*>;
446         } else {
447                 mkdir("$clientdir/statedir", 0777);
448         }
449
450         if ( -d "$clientdir/cachedir" ) {
451                 unlink <$clientdir/cachedir/*>;
452         } else {
453                 mkdir("$clientdir/cachedir", 0777);
454         }
455
456         # this is ugly, but the ncalrpcdir needs exactly 0755
457         # otherwise tests fail.
458         my $mask = umask;
459         umask 0022;
460         if ( -d "$clientdir/ncalrpcdir/np" ) {
461                 unlink <$clientdir/ncalrpcdir/np/*>;
462                 rmdir "$clientdir/ncalrpcdir/np";
463         }
464         if ( -d "$clientdir/ncalrpcdir" ) {
465                 unlink <$clientdir/ncalrpcdir/*>;
466                 rmdir "$clientdir/ncalrpcdir";
467         }
468         mkdir("$clientdir/ncalrpcdir", 0755);
469         umask $mask;
470
471         open(CF, ">$conffile");
472         print CF "[global]\n";
473         print CF "\tnetbios name = client\n";
474         if (defined($vars->{DOMAIN})) {
475                 print CF "\tworkgroup = $vars->{DOMAIN}\n";
476         }
477         if (defined($vars->{REALM})) {
478                 print CF "\trealm = $vars->{REALM}\n";
479         }
480         if ($opt_socket_wrapper) {
481                 print CF "\tinterfaces = $interfaces\n";
482         }
483         print CF "
484         private dir = $clientdir/private
485         lock dir = $clientdir/lockdir
486         state directory = $clientdir/statedir
487         cache directory = $clientdir/cachedir
488         ncalrpc dir = $clientdir/ncalrpcdir
489         name resolve order = file bcast
490         panic action = $RealBin/gdb_backtrace \%d
491         max xmit = 32K
492         notify:inotify = false
493         ldb:nosync = true
494         system:anonymous = true
495         client lanman auth = Yes
496         log level = 1
497         torture:basedir = $clientdir
498 #We don't want to pass our self-tests if the PAC code is wrong
499         gensec:require_pac = true
500         resolv:host file = $prefix_abs/dns_host_file
501 #We don't want to run 'speed' tests for very long
502         torture:timelimit = 1
503 ";
504         close(CF);
505 }
506
507 my @todo = ();
508
509 sub should_run_test($)
510 {
511         my $name = shift;
512         if ($#tests == -1) {
513                 return 1;
514         }
515         for (my $i=0; $i <= $#tests; $i++) {
516                 if ($name =~ /$tests[$i]/i) {
517                         return 1;
518                 }
519         }
520         return 0;
521 }
522
523 sub read_testlist($)
524 {
525         my ($filename) = @_;
526
527         my @ret = ();
528         open(IN, $filename) or die("Unable to open $filename: $!");
529
530         while (<IN>) {
531                 if (/-- TEST(-LOADLIST|-IDLIST|) --\n/) {
532                         my $supports_loadlist = (defined($1) and $1 eq "-LOADLIST");
533                         my $supports_idlist = (defined($1) and $1 eq "-IDLIST");
534                         my $name = <IN>;
535                         $name =~ s/\n//g;
536                         my $env = <IN>;
537                         $env =~ s/\n//g;
538                         my $cmdline = <IN>;
539                         $cmdline =~ s/\n//g;
540                         if (should_run_test($name) == 1) {
541                                 push (@ret, [$name, $env, $cmdline, $supports_loadlist, $supports_idlist]);
542                         }
543                 } else {
544                         print;
545                 }
546         }
547         close(IN) or die("Error creating recipe");
548         return @ret;
549 }
550
551 if ($#testlists == -1) {
552         die("No testlists specified");
553 }
554
555 $ENV{SELFTEST_PREFIX} = "$prefix_abs";
556 $ENV{SELFTEST_TMPDIR} = "$tmpdir_abs";
557 $ENV{TEST_DATA_PREFIX} = "$tmpdir_abs";
558 if ($opt_socket_wrapper) {
559         $ENV{SELFTEST_INTERFACES} = $interfaces;
560 } else {
561         $ENV{SELFTEST_INTERFACES} = "";
562 }
563 if ($opt_quick) {
564         $ENV{SELFTEST_QUICK} = "1";
565 } else {
566         $ENV{SELFTEST_QUICK} = "";
567 }
568 $ENV{SELFTEST_MAXTIME} = $torture_maxtime;
569
570 my @available = ();
571 foreach my $fn (@testlists) {
572         foreach (read_testlist($fn)) {
573                 my $name = $$_[0];
574                 next if (@includes and not defined(find_in_list(\@includes, $name)));
575                 push (@available, $_);
576         }
577 }
578
579 my $restricted = undef;
580 my $restricted_used = {};
581
582 if ($opt_load_list) {
583         $restricted = [];
584         open(LOAD_LIST, "<$opt_load_list") or die("Unable to open $opt_load_list");
585         while (<LOAD_LIST>) {
586                 chomp;
587                 push (@$restricted, $_);
588         }
589         close(LOAD_LIST);
590 }
591
592 my $individual_tests = undef;
593 $individual_tests = {};
594
595 foreach my $testsuite (@available) {
596         my $name = $$testsuite[0];
597         my $skipreason = skip($name);
598         if (defined($restricted)) {
599                 # Find the testsuite for this test
600                 my $match = undef;
601                 foreach my $r (@$restricted) {
602                         if ($r eq $name) {
603                                 $individual_tests->{$name} = [];
604                                 $match = $r;
605                                 $restricted_used->{$r} = 1;
606                         } elsif (substr($r, 0, length($name)+1) eq "$name.") {
607                                 push(@{$individual_tests->{$name}}, $r);
608                                 $match = $r;
609                                 $restricted_used->{$r} = 1;
610                         }
611                 }
612                 if ($match) {
613                         if (defined($skipreason)) {
614                                 if (not $opt_list) {
615                                         Subunit::skip_testsuite($name, $skipreason);
616                                 }
617                         } else {
618                                 push(@todo, $testsuite);
619                         }
620                 }
621         } elsif (defined($skipreason)) {
622                 if (not $opt_list) {
623                         Subunit::skip_testsuite($name, $skipreason);
624                 }
625         } else {
626                 push(@todo, $testsuite);
627         }
628 }
629
630 if (defined($restricted)) {
631         foreach (@$restricted) {
632                 unless (defined($restricted_used->{$_})) {
633                         print "No test or testsuite found matching $_\n";
634                 }
635         }
636 } elsif ($#todo == -1) {
637         print STDERR "No tests to run\n";
638         exit(1);
639 }
640
641 my $suitestotal = $#todo + 1;
642
643 unless ($opt_list) {
644         Subunit::progress($suitestotal);
645         Subunit::report_time(time());
646 }
647
648 my $i = 0;
649 $| = 1;
650
651 my %running_envs = ();
652
653 sub get_running_env($)
654 {
655         my ($name) = @_;
656
657         my $envname = $name;
658
659         $envname =~ s/:.*//;
660
661         return $running_envs{$envname};
662 }
663
664 my @exported_envvars = (
665         # domain stuff
666         "DOMAIN",
667         "REALM",
668
669         # domain controller stuff
670         "DC_SERVER",
671         "DC_SERVER_IP",
672         "DC_NETBIOSNAME",
673         "DC_NETBIOSALIAS",
674
675         # domain member
676         "MEMBER_SERVER",
677         "MEMBER_SERVER_IP",
678         "MEMBER_NETBIOSNAME",
679         "MEMBER_NETBIOSALIAS",
680
681         # rpc proxy controller stuff
682         "RPC_PROXY_SERVER",
683         "RPC_PROXY_SERVER_IP",
684         "RPC_PROXY_NETBIOSNAME",
685         "RPC_PROXY_NETBIOSALIAS",
686
687         # domain controller stuff for Vampired DC
688         "VAMPIRE_DC_SERVER",
689         "VAMPIRE_DC_SERVER_IP",
690         "VAMPIRE_DC_NETBIOSNAME",
691         "VAMPIRE_DC_NETBIOSALIAS",
692
693         # server stuff
694         "SERVER",
695         "SERVER_IP",
696         "NETBIOSNAME",
697         "NETBIOSALIAS",
698
699         # user stuff
700         "USERNAME",
701         "USERID",
702         "PASSWORD",
703         "DC_USERNAME",
704         "DC_PASSWORD",
705
706         # misc stuff
707         "KRB5_CONFIG",
708         "WINBINDD_SOCKET_DIR",
709         "WINBINDD_PRIV_PIPE_DIR",
710         "NMBD_SOCKET_DIR",
711         "LOCAL_PATH",
712
713         # nss_wrapper
714         "NSS_WRAPPER_PASSWD",
715         "NSS_WRAPPER_GROUP"
716
717 );
718
719 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { 
720         my $signame = shift;
721         teardown_env($_) foreach(keys %running_envs);
722         die("Received signal $signame");
723 };
724
725 sub setup_env($$)
726 {
727         my ($name, $prefix) = @_;
728
729         my $testenv_vars = undef;
730
731         my $envname = $name;
732         my $option = $name;
733
734         $envname =~ s/:.*//;
735         $option =~ s/^[^:]*//;
736         $option =~ s/^://;
737
738         $option = "client" if $option eq "";
739
740         if ($envname eq "none") {
741                 $testenv_vars = {};
742         } elsif (defined(get_running_env($envname))) {
743                 $testenv_vars = get_running_env($envname);
744                 if (not $testenv_vars->{target}->check_env($testenv_vars)) {
745                         print $testenv_vars->{target}->getlog_env($testenv_vars);
746                         $testenv_vars = undef;
747                 }
748         } else {
749                 $testenv_vars = $target->setup_env($envname, $prefix);
750                 if (defined($testenv_vars) and $testenv_vars eq "UNKNOWN") {
751                     return $testenv_vars;
752                 } elsif (defined($testenv_vars) && not defined($testenv_vars->{target})) {
753                         $testenv_vars->{target} = $target;
754                 }
755                 if (not defined($testenv_vars)) {
756                         warn("$opt_target can't start up known environment '$envname'");
757                 }
758         }
759
760         
761         return undef unless defined($testenv_vars);
762
763         $running_envs{$envname} = $testenv_vars;
764
765         if ($option eq "local") {
766                 SocketWrapper::set_default_iface($testenv_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
767                 $ENV{SMB_CONF_PATH} = $testenv_vars->{SERVERCONFFILE};
768         } elsif ($option eq "client") {
769                 SocketWrapper::set_default_iface(11);
770                 write_clientconf($conffile, $clientdir, $testenv_vars);
771                 $ENV{SMB_CONF_PATH} = $conffile;
772         } else {
773                 die("Unknown option[$option] for envname[$envname]");
774         }
775
776         foreach (@exported_envvars) {
777                 if (defined($testenv_vars->{$_})) {
778                         $ENV{$_} = $testenv_vars->{$_};
779                 } else {
780                         delete $ENV{$_};
781                 }
782         }
783
784         return $testenv_vars;
785 }
786
787 sub exported_envvars_str($)
788 {
789         my ($testenv_vars) = @_;
790         my $out = "";
791
792         foreach (@exported_envvars) {
793                 next unless defined($testenv_vars->{$_});
794                 $out .= $_."=".$testenv_vars->{$_}."\n";
795         }
796
797         return $out;
798 }
799
800 sub getlog_env($)
801 {
802         my ($envname) = @_;
803         return "" if ($envname eq "none");
804         my $env = get_running_env($envname);
805         return $env->{target}->getlog_env($env);
806 }
807
808 sub check_env($)
809 {
810         my ($envname) = @_;
811         return 1 if ($envname eq "none");
812         my $env = get_running_env($envname);
813         return $env->{target}->check_env($env);
814 }
815
816 sub teardown_env($)
817 {
818         my ($envname) = @_;
819         return if ($envname eq "none");
820         my $env = get_running_env($envname);
821         $env->{target}->teardown_env($env);
822         delete $running_envs{$envname};
823 }
824
825 # This 'global' file needs to be empty when we start
826 unlink("$prefix_abs/dns_host_file");
827
828 if ($opt_testenv) {
829         my $testenv_name = $ENV{SELFTEST_TESTENV};
830         $testenv_name = $testenv_default unless defined($testenv_name);
831
832         my $testenv_vars = setup_env($testenv_name, $prefix);
833
834         die("Unable to setup environment $testenv_name") unless ($testenv_vars);
835
836         $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
837         $ENV{ENVNAME} = $testenv_name;
838
839         my $envvarstr = exported_envvars_str($testenv_vars);
840
841         my $term = ($ENV{TERMINAL} or "xterm -e");
842         system("$term 'echo -e \"
843 Welcome to the Samba4 Test environment '$testenv_name'
844
845 This matches the client environment used in make test
846 server is pid `cat \$PIDDIR/samba.pid`
847
848 Some useful environment variables:
849 TORTURE_OPTIONS=\$TORTURE_OPTIONS
850 SMB_CONF_PATH=\$SMB_CONF_PATH
851
852 $envvarstr
853 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
854         teardown_env($testenv_name);
855 } elsif ($opt_list) {
856         foreach (@todo) {
857                 my $cmd = $$_[2];
858                 my $name = $$_[0];
859                 my $envname = $$_[1];
860
861                 unless($cmd =~ /\$LISTOPT/) {
862                         warn("Unable to list tests in $name");
863                         next;
864                 }
865
866                 $cmd =~ s/\$LISTOPT/--list/g;
867
868                 system($cmd);
869
870                 if ($? == -1) {
871                         die("Unable to run $cmd: $!");
872                 } elsif ($? & 127) {
873                         die(snprintf("%s died with signal %d, %s coredump\n", $cmd, ($? & 127),  ($? & 128) ? 'with' : 'without'));
874                 }
875
876                 my $exitcode = $? >> 8;
877                 if ($exitcode != 0) {
878                         die("$cmd exited with exit code $exitcode");
879                 }
880         }
881 } else {
882         foreach (@todo) {
883                 $i++;
884                 my $cmd = $$_[2];
885                 my $name = $$_[0];
886                 my $envname = $$_[1];
887
888                 my $envvars = setup_env($envname, $prefix);
889                 if (not defined($envvars)) {
890                         Subunit::start_testsuite($name);
891                         Subunit::end_testsuite($name, "error",
892                                 "unable to set up environment $envname - exiting");
893                         next;
894                 } elsif ($envvars eq "UNKNOWN") {
895                         Subunit::start_testsuite($name);
896                         Subunit::end_testsuite($name, "skip",
897                                 "environment $envname is unknown in this test backend - skipping");
898                         next;
899                 }
900
901                 # Generate a file with the individual tests to run, if the 
902                 # test runner for this test suite supports it.
903                 if ($individual_tests and $individual_tests->{$name}) {
904                         if ($$_[3]) {
905                                 my ($fh, $listid_file) = tempfile(UNLINK => 0);
906                                 foreach my $test (@{$individual_tests->{$name}}) {
907                                         print $fh substr($test, length($name)+1) . "\n";
908                                 }
909                                 $cmd =~ s/\$LOADLIST/--load-list=$listid_file/g;
910                         } elsif ($$_[4]) {
911                                 $cmd =~ s/\s+[^\s]+\s*$//;
912                                 $cmd .= " " . join(' ', @{$individual_tests->{$name}});
913                         }
914                 }
915
916                 run_testsuite($envname, $name, $cmd, $i, $suitestotal);
917
918                 teardown_env($envname) if ($opt_resetup_env);
919         }
920 }
921
922 print "\n";
923
924 teardown_env($_) foreach (keys %running_envs);
925
926 my $failed = 0;
927
928 # if there were any valgrind failures, show them
929 foreach (<$prefix/valgrind.log*>) {
930         next unless (-s $_);
931         print "VALGRIND FAILURE\n";
932         $failed++;
933         system("cat $_");
934 }
935 exit 0;