c407fbd32901970d7f64787cb4713ce5f62328c3
[kai/samba.git] / source4 / selftest / selftest.pl
1 #!/usr/bin/perl
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.
5
6 =pod
7
8 =head1 NAME
9
10 selftest - Samba test runner
11
12 =head1 SYNOPSIS
13
14 selftest --help
15
16 selftest [--srcdir=DIR] [--builddir=DIR] [--target=samba4|samba3|win] [--socket-wrapper] [--quick] [--one] [--prefix=prefix] [--immediate] [TESTS]
17
18 =head1 DESCRIPTION
19
20 A simple test runner. TESTS is a regular expression with tests to run.
21
22 =head1 OPTIONS
23
24 =over 4
25
26 =item I<--help>
27
28 Show list of available options.
29
30 =item I<--srcdir=DIR>
31
32 Source directory.
33
34 =item I<--builddir=DIR>
35
36 Build directory.
37
38 =item I<--prefix=DIR>
39
40 Change directory to run tests in. Default is 'st'.
41
42 =item I<--immediate>
43
44 Show errors as soon as they happen rather than at the end of the test run.
45                 
46 =item I<--target samba4|samba3|win>
47
48 Specify test target against which to run. Default is 'samba4'.
49
50 =item I<--quick>
51
52 Run only a limited number of tests. Intended to run in about 30 seconds on 
53 moderately recent systems.
54                 
55 =item I<--socket-wrapper>
56
57 Use socket wrapper library for communication with server. Only works 
58 when the server is running locally.
59
60 Will prevent TCP and UDP ports being opened on the local host but 
61 (transparently) redirects these calls to use unix domain sockets.
62
63 =item I<--expected-failures>
64
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.
67
68 The format for the file is, one entry per line:
69
70 TESTSUITE-NAME/TEST-NAME
71
72 =item I<--skip>
73
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.
76
77 =item I<--one>
78
79 Abort as soon as one test fails.
80
81 =back
82
83 =head1 ENVIRONMENT
84
85 =over 4
86
87 =item I<SMBD_VALGRIND>
88
89 =item I<TORTURE_MAXTIME>
90
91 =item I<VALGRIND>
92
93 =item I<TLS_ENABLED>
94
95 =item I<srcdir>
96
97 =back
98
99 =head1 LICENSE
100
101 selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
102
103 =head1 AUTHOR
104
105 Jelmer Vernooij
106
107 =cut
108
109 use strict;
110
111 use FindBin qw($RealBin $Script);
112 use File::Spec;
113 use Getopt::Long;
114 use POSIX;
115 use Cwd qw(abs_path);
116 use lib "$RealBin";
117 use Subunit qw(parse_results);
118 use env::Samba3;
119 use env::Samba4;
120 use env::Windows;
121 use SocketWrapper;
122
123 my $opt_help = 0;
124 my $opt_target = "samba4";
125 my $opt_quick = 0;
126 my $opt_socket_wrapper = 0;
127 my $opt_socket_wrapper_pcap = undef;
128 my $opt_socket_wrapper_keep_pcap = undef;
129 my $opt_one = 0;
130 my $opt_immediate = 0;
131 my $opt_expected_failures = undef;
132 my $opt_skip = undef;
133 my $opt_verbose = 0;
134 my $opt_testenv = 0;
135 my $ldap = undef;
136 my $opt_analyse_cmd = undef;
137 my $opt_resetup_env = undef;
138 my $opt_bindir = undef;
139 my $opt_no_lazy_setup = undef;
140 my $opt_format = "plain";
141
142 my $srcdir = ".";
143 my $builddir = ".";
144 my $prefix = "./st";
145
146 my @expected_failures = ();
147 my @skips = ();
148
149 my $statistics = {
150         START_TIME => time(),
151
152         SUITES_FAIL => 0,
153         SUITES_OK => 0,
154         SUITES_SKIPPED => 0,
155
156         TESTS_UNEXPECTED_OK => 0,
157         TESTS_EXPECTED_OK => 0,
158         TESTS_UNEXPECTED_FAIL => 0,
159         TESTS_EXPECTED_FAIL => 0,
160         TESTS_ERROR => 0,
161         TESTS_SKIP => 0,
162 };
163
164 sub expecting_failure($)
165 {
166         my $fullname = shift;
167
168         foreach (@expected_failures) {
169                 return 1 if ($fullname =~ /$_/);
170         }
171
172         return 0;
173 }
174
175 sub skip($)
176 {
177         my $fullname = shift;
178
179         foreach (@skips) {
180                 return 1 if ($fullname =~ /$_/);
181         }
182
183         return 0;
184 }
185
186 sub getlog_env($);
187
188 sub setup_pcap($)
189 {
190         my ($state) = @_;
191
192         return unless ($opt_socket_wrapper_pcap);
193         return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR});
194
195         my $fname = sprintf("t%03u_%s", $state->{INDEX}, $state->{NAME});
196         $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g;
197
198         $state->{PCAP_FILE} = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap";
199
200         SocketWrapper::setup_pcap($state->{PCAP_FILE});
201 }
202
203 sub cleanup_pcap($$$)
204 {
205         my ($state, $expected_ret, $ret) = @_;
206
207         return unless ($opt_socket_wrapper_pcap);
208         return if ($opt_socket_wrapper_keep_pcap);
209         return unless ($expected_ret == $ret);
210         return unless defined($state->{PCAP_FILE});
211
212         unlink($state->{PCAP_FILE});
213         $state->{PCAP_FILE} = undef;
214 }
215
216 sub run_testsuite($$$$$$)
217 {
218         my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_;
219         my $msg_state = {
220                 ENVNAME => $envname,
221                 NAME    => $name,
222                 CMD     => $cmd,
223                 INDEX   => $i,
224                 TOTAL   => $totalsuites,
225                 START_TIME      => time()
226         };
227
228         setup_pcap($msg_state);
229
230         open(RESULT, "$cmd 2>&1|");
231         $msg_ops->start_testsuite($msg_state);
232
233         my $expected_ret = parse_results(
234                 $msg_ops, $msg_state, $statistics, *RESULT, \&expecting_failure);
235
236         my $ret = close(RESULT);
237
238         cleanup_pcap($msg_state, $expected_ret, $ret);
239
240         $msg_ops->end_testsuite($msg_state, $expected_ret, $ret,
241                                                         getlog_env($msg_state->{ENVNAME}));
242
243         if (not $opt_socket_wrapper_keep_pcap and 
244                 defined($msg_state->{PCAP_FILE})) {
245                 $msg_ops->output_msg($msg_state, 
246                         "PCAP FILE: $msg_state->{PCAP_FILE}\n");
247         }
248
249         if ($ret != $expected_ret) {
250                 $statistics->{SUITES_FAIL}++;
251                 exit(1) if ($opt_one);
252         } else {
253                 $statistics->{SUITES_OK}++;
254         }
255
256         return ($ret == $expected_ret);
257 }
258
259 sub ShowHelp()
260 {
261         print "Samba test runner
262 Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
263
264 Usage: $Script [OPTIONS] PREFIX
265
266 Generic options:
267  --help                     this help page
268  --target=samba4|samba3|win Samba version to target
269
270 Paths:
271  --prefix=DIR               prefix to run tests in [st]
272  --srcdir=DIR               source directory [.]
273  --builddir=DIR             output directory [.]
274
275 Target Specific:
276  --socket-wrapper-pcap=DIR      save traffic to pcap directories
277  --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that 
278                             failed
279  --socket-wrapper           enable socket wrapper
280  --expected-failures=FILE   specify list of tests that is guaranteed to fail
281
282 Samba4 Specific:
283  --ldap=openldap|fedora-ds     back smbd onto specified ldap server
284
285 Samba3 Specific:
286  --bindir=PATH              path to binaries
287
288 Behaviour:
289  --quick                    run quick overall test
290  --one                      abort when the first test fails
291  --immediate                print test output for failed tests during run
292  --verbose                  be verbose
293  --analyse-cmd CMD          command to run after each test
294 ";
295         exit(0);
296 }
297
298 my $result = GetOptions (
299                 'help|h|?' => \$opt_help,
300                 'target=s' => \$opt_target,
301                 'prefix=s' => \$prefix,
302                 'socket-wrapper' => \$opt_socket_wrapper,
303                 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap,
304                 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap,
305                 'quick' => \$opt_quick,
306                 'one' => \$opt_one,
307                 'immediate' => \$opt_immediate,
308                 'expected-failures=s' => \$opt_expected_failures,
309                 'skip=s' => \$opt_skip,
310                 'srcdir=s' => \$srcdir,
311                 'builddir=s' => \$builddir,
312                 'verbose' => \$opt_verbose,
313                 'testenv' => \$opt_testenv,
314                 'ldap:s' => \$ldap,
315                 'analyse-cmd=s' => \$opt_analyse_cmd,
316                 'no-lazy-setup' => \$opt_no_lazy_setup,
317                 'resetup-environment' => \$opt_resetup_env,
318                 'bindir:s' => \$opt_bindir,
319                 'format=s' => \$opt_format,
320             );
321
322 exit(1) if (not $result);
323
324 ShowHelp() if ($opt_help);
325
326 my $tests = shift;
327
328 # quick hack to disable rpc validation when using valgrind - its way too slow
329 unless (defined($ENV{VALGRIND})) {
330         $ENV{VALIDATE} = "validate";
331         $ENV{MALLOC_CHECK_} = 2;
332 }
333
334 my $old_pwd = "$RealBin/..";
335
336 # Backwards compatibility:
337 if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") {
338         if (defined($ENV{FEDORA_DS_PREFIX})) {
339                 $ldap = "fedora-ds";
340         } else {
341                 $ldap = "openldap";
342         }
343 }
344
345 my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200);
346 if ($ldap) {
347         # LDAP is slow
348         $torture_maxtime *= 2;
349 }
350
351 $prefix =~ s+//+/+;
352 $prefix =~ s+/./+/+;
353 $prefix =~ s+/$++;
354
355 die("using an empty prefix isn't allowed") unless $prefix ne "";
356
357 #Ensure we have the test prefix around
358 mkdir($prefix, 0777) unless -d $prefix;
359
360 my $prefix_abs = abs_path($prefix);
361 my $srcdir_abs = abs_path($srcdir);
362
363 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
364 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
365
366 $ENV{PREFIX} = $prefix;
367 $ENV{PREFIX_ABS} = $prefix_abs;
368 $ENV{SRCDIR} = $srcdir;
369 $ENV{SRCDIR_ABS} = $srcdir_abs;
370
371 my $tls_enabled = not $opt_quick;
372 if (defined($ENV{RUN_FROM_BUILD_FARM}) and 
373         ($ENV{RUN_FROM_BUILD_FARM} eq "yes")) {
374         $opt_format = "buildfarm";
375 }
376
377 $ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no");
378 $ENV{LD_LDB_MODULE_PATH} = "$old_pwd/bin/modules/ldb";
379 $ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules";
380 if (defined($ENV{LD_LIBRARY_PATH})) {
381         $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared:$ENV{LD_LIBRARY_PATH}";
382 } else {
383         $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared";
384 }
385 if (defined($ENV{PKG_CONFIG_PATH})) {
386         $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}";
387 } else { 
388         $ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig";
389 }
390 # Required for smbscript:
391 $ENV{PATH} = "$old_pwd/bin:$old_pwd:$ENV{PATH}";
392
393
394 if ($opt_socket_wrapper_pcap) {
395         # Socket wrapper pcap implies socket wrapper
396         $opt_socket_wrapper = 1;
397 }
398
399 my $socket_wrapper_dir;
400 if ($opt_socket_wrapper) {
401         $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap);
402         print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n";
403 } else {
404         warn("Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports") unless $< == 0;
405 }
406
407 my $target;
408
409 if ($opt_target eq "samba4") {
410         $target = new Samba4($opt_bindir or "$srcdir/bin", $ldap, "$srcdir/setup");
411 } elsif ($opt_target eq "samba3") {
412         if ($opt_socket_wrapper and `$opt_bindir/smbd -b | grep SOCKET_WRAPPER` eq "") {
413                 die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'.  Exiting....");
414         }
415
416         $target = new Samba3($opt_bindir);
417 } elsif ($opt_target eq "win") {
418         die("Windows tests will not run with socket wrapper enabled.") 
419                 if ($opt_socket_wrapper);
420         $target = new Windows();
421 }
422
423 if (defined($opt_expected_failures)) {
424         open(KNOWN, "<$opt_expected_failures") or die("unable to read known failures file: $!");
425         while (<KNOWN>) { 
426                 chomp; 
427                 s/([ \t]+)\#(.*)$//;
428                 push (@expected_failures, $_); }
429         close(KNOWN);
430 }
431
432 if (defined($opt_skip)) {
433         open(SKIP, "<$opt_skip") or die("unable to read skip file: $!");
434         while (<SKIP>) { 
435                 chomp; 
436                 s/([ \t]+)\#(.*)$//;
437                 push (@skips, $_); }
438         close(SKIP);
439 }
440
441 my $interfaces = join(',', ("127.0.0.6/8", 
442                             "127.0.0.7/8",
443                             "127.0.0.8/8",
444                             "127.0.0.9/8",
445                             "127.0.0.10/8",
446                             "127.0.0.11/8"));
447
448 my $conffile = "$prefix_abs/client/client.conf";
449
450 sub write_clientconf($$)
451 {
452         my ($conffile, $vars) = @_;
453
454         mkdir("$prefix/client", 0777) unless -d "$prefix/client";
455         
456         if ( -d "$prefix/client/private" ) {
457                 unlink <$prefix/client/private/*>;
458         } else {
459                 mkdir("$prefix/client/private", 0777);
460         }
461
462         open(CF, ">$conffile");
463         print CF "[global]\n";
464         if (defined($ENV{VALGRIND})) {
465                 print CF "\ticonv:native = true\n";
466         } else {
467                 print CF "\ticonv:native = false\n";
468         }
469         print CF "\tnetbios name = client\n";
470         if (defined($vars->{DOMAIN})) {
471                 print CF "\tworkgroup = $vars->{DOMAIN}\n";
472         }
473         if (defined($vars->{REALM})) {
474                 print CF "\trealm = $vars->{REALM}\n";
475         }
476         if (defined($vars->{NCALRPCDIR})) {
477                 print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n";
478         }
479         if (defined($vars->{PIDDIR})) {
480                 print CF "\tpid directory = $vars->{PIDDIR}\n";
481         }
482         if (defined($vars->{WINBINDD_SOCKET_DIR})) {
483                 print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n";
484         }
485         print CF "
486         private dir = $prefix_abs/client/private
487         js include = $srcdir_abs/scripting/libjs
488         name resolve order = bcast
489         interfaces = $interfaces
490         panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\%
491         max xmit = 32K
492         notify:inotify = false
493         ldb:nosync = true
494         system:anonymous = true
495         torture:basedir = $prefix_abs/client
496 #We don't want to pass our self-tests if the PAC code is wrong
497         gensec:require_pac = true
498 ";
499         close(CF);
500 }
501
502
503 my @torture_options = ();
504 push (@torture_options, "--configfile=$conffile");
505 # ensure any one smbtorture call doesn't run too long
506 push (@torture_options, "--maximum-runtime=$torture_maxtime");
507 push (@torture_options, "--target=$opt_target");
508 push (@torture_options, "--basedir=$prefix");
509 push (@torture_options, "--option=torture:progress=no") if ($opt_format eq "buildfarm");
510 push (@torture_options, "--format=subunit");
511 push (@torture_options, "--option=torture:quick=yes") if ($opt_quick);
512
513 $ENV{TORTURE_OPTIONS} = join(' ', @torture_options);
514 print "OPTIONS $ENV{TORTURE_OPTIONS}\n";
515
516 my @todo = ();
517
518 my $testsdir = "$srcdir/selftest";
519 $ENV{SMB_CONF_PATH} = "$conffile";
520 $ENV{CONFIGURATION} = "--configfile=$conffile";
521
522 my %required_envs = ();
523
524 if ($opt_quick) {
525         open(IN, "$testsdir/tests_quick.sh|");
526 } else {
527         open(IN, "$testsdir/tests_all.sh|");
528 }
529 while (<IN>) {
530         if ($_ eq "-- TEST --\n") {
531                 my $name = <IN>;
532                 $name =~ s/\n//g;
533                 my $env = <IN>;
534                 $env =~ s/\n//g;
535                 my $cmdline = <IN>;
536                 $cmdline =~ s/\n//g;
537                 if (not defined($tests) or $name =~ /$tests/) {
538                         $required_envs{$env} = 1;
539                         push (@todo, [$name, $env, $cmdline]);
540                 }
541         } else {
542                 print;
543         }
544 }
545 close(IN) or die("Error creating recipe");
546
547 my $suitestotal = $#todo + 1;
548 my $i = 0;
549 $| = 1;
550
551 my %running_envs = ();
552
553 my @exported_envvars = (
554         # domain stuff
555         "DOMAIN",
556         "REALM",
557
558         # domain controller stuff
559         "DC_SERVER",
560         "DC_SERVER_IP",
561         "DC_NETBIOSNAME",
562         "DC_NETBIOSALIAS",
563
564         # server stuff
565         "SERVER",
566         "SERVER_IP",
567         "NETBIOSNAME",
568         "NETBIOSALIAS",
569
570         # user stuff
571         "USERNAME",
572         "PASSWORD",
573         "DC_USERNAME",
574         "DC_PASSWORD",
575
576         # misc stuff
577         "KRB5_CONFIG",
578         "WINBINDD_SOCKET_DIR"
579 );
580
581 sub setup_env($)
582 {
583         my ($envname) = @_;
584
585         my $testenv_vars;
586         if ($envname eq "none") {
587                 $testenv_vars = {};
588         } elsif (defined($running_envs{$envname})) {
589                 $testenv_vars = $running_envs{$envname};
590                 if (not $target->check_env($testenv_vars)) {
591                         $testenv_vars = undef;
592                 }
593         } else {
594                 $testenv_vars = $target->setup_env($envname, $prefix);
595         }
596
597         return undef unless defined($testenv_vars);
598
599         SocketWrapper::set_default_iface(6);
600         write_clientconf($conffile, $testenv_vars);
601
602         foreach (@exported_envvars) {
603                 if (defined($testenv_vars->{$_})) {
604                         $ENV{$_} = $testenv_vars->{$_};
605                 } else {
606                         delete $ENV{$_};
607                 }
608         }
609
610         $running_envs{$envname} = $testenv_vars;
611         return $testenv_vars;
612 }
613
614 sub exported_envvars_str($)
615 {
616         my ($testenv_vars) = @_;
617         my $out = "";
618
619         foreach (@exported_envvars) {
620                 next unless defined($testenv_vars->{$_});
621                 $out .= $_."=".$testenv_vars->{$_}."\n";
622         }
623
624         return $out;
625 }
626
627 sub getlog_env($)
628 {
629         my ($envname) = @_;
630         return "" if ($envname eq "none");
631         return $target->getlog_env($running_envs{$envname});
632 }
633
634 sub check_env($)
635 {
636         my ($envname) = @_;
637         return 1 if ($envname eq "none");
638         return $target->check_env($running_envs{$envname});
639 }
640
641 sub teardown_env($)
642 {
643         my ($envname) = @_;
644         return if ($envname eq "none");
645         $target->teardown_env($running_envs{$envname});
646         delete $running_envs{$envname};
647 }
648
649 my $msg_ops;
650 if ($opt_format eq "buildfarm") {
651         require output::buildfarm;
652         $msg_ops = new output::buildfarm();
653 } elsif ($opt_format eq "plain") {
654         require output::plain;
655         $msg_ops = new output::plain($opt_verbose, $opt_immediate, $statistics);
656 } elsif ($opt_format eq "html") {
657         require output::html;
658         mkdir("test-results", 0777);
659         $msg_ops = new output::html("test-results", $statistics);
660 } else {
661         die("Invalid output format '$opt_format'");
662 }
663
664 if ($opt_no_lazy_setup) {
665         setup_env($_) foreach (keys %required_envs);
666 }
667
668 if ($opt_testenv) {
669         my $testenv_name = $ENV{SELFTEST_TESTENV};
670         $testenv_name = "member" unless defined($testenv_name);
671
672         my $testenv_vars = setup_env($testenv_name);
673
674         $ENV{PIDDIR} = $testenv_vars->{PIDDIR};
675
676         my $envvarstr = exported_envvars_str($testenv_vars);
677
678         my $term = ($ENV{TERM} or "xterm");
679         system("$term -e 'echo -e \"
680 Welcome to the Samba4 Test environment '$testenv_name'
681
682 This matches the client environment used in make test
683 smbd is pid `cat \$PIDDIR/smbd.pid`
684
685 Some useful environment variables:
686 TORTURE_OPTIONS=\$TORTURE_OPTIONS
687 CONFIGURATION=\$CONFIGURATION
688
689 $envvarstr
690 \" && bash'");
691         teardown_env($testenv_name);
692 } else {
693         foreach (@todo) {
694                 $i++;
695                 my $cmd = $$_[2];
696                 $cmd =~ s/([\(\)])/\\$1/g;
697                 my $name = $$_[0];
698                 my $envname = $$_[1];
699                 
700                 if (skip($name)) {
701                         $msg_ops->skip_testsuite($envname, $name);
702                         $statistics->{SUITES_SKIPPED}++;
703                         next;
704                 }
705
706                 my $envvars = setup_env($envname);
707                 if (not defined($envvars)) {
708                         $statistics->{SUITES_FAIL}++;
709                         $statistics->{TESTS_ERROR}++;
710                         $msg_ops->missing_env($name, $envname);
711                         next;
712                 }
713
714                 run_testsuite($envname, $name, $cmd, $i, $suitestotal, $msg_ops);
715
716                 if (defined($opt_analyse_cmd)) {
717                         system("$opt_analyse_cmd \"$name\"");
718                 }
719
720                 teardown_env($envname) if ($opt_resetup_env);
721         }
722 }
723
724 print "\n";
725
726 teardown_env($_) foreach (keys %running_envs);
727
728 $target->stop();
729
730 $statistics->{END_TIME} = time();
731 my $duration = ($statistics->{END_TIME}-$statistics->{START_TIME});
732 $msg_ops->summary();
733 print "DURATION: $duration seconds\n";
734
735 my $failed = 0;
736
737 # if there were any valgrind failures, show them
738 foreach (<$prefix/valgrind.log*>) {
739         next unless (-s $_);
740         system("grep DWARF2.CFI.reader $_ > /dev/null");
741         if ($? >> 8 == 0) {
742             print "VALGRIND FAILURE\n";
743             $failed++;
744             system("cat $_");
745         }
746 }
747
748 if ($opt_format eq "buildfarm") {
749         print "TEST STATUS: $statistics->{SUITES_FAIL}\n";
750 }
751
752 exit $statistics->{SUITES_FAIL};