Annotation of mandoc/regress/regress.pl, Revision 1.1
1.1 ! schwarze 1: #!/usr/bin/env perl
! 2: #
! 3: # $Id$
! 4: #
! 5: # Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
! 6: #
! 7: # Permission to use, copy, modify, and distribute this software for any
! 8: # purpose with or without fee is hereby granted, provided that the above
! 9: # copyright notice and this permission notice appear in all copies.
! 10: #
! 11: # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 16: # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 17: # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18:
! 19: use warnings;
! 20: use strict;
! 21:
! 22: # Used because open(3p) and open2(3p) provide no way for handling
! 23: # STDERR of the child process, neither for appending it to STDOUT,
! 24: # nor for piping it into the Perl program.
! 25: use IPC::Open3 qw(open3);
! 26:
! 27: # --- utility functions ------------------------------------------------
! 28:
! 29: sub usage ($) {
! 30: warn shift;
! 31: print STDERR "usage: $0 [directory[:test] [modifier ...]]\n";
! 32: exit 1;
! 33: }
! 34:
! 35: # Run a command and send STDOUT and STDERR to a file.
! 36: # 1st argument: path to the output file
! 37: # 2nd argument: command name
! 38: # The remaining arguments are passed to the command.
! 39: sub sysout ($@) {
! 40: my $outfile = shift;
! 41: local *OUT_FH;
! 42: open OUT_FH, '>', $outfile or die "$outfile: $!";
! 43: my $pid = open3 undef, ">&OUT_FH", undef, @_;
! 44: close OUT_FH;
! 45: waitpid $pid, 0;
! 46: return $? >> 8;
! 47: }
! 48:
! 49: # Simlar, but filter the output as needed for the lint test.
! 50: sub syslint ($@) {
! 51: my $outfile = shift;
! 52: open my $outfd, '>', $outfile or die "$outfile: $!";
! 53: my $infd;
! 54: my $pid = open3 undef, $infd, undef, @_;
! 55: while (<$infd>) {
! 56: s/^mandoc: [^:]+\//mandoc: /;
! 57: print $outfd $_;
! 58: }
! 59: close $outfd;
! 60: close $infd;
! 61: waitpid $pid, 0;
! 62: return 0;
! 63: }
! 64:
! 65: # Simlar, but filter the output as needed for the html test.
! 66: sub syshtml ($@) {
! 67: my $outfile = shift;
! 68: open my $outfd, '>', $outfile or die "$outfile: $!";
! 69: my $infd;
! 70: my $pid = open3 undef, $infd, undef, @_;
! 71: my $state;
! 72: while (<$infd>) {
! 73: chomp;
! 74: if (!$state && s/.*<math class="eqn">//) {
! 75: $state = 1;
! 76: next unless length;
! 77: }
! 78: $state = 1 if /^BEGINTEST/;
! 79: if ($state && s/<\/math>.*//) {
! 80: s/^ *//;
! 81: print $outfd "$_\n" if length;
! 82: undef $state;
! 83: next;
! 84: }
! 85: s/^ *//;
! 86: print $outfd "$_\n" if $state;
! 87: undef $state if /^ENDTEST/;
! 88: }
! 89: close $outfd;
! 90: close $infd;
! 91: waitpid $pid, 0;
! 92: return 0;
! 93: }
! 94:
! 95: my @failures;
! 96: sub fail ($$$) {
! 97: warn "FAILED: @_\n";
! 98: push @failures, [@_];
! 99: }
! 100:
! 101:
! 102: # --- process command line arguments -----------------------------------
! 103:
! 104: my ($subdir, $onlytest) = split ':', (shift // '.');
! 105: my $displaylevel = 2;
! 106: my %targets;
! 107: for (@ARGV) {
! 108: if (/^[0123]$/) {
! 109: $displaylevel = int;
! 110: next;
! 111: }
! 112: /^(all|ascii|utf8|man|html|lint|clean|verbose)$/
! 113: or usage "$_: invalid modifier";
! 114: $targets{$_} = 1;
! 115: }
! 116: $targets{all} = 1
! 117: unless $targets{ascii} || $targets{utf8} || $targets{man} ||
! 118: $targets{html} || $targets{lint} || $targets{clean};
! 119: $targets{ascii} = $targets{utf8} = $targets{man} = $targets{html} =
! 120: $targets{lint} = 1 if $targets{all};
! 121: $displaylevel = 3 if $targets{verbose};
! 122:
! 123:
! 124: # --- parse Makefiles --------------------------------------------------
! 125:
! 126: my %vars = (MOPTS => '');
! 127: sub parse_makefile ($) {
! 128: my $filename = shift;
! 129: open my $fh, '<', $filename or die "$filename: $!";
! 130: while (<$fh>) {
! 131: chomp;
! 132: next unless /\S/;
! 133: last if /^# OpenBSD only/;
! 134: next if /^#/;
! 135: next if /^\.include/;
! 136: /^(\w+)\s*([?+]?)=\s*(.*)/
! 137: or die "$filename: parse error: $_";
! 138: my $var = $1;
! 139: my $opt = $2;
! 140: my $val = $3;
! 141: $val =~ s/\${(\w+)}/$vars{$1}/;
! 142: $val = "$vars{$var} $val" if $opt eq '+';
! 143: $vars{$var} = $val
! 144: unless $opt eq '?' && defined $vars{$var};
! 145: }
! 146: close $fh;
! 147: }
! 148:
! 149: if ($subdir eq '.') {
! 150: $vars{SUBDIR} = 'roff char mdoc man tbl eqn';
! 151: } else {
! 152: parse_makefile "$subdir/Makefile";
! 153: parse_makefile "$subdir/../Makefile.inc"
! 154: if -e "$subdir/../Makefile.inc";
! 155: }
! 156:
! 157: my @mandoc = '../mandoc';
! 158: my @subdir_names;
! 159: my (@regress_testnames, @utf8_testnames, @html_testnames, @lint_testnames);
! 160: my (%skip_ascii, %skip_man);
! 161:
! 162: push @mandoc, split ' ', $vars{MOPTS} if $vars{MOPTS};
! 163: delete $vars{MOPTS};
! 164: delete $vars{SKIP_GROFF};
! 165: delete $vars{SKIP_GROFF_ASCII};
! 166: delete $vars{TBL};
! 167: delete $vars{EQN};
! 168: if (defined $vars{SUBDIR}) {
! 169: @subdir_names = split ' ', $vars{SUBDIR};
! 170: delete $vars{SUBDIR};
! 171: }
! 172: if (defined $vars{REGRESS_TARGETS}) {
! 173: @regress_testnames = split ' ', $vars{REGRESS_TARGETS};
! 174: delete $vars{REGRESS_TARGETS};
! 175: }
! 176: if (defined $vars{UTF8_TARGETS}) {
! 177: @utf8_testnames = split ' ', $vars{UTF8_TARGETS};
! 178: delete $vars{UTF8_TARGETS};
! 179: }
! 180: if (defined $vars{HTML_TARGETS}) {
! 181: @html_testnames = split ' ', $vars{HTML_TARGETS};
! 182: delete $vars{HTML_TARGETS};
! 183: }
! 184: if (defined $vars{LINT_TARGETS}) {
! 185: @lint_testnames = split ' ', $vars{LINT_TARGETS};
! 186: delete $vars{LINT_TARGETS};
! 187: }
! 188: if (defined $vars{SKIP_ASCII}) {
! 189: for (split ' ', $vars{SKIP_ASCII}) {
! 190: $skip_ascii{$_} = 1;
! 191: $skip_man{$_} = 1;
! 192: }
! 193: delete $vars{SKIP_ASCII};
! 194: }
! 195: if (defined $vars{SKIP_TMAN}) {
! 196: $skip_man{$_} = 1 for split ' ', $vars{SKIP_TMAN};
! 197: delete $vars{SKIP_TMAN};
! 198: }
! 199: if (keys %vars) {
! 200: my @vars = keys %vars;
! 201: die "unknown var(s) @vars";
! 202: }
! 203: map { $skip_ascii{$_} = 1; } @regress_testnames if $skip_ascii{ALL};
! 204: map { $skip_man{$_} = 1; } @regress_testnames if $skip_man{ALL};
! 205:
! 206: # --- run targets ------------------------------------------------------
! 207:
! 208: my $count_total = 0;
! 209: for my $dirname (@subdir_names) {
! 210: $count_total++;
! 211: print "\n" if $targets{verbose};
! 212: system './regress.pl', "$subdir/$dirname", keys %targets,
! 213: ($displaylevel ? $displaylevel - 1 : 0),
! 214: and fail $subdir, $dirname, 'subdir';
! 215: }
! 216:
! 217: my $count_ascii = 0;
! 218: my $count_man = 0;
! 219: for my $testname (@regress_testnames) {
! 220: next if $onlytest && $testname ne $onlytest;
! 221: my $i = "$subdir/$testname.in";
! 222: my $o = "$subdir/$testname.mandoc_ascii";
! 223: my $w = "$subdir/$testname.out_ascii";
! 224: if ($targets{ascii} && !$skip_ascii{$testname}) {
! 225: $count_ascii++;
! 226: $count_total++;
! 227: print "@mandoc -T ascii $i\n" if $targets{verbose};
! 228: sysout $o, @mandoc, qw(-T ascii), $i
! 229: and fail $subdir, $testname, 'ascii:mandoc';
! 230: system qw(diff -au), $w, $o
! 231: and fail $subdir, $testname, 'ascii:diff';
! 232: }
! 233: my $m = "$subdir/$testname.in_man";
! 234: my $mo = "$subdir/$testname.mandoc_man";
! 235: if ($targets{man} && !$skip_man{$testname}) {
! 236: $count_man++;
! 237: $count_total++;
! 238: print "@mandoc -T man $i\n" if $targets{verbose};
! 239: sysout $m, @mandoc, qw(-T man), $i
! 240: and fail $subdir, $testname, 'man:man';
! 241: print "@mandoc -man -T ascii $m\n" if $targets{verbose};
! 242: sysout $mo, @mandoc, qw(-man -T ascii -O mdoc), $m
! 243: and fail $subdir, $testname, 'man:mandoc';
! 244: system qw(diff -au), $w, $mo
! 245: and fail $subdir, $testname, 'man:diff';
! 246: }
! 247: if ($targets{clean}) {
! 248: print "rm $o\n"
! 249: if $targets{verbose} && !$skip_ascii{$testname};
! 250: unlink $o;
! 251: print "rm $m $mo\n"
! 252: if $targets{verbose} && !$skip_man{$testname};
! 253: unlink $m, $mo;
! 254: }
! 255: }
! 256:
! 257: my $count_utf8 = 0;
! 258: for my $testname (@utf8_testnames) {
! 259: next if $onlytest && $testname ne $onlytest;
! 260: my $i = "$subdir/$testname.in";
! 261: my $o = "$subdir/$testname.mandoc_utf8";
! 262: my $w = "$subdir/$testname.out_utf8";
! 263: if ($targets{utf8}) {
! 264: $count_utf8++;
! 265: $count_total++;
! 266: print "@mandoc -T utf8 $i\n" if $targets{verbose};
! 267: sysout $o, @mandoc, qw(-T utf8), $i
! 268: and fail $subdir, $testname, 'utf8:mandoc';
! 269: system qw(diff -au), $w, $o
! 270: and fail $subdir, $testname, 'utf8:diff';
! 271: }
! 272: if ($targets{clean}) {
! 273: print "rm $o\n" if $targets{verbose};
! 274: unlink $o;
! 275: }
! 276: }
! 277:
! 278: my $count_html = 0;
! 279: for my $testname (@html_testnames) {
! 280: next if $onlytest && $testname ne $onlytest;
! 281: my $i = "$subdir/$testname.in";
! 282: my $o = "$subdir/$testname.mandoc_html";
! 283: my $w = "$subdir/$testname.out_html";
! 284: if ($targets{html}) {
! 285: $count_html++;
! 286: $count_total++;
! 287: print "@mandoc -T html $i\n" if $targets{verbose};
! 288: syshtml $o, @mandoc, qw(-T html), $i
! 289: and fail $subdir, $testname, 'html:mandoc';
! 290: system qw(diff -au), $w, $o
! 291: and fail $subdir, $testname, 'html:diff';
! 292: }
! 293: if ($targets{clean}) {
! 294: print "rm $o\n" if $targets{verbose};
! 295: unlink $o;
! 296: }
! 297: }
! 298:
! 299: my $count_lint = 0;
! 300: for my $testname (@lint_testnames) {
! 301: next if $onlytest && $testname ne $onlytest;
! 302: my $i = "$subdir/$testname.in";
! 303: my $o = "$subdir/$testname.mandoc_lint";
! 304: my $w = "$subdir/$testname.out_lint";
! 305: if ($targets{lint}) {
! 306: $count_lint++;
! 307: $count_total++;
! 308: print "@mandoc -T lint $i\n" if $targets{verbose};
! 309: syslint $o, @mandoc, qw(-T lint), $i
! 310: and fail $subdir, $testname, 'lint:mandoc';
! 311: system qw(diff -au), $w, $o
! 312: and fail $subdir, $testname, 'lint:diff';
! 313: }
! 314: if ($targets{clean}) {
! 315: print "rm $o\n" if $targets{verbose};
! 316: unlink $o;
! 317: }
! 318: }
! 319:
! 320: exit 0 unless $displaylevel or @failures;
! 321:
! 322: print "\n" if $targets{verbose};
! 323: if ($onlytest) {
! 324: print "test $subdir:$onlytest finished";
! 325: } else {
! 326: print "testsuite $subdir finished";
! 327: }
! 328: print ' ', (scalar @subdir_names), ' subdirectories' if @subdir_names;
! 329: print " $count_ascii ascii" if $count_ascii;
! 330: print " $count_man man" if $count_man;
! 331: print " $count_utf8 utf8" if $count_utf8;
! 332: print " $count_html html" if $count_html;
! 333: print " $count_lint lint" if $count_lint;
! 334:
! 335: if (@failures) {
! 336: print " (FAIL)\n\nSOME TESTS FAILED:\n\n";
! 337: print "@$_\n" for @failures;
! 338: print "\n";
! 339: exit 1;
! 340: } elsif ($count_total == 1) {
! 341: print " (OK)\n";
! 342: } elsif ($count_total) {
! 343: print " (all $count_total tests OK)\n";
! 344: } else {
! 345: print " (no tests run)\n";
! 346: }
! 347: exit 0;
CVSweb