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] [--one] [--prefix=prefix] [--immediate] [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
74 Specify a file containing a list of tests that should be skipped. Possible candidates are
75 tests that segfault the server, flip or don't end.
79 Abort as soon as one test fails.
87 =item I<SMBD_VALGRIND>
89 =item I<TORTURE_MAXTIME>
103 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
114 use FindBin
qw($RealBin $Script);
124 my $opt_target = "samba4";
126 my $opt_socket_wrapper = 0;
127 my $opt_socket_wrapper_pcap = undef;
129 my $opt_immediate = 0;
130 my $opt_expected_failures = undef;
131 my $opt_skip = undef;
138 my $suitesfailed = [];
140 my @expected_failures = ();
148 TESTS_UNEXPECTED_OK => 0,
149 TESTS_EXPECTED_OK => 0,
150 TESTS_UNEXPECTED_FAIL => 0,
151 TESTS_EXPECTED_FAIL => 0,
155 sub expecting_failure($)
157 my $fullname = shift;
159 return 1 if (grep(/^$fullname$/, @expected_failures));
166 my $fullname = shift;
168 return 1 if (grep(/^$fullname$/, @skips));
172 sub run_test_buildfarm($$$$)
174 my ($name, $cmd, $i, $suitestotal) = @_;
175 print "--==--==--==--==--==--==--==--==--==--==--\n";
176 print "Running test $name (level 0 stdout)\n";
177 print "--==--==--==--==--==--==--==--==--==--==--\n";
180 my $expected_ret = 1;
182 open(RESULT, "$cmd 2>&1|");
185 if (/^test: (.+)\n/) {
186 $open_tests->{$1} = 1;
187 } elsif (/^(success|failure|skip|error): (.*?)( \[)?\n/) {
189 if ($1 eq "success") {
190 delete $open_tests->{$2};
191 if (expecting_failure("$name/$2")) {
192 $statistics->{TESTS_UNEXPECTED_OK}++;
194 $statistics->{TESTS_EXPECTED_OK}++;
196 } elsif ($1 eq "failure") {
197 delete $open_tests->{$2};
198 if (expecting_failure("$name/$2")) {
199 $statistics->{TESTS_EXPECTED_FAIL}++;
202 $statistics->{TESTS_UNEXPECTED_FAIL}++;
204 } elsif ($1 eq "skip") {
205 delete $open_tests->{$2};
206 } elsif ($1 eq "error") {
207 $statistics->{TESTS_ERROR}++;
208 delete $open_tests->{$2};
212 print "COMMAND: $cmd\n";
213 foreach (keys %$open_tests) {
214 print "$_ was started but never finished!\n";
215 $statistics->{TESTS_ERROR}++;
217 my $ret = close(RESULT);
219 print "==========================================\n";
220 if ($ret == $expected_ret) {
221 print "TEST PASSED: $name\n";
223 print "TEST FAILED: $name (status $ret)\n";
225 print "==========================================\n";
228 my $test_output = {};
229 sub run_test_plain($$$$)
231 my ($name, $cmd, $i, $totalsuites) = @_;
233 if ($#$suitesfailed+1 > 0) { $err = ", ".($#$suitesfailed+1)." errors"; }
234 printf "[$i/$totalsuites in " . (time() - $start)."s$err] $name\n";
235 open(RESULT, "$cmd 2>&1|");
236 my $expected_ret = 1;
238 $test_output->{$name} = "";
240 $test_output->{$name}.=$_;
241 print if ($opt_verbose);
242 if (/^test: (.+)\n/) {
243 $open_tests->{$1} = 1;
244 } elsif (/^(success|failure|skip|error): (.*?)( \[)?\n/) {
246 if ($1 eq "success") {
247 delete $open_tests->{$2};
248 if (expecting_failure("$name/$2")) {
249 $statistics->{TESTS_UNEXPECTED_OK}++;
251 $statistics->{TESTS_EXPECTED_OK}++;
253 } elsif ($1 eq "failure") {
254 delete $open_tests->{$2};
255 if (expecting_failure("$name/$2")) {
256 $statistics->{TESTS_EXPECTED_FAIL}++;
259 $statistics->{TESTS_UNEXPECTED_FAIL}++;
261 } elsif ($1 eq "skip") {
262 delete $open_tests->{$2};
263 } elsif ($1 eq "error") {
264 $statistics->{TESTS_ERROR}++;
265 delete $open_tests->{$2};
269 $test_output->{$name}.="COMMAND: $cmd\n";
270 foreach (keys %$open_tests) {
271 $test_output->{$name}.="$_ was started but never finished!\n";
272 $statistics->{TESTS_ERROR}++;
274 my $ret = close(RESULT);
275 if ($ret != $expected_ret and ($opt_immediate or $opt_one) and not $opt_verbose) {
276 print "$test_output->{$name}\n";
278 if ($ret != $expected_ret) {
279 push(@$suitesfailed, $name);
280 $statistics->{SUITES_FAIL}++;
281 exit(1) if ($opt_one);
283 $statistics->{SUITES_OK}++;
289 print "Samba test runner
290 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
292 Usage: $Script [OPTIONS] PREFIX
295 --help this help page
298 --prefix=DIR prefix to run tests in [st]
299 --srcdir=DIR source directory [.]
300 --builddir=DIR output directory [.]
303 --target=samba4|samba3|win Samba version to target
304 --socket-wrapper-pcap=FILE save traffic to pcap file
305 --socket-wrapper enable socket wrapper
306 --expected-failures=FILE specify list of tests that is guaranteed to fail
309 --quick run quick overall test
310 --one abort when the first test fails
311 --immediate print test output for failed tests during run
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=s' => \$opt_socket_wrapper_pcap,
323 'quick' => \$opt_quick,
325 'immediate' => \$opt_immediate,
326 'expected-failures=s' => \$opt_expected_failures,
327 'skip=s' => \$opt_skip,
328 'srcdir=s' => \$srcdir,
329 'builddir=s' => \$builddir,
330 'verbose' => \$opt_verbose
333 exit(1) if (not $result);
335 ShowHelp() if ($opt_help);
339 my $torture_maxtime = $ENV{TORTURE_MAXTIME};
340 unless (defined($torture_maxtime)) {
341 $torture_maxtime = 1200;
344 # quick hack to disable rpc validation when using valgrind - its way too slow
345 unless (defined($ENV{VALGRIND})) {
346 $ENV{VALIDATE} = "validate";
349 my $old_pwd = "$RealBin/../..";
350 my $ldap = (defined($ENV{TEST_LDAP}) and ($ENV{TEST_LDAP} eq "yes"))?1:0;
353 $ENV{PREFIX} = $prefix;
355 $ENV{SRCDIR} = $srcdir;
357 my $bindir = "$srcdir/bin";
358 my $setupdir = "$srcdir/setup";
359 my $testsdir = "$srcdir/script/tests";
361 my $tls_enabled = not $opt_quick;
362 my $from_build_farm = (defined($ENV{RUN_FROM_BUILD_FARM}) and
363 ($ENV{RUN_FROM_BUILD_FARM} eq "yes"));
365 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
366 $ENV{LD_LDB_MODULE_PATH} = "$old_pwd/bin/modules/ldb";
367 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules";
368 if (defined($ENV{LD_LIBRARY_PATH})) {
369 $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared:$ENV{LD_LIBRARY_PATH}";
371 $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared";
373 $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}";
374 $ENV{PATH} = "$old_pwd/bin:$ENV{PATH}";
376 my @torture_options = ();
378 my $testenv_vars = {};
380 if ($opt_target eq "samba4") {
381 $testenv_vars = Samba4::provision($prefix);
382 } elsif ($opt_target eq "win") {
383 die ("Windows tests will not run without root privileges.")
384 if (`whoami` ne "root");
386 die("Windows tests will not run with socket wrapper enabled.")
387 if ($opt_socket_wrapper);
389 die("Windows tests will not run quickly.") if ($opt_quick);
391 die("Environment variable WINTESTCONF has not been defined.\n".
392 "Windows tests will not run unconfigured.") if (not defined($ENV{WINTESTCONF}));
394 die ("$ENV{WINTESTCONF} could not be read.") if (! -r $ENV{WINTESTCONF});
396 $ENV{WINTEST_DIR}="$ENV{SRCDIR}/script/tests/win";
397 } elsif ($opt_target eq "none") {
399 die("unknown target `$opt_target'");
402 foreach (keys %$testenv_vars) { $ENV{$_} = $testenv_vars->{$_}; }
404 if ($opt_socket_wrapper_pcap) {
405 $ENV{SOCKET_WRAPPER_PCAP_FILE} = $opt_socket_wrapper_pcap;
406 # Socket wrapper pcap implies socket wrapper
407 $opt_socket_wrapper = 1;
410 my $socket_wrapper_dir;
411 if ($opt_socket_wrapper)
413 $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w");
414 print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
417 # Start slapd before smbd
419 Samba4::slapd_start($ENV{SLAPD_CONF}, $ENV{LDAPI_ESCAPE}) or die("couldn't start slapd");
421 print "LDAP PROVISIONING...";
422 Samba4::provision_ldap($bindir, $setupdir);
425 $torture_maxtime *= 2;
428 if (defined($opt_expected_failures)) {
429 open(KNOWN, "<$opt_expected_failures") or die("unable to read known failures file: $!");
433 push (@expected_failures, $_); }
437 if (defined($opt_skip)) {
438 open(SKIP, "<$opt_skip") or die("unable to read skip file: $!");
446 my $test_fifo = "$prefix/smbd_test.fifo";
448 $ENV{SMBD_TEST_FIFO} = $test_fifo;
449 $ENV{SMBD_TEST_LOG} = "$prefix/smbd_test.log";
451 SocketWrapper::set_default_iface(1);
453 if (defined($ENV{SMBD_MAX_TIME})) {
454 $max_time = $ENV{SMBD_MAX_TIME};
456 Samba4::smbd_check_or_start($bindir, $test_fifo, $ENV{SMBD_TEST_LOG},
457 $socket_wrapper_dir, $max_time, $ENV{CONFFILE});
459 SocketWrapper::set_default_iface(6);
461 my $interfaces = join(',', ("127.0.0.6/8",
468 push (@torture_options, "--option=interfaces=$interfaces");
469 push (@torture_options, $ENV{CONFIGURATION});
470 # ensure any one smbtorture call doesn't run too long
471 push (@torture_options, "--maximum-runtime=$torture_maxtime");
472 push (@torture_options, "--target=$opt_target");
473 push (@torture_options, "--option=torture:progress=no") if ($from_build_farm);
474 push (@torture_options, "--format=subunit");
475 push (@torture_options, "--option=torture:quick=yes") if ($opt_quick);
477 $ENV{TORTURE_OPTIONS} = join(' ', @torture_options);
478 print "OPTIONS $ENV{TORTURE_OPTIONS}\n";
480 open(DATA, ">$test_fifo");
484 if ($opt_target eq "win") {
485 system("$testsdir/test_win.sh");
488 open(IN, "$testsdir/tests_quick.sh|");
490 open(IN, "$testsdir/tests_all.sh|");
493 if ($_ eq "-- TEST --\n") {
498 push (@todo, [$name, $cmdline])
499 if (not defined($tests) or $name =~ /$tests/);
504 close(IN) or die("Error creating recipe");
507 Samba4::wait_for_start();
509 # start off with 0 failures
512 my $suitestotal = $#todo + 1;
521 $cmd =~ s/([\(\)])/\\$1/g;
525 print "SKIPPED: $name\n";
526 $statistics->{SUITES_SKIPPED}++;
530 if ($from_build_farm) {
531 run_test_buildfarm($name, $cmd, $i, $suitestotal);
533 run_test_plain($name, $cmd, $i, $suitestotal);
543 my $failed = $? >> 8;
545 if (-f "$ENV{PIDDIR}/smbd.pid" ) {
546 open(IN, "<$ENV{PIDDIR}/smbd.pid") or die("unable to open smbd pid file");
551 Samba4::slapd_stop() if ($ldap);
554 my $duration = ($end-$start);
555 my $numfailed = $#$suitesfailed+1;
556 if ($numfailed == 0) {
557 my $ok = $statistics->{TESTS_EXPECTED_OK} + $statistics->{TESTS_EXPECTED_FAIL};
558 print "ALL OK ($ok tests in $statistics->{SUITES_OK} testsuites)\n";
561 unless ($from_build_farm) {
562 if (not $opt_immediate and not $opt_verbose) {
563 foreach (@$suitesfailed) {
564 print "===============================================================================\n";
566 print $test_output->{$_};
571 print "FAILED ($statistics->{TESTS_UNEXPECTED_FAIL} failures and $statistics->{TESTS_ERROR} errors in $statistics->{SUITES_FAIL} testsuites)\n";
574 ************************
575 *** TESTSUITE FAILED ***
576 ************************
581 print "DURATION: $duration seconds\n";
583 # if there were any valgrind failures, show them
584 foreach (<$prefix/valgrind
.log*>) {
586 system("grep DWARF2.CFI.reader $_ > /dev/null");
588 print "VALGRIND FAILURE\n";
594 if ($from_build_farm) {
595 print "TEST STATUS: $numfailed\n";