2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
4 # Copyright (C) 2007-2009 Stefan Metzmacher <metze@samba.org>
5 # Published under the GNU GPL, v3 or later.
11 selftest - Samba test runner
17 selftest [--srcdir=DIR] [--builddir=DIR] [--exeext=EXT][--target=samba4|samba3|win|kvm] [--socket-wrapper] [--quick] [--exclude=FILE] [--include=FILE] [--one] [--prefix=prefix] [--immediate] [--testlist=FILE] [TESTS]
21 A simple test runner. TESTS is a regular expression with tests to run.
29 Show list of available options.
35 =item I<--builddir=DIR>
45 Change directory to run tests in. Default is 'st'.
49 Show errors as soon as they happen rather than at the end of the test run.
51 =item I<--target samba4|samba3|win|kvm>
53 Specify test target against which to run. Default is 'samba4'.
57 Run only a limited number of tests. Intended to run in about 30 seconds on
58 moderately recent systems.
60 =item I<--socket-wrapper>
62 Use socket wrapper library for communication with server. Only works
63 when the server is running locally.
65 Will prevent TCP and UDP ports being opened on the local host but
66 (transparently) redirects these calls to use unix domain sockets.
68 =item I<--expected-failures>
70 Specify a file containing a list of tests that are expected to fail. Failures for
71 these tests will be counted as successes, successes will be counted as failures.
73 The format for the file is, one entry per line:
75 TESTSUITE-NAME.TEST-NAME
77 The reason for a test can also be specified, by adding a hash sign (#) and the reason
82 Specify a file containing a list of tests that should be skipped. Possible
83 candidates are tests that segfault the server, flip or don't end. The format of this file is the same as
84 for the --expected-failures flag.
88 Specify a file containing a list of tests that should be run. Same format
89 as the --exclude flag.
91 Not includes specified means all tests will be run.
95 Abort as soon as one test fails.
99 Load a list of tests from the specified location.
107 =item I<SMBD_VALGRIND>
109 =item I<TORTURE_MAXTIME>
121 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
131 use FindBin qw($RealBin $Script);
135 use Cwd qw(abs_path);
137 use Subunit qw(parse_results);
141 my $opt_target = "samba4";
143 my $opt_socket_wrapper = 0;
144 my $opt_socket_wrapper_pcap = undef;
145 my $opt_socket_wrapper_keep_pcap = undef;
147 my $opt_immediate = 0;
148 my $opt_expected_failures = undef;
149 my @opt_exclude = ();
150 my @opt_include = ();
152 my $opt_image = undef;
155 my $opt_analyse_cmd = undef;
156 my $opt_resetup_env = undef;
157 my $opt_bindir = undef;
158 my $opt_no_lazy_setup = undef;
159 my $opt_format = "plain";
167 my @expected_failures = ();
174 TESTS_UNEXPECTED_OK => 0,
175 TESTS_EXPECTED_OK => 0,
176 TESTS_UNEXPECTED_FAIL => 0,
177 TESTS_EXPECTED_FAIL => 0,
184 my ($list, $fullname) = @_;
187 if ($fullname =~ /$$_[0]/) {
188 return ($$_[1]) if ($$_[1]);
189 return "NO REASON SPECIFIED";
196 sub expecting_failure($)
199 return find_in_list(\@expected_failures, $name);
206 return find_in_list(\@excludes, $name);
215 return unless ($opt_socket_wrapper_pcap);
216 return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
219 $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
221 my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
223 SocketWrapper::setup_pcap($pcap_file);
228 sub cleanup_pcap($$$)
230 my ($pcap_file, $expected_ret, $ret) = @_;
232 return unless ($opt_socket_wrapper_pcap);
233 return if ($opt_socket_wrapper_keep_pcap);
234 return unless ($expected_ret == $ret);
235 return unless defined($pcap_file);
240 sub run_testsuite($$$$$$)
242 my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
243 my $pcap_file = setup_pcap($name);
245 $msg_ops->start_test([], $name);
247 unless (open(RESULT, "$cmd 2>&1|")) {
248 $statistics->{TESTS_ERROR}++;
249 $msg_ops->end_test([], $name, "error", 1, "Unable to run $cmd: $!");
250 $statistics->{SUITES_FAIL}++;
254 my $expected_ret = parse_results(
255 $msg_ops, $statistics, *RESULT, \&expecting_failure, [$name]);
257 my $envlog = getlog_env($envname);
258 $msg_ops->output_msg("ENVLOG: $envlog\n") if ($envlog ne "");
260 $msg_ops->output_msg("CMD: $cmd\n");
262 my $ret = close(RESULT);
263 $ret = 0 unless $ret == 1;
265 my $exitcode = $? >> 8;
268 $msg_ops->end_test([], $name, "success", $expected_ret != $ret, undef);
270 $msg_ops->end_test([], $name, "failure", $expected_ret != $ret, "Exit code was $exitcode");
273 cleanup_pcap($pcap_file, $expected_ret, $ret);
275 if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
276 $msg_ops->output_msg("PCAP FILE: $pcap_file\n");
279 if ($ret != $expected_ret) {
280 $statistics->{SUITES_FAIL}++;
281 exit(1) if ($opt_one);
284 return ($ret == $expected_ret);
289 print "Samba test runner
290 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
291 Copyright (C) Stefan Metzmacher <metze\@samba.org>
293 Usage: $Script [OPTIONS] TESTNAME-REGEX
296 --help this help page
297 --target=samba[34]|win|kvm Samba version to target
298 --testlist=FILE file to read available tests from
301 --prefix=DIR prefix to run tests in [st]
302 --srcdir=DIR source directory [.]
303 --builddir=DIR output directory [.]
304 --exeext=EXT executable extention []
307 --socket-wrapper-pcap save traffic to pcap directories
308 --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that
310 --socket-wrapper enable socket wrapper
311 --bindir=PATH path to target binaries
312 --expected-failures=FILE specify list of tests that is guaranteed to fail
315 --ldap=openldap|fedora-ds back samba onto specified ldap server
318 --image=PATH path to KVM image
321 --quick run quick overall test
322 --one abort when the first test fails
323 --immediate print test output for failed tests during run
325 --analyse-cmd CMD command to run after each test
330 my $result = GetOptions (
331 'help|h|?' => \$opt_help,
332 'target=s' => \$opt_target,
333 'prefix=s' => \$prefix,
334 'socket-wrapper' => \$opt_socket_wrapper,
335 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
336 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
337 'quick' => \$opt_quick,
339 'immediate' => \$opt_immediate,
340 'expected-failures=s' => \$opt_expected_failures,
341 'exclude=s' => \@opt_exclude,
342 'include=s' => \@opt_include,
343 'srcdir=s' => \$srcdir,
344 'builddir=s' => \$builddir,
345 'exeext=s' => \$exeext,
346 'verbose' => \$opt_verbose,
347 'testenv' => \$opt_testenv,
349 'analyse-cmd=s' => \$opt_analyse_cmd,
350 'no-lazy-setup' => \$opt_no_lazy_setup,
351 'resetup-environment' => \$opt_resetup_env,
352 'bindir:s' => \$opt_bindir,
353 'format=s' => \$opt_format,
354 'image=s' => \$opt_image,
355 'testlist=s' => \@testlists
358 exit(1) if (not $result);
360 ShowHelp() if ($opt_help);
364 # quick hack to disable rpc validation when using valgrind - its way too slow
365 unless (defined($ENV{VALGRIND})) {
366 $ENV{VALIDATE} = "validate";
367 $ENV{MALLOC_CHECK_} = 2;
370 my $bindir = ($opt_bindir or "$builddir/bin");
371 my $bindir_abs = abs_path($bindir);
373 # Backwards compatibility:
374 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
375 if (defined($ENV{FEDORA_DS_ROOT})) {
382 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
385 $torture_maxtime *= 2;
392 die("using an empty prefix isn't allowed") unless $prefix ne "";
394 #Ensure we have the test prefix around
395 mkdir($prefix, 0777) unless -d $prefix;
397 my $prefix_abs = abs_path($prefix);
398 my $srcdir_abs = abs_path($srcdir);
399 my $builddir_abs = abs_path($builddir);
401 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
402 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
404 $ENV{PREFIX} = $prefix;
405 $ENV{KRB5CCNAME} = "$prefix/krb5ticket";
406 $ENV{PREFIX_ABS} = $prefix_abs;
407 $ENV{SRCDIR} = $srcdir;
408 $ENV{SRCDIR_ABS} = $srcdir_abs;
409 $ENV{BUILDDIR} = $builddir;
410 $ENV{BUILDDIR_ABS} = $builddir_abs;
411 $ENV{EXEEXT} = $exeext;
413 if (defined($ENV{RUN_FROM_BUILD_FARM}) and
414 ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
415 $opt_format = "buildfarm";
418 my $tls_enabled = not $opt_quick;
419 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
420 $ENV{LDB_MODULES_PATH} = "$bindir_abs/modules/ldb";
421 $ENV{LD_SAMBA_MODULE_PATH} = "$bindir_abs/modules";
422 sub prefix_pathvar($$)
424 my ($name, $newpath) = @_;
425 if (defined($ENV{$name})) {
426 $ENV{$name} = "$newpath:$ENV{$name}";
428 $ENV{$name} = $newpath;
431 prefix_pathvar("PKG_CONFIG_PATH", "$bindir_abs/pkgconfig");
432 prefix_pathvar("PYTHONPATH", "$bindir_abs/python");
434 if ($opt_socket_wrapper_keep_pcap) {
435 # Socket wrapper keep pcap implies socket wrapper pcap
436 $opt_socket_wrapper_pcap = 1;
439 if ($opt_socket_wrapper_pcap) {
440 # Socket wrapper pcap implies socket wrapper
441 $opt_socket_wrapper = 1;
444 my $socket_wrapper_dir;
445 if ($opt_socket_wrapper) {
446 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
447 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
450 print "WARNING: Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports\n";
455 my $testenv_default = "none";
457 if ($opt_target eq "samba4") {
458 $testenv_default = "member";
459 require target::Samba4;
460 $target = new Samba4($bindir, $ldap, "$srcdir/setup", $exeext);
461 } elsif ($opt_target eq "samba3") {
462 if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
463 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
465 $testenv_default = "member";
466 require target::Samba3;
467 $target = new Samba3($bindir);
468 } elsif ($opt_target eq "samba34") {
469 if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
470 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
472 $testenv_default = "franky_dc";
473 require target::Samba34;
474 $target = new Samba34($bindir);
475 } elsif ($opt_target eq "win") {
476 die("Windows tests will not run with socket wrapper enabled.")
477 if ($opt_socket_wrapper);
478 $testenv_default = "dc";
479 require target::Windows;
480 $target = new Windows();
481 } elsif ($opt_target eq "kvm") {
482 die("Kvm tests will not run with socket wrapper enabled.")
483 if ($opt_socket_wrapper);
485 die("No image specified") unless ($opt_image);
486 $target = new Kvm($opt_image, undef);
490 # Start a Virtual Distributed Ethernet Switch
491 # Returns the pid of the switch.
493 sub start_vde_switch($)
497 system("vde_switch --pidfile $path/vde.pid --sock $path/vde.sock --daemon");
499 open(PID, "$path/vde.pid");
507 # Stop a Virtual Distributed Ethernet Switch
508 sub stop_vde_switch($)
514 sub read_test_regexes($)
518 open(LF, "<$name") or die("unable to read $name: $!");
522 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
523 push (@ret, [$1, $4]);
525 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
526 push (@ret, [$_, undef]);
533 if (defined($opt_expected_failures)) {
534 @expected_failures = read_test_regexes($opt_expected_failures);
537 foreach (@opt_exclude) {
538 push (@excludes, read_test_regexes($_));
541 foreach (@opt_include) {
542 push (@includes, read_test_regexes($_));
545 my $interfaces = join(',', ("127.0.0.6/8",
552 my $conffile = "$prefix_abs/client/client.conf";
553 $ENV{SMB_CONF_PATH} = $conffile;
555 sub write_clientconf($$)
557 my ($conffile, $vars) = @_;
559 mkdir("$prefix/client", 0777) unless -d "$prefix/client";
561 if ( -d "$prefix/client/private" ) {
562 unlink <$prefix/client/private/*>;
564 mkdir("$prefix/client/private", 0777);
567 if ( -d "$prefix/client/lock" ) {
568 unlink <$prefix/client/lockdir/*>;
570 mkdir("$prefix/client/lockdir", 0777);
573 open(CF, ">$conffile");
574 print CF "[global]\n";
575 if (defined($ENV{VALGRIND})) {
576 print CF "\ticonv:native = true\n";
578 print CF "\ticonv:native = false\n";
580 print CF "\tnetbios name = client\n";
581 if (defined($vars->{DOMAIN})) {
582 print CF "\tworkgroup = $vars->{DOMAIN}\n";
584 if (defined($vars->{REALM})) {
585 print CF "\trealm = $vars->{REALM}\n";
587 if ($opt_socket_wrapper) {
588 print CF "\tinterfaces = $interfaces\n";
591 private dir = $prefix_abs/client/private
592 lock dir = $prefix_abs/client/lockdir
593 name resolve order = bcast
594 panic action = $RealBin/gdb_backtrace \%PID\% \%PROG\%
596 notify:inotify = false
598 system:anonymous = true
599 client lanman auth = Yes
600 torture:basedir = $prefix_abs/client
601 #We don't want to pass our self-tests if the PAC code is wrong
602 gensec:require_pac = true
603 modules dir = $ENV{LD_SAMBA_MODULE_PATH}
610 my $testsdir = "$srcdir/selftest";
612 my %required_envs = ();
619 open(IN, $filename) or die("Unable to open $filename: $!");
622 if ($_ eq "-- TEST --\n") {
629 if (not defined($tests) or $name =~ /$tests/) {
630 $required_envs{$env} = 1;
631 push (@ret, [$name, $env, $cmdline]);
637 close(IN) or die("Error creating recipe");
641 if ($#testlists == -1) {
642 die("No testlists specified");
645 $ENV{SELFTEST_PREFIX} = "$prefix_abs";
646 if ($opt_socket_wrapper) {
647 $ENV{SELFTEST_INTERFACES} = $interfaces;
649 $ENV{SELFTEST_INTERFACES} = "";
652 $ENV{SELFTEST_VERBOSE} = "1";
654 $ENV{SELFTEST_VERBOSE} = "";
657 $ENV{SELFTEST_QUICK} = "1";
659 $ENV{SELFTEST_QUICK} = "";
661 $ENV{SELFTEST_TARGET} = $opt_target;
662 $ENV{SELFTEST_MAXTIME} = $torture_maxtime;
665 foreach my $fn (@testlists) {
666 foreach (read_testlist($fn)) {
668 next if (@includes and not find_in_list(\@includes, $name));
669 push (@available, $_);
674 if ($opt_format eq "buildfarm") {
675 require output::buildfarm;
676 $msg_ops = new output::buildfarm($statistics);
677 } elsif ($opt_format eq "plain") {
678 require output::plain;
679 $msg_ops = new output::plain("$prefix/summary", $opt_verbose, $opt_immediate, $statistics, $#available+1);
680 } elsif ($opt_format eq "html") {
681 require output::html;
682 mkdir("test-results", 0777);
683 $msg_ops = new output::html("test-results", $statistics);
685 die("Invalid output format '$opt_format'");
689 foreach (@available) {
691 my $skipreason = skip($name);
693 $msg_ops->skip_testsuite($name, $skipreason);
700 print STDERR "No tests to run\n";
704 my $suitestotal = $#todo + 1;
708 my %running_envs = ();
710 sub get_running_env($)
718 return $running_envs{$envname};
721 my @exported_envvars = (
726 # domain controller stuff
746 "WINBINDD_SOCKET_DIR",
747 "WINBINDD_PRIV_PIPE_DIR"
750 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
752 teardown_env($_) foreach(keys %running_envs);
753 die("Received signal $signame");
760 my $testenv_vars = undef;
766 $option =~ s/^[^:]*//;
769 $option = "client" if $option eq "";
771 if ($envname eq "none") {
773 } elsif (defined(get_running_env($envname))) {
774 $testenv_vars = get_running_env($envname);
775 if (not $target->check_env($testenv_vars)) {
776 $testenv_vars = undef;
779 $testenv_vars = $target->setup_env($envname, $prefix);
782 return undef unless defined($testenv_vars);
784 $running_envs{$envname} = $testenv_vars;
786 if ($option eq "local") {
787 SocketWrapper::set_default_iface($testenv_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
788 $ENV{SMB_CONF_PATH} = $testenv_vars->{SERVERCONFFILE};
789 } elsif ($option eq "client") {
790 SocketWrapper::set_default_iface(6);
791 write_clientconf($conffile, $testenv_vars);
792 $ENV{SMB_CONF_PATH} = $conffile;
794 die("Unknown option[$option] for envname[$envname]");
797 foreach (@exported_envvars) {
798 if (defined($testenv_vars->{$_})) {
799 $ENV{$_} = $testenv_vars->{$_};
805 return $testenv_vars;
808 sub exported_envvars_str($)
810 my ($testenv_vars) = @_;
813 foreach (@exported_envvars) {
814 next unless defined($testenv_vars->{$_});
815 $out .= $_."=".$testenv_vars->{$_}."\n";
824 return "" if ($envname eq "none");
825 return $target->getlog_env(get_running_env($envname));
831 return 1 if ($envname eq "none");
832 return $target->check_env(get_running_env($envname));
838 return if ($envname eq "none");
839 $target->teardown_env(get_running_env($envname));
840 delete $running_envs{$envname};
843 if ($opt_no_lazy_setup) {
844 setup_env($_) foreach (keys %required_envs);
848 my $testenv_name = $ENV{SELFTEST_TESTENV};
849 $testenv_name = $testenv_default unless defined($testenv_name);
851 my $testenv_vars = setup_env($testenv_name);
853 $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
855 my $envvarstr = exported_envvars_str($testenv_vars);
857 my $term = ($ENV{TERM} or "xterm");
858 system("$term -e 'echo -e \"
859 Welcome to the Samba4 Test environment '$testenv_name'
861 This matches the client environment used in make test
862 server is pid `cat \$PIDDIR/samba.pid`
864 Some useful environment variables:
865 TORTURE_OPTIONS=\$TORTURE_OPTIONS
866 SMB_CONF_PATH=\$SMB_CONF_PATH
869 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
870 teardown_env($testenv_name);
875 $cmd =~ s/([\(\)])/\\$1/g;
877 my $envname = $$_[1];
879 my $envvars = setup_env($envname);
880 if (not defined($envvars)) {
881 $msg_ops->skip_testsuite($name, "unable to set up environment $envname");
885 run_testsuite($envname, $name, $cmd, $i, $suitestotal,
888 if (defined($opt_analyse_cmd)) {
889 system("$opt_analyse_cmd \"$name\"");
892 teardown_env($envname) if ($opt_resetup_env);
898 teardown_env($_) foreach (keys %running_envs);
906 # if there were any valgrind failures, show them
907 foreach (<$prefix/valgrind.log*>) {
909 system("grep DWARF2.CFI.reader $_ > /dev/null");
911 print "VALGRIND FAILURE\n";
917 if ($opt_format eq "buildfarm") {
918 print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
921 exit $statistics->{SUITES_FAIL};