1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
# -*- perl -*-
use strict; use warnings;
use Test::More;
my $n_tests;
use constant DEVNULL => $^O eq 'MSWin32' ? 'NUL' : '/dev/null';
use constant REDIRECT => '>' . DEVNULL . ' 2>' . DEVNULL;
use constant Q_REDIRECT => '" ' . REDIRECT;
use constant ERR_TXT => ( 'boo', 'bah');
use constant ERRFILE => {
mine => 'my_errors',
std => 'errors.err',
};
# number of tests per call of run_tests()
use constant PER_CALL => @{ [ ERR_TXT]};
BEGIN { $n_tests += 2 * PER_CALL }
{{
my $command = qq($^X -Ilib -e");
$command .= qq(use Vi::QuickFix;);
$command .= qq( warn qq($_); print STDERR qq(# something else\\n);) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_use', 'std', $command);
$command = qq($^X -Ilib -MVi::QuickFix -e");
$command .= qq( warn qq($_);) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_switch', 'std', $command);
}}
BEGIN { $n_tests += 2 * PER_CALL }
{{
my $command = qq($^X -Ilib -MVi::QuickFix=*ERRFILE* -e");
$command .= qq(warn qq($_); ) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_switch', 'mine', $command);
$command = qq($^X -Ilib -e");
$command .= qq(use Vi::QuickFix "*ERRFILE*"; );
$command .= qq(warn qq($_); print STDERR qq(something else\\n); ) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_use', 'mine', $command);
}}
### If $] >= 5.008001, the above has tested "tie" mode, and we now
# want to check "sig" mode. If $] < 5.008001, the above has tested
# "sig" mode. Since "tie" mode can't be run, we just skip the "sig"-
# specific tests
use constant LOW_VERSION => $] < 5.008001;
use constant REASON_LOW => "already done with perl $]";
BEGIN { $n_tests += 2 * PER_CALL }
SKIP: {{
skip REASON_LOW, 2 * PER_CALL if LOW_VERSION;
my $command = qq($^X -Ilib -MVi::QuickFix=sig -e");
$command .= qq(warn qq($_); ) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_switch(sig)', 'std', $command);
$command = qq($^X -Ilib -e");
$command .= qq(use Vi::QuickFix qw( sig); );
$command .= qq(warn qq($_); print STDERR qq(# something else\\n); ) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_use(sig)', 'std', $command);
}}
BEGIN { $n_tests += 2 * PER_CALL }
SKIP: {{
skip REASON_LOW, 2 * PER_CALL if LOW_VERSION;
my $command = qq($^X -Ilib -MVi::QuickFix=sig,*ERRFILE* -e");
$command .= qq(warn qq($_); ) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_switch(sig)', 'mine', $command);
$command = qq($^X -Ilib -e");
$command .= qq(use Vi::QuickFix "sig", "*ERRFILE*"; );
$command .= qq(warn qq($_); print STDERR qq(something else\\n); ) for ERR_TXT;
$command .= Q_REDIRECT;
run_tests( 'module_use(sig)', 'mine', $command);
}}
### more non-specific tests (as to sig/warn)
# prepare input file for executable (used in two test blocks)
open my $infile, '>', 'infile' or die;
print $infile "$_ at some_file line 12.\nsomething_else\n" for ERR_TXT;
close $infile;
BEGIN { $n_tests += 2 * ( PER_CALL + 1) }
{{
my $command = qq($^X lib/Vi/QuickFix.pm infile >outfile 2>) . DEVNULL;
run_tests( 'command_file', 'std', $command);
is( -s 'outfile', -s 'infile', 'input copied to stdout');
$command = qq($^X ./lib/Vi/QuickFix.pm <infile >outfile 2>) . DEVNULL;
run_tests( 'command_stdin', 'std', $command);
is( -s 'outfile', -s 'infile', 'file copied to stdout');
}}
BEGIN { $n_tests += 2 + 2 * PER_CALL }
{{
# check -v key (version)
my $command = qq($^X lib/Vi/QuickFix.pm -v);
open my $f, "$command |";
ok( defined $f, "got a handle");
like( scalar <$f>, qr/version *\d+\.\d+/, "-v returns version");
$command = qq($^X lib/Vi/QuickFix.pm -f *ERRFILE* infile) . REDIRECT;
run_tests( 'command_file', 'mine', $command);
$command = qq($^X lib/Vi/QuickFix.pm -q *ERRFILE* <infile) . REDIRECT;
run_tests( 'command_stdin', 'mine', $command);
}}
unlink 'infile', 'outfile';
# do we catch (not catch) all types of STDERR output?
use constant CASES => (
[ runtime_warning => '() = qq(a) + 0', 'Argument "a"' ],
[ runtime_error => 'my %h = %{ \ 0 }', 'Not a HASH' ],
[ compiletime_warning => 'my @y; @y = @y[0]', 'Scalar value' ],
[ compiletime_error => '%', 'syntax error' ],
[ explicit_warning => 'warn qq(xxx)', 'xxx' ],
[ explicit_error => 'die qq(yyy)', 'yyy' ],
);
BEGIN { $n_tests += 2*@{ [ CASES]} }
{{
for ( CASES ) {
my ( $case, $prog, $msg) = @$_;
unlink 'errors.err';
my $cmd = qq($^X -Ilib -MVi::QuickFix -we "$prog" ) . REDIRECT;
system $cmd;
like( read_errfile(), qr/^.*:\d+:$msg/, "$case message");
}
for ( CASES ) {
my ( $case, $prog, $msg) = @$_;
unlink 'errors.err';
my $cmd = qq($^X -Ilib -MVi::QuickFix -we "eval '$prog'" ) . REDIRECT;
system $cmd;
if ( $case =~ /_error$/ ) {
$msg = 'QuickFix .* active';
like( read_errfile(), qr/^.*:\d+:$msg/, "eval $case no message");
} else {
like( read_errfile(), qr/^.*:\d+:$msg/, "eval $case message");
}
}
}}
# repeat these in "sig" mode, if both modes possible
BEGIN { $n_tests += 2*@{ [ CASES]} }
SKIP: {{
skip REASON_LOW, scalar 2*@{ [ CASES]} if LOW_VERSION;
for ( CASES ) {
my ( $case, $prog, $msg) = @$_;
unlink 'errors.err';
my $cmd =
qq($^X -Ilib -MVi::QuickFix=sig -we "$prog" ) . REDIRECT;
system $cmd;
like( read_errfile(), qr/^.*:\d+:$msg/, "$case(sig) message");
}
for ( CASES ) {
my ( $case, $prog, $msg) = @$_;
unlink 'errors.err';
my $cmd =
qq($^X -Ilib -MVi::QuickFix=sig -we "eval '$prog'" ) . REDIRECT;
system $cmd;
if ( $case =~ /_error$/ ) {
$msg = 'QuickFix .* active';
like( read_errfile(), qr/^.*:\d+:$msg/, "eval $case(sig) no message");
} else {
like( read_errfile(), qr/^.*:\d+:$msg/, "eval $case(sig) message");
}
}
}}
# repeat these in "fork" mode
BEGIN { $n_tests += 2*@{ [ CASES]} }
SKIP: {{
skip "'fork' mode currently not testable", 2*@{ [ CASES]};
for ( CASES ) {
my ( $case, $prog, $msg) = @$_;
unlink 'errors.err';
my $cmd = qq($^X -Ilib -MVi::QuickFix=fork -we "$prog" ) . REDIRECT;
system $cmd;
like( read_errfile(), qr/^.*:\d+:$msg/, "$case(fork) message");
}
for ( CASES ) {
my ( $case, $prog, $msg) = @$_;
unlink 'errors.err';
my $cmd = qq($^X -Ilib -MVi::QuickFix=fork -we "eval '$prog'" ) . REDIRECT;
system $cmd;
if ( $case =~ /_error$/ ) {
$msg = 'QuickFix .* active';
like( read_errfile(), qr/^.*:\d+:$msg/, "eval $case(fork) no message");
} else {
like( read_errfile(), qr/^.*:\d+:$msg/, "eval $case(fork) message");
}
}
}}
BEGIN { $n_tests += 8 }
{{
# do we get the obligatory warning?
unlink 'errors.err';
my $cmd =
qq($^X -Ilib -MVi::QuickFix -we "warn qq(abc)" ) . REDIRECT;
system $cmd;
like( (read_errfile())[ -1],
qr/QuickFix.*active/, "obligatory message found");
# does silent mode work?
unlink 'errors.err';
system qq($^X -Ilib -MVi::QuickFix=silent -we 'warn "abc"' ) . REDIRECT;
unlike( (read_errfile())[ -1],
qr/QuickFix/, "silent mode message not found");
# do we get only one obwarn when we fork?
unlink 'errors.err';
system qq($^X -Ilib -MVi::QuickFix -efork ) . REDIRECT;
is( scalar( () = read_errfile()), 1, "fork one message");
# do we not get it in exec mode?
unlink 'errors.err';
system qq($^X lib/Vi/QuickFix.pm <) . DEVNULL . ' ' . REDIRECT;
ok( not( -e 'errors.err'), "no message in exec mode");
# is an empty error file removed (needs silent mode)?
system qq($^X -Ilib -MVi::QuickFix -we ';' ) . REDIRECT; # create error file
ok( -e 'errors.err', "Error file exists");
system( qq($^X -Ilib -MVi::QuickFix=silent -we";"));
ok( not( -e 'errors.err'), "Empty error file erased");
# Does it behave under -c?
unlink qw( stderr_out errors.err);
system qq($^X -c -Ilib -we"use Vi::QuickFix" 2>stderr_out);
is( -s( 'errors.err') || 0, 0, "-c: error file empty");
like( read_errfile( 'stderr_out'), qr/^-e syntax OK/, "-c: -e syntax OK");
unlink qw( stderr_out errors.err);
}}
### environment variable VI_QUICKFIX_SOURCEFILE
BEGIN { $n_tests += 2 }
{{
my $cmd = qq($^X -Ilib -MVi::QuickFix ) . REDIRECT;
delete $ENV{ VI_QUICKFIX_SOURCEFILE};
open my $p, '|-', $cmd;
print $p 'warn "boo"';
close $p;
like ( read_errfile(), qr/^-:/, 'env-var unset, found "-"');
$ENV{ VI_QUICKFIX_SOURCEFILE} = 'somefile.pl';
open $p, '|-', $cmd;
print $p 'warn "boo"';
close $p;
like ( read_errfile(), qr/^$ENV{ VI_QUICKFIX_SOURCEFILE}:/,
"env-var set, found filename");
}}
# error behavior
BEGIN { $n_tests += 5 }
{{
# unable to create error file
require Vi::QuickFix;
local $SIG{__WARN__} = sub { die @_ };
eval { Vi::QuickFix->import( 'tie', 'gibsnich/wirdnix') };
like( $@, qr/Can't create error file/, "Warning without error file");
SKIP: {
skip "Can't be tested with perl $]", 3 if LOW_VERSION;
# refuse to re-tie STDERR
require Tie::Handle;
tie *STDERR, 'Tie::StdHandle', '>&STDERR';
require Vi::QuickFix;
eval { Vi::QuickFix->import( 'tie') };
like( $@, qr/STDERR already tied/, "Refused to re-tie");
untie *STDERR;
# accept second use (no action then)
Vi::QuickFix->import( 'tie', 'silent');
ok( tied *STDERR, 'Second use: STDERR is tied');
eval { Vi::QuickFix->import('tie') };
like( $@, qr/^$/, 'Second use no error');
untie *STDERR;
}
# reject "tie" mode on low version
SKIP: {
skip "irrelevant with perl $]", 1 unless LOW_VERSION;
# make silent, so test doesn't warn
eval { Vi::QuickFix->import( 'tie', 'silent') };
like( $@, qr/^Cannot use 'tie'/, 'Reject tie mode');
}
}}
BEGIN { plan tests => $n_tests }
#####################################################################
sub run_tests {
my ( $call, $errf, $command) = @_;
my $errfile = ERRFILE->{ $errf};
$command =~ s/\*ERRFILE\*/$errfile/g;
unlink $errfile;
system( $command);
# don't forget PER_CALL when uncommenting
# ok( -s $errfile, "$call $errf size");
my @lines = read_errfile( $errfile);
my $i;
for ( ERR_TXT ) {
$i ++;
my $line = shift @lines;
like( $line, qr/^(.*?):\d+:$_$/, "$call $errf $i");
}
unlink $errfile;
}
sub read_errfile {
my $file = shift || 'errors.err';
open my( $e), '<', $file or return '-';
return join '', <$e> unless wantarray;
return <$e>;
}
|