| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test::Stream::Workflow::Unit; | 
| 2 | 95 |  |  | 95 |  | 1170 | use strict; | 
|  | 95 |  |  |  |  | 187 |  | 
|  | 95 |  |  |  |  | 2277 |  | 
| 3 | 95 |  |  | 95 |  | 480 | use warnings; | 
|  | 95 |  |  |  |  | 182 |  | 
|  | 95 |  |  |  |  | 2179 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 95 |  |  | 95 |  | 480 | use Test::Stream::Sync; | 
|  | 95 |  |  |  |  | 172 |  | 
|  | 95 |  |  |  |  | 1856 |  | 
| 6 | 95 |  |  | 95 |  | 566 | use Test::Stream::Context(); | 
|  | 95 |  |  |  |  | 171 |  | 
|  | 95 |  |  |  |  | 1678 |  | 
| 7 | 95 |  |  | 95 |  | 499 | use Test::Stream::DebugInfo; | 
|  | 95 |  |  |  |  | 191 |  | 
|  | 95 |  |  |  |  | 2831 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 95 |  |  | 95 |  | 513 | use Carp qw/confess/; | 
|  | 95 |  |  |  |  | 206 |  | 
|  | 95 |  |  |  |  | 4427 |  | 
| 10 | 95 |  |  | 95 |  | 480 | use Scalar::Util qw/reftype/; | 
|  | 95 |  |  |  |  | 187 |  | 
|  | 95 |  |  |  |  | 5871 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | use Test::Stream::HashBase( | 
| 13 | 95 |  |  |  |  | 932 | accessors => [qw{ | 
| 14 |  |  |  |  |  |  | name meta type wrap stash | 
| 15 |  |  |  |  |  |  | package file start_line end_line | 
| 16 |  |  |  |  |  |  | post | 
| 17 |  |  |  |  |  |  | modify | 
| 18 |  |  |  |  |  |  | buildup | 
| 19 |  |  |  |  |  |  | primary | 
| 20 |  |  |  |  |  |  | teardown | 
| 21 |  |  |  |  |  |  | is_root | 
| 22 |  |  |  |  |  |  | }], | 
| 23 | 95 |  |  | 95 |  | 519 | ); | 
|  | 95 |  |  |  |  | 229 |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | sub init { | 
| 26 | 344 |  | 100 | 344 | 0 | 1810 | $_[0]->{+META} ||= {}; | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 344 |  |  |  |  | 912 | for (NAME, PACKAGE, FILE, START_LINE, END_LINE) { | 
| 29 | 1716 | 100 |  |  |  | 5579 | confess "$_ is a required attribute" unless defined $_[0]->{$_} | 
| 30 |  |  |  |  |  |  | } | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 343 |  | 100 |  |  | 1838 | $_[0]->{+STASH} ||= {}; | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | sub contains { | 
| 36 | 14 |  |  | 14 | 1 | 31 | my $self = shift; | 
| 37 | 14 |  |  |  |  | 19 | my ($thing) = @_; | 
| 38 | 14 |  |  |  |  | 16 | my ($file, $line, $name); | 
| 39 | 14 | 100 |  |  |  | 65 | if ($thing =~ m/^(\S+) (\d+)$/) { | 
|  |  | 100 |  |  |  |  |  | 
| 40 | 2 |  |  |  |  | 6 | ($file, $line) = ($1, $2); | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  | elsif ($thing =~ m/^\d+$/) { | 
| 43 | 6 |  |  |  |  | 11 | $line = $thing; | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  | else { | 
| 46 | 6 |  |  |  |  | 11 | $name = $thing; | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 14 |  |  |  |  | 33 | return $self->_contains($file, $line, $name); | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | sub _contains { | 
| 53 | 16 |  |  | 16 |  | 18 | my $self = shift; | 
| 54 | 16 |  |  |  |  | 26 | my ($file, $line, $name) = @_; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 16 |  | 100 |  |  | 54 | my $name_ok = !defined($name) || $self->{+NAME} eq $name; | 
| 57 | 16 |  | 100 |  |  | 40 | my $file_ok = !defined($file) || $self->{+FILE} eq $file; | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | my $line_ok = !defined($line) || ( | 
| 60 |  |  |  |  |  |  | $line >= $self->{+START_LINE} | 
| 61 | 16 |  | 66 |  |  | 79 | && ($self->{+END_LINE} . "" eq 'EOF' || $line <= $self->{+END_LINE}) | 
| 62 |  |  |  |  |  |  | ); | 
| 63 |  |  |  |  |  |  |  | 
| 64 | 16 |  |  |  |  | 19 | my $child_ok = 0; | 
| 65 | 16 |  |  |  |  | 34 | for my $stash (MODIFY(), BUILDUP(), PRIMARY(), TEARDOWN()) { | 
| 66 | 64 |  | 100 |  |  | 325 | my $set = $self->$stash || next; | 
| 67 | 2 | 50 | 33 |  |  | 21 | next unless ref $set && reftype($set) eq 'ARRAY'; | 
| 68 | 2 |  |  |  |  | 5 | for my $unit (@$set) { | 
| 69 | 2 | 100 |  |  |  | 7 | $child_ok = 1 if $unit->_contains($file, $line, $name); | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  |  | 
| 73 | 16 |  | 66 |  |  | 203 | return $child_ok || ($name_ok && $file_ok && $line_ok); | 
| 74 |  |  |  |  |  |  | } | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | sub do_post { | 
| 77 | 54 |  |  | 54 | 1 | 249 | my $self = shift; | 
| 78 |  |  |  |  |  |  |  | 
| 79 | 54 | 100 |  |  |  | 302 | my $post = delete $self->{+POST} or return; | 
| 80 | 19 |  |  |  |  | 93 | $_->($self) for @$post; | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | for my $type (MODIFY(), BUILDUP(), PRIMARY(), TEARDOWN()) { | 
| 84 | 95 |  |  | 95 |  | 597 | no strict 'refs'; | 
|  | 95 |  |  |  |  | 182 |  | 
|  | 95 |  |  |  |  | 5075 |  | 
| 85 |  |  |  |  |  |  | *{"add_$type"} = sub { | 
| 86 | 95 |  |  | 95 |  | 517 | use strict; | 
|  | 95 |  |  |  |  | 217 |  | 
|  | 95 |  |  |  |  | 64252 |  | 
| 87 | 264 |  |  | 264 |  | 420 | my $self = shift; | 
| 88 | 264 |  | 100 |  |  | 932 | $self->{$type} ||= []; | 
| 89 | 264 |  |  |  |  | 359 | push @{$self->{$type}} => @_; | 
|  | 264 |  |  |  |  | 1645 |  | 
| 90 |  |  |  |  |  |  | }; | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | sub adjust_lines { | 
| 94 | 29 |  |  | 29 | 1 | 67 | my $self = shift; | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 29 |  |  |  |  | 62 | my $start = $self->{+START_LINE}; | 
| 97 | 29 |  |  |  |  | 52 | my $end   = $self->{+END_LINE}; | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 29 |  |  |  |  | 82 | for my $stash (MODIFY(), BUILDUP(), PRIMARY(), TEARDOWN()) { | 
| 100 | 116 | 100 |  |  |  | 375 | my $list = $self->{$stash} or next; | 
| 101 | 42 | 50 |  |  |  | 112 | next unless ref $list; | 
| 102 | 42 | 50 |  |  |  | 164 | next unless reftype($list) eq 'ARRAY'; | 
| 103 | 42 | 50 |  |  |  | 101 | next unless @$list; | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 42 | 50 |  |  |  | 107 | my $top = $list->[0] or next; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 42 |  |  |  |  | 143 | my $c_start = $top->start_line; | 
| 108 | 42 |  |  |  |  | 221 | my $c_end   = $top->end_line; | 
| 109 |  |  |  |  |  |  |  | 
| 110 | 42 | 100 | 33 |  |  | 506 | $start = $c_start | 
|  |  |  | 66 |  |  |  |  | 
| 111 |  |  |  |  |  |  | if defined($c_start) | 
| 112 |  |  |  |  |  |  | && $c_start =~ m/^\d+$/ | 
| 113 |  |  |  |  |  |  | && $c_start < $start; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 42 | 50 | 33 |  |  | 238 | next if $end && "$end" eq 'EOF'; | 
| 116 | 42 | 50 |  |  |  | 102 | next unless defined $c_end; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 42 | 100 | 100 |  |  | 426 | $end = $c_end | 
|  |  |  | 100 |  |  |  |  | 
| 119 |  |  |  |  |  |  | if ($c_end =~ m/^\d+$/ && $c_end > $end) | 
| 120 |  |  |  |  |  |  | || "$c_end" eq 'EOF'; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 29 | 100 |  |  |  | 102 | if ("$end" eq 'EOF') { | 
| 124 | 1 | 50 |  |  |  | 4 | $start -= 1 if $start != $self->{+START_LINE}; | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  | else { | 
| 127 | 28 | 100 | 100 |  |  | 163 | $start -= 1 if $start != $end && $start != $self->{+START_LINE}; | 
| 128 | 28 | 100 | 100 |  |  | 174 | $end   += 1 if $end != $start && $end   != $self->{+END_LINE}; | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 29 |  |  |  |  | 54 | $self->{+START_LINE} = $start; | 
| 132 | 29 |  |  |  |  | 89 | $self->{+END_LINE}   = $end; | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | sub add_post { | 
| 136 | 27 |  |  | 27 | 1 | 59 | my $self = shift; | 
| 137 | 27 | 50 |  |  |  | 93 | confess "post units only apply to group units" | 
| 138 |  |  |  |  |  |  | unless $self->type eq 'group'; | 
| 139 | 27 |  | 100 |  |  | 225 | $self->{post} ||= []; | 
| 140 | 27 |  |  |  |  | 38 | push @{$self->{post}} => @_; | 
|  | 27 |  |  |  |  | 101 |  | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | sub debug { | 
| 144 | 745 |  |  | 745 | 1 | 1017 | my $self = shift; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 745 |  |  |  |  | 2073 | my $stack = Test::Stream::Sync->stack; | 
| 147 | 745 |  |  |  |  | 2006 | my $hub   = $stack->top; | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | return Test::Stream::DebugInfo->new( | 
| 150 |  |  |  |  |  |  | frame       => [@$self{qw/package file start_line name/}], | 
| 151 |  |  |  |  |  |  | skip        => $self->meta->{skip}, | 
| 152 | 745 |  |  |  |  | 3978 | detail => "in block '$self->{+NAME}' defined in $self->{+FILE} (Approx) lines $self->{+START_LINE} -> $self->{+END_LINE}", | 
| 153 |  |  |  |  |  |  | $hub->debug_todo, | 
| 154 |  |  |  |  |  |  | ); | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | sub context { | 
| 158 | 745 |  |  | 745 | 1 | 1069 | my $self = shift; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 745 |  |  |  |  | 2723 | my $stack = Test::Stream::Sync->stack; | 
| 161 | 745 |  |  |  |  | 2277 | my $hub   = $stack->top; | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 745 |  |  |  |  | 998 | my $ref; | 
| 164 | 745 | 100 |  |  |  | 2115 | if(my $todo = $self->meta->{todo}) { | 
| 165 | 9 |  |  |  |  | 74 | $ref = $hub->set_todo($todo); | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 | 745 |  |  |  |  | 4074 | my $dbg = $self->debug; | 
| 169 |  |  |  |  |  |  |  | 
| 170 | 745 |  |  |  |  | 3901 | my $ctx = Test::Stream::Context->new( | 
| 171 |  |  |  |  |  |  | stack => $stack, | 
| 172 |  |  |  |  |  |  | hub   => $hub, | 
| 173 |  |  |  |  |  |  | debug => $dbg, | 
| 174 |  |  |  |  |  |  | ); | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | # Stash the todo ref in the context so that it goes away with the context | 
| 177 | 745 |  |  |  |  | 1364 | $ctx->{_todo_ref} = $ref; | 
| 178 |  |  |  |  |  |  |  | 
| 179 | 745 |  |  |  |  | 1947 | return $ctx; | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | 1; | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | __END__ |