File Coverage

blib/lib/Test/Stream/Plugin/Subtest.pm
Criterion Covered Total %
statement 86 86 100.0
branch 24 28 85.7
condition 14 23 60.8
subroutine 15 15 100.0
pod 2 3 66.6
total 141 155 90.9


line stmt bran cond sub pod time code
1             package Test::Stream::Plugin::Subtest;
2 31     31   100 use strict;
  31         39  
  31         695  
3 31     31   95 use warnings;
  31         33  
  31         622  
4              
5 31     31   101 use Test::Stream::Context qw/context/;
  31         35  
  31         171  
6 31     31   111 use Test::Stream::Util qw/try/;
  31         50  
  31         119  
7              
8 31     31   10884 use Test::Stream::Event::Subtest();
  31         55  
  31         470  
9 31     31   10743 use Test::Stream::Hub::Subtest();
  31         46  
  31         510  
10 31     31   113 use Test::Stream::Plugin qw/import/;
  31         38  
  31         161  
11              
12             sub load_ts_plugin {
13 31     31 0 46 my $class = shift;
14 31         36 my $caller = shift;
15              
16 31 100 66     363 if (!@_ || (@_ == 1 && $_[0] =~ m/^(streamed|buffered)$/)) {
      66        
17 2   50     14 my $name = $1 || $_[0] || 'buffered';
18 31     31   131 no strict 'refs';
  31         41  
  31         3783  
19 2         9 *{"$caller->[0]\::subtest"} = $class->can("subtest_$name");
  2         9  
20 2         7 return;
21             }
22              
23 29         54 for my $arg (@_) {
24 30         110 my $ok = $arg =~ m/^subtest_(streamed|buffered)$/;
25 30 50       254 my $sub = $ok ? $class->can($arg) : undef;
26 30 50       110 die "$class does not export '$arg' at $caller->[1] line $caller->[2].\n"
27             unless $sub;
28              
29 31     31   132 no strict 'refs';
  31         42  
  31         13659  
30 30         34 *{"$caller->[0]\::$arg"} = $sub;
  30         762  
31             }
32             }
33              
34             sub subtest_streamed {
35 10     10 1 168 my ($name, $code, @args) = @_;
36 10         24 my $ctx = context();
37 10         39 my $pass = _subtest("Subtest: $name", $code, 0, @args);
38 9         48 $ctx->release;
39 9         20 return $pass;
40             }
41              
42             sub subtest_buffered {
43 213     213 1 314 my ($name, $code, @args) = @_;
44 213         431 my $ctx = context();
45 213         445 my $pass = _subtest($name, $code, 1, @args);
46 211         854 $ctx->release;
47 211         441 return $pass;
48             }
49              
50             sub _subtest {
51 223     223   292 my ($name, $code, $buffered, @args) = @_;
52              
53 223         367 my $ctx = context();
54              
55 223 100       411 $ctx->note($name) unless $buffered;
56              
57 223         505 my $parent = $ctx->hub;
58              
59 223   66     724 my $stack = $ctx->stack || Test::Stream::Sync->stack;
60 223         1015 my $hub = $stack->new_hub(
61             class => 'Test::Stream::Hub::Subtest',
62             );
63              
64 223         234 my @events;
65 223 100       1861 $hub->set_nested( $parent->isa('Test::Stream::Hub::Subtest') ? $parent->nested + 1 : 1 );
66 223     1564   1522 $hub->listen(sub { push @events => $_[1] });
  1564         4378  
67 223 100       775 $hub->format(undef) if $buffered;
68              
69 223         508 my $no_diag = $ctx->debug->no_diag;
70 223 100       424 $hub->set_parent_todo($no_diag) if $no_diag;
71              
72 223         239 my ($ok, $err, $finished);
73             TS_SUBTEST_WRAPPER: {
74 223     223   176 ($ok, $err) = try { $code->(@args) };
  223         885  
  223         495  
75              
76             # They might have done 'BEGIN { skip_all => "whatever" }'
77 218 100 66     899 if (!$ok && $err =~ m/Label not found for "last TS_SUBTEST_WRAPPER"/) {
78 1         3 $ok = undef;
79 1         3 $err = undef;
80             }
81             else {
82 217         261 $finished = 1;
83             }
84             }
85 222         638 $stack->pop($hub);
86              
87 222         494 my $dbg = $ctx->debug;
88              
89 222 100       690 if (!$finished) {
90 5 100       19 if(my $bailed = $hub->bailed_out) {
91 2         12 $ctx->bail($bailed->reason);
92             }
93 3         25 my $code = $hub->exit_code;
94 3         12 $ok = !$code;
95 3 50       12 $err = "Subtest ended with exit code $code" if $code;
96             }
97              
98 220 100 33     822 $hub->finalize($dbg, 1)
      66        
99             if $ok
100             && !$hub->no_ending
101             && !$hub->state->ended;
102              
103 220   66     764 my $pass = $ok && $hub->state->is_passing;
104 220         817 my $e = $ctx->build_event(
105             'Subtest',
106             pass => $pass,
107             name => $name,
108             buffered => $buffered,
109             subevents => \@events,
110             );
111              
112 220 50       530 $e->set_diag([
    100          
113             $e->default_diag,
114             $ok ? () : ("Caught exception in subtest: $err"),
115             ]) unless $pass;
116              
117 220         520 $ctx->hub->send($e);
118              
119 220         601 $ctx->release;
120 220         580 return $hub->state->is_passing;
121             }
122              
123             1;
124              
125             __END__