2 # A common SlayMakefile for executing tests
3 # It is intended to be called from two levels lower in the directory
4 # hierarchy using "slaymake -f ../../Common.smak <target>".
14 Used as the common C<Slay::Makefile> input for all the
15 C<Text::Restructured> tests. It contains all the infrastructure needed
16 for executing the python tests from docutils, while still providing
17 tailorability for tests that do not fit the framework. The tests are
18 divided into suites (e.g., C<10_parse>), each of which can have more
19 than one C<.t> file in it with its associated C<.init> directory to
20 implement multiple related tests. The customizability comes the
21 following files (relative to the C<.dir> directory created by C<gress.pm>):
27 If it exists, overrides variables for the entire suite.
31 If it exists, allows overriding for the directory and for individual
32 tests within the directory
42 Returns the dependencies in global variable C<@PRETESTS>, which is
43 initialized to the targets C<unpack> and C<find_oks>, but can be added
44 to by the custom C<Slay::Makefile> files above.
48 Checks for a python test file and, if it exists, calls the
49 C<extract_tests> script from the C<tbin> directory on it to create a
50 series of C<.rst> and C<.dom> files for testing.
54 Sets the global variable C<@OKS> to contain the list of C<.rst> files
55 in the directory with the C<.rst> extension replaced by C<.ok>.
56 Override this target if there is a different way to determine the list
57 of targets corresponding to tests.
61 Returns the global variable C<@OKS>.
65 Looks for an expect file for the C<$1> part (the part matching the
66 first C<%>) in order to determine which writer to use when calling
67 C<prest>. For writer C<xyz>, the expect file should be one of
73 The unpacked python expects all have this form.
77 Sometimes prest intentionally does not match the python output, so
78 C<$1.myxyz> is used in preference to C<$1.xyz> if both exist.
82 Sometimes a regular expression difference, using the C<rediff> script
83 in the C<tbin> directory, needs to be done for fault grading. This
84 file contains regular expressions and is used in preference to either
89 Note: There are two exceptions to the one-to-one mapping between
90 C<xyz> and the writer namely, namely C<tex> runs the C<latex> writer
91 and C<idx> runs the C<index> writer.
93 This target returns an error if no expect file for a known writer is
96 After determining which writer is appropriate, this target returns two
97 dependencies, one of which will be the output of the writer
98 (C<$1.xyz.out>), and the other of which is the file against which
99 fault grading occurs. If the expect file has extension C<.xyz.re> or
100 if there exists a file C<$1.r>, then C<rediff> is used for fault
101 grading, and the fault grading file is C<$1.xyz.re>. Otherwise,
102 C<diff> is used for fault grading and the fault grading file is
107 Copies C<$1.stderr>, if it exists, and the first of C<$1.my$2> or
108 C<$1.$2> to the target, where C<$2> is the writer. Thus, any error
109 messages printed to STDERR become part of the fault grading.
113 If there was already a C<$1.$2.re> file, this rule does nothing.
114 Otherwise, it was invoked because there was a C<$1.r> file. It passes
115 C<$1.stderr>, if it exists, and the first of C<$1.my$2> or C<$1.$2> as
116 arguments to the script C<re$2> (e.g., C<redom>), located in the
117 C<tbin> directory. The purpose of such a script is to elide with
118 regular expressions that part of the output that can validly differ.
122 Dependencies are C<$1.rst> (if it exists), the C<prest> script, and
123 the file containing the implemention of the writer C<$2>. Invokes
125 perl $PERL_FILE_FLAGS{$1} $PERL_DIR_FLAGS $PERL_SUITE_FLAGS \
126 $PERL_WRT_FLAGS{$2} $PERL_FLAGS -I <root>/blib/lib \
127 <root>/blib/script/prest -w $2 \
128 $PREST_FLAGS $PREST_WRT_FLAGS{$2} $PREST_SUITE_FLAGS \
129 $PREST_DIR_FLAGS $PREST_FILE_FLAGS{$1} [$1.rst] \
130 $POSTPROC_FILE{$1} > $target
132 If C<$3> is null, then any output to STDERR is captured in the output
133 file; otherwise the output file contains only the prest output to STDOUT.
134 If there is no C<$1.rst> file, then C<$PREST_FILE_FLAGS{$1}> should
135 contain the list of input files.
139 =head1 GLOBAL VARIABLES
141 As can be seen above, there are a number of global variables that
142 affect the processing of the prest command:
146 =item C<$PERL_DIR_FLAGS> (Dir.smak)
148 Flags for perl invocation of prest for a directory.
150 =item C<$PERL_SUITE_FLAGS> (Suite.smak)
152 Flags for perl invocation of prest for a suite.
154 =item C<%PERL_WRT_FLAGS> (Suite.smak or Perl.smak)
156 Flags for perl invocation of prest for specific writers (indexed by
159 =item C<%PERL_FILE_FLAGS> (Dir.smak)
161 Flags for perl invocation of prest for specific files (indexed by base
164 =item C<$PREST_DIR_FLAGS> (Dir.smak)
166 Writer- and file-independent flags for prest for a directory.
168 =item C<$PREST_FLAGS> (Suite.smak or Dir.smak)
170 Writer- and file-independent flags for prest. Defaults to
172 -D source='test data' -D xformoff='.*' -D align=0
176 =item C<$PREST_SUITE_FLAGS> (Suite.smak)
178 Writer- and file-independent flags for prest for a suite.
180 =item C<%PREST_WRT_FLAGS> (Suite.smak or Dir.smak)
182 Flags for specific writers (indexed by writer). C<$PREST_WRT_FLAGS{dom}>
183 defaults to "-W nobackn" unless already set.
185 =item C<%PREST_FILE_FLAGS> (Dir.smak)
187 Flags for specific files (indexed by base filename).
189 =item C<%POSTPROC_FILE> (Dir.smak)
191 Text for postprocessing output before check for specific files
192 (indexed by base filename). Usually starts with "|".
196 =head1 ENVIRONMENT VARIABLES
202 If set, runs perl with flags to create a coverage database using
207 If set, runs perl with the C<-d> flag (debug mode).
211 If set, echoes to STDERR the commands to be executed, but does not
212 actually execute them.
216 If set, echoes to STDERR the commands as they execute.
227 use vars qw(@OKS @PRETESTS);
228 # Flags that can be set in Suite.smak and Dir.smak:
229 # $EXTRACT_TEST_FLAGS Flags for extract_tests script
230 # $PERL_DIR_FLAGS Flags for perl invocation of prest for a directory
231 # $PERL_SUITE_FLAGS Flags for perl invocation of prest for a suite
232 # %PERL_WRT_FLAGS Flags for perl invocation of prest for specific
233 # writers (indexed by writer)
234 # %PERL_FILE_FLAGS Flags for perl infocation of prest for specific
235 # files (indexed by base filename)
236 # $PREST_DIR_FLAGS Generic flags for prest for a directory
237 # $PREST_FLAGS Generic flags for prest
238 # $PREST_SUITE_FLAGS Generic flags for prest for a suite
239 # %PREST_WRT_FLAGS Flags for specific writers (indexed by writer)
240 # %PREST_FILE_FLAGS Flags for specific files (indexed by base filename)
241 # %POSTPROC_FILE Text for postprocessing output before check for
242 # specific files (indexed by base filename). Usually
245 use vars qw(%EXT_TO_WRT $EXTRACT_TEST_FLAGS $PREST_FLAGS
246 $PERL_DIR_FLAGS $PERL_SUITE_FLAGS %PERL_WRT_FLAGS
249 $PREST_DIR_FLAGS $PREST_SUITE_FLAGS %PREST_WRT_FLAGS
252 %EXT_TO_WRT = (tex => 'latex', idx => 'index');
253 $EXTRACT_TEST_FLAGS = '';
254 @PRETESTS = qw(unpack find_oks);
255 # Executes a command line while possibly echoing it to the screen
258 print STDERR "\t$cmd\n" if $ENV{TRACE} || $ENV{PRINT};
259 system $cmd unless $ENV{PRINT};
264 # Include the suite's SlayMakefile if it exists
265 -include ../Suite.smak
267 # Include the directory's SlayMakefile if it exists
272 pretest: { @PRETESTS }
275 # Set up our make variables
277 use vars qw($EXTRACT_TESTS $LIB $PERL $PERL_FLAGS $SCRIPT $TBIN $TOP
280 # Find our top directory
281 chomp ($TOP = `pwd`);
284 $SCRIPT = "$TOP/blib/script";
285 $LIB = "$TOP/blib/lib";
286 $EXTRACT_TESTS = "$TBIN/extract_tests";
288 # Get list of writers
289 my ($dir, @writers, %writer_seen);
290 foreach $dir (@INC) {
291 push @writers, glob("$dir/Text/Restructured/Writer/*.wrt")
293 @WRITERS = grep(! $writer_seen{$_}++,
294 grep(s|.*/([^/]+)\.wrt$|$1|, @writers));
295 eval "use lib \$LIB; use Text::Restructured::PrestConfig;";
297 push @flags, '-T' if $Text::Restructured::PrestConfig::TAINT =~ /^y/i;
298 push @flags, '-d' if $ENV{DEBUG};
299 push @flags, '-MDevel::Cover=-db,../../cover_db,-silent,1,-summary,0'
301 push @flags, q(-M-warnings) if $ENV{COVER};
302 $PERL_FLAGS = "@flags";
303 # Default version of PREST_FLAGS
304 $PREST_FLAGS = q(-D source='test data' -D xformoff='.*' -D align=0)
305 unless defined $PREST_FLAGS;
306 $PREST_FLAGS .= q( -D no_line_directives) if $ENV{DEBUG};
307 # Default version of PREST_WRT_FLAGS for dom
308 $PREST_WRT_FLAGS{dom} = '-W nobackn' unless defined $PREST_WRT_FLAGS{dom};
311 # Unpack the .py file if it exists
314 my @test_pys = <test_*.py>;
315 foreach (@test_pys) {
316 execute "$PERL $EXTRACT_TESTS $EXTRACT_TEST_FLAGS $_";
323 s/\.rst$/.ok/ foreach @OKS;
326 # Fault grading. This is complicated because we can do either diff or
327 # rediff for checking and we can build the targets in a number of ways,
328 # depending upon which writer needs to be used, which depends upon
329 # what kinds of expects we have
331 my($maker, $target, $matches) = @_;
332 my $m = $matches->[0];
333 # Search for .xyz or .myxyz or .xyzre files for each of
334 # the different writers xyz
335 my @writers = grep(-f "$m.$_" || -f "$m.my$_" ||
337 (@WRITERS, qw(tex idx txt)));
338 my $writer = $writers[0];
339 die "Cannot find expect file for $m" unless defined $writer;
340 my $ext = -f "$m.r" || -f "$m.$writer.re" ? 're' : 'df';
341 ("$m.$writer.$ext", "$m.$writer.out");
345 my($maker, $target, $deps, $matches) = @_;
346 my $prog = $deps->[0] =~ /\.df/ ? 'diff' : "$PERL $TBIN/diffre";
347 execute "$prog @$deps[0..1] > $target";
350 # Make a straight diff file
352 my($maker, $target, $matches) = @_;
353 my @exp = grep(-f $_, "$matches->[0].my$matches->[1]",
354 "$matches->[0].$matches->[1]");
356 push @files, "$matches->[0].stderr" if -f "$matches->[0].stderr";
357 push @files, $exp[0];
361 cat $DEP0 $DEP1 > $TARGET
363 # Make a regular expression diff file
365 my($maker, $target, $matches) = @_;
366 my @exp = grep(-f $_, "$matches->[0].my$matches->[1]",
367 "$matches->[0].$matches->[1]");
369 push @files, "$matches->[0].stderr" if -f "$matches->[0].stderr";
370 push @files, $exp[0] if $exp[0];
375 my($maker, $target, $deps, $matches) = @_;
376 my $dep = $deps->[-1];
377 $dep =~ /\. (my)? ([^\.]+?) \z/x;
379 execute "$PERL $TBIN/re$re @$deps > $target";
382 # Run prest with the appropriate writer
383 # Anything after the ".out" causes the output to be generated without STDERR.
385 # Add the prest script and the appropriate writer as dependencies
386 my($maker, $target, $matches) = @_;
387 my $writer = $EXT_TO_WRT{$matches->[1]} || $matches->[1];
389 # Make the .rst file a dependency if it exists (it usually does)
390 push @deps, "$matches->[0].rst" if -f "$matches->[0].rst";
391 # Add the prest script and perl modules to the dependencies
392 push @deps, ("$SCRIPT/prest",
393 "$LIB/Text/Restructured/Writer/$writer.wrt");
394 push @deps, (<$LIB/Text/*.pm>, <$LIB/Text/Restructured/*.pm>,
395 <$LIB/Text/Restructured/Directive/*.pm>);
400 my($maker, $target, $deps, $matches) = @_;
401 my $m0 = $matches->[0];
402 my $writer = $EXT_TO_WRT{$matches->[1]} || $matches->[1];
403 # Note: since these are usually -I flags, the local ones come first
405 grep(defined $_, $PERL_FILE_FLAGS{$m0},
406 $PERL_DIR_FLAGS, $PERL_SUITE_FLAGS,
407 $PERL_WRT_FLAGS{$writer}, $PERL_FLAGS, );
408 my $prest_cmd = "$PERL @perl_flags -I $LIB $SCRIPT/prest";
410 grep(defined $_, $PREST_FLAGS, $PREST_WRT_FLAGS{$writer},
411 $PREST_SUITE_FLAGS, $PREST_DIR_FLAGS,
412 $PREST_FILE_FLAGS{$m0});
413 push @flags, "$m0.rst" if -f "$m0.rst";
414 my $redir = $matches->[2] ? '' : '2>&1' ;
415 my $postproc = $POSTPROC_FILE{$m0} || '';
416 my $redirect = $ENV{DEBUG} ? '' : "> $target";
417 execute "$prest_cmd -w $writer @flags $redir $postproc |
418 grep -v 'Wide character'$redirect";