2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2007 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 = ();
149 my $opt_analyse_cmd = undef;
150 my $opt_resetup_env = undef;
151 my $opt_bindir = undef;
152 my $opt_no_lazy_setup = undef;
153 my $opt_format = "plain";
160 my @expected_failures = ();
167 TESTS_UNEXPECTED_OK => 0,
168 TESTS_EXPECTED_OK => 0,
169 TESTS_UNEXPECTED_FAIL => 0,
170 TESTS_EXPECTED_FAIL => 0,
177 my ($list, $fullname) = @_;
180 if ($fullname =~ /$$_[0]/) {
181 return ($$_[1]) if ($$_[1]);
182 return "NO REASON SPECIFIED";
189 sub expecting_failure($)
192 return find_in_list(\@expected_failures, $name);
199 return find_in_list(\@excludes, $name);
206 my ($state, $name) = @_;
208 return unless ($opt_socket_wrapper_pcap);
209 return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
212 $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
214 my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
216 SocketWrapper::setup_pcap($pcap_file);
221 sub cleanup_pcap($$$)
223 my ($pcap_file, $expected_ret, $ret) = @_;
225 return unless ($opt_socket_wrapper_pcap);
226 return if ($opt_socket_wrapper_keep_pcap);
227 return unless ($expected_ret == $ret);
228 return unless defined($pcap_file);
233 sub run_testsuite($$$$$$)
235 my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
236 my $pcap_file = setup_pcap($name);
238 $msg_ops->start_test([], $name);
240 open(RESULT, "$cmd 2>&1|");
241 my $expected_ret = parse_results(
242 $msg_ops, $statistics, *RESULT, \&expecting_failure, [$name]);
244 my $envlog = getlog_env($envname);
245 $msg_ops->output_msg("ENVLOG: $envlog\n") if ($envlog ne "");
247 $msg_ops->output_msg("CMD: $cmd\n");
249 my $ret = close(RESULT);
250 $ret = 0 unless $ret == 1;
253 $msg_ops->end_test([], $name, "success", $expected_ret != $ret, undef);
255 $msg_ops->end_test([], $name, "failure", $expected_ret != $ret,
259 cleanup_pcap($pcap_file, $expected_ret, $ret);
261 if (not $opt_socket_wrapper_keep_pcap and
262 defined($pcap_file)) {
263 $msg_ops->output_msg("PCAP FILE: $pcap_file\n");
266 if ($ret != $expected_ret) {
267 $statistics->{SUITES_FAIL}++;
268 exit(1) if ($opt_one);
271 return ($ret == $expected_ret);
276 print "Samba test runner
277 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
279 Usage: $Script [OPTIONS] PREFIX
282 --help this help page
283 --target=samba[34]|win|kvm Samba version to target
284 --testlist=FILE file to read available tests from
287 --prefix=DIR prefix to run tests in [st]
288 --srcdir=DIR source directory [.]
289 --builddir=DIR output directory [.]
292 --socket-wrapper-pcap save traffic to pcap directories
293 --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that
295 --socket-wrapper enable socket wrapper
296 --expected-failures=FILE specify list of tests that is guaranteed to fail
299 --ldap=openldap|fedora-ds back smbd onto specified ldap server
302 --bindir=PATH path to binaries
305 --image=PATH path to KVM image
308 --quick run quick overall test
309 --one abort when the first test fails
310 --immediate print test output for failed tests during run
312 --analyse-cmd CMD command to run after each test
317 my $result = GetOptions (
318 'help|h|?' => \$opt_help,
319 'target=s' => \$opt_target,
320 'prefix=s' => \$prefix,
321 'socket-wrapper' => \$opt_socket_wrapper,
322 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
323 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
324 'quick' => \$opt_quick,
326 'immediate' => \$opt_immediate,
327 'expected-failures=s' => \$opt_expected_failures,
328 'exclude=s' => \@opt_exclude,
329 'include=s' => \@opt_include,
330 'srcdir=s' => \$srcdir,
331 'builddir=s' => \$builddir,
332 'verbose' => \$opt_verbose,
333 'testenv' => \$opt_testenv,
335 'analyse-cmd=s' => \$opt_analyse_cmd,
336 'no-lazy-setup' => \$opt_no_lazy_setup,
337 'resetup-environment' => \$opt_resetup_env,
338 'bindir:s' => \$opt_bindir,
339 'format=s' => \$opt_format,
340 'image=s' => \$opt_image,
341 'testlist=s' => \@testlists
344 exit(1) if (not $result);
346 ShowHelp() if ($opt_help);
350 # quick hack to disable rpc validation when using valgrind - its way too slow
351 unless (defined($ENV{VALGRIND})) {
352 $ENV{VALIDATE} = "validate";
353 $ENV{MALLOC_CHECK_} = 2;
356 my $old_pwd = "$RealBin/..";
358 # Backwards compatibility:
359 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
360 if (defined($ENV{FEDORA_DS_ROOT})) {
367 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
370 $torture_maxtime *= 2;
377 die("using an empty prefix isn't allowed") unless $prefix ne "";
379 #Ensure we have the test prefix around
380 mkdir($prefix, 0777) unless -d $prefix;
382 my $prefix_abs = abs_path($prefix);
383 my $srcdir_abs = abs_path($srcdir);
385 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
386 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
388 $ENV{PREFIX} = $prefix;
389 $ENV{KRB5CCNAME} = "$prefix/krb5ticket";
390 $ENV{PREFIX_ABS} = $prefix_abs;
391 $ENV{SRCDIR} = $srcdir;
392 $ENV{SRCDIR_ABS} = $srcdir_abs;
394 if (defined($ENV{RUN_FROM_BUILD_FARM}) and
395 ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
396 $opt_format = "buildfarm";
399 my $tls_enabled = not $opt_quick;
400 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
401 $ENV{LDB_MODULES_PATH} = "$old_pwd/bin/modules/ldb";
402 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules";
403 if (defined($ENV{PKG_CONFIG_PATH})) {
404 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}";
406 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig";
408 # Required for smbscript:
409 $ENV{PATH} = "$old_pwd/bin:$old_pwd:$ENV{PATH}";
411 if ($opt_socket_wrapper_keep_pcap) {
412 # Socket wrapper keep pcap implies socket wrapper pcap
413 $opt_socket_wrapper_pcap = 1;
416 if ($opt_socket_wrapper_pcap) {
417 # Socket wrapper pcap implies socket wrapper
418 $opt_socket_wrapper = 1;
421 my $socket_wrapper_dir;
422 if ($opt_socket_wrapper) {
423 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
424 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
426 warn("Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports") unless $< == 0;
430 my $testenv_default = "none";
432 if ($opt_target eq "samba4") {
433 $testenv_default = "member";
434 require target::Samba4;
435 $target = new Samba4($opt_bindir or "$srcdir/bin", $ldap, "$srcdir/setup");
436 } elsif ($opt_target eq "samba3") {
437 if ($opt_socket_wrapper and `$opt_bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
438 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
440 $testenv_default = "dc";
441 require target::Samba3;
442 $target = new Samba3($opt_bindir);
443 } elsif ($opt_target eq "win") {
444 die("Windows tests will not run with socket wrapper enabled.")
445 if ($opt_socket_wrapper);
446 $testenv_default = "dc";
447 require target::Windows;
448 $target = new Windows();
449 } elsif ($opt_target eq "kvm") {
451 die("No image specified") unless ($opt_image);
452 $target = new Kvm($opt_image);
455 sub read_test_regexes($)
459 open(LF, "<$name") or die("unable to read $name: $!");
462 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
463 push (@ret, [$1, $4]);
465 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
466 push (@ret, [$_, undef]);
473 if (defined($opt_expected_failures)) {
474 @expected_failures = read_test_regexes($opt_expected_failures);
477 foreach (@opt_exclude) {
478 push (@excludes, read_test_regexes($_));
482 push (@includes, read_test_regexes("samba4-quick"));
485 foreach (@opt_include) {
486 push (@includes, read_test_regexes($_));
489 my $interfaces = join(',', ("127.0.0.6/8",
496 my $conffile = "$prefix_abs/client/client.conf";
498 sub write_clientconf($$)
500 my ($conffile, $vars) = @_;
502 mkdir("$prefix/client", 0777) unless -d "$prefix/client";
504 if ( -d "$prefix/client/private" ) {
505 unlink <$prefix/client/private/*>;
507 mkdir("$prefix/client/private", 0777);
510 open(CF, ">$conffile");
511 print CF "[global]\n";
512 if (defined($ENV{VALGRIND})) {
513 print CF "\ticonv:native = true\n";
515 print CF "\ticonv:native = false\n";
517 print CF "\tnetbios name = client\n";
518 if (defined($vars->{DOMAIN})) {
519 print CF "\tworkgroup = $vars->{DOMAIN}\n";
521 if (defined($vars->{REALM})) {
522 print CF "\trealm = $vars->{REALM}\n";
524 if (defined($vars->{NCALRPCDIR})) {
525 print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n";
527 if (defined($vars->{PIDDIR})) {
528 print CF "\tpid directory = $vars->{PIDDIR}\n";
530 if (defined($vars->{WINBINDD_SOCKET_DIR})) {
531 print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n";
534 private dir = $prefix_abs/client/private
535 js include = $srcdir_abs/scripting/libjs
536 name resolve order = bcast
537 interfaces = $interfaces
538 panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\%
540 notify:inotify = false
542 system:anonymous = true
543 torture:basedir = $prefix_abs/client
544 #We don't want to pass our self-tests if the PAC code is wrong
545 gensec:require_pac = true
546 modules dir = $ENV{LD_SAMBA_MODULE_PATH}
551 my @torture_options = ();
552 push (@torture_options, "--configfile=$conffile");
553 # ensure any one smbtorture call doesn't run too long
554 push (@torture_options, "--maximum-runtime=$torture_maxtime");
555 push (@torture_options, "--target=$opt_target");
556 push (@torture_options, "--basedir=$prefix_abs");
557 push (@torture_options, "--option=torture:progress=no") if ($opt_format eq "buildfarm");
558 push (@torture_options, "--format=subunit");
559 push (@torture_options, "--option=torture:quick=yes") if ($opt_quick);
561 $ENV{TORTURE_OPTIONS} = join(' ', @torture_options);
562 print "OPTIONS $ENV{TORTURE_OPTIONS}\n";
566 my $testsdir = "$srcdir/selftest";
567 $ENV{SMB_CONF_PATH} = "$conffile";
568 $ENV{CONFIGURATION} = "--configfile=$conffile";
570 my %required_envs = ();
577 open(IN, $filename) or die("Unable to open $filename: $!");
580 if ($_ eq "-- TEST --\n") {
587 if (not defined($tests) or $name =~ /$tests/) {
588 $required_envs{$env} = 1;
589 push (@ret, [$name, $env, $cmdline]);
595 close(IN) or die("Error creating recipe");
599 if ($#testlists == -1) {
600 die("No testlists specified");
604 foreach my $fn (@testlists) {
605 foreach (read_testlist($fn)) {
607 next if (@includes and not find_in_list(\@includes, $name));
608 push (@available, $_);
613 if ($opt_format eq "buildfarm") {
614 require output::buildfarm;
615 $msg_ops = new output::buildfarm($statistics);
616 } elsif ($opt_format eq "plain") {
617 require output::plain;
618 $msg_ops = new output::plain("$prefix/summary", $opt_verbose, $opt_immediate, $statistics, $#available+1);
619 } elsif ($opt_format eq "html") {
620 require output::html;
621 mkdir("test-results", 0777);
622 $msg_ops = new output::html("test-results", $statistics);
624 die("Invalid output format '$opt_format'");
628 foreach (@available) {
630 my $skipreason = skip($name);
632 $msg_ops->skip_testsuite($name, $skipreason);
639 print STDERR "No tests to run\n";
643 my $suitestotal = $#todo + 1;
647 my %running_envs = ();
649 my @exported_envvars = (
654 # domain controller stuff
674 "WINBINDD_SOCKET_DIR",
675 "WINBINDD_PRIV_PIPE_DIR"
678 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
680 teardown_env($_) foreach(keys %running_envs);
681 die("Received signal $signame");
689 if ($envname eq "none") {
691 } elsif (defined($running_envs{$envname})) {
692 $testenv_vars = $running_envs{$envname};
693 if (not $target->check_env($testenv_vars)) {
694 $testenv_vars = undef;
697 $testenv_vars = $target->setup_env($envname, $prefix);
700 return undef unless defined($testenv_vars);
702 $running_envs{$envname} = $testenv_vars;
704 SocketWrapper::set_default_iface(6);
705 write_clientconf($conffile, $testenv_vars);
707 foreach (@exported_envvars) {
708 if (defined($testenv_vars->{$_})) {
709 $ENV{$_} = $testenv_vars->{$_};
715 return $testenv_vars;
718 sub exported_envvars_str($)
720 my ($testenv_vars) = @_;
723 foreach (@exported_envvars) {
724 next unless defined($testenv_vars->{$_});
725 $out .= $_."=".$testenv_vars->{$_}."\n";
734 return "" if ($envname eq "none");
735 return $target->getlog_env($running_envs{$envname});
741 return 1 if ($envname eq "none");
742 return $target->check_env($running_envs{$envname});
748 return if ($envname eq "none");
749 $target->teardown_env($running_envs{$envname});
750 delete $running_envs{$envname};
753 if ($opt_no_lazy_setup) {
754 setup_env($_) foreach (keys %required_envs);
758 my $testenv_name = $ENV{SELFTEST_TESTENV};
759 $testenv_name = $testenv_default unless defined($testenv_name);
761 my $testenv_vars = setup_env($testenv_name);
763 $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
765 my $envvarstr = exported_envvars_str($testenv_vars);
767 my $term = ($ENV{TERM} or "xterm");
768 system("$term -e 'echo -e \"
769 Welcome to the Samba4 Test environment '$testenv_name'
771 This matches the client environment used in make test
772 smbd is pid `cat \$PIDDIR/smbd.pid`
774 Some useful environment variables:
775 TORTURE_OPTIONS=\$TORTURE_OPTIONS
776 CONFIGURATION=\$CONFIGURATION
779 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
780 teardown_env($testenv_name);
785 $cmd =~ s/([\(\)])/\\$1/g;
787 my $envname = $$_[1];
789 my $envvars = setup_env($envname);
790 if (not defined($envvars)) {
791 $msg_ops->skip_testsuite($name, "unable to set up environment $envname");
795 run_testsuite($envname, $name, $cmd, $i, $suitestotal,
798 if (defined($opt_analyse_cmd)) {
799 system("$opt_analyse_cmd \"$name\"");
802 teardown_env($envname) if ($opt_resetup_env);
808 teardown_env($_) foreach (keys %running_envs);
816 # if there were any valgrind failures, show them
817 foreach (<$prefix/valgrind.log*>) {
819 system("grep DWARF2.CFI.reader $_ > /dev/null");
821 print "VALGRIND FAILURE\n";
827 if ($opt_format eq "buildfarm") {
828 print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
831 exit $statistics->{SUITES_FAIL};