mirror of
https://github.com/git/git.git
synced 2024-11-23 18:05:29 +08:00
03763e68fb
While working on chainlint.pl recently, we introduced some bugs that showed incorrect line numbers in the output. But it was hard to notice, since we sanitize the output by removing all of the line numbers! It would be nice to retain these so we can catch any regressions. The main reason we sanitize is for maintainability: we concatenate all of the test snippets into a single file, so it's hard for each ".expect" file to know at which offset its test input will be found. We can handle that by storing the per-test line numbers in the ".expect" files, and then dynamically offsetting them as we build the concatenated test and expect files together. The changes to the ".expect" files look like tedious boilerplate, but it actually makes adding new tests easier. You can now just run: perl chainlint.pl chainlint/foo.test | tail -n +2 >chainlint/foo.expect to save the output of the script minus the comment headers (after checking that it is correct, of course). Whereas before you had to strip the line numbers. The conversions here were done mechanically using something like the script above, and then spot-checked manually. It would be possible to do all of this in shell via the Makefile, but it gets a bit complicated (and requires a lot of extra processes). Instead, I've written a short perl script that generates the concatenated files (we already depend on perl, since chainlint.pl uses it). Incidentally, this improves a few other things: - we incorrectly used $(CHAINLINTTMP_SQ) inside a double-quoted string. So if your test directory required quoting, like: make "TEST_OUTPUT_DIRECTORY=/tmp/h'orrible" we'd fail the chainlint tests. - the shell in the Makefile didn't handle &&-chaining correctly in its loops (though in practice the "sed" and "cat" invocations are not likely to fail). - likewise, the sed invocation to strip numbers was hiding the exit code of chainlint.pl itself. In practice this isn't a big deal; since there are linter violations in the test files, we expect it to exit non-zero. But we could later use exit codes to distinguish serious errors from expected ones. - we now use a constant number of processes, instead of scaling with the number of test scripts. So it should be a little faster (on my machine, "make check-chainlint" goes from 133ms to 73ms). There are some alternatives to this approach, but I think this is still a good intermediate step: 1. We could invoke chainlint.pl individually on each test file, and compare it to the expected output (and possibly using "make" to avoid repeating already-done checks). This is a much bigger change (and we'd have to figure out what to do with the "# LINT" lines in the inputs). But in this case we'd still want the "expect" files to be annotated with line numbers. So most of what's in this patch would be needed anyway. 2. Likewise, we could run a single chainlint.pl and feed it all of the scripts (with "--jobs=1" to get deterministic output). But we'd still need to annotate the scripts as we did here, and we'd still need to either assemble the "expect" file, or break apart the script output to compare to each individual ".expect" file. So we may pursue those in the long run, but this patch gives us more robust tests without too much extra work or moving in a useless direction. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
30 lines
709 B
Perl
30 lines
709 B
Perl
#!/usr/bin/env perl
|
|
|
|
my $outdir = shift;
|
|
open(my $tests, '>', "$outdir/tests")
|
|
or die "unable to open $outdir/tests: $!";
|
|
open(my $expect, '>', "$outdir/expect")
|
|
or die "unable to open $outdir/expect: $!";
|
|
|
|
print $expect "# chainlint: $outdir/tests\n";
|
|
|
|
my $offset = 0;
|
|
for my $script (@ARGV) {
|
|
print $expect "# chainlint: $script\n";
|
|
|
|
open(my $expect_in, '<', "chainlint/$script.expect")
|
|
or die "unable to open chainlint/$script.expect: $!";
|
|
while (<$expect_in>) {
|
|
s/^\d+/$& + $offset/e;
|
|
print $expect $_;
|
|
}
|
|
|
|
open(my $test_in, '<', "chainlint/$script.test")
|
|
or die "unable to open chainlint/$script.test: $!";
|
|
while (<$test_in>) {
|
|
/^# LINT: / and next;
|
|
print $tests $_;
|
|
$offset++;
|
|
}
|
|
}
|