2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2009 Jelmer Vernooij <jelmer@samba.org>
4 # Copyright (C) 2007-2009 Stefan Metzmacher <metze@samba.org>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 selftest - Samba test runner
29 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]
33 A simple test runner. TESTS is a regular expression with tests to run.
41 Show list of available options.
47 =item I<--builddir=DIR>
57 Change directory to run tests in. Default is 'st'.
61 Show errors as soon as they happen rather than at the end of the test run.
63 =item I<--target samba4|samba3|win|kvm>
65 Specify test target against which to run. Default is 'samba4'.
69 Run only a limited number of tests. Intended to run in about 30 seconds on
70 moderately recent systems.
72 =item I<--socket-wrapper>
74 Use socket wrapper library for communication with server. Only works
75 when the server is running locally.
77 Will prevent TCP and UDP ports being opened on the local host but
78 (transparently) redirects these calls to use unix domain sockets.
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.
87 Specify a file containing a list of tests that should be run. Same format
88 as the --exclude flag.
90 Not includes specified means all tests will be run.
94 Abort as soon as one test fails.
98 Load a list of tests from the specified location.
106 =item I<SMBD_VALGRIND>
108 =item I<TORTURE_MAXTIME>
120 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
130 use FindBin qw($RealBin $Script);
134 use Cwd qw(abs_path);
136 use Subunit qw(parse_results);
140 my $opt_target = "samba4";
142 my $opt_socket_wrapper = 0;
143 my $opt_socket_wrapper_pcap = undef;
144 my $opt_socket_wrapper_keep_pcap = undef;
146 my $opt_immediate = 0;
147 my @opt_exclude = ();
148 my @opt_include = ();
150 my $opt_image = undef;
153 my $opt_analyse_cmd = undef;
154 my $opt_resetup_env = undef;
155 my $opt_bindir = undef;
156 my $opt_no_lazy_setup = undef;
157 my $opt_format = "plain";
171 TESTS_UNEXPECTED_OK => 0,
172 TESTS_EXPECTED_OK => 0,
173 TESTS_UNEXPECTED_FAIL => 0,
174 TESTS_EXPECTED_FAIL => 0,
181 my ($list, $fullname) = @_;
184 if ($fullname =~ /$$_[0]/) {
185 return ($$_[1]) if ($$_[1]);
186 return "NO REASON SPECIFIED";
197 return find_in_list(\@excludes, $name);
206 return unless ($opt_socket_wrapper_pcap);
207 return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
210 $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
212 my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
214 SocketWrapper::setup_pcap($pcap_file);
219 sub cleanup_pcap($$$)
221 my ($pcap_file, $expected_ret, $ret) = @_;
223 return unless ($opt_socket_wrapper_pcap);
224 return if ($opt_socket_wrapper_keep_pcap);
225 return unless ($expected_ret == $ret);
226 return unless defined($pcap_file);
231 sub run_testsuite($$$$$$)
233 my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
234 my $pcap_file = setup_pcap($name);
236 $msg_ops->report_time(time());
237 $msg_ops->start_test([], $name);
239 unless (open(RESULT, "$cmd 2>&1|")) {
240 $statistics->{TESTS_ERROR}++;
241 $msg_ops->end_test([], $name, "error", 1, "Unable to run $cmd: $!");
242 $statistics->{SUITES_FAIL}++;
246 my $expected_ret = parse_results(
247 $msg_ops, $statistics, *RESULT, [$name]);
249 my $envlog = getlog_env($envname);
250 $msg_ops->output_msg("ENVLOG: $envlog\n") if ($envlog ne "");
252 $msg_ops->output_msg("CMD: $cmd\n");
254 my $ret = close(RESULT);
255 $ret = 0 unless $ret == 1;
257 my $exitcode = $? >> 8;
259 $msg_ops->report_time(time());
261 $msg_ops->end_test([], $name, "success", $expected_ret != $ret, undef);
263 $msg_ops->end_test([], $name, "failure", $expected_ret != $ret, "Exit code was $exitcode");
266 cleanup_pcap($pcap_file, $expected_ret, $ret);
268 if (not $opt_socket_wrapper_keep_pcap and defined($pcap_file)) {
269 $msg_ops->output_msg("PCAP FILE: $pcap_file\n");
272 if ($ret != $expected_ret) {
273 $statistics->{SUITES_FAIL}++;
274 exit(1) if ($opt_one);
277 return ($ret == $expected_ret);
282 print "Samba test runner
283 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
284 Copyright (C) Stefan Metzmacher <metze\@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 [.]
297 --exeext=EXT executable extention []
300 --socket-wrapper-pcap save traffic to pcap directories
301 --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that
303 --socket-wrapper enable socket wrapper
304 --bindir=PATH path to target binaries
307 --ldap=openldap|fedora-ds back samba onto specified ldap server
310 --image=PATH path to KVM image
313 --quick run quick overall test
314 --one abort when the first test fails
315 --immediate print test output for failed tests during run
317 --analyse-cmd CMD command to run after each test
322 my $result = GetOptions (
323 'help|h|?' => \$opt_help,
324 'target=s' => \$opt_target,
325 'prefix=s' => \$prefix,
326 'socket-wrapper' => \$opt_socket_wrapper,
327 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
328 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
329 'quick' => \$opt_quick,
331 'immediate' => \$opt_immediate,
332 'exclude=s' => \@opt_exclude,
333 'include=s' => \@opt_include,
334 'srcdir=s' => \$srcdir,
335 'builddir=s' => \$builddir,
336 'exeext=s' => \$exeext,
337 'verbose' => \$opt_verbose,
338 'testenv' => \$opt_testenv,
340 'analyse-cmd=s' => \$opt_analyse_cmd,
341 'no-lazy-setup' => \$opt_no_lazy_setup,
342 'resetup-environment' => \$opt_resetup_env,
343 'bindir:s' => \$opt_bindir,
344 'format=s' => \$opt_format,
345 'image=s' => \$opt_image,
346 'testlist=s' => \@testlists
349 exit(1) if (not $result);
351 ShowHelp() if ($opt_help);
355 # quick hack to disable rpc validation when using valgrind - its way too slow
356 unless (defined($ENV{VALGRIND})) {
357 $ENV{VALIDATE} = "validate";
358 $ENV{MALLOC_CHECK_} = 2;
361 my $bindir = ($opt_bindir or "$builddir/bin");
362 my $bindir_abs = abs_path($bindir);
364 # Backwards compatibility:
365 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
366 if (defined($ENV{FEDORA_DS_ROOT})) {
373 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
376 $torture_maxtime *= 2;
383 die("using an empty prefix isn't allowed") unless $prefix ne "";
385 #Ensure we have the test prefix around
386 mkdir($prefix, 0777) unless -d $prefix;
388 my $prefix_abs = abs_path($prefix);
389 my $srcdir_abs = abs_path($srcdir);
390 my $builddir_abs = abs_path($builddir);
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;
400 $ENV{BUILDDIR} = $builddir;
401 $ENV{BUILDDIR_ABS} = $builddir_abs;
402 $ENV{EXEEXT} = $exeext;
404 if (defined($ENV{RUN_FROM_BUILD_FARM}) and
405 ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
406 $opt_format = "buildfarm";
409 my $tls_enabled = not $opt_quick;
410 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
411 $ENV{LDB_MODULES_PATH} = "$bindir_abs/modules/ldb";
412 $ENV{LD_SAMBA_MODULE_PATH} = "$bindir_abs/modules";
413 sub prefix_pathvar($$)
415 my ($name, $newpath) = @_;
416 if (defined($ENV{$name})) {
417 $ENV{$name} = "$newpath:$ENV{$name}";
419 $ENV{$name} = $newpath;
422 prefix_pathvar("PKG_CONFIG_PATH", "$bindir_abs/pkgconfig");
423 prefix_pathvar("PYTHONPATH", "$bindir_abs/python");
425 if ($opt_socket_wrapper_keep_pcap) {
426 # Socket wrapper keep pcap implies socket wrapper pcap
427 $opt_socket_wrapper_pcap = 1;
430 if ($opt_socket_wrapper_pcap) {
431 # Socket wrapper pcap implies socket wrapper
432 $opt_socket_wrapper = 1;
435 my $socket_wrapper_dir;
436 if ($opt_socket_wrapper) {
437 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
438 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
441 print "WARNING: Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports\n";
446 my $testenv_default = "none";
448 if ($opt_target eq "samba4") {
449 $testenv_default = "member";
450 require target::Samba4;
451 $target = new Samba4($bindir, $ldap, "$srcdir/setup", $exeext);
452 } elsif ($opt_target eq "samba3") {
453 if ($opt_socket_wrapper and `$bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
454 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....");
456 $testenv_default = "member";
457 require target::Samba3;
458 $target = new Samba3($bindir);
459 } elsif ($opt_target eq "win") {
460 die("Windows tests will not run with socket wrapper enabled.")
461 if ($opt_socket_wrapper);
462 $testenv_default = "dc";
463 require target::Windows;
464 $target = new Windows();
465 } elsif ($opt_target eq "kvm") {
466 die("Kvm tests will not run with socket wrapper enabled.")
467 if ($opt_socket_wrapper);
469 die("No image specified") unless ($opt_image);
470 $target = new Kvm($opt_image, undef);
474 # Start a Virtual Distributed Ethernet Switch
475 # Returns the pid of the switch.
477 sub start_vde_switch($)
481 system("vde_switch --pidfile $path/vde.pid --sock $path/vde.sock --daemon");
483 open(PID, "$path/vde.pid");
491 # Stop a Virtual Distributed Ethernet Switch
492 sub stop_vde_switch($)
498 sub read_test_regexes($)
502 open(LF, "<$name") or die("unable to read $name: $!");
506 if (/^(.*?)([ \t]+)\#([\t ]*)(.*?)$/) {
507 push (@ret, [$1, $4]);
509 s/^(.*?)([ \t]+)\#([\t ]*)(.*?)$//;
510 push (@ret, [$_, undef]);
517 foreach (@opt_exclude) {
518 push (@excludes, read_test_regexes($_));
521 foreach (@opt_include) {
522 push (@includes, read_test_regexes($_));
525 my $interfaces = join(',', ("127.0.0.6/8",
532 my $conffile = "$prefix_abs/client/client.conf";
533 $ENV{SMB_CONF_PATH} = $conffile;
535 sub write_clientconf($$)
537 my ($conffile, $vars) = @_;
539 mkdir("$prefix/client", 0777) unless -d "$prefix/client";
541 if ( -d "$prefix/client/private" ) {
542 unlink <$prefix/client/private/*>;
544 mkdir("$prefix/client/private", 0777);
547 if ( -d "$prefix/client/lock" ) {
548 unlink <$prefix/client/lockdir/*>;
550 mkdir("$prefix/client/lockdir", 0777);
553 open(CF, ">$conffile");
554 print CF "[global]\n";
555 if (defined($ENV{VALGRIND})) {
556 print CF "\ticonv:native = true\n";
558 print CF "\ticonv:native = false\n";
560 print CF "\tnetbios name = client\n";
561 if (defined($vars->{DOMAIN})) {
562 print CF "\tworkgroup = $vars->{DOMAIN}\n";
564 if (defined($vars->{REALM})) {
565 print CF "\trealm = $vars->{REALM}\n";
567 if ($opt_socket_wrapper) {
568 print CF "\tinterfaces = $interfaces\n";
571 private dir = $prefix_abs/client/private
572 lock dir = $prefix_abs/client/lockdir
573 name resolve order = bcast
574 panic action = $RealBin/gdb_backtrace \%PID\% \%PROG\%
576 notify:inotify = false
578 system:anonymous = true
579 client lanman auth = Yes
580 torture:basedir = $prefix_abs/client
581 #We don't want to pass our self-tests if the PAC code is wrong
582 gensec:require_pac = true
583 modules dir = $ENV{LD_SAMBA_MODULE_PATH}
590 my $testsdir = "$srcdir/selftest";
592 my %required_envs = ();
599 open(IN, $filename) or die("Unable to open $filename: $!");
602 if ($_ eq "-- TEST --\n") {
609 if (not defined($tests) or $name =~ /$tests/) {
610 $required_envs{$env} = 1;
611 push (@ret, [$name, $env, $cmdline]);
617 close(IN) or die("Error creating recipe");
621 if ($#testlists == -1) {
622 die("No testlists specified");
625 $ENV{SELFTEST_PREFIX} = "$prefix_abs";
626 if ($opt_socket_wrapper) {
627 $ENV{SELFTEST_INTERFACES} = $interfaces;
629 $ENV{SELFTEST_INTERFACES} = "";
632 $ENV{SELFTEST_VERBOSE} = "1";
634 $ENV{SELFTEST_VERBOSE} = "";
637 $ENV{SELFTEST_QUICK} = "1";
639 $ENV{SELFTEST_QUICK} = "";
641 $ENV{SELFTEST_TARGET} = $opt_target;
642 $ENV{SELFTEST_MAXTIME} = $torture_maxtime;
645 foreach my $fn (@testlists) {
646 foreach (read_testlist($fn)) {
648 next if (@includes and not find_in_list(\@includes, $name));
649 push (@available, $_);
654 if ($opt_format eq "buildfarm") {
655 require output::buildfarm;
656 $msg_ops = new output::buildfarm($statistics);
657 } elsif ($opt_format eq "plain") {
658 require output::plain;
659 $msg_ops = new output::plain("$prefix/summary", $opt_verbose, $opt_immediate, $statistics, $#available+1);
660 } elsif ($opt_format eq "html") {
661 require output::html;
662 mkdir("test-results", 0777);
663 $msg_ops = new output::html("test-results", $statistics);
664 } elsif ($opt_format eq "subunit") {
665 require output::subunit;
666 $msg_ops = new output::subunit();
668 die("Invalid output format '$opt_format'");
670 $msg_ops->report_time(time());
672 foreach (@available) {
674 my $skipreason = skip($name);
676 $msg_ops->skip_testsuite($name, $skipreason);
683 print STDERR "No tests to run\n";
687 my $suitestotal = $#todo + 1;
691 my %running_envs = ();
693 sub get_running_env($)
701 return $running_envs{$envname};
704 my @exported_envvars = (
709 # domain controller stuff
729 "WINBINDD_SOCKET_DIR",
730 "WINBINDD_PRIV_PIPE_DIR"
733 $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
735 teardown_env($_) foreach(keys %running_envs);
736 die("Received signal $signame");
743 my $testenv_vars = undef;
749 $option =~ s/^[^:]*//;
752 $option = "client" if $option eq "";
754 if ($envname eq "none") {
756 } elsif (defined(get_running_env($envname))) {
757 $testenv_vars = get_running_env($envname);
758 if (not $target->check_env($testenv_vars)) {
759 $testenv_vars = undef;
762 $testenv_vars = $target->setup_env($envname, $prefix);
765 return undef unless defined($testenv_vars);
767 $running_envs{$envname} = $testenv_vars;
769 if ($option eq "local") {
770 SocketWrapper::set_default_iface($testenv_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
771 $ENV{SMB_CONF_PATH} = $testenv_vars->{SERVERCONFFILE};
772 } elsif ($option eq "client") {
773 SocketWrapper::set_default_iface(6);
774 write_clientconf($conffile, $testenv_vars);
775 $ENV{SMB_CONF_PATH} = $conffile;
777 die("Unknown option[$option] for envname[$envname]");
780 foreach (@exported_envvars) {
781 if (defined($testenv_vars->{$_})) {
782 $ENV{$_} = $testenv_vars->{$_};
788 return $testenv_vars;
791 sub exported_envvars_str($)
793 my ($testenv_vars) = @_;
796 foreach (@exported_envvars) {
797 next unless defined($testenv_vars->{$_});
798 $out .= $_."=".$testenv_vars->{$_}."\n";
807 return "" if ($envname eq "none");
808 return $target->getlog_env(get_running_env($envname));
814 return 1 if ($envname eq "none");
815 return $target->check_env(get_running_env($envname));
821 return if ($envname eq "none");
822 $target->teardown_env(get_running_env($envname));
823 delete $running_envs{$envname};
826 if ($opt_no_lazy_setup) {
827 setup_env($_) foreach (keys %required_envs);
831 my $testenv_name = $ENV{SELFTEST_TESTENV};
832 $testenv_name = $testenv_default unless defined($testenv_name);
834 my $testenv_vars = setup_env($testenv_name);
836 $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
838 my $envvarstr = exported_envvars_str($testenv_vars);
840 my $term = ($ENV{TERM} or "xterm");
841 system("$term -e 'echo -e \"
842 Welcome to the Samba4 Test environment '$testenv_name'
844 This matches the client environment used in make test
845 server is pid `cat \$PIDDIR/samba.pid`
847 Some useful environment variables:
848 TORTURE_OPTIONS=\$TORTURE_OPTIONS
849 SMB_CONF_PATH=\$SMB_CONF_PATH
852 \" && LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} bash'");
853 teardown_env($testenv_name);
858 $cmd =~ s/([\(\)])/\\$1/g;
860 my $envname = $$_[1];
862 my $envvars = setup_env($envname);
863 if (not defined($envvars)) {
864 $msg_ops->skip_testsuite($name,
865 "unable to set up environment $envname");
869 run_testsuite($envname, $name, $cmd, $i, $suitestotal,
872 if (defined($opt_analyse_cmd)) {
873 system("$opt_analyse_cmd \"$name\"");
876 teardown_env($envname) if ($opt_resetup_env);
882 teardown_env($_) foreach (keys %running_envs);
890 # if there were any valgrind failures, show them
891 foreach (<$prefix/valgrind.log*>) {
893 system("grep DWARF2.CFI.reader $_ > /dev/null");
895 print "VALGRIND FAILURE\n";
901 if ($opt_format eq "buildfarm") {
902 print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
905 exit $statistics->{SUITES_FAIL};