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   160 use strict;
  31         62  
  31         798  
3 31     31   153 use warnings;
  31         62  
  31         872  
4              
5 31     31   163 use Test::Stream::Context qw/context/;
  31         62  
  31         243  
6 31     31   167 use Test::Stream::Util qw/try/;
  31         64  
  31         190  
7              
8 31     31   18492 use Test::Stream::Event::Subtest;
  31         79  
  31         224  
9 31     31   18085 use Test::Stream::Hub::Subtest;
  31         93  
  31         746  
10 31     31   173 use Test::Stream::Plugin;
  31         61  
  31         232  
11              
12             sub load_ts_plugin {
13 31     31 0 69 my $class = shift;
14 31         68 my $caller = shift;
15              
16 31 100 66     427 if (!@_ || (@_ == 1 && $_[0] =~ m/^(streamed|buffered)$/)) {
      66        
17 2   50     19 my $name = $1 || $_[0] || 'buffered';
18 31     31   166 no strict 'refs';
  31         63  
  31         5169  
19 2         13 *{"$caller->[0]\::subtest"} = $class->can("subtest_$name");
  2         13  
20 2         10 return;
21             }
22              
23 29         79 for my $arg (@_) {
24 30         145 my $ok = $arg =~ m/^subtest_(streamed|buffered)$/;
25 30 50       315 my $sub = $ok ? $class->can($arg) : undef;
26 30 50       139 die "$class does not export '$arg' at $caller->[1] line $caller->[2].\n"
27             unless $sub;
28              
29 31     31   173 no strict 'refs';
  31         66  
  31         20631  
30 30         59 *{"$caller->[0]\::$arg"} = $sub;
  30         965  
31             }
32             }
33              
34             sub subtest_streamed {
35 10     10 1 144 my ($name, $code, @args) = @_;
36 10         29 my $ctx = context();
37 10         40 my $pass = _subtest("Subtest: $name", $code, 0, @args);
38 9         53 $ctx->release;
39 9         30 return $pass;
40             }
41              
42             sub subtest_buffered {
43 212     212 1 536 my ($name, $code, @args) = @_;
44 212         702 my $ctx = context();
45 212         730 my $pass = _subtest($name, $code, 1, @args);
46 210         1369 $ctx->release;
47 210         685 return $pass;
48             }
49              
50             sub _subtest {
51 222     222   549 my ($name, $code, $buffered, @args) = @_;
52              
53 222         697 my $ctx = context();
54              
55 222 100       663 $ctx->note($name) unless $buffered;
56              
57 222         811 my $parent = $ctx->hub;
58              
59 222   66     1203 my $stack = $ctx->stack || Test::Stream::Sync->stack;
60 222         1628 my $hub = $stack->new_hub(
61             class => 'Test::Stream::Hub::Subtest',
62             );
63              
64 222         406 my @events;
65 222 100       2592 $hub->set_nested( $parent->isa('Test::Stream::Hub::Subtest') ? $parent->nested + 1 : 1 );
66 222     1554   2286 $hub->listen(sub { push @events => $_[1] });
  1554         6912  
67 222 100       1195 $hub->format(undef) if $buffered;
68              
69 222         775 my $no_diag = $ctx->debug->no_diag;
70 222 100       634 $hub->set_parent_todo($no_diag) if $no_diag;
71              
72 222         323 my ($ok, $err, $finished);
73             TS_SUBTEST_WRAPPER: {
74 222     222   320 ($ok, $err) = try { $code->(@args) };
  222         1293  
  222         744  
75              
76             # They might have done 'BEGIN { skip_all => "whatever" }'
77 217 100 66     1292 if (!$ok && $err =~ m/Label not found for "last TS_SUBTEST_WRAPPER"/) {
78 1         3 $ok = undef;
79 1         2 $err = undef;
80             }
81             else {
82 216         413 $finished = 1;
83             }
84             }
85 221         970 $stack->pop($hub);
86              
87 221         763 my $dbg = $ctx->debug;
88              
89 221 100       1088 if (!$finished) {
90 5 100       19 if(my $bailed = $hub->bailed_out) {
91 2         13 $ctx->bail($bailed->reason);
92             }
93 3         20 my $code = $hub->exit_code;
94 3         12 $ok = !$code;
95 3 50       8 $err = "Subtest ended with exit code $code" if $code;
96             }
97              
98 219 100 33     1274 $hub->finalize($dbg, 1)
      66        
99             if $ok
100             && !$hub->no_ending
101             && !$hub->state->ended;
102              
103 219   66     1120 my $pass = $ok && $hub->state->is_passing;
104 219         1066 my $e = $ctx->build_event(
105             'Subtest',
106             pass => $pass,
107             name => $name,
108             buffered => $buffered,
109             subevents => \@events,
110             );
111              
112 219 50       824 $e->set_diag([
    100          
113             $e->default_diag,
114             $ok ? () : ("Caught exception in subtest: $err"),
115             ]) unless $pass;
116              
117 219         822 $ctx->hub->send($e);
118              
119 219         918 $ctx->release;
120 219         868 return $hub->state->is_passing;
121             }
122              
123             1;
124              
125             __END__