t/regress: prepend commands to output files, cmddiff to compare
[barcat.git] / t / cmddiff
1 #!/usr/bin/env perl
2 use 5.012;
3 use warnings;
4
5 # run script on the first line and compare its output to remaining lines
6
7 my $regenerate = @ARGV > 1 && $ARGV[0] eq '-G' && shift;
8
9 @ARGV or die "missing input script\n";
10 !!(my $spec = readline)
11         or die "input lacks a script on the first line\n";
12
13 my $script = $spec;
14 chomp $script;
15 my $wantexit = $script =~ s/\h+[?](\d+)\z// ? $1 : 0;
16 my $wantwarn = $script !~ s/[?]\z//;
17 my $shell = $script;
18 if ($script =~ /\|/) {
19         # explicit shell wrapper to capture all warnings
20         $script =~ s/'/'\\''/g;
21         $shell = "sh -c '$shell'";
22 }
23 $shell .= ' 2>&1' if $wantwarn;
24
25 local $ENV{COLUMNS} = 40;
26 open my $cmd, '-|', $shell or do {
27         say "cannot run script `$script`: $!";
28         exit 2;
29 };
30 my @lines = readline $cmd;
31 close $cmd;
32 my $error = $? >> 8;
33
34 if ($regenerate) {
35         open my $rewrite, '>', $ARGV;
36         print {$rewrite} $_ for $spec, @lines;
37         exit;
38 }
39
40 if ($error != $wantexit) {
41         say "unexpected exit status $error for `$script`";
42         exit 2;
43 }
44
45 my @wanted = readline;
46 my $diff = 0;
47
48 while (@lines or @wanted) {
49         my $was = shift @wanted;
50         my $is  = shift @lines;
51         next if defined $was and defined $is and $was eq $is;
52         $diff++;
53         print color(32), "< ", color(0), $_ for $was // ();
54         print color(31), "> ", color(0), $_ for $is  // ();
55 }
56
57 exit($diff > 0);
58
59 sub color {
60         return "\e[@{_}m";
61 }