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>
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.
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.
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/>.
23 selftest - Samba test runner
29 selftest [--srcdir=DIR] [--builddir=DIR] [--exeext=EXT][--target=samba4|samba3|win|kvm] [--socket-wrapper] [--quick] [--exclude=FILE] [--include=FILE] [--one] [--prefix=prefix] [--testlist=FILE] [TESTS]
33 A simple test runner. TESTS is a regular expression with tests to run.
41 Show list of available options.
47 =item I<--builddir=DIR>
57 Change directory to run tests in. Default is 'st'.
59 =item I<--target samba4|samba3|win|kvm>
61 Specify test target against which to run. Default is 'samba4'.
65 Run only a limited number of tests. Intended to run in about 30 seconds on
66 moderately recent systems.
68 =item I<--socket-wrapper>
70 Use socket wrapper library for communication with server. Only works
71 when the server is running locally.
73 Will prevent TCP and UDP ports being opened on the local host but
74 (transparently) redirects these calls to use unix domain sockets.
78 Specify a file containing a list of tests that should be skipped. Possible
79 candidates are tests that segfault the server, flip or don't end.
83 Specify a file containing a list of tests that should be run. Same format
84 as the --exclude flag.
86 Not includes specified means all tests will be run.
90 Abort as soon as one test fails.
94 Load a list of tests from the specified location.
102 =item I<SMBD_VALGRIND>
104 =item I<TORTURE_MAXTIME>
116 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
126 use FindBin
qw($RealBin $Script);
128 use File::Temp qw(tempfile);
131 use Cwd
qw(abs_path);
140 use Time
::HiRes
qw(time);
144 my $opt_target = "samba4";
146 my $opt_socket_wrapper = 0;
147 my $opt_socket_wrapper_pcap = undef;
148 my $opt_socket_wrapper_keep_pcap = undef;
150 my @opt_exclude = ();
151 my @opt_include = ();
153 my $opt_image = undef;
156 my $opt_resetup_env = undef;
157 my $opt_bindir = undef;
158 my $opt_load_list = undef;
171 print STDERR
"Exiting early because of SIGPIPE.\n";
175 $SIG{PIPE
} = \
&pipe_handler
;
179 my ($list, $fullname) = @_;
182 if ($fullname =~ /$$_[0]/) {
183 return ($$_[1]) if ($$_[1]);
195 return find_in_list
(\
@excludes, $name);
204 return unless ($opt_socket_wrapper_pcap);
205 return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR
});
208 $fname =~ s
%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\
-]%_%g;
210 my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
212 SocketWrapper
::setup_pcap
($pcap_file);
219 my ($pcap_file, $exitcode) = @_;
221 return unless ($opt_socket_wrapper_pcap);
222 return if ($opt_socket_wrapper_keep_pcap);
223 return unless ($exitcode == 0);
224 return unless defined($pcap_file);
229 # expand strings from %ENV
230 sub expand_environment_strings
($)
233 # we use a reverse sort so we do the longer ones first
234 foreach my $k (sort { $b cmp $a } keys %ENV) {
235 $s =~ s/\$$k/$ENV{$k}/g;
240 sub run_testsuite
($$$$$)
242 my ($envname, $name, $cmd, $i, $totalsuites) = @_;
243 my $pcap_file = setup_pcap
($name);
245 Subunit
::start_testsuite
($name);
246 Subunit
::progress_push
();
247 Subunit
::report_time
(time());
249 Subunit
::report_time
(time());
250 Subunit
::progress_pop
();
253 Subunit
::progress_pop
();
254 Subunit
::end_testsuite
($name, "error", "Unable to run $cmd: $!");
257 Subunit
::end_testsuite
($name, "error",
258 sprintf("%s died with signal %d, %s coredump\n", $cmd, ($?
& 127), ($?
& 128) ?
'with' : 'without'));
262 my $exitcode = $?
>> 8;
264 my $envlog = getlog_env
($envname);
266 print "envlog: $envlog\n";
269 print "command: $cmd\n";
270 printf "expanded command: %s\n", expand_environment_strings
($cmd);
272 if ($exitcode == 0) {
273 Subunit
::end_testsuite
($name, "success");
275 Subunit
::end_testsuite
($name, "failure", "Exit code was $exitcode");
278 cleanup_pcap
($pcap_file, $exitcode);
280 if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
281 print "PCAP FILE: $pcap_file\n";
284 if ($exitcode != 0) {
285 exit(1) if ($opt_one);
293 print "Samba test runner
294 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
295 Copyright (C) Stefan Metzmacher <metze\@samba.org>
297 Usage: $Script [OPTIONS] TESTNAME-REGEX
300 --help this help page
301 --target=samba[34]|win|kvm Samba version to target
302 --testlist=FILE file to read available tests from
305 --prefix=DIR prefix to run tests in [st]
306 --srcdir=DIR source directory [.]
307 --builddir=DIR output directory [.]
308 --exeext=EXT executable extention []
311 --socket-wrapper-pcap save traffic to pcap directories
312 --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that
314 --socket-wrapper enable socket wrapper
315 --bindir=PATH path to target binaries
318 --ldap=openldap|fedora-ds back samba onto specified ldap server
321 --image=PATH path to KVM image
324 --quick run quick overall test
325 --one abort when the first test fails
327 --analyse-cmd CMD command to run after each test
332 my $result = GetOptions
(
333 'help|h|?' => \
$opt_help,
334 'target=s' => \
$opt_target,
335 'prefix=s' => \
$prefix,
336 'socket-wrapper' => \
$opt_socket_wrapper,
337 'socket-wrapper-pcap' => \
$opt_socket_wrapper_pcap,
338 'socket-wrapper-keep-pcap' => \
$opt_socket_wrapper_keep_pcap,
339 'quick' => \
$opt_quick,
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,
349 'resetup-environment' => \
$opt_resetup_env,
350 'bindir:s' => \
$opt_bindir,
351 'image=s' => \
$opt_image,
352 'testlist=s' => \
@testlists,
353 'load-list=s' => \
$opt_load_list,
356 exit(1) if (not $result);
358 ShowHelp
() if ($opt_help);
360 # we want unbuffered output
365 # quick hack to disable rpc validation when using valgrind - its way too slow
366 unless (defined($ENV{VALGRIND
})) {
367 $ENV{VALIDATE
} = "validate";
368 $ENV{MALLOC_CHECK_
} = 2;
371 # make all our python scripts unbuffered
372 $ENV{PYTHONUNBUFFERED
} = 1;
374 my $bindir = ($opt_bindir or "$builddir/bin");
375 my $bindir_abs = abs_path
($bindir);
377 # Backwards compatibility:
378 if (defined($ENV{TEST_LDAP
}) and $ENV{TEST_LDAP
} eq "yes") {
379 if (defined($ENV{FEDORA_DS_ROOT
})) {
386 my $torture_maxtime = ($ENV{TORTURE_MAXTIME
} or 1200);
389 $torture_maxtime *= 2;
396 die("using an empty prefix isn't allowed") unless $prefix ne "";
398 #Ensure we have the test prefix around
399 mkdir($prefix, 0777) unless -d
$prefix;
401 my $prefix_abs = abs_path
($prefix);
402 my $tmpdir_abs = abs_path
("$prefix/tmp");
403 mkdir($tmpdir_abs, 0777) unless -d
$tmpdir_abs;
405 my $srcdir_abs = abs_path
($srcdir);
406 my $builddir_abs = abs_path
($builddir);
408 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
409 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
411 $ENV{PREFIX
} = $prefix;
412 $ENV{KRB5CCNAME
} = "$prefix/krb5ticket";
413 $ENV{PREFIX_ABS
} = $prefix_abs;
414 $ENV{SRCDIR
} = $srcdir;
415 $ENV{SRCDIR_ABS
} = $srcdir_abs;
416 $ENV{BUILDDIR
} = $builddir;
417 $ENV{BUILDDIR_ABS
} = $builddir_abs;
418 $ENV{EXEEXT
} = $exeext;
420 my $tls_enabled = not $opt_quick;
421 $ENV{TLS_ENABLED
} = ($tls_enabled?
"yes":"no");
422 $ENV{LDB_MODULES_PATH
} = "$bindir_abs/modules/ldb";
423 $ENV{LD_SAMBA_MODULE_PATH
} = "$bindir_abs/modules";
424 sub prefix_pathvar
($$)
426 my ($name, $newpath) = @_;
427 if (defined($ENV{$name})) {
428 $ENV{$name} = "$newpath:$ENV{$name}";
430 $ENV{$name} = $newpath;
433 prefix_pathvar
("PKG_CONFIG_PATH", "$bindir_abs/pkgconfig");
434 prefix_pathvar
("PYTHONPATH", "$bindir_abs/python");
436 if ($opt_socket_wrapper_keep_pcap) {
437 # Socket wrapper keep pcap implies socket wrapper pcap
438 $opt_socket_wrapper_pcap = 1;
441 if ($opt_socket_wrapper_pcap) {
442 # Socket wrapper pcap implies socket wrapper
443 $opt_socket_wrapper = 1;
446 my $socket_wrapper_dir;
447 if ($opt_socket_wrapper) {
448 $socket_wrapper_dir = SocketWrapper
::setup_dir
("$prefix_abs/w", $opt_socket_wrapper_pcap);
449 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
452 print "WARNING: Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports\n";
457 my $testenv_default = "none";
459 if ($opt_target eq "samba4") {
460 $testenv_default = "all";
461 require target
::Samba4
;
462 $target = new Samba4
($bindir, $ldap, "$srcdir/setup", $exeext);
463 } elsif ($opt_target eq "samba3") {
464 if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
465 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
467 $testenv_default = "member";
468 require target
::Samba3
;
469 $target = new Samba3
($bindir);
470 } elsif ($opt_target eq "win") {
471 die("Windows tests will not run with socket wrapper enabled.")
472 if ($opt_socket_wrapper);
473 $testenv_default = "dc";
474 require target
::Windows
;
475 $target = new Windows
();
476 } elsif ($opt_target eq "kvm") {
477 die("Kvm tests will not run with socket wrapper enabled.")
478 if ($opt_socket_wrapper);
480 die("No image specified") unless ($opt_image);
481 $target = new Kvm
($opt_image, undef);
485 # Start a Virtual Distributed Ethernet Switch
486 # Returns the pid of the switch.
488 sub start_vde_switch
($)
492 system("vde_switch --pidfile $path/vde.pid --sock $path/vde.sock --daemon");
494 open(PID
, "$path/vde.pid");
502 # Stop a Virtual Distributed Ethernet Switch
503 sub stop_vde_switch
($)
509 sub read_test_regexes
($)
513 open(LF
, "<$name") or die("unable to read $name: $!");
517 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
518 push (@ret, [$1, $4]);
520 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
521 push (@ret, [$_, undef]);
528 foreach (@opt_exclude) {
529 push (@excludes, read_test_regexes
($_));
532 foreach (@opt_include) {
533 push (@includes, read_test_regexes
($_));
536 my $interfaces = join(',', ("127.0.0.11/8",
543 my $clientdir = "$prefix_abs/client";
545 my $conffile = "$clientdir/client.conf";
546 $ENV{SMB_CONF_PATH
} = $conffile;
548 sub write_clientconf
($$$)
550 my ($conffile, $clientdir, $vars) = @_;
552 mkdir("$clientdir", 0777) unless -d
"$clientdir";
554 if ( -d
"$clientdir/private" ) {
555 unlink <$clientdir/private/*>;
557 mkdir("$clientdir/private", 0777);
560 if ( -d
"$clientdir/lockdir" ) {
561 unlink <$clientdir/lockdir/*>;
563 mkdir("$clientdir/lockdir", 0777);
566 if ( -d
"$clientdir/ncalrpcdir" ) {
567 unlink <$clientdir/ncalrpcdir/*>;
569 mkdir("$clientdir/ncalrpcdir", 0777);
572 open(CF
, ">$conffile");
573 print CF
"[global]\n";
574 if (defined($ENV{VALGRIND
})) {
575 print CF
"\ticonv:native = true\n";
577 print CF
"\ticonv:native = false\n";
579 print CF
"\tnetbios name = client\n";
580 if (defined($vars->{DOMAIN
})) {
581 print CF
"\tworkgroup = $vars->{DOMAIN}\n";
583 if (defined($vars->{REALM
})) {
584 print CF
"\trealm = $vars->{REALM}\n";
586 if ($opt_socket_wrapper) {
587 print CF
"\tinterfaces = $interfaces\n";
590 private dir = $clientdir/private
591 lock dir = $clientdir/lockdir
592 ncalrpc dir = $clientdir/ncalrpcdir
593 name resolve order = bcast file
594 panic action = $RealBin/gdb_backtrace \%PID\% \%PROG\%
596 notify:inotify = false
598 system:anonymous = true
599 client lanman auth = Yes
601 torture:basedir = $clientdir
602 #We don't want to pass our self-tests if the PAC code is wrong
603 gensec:require_pac = true
604 modules dir = $ENV{LD_SAMBA_MODULE_PATH}
605 setup directory = ./setup
606 resolv:host file = $prefix_abs/dns_host_file
607 #We don't want to run 'speed' tests for very long
608 torture:timelimit = 1
615 my $testsdir = "$srcdir/selftest";
617 sub should_run_test
($)
623 for (my $i=0; $i <= $#tests; $i++) {
624 if ($name =~ /$tests[$i]/i) {
636 open(IN
, $filename) or die("Unable to open $filename: $!");
639 if (/-- TEST(-LOADLIST|-IDLIST|) --\n/) {
640 my $supports_loadlist = (defined($1) and $1 eq "-LOADLIST");
641 my $supports_idlist = (defined($1) and $1 eq "-IDLIST");
648 if (should_run_test
($name) == 1) {
649 push (@ret, [$name, $env, $cmdline, $supports_loadlist, $supports_idlist]);
655 close(IN
) or die("Error creating recipe");
659 if ($#testlists == -1) {
660 die("No testlists specified");
663 $ENV{SELFTEST_PREFIX
} = "$prefix_abs";
664 $ENV{SELFTEST_TMPDIR
} = "$tmpdir_abs";
665 if ($opt_socket_wrapper) {
666 $ENV{SELFTEST_INTERFACES
} = $interfaces;
668 $ENV{SELFTEST_INTERFACES
} = "";
671 $ENV{SELFTEST_VERBOSE
} = "1";
673 $ENV{SELFTEST_VERBOSE
} = "";
676 $ENV{SELFTEST_QUICK
} = "1";
678 $ENV{SELFTEST_QUICK
} = "";
680 $ENV{SELFTEST_TARGET
} = $opt_target;
681 $ENV{SELFTEST_MAXTIME
} = $torture_maxtime;
684 foreach my $fn (@testlists) {
685 foreach (read_testlist
($fn)) {
687 next if (@includes and not defined(find_in_list
(\
@includes, $name)));
688 push (@available, $_);
692 my $restricted = undef;
693 my $restricted_used = {};
695 if ($opt_load_list) {
697 open(LOAD_LIST
, "<$opt_load_list") or die("Unable to open $opt_load_list");
698 while (<LOAD_LIST
>) {
700 push (@
$restricted, $_);
705 my $individual_tests = undef;
706 $individual_tests = {};
708 foreach my $testsuite (@available) {
709 my $name = $$testsuite[0];
710 my $skipreason = skip
($name);
711 if (defined($restricted)) {
712 # Find the testsuite for this test
714 foreach my $r (@
$restricted) {
716 $individual_tests->{$name} = [];
718 $restricted_used->{$r} = 1;
719 } elsif (substr($r, 0, length($name)+1) eq "$name.") {
720 push(@
{$individual_tests->{$name}}, $r);
722 $restricted_used->{$r} = 1;
726 if (defined($skipreason)) {
727 Subunit
::skip_testsuite
($name, $skipreason);
729 push(@todo, $testsuite);
732 } elsif (defined($skipreason)) {
733 Subunit
::skip_testsuite
($name, $skipreason);
735 push(@todo, $testsuite);
739 if (defined($restricted)) {
740 foreach (@
$restricted) {
741 unless (defined($restricted_used->{$_})) {
742 print "No test or testsuite found matching $_\n";
745 } elsif ($#todo == -1) {
746 print STDERR
"No tests to run\n";
750 my $suitestotal = $#todo + 1;
752 Subunit
::progress
($suitestotal);
753 Subunit
::report_time
(time());
758 my %running_envs = ();
760 sub get_running_env
($)
768 return $running_envs{$envname};
771 my @exported_envvars = (
776 # domain controller stuff
785 "MEMBER_NETBIOSNAME",
786 "MEMBER_NETBIOSALIAS",
788 # rpc proxy controller stuff
790 "RPC_PROXY_SERVER_IP",
791 "RPC_PROXY_NETBIOSNAME",
792 "RPC_PROXY_NETBIOSALIAS",
794 # domain controller stuff for Vampired DC
796 "VAMPIRE_DC_SERVER_IP",
797 "VAMPIRE_DC_NETBIOSNAME",
798 "VAMPIRE_DC_NETBIOSALIAS",
815 "WINBINDD_SOCKET_DIR",
816 "WINBINDD_PRIV_PIPE_DIR",
820 $SIG{INT
} = $SIG{QUIT
} = $SIG{TERM
} = sub {
822 teardown_env
($_) foreach(keys %running_envs);
823 die("Received signal $signame");
828 my ($name, $prefix) = @_;
830 my $testenv_vars = undef;
836 $option =~ s/^[^:]*//;
839 $option = "client" if $option eq "";
841 if ($envname eq "none") {
843 } elsif (defined(get_running_env
($envname))) {
844 $testenv_vars = get_running_env
($envname);
845 if (not $target->check_env($testenv_vars)) {
846 print $target->getlog_env($testenv_vars);
847 $testenv_vars = undef;
850 $testenv_vars = $target->setup_env($envname, $prefix);
853 return undef unless defined($testenv_vars);
855 $running_envs{$envname} = $testenv_vars;
857 if ($option eq "local") {
858 SocketWrapper
::set_default_iface
($testenv_vars->{SOCKET_WRAPPER_DEFAULT_IFACE
});
859 $ENV{SMB_CONF_PATH
} = $testenv_vars->{SERVERCONFFILE
};
860 } elsif ($option eq "client") {
861 SocketWrapper
::set_default_iface
(11);
862 write_clientconf
($conffile, $clientdir, $testenv_vars);
863 $ENV{SMB_CONF_PATH
} = $conffile;
865 die("Unknown option[$option] for envname[$envname]");
868 foreach (@exported_envvars) {
869 if (defined($testenv_vars->{$_})) {
870 $ENV{$_} = $testenv_vars->{$_};
876 return $testenv_vars;
879 sub exported_envvars_str
($)
881 my ($testenv_vars) = @_;
884 foreach (@exported_envvars) {
885 next unless defined($testenv_vars->{$_});
886 $out .= $_."=".$testenv_vars->{$_}."\n";
895 return "" if ($envname eq "none");
896 return $target->getlog_env(get_running_env
($envname));
902 return 1 if ($envname eq "none");
903 return $target->check_env(get_running_env
($envname));
909 return if ($envname eq "none");
910 $target->teardown_env(get_running_env
($envname));
911 delete $running_envs{$envname};
914 # This 'global' file needs to be empty when we start
915 unlink("$prefix_abs/dns_host_file");
918 my $testenv_name = $ENV{SELFTEST_TESTENV
};
919 $testenv_name = $testenv_default unless defined($testenv_name);
921 my $testenv_vars = setup_env
($testenv_name, $prefix);
923 die("Unable to setup environment $testenv_name") unless ($testenv_vars);
925 $ENV{PIDDIR
} = $testenv_vars->{PIDDIR
};
926 $ENV{ENVNAME
} = $testenv_name;
928 my $envvarstr = exported_envvars_str
($testenv_vars);
930 my $term = ($ENV{TERMINAL
} or "xterm -e");
931 system("$term 'echo -e \"
932 Welcome to the Samba4 Test environment '$testenv_name'
934 This matches the client environment used in make test
935 server is pid `cat \$PIDDIR/samba.pid`
937 Some useful environment variables:
938 TORTURE_OPTIONS=\$TORTURE_OPTIONS
939 SMB_CONF_PATH=\$SMB_CONF_PATH
942 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
943 teardown_env
($testenv_name);
949 my $envname = $$_[1];
951 my $envvars = setup_env
($envname, $prefix);
952 if (not defined($envvars)) {
953 Subunit
::start_testsuite
($name);
954 Subunit
::end_testsuite
($name, "error",
955 "unable to set up environment $envname");
959 # Generate a file with the individual tests to run, if the
960 # test runner for this test suite supports it.
961 if ($individual_tests and $individual_tests->{$name}) {
963 my ($fh, $listid_file) = tempfile
(UNLINK
=> 0);
964 foreach my $test (@
{$individual_tests->{$name}}) {
965 print $fh substr($test, length($name)+1) . "\n";
967 $cmd =~ s/\$LOADLIST/--load-list=$listid_file/g;
969 $cmd =~ s/\s+[^\s]+\s*$//;
970 $cmd .= " " . join(' ', @
{$individual_tests->{$name}});
974 run_testsuite
($envname, $name, $cmd, $i, $suitestotal);
976 teardown_env
($envname) if ($opt_resetup_env);
982 teardown_env
($_) foreach (keys %running_envs);
986 # if there were any valgrind failures, show them
987 foreach (<$prefix/valgrind
.log*>) {
989 print "VALGRIND FAILURE\n";