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);
139 my $opt_target = "samba4";
141 my $opt_socket_wrapper = 0;
142 my $opt_socket_wrapper_pcap = undef;
143 my $opt_socket_wrapper_keep_pcap = undef;
145 my $opt_immediate = 0;
146 my $opt_expected_failures = undef;
147 my @opt_exclude = ();
148 my @opt_include = ();
152 my $opt_analyse_cmd = undef;
153 my $opt_resetup_env = undef;
154 my $opt_bindir = undef;
155 my $opt_no_lazy_setup = undef;
156 my $opt_format = "plain";
163 my @expected_failures = ();
170 TESTS_UNEXPECTED_OK => 0,
171 TESTS_EXPECTED_OK => 0,
172 TESTS_UNEXPECTED_FAIL => 0,
173 TESTS_EXPECTED_FAIL => 0,
180 my ($list, $fullname) = @_;
183 if ($fullname =~ /$$_[0]/) {
184 return ($$_[1]) if ($$_[1]);
185 return "NO REASON SPECIFIED";
192 sub expecting_failure($)
195 return find_in_list(\@expected_failures, $name);
202 return find_in_list(\@excludes, $name);
209 my ($state, $name) = @_;
211 return unless ($opt_socket_wrapper_pcap);
212 return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
215 $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
217 my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
219 SocketWrapper::setup_pcap($pcap_file);
224 sub cleanup_pcap($$$)
226 my ($pcap_file, $expected_ret, $ret) = @_;
228 return unless ($opt_socket_wrapper_pcap);
229 return if ($opt_socket_wrapper_keep_pcap);
230 return unless ($expected_ret == $ret);
231 return unless defined($pcap_file);
236 sub run_testsuite($$$$$$)
238 my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
239 my $pcap_file = setup_pcap($name);
241 $msg_ops->start_test([], $name);
243 open(RESULT, "$cmd 2>&1|");
244 my $expected_ret = parse_results(
245 $msg_ops, $statistics, *RESULT, \&expecting_failure, [$name]);
247 my $envlog = getlog_env($envname);
248 $msg_ops->output_msg("ENVLOG: $envlog\n") if ($envlog ne "");
250 $msg_ops->output_msg("CMD: $cmd\n");
252 my $ret = close(RESULT);
253 $ret = 0 unless $ret == 1;
256 $msg_ops->end_test([], $name, "success", $expected_ret != $ret, undef);
258 $msg_ops->end_test([], $name, "failure", $expected_ret != $ret,
262 cleanup_pcap($pcap_file, $expected_ret, $ret);
264 if (not $opt_socket_wrapper_keep_pcap and
265 defined($pcap_file)) {
266 $msg_ops->output_msg("PCAP FILE: $pcap_file\n");
269 if ($ret != $expected_ret) {
270 $statistics->{SUITES_FAIL}++;
271 exit(1) if ($opt_one);
274 return ($ret == $expected_ret);
279 print "Samba test runner
280 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
282 Usage: $Script [OPTIONS] PREFIX
285 --help this help page
286 --target=samba4|samba3|win Samba version to target
287 --testlist=FILE file to read available tests from
290 --prefix=DIR prefix to run tests in [st]
291 --srcdir=DIR source directory [.]
292 --builddir=DIR output directory [.]
295 --socket-wrapper-pcap save traffic to pcap directories
296 --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that
298 --socket-wrapper enable socket wrapper
299 --expected-failures=FILE specify list of tests that is guaranteed to fail
302 --ldap=openldap|fedora-ds back smbd onto specified ldap server
305 --bindir=PATH path to binaries
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 'testlist=s' => \@testlists
343 exit(1) if (not $result);
345 ShowHelp() if ($opt_help);
349 # quick hack to disable rpc validation when using valgrind - its way too slow
350 unless (defined($ENV{VALGRIND})) {
351 $ENV{VALIDATE} = "validate";
352 $ENV{MALLOC_CHECK_} = 2;
355 my $old_pwd = "$RealBin/..";
357 # Backwards compatibility:
358 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
359 if (defined($ENV{FEDORA_DS_ROOT})) {
366 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
369 $torture_maxtime *= 2;
376 die("using an empty prefix isn't allowed") unless $prefix ne "";
378 #Ensure we have the test prefix around
379 mkdir($prefix, 0777) unless -d $prefix;
381 my $prefix_abs = abs_path($prefix);
382 my $srcdir_abs = abs_path($srcdir);
384 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
385 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
387 $ENV{PREFIX} = $prefix;
388 $ENV{PREFIX_ABS} = $prefix_abs;
389 $ENV{SRCDIR} = $srcdir;
390 $ENV{SRCDIR_ABS} = $srcdir_abs;
392 if (defined($ENV{RUN_FROM_BUILD_FARM}) and
393 ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
394 $opt_format = "buildfarm";
397 my $tls_enabled = not $opt_quick;
398 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
399 $ENV{LDB_MODULES_PATH} = "$old_pwd/bin/modules/ldb";
400 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules";
401 if (defined($ENV{PKG_CONFIG_PATH})) {
402 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}";
404 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig";
406 # Required for smbscript:
407 $ENV{PATH} = "$old_pwd/bin:$old_pwd:$ENV{PATH}";
409 if ($opt_socket_wrapper_keep_pcap) {
410 # Socket wrapper keep pcap implies socket wrapper pcap
411 $opt_socket_wrapper_pcap = 1;
414 if ($opt_socket_wrapper_pcap) {
415 # Socket wrapper pcap implies socket wrapper
416 $opt_socket_wrapper = 1;
419 my $socket_wrapper_dir;
420 if ($opt_socket_wrapper) {
421 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
422 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
424 warn("Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports") unless $< == 0;
428 my $testenv_default = "none";
430 if ($opt_target eq "samba4") {
431 $testenv_default = "member";
432 $target = new Samba4($opt_bindir or "$srcdir/bin", $ldap, "$srcdir/setup");
433 } elsif ($opt_target eq "samba3") {
434 if ($opt_socket_wrapper and `$opt_bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
435 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
437 $testenv_default = "dc";
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 $target = new Windows();
446 sub read_test_regexes($)
450 open(LF, "<$name") or die("unable to read $name: $!");
453 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
454 push (@ret, [$1, $4]);
456 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
457 push (@ret, [$_, undef]);
464 if (defined($opt_expected_failures)) {
465 @expected_failures = read_test_regexes($opt_expected_failures);
468 foreach (@opt_exclude) {
469 push (@excludes, read_test_regexes($_));
473 push (@includes, read_test_regexes("samba4-quick"));
476 foreach (@opt_include) {
477 push (@includes, read_test_regexes($_));
480 my $interfaces = join(',', ("127.0.0.6/8",
487 my $conffile = "$prefix_abs/client/client.conf";
489 sub write_clientconf($$)
491 my ($conffile, $vars) = @_;
493 mkdir("$prefix/client", 0777) unless -d "$prefix/client";
495 if ( -d "$prefix/client/private" ) {
496 unlink <$prefix/client/private/*>;
498 mkdir("$prefix/client/private", 0777);
501 open(CF, ">$conffile");
502 print CF "[global]\n";
503 if (defined($ENV{VALGRIND})) {
504 print CF "\ticonv:native = true\n";
506 print CF "\ticonv:native = false\n";
508 print CF "\tnetbios name = client\n";
509 if (defined($vars->{DOMAIN})) {
510 print CF "\tworkgroup = $vars->{DOMAIN}\n";
512 if (defined($vars->{REALM})) {
513 print CF "\trealm = $vars->{REALM}\n";
515 if (defined($vars->{NCALRPCDIR})) {
516 print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n";
518 if (defined($vars->{PIDDIR})) {
519 print CF "\tpid directory = $vars->{PIDDIR}\n";
521 if (defined($vars->{WINBINDD_SOCKET_DIR})) {
522 print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n";
525 private dir = $prefix_abs/client/private
526 js include = $srcdir_abs/scripting/libjs
527 name resolve order = bcast
528 interfaces = $interfaces
529 panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\%
531 notify:inotify = false
533 system:anonymous = true
534 torture:basedir = $prefix_abs/client
535 #We don't want to pass our self-tests if the PAC code is wrong
536 gensec:require_pac = true
537 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};
746 if ($opt_no_lazy_setup) {
747 setup_env($_) foreach (keys %required_envs);
751 my $testenv_name = $ENV{SELFTEST_TESTENV};
752 $testenv_name = $testenv_default unless defined($testenv_name);
754 my $testenv_vars = setup_env($testenv_name);
756 $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
758 my $envvarstr = exported_envvars_str($testenv_vars);
760 my $term = ($ENV{TERM} or "xterm");
761 system("$term -e 'echo -e \"
762 Welcome to the Samba4 Test environment '$testenv_name'
764 This matches the client environment used in make test
765 smbd is pid `cat \$PIDDIR/smbd.pid`
767 Some useful environment variables:
768 TORTURE_OPTIONS=\$TORTURE_OPTIONS
769 CONFIGURATION=\$CONFIGURATION
773 teardown_env($testenv_name);
778 $cmd =~ s/([\(\)])/\\$1/g;
780 my $envname = $$_[1];
782 my $envvars = setup_env($envname);
783 if (not defined($envvars)) {
784 $msg_ops->skip_testsuite($name, "unable to set up environment $envname");
788 run_testsuite($envname, $name, $cmd, $i, $suitestotal,
791 if (defined($opt_analyse_cmd)) {
792 system("$opt_analyse_cmd \"$name\"");
795 teardown_env($envname) if ($opt_resetup_env);
801 teardown_env($_) foreach (keys %running_envs);
809 # if there were any valgrind failures, show them
810 foreach (<$prefix/valgrind.log*>) {
812 system("grep DWARF2.CFI.reader $_ > /dev/null");
814 print "VALGRIND FAILURE\n";
820 if ($opt_format eq "buildfarm") {
821 print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
824 exit $statistics->{SUITES_FAIL};