]>
The Tcpdump Group git mirrors - libpcap/blob - testprogs/TESTlib.pm
1 require 5.8.4; # Solaris 10
3 use warnings FATAL
=> qw(uninitialized);
5 use File
::Temp
qw(tempdir);
6 use List
::Util
qw(min max sum);
8 # TESTrun helper functions (common to all projects).
10 # TESTst.pm or TESTmt.pm
17 # The characters are inspired by PHPUnit format, but are not exactly the same.
22 CHAR_TIMED_OUT
=> 'T',
28 dragonfly
=> 'DragonFly BSD',
37 solaris
=> 'illumos/Solaris',
42 my $max_result_digits;
43 my $max_results_per_line;
44 my $flush_after_newline;
50 # No File::Temp->newdir() in Perl 5.8.4.
59 return sprintf '%s/%s-%s', $tmpdir, my_tmp_id
, shift;
64 if (! defined $ENV{TESTRUN_JOBS
}) {
66 } elsif ($ENV{TESTRUN_JOBS
} =~ /^\d+\z/) {
67 $njobs = int ($ENV{TESTRUN_JOBS
});
71 die "ERROR: '$ENV{TESTRUN_JOBS}' is not a valid value for TESTRUN_JOBS" if ! $njobs;
76 return defined $ENV{DIFF_FLAGS
} ?
$ENV{DIFF_FLAGS
} :
77 $^O
eq 'hpux' ?
'-c' :
81 # Parse config.h into a hash for later use.
85 open FH
, '<', $config_h or die "failed opening '$config_h'";
87 $config{$1} = $2 if /^
89 [[:blank
:]]+([0-9_A
-Z
]+)
90 [[:blank
:]]+([0-9]+|".*")
93 close FH
or die "failed closing '$config_h'";
97 # This is a simpler version of the PHP function.
98 sub file_put_contents
{
99 my ($filename, $contents) = @_;
100 open FH
, '>', $filename or die "failed opening '$filename'";
102 close FH
or die "failed closing '$filename'";
106 sub file_get_contents
{
107 my $filename = shift;
108 open FH
, '<', $filename or die "failed opening '$filename'";
110 $ret .= $_ while (<FH
>);
111 close FH
or die "failed closing '$filename'";
116 my ($string, $filename) = @_;
118 open FH
, '<', $filename or die "failed opening '$filename'";
120 if (-1 != index $_, $string) {
125 close FH
or die "failed closing '$filename'";
131 my $bettername = $osnames{$name} || $name;
132 return $^O
eq $name ?
"is $bettername" : '';
137 my $bettername = $osnames{$name} || $name;
138 return $^O
ne $name ?
"is not $bettername" : '';
141 sub skip_config_def1
{
143 return (defined $config{$symbol} && $config{$symbol} eq '1') ?
147 sub skip_config_undef
{
149 return (! defined $config{$symbol} || $config{$symbol} ne '1') ?
153 sub skip_config_have_decl
{
154 my ($name, $value) = @_;
155 $name = 'HAVE_DECL_' . $name;
156 # "Unlike the other ‘AC_CHECK_*S’ macros, when a symbol is not declared,
157 # HAVE_DECL_symbol is defined to ‘0’ instead of leaving HAVE_DECL_symbol
158 # undeclared." -- GNU Autoconf manual.
160 # (This requires the CMake leg to do the same for the same symbol.)
161 die "no $name in config.h" unless defined $config{$name};
162 return int ($config{$name}) == $value ?
"$name==$value" : '';
167 char
=> CHAR_SKIPPED
,
189 sub result_timed_out
{
191 char
=> CHAR_TIMED_OUT
,
192 failure
=> {reason
=> shift}
198 return result_skipped
$test->{skip
};
201 # <------------------------- $maxcols -------------------------->
202 # ............................................ 0000 / 0000 (000%)
203 # $max_result_digits >----< >----<
204 # <--------- $max_results_per_line ---------->
205 sub init_results_processing
{
207 $results_to_print = shift;
208 if ($Config{useithreads
}) {
209 # When using threads, STDOUT becomes line-buffered on TTYs, which is
210 # not good for interactive progress monitoring.
211 STDOUT
->autoflush (1) if -t STDOUT
;
212 $flush_after_newline = ! -t STDOUT
;
214 $results_printed = 0;
215 $max_result_digits = 1 + int (log ($results_to_print) / log (10));
216 $max_results_per_line = $maxcols - 11 - 2 * $max_result_digits;
219 # Produce a results map in PHPUnit output format.
220 sub print_result_char
{
222 if (++$results_printed > $results_to_print) {
223 die "Internal error: unexpected results after 100%!";
225 my $results_dangling = $results_printed % $max_results_per_line;
226 if ($results_dangling) {
227 return if $results_printed < $results_to_print;
228 # Complete the dangling line to keep the progress column aligned.
229 print ' ' x
($max_results_per_line - $results_dangling);
231 printf " %*u / %*u (%3u%%)\n",
236 100 * $results_printed / $results_to_print;
237 # When using threads, STDOUT becomes block-buffered on pipes, which is
238 # not good for CI progress monitoring.
239 STDOUT
->flush if $flush_after_newline;
243 printf " %-40s: %s\n", @_;
246 sub test_and_report
{
251 my $label = $_->{label
};
252 die "ERROR: Duplicate test label '$label'" if exists $seen_labels{$label};
253 $seen_labels{$label} = 1;
257 start_tests
(@tests);
258 init_results_processing
scalar @tests;
260 # key: test label, value: reason for skipping
262 # key: test label, value: hash of
263 # * reason (mandatory, string)
264 # * details (optional, [multi-line] string)
267 my %passed; # May stay empty even if $passedcount > 0.
269 printf "INFO: %s = skipped, %s = passed, %s = failed, %s = timed out\n",
270 CHAR_SKIPPED
, CHAR_PASSED
, CHAR_FAILED
, CHAR_TIMED_OUT
;
272 # Ordering of the results is the same as ordering of the tests. Print the
273 # results map immediately and buffer any skipped/failed test details for the
274 # post-map diagnostics.
275 while (defined (my $result = get_next_result
)) {
276 print_result_char
($result->{char
});
277 if (defined $result->{skip
}) {
278 $skipped{$result->{label
}} = $result->{skip
};
279 } elsif (defined $result->{failure
}) {
280 $failed{$result->{label
}} = $result->{failure
};
283 $passed{$result->{label
}} = $result->{T
} if defined $result->{T
};
289 print "Passed tests:\n";
290 print_result
$_, sprintf ('T=%.06fs', $passed{$_}) foreach (sort keys %passed);
294 print "Skipped tests:\n";
295 foreach (sort keys %skipped) {
296 print_result
$_, $skipped{$_} if $skipped{$_} ne '';
302 print "Failed tests:\n";
303 foreach (sort keys %failed) {
304 print_result
$_, $failed{$_}{reason
};
305 print $failed{$_}{details
} if defined $failed{$_}{details
};
310 # scalar (%hash) returns incorrect value on Perl 5.8.4.
311 my $skippedcount = scalar keys %skipped;
312 my $failedcount = scalar keys %failed;
313 print "------------------------------------------------\n";
314 printf "%4u tests skipped\n", $skippedcount;
315 printf "%4u tests failed\n", $failedcount;
316 if (! scalar keys %passed) {
317 # There isn't any test duration statistics.
318 printf "%4u tests passed\n", $passedcount;
319 } elsif ($passedcount != scalar keys %passed) {
320 die sprintf ("Internal error: statistics bug (%u != %u)",
322 scalar (keys %passed)
325 printf "%4u tests passed: T min/avg/max = %.06f/%.06f/%.06fs\n",
326 scalar (keys %passed),
327 min
(values %passed),
328 sum
(values %passed) / scalar (keys %passed),
329 max
(values %passed);
332 if ($skippedcount + $failedcount + $passedcount != $results_to_print) {
333 printf STDERR
"Internal error: statistics bug (%u + %u + %u != %u)\n",