2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
4 # Published under the GNU GPL, v3 or later.
10 selftest - Samba test runner
16 selftest [--srcdir=DIR] [--builddir=DIR] [--target=samba4|samba3|win|kvm] [--socket-wrapper] [--quick] [--exclude=FILE] [--include=FILE] [--one] [--prefix=prefix] [--immediate] [--testlist=FILE] [TESTS]
20 A simple test runner. TESTS is a regular expression with tests to run.
28 Show list of available options.
34 =item I<--builddir=DIR>
40 Change directory to run tests in. Default is 'st'.
44 Show errors as soon as they happen rather than at the end of the test run.
46 =item I<--target samba4|samba3|win|kvm>
48 Specify test target against which to run. Default is 'samba4'.
52 Run only a limited number of tests. Intended to run in about 30 seconds on
53 moderately recent systems.
55 =item I<--socket-wrapper>
57 Use socket wrapper library for communication with server. Only works
58 when the server is running locally.
60 Will prevent TCP and UDP ports being opened on the local host but
61 (transparently) redirects these calls to use unix domain sockets.
63 =item I<--expected-failures>
65 Specify a file containing a list of tests that are expected to fail. Failures for
66 these tests will be counted as successes, successes will be counted as failures.
68 The format for the file is, one entry per line:
70 TESTSUITE-NAME.TEST-NAME
72 The reason for a test can also be specified, by adding a hash sign (#) and the reason
77 Specify a file containing a list of tests that should be skipped. Possible
78 candidates are tests that segfault the server, flip or don't end. The format of this file is the same as
79 for the --expected-failures flag.
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);
130 use Cwd qw(abs_path);
132 use Subunit qw(parse_results);
136 my $opt_target = "samba4";
138 my $opt_socket_wrapper = 0;
139 my $opt_socket_wrapper_pcap = undef;
140 my $opt_socket_wrapper_keep_pcap = undef;
142 my $opt_immediate = 0;
143 my $opt_expected_failures = undef;
144 my @opt_exclude = ();
145 my @opt_include = ();
147 my $opt_image = undef;
150 my $opt_analyse_cmd = undef;
151 my $opt_resetup_env = undef;
152 my $opt_bindir = undef;
153 my $opt_no_lazy_setup = undef;
154 my $opt_format = "plain";
161 my @expected_failures = ();
168 TESTS_UNEXPECTED_OK => 0,
169 TESTS_EXPECTED_OK => 0,
170 TESTS_UNEXPECTED_FAIL => 0,
171 TESTS_EXPECTED_FAIL => 0,
178 my ($list, $fullname) = @_;
181 if ($fullname =~ /$$_[0]/) {
182 return ($$_[1]) if ($$_[1]);
183 return "NO REASON SPECIFIED";
190 sub expecting_failure($)
193 return find_in_list(\@expected_failures, $name);
200 return find_in_list(\@excludes, $name);
209 return unless ($opt_socket_wrapper_pcap);
210 return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
213 $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
215 my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
217 SocketWrapper::setup_pcap($pcap_file);
222 sub cleanup_pcap($$$)
224 my ($pcap_file, $expected_ret, $ret) = @_;
226 return unless ($opt_socket_wrapper_pcap);
227 return if ($opt_socket_wrapper_keep_pcap);
228 return unless ($expected_ret == $ret);
229 return unless defined($pcap_file);
234 sub run_testsuite($$$$$$)
236 my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
237 my $pcap_file = setup_pcap($name);
239 $msg_ops->start_test([], $name);
241 unless (open(RESULT, "$cmd 2>&1|")) {
242 $statistics->{TESTS_ERROR}++;
243 $msg_ops->end_test([], $name, "error", 1, "Unable to run $cmd: $!");
244 $statistics->{SUITES_FAIL}++;
248 my $expected_ret = parse_results(
249 $msg_ops, $statistics, *RESULT, \&expecting_failure, [$name]);
251 my $envlog = getlog_env($envname);
252 $msg_ops->output_msg("ENVLOG: $envlog\n") if ($envlog ne "");
254 $msg_ops->output_msg("CMD: $cmd\n");
256 my $ret = close(RESULT);
257 $ret = 0 unless $ret == 1;
259 my $exitcode = $? >> 8;
262 $msg_ops->end_test([], $name, "success", $expected_ret != $ret, undef);
264 $msg_ops->end_test([], $name, "failure", $expected_ret != $ret, "Exit code was $exitcode");
267 cleanup_pcap($pcap_file, $expected_ret, $ret);
269 if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
270 $msg_ops->output_msg("PCAP FILE: $pcap_file\n");
273 if ($ret != $expected_ret) {
274 $statistics->{SUITES_FAIL}++;
275 exit(1) if ($opt_one);
278 return ($ret == $expected_ret);
283 print "Samba test runner
284 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
286 Usage: $Script [OPTIONS] TESTNAME-REGEX
289 --help this help page
290 --target=samba[34]|win|kvm Samba version to target
291 --testlist=FILE file to read available tests from
294 --prefix=DIR prefix to run tests in [st]
295 --srcdir=DIR source directory [.]
296 --builddir=DIR output directory [.]
299 --socket-wrapper-pcap save traffic to pcap directories
300 --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that
302 --socket-wrapper enable socket wrapper
303 --expected-failures=FILE specify list of tests that is guaranteed to fail
306 --ldap=openldap|fedora-ds back samba onto specified ldap server
309 --bindir=PATH path to binaries
312 --image=PATH path to KVM image
315 --quick run quick overall test
316 --one abort when the first test fails
317 --immediate print test output for failed tests during run
319 --analyse-cmd CMD command to run after each test
324 my $result = GetOptions (
325 'help|h|?' => \$opt_help,
326 'target=s' => \$opt_target,
327 'prefix=s' => \$prefix,
328 'socket-wrapper' => \$opt_socket_wrapper,
329 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
330 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
331 'quick' => \$opt_quick,
333 'immediate' => \$opt_immediate,
334 'expected-failures=s' => \$opt_expected_failures,
335 'exclude=s' => \@opt_exclude,
336 'include=s' => \@opt_include,
337 'srcdir=s' => \$srcdir,
338 'builddir=s' => \$builddir,
339 'verbose' => \$opt_verbose,
340 'testenv' => \$opt_testenv,
342 'analyse-cmd=s' => \$opt_analyse_cmd,
343 'no-lazy-setup' => \$opt_no_lazy_setup,
344 'resetup-environment' => \$opt_resetup_env,
345 'bindir:s' => \$opt_bindir,
346 'format=s' => \$opt_format,
347 'image=s' => \$opt_image,
348 'testlist=s' => \@testlists
351 exit(1) if (not $result);
353 ShowHelp() if ($opt_help);
357 # quick hack to disable rpc validation when using valgrind - its way too slow
358 unless (defined($ENV{VALGRIND})) {
359 $ENV{VALIDATE} = "validate";
360 $ENV{MALLOC_CHECK_} = 2;
363 my $old_pwd = "$RealBin/..";
365 # Backwards compatibility:
366 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
367 if (defined($ENV{FEDORA_DS_ROOT})) {
374 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
377 $torture_maxtime *= 2;
384 die("using an empty prefix isn't allowed") unless $prefix ne "";
386 #Ensure we have the test prefix around
387 mkdir($prefix, 0777) unless -d $prefix;
389 my $prefix_abs = abs_path($prefix);
390 my $srcdir_abs = abs_path($srcdir);
392 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
393 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
395 $ENV{PREFIX} = $prefix;
396 $ENV{KRB5CCNAME} = "$prefix/krb5ticket";
397 $ENV{PREFIX_ABS} = $prefix_abs;
398 $ENV{SRCDIR} = $srcdir;
399 $ENV{SRCDIR_ABS} = $srcdir_abs;
401 if (defined($ENV{RUN_FROM_BUILD_FARM}) and
402 ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
403 $opt_format = "buildfarm";
406 my $tls_enabled = not $opt_quick;
407 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
408 $ENV{LDB_MODULES_PATH} = "$old_pwd/source4/bin/modules/ldb";
409 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/source4/bin/modules";
410 sub prefix_pathvar($$)
412 my ($name, $newpath) = @_;
413 if (defined($ENV{$name})) {
414 $ENV{$name} = "$newpath:$ENV{$name}";
416 $ENV{$name} = $newpath;
419 prefix_pathvar("PKG_CONFIG_PATH", "$old_pwd/source4/bin/pkgconfig");
420 prefix_pathvar("PYTHONPATH", "$old_pwd/source4/bin/python");
422 if ($opt_socket_wrapper_keep_pcap) {
423 # Socket wrapper keep pcap implies socket wrapper pcap
424 $opt_socket_wrapper_pcap = 1;
427 if ($opt_socket_wrapper_pcap) {
428 # Socket wrapper pcap implies socket wrapper
429 $opt_socket_wrapper = 1;
432 my $socket_wrapper_dir;
433 if ($opt_socket_wrapper) {
434 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
435 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
438 print "WARNING: Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports\n";
443 my $testenv_default = "none";
445 if ($opt_target eq "samba4") {
446 $testenv_default = "member";
447 require target::Samba4;
448 $target = new Samba4($opt_bindir or "$srcdir/bin", $ldap, "$srcdir/setup");
449 } elsif ($opt_target eq "samba3") {
450 if ($opt_socket_wrapper and `$opt_bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
451 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
453 $testenv_default = "dc";
454 require target::Samba3;
455 $target = new Samba3($opt_bindir);
456 } elsif ($opt_target eq "win") {
457 die("Windows tests will not run with socket wrapper enabled.")
458 if ($opt_socket_wrapper);
459 $testenv_default = "dc";
460 require target::Windows;
461 $target = new Windows();
462 } elsif ($opt_target eq "kvm") {
463 die("Kvm tests will not run with socket wrapper enabled.")
464 if ($opt_socket_wrapper);
466 die("No image specified") unless ($opt_image);
467 $target = new Kvm($opt_image, undef);
471 # Start a Virtual Distributed Ethernet Switch
472 # Returns the pid of the switch.
474 sub start_vde_switch($)
478 system("vde_switch --pidfile $path/vde.pid --sock $path/vde.sock --daemon");
480 open(PID, "$path/vde.pid");
488 # Stop a Virtual Distributed Ethernet Switch
489 sub stop_vde_switch($)
495 sub read_test_regexes($)
499 open(LF, "<$name") or die("unable to read $name: $!");
503 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
504 push (@ret, [$1, $4]);
506 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
507 push (@ret, [$_, undef]);
514 if (defined($opt_expected_failures)) {
515 @expected_failures = read_test_regexes($opt_expected_failures);
518 foreach (@opt_exclude) {
519 push (@excludes, read_test_regexes($_));
523 push (@includes, read_test_regexes("samba4-quick"));
526 foreach (@opt_include) {
527 push (@includes, read_test_regexes($_));
530 my $interfaces = join(',', ("127.0.0.6/8",
537 my $conffile = "$prefix_abs/client/client.conf";
538 $ENV{SMB_CONF_PATH} = $conffile;
540 sub write_clientconf($$)
542 my ($conffile, $vars) = @_;
544 mkdir("$prefix/client", 0777) unless -d "$prefix/client";
546 if ( -d "$prefix/client/private" ) {
547 unlink <$prefix/client/private/*>;
549 mkdir("$prefix/client/private", 0777);
552 open(CF, ">$conffile");
553 print CF "[global]\n";
554 if (defined($ENV{VALGRIND})) {
555 print CF "\ticonv:native = true\n";
557 print CF "\ticonv:native = false\n";
559 print CF "\tnetbios name = client\n";
560 if (defined($vars->{DOMAIN})) {
561 print CF "\tworkgroup = $vars->{DOMAIN}\n";
563 if (defined($vars->{REALM})) {
564 print CF "\trealm = $vars->{REALM}\n";
566 if (defined($vars->{NCALRPCDIR})) {
567 print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n";
569 if (defined($vars->{PIDDIR})) {
570 print CF "\tpid directory = $vars->{PIDDIR}\n";
572 if (defined($vars->{WINBINDD_SOCKET_DIR})) {
573 print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n";
575 if ($opt_socket_wrapper) {
576 print CF "\tinterfaces = $interfaces\n";
579 private dir = $prefix_abs/client/private
580 name resolve order = bcast
581 panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\%
583 notify:inotify = false
585 system:anonymous = true
586 torture:basedir = $prefix_abs/client
587 #We don't want to pass our self-tests if the PAC code is wrong
588 gensec:require_pac = true
589 modules dir = $ENV{LD_SAMBA_MODULE_PATH}
596 my $testsdir = "$srcdir/selftest";
598 my %required_envs = ();
605 open(IN, $filename) or die("Unable to open $filename: $!");
608 if ($_ eq "-- TEST --\n") {
615 if (not defined($tests) or $name =~ /$tests/) {
616 $required_envs{$env} = 1;
617 push (@ret, [$name, $env, $cmdline]);
623 close(IN) or die("Error creating recipe");
627 if ($#testlists == -1) {
628 die("No testlists specified");
631 $ENV{SELFTEST_PREFIX} = "$prefix_abs";
632 if ($opt_socket_wrapper) {
633 $ENV{SELFTEST_INTERFACES} = $interfaces;
635 $ENV{SELFTEST_INTERFACES} = "";
638 $ENV{SELFTEST_VERBOSE} = "1";
640 $ENV{SELFTEST_VERBOSE} = "";
643 $ENV{SELFTEST_QUICK} = "1";
645 $ENV{SELFTEST_QUICK} = "";
647 $ENV{SELFTEST_TARGET} = $opt_target;
648 $ENV{SELFTEST_MAXTIME} = $torture_maxtime;
649 $ENV{SELFTEST_CONFFILE} = $conffile;
652 foreach my $fn (@testlists) {
653 foreach (read_testlist($fn)) {
655 next if (@includes and not find_in_list(\@includes, $name));
656 push (@available, $_);
661 if ($opt_format eq "buildfarm") {
662 require output::buildfarm;
663 $msg_ops = new output::buildfarm($statistics);
664 } elsif ($opt_format eq "plain") {
665 require output::plain;
666 $msg_ops = new output::plain("$prefix/summary", $opt_verbose, $opt_immediate, $statistics, $#available+1);
667 } elsif ($opt_format eq "html") {
668 require output::html;
669 mkdir("test-results", 0777);
670 $msg_ops = new output::html("test-results", $statistics);
672 die("Invalid output format '$opt_format'");
676 foreach (@available) {
678 my $skipreason = skip($name);
680 $msg_ops->skip_testsuite($name, $skipreason);
687 print STDERR "No tests to run\n";
691 my $suitestotal = $#todo + 1;
695 my %running_envs = ();
697 my @exported_envvars = (
702 # domain controller stuff
722 "WINBINDD_SOCKET_DIR",
723 "WINBINDD_PRIV_PIPE_DIR"
726 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
728 teardown_env($_) foreach(keys %running_envs);
729 die("Received signal $signame");
737 if ($envname eq "none") {
739 } elsif (defined($running_envs{$envname})) {
740 $testenv_vars = $running_envs{$envname};
741 if (not $target->check_env($testenv_vars)) {
742 $testenv_vars = undef;
745 $testenv_vars = $target->setup_env($envname, $prefix);
748 return undef unless defined($testenv_vars);
750 $running_envs{$envname} = $testenv_vars;
752 SocketWrapper::set_default_iface(6);
753 write_clientconf($conffile, $testenv_vars);
755 foreach (@exported_envvars) {
756 if (defined($testenv_vars->{$_})) {
757 $ENV{$_} = $testenv_vars->{$_};
763 return $testenv_vars;
766 sub exported_envvars_str($)
768 my ($testenv_vars) = @_;
771 foreach (@exported_envvars) {
772 next unless defined($testenv_vars->{$_});
773 $out .= $_."=".$testenv_vars->{$_}."\n";
782 return "" if ($envname eq "none");
783 return $target->getlog_env($running_envs{$envname});
789 return 1 if ($envname eq "none");
790 return $target->check_env($running_envs{$envname});
796 return if ($envname eq "none");
797 $target->teardown_env($running_envs{$envname});
798 delete $running_envs{$envname};
801 if ($opt_no_lazy_setup) {
802 setup_env($_) foreach (keys %required_envs);
806 my $testenv_name = $ENV{SELFTEST_TESTENV};
807 $testenv_name = $testenv_default unless defined($testenv_name);
809 my $testenv_vars = setup_env($testenv_name);
811 $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
813 my $envvarstr = exported_envvars_str($testenv_vars);
815 my $term = ($ENV{TERM} or "xterm");
816 system("$term -e 'echo -e \"
817 Welcome to the Samba4 Test environment '$testenv_name'
819 This matches the client environment used in make test
820 server is pid `cat \$PIDDIR/samba.pid`
822 Some useful environment variables:
823 TORTURE_OPTIONS=\$TORTURE_OPTIONS
824 CONFIGURATION=\$CONFIGURATION
827 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
828 teardown_env($testenv_name);
833 $cmd =~ s/([\(\)])/\\$1/g;
835 my $envname = $$_[1];
837 my $envvars = setup_env($envname);
838 if (not defined($envvars)) {
839 $msg_ops->skip_testsuite($name, "unable to set up environment $envname");
843 run_testsuite($envname, $name, $cmd, $i, $suitestotal,
846 if (defined($opt_analyse_cmd)) {
847 system("$opt_analyse_cmd \"$name\"");
850 teardown_env($envname) if ($opt_resetup_env);
856 teardown_env($_) foreach (keys %running_envs);
864 # if there were any valgrind failures, show them
865 foreach (<$prefix/valgrind.log*>) {
867 system("grep DWARF2.CFI.reader $_ > /dev/null");
869 print "VALGRIND FAILURE\n";
875 if ($opt_format eq "buildfarm") {
876 print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
879 exit $statistics->{SUITES_FAIL};