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] [--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>
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=samba4|samba3|win 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 --quick run quick overall test
306 --one abort when the first test fails
307 --immediate print test output for failed tests during run
309 --analyse-cmd CMD command to run after each test
314 my $result = GetOptions (
315 'help|h|?' => \$opt_help,
316 'target=s' => \$opt_target,
317 'prefix=s' => \$prefix,
318 'socket-wrapper' => \$opt_socket_wrapper,
319 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
320 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
321 'quick' => \$opt_quick,
323 'immediate' => \$opt_immediate,
324 'expected-failures=s' => \$opt_expected_failures,
325 'exclude=s' => \@opt_exclude,
326 'include=s' => \@opt_include,
327 'srcdir=s' => \$srcdir,
328 'builddir=s' => \$builddir,
329 'verbose' => \$opt_verbose,
330 'testenv' => \$opt_testenv,
332 'analyse-cmd=s' => \$opt_analyse_cmd,
333 'no-lazy-setup' => \$opt_no_lazy_setup,
334 'resetup-environment' => \$opt_resetup_env,
335 'bindir:s' => \$opt_bindir,
336 'format=s' => \$opt_format,
337 'testlist=s' => \@testlists
340 exit(1) if (not $result);
342 ShowHelp() if ($opt_help);
346 # quick hack to disable rpc validation when using valgrind - its way too slow
347 unless (defined($ENV{VALGRIND})) {
348 $ENV{VALIDATE} = "validate";
349 $ENV{MALLOC_CHECK_} = 2;
352 my $old_pwd = "$RealBin/..";
354 # Backwards compatibility:
355 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
356 if (defined($ENV{FEDORA_DS_ROOT})) {
363 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
366 $torture_maxtime *= 2;
373 die("using an empty prefix isn't allowed") unless $prefix ne "";
375 #Ensure we have the test prefix around
376 mkdir($prefix, 0777) unless -d $prefix;
378 my $prefix_abs = abs_path($prefix);
379 my $srcdir_abs = abs_path($srcdir);
381 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
382 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
384 $ENV{PREFIX} = $prefix;
385 $ENV{KRB5CCNAME} = "$prefix/krb5ticket";
386 $ENV{PREFIX_ABS} = $prefix_abs;
387 $ENV{SRCDIR} = $srcdir;
388 $ENV{SRCDIR_ABS} = $srcdir_abs;
390 if (defined($ENV{RUN_FROM_BUILD_FARM}) and
391 ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
392 $opt_format = "buildfarm";
395 my $tls_enabled = not $opt_quick;
396 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
397 $ENV{LDB_MODULES_PATH} = "$old_pwd/bin/modules/ldb";
398 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules";
399 if (defined($ENV{PKG_CONFIG_PATH})) {
400 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}";
402 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig";
404 # Required for smbscript:
405 $ENV{PATH} = "$old_pwd/bin:$old_pwd:$ENV{PATH}";
407 if ($opt_socket_wrapper_keep_pcap) {
408 # Socket wrapper keep pcap implies socket wrapper pcap
409 $opt_socket_wrapper_pcap = 1;
412 if ($opt_socket_wrapper_pcap) {
413 # Socket wrapper pcap implies socket wrapper
414 $opt_socket_wrapper = 1;
417 my $socket_wrapper_dir;
418 if ($opt_socket_wrapper) {
419 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
420 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
422 warn("Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports") unless $< == 0;
426 my $testenv_default = "none";
428 if ($opt_target eq "samba4") {
429 $testenv_default = "member";
430 require target::Samba4;
431 $target = new Samba4($opt_bindir or "$srcdir/bin", $ldap, "$srcdir/setup");
432 } elsif ($opt_target eq "samba3") {
433 if ($opt_socket_wrapper and `$opt_bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
434 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
436 $testenv_default = "dc";
437 require target::Samba3;
438 $target = new Samba3($opt_bindir);
439 } elsif ($opt_target eq "win") {
440 die("Windows tests will not run with socket wrapper enabled.")
441 if ($opt_socket_wrapper);
442 $testenv_default = "dc";
443 require target::Windows;
444 $target = new Windows();
447 sub read_test_regexes($)
451 open(LF, "<$name") or die("unable to read $name: $!");
454 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
455 push (@ret, [$1, $4]);
457 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
458 push (@ret, [$_, undef]);
465 if (defined($opt_expected_failures)) {
466 @expected_failures = read_test_regexes($opt_expected_failures);
469 foreach (@opt_exclude) {
470 push (@excludes, read_test_regexes($_));
474 push (@includes, read_test_regexes("samba4-quick"));
477 foreach (@opt_include) {
478 push (@includes, read_test_regexes($_));
481 my $interfaces = join(',', ("127.0.0.6/8",
488 my $conffile = "$prefix_abs/client/client.conf";
490 sub write_clientconf($$)
492 my ($conffile, $vars) = @_;
494 mkdir("$prefix/client", 0777) unless -d "$prefix/client";
496 if ( -d "$prefix/client/private" ) {
497 unlink <$prefix/client/private/*>;
499 mkdir("$prefix/client/private", 0777);
502 open(CF, ">$conffile");
503 print CF "[global]\n";
504 if (defined($ENV{VALGRIND})) {
505 print CF "\ticonv:native = true\n";
507 print CF "\ticonv:native = false\n";
509 print CF "\tnetbios name = client\n";
510 if (defined($vars->{DOMAIN})) {
511 print CF "\tworkgroup = $vars->{DOMAIN}\n";
513 if (defined($vars->{REALM})) {
514 print CF "\trealm = $vars->{REALM}\n";
516 if (defined($vars->{NCALRPCDIR})) {
517 print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n";
519 if (defined($vars->{PIDDIR})) {
520 print CF "\tpid directory = $vars->{PIDDIR}\n";
522 if (defined($vars->{WINBINDD_SOCKET_DIR})) {
523 print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n";
526 private dir = $prefix_abs/client/private
527 js include = $srcdir_abs/scripting/libjs
528 name resolve order = bcast
529 interfaces = $interfaces
530 panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\%
532 notify:inotify = false
534 system:anonymous = true
535 torture:basedir = $prefix_abs/client
536 #We don't want to pass our self-tests if the PAC code is wrong
537 gensec:require_pac = true
538 modules dir = $ENV{LD_SAMBA_MODULE_PATH}
543 my @torture_options = ();
544 push (@torture_options, "--configfile=$conffile");
545 # ensure any one smbtorture call doesn't run too long
546 push (@torture_options, "--maximum-runtime=$torture_maxtime");
547 push (@torture_options, "--target=$opt_target");
548 push (@torture_options, "--basedir=$prefix_abs");
549 push (@torture_options, "--option=torture:progress=no") if ($opt_format eq "buildfarm");
550 push (@torture_options, "--format=subunit");
551 push (@torture_options, "--option=torture:quick=yes") if ($opt_quick);
553 $ENV{TORTURE_OPTIONS} = join(' ', @torture_options);
554 print "OPTIONS $ENV{TORTURE_OPTIONS}\n";
558 my $testsdir = "$srcdir/selftest";
559 $ENV{SMB_CONF_PATH} = "$conffile";
560 $ENV{CONFIGURATION} = "--configfile=$conffile";
562 my %required_envs = ();
569 open(IN, $filename) or die("Unable to open $filename: $!");
572 if ($_ eq "-- TEST --\n") {
579 if (not defined($tests) or $name =~ /$tests/) {
580 $required_envs{$env} = 1;
581 push (@ret, [$name, $env, $cmdline]);
587 close(IN) or die("Error creating recipe");
591 if ($#testlists == -1) {
592 die("No testlists specified");
596 foreach my $fn (@testlists) {
597 foreach (read_testlist($fn)) {
599 next if (@includes and not find_in_list(\@includes, $name));
600 push (@available, $_);
605 if ($opt_format eq "buildfarm") {
606 require output::buildfarm;
607 $msg_ops = new output::buildfarm($statistics);
608 } elsif ($opt_format eq "plain") {
609 require output::plain;
610 $msg_ops = new output::plain("$prefix/summary", $opt_verbose, $opt_immediate, $statistics, $#available+1);
611 } elsif ($opt_format eq "html") {
612 require output::html;
613 mkdir("test-results", 0777);
614 $msg_ops = new output::html("test-results", $statistics);
616 die("Invalid output format '$opt_format'");
620 foreach (@available) {
622 my $skipreason = skip($name);
624 $msg_ops->skip_testsuite($name, $skipreason);
631 print STDERR "No tests to run\n";
635 my $suitestotal = $#todo + 1;
639 my %running_envs = ();
641 my @exported_envvars = (
646 # domain controller stuff
666 "WINBINDD_SOCKET_DIR",
667 "WINBINDD_PRIV_PIPE_DIR"
670 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
672 teardown_env($_) foreach(keys %running_envs);
673 die("Received signal $signame");
681 if ($envname eq "none") {
683 } elsif (defined($running_envs{$envname})) {
684 $testenv_vars = $running_envs{$envname};
685 if (not $target->check_env($testenv_vars)) {
686 $testenv_vars = undef;
689 $testenv_vars = $target->setup_env($envname, $prefix);
692 return undef unless defined($testenv_vars);
694 $running_envs{$envname} = $testenv_vars;
696 SocketWrapper::set_default_iface(6);
697 write_clientconf($conffile, $testenv_vars);
699 foreach (@exported_envvars) {
700 if (defined($testenv_vars->{$_})) {
701 $ENV{$_} = $testenv_vars->{$_};
707 return $testenv_vars;
710 sub exported_envvars_str($)
712 my ($testenv_vars) = @_;
715 foreach (@exported_envvars) {
716 next unless defined($testenv_vars->{$_});
717 $out .= $_."=".$testenv_vars->{$_}."\n";
726 return "" if ($envname eq "none");
727 return $target->getlog_env($running_envs{$envname});
733 return 1 if ($envname eq "none");
734 return $target->check_env($running_envs{$envname});
740 return if ($envname eq "none");
741 $target->teardown_env($running_envs{$envname});
742 delete $running_envs{$envname};
745 if ($opt_no_lazy_setup) {
746 setup_env($_) foreach (keys %required_envs);
750 my $testenv_name = $ENV{SELFTEST_TESTENV};
751 $testenv_name = $testenv_default unless defined($testenv_name);
753 my $testenv_vars = setup_env($testenv_name);
755 $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
757 my $envvarstr = exported_envvars_str($testenv_vars);
759 my $term = ($ENV{TERM} or "xterm");
760 system("$term -e 'echo -e \"
761 Welcome to the Samba4 Test environment '$testenv_name'
763 This matches the client environment used in make test
764 smbd is pid `cat \$PIDDIR/smbd.pid`
766 Some useful environment variables:
767 TORTURE_OPTIONS=\$TORTURE_OPTIONS
768 CONFIGURATION=\$CONFIGURATION
771 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
772 teardown_env($testenv_name);
777 $cmd =~ s/([\(\)])/\\$1/g;
779 my $envname = $$_[1];
781 my $envvars = setup_env($envname);
782 if (not defined($envvars)) {
783 $msg_ops->skip_testsuite($name, "unable to set up environment $envname");
787 run_testsuite($envname, $name, $cmd, $i, $suitestotal,
790 if (defined($opt_analyse_cmd)) {
791 system("$opt_analyse_cmd \"$name\"");
794 teardown_env($envname) if ($opt_resetup_env);
800 teardown_env($_) foreach (keys %running_envs);
808 # if there were any valgrind failures, show them
809 foreach (<$prefix/valgrind.log*>) {
811 system("grep DWARF2.CFI.reader $_ > /dev/null");
813 print "VALGRIND FAILURE\n";
819 if ($opt_format eq "buildfarm") {
820 print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
823 exit $statistics->{SUITES_FAIL};