selftest: generate a ramdon domain sid during provision and export as SAMSID/[TRUST_...
[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 use target::Samba;
31
32 eval {
33 require Time::HiRes;
34 Time::HiRes->import("time");
35 };
36 if ($@) {
37         print "You don't have Time::Hires installed !\n";
38 }
39
40 my $opt_help = 0;
41 my $opt_target = "samba";
42 my $opt_quick = 0;
43 my $opt_socket_wrapper = 0;
44 my $opt_socket_wrapper_pcap = undef;
45 my $opt_socket_wrapper_keep_pcap = undef;
46 my $opt_random_order = 0;
47 my $opt_one = 0;
48 my @opt_exclude = ();
49 my @opt_include = ();
50 my @opt_exclude_env = ();
51 my @opt_include_env = ();
52 my $opt_testenv = 0;
53 my $opt_list = 0;
54 my $opt_mitkrb5 = 0;
55 my $ldap = undef;
56 my $opt_resetup_env = undef;
57 my $opt_load_list = undef;
58 my $opt_libnss_wrapper_so_path = "";
59 my $opt_libresolv_wrapper_so_path = "";
60 my $opt_libsocket_wrapper_so_path = "";
61 my $opt_libuid_wrapper_so_path = "";
62 my $opt_use_dns_faking = 0;
63 my @testlists = ();
64
65 my $srcdir = ".";
66 my $bindir = "./bin";
67 my $prefix = "./st";
68
69 my @includes = ();
70 my @excludes = ();
71
72 sub find_in_list($$)
73 {
74         my ($list, $fullname) = @_;
75
76         foreach (@$list) {
77                 if ($fullname =~ /$$_[0]/) {
78                          return ($$_[1]) if ($$_[1]);
79                          return "";
80                 }
81         }
82
83         return undef;
84 }
85
86 sub skip
87 {
88         my ($name, $envname) = @_;
89         my ($env_basename, $env_localpart) = split(/:/, $envname);
90
91         if ($opt_target eq "samba3" && $Samba::ENV_NEEDS_AD_DC{$env_basename}) {
92                 return "environment $envname is disabled as this build does not include an AD DC";
93         }
94
95         if (@opt_include_env && !(grep {$_ eq $env_basename} @opt_include_env)) {
96                 return "environment $envname is disabled (via --include-env command line option) in this test run - skipping";
97         } elsif (@opt_exclude_env && grep {$_ eq $env_basename} @opt_exclude_env) {
98                 return "environment $envname is disabled (via --exclude-env command line option) in this test run - skipping";
99         }
100
101         return find_in_list(\@excludes, $name);
102 }
103
104 sub getlog_env($);
105
106 sub setup_pcap($)
107 {
108         my ($name) = @_;
109
110         return unless ($opt_socket_wrapper_pcap);
111         return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
112
113         my $fname = $name;
114         $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
115
116         my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
117
118         SocketWrapper::setup_pcap($pcap_file);
119
120         return $pcap_file;
121 }
122
123 sub cleanup_pcap($$)
124 {
125         my ($pcap_file, $exitcode) = @_;
126
127         return unless ($opt_socket_wrapper_pcap);
128         return if ($opt_socket_wrapper_keep_pcap);
129         return unless ($exitcode == 0);
130         return unless defined($pcap_file);
131
132         unlink($pcap_file);
133 }
134
135 # expand strings from %ENV
136 sub expand_environment_strings($)
137 {
138         my $s = shift;
139         # we use a reverse sort so we do the longer ones first
140         foreach my $k (sort { $b cmp $a } keys %ENV) {
141                 $s =~ s/\$$k/$ENV{$k}/g;
142         }
143         return $s;
144 }
145
146 sub run_testsuite($$$$$)
147 {
148         my ($envname, $name, $cmd, $i, $totalsuites) = @_;
149         my $pcap_file = setup_pcap($name);
150
151         Subunit::start_testsuite($name);
152         Subunit::progress_push();
153         Subunit::report_time(time());
154         system($cmd);
155         Subunit::report_time(time());
156         Subunit::progress_pop();
157
158         if ($? == -1) {
159                 print "command: $cmd\n";
160                 printf "expanded command: %s\n", expand_environment_strings($cmd);
161                 Subunit::end_testsuite($name, "error", "Unable to run $cmd: $!");
162                 exit(1);
163         } elsif ($? & 127) {
164                 print "command: $cmd\n";
165                 printf "expanded command: %s\n", expand_environment_strings($cmd);
166                 Subunit::end_testsuite($name, "error",
167                         sprintf("%s died with signal %d, %s coredump\n", $cmd, ($? & 127),  ($? & 128) ? 'with' : 'without'));
168                 exit(1);
169         }
170
171         my $exitcode = $? >> 8;
172
173         my $envlog = getlog_env($envname);
174         if ($envlog ne "") {
175                 print "envlog: $envlog\n";
176         }
177
178         print "command: $cmd\n";
179         printf "expanded command: %s\n", expand_environment_strings($cmd);
180
181         if ($exitcode == 0) {
182                 Subunit::end_testsuite($name, "success");
183         } else {
184                 Subunit::end_testsuite($name, "failure", "Exit code was $exitcode");
185         }
186
187         cleanup_pcap($pcap_file, $exitcode);
188
189         if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
190                 print "PCAP FILE: $pcap_file\n";
191         }
192
193         if ($exitcode != 0) {
194                 exit(1) if ($opt_one);
195         }
196
197         return $exitcode;
198 }
199
200 sub ShowHelp()
201 {
202         print "Samba test runner
203 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
204 Copyright (C) Stefan Metzmacher <metze\@samba.org>
205
206 Usage: $Script [OPTIONS] TESTNAME-REGEX [TESTNAME-REGEX...]
207
208 Generic options:
209  --help                     this help page
210  --target=samba[3]|win      Samba version to target
211  --testlist=FILE            file to read available tests from
212  --exclude=FILE             Exclude tests listed in the file
213  --include=FILE             Include tests listed in the file
214  --exclude-env=ENV          Exclude tests for the specified environment
215  --include-env=ENV          Include tests for the specified environment
216
217 Paths:
218  --prefix=DIR               prefix to run tests in [st]
219  --srcdir=DIR               source directory [.]
220  --bindir=DIR               binaries directory [./bin]
221
222 Preload cwrap:
223  --nss_wrapper_so_path=FILE the nss_wrapper library to preload
224  --resolv_wrapper_so_path=FILE the resolv_wrapper library to preload
225  --socket_wrapper_so_path=FILE the socket_wrapper library to preload
226  --uid_wrapper_so_path=FILE the uid_wrapper library to preload
227
228 DNS:
229   --use-dns-faking          Fake DNS entries rather than talking to our
230                             DNS implementation.
231
232 Target Specific:
233  --socket-wrapper-pcap      save traffic to pcap directories
234  --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that 
235                             failed
236  --socket-wrapper           enable socket wrapper
237
238 Samba4 Specific:
239  --ldap=openldap|fedora-ds  back samba onto specified ldap server
240
241 Behaviour:
242  --quick                    run quick overall test
243  --one                      abort when the first test fails
244  --testenv                  run a shell in the requested test environment
245  --list                     list available tests
246 ";
247         exit(0);
248 }
249
250 my $result = GetOptions (
251                 'help|h|?' => \$opt_help,
252                 'target=s' => \$opt_target,
253                 'prefix=s' => \$prefix,
254                 'socket-wrapper' => \$opt_socket_wrapper,
255                 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
256                 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
257                 'quick' => \$opt_quick,
258                 'one' => \$opt_one,
259                 'exclude=s' => \@opt_exclude,
260                 'include=s' => \@opt_include,
261                 'exclude-env=s' => \@opt_exclude_env,
262                 'include-env=s' => \@opt_include_env,
263                 'srcdir=s' => \$srcdir,
264                 'bindir=s' => \$bindir,
265                 'testenv' => \$opt_testenv,
266                 'list' => \$opt_list,
267                 'mitkrb5' => \$opt_mitkrb5,
268                 'ldap:s' => \$ldap,
269                 'resetup-environment' => \$opt_resetup_env,
270                 'testlist=s' => \@testlists,
271                 'random-order' => \$opt_random_order,
272                 'load-list=s' => \$opt_load_list,
273                 'nss_wrapper_so_path=s' => \$opt_libnss_wrapper_so_path,
274                 'resolv_wrapper_so_path=s' => \$opt_libresolv_wrapper_so_path,
275                 'socket_wrapper_so_path=s' => \$opt_libsocket_wrapper_so_path,
276                 'uid_wrapper_so_path=s' => \$opt_libuid_wrapper_so_path,
277                 'use-dns-faking' => \$opt_use_dns_faking
278             );
279
280 exit(1) if (not $result);
281
282 ShowHelp() if ($opt_help);
283
284 die("--list and --testenv are mutually exclusive") if ($opt_list and $opt_testenv);
285
286 # we want unbuffered output
287 $| = 1;
288
289 my @tests = @ARGV;
290
291 # quick hack to disable rpc validation when using valgrind - its way too slow
292 unless (defined($ENV{VALGRIND})) {
293         $ENV{VALIDATE} = "validate";
294         $ENV{MALLOC_CHECK_} = 3;
295 }
296
297 # make all our python scripts unbuffered
298 $ENV{PYTHONUNBUFFERED} = 1;
299
300 my $bindir_abs = abs_path($bindir);
301
302 # Backwards compatibility:
303 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
304         if (defined($ENV{FEDORA_DS_ROOT})) {
305                 $ldap = "fedora-ds";
306         } else {
307                 $ldap = "openldap";
308         }
309 }
310
311 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
312 if ($ldap) {
313         # LDAP is slow
314         $torture_maxtime *= 2;
315 }
316
317 $prefix =~ s+//+/+;
318 $prefix =~ s+/./+/+;
319 $prefix =~ s+/$++;
320
321 die("using an empty prefix isn't allowed") unless $prefix ne "";
322
323 # Ensure we have the test prefix around.
324 #
325 # We need restrictive
326 # permissions on this as some subdirectories in this tree will have
327 # wider permissions (ie 0777) and this would allow other users on the
328 # host to subvert the test process.
329 umask 0077;
330 mkdir($prefix, 0700) unless -d $prefix;
331 chmod 0700, $prefix;
332 # We need to have no umask limitations for the tests.
333 umask 0000;
334
335 my $prefix_abs = abs_path($prefix);
336 my $tmpdir_abs = abs_path("$prefix/tmp");
337 mkdir($tmpdir_abs, 0777) unless -d $tmpdir_abs;
338
339 my $srcdir_abs = abs_path($srcdir);
340
341 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
342 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
343
344 $ENV{SAMBA_SELFTEST} = "1";
345
346 $ENV{PREFIX} = $prefix;
347 $ENV{PREFIX_ABS} = $prefix_abs;
348 $ENV{SRCDIR} = $srcdir;
349 $ENV{SRCDIR_ABS} = $srcdir_abs;
350 $ENV{GNUPGHOME} = "$srcdir_abs/selftest/gnupg";
351 $ENV{BINDIR} = $bindir_abs;
352
353 my $tls_enabled = not $opt_quick;
354 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
355
356 sub prefix_pathvar($$)
357 {
358         my ($name, $newpath) = @_;
359         if (defined($ENV{$name})) {
360                 $ENV{$name} = "$newpath:$ENV{$name}";
361         } else {
362                 $ENV{$name} = $newpath;
363         }
364 }
365 prefix_pathvar("PKG_CONFIG_PATH", "$bindir_abs/pkgconfig");
366 prefix_pathvar("PYTHONPATH", "$bindir_abs/python");
367
368 if ($opt_socket_wrapper_keep_pcap) {
369         # Socket wrapper keep pcap implies socket wrapper pcap
370         $opt_socket_wrapper_pcap = 1;
371 }
372
373 if ($opt_socket_wrapper_pcap) {
374         # Socket wrapper pcap implies socket wrapper
375         $opt_socket_wrapper = 1;
376 }
377
378 my $ld_preload = $ENV{LD_PRELOAD};
379
380 if ($opt_libnss_wrapper_so_path) {
381         if ($ld_preload) {
382                 $ld_preload = "$ld_preload:$opt_libnss_wrapper_so_path";
383         } else {
384                 $ld_preload = "$opt_libnss_wrapper_so_path";
385         }
386 }
387
388 if ($opt_libresolv_wrapper_so_path) {
389         if ($ld_preload) {
390                 $ld_preload = "$ld_preload:$opt_libresolv_wrapper_so_path";
391         } else {
392                 $ld_preload = "$opt_libresolv_wrapper_so_path";
393         }
394 }
395
396 if ($opt_libsocket_wrapper_so_path) {
397         if ($ld_preload) {
398                 $ld_preload = "$ld_preload:$opt_libsocket_wrapper_so_path";
399         } else {
400                 $ld_preload = "$opt_libsocket_wrapper_so_path";
401         }
402 }
403
404 if ($opt_libuid_wrapper_so_path) {
405         if ($ld_preload) {
406                 $ld_preload = "$ld_preload:$opt_libuid_wrapper_so_path";
407         } else {
408                 $ld_preload = "$opt_libuid_wrapper_so_path";
409         }
410 }
411
412 $ENV{LD_PRELOAD} = $ld_preload;
413 print "LD_PRELOAD=$ENV{LD_PRELOAD}\n";
414
415 # Enable uid_wrapper globally
416 $ENV{UID_WRAPPER} = 1;
417
418 # Disable RTLD_DEEPBIND hack for Samba bind dlz module
419 #
420 # This is needed in order to allow the ldb_*ldap module
421 # to work with a preloaded socket wrapper.
422 $ENV{LDB_MODULES_DISABLE_DEEPBIND} = 1;
423
424 my $socket_wrapper_dir;
425 if ($opt_socket_wrapper) {
426         $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix_abs/w", $opt_socket_wrapper_pcap);
427         print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
428 } elsif (not $opt_list) {
429          unless ($< == 0) {
430                  warn("not using socket wrapper, but also not running as root. Will not be able to listen on proper ports");
431          }
432 }
433
434 if ($opt_use_dns_faking) {
435         print "DNS: Faking nameserver\n";
436         $ENV{SAMBA_DNS_FAKING} = 1;
437 }
438
439 my $target;
440 my $testenv_default = "none";
441
442 if ($opt_mitkrb5 == 1) {
443         $ENV{MITKRB5} = $opt_mitkrb5;
444 }
445
446 # After this many seconds, the server will self-terminate.  All tests
447 # must terminate in this time, and testenv will only stay alive this
448 # long
449
450 my $server_maxtime;
451 if ($opt_testenv) {
452     # 1 year should be enough :-)
453     $server_maxtime = 365 * 24 * 60 * 60;
454 } else {
455     # make test should run under 5 hours
456     $server_maxtime = 5 * 60 * 60;
457 }
458
459 if (defined($ENV{SMBD_MAXTIME}) and $ENV{SMBD_MAXTIME} ne "") {
460     $server_maxtime = $ENV{SMBD_MAXTIME};
461 }
462
463 $target = new Samba($bindir, $ldap, $srcdir, $server_maxtime);
464 unless ($opt_list) {
465         if ($opt_target eq "samba") {
466                 $testenv_default = "ad_dc";
467         } elsif ($opt_target eq "samba3") {
468                 $testenv_default = "nt4_member";
469         }
470 }
471
472 sub read_test_regexes($)
473 {
474         my ($name) = @_;
475         my @ret = ();
476         open(LF, "<$name") or die("unable to read $name: $!");
477         while (<LF>) { 
478                 chomp; 
479                 next if (/^#/);
480                 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
481                         push (@ret, [$1, $4]);
482                 } else {
483                         s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
484                         push (@ret, [$_, undef]); 
485                 }
486         }
487         close(LF);
488         return @ret;
489 }
490
491 foreach (@opt_exclude) {
492         push (@excludes, read_test_regexes($_));
493 }
494
495 foreach (@opt_include) {
496         push (@includes, read_test_regexes($_));
497 }
498
499 my $interfaces = join(',', ("127.0.0.11/8",
500                             "127.0.0.12/8",
501                             "127.0.0.13/8",
502                             "127.0.0.14/8",
503                             "127.0.0.15/8",
504                             "127.0.0.16/8"));
505
506 my $clientdir = "$prefix_abs/client";
507
508 my $conffile = "$clientdir/client.conf";
509 $ENV{SMB_CONF_PATH} = $conffile;
510
511 sub write_clientconf($$$)
512 {
513         my ($conffile, $clientdir, $vars) = @_;
514
515         mkdir("$clientdir", 0777) unless -d "$clientdir";
516
517         if ( -d "$clientdir/private" ) {
518                 unlink <$clientdir/private/*>;
519         } else {
520                 mkdir("$clientdir/private", 0777);
521         }
522
523         if ( -d "$clientdir/bind-dns" ) {
524                 unlink <$clientdir/bind-dns/*>;
525         } else {
526                 mkdir("$clientdir/bind-dns", 0777);
527         }
528
529         if ( -d "$clientdir/lockdir" ) {
530                 unlink <$clientdir/lockdir/*>;
531         } else {
532                 mkdir("$clientdir/lockdir", 0777);
533         }
534
535         if ( -d "$clientdir/statedir" ) {
536                 unlink <$clientdir/statedir/*>;
537         } else {
538                 mkdir("$clientdir/statedir", 0777);
539         }
540
541         if ( -d "$clientdir/cachedir" ) {
542                 unlink <$clientdir/cachedir/*>;
543         } else {
544                 mkdir("$clientdir/cachedir", 0777);
545         }
546
547         # this is ugly, but the ncalrpcdir needs exactly 0755
548         # otherwise tests fail.
549         my $mask = umask;
550         umask 0022;
551         if ( -d "$clientdir/ncalrpcdir/np" ) {
552                 unlink <$clientdir/ncalrpcdir/np/*>;
553                 rmdir "$clientdir/ncalrpcdir/np";
554         }
555         if ( -d "$clientdir/ncalrpcdir" ) {
556                 unlink <$clientdir/ncalrpcdir/*>;
557                 rmdir "$clientdir/ncalrpcdir";
558         }
559         mkdir("$clientdir/ncalrpcdir", 0755);
560         umask $mask;
561
562         my $cadir = "$ENV{SRCDIR_ABS}/selftest/manage-ca/CA-samba.example.com";
563         my $cacert = "$cadir/Public/CA-samba.example.com-cert.pem";
564         my $cacrl_pem = "$cadir/Public/CA-samba.example.com-crl.pem";
565         my $ca_users_dir = "$cadir/Users";
566
567         if ( -d "$clientdir/pkinit" ) {
568                 unlink <$clientdir/pkinit/*>;
569         } else {
570                 mkdir("$clientdir/pkinit", 0700);
571         }
572
573         # each user has a USER-${USER_PRINCIPAL_NAME}-cert.pem and
574         # USER-${USER_PRINCIPAL_NAME}-private-key.pem symlink
575         # We make a copy here and make the certificated easily
576         # accessable in the client environment.
577         my $mask = umask;
578         umask 0077;
579         opendir USERS, "${ca_users_dir}" or die "Could not open dir '${ca_users_dir}': $!";
580         for my $d (readdir USERS) {
581                 my $user_dir = "${ca_users_dir}/${d}";
582                 next if ${d} =~ /^\./;
583                 next if (! -d "${user_dir}");
584                 opendir USER, "${user_dir}" or die "Could not open dir '${user_dir}': $!";
585                 for my $l (readdir USER) {
586                         my $user_link = "${user_dir}/${l}";
587                         next if ${l} =~ /^\./;
588                         next if (! -l "${user_link}");
589
590                         my $dest = "${clientdir}/pkinit/${l}";
591                         Samba::copy_file_content(${user_link}, ${dest});
592                 }
593                 closedir USER;
594         }
595         closedir USERS;
596         umask $mask;
597
598         open(CF, ">$conffile");
599         print CF "[global]\n";
600         print CF "\tnetbios name = client\n";
601         if (defined($vars->{DOMAIN})) {
602                 print CF "\tworkgroup = $vars->{DOMAIN}\n";
603         }
604         if (defined($vars->{REALM})) {
605                 print CF "\trealm = $vars->{REALM}\n";
606         }
607         if ($opt_socket_wrapper) {
608                 print CF "\tinterfaces = $interfaces\n";
609         }
610         print CF "
611         private dir = $clientdir/private
612         binddns dir = $clientdir/bind-dns
613         lock dir = $clientdir/lockdir
614         state directory = $clientdir/statedir
615         cache directory = $clientdir/cachedir
616         ncalrpc dir = $clientdir/ncalrpcdir
617         panic action = $RealBin/gdb_backtrace \%d
618         max xmit = 32K
619         notify:inotify = false
620         ldb:nosync = true
621         system:anonymous = true
622         client lanman auth = Yes
623         log level = 1
624         torture:basedir = $clientdir
625 #We don't want to pass our self-tests if the PAC code is wrong
626         gensec:require_pac = true
627 #We don't want to run 'speed' tests for very long
628         torture:timelimit = 1
629         winbind separator = /
630         tls cafile = ${cacert}
631         tls crlfile = ${cacrl_pem}
632         tls verify peer = no_check
633         include system krb5 conf = no
634 ";
635         close(CF);
636 }
637
638 my @todo = ();
639
640 sub should_run_test($)
641 {
642         my $name = shift;
643         if ($#tests == -1) {
644                 return 1;
645         }
646         for (my $i=0; $i <= $#tests; $i++) {
647                 if ($name =~ /$tests[$i]/i) {
648                         return 1;
649                 }
650         }
651         return 0;
652 }
653
654 sub read_testlist($)
655 {
656         my ($filename) = @_;
657
658         my @ret = ();
659         open(IN, $filename) or die("Unable to open $filename: $!");
660
661         while (<IN>) {
662                 if (/-- TEST(-LOADLIST|) --\n/) {
663                         my $supports_loadlist = (defined($1) and $1 eq "-LOADLIST");
664                         my $name = <IN>;
665                         $name =~ s/\n//g;
666                         my $env = <IN>;
667                         $env =~ s/\n//g;
668                         my $loadlist;
669                         if ($supports_loadlist) {
670                                 $loadlist = <IN>;
671                                 $loadlist =~ s/\n//g;
672                         }
673                         my $cmdline = <IN>;
674                         $cmdline =~ s/\n//g;
675                         if (should_run_test($name) == 1) {
676                                 push (@ret, [$name, $env, $cmdline, $loadlist]);
677                         }
678                 } else {
679                         print;
680                 }
681         }
682         close(IN) or die("Error creating recipe from $filename");
683         return @ret;
684 }
685
686 if ($#testlists == -1) {
687         die("No testlists specified");
688 }
689
690 $ENV{SELFTEST_PREFIX} = "$prefix_abs";
691 $ENV{SELFTEST_TMPDIR} = "$tmpdir_abs";
692 $ENV{TMPDIR} = "$tmpdir_abs";
693 $ENV{TEST_DATA_PREFIX} = "$tmpdir_abs";
694 if ($opt_socket_wrapper) {
695         $ENV{SELFTEST_INTERFACES} = $interfaces;
696 } else {
697         $ENV{SELFTEST_INTERFACES} = "";
698 }
699 if ($opt_quick) {
700         $ENV{SELFTEST_QUICK} = "1";
701 } else {
702         $ENV{SELFTEST_QUICK} = "";
703 }
704 $ENV{SELFTEST_MAXTIME} = $torture_maxtime;
705
706 my $selftest_krbt_ccache_path = "$tmpdir_abs/selftest.krb5_ccache";
707 $ENV{KRB5CCNAME} = "FILE:${selftest_krbt_ccache_path}.global";
708
709 my @available = ();
710 foreach my $fn (@testlists) {
711         foreach (read_testlist($fn)) {
712                 my $name = $$_[0];
713                 next if (@includes and not defined(find_in_list(\@includes, $name)));
714                 push (@available, $_);
715         }
716 }
717
718 my $restricted = undef;
719 my $restricted_used = {};
720
721 if ($opt_load_list) {
722         $restricted = [];
723         open(LOAD_LIST, "<$opt_load_list") or die("Unable to open $opt_load_list");
724         while (<LOAD_LIST>) {
725                 chomp;
726                 push (@$restricted, $_);
727         }
728         close(LOAD_LIST);
729 }
730
731 my $individual_tests = undef;
732 $individual_tests = {};
733
734 foreach my $testsuite (@available) {
735         my $name = $$testsuite[0];
736         my $skipreason = skip(@$testsuite);
737         if (defined($restricted)) {
738                 # Find the testsuite for this test
739                 my $match = undef;
740                 foreach my $r (@$restricted) {
741                         if ($r eq $name) {
742                                 $individual_tests->{$name} = [];
743                                 $match = $r;
744                                 $restricted_used->{$r} = 1;
745                         } elsif (substr($r, 0, length($name)+1) eq "$name.") {
746                                 push(@{$individual_tests->{$name}}, $r);
747                                 $match = $r;
748                                 $restricted_used->{$r} = 1;
749                         }
750                 }
751                 if ($match) {
752                         if (defined($skipreason)) {
753                                 if (not $opt_list) {
754                                         Subunit::skip_testsuite($name, $skipreason);
755                                 }
756                         } else {
757                                 push(@todo, $testsuite);
758                         }
759                 }
760         } elsif (defined($skipreason)) {
761                 if (not $opt_list) {
762                         Subunit::skip_testsuite($name, $skipreason);
763                 }
764         } else {
765                 push(@todo, $testsuite);
766         }
767 }
768
769 if (defined($restricted)) {
770         foreach (@$restricted) {
771                 unless (defined($restricted_used->{$_})) {
772                         print "No test or testsuite found matching $_\n";
773                 }
774         }
775 } elsif ($#todo == -1) {
776         print STDERR "No tests to run\n";
777         exit(1);
778 }
779
780 my $suitestotal = $#todo + 1;
781
782 unless ($opt_list) {
783         Subunit::progress($suitestotal);
784         Subunit::report_time(time());
785 }
786
787 my $i = 0;
788 $| = 1;
789
790 my %running_envs = ();
791
792 sub get_running_env($)
793 {
794         my ($name) = @_;
795
796         my $envname = $name;
797
798         $envname =~ s/:.*//;
799
800         return $running_envs{$envname};
801 }
802
803 my @exported_envvars = (
804         # domain stuff
805         "DOMAIN",
806         "REALM",
807         "DOMSID",
808
809         # stuff related to a trusted domain
810         "TRUST_SERVER",
811         "TRUST_SERVER_IP",
812         "TRUST_SERVER_IPV6",
813         "TRUST_NETBIOSNAME",
814         "TRUST_USERNAME",
815         "TRUST_PASSWORD",
816         "TRUST_DOMAIN",
817         "TRUST_REALM",
818         "TRUST_DOMSID",
819
820         # domain controller stuff
821         "DC_SERVER",
822         "DC_SERVER_IP",
823         "DC_SERVER_IPV6",
824         "DC_NETBIOSNAME",
825         "DC_NETBIOSALIAS",
826
827         # domain member
828         "MEMBER_SERVER",
829         "MEMBER_SERVER_IP",
830         "MEMBER_SERVER_IPV6",
831         "MEMBER_NETBIOSNAME",
832         "MEMBER_NETBIOSALIAS",
833
834         # rpc proxy controller stuff
835         "RPC_PROXY_SERVER",
836         "RPC_PROXY_SERVER_IP",
837         "RPC_PROXY_SERVER_IPV6",
838         "RPC_PROXY_NETBIOSNAME",
839         "RPC_PROXY_NETBIOSALIAS",
840
841         # domain controller stuff for Vampired DC
842         "VAMPIRE_DC_SERVER",
843         "VAMPIRE_DC_SERVER_IP",
844         "VAMPIRE_DC_SERVER_IPV6",
845         "VAMPIRE_DC_NETBIOSNAME",
846         "VAMPIRE_DC_NETBIOSALIAS",
847
848         # domain controller stuff for RODC
849         "RODC_DC_SERVER",
850         "RODC_DC_SERVER_IP",
851         "RODC_DC_SERVER_IPV6",
852         "RODC_DC_NETBIOSNAME",
853
854         # domain controller stuff for FL 2000 Vampired DC
855         "VAMPIRE_2000_DC_SERVER",
856         "VAMPIRE_2000_DC_SERVER_IP",
857         "VAMPIRE_2000_DC_SERVER_IPV6",
858         "VAMPIRE_2000_DC_NETBIOSNAME",
859         "VAMPIRE_2000_DC_NETBIOSALIAS",
860
861         "PROMOTED_DC_SERVER",
862         "PROMOTED_DC_SERVER_IP",
863         "PROMOTED_DC_SERVER_IPV6",
864         "PROMOTED_DC_NETBIOSNAME",
865         "PROMOTED_DC_NETBIOSALIAS",
866
867         # server stuff
868         "SERVER",
869         "SERVER_IP",
870         "SERVER_IPV6",
871         "NETBIOSNAME",
872         "NETBIOSALIAS",
873         "SAMSID",
874
875         # user stuff
876         "USERNAME",
877         "USERID",
878         "PASSWORD",
879         "DC_USERNAME",
880         "DC_PASSWORD",
881
882         # UID/GID for rfc2307 mapping tests
883         "UID_RFC2307TEST",
884         "GID_RFC2307TEST",
885
886         # misc stuff
887         "KRB5_CONFIG",
888         "KRB5CCNAME",
889         "SELFTEST_WINBINDD_SOCKET_DIR",
890         "NMBD_SOCKET_DIR",
891         "LOCAL_PATH",
892         "DNS_FORWARDER1",
893         "DNS_FORWARDER2",
894         "RESOLV_CONF",
895         "UNACCEPTABLE_PASSWORD",
896         "LOCK_DIR",
897         "SMBD_TEST_LOG",
898
899         # nss_wrapper
900         "NSS_WRAPPER_PASSWD",
901         "NSS_WRAPPER_GROUP",
902         "NSS_WRAPPER_HOSTS",
903         "NSS_WRAPPER_HOSTNAME",
904         "NSS_WRAPPER_MODULE_SO_PATH",
905         "NSS_WRAPPER_MODULE_FN_PREFIX",
906
907         # resolv_wrapper
908         "RESOLV_WRAPPER_CONF",
909         "RESOLV_WRAPPER_HOSTS",
910 );
911
912 sub sighandler($)
913 {
914         my $signame = shift;
915
916         $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = 'DEFAULT';
917         $SIG{PIPE} = 'IGNORE';
918
919         open(STDOUT, ">&STDERR") or die "can't dup STDOUT to STDERR: $!";
920
921         print "$0: PID[$$]: Got SIG${signame} teardown environments.\n";
922         teardown_env($_) foreach(keys %running_envs);
923         system("pstree -p $$");
924         print "$0: PID[$$]: Exiting...\n";
925         exit(1);
926 };
927
928 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = $SIG{PIPE} = \&sighandler;
929
930 sub setup_env($$)
931 {
932         my ($name, $prefix) = @_;
933
934         my $testenv_vars = undef;
935
936         my $envname = $name;
937         my $option = $name;
938
939         $envname =~ s/:.*//;
940         $option =~ s/^[^:]*//;
941         $option =~ s/^://;
942
943         $option = "client" if $option eq "";
944
945         $ENV{KRB5CCNAME} = "FILE:${selftest_krbt_ccache_path}.${envname}/ignore";
946
947         if (defined(get_running_env($envname))) {
948                 $testenv_vars = get_running_env($envname);
949                 if (not $testenv_vars->{target}->check_env($testenv_vars)) {
950                         print $testenv_vars->{target}->getlog_env($testenv_vars);
951                         $testenv_vars = undef;
952                 }
953         } else {
954                 $testenv_vars = $target->setup_env($envname, $prefix);
955                 if (defined($testenv_vars) and $testenv_vars eq "UNKNOWN") {
956                     return $testenv_vars;
957                 } elsif (defined($testenv_vars) && not defined($testenv_vars->{target})) {
958                         $testenv_vars->{target} = $target;
959                 }
960                 if (not defined($testenv_vars)) {
961                         warn("$opt_target can't start up known environment '$envname'");
962                 }
963         }
964
965         return undef unless defined($testenv_vars);
966
967         $running_envs{$envname} = $testenv_vars;
968
969         if ($option eq "local") {
970                 SocketWrapper::set_default_iface($testenv_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
971                 $ENV{SMB_CONF_PATH} = $testenv_vars->{SERVERCONFFILE};
972         } elsif ($option eq "client") {
973                 SocketWrapper::set_default_iface(11);
974                 write_clientconf($conffile, $clientdir, $testenv_vars);
975                 $ENV{SMB_CONF_PATH} = $conffile;
976         } else {
977                 die("Unknown option[$option] for envname[$envname]");
978         }
979
980         foreach (@exported_envvars) {
981                 if (defined($testenv_vars->{$_})) {
982                         $ENV{$_} = $testenv_vars->{$_};
983                 } else {
984                         delete $ENV{$_};
985                 }
986         }
987
988         my $krb5_ccache_path = "${selftest_krbt_ccache_path}.${envname}.${option}";
989         unlink($krb5_ccache_path);
990         $ENV{KRB5CCNAME} = "FILE:${krb5_ccache_path}";
991         return $testenv_vars;
992 }
993
994 sub exported_envvars_str($)
995 {
996         my ($testenv_vars) = @_;
997         my $out = "";
998
999         foreach (@exported_envvars) {
1000                 next unless defined($testenv_vars->{$_});
1001                 $out .= $_."=".$testenv_vars->{$_}."\n";
1002         }
1003
1004         return $out;
1005 }
1006
1007 sub getlog_env($)
1008 {
1009         my ($envname) = @_;
1010         return "" if ($envname eq "none");
1011         my $env = get_running_env($envname);
1012         return $env->{target}->getlog_env($env);
1013 }
1014
1015 sub check_env($)
1016 {
1017         my ($envname) = @_;
1018         my $env = get_running_env($envname);
1019         return $env->{target}->check_env($env);
1020 }
1021
1022 sub teardown_env($)
1023 {
1024         my ($envname) = @_;
1025         return if ($envname eq "none");
1026         print STDERR "teardown_env($envname)\n";
1027         my $env = get_running_env($envname);
1028         $env->{target}->teardown_env($env);
1029         delete $running_envs{$envname};
1030 }
1031
1032 # This 'global' file needs to be empty when we start
1033 unlink("$prefix_abs/dns_host_file");
1034 unlink("$prefix_abs/hosts");
1035
1036 if ($opt_random_order) {
1037         require List::Util;
1038         my @newtodo = List::Util::shuffle(@todo);
1039         @todo = @newtodo;
1040 }
1041
1042 if ($opt_testenv) {
1043         my $testenv_name = $ENV{SELFTEST_TESTENV};
1044         $testenv_name = $testenv_default unless defined($testenv_name);
1045
1046         my $testenv_vars = setup_env($testenv_name, $prefix);
1047
1048         if (not $testenv_vars or $testenv_vars eq "UNKNOWN") {
1049                 die("Unable to setup environment $testenv_name");
1050         }
1051
1052         $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
1053         $ENV{ENVNAME} = $testenv_name;
1054
1055         my $envvarstr = exported_envvars_str($testenv_vars);
1056
1057         my @term_args = ("echo -e \"
1058 Welcome to the Samba4 Test environment '$testenv_name'
1059
1060 This matches the client environment used in make test
1061 server is pid `cat \$PIDDIR/samba.pid`
1062
1063 Some useful environment variables:
1064 TORTURE_OPTIONS=\$TORTURE_OPTIONS
1065 SMB_CONF_PATH=\$SMB_CONF_PATH
1066
1067 $envvarstr
1068 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash");
1069         my @term = ();
1070         if ($ENV{TERMINAL}) {
1071             @term = ($ENV{TERMINAL});
1072         } else {
1073             @term = ("xterm", "-e");
1074             unshift(@term_args, ("bash", "-c"));
1075         }
1076
1077         system(@term, @term_args);
1078
1079         teardown_env($testenv_name);
1080 } elsif ($opt_list) {
1081         foreach (@todo) {
1082                 my $name = $$_[0];
1083                 my $envname = $$_[1];
1084                 my $cmd = $$_[2];
1085                 my $listcmd = $$_[3];
1086
1087                 unless (defined($listcmd)) {
1088                         warn("Unable to list tests in $name");
1089                         # Rather than ignoring this testsuite altogether, just pretend the entire testsuite is
1090                         # a single "test".
1091                         print "$name\n";
1092                         next;
1093                 }
1094
1095                 system($listcmd);
1096
1097                 if ($? == -1) {
1098                         die("Unable to run $listcmd: $!");
1099                 } elsif ($? & 127) {
1100                         die(sprintf("%s died with signal %d, %s coredump\n", $listcmd, ($? & 127),  ($? & 128) ? 'with' : 'without'));
1101                 }
1102
1103                 my $exitcode = $? >> 8;
1104                 if ($exitcode != 0) {
1105                         die("$cmd exited with exit code $exitcode");
1106                 }
1107         }
1108 } else {
1109         foreach (@todo) {
1110                 $i++;
1111                 my $cmd = $$_[2];
1112                 my $name = $$_[0];
1113                 my $envname = $$_[1];
1114                 my $envvars = setup_env($envname, $prefix);
1115
1116                 if (not defined($envvars)) {
1117                         Subunit::start_testsuite($name);
1118                         Subunit::end_testsuite($name, "error",
1119                                 "unable to set up environment $envname - exiting");
1120                         next;
1121                 } elsif ($envvars eq "UNKNOWN") {
1122                         Subunit::start_testsuite($name);
1123                         Subunit::end_testsuite($name, "error",
1124                                 "environment $envname is unknown - exiting");
1125                         next;
1126                 }
1127
1128                 # Generate a file with the individual tests to run, if the 
1129                 # test runner for this test suite supports it.
1130                 if ($individual_tests and $individual_tests->{$name}) {
1131                         if ($$_[3]) {
1132                                 my ($fh, $listid_file) = tempfile(UNLINK => 0);
1133                                 foreach my $test (@{$individual_tests->{$name}}) {
1134                                         print $fh substr($test, length($name)+1) . "\n";
1135                                 }
1136                                 $cmd =~ s/\$LOADLIST/--load-list=$listid_file/g;
1137                         } else {
1138                                 warn("Unable to run individual tests in $name, it does not support --loadlist.");
1139                         }
1140                 }
1141
1142                 run_testsuite($envname, $name, $cmd, $i, $suitestotal);
1143
1144                 teardown_env($envname) if ($opt_resetup_env);
1145         }
1146 }
1147
1148 print "\n";
1149
1150 teardown_env($_) foreach (keys %running_envs);
1151
1152 my $failed = 0;
1153
1154 # if there were any valgrind failures, show them
1155 foreach (<$prefix/valgrind.log*>) {
1156         next unless (-s $_);
1157         print "VALGRIND FAILURE\n";
1158         $failed++;
1159         system("cat $_");
1160 }
1161 exit 0;