| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test::Script::Async; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 14 |  |  | 14 |  | 2241668 | use strict; | 
|  | 14 |  |  |  |  | 34 |  | 
|  | 14 |  |  |  |  | 418 |  | 
| 4 | 14 |  |  | 14 |  | 210 | use warnings; | 
|  | 14 |  |  |  |  | 29 |  | 
|  | 14 |  |  |  |  | 403 |  | 
| 5 | 14 |  |  | 14 |  | 401 | use 5.008001; | 
|  | 14 |  |  |  |  | 44 |  | 
| 6 | 14 |  |  | 14 |  | 78 | use Carp (); | 
|  | 14 |  |  |  |  | 38 |  | 
|  | 14 |  |  |  |  | 364 |  | 
| 7 | 14 |  |  | 14 |  | 11262 | use AnyEvent::Open3::Simple 0.86; | 
|  | 14 |  |  |  |  | 178687 |  | 
|  | 14 |  |  |  |  | 434 |  | 
| 8 | 14 |  |  | 14 |  | 100 | use File::Spec (); | 
|  | 14 |  |  |  |  | 28 |  | 
|  | 14 |  |  |  |  | 295 |  | 
| 9 | 14 |  |  | 14 |  | 10475 | use Probe::Perl; | 
|  | 14 |  |  |  |  | 27306 |  | 
|  | 14 |  |  |  |  | 504 |  | 
| 10 | 14 |  |  | 14 |  | 3037 | use Test::Stream::Context qw( context ); | 
|  | 14 |  |  |  |  | 149721 |  | 
|  | 14 |  |  |  |  | 147 |  | 
| 11 | 14 |  |  | 14 |  | 1231 | use Test::Stream::Exporter; | 
|  | 14 |  |  |  |  | 28 |  | 
|  | 14 |  |  |  |  | 100 |  | 
| 12 |  |  |  |  |  |  | default_exports qw( script_compiles script_runs ); | 
| 13 | 14 |  |  | 14 |  | 1717 | no Test::Stream::Exporter; | 
|  | 14 |  |  |  |  | 29 |  | 
|  | 14 |  |  |  |  | 76 |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | # ABSTRACT: Non-blocking friendly tests for scripts | 
| 16 |  |  |  |  |  |  | our $VERSION = '0.01'; # VERSION | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | sub _path ($) | 
| 20 |  |  |  |  |  |  | { | 
| 21 | 53 |  |  | 53 |  | 329 | my $path = shift; | 
| 22 | 53 | 50 |  |  |  | 201 | Carp::croak("Did not provide a script name") unless $path; | 
| 23 | 53 | 50 |  |  |  | 805 | Carp::croak("Script name must be relative") if File::Spec::Unix->file_name_is_absolute($path); | 
| 24 | 53 |  |  |  |  | 1625 | File::Spec->catfile( | 
| 25 |  |  |  |  |  |  | File::Spec->curdir, | 
| 26 |  |  |  |  |  |  | split /\//, $path | 
| 27 |  |  |  |  |  |  | ); | 
| 28 |  |  |  |  |  |  | } | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | my $perl; | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | sub _perl () | 
| 33 |  |  |  |  |  |  | { | 
| 34 | 29 |  | 66 | 29 |  | 325 | $perl ||= Probe::Perl->find_perl_interpreter; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | sub _detect | 
| 38 |  |  |  |  |  |  | { | 
| 39 | 90 | 50 |  | 90 |  | 13767 | if(grep /^(Mojo|Mojolicious)(\/.*)?\.pm?$/, keys %INC) | 
| 40 | 0 |  |  |  |  | 0 | { 'mojo' } | 
| 41 |  |  |  |  |  |  | else | 
| 42 | 90 |  |  |  |  | 708 | { return undef } | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | sub _is_mojo | 
| 46 |  |  |  |  |  |  | { | 
| 47 | 40 |  |  | 40 |  | 221 | my $detect = _detect(); | 
| 48 | 40 | 50 |  |  |  | 1047 | defined $detect && $detect eq 'mojo'; | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | sub script_compiles | 
| 53 |  |  |  |  |  |  | { | 
| 54 | 5 |  |  | 5 | 1 | 19780 | my($script, $test_name) = @_; | 
| 55 | 5 |  |  |  |  | 30 | my @libs = map { "-I$_" } grep { !ref($_) } @INC; | 
|  | 55 |  |  |  |  | 177 |  | 
|  | 55 |  |  |  |  | 145 |  | 
| 56 | 5 |  |  |  |  | 28 | my @cmd = ( _perl, @libs, '-c', _path $script ); | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 5 |  | 66 |  |  | 49 | $test_name ||= "Script $script compiles"; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | # TODO: also work with mojo | 
| 61 | 5 |  |  |  |  | 11 | my $done; | 
| 62 | 5 | 50 |  |  |  | 19 | unless(_detect()) | 
| 63 |  |  |  |  |  |  | { | 
| 64 | 5 |  |  |  |  | 1475 | require AE; | 
| 65 | 5 |  |  |  |  | 14664 | $done = AE::cv(); | 
| 66 |  |  |  |  |  |  | } | 
| 67 | 5 |  |  |  |  | 9926 | my @stderr; | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 5 |  |  |  |  | 21 | my $ctx = context(); | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | my $ipc = AnyEvent::Open3::Simple->new( | 
| 72 |  |  |  |  |  |  | on_stderr => sub { | 
| 73 | 6 |  |  | 6 |  | 30497 | my($proc, $line) = @_; | 
| 74 | 6 |  |  |  |  | 95 | push @stderr, $line; | 
| 75 |  |  |  |  |  |  | }, | 
| 76 |  |  |  |  |  |  | on_exit   => sub { | 
| 77 | 5 |  |  | 5 |  | 1535 | my($proc, $exit, $sig) = @_; | 
| 78 |  |  |  |  |  |  |  | 
| 79 | 5 |  | 66 |  |  | 150 | my $ok = $exit == 0 && $sig == 0 && grep / syntax OK$/, @stderr; | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 5 |  |  |  |  | 97 | $ctx->ok($ok, $test_name); | 
| 82 | 5 | 100 |  |  |  | 1609 | $ctx->diag(@stderr) unless $ok; | 
| 83 | 5 | 100 |  |  |  | 347 | $ctx->diag("exit - $exit") if $exit; | 
| 84 | 5 | 50 |  |  |  | 234 | $ctx->diag("signal - $sig") if $sig; | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 5 |  |  |  |  | 53 | $done->send($ok); | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | }, | 
| 89 |  |  |  |  |  |  | on_error  => sub { | 
| 90 | 0 |  |  | 0 |  | 0 | my($error) = @_; | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 0 |  |  |  |  | 0 | $ctx->ok(0, $test_name); | 
| 93 | 0 |  |  |  |  | 0 | $ctx->diag("error compiling script: $error"); | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 0 |  |  |  |  | 0 | $done->send(0); | 
| 96 |  |  |  |  |  |  | }, | 
| 97 | 5 |  |  |  |  | 497 | ); | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 5 |  |  |  |  | 334 | $ipc->run(@cmd); | 
| 100 | 5 |  |  |  |  | 26769 | my $ok = $done->recv; | 
| 101 | 5 |  |  |  |  | 668 | $ctx->release; | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 5 |  |  |  |  | 448 | $ok; | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | # TODO: support stdin input | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | sub script_runs | 
| 110 |  |  |  |  |  |  | { | 
| 111 | 24 |  |  | 24 | 1 | 61802 | my($script, $test_name) = @_; | 
| 112 | 24 |  |  |  |  | 114 | my @libs = map { "-I$_" } grep { !ref($_) } @INC; | 
|  | 264 |  |  |  |  | 788 |  | 
|  | 264 |  |  |  |  | 637 |  | 
| 113 | 24 | 100 |  |  |  | 153 | $script = [ $script ] unless ref $script; | 
| 114 | 24 |  |  |  |  | 71 | my @args; | 
| 115 | 24 |  |  |  |  | 83 | ($script, @args) = @$script; | 
| 116 | 24 |  |  |  |  | 124 | my @cmd = ( _perl, @libs, _path $script, @args ); | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 24 | 100 | 66 |  |  | 327 | $test_name ||= @args ? "Script $script runs with arguments @args" : "Script $script runs"; | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | # TODO: also work with mojo | 
| 121 | 24 |  |  |  |  | 48 | my $done; | 
| 122 | 24 | 50 |  |  |  | 76 | unless(_detect()) | 
| 123 |  |  |  |  |  |  | { | 
| 124 | 24 |  |  |  |  | 6651 | require AE; | 
| 125 | 24 |  |  |  |  | 66630 | $done = AE::cv(); | 
| 126 |  |  |  |  |  |  | } | 
| 127 | 24 |  |  |  |  | 44053 | my $run = bless { | 
| 128 |  |  |  |  |  |  | script => _path $script, | 
| 129 |  |  |  |  |  |  | args   => [@args], | 
| 130 |  |  |  |  |  |  | out    => [], | 
| 131 |  |  |  |  |  |  | err    => [], | 
| 132 |  |  |  |  |  |  | ok     => 0, | 
| 133 |  |  |  |  |  |  | }, __PACKAGE__; | 
| 134 | 24 |  |  |  |  | 149 | my $ctx = context(); | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 24 | 100 |  |  |  | 2441 | unless(-f $script) | 
| 137 |  |  |  |  |  |  | { | 
| 138 | 4 |  |  |  |  | 41 | $ctx->ok(0, $test_name); | 
| 139 | 4 |  |  |  |  | 749 | $ctx->diag("script does not exist"); | 
| 140 | 4 |  |  |  |  | 571 | $run->{fail} = 'script not found'; | 
| 141 | 4 |  |  |  |  | 30 | $ctx->release; | 
| 142 | 4 |  |  |  |  | 103 | return $run; | 
| 143 |  |  |  |  |  |  | } | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | my $ipc = AnyEvent::Open3::Simple->new( | 
| 146 |  |  |  |  |  |  | implementation => _detect(), | 
| 147 |  |  |  |  |  |  | on_stderr => sub { | 
| 148 | 20 |  |  | 20 |  | 21540 | my(undef, $line) = @_; | 
| 149 | 20 |  |  |  |  | 63 | push @{ $run->{err} }, $line; | 
|  | 20 |  |  |  |  | 221 |  | 
| 150 |  |  |  |  |  |  | }, | 
| 151 |  |  |  |  |  |  | on_stdout => sub { | 
| 152 | 25 |  |  | 25 |  | 114718 | my(undef, $line) = @_; | 
| 153 | 25 |  |  |  |  | 77 | push @{ $run->{out} }, $line; | 
|  | 25 |  |  |  |  | 284 |  | 
| 154 |  |  |  |  |  |  | }, | 
| 155 |  |  |  |  |  |  | on_exit   => sub { | 
| 156 | 20 |  |  | 20 |  | 115652 | (undef, $run->{exit}, $run->{signal}) = @_; | 
| 157 |  |  |  |  |  |  |  | 
| 158 | 20 |  |  |  |  | 107 | $run->{ok} = 1; | 
| 159 | 20 |  |  |  |  | 395 | $ctx->ok(1, $test_name); | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 20 | 50 |  |  |  | 10337 | _is_mojo() ? $done = 1 : $done->send; | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | }, | 
| 164 |  |  |  |  |  |  | on_error  => sub { | 
| 165 | 0 |  |  | 0 |  | 0 | my($error) = @_; | 
| 166 |  |  |  |  |  |  |  | 
| 167 | 0 |  |  |  |  | 0 | $run->{ok} = 0; | 
| 168 | 0 |  |  |  |  | 0 | $run->{fail} = $error; | 
| 169 | 0 |  |  |  |  | 0 | $ctx->ok(0, $test_name); | 
| 170 | 0 |  |  |  |  | 0 | $ctx->diag("error running script: $error"); | 
| 171 | 0 | 0 |  |  |  | 0 | _is_mojo() ? $done = 1 : $done->send; | 
| 172 |  |  |  |  |  |  | }, | 
| 173 | 20 |  |  |  |  | 93 | ); | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 20 |  |  |  |  | 1358 | $ipc->run(@cmd); | 
| 176 | 20 | 50 |  |  |  | 122799 | if(_is_mojo()) | 
| 177 |  |  |  |  |  |  | { | 
| 178 | 0 |  |  |  |  | 0 | Mojo::IOLoop->one_tick until $done; | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | else | 
| 181 |  |  |  |  |  |  | { | 
| 182 | 20 |  |  |  |  | 387 | $done->recv; | 
| 183 |  |  |  |  |  |  | } | 
| 184 | 20 |  |  |  |  | 2787 | $ctx->release; | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 20 |  |  |  |  | 1827 | $run; | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  |  | 
| 190 | 7 |  |  | 7 | 1 | 347 | sub out { shift->{out} } | 
| 191 | 5 |  |  | 5 | 1 | 122 | sub err { shift->{err} } | 
| 192 | 43 |  |  | 43 | 1 | 531 | sub exit { shift->{exit} } | 
| 193 | 54 |  |  | 54 | 1 | 317 | sub signal { shift->{signal} } | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | our $reverse = 0; | 
| 197 |  |  |  |  |  |  | our $level   = 0; | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | sub exit_is | 
| 200 |  |  |  |  |  |  | { | 
| 201 | 12 |  |  | 12 | 1 | 9372 | my($self, $value, $test_message) = @_; | 
| 202 | 12 |  |  |  |  | 61 | my $ctx = context( level => $level ); | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 12 | 100 | 66 |  |  | 1001 | $test_message ||= $reverse ? "script exited with a value other than $value" : "script exited with value $value"; | 
| 205 | 12 |  | 66 |  |  | 45 | my $ok = defined $self->exit && !$self->{signal} && ($reverse ? $self->exit != $value : $self->exit == $value); | 
| 206 |  |  |  |  |  |  |  | 
| 207 | 12 |  |  |  |  | 49 | $ctx->ok($ok, $test_message); | 
| 208 | 12 | 100 |  |  |  | 1549 | if(!defined $self->exit) | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | { | 
| 210 | 2 |  |  |  |  | 11 | $ctx->diag("script did not run so did not exit"); | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  | elsif($self->signal) | 
| 213 |  |  |  |  |  |  | { | 
| 214 | 2 |  |  |  |  | 6 | $ctx->diag("script killed with signal @{[ $self->signal ]}"); | 
|  | 2 |  |  |  |  | 9 |  | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  | elsif(!$ok) | 
| 217 |  |  |  |  |  |  | { | 
| 218 | 3 |  |  |  |  | 7 | $ctx->diag("script exited with value @{[ $self->exit ]}"); | 
|  | 3 |  |  |  |  | 9 |  | 
| 219 |  |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 12 | 100 |  |  |  | 775 | $self->{ok} = 0 unless $ok; | 
| 222 |  |  |  |  |  |  |  | 
| 223 | 12 |  |  |  |  | 38 | $ctx->release; | 
| 224 | 12 |  |  |  |  | 198 | $self; | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | sub exit_isnt | 
| 229 |  |  |  |  |  |  | { | 
| 230 | 5 |  |  | 5 | 1 | 74 | local $reverse = 1; | 
| 231 | 5 |  |  |  |  | 13 | local $level   = 1; | 
| 232 | 5 |  |  |  |  | 11 | shift->exit_is(@_); | 
| 233 |  |  |  |  |  |  | } | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | sub signal_is | 
| 237 |  |  |  |  |  |  | { | 
| 238 | 10 |  |  | 10 | 1 | 10949 | my($self, $value, $test_message) = @_; | 
| 239 | 10 |  |  |  |  | 30 | my $ctx = context(level => $level); | 
| 240 |  |  |  |  |  |  |  | 
| 241 | 10 | 100 | 66 |  |  | 698 | $test_message ||= $reverse ? "script not killed by signal $value" : "script killed by signal $value"; | 
| 242 | 10 |  | 66 |  |  | 32 | my $ok = $self->signal && ($reverse ? $self->signal != $value : $self->signal == $value); | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 10 |  |  |  |  | 34 | $ctx->ok($ok, $test_message); | 
| 245 | 10 | 100 |  |  |  | 1093 | if(!defined $self->signal) | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | { | 
| 247 | 2 |  |  |  |  | 11 | $ctx->diag("script did not run so was not killed"); | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  | elsif(!$self->signal) | 
| 250 |  |  |  |  |  |  | { | 
| 251 | 2 |  |  |  |  | 5 | $ctx->diag("script exited with value @{[ $self->exit ]}"); | 
|  | 2 |  |  |  |  | 12 |  | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  | elsif(!$ok) | 
| 254 |  |  |  |  |  |  | { | 
| 255 | 2 |  |  |  |  | 4 | $ctx->diag("script killed with signal @{[ $self->signal ]}"); | 
|  | 2 |  |  |  |  | 6 |  | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  |  | 
| 258 | 10 | 100 |  |  |  | 540 | $self->{ok} = 0 unless $ok; | 
| 259 |  |  |  |  |  |  |  | 
| 260 | 10 |  |  |  |  | 31 | $ctx->release; | 
| 261 | 10 |  |  |  |  | 176 | $self; | 
| 262 |  |  |  |  |  |  | } | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | sub signal_isnt | 
| 266 |  |  |  |  |  |  | { | 
| 267 | 5 |  |  | 5 | 1 | 15692 | local $reverse = 1; | 
| 268 | 5 |  |  |  |  | 12 | local $level   = 1; | 
| 269 | 5 |  |  |  |  | 17 | shift->signal_is(@_); | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | our $stream = 'out'; | 
| 274 |  |  |  |  |  |  | our $stream_name = 'standard output'; | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | sub out_like | 
| 277 |  |  |  |  |  |  | { | 
| 278 | 9 |  |  | 9 | 1 | 6632 | my($self, $regex, $test_name) = @_; | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 9 |  |  |  |  | 45 | my $ctx = context(level => $level); | 
| 281 | 9 | 100 | 33 |  |  | 654 | $test_name ||= $reverse ? "$stream_name does not match $regex" : "$stream_name matches $regex"; | 
| 282 |  |  |  |  |  |  |  | 
| 283 | 9 |  |  |  |  | 16 | my $ok; | 
| 284 |  |  |  |  |  |  | my @diag; | 
| 285 |  |  |  |  |  |  |  | 
| 286 | 9 | 100 |  |  |  | 25 | if($reverse) | 
| 287 |  |  |  |  |  |  | { | 
| 288 | 4 |  |  |  |  | 6 | $ok = 1; | 
| 289 | 4 |  |  |  |  | 7 | my $num = 1; | 
| 290 | 4 |  |  |  |  | 7 | foreach my $line (@{ $self->{$stream} }) | 
|  | 4 |  |  |  |  | 13 |  | 
| 291 |  |  |  |  |  |  | { | 
| 292 | 16 | 100 |  |  |  | 68 | if($line =~ $regex) | 
| 293 |  |  |  |  |  |  | { | 
| 294 | 2 |  |  |  |  | 6 | $ok = 0; | 
| 295 | 2 |  |  |  |  | 9 | push @diag, "line $num of $stream_name matches: $line"; | 
| 296 |  |  |  |  |  |  | } | 
| 297 | 16 |  |  |  |  | 27 | $num++; | 
| 298 |  |  |  |  |  |  | } | 
| 299 |  |  |  |  |  |  | } | 
| 300 |  |  |  |  |  |  | else | 
| 301 |  |  |  |  |  |  | { | 
| 302 | 5 |  |  |  |  | 16 | $ok = 0; | 
| 303 | 5 |  |  |  |  | 11 | foreach my $line (@{ $self->{$stream} }) | 
|  | 5 |  |  |  |  | 23 |  | 
| 304 |  |  |  |  |  |  | { | 
| 305 | 15 | 100 |  |  |  | 86 | if($line =~ $regex) | 
| 306 |  |  |  |  |  |  | { | 
| 307 | 3 |  |  |  |  | 9 | $ok = 1; | 
| 308 | 3 |  |  |  |  | 12 | last; | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  | } | 
| 311 |  |  |  |  |  |  | } | 
| 312 |  |  |  |  |  |  |  | 
| 313 | 9 |  |  |  |  | 34 | $ctx->ok($ok, $test_name); | 
| 314 | 9 |  |  |  |  | 1128 | $ctx->diag($_) for @diag; | 
| 315 |  |  |  |  |  |  |  | 
| 316 | 9 |  |  |  |  | 224 | $ctx->release; | 
| 317 | 9 | 100 |  |  |  | 170 | $self->{ok} = 0 unless $ok; | 
| 318 |  |  |  |  |  |  |  | 
| 319 | 9 |  |  |  |  | 55 | $self; | 
| 320 |  |  |  |  |  |  | } | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | sub out_unlike | 
| 324 |  |  |  |  |  |  | { | 
| 325 | 2 |  |  | 2 | 1 | 6362 | local $reverse = 1; | 
| 326 | 2 |  |  |  |  | 6 | local $level   = 1; | 
| 327 | 2 |  |  |  |  | 9 | shift->out_like(@_); | 
| 328 |  |  |  |  |  |  | } | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | sub err_like | 
| 332 |  |  |  |  |  |  | { | 
| 333 | 2 |  |  | 2 | 1 | 5585 | local $stream      = 'err'; | 
| 334 | 2 |  |  |  |  | 7 | local $stream_name = 'standard error'; | 
| 335 | 2 |  |  |  |  | 3 | local $level       = 1; | 
| 336 | 2 |  |  |  |  | 8 | shift->out_like(@_); | 
| 337 |  |  |  |  |  |  | } | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | sub err_unlike | 
| 341 |  |  |  |  |  |  | { | 
| 342 | 2 |  |  | 2 | 1 | 6401 | local $stream      = 'err'; | 
| 343 | 2 |  |  |  |  | 4 | local $stream_name = 'standard error'; | 
| 344 | 2 |  |  |  |  | 10 | local $reverse     = 1; | 
| 345 | 2 |  |  |  |  | 4 | local $level       = 1; | 
| 346 | 2 |  |  |  |  | 7 | shift->out_like(@_); | 
| 347 |  |  |  |  |  |  | } | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | our $diag = 'diag'; | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | sub diag | 
| 353 |  |  |  |  |  |  | { | 
| 354 | 4 |  |  | 4 | 1 | 24 | my($self) = @_; | 
| 355 |  |  |  |  |  |  |  | 
| 356 | 4 |  |  |  |  | 43 | my $ctx = context(level => $level); | 
| 357 |  |  |  |  |  |  |  | 
| 358 | 4 |  |  |  |  | 605 | $ctx->$diag("script:    @{[ $self->{script} ]}"); | 
|  | 4 |  |  |  |  | 73 |  | 
| 359 | 4 | 100 |  |  |  | 997 | $ctx->$diag("arguments: @{[ join ' ', @{ $self->{args} } ]}") if @{ $self->{args} }; | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 31 |  | 
|  | 4 |  |  |  |  | 37 |  | 
| 360 | 4 | 50 |  |  |  | 506 | if(defined $self->{fail}) | 
|  |  | 100 |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | { | 
| 362 | 0 |  |  |  |  | 0 | $ctx->$diag("error:     @{[ $self->{fail} ]}"); | 
|  | 0 |  |  |  |  | 0 |  | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  | elsif($self->signal) | 
| 365 |  |  |  |  |  |  | { | 
| 366 | 1 |  |  |  |  | 7 | $ctx->$diag("signal:    @{[ $self->signal ]}"); | 
|  | 1 |  |  |  |  | 10 |  | 
| 367 |  |  |  |  |  |  | } | 
| 368 |  |  |  |  |  |  | else | 
| 369 |  |  |  |  |  |  | { | 
| 370 | 3 |  |  |  |  | 11 | $ctx->$diag("exit:      @{[ $self->exit ]}"); | 
|  | 3 |  |  |  |  | 20 |  | 
| 371 |  |  |  |  |  |  | } | 
| 372 | 4 |  |  |  |  | 505 | $ctx->$diag("[out] $_") for @{ $self->out }; | 
|  | 4 |  |  |  |  | 29 |  | 
| 373 | 4 |  |  |  |  | 1009 | $ctx->$diag("[err] $_") for @{ $self->err }; | 
|  | 4 |  |  |  |  | 32 |  | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 4 |  |  |  |  | 1070 | $ctx->release; | 
| 376 |  |  |  |  |  |  |  | 
| 377 | 4 |  |  |  |  | 101 | $self; | 
| 378 |  |  |  |  |  |  | } | 
| 379 |  |  |  |  |  |  |  | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | sub note | 
| 382 |  |  |  |  |  |  | { | 
| 383 | 3 |  |  | 3 | 1 | 275 | local $diag  = 'note'; | 
| 384 | 3 |  |  |  |  | 26 | local $level = 1; | 
| 385 | 3 |  |  |  |  | 17 | shift->diag; | 
| 386 |  |  |  |  |  |  | } | 
| 387 |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | sub diag_if_fail | 
| 390 |  |  |  |  |  |  | { | 
| 391 | 4 |  |  | 4 | 1 | 4439 | my($self) = @_; | 
| 392 | 4 | 100 |  |  |  | 43 | return if $self->{ok}; | 
| 393 | 1 |  |  |  |  | 4 | local $level = 1; | 
| 394 | 1 |  |  |  |  | 11 | $self->diag; | 
| 395 | 1 |  |  |  |  | 28 | $self; | 
| 396 |  |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | 1; | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | __END__ |