]>
The Tcpdump Group git mirrors - tcpdump/blob - tests/TESTlib.pm
1 require 5.8.4; # Solaris 10
3 use warnings FATAL
=> qw(uninitialized);
5 use File
::Temp
qw(tempdir);
7 # TESTrun helper functions (common to all projects).
9 # TESTst.pm or TESTmt.pm
16 # The characters are inspired by PHPUnit format, but are not exactly the same.
21 CHAR_TIMED_OUT
=> 'T',
26 my $max_result_digits;
27 my $max_results_per_line;
28 my $flush_after_newline;
34 # No File::Temp->newdir() in Perl 5.8.4.
43 return sprintf '%s/%s-%s', $tmpdir, my_tmp_id
, shift;
48 if (! defined $ENV{TESTRUN_JOBS
}) {
50 } elsif ($ENV{TESTRUN_JOBS
} =~ /^\d+\z/) {
51 $njobs = int ($ENV{TESTRUN_JOBS
});
55 die "ERROR: '$ENV{TESTRUN_JOBS}' is not a valid value for TESTRUN_JOBS" if ! $njobs;
60 return defined $ENV{DIFF_FLAGS
} ?
$ENV{DIFF_FLAGS
} :
61 $^O
eq 'hpux' ?
'-c' :
65 # Parse config.h into a hash for later use.
69 my $re_define_uint = qr/^#define ([0-9_A-Z]+) ([0-9]+)$/;
70 my $re_define_str = qr/^#define ([0-9_A-Z]+) "(.+)"$/;
71 open (my $fh, '<', $config_h) || die "failed opening '$config_h'";
73 $config{$1} = $2 if /$re_define_uint/o || /$re_define_str/o;
75 close ($fh) || die "failed closing '$config_h'";
78 # This is a simpler version of the PHP function.
79 sub file_put_contents
{
80 my ($filename, $contents) = @_;
81 open (my $fh, '>', $filename) || die "failed opening '$filename'";
83 close ($fh) || die "failed closing '$filename'";
87 sub file_get_contents
{
89 open (my $fh, '<', $filename) || die "failed opening '$filename'";
91 $ret .= $_ while (<$fh>);
92 close ($fh) || die "failed closing '$filename'";
97 my ($string, $filename) = @_;
99 open (my $fh, '<', $filename) || die "failed opening '$filename'";
101 if (-1 != index $_, $string) {
106 close ($fh) || die "failed closing '$filename'";
112 return $^O
eq $name ?
"is $name" : '';
117 return $^O
ne $name ?
"is not $name" : '';
120 sub skip_config_def1
{
122 return (defined $config{$symbol} && $config{$symbol} eq '1') ?
126 sub skip_config_undef
{
128 return (! defined $config{$symbol} || $config{$symbol} ne '1') ?
132 sub skip_config_have_decl
{
133 my ($name, $value) = @_;
134 $name = 'HAVE_DECL_' . $name;
135 # "Unlike the other ‘AC_CHECK_*S’ macros, when a symbol is not declared,
136 # HAVE_DECL_symbol is defined to ‘0’ instead of leaving HAVE_DECL_symbol
137 # undeclared." -- GNU Autoconf manual.
139 # (This requires the CMake leg to do the same for the same symbol.)
140 die "no $name in config.h" unless defined $config{$name};
141 return int ($config{$name}) == $value ?
"$name==$value" : '';
146 char
=> CHAR_SKIPPED
,
152 return {char
=> CHAR_PASSED
};
165 sub result_timed_out
{
167 char
=> CHAR_TIMED_OUT
,
168 failure
=> {reason
=> shift}
174 return result_skipped
$test->{skip
};
177 # <------------------------- $maxcols -------------------------->
178 # ............................................ 0000 / 0000 (000%)
179 # $max_result_digits >----< >----<
180 # <--------- $max_results_per_line ---------->
181 sub init_results_processing
{
183 $results_to_print = shift;
184 if ($Config{useithreads
}) {
185 # When using threads, STDOUT becomes line-buffered on TTYs, which is
186 # not good for interactive progress monitoring.
187 STDOUT
->autoflush (1) if -t STDOUT
;
188 $flush_after_newline = ! -t STDOUT
;
190 $results_printed = 0;
191 $max_result_digits = 1 + int (log ($results_to_print) / log (10));
192 $max_results_per_line = $maxcols - 11 - 2 * $max_result_digits;
195 # Produce a results map in PHPUnit output format.
196 sub print_result_char
{
198 if (++$results_printed > $results_to_print) {
199 die "Internal error: unexpected results after 100%!";
201 my $results_dangling = $results_printed % $max_results_per_line;
202 if ($results_dangling) {
203 return if $results_printed < $results_to_print;
204 # Complete the dangling line to keep the progress column aligned.
205 print ' ' for (1 .. $max_results_per_line - $results_dangling);
207 printf " %*u / %*u (%3u%%)\n",
212 100 * $results_printed / $results_to_print;
213 # When using threads, STDOUT becomes block-buffered on pipes, which is
214 # not good for CI progress monitoring.
215 STDOUT
->flush if $flush_after_newline;
219 printf " %-40s: %s\n", @_;
222 sub test_and_report
{
224 start_tests
(@tests);
225 init_results_processing
scalar @tests;
227 # key: test label, value: reason for skipping
229 # key: test label, value: hash of
230 # * reason (mandatory, string)
231 # * details (optional, [multi-line] string)
235 # Ordering of the results is the same as ordering of the tests. Print the
236 # results map immediately and buffer any skipped/failed test details for the
237 # post-map diagnostics.
238 while (defined (my $result = get_next_result
)) {
239 print_result_char
($result->{char
});
240 if (defined $result->{skip
}) {
241 $skipped{$result->{label
}} = $result->{skip
};
242 } elsif (defined $result->{failure
}) {
243 $failed{$result->{label
}} = $result->{failure
};
251 print "Skipped tests:\n";
252 print_result
$_, $skipped{$_} foreach (sort keys %skipped);
257 print "Failed tests:\n";
258 foreach (sort keys %failed) {
259 print_result
$_, $failed{$_}{reason
};
260 print $failed{$_}{details
} if defined $failed{$_}{details
};
265 # scalar (%hash) returns incorrect value on Perl 5.8.4.
266 my $skippedcount = scalar keys %skipped;
267 my $failedcount = scalar keys %failed;
268 print "------------------------------------------------\n";
269 printf "%4u tests skipped\n", $skippedcount;
270 printf "%4u tests failed\n", $failedcount;
271 printf "%4u tests passed\n", $passedcount;
273 if ($skippedcount + $failedcount + $passedcount != $results_to_print) {
274 printf STDERR
"Internal error: statistics bug (%u + %u + %u != %u)\n",