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
|
#!perl -T
# -*- mode: cperl ; compile-command: "cd .. ; ./Build ; prove -vb t/07-*.t" -*-
BEGIN { $_ = defined && /(.*)/ && $1 for @ENV{qw/ TMPDIR TEMP TMP /} } # taint vs tempfile
use Test::More tests => 8 + 5*18;
use strict;
use warnings;
use Test::Trap::Builder;
my $Builder; BEGIN { $Builder = Test::Trap::Builder->new }
local @ARGV; # in case some harness wants to mess with it ...
my @argv = ('A');
BEGIN {
package TT::A;
use base 'Test::Trap';
$Builder->layer( argv => $_ ) for sub {
my $self = shift;
local *ARGV = \@argv;
$self->{inargv} = [@argv];
$self->Next;
$self->{outargv} = [@argv];
};
$Builder->accessor( is_array => 1, simple => [qw/inargv outargv/] );
$Builder->accessor( flexible =>
{ argv => sub {
$_[1] && $_[1] !~ /in/i ? $_[0]{outargv} : $_[0]{inargv};
},
},
);
$Builder->test( can => 'element, predicate, name', $_ ) for sub {
my ($got, $methods) = @_;
@_ = ($got, @$methods);
goto &Test::More::can_ok;
};
# Hack! Make perl think we have successfully required this package,
# so that we can "use" it, even though it can't be found:
$INC{'TT/A.pm'} = 'Hack!';
}
BEGIN {
package TT::B;
use base 'Test::Trap';
$Builder->accessor( flexible =>
{ leavewith => sub {
my $self = shift;
my $leaveby = $self->leaveby;
$self->$leaveby;
},
},
);
# Hack! Make perl think we have successfully required this package,
# so that we can "use" it, even though it can't be found:
$INC{'TT/B.pm'} = 'Hack!';
}
BEGIN {
package TT::AB;
use base qw( TT::A TT::B );
$Builder->test( fail => 'name', \&Test::More::fail );
# Hack! Make perl think we have successfully required this package,
# so that we can "use" it, even though it can't be found:
$INC{'TT/AB.pm'} = 'Hack!';
}
BEGIN {
package TT::A2;
use base qw( TT::A );
$Builder->test( anotherfail => 'name', \&Test::More::fail );
$Builder->accessor( flexible =>
{ anotherouterr => sub {
my $self = shift;
$self->stdout . $self->stderr;
},
},
);
# Hack! Make perl think we have successfully required this package,
# so that we can "use" it, even though it can't be found:
$INC{'TT/A2.pm'} = 'Hack!';
}
BEGIN {
# Insert s'mores into Test::Trap itself ... not clean, but a nice
# quick thing to be able to do, in need:
package Test::Trap;
$Builder->test( pass => 'name', \&Test::More::pass );
$Builder->accessor( flexible =>
{ outerr => sub {
my $self = shift;
$self->stdout . $self->stderr;
},
},
);
}
BEGIN {
use_ok( 'Test::Trap' ); # import a standard trap/$trap
use_ok( 'Test::Trap', '$D', 'D' );
use_ok( 'TT::A', '$A', 'A', ':argv' );
use_ok( 'TT::B', '$B', 'B' );
use_ok( 'TT::AB', '$AB', 'AB', ':argv' );
use_ok( 'TT::A2', '$A2', 'A2', ':argv' );
}
BEGIN {
trap {
package TT::badclass;
use base 'Test::Trap';
$Builder->multi_layer( trouble => qw( warn no_such_layer ) );
};
like( $trap->die,
qr/^\QUnknown trap layer "no_such_layer" at ${\__FILE__} line/,
'Bad definition: unknown layer',
);
}
BEGIN {
trap {
package TT::badclass3;
use base 'Test::Trap';
$Builder->test( pass => 'named', \&Test::More::pass );
};
like( $trap->die,
qr/^\QUnrecognized identifier named in argspec at ${\__FILE__} line/,
'Bad definition: test argspec typo ("named" for "name")',
);
}
basic( \&D, \$D, 'Unmodified Test::Trap',
qw( isno_A isno_B isno_AB ),
);
basic( \&A, \$A, 'TT::A',
qw( isan_A isno_B isno_AB ),
);
basic( \&B, \$B, 'TT::B',
qw( isno_A isa_B isno_AB ),
);
basic( \&AB, \$AB, 'TT::AB',
qw( isan_A isa_B isan_AB ),
);
basic( \&A2, \$A2, 'TT::A2',
qw( isan_A isno_B isno_AB ),
);
exit 0;
# compile this after the CORE::GLOBAL::exit has been set:
my $argv_expected;
my $ARGV_expected;
sub isno_A {
my ($func, $handle, $name) = @_;
ok( !exists $$handle->{inargv}, "$name: no inargv internally" );
push @$ARGV_expected, $name;
ok( !exists $$handle->{outargv}, "$name: no outargv internally" );
is_deeply( \@ARGV, $ARGV_expected, "$name: \@ARGV modified" );
is_deeply( \@argv, $argv_expected, "$name: \@argv unmofied" );
ok( !$$handle->can('return_can'), "$name: no return_can method" );
ok( !$$handle->can('outargv'), "$name: no outargv method" );
ok( !$$handle->can('outargv_can'), "$name: no outargv_can method" );
ok( !$$handle->can('outargv_pass'), "$name: no outargv_pass method" );
}
sub isan_A {
my ($func, $handle, $name) = @_;
is_deeply( $$handle->{inargv}, $argv_expected, "$name: inargv present internally" );
push @$argv_expected, $name;
is_deeply( $$handle->{outargv}, $argv_expected, "$name: outargv present internally" );
is_deeply( \@ARGV, $ARGV_expected, "$name: \@ARGV unmodified" );
is_deeply( \@argv, $argv_expected, "$name: \@argv modified" );
ok( $$handle->can('return_can'), "$name: return_can method present" );
() = trap { $$handle->outargv };
$trap->return_is_deeply( [$argv_expected], "$name: outargv method present and functional" );
ok( $$handle->can('outargv_can'), "$name: outargv_can method present" );
ok( $$handle->can('outargv_pass'), "$name: outargv_pass method present" );
}
sub isa_B {
my ($func, $handle, $name) = @_;
() = trap { $$handle->leavewith };
$trap->return_is_deeply( [1], "$name: leavewith method present and functional" );
}
sub isno_B {
my ($func, $handle, $name) = @_;
ok( !$$handle->can('leavewith'), "$name: no leavewith method" );
}
sub isan_AB {
my ($func, $handle, $name) = @_;
ok( $$handle->can('stderr_fail'), "$name: stderr_fail method present" );
ok( $$handle->can('argv_fail'), "$name: argv_fail method present" );
ok( $$handle->can('leavewith_fail'), "$name: leavewith_fail method present" );
TODO: {
local $TODO = 'Multiple inheritance still incomplete';
ok( $$handle->can('leavewith_can'), "$name: leavewith_fail method present" );
}
}
sub isno_AB {
my ($func, $handle, $name) = @_;
ok( !$$handle->can('stderr_fail'), "$name: no stderr_fail method" );
ok( !$$handle->can('argv_fail'), "$name: no argv_fail method" );
ok( !$$handle->can('leavewith_fail'), "$name: no leavewith_fail method" );
ok( !$$handle->can('leavewith_can'), "$name: no leavewith_can method" );
}
sub basic {
my ($func, $handle, $name) = @_;
$argv_expected ||= ['A'];
$ARGV_expected ||= [];
$func->(sub { print "Hello"; warn "Hi!\n"; push @ARGV, $name; exit 1 });
local $Test::Builder::Level = $Test::Builder::Level + 1;
is( $$handle->exit, 1, "$name: trapped exit" );
is( $$handle->stdout, "Hello", "$name: trapped stdout" );
is( $$handle->stderr, "Hi!\n", "$name: trapped stderr" );
is_deeply( $$handle->warn, ["Hi!\n"], "$name: trapped warnings" );
ok( $$handle->can('stdout_pass'), "$name: stdout_pass method present" );
$Test::Builder::Level++;
no strict 'refs';
$_->(@_) for @_[3..$#_];
}
|