| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test::Stream::Workflow::Unit; | 
| 2 | 95 |  |  | 95 |  | 1043 | use strict; | 
|  | 95 |  |  |  |  | 191 |  | 
|  | 95 |  |  |  |  | 2461 |  | 
| 3 | 95 |  |  | 95 |  | 468 | use warnings; | 
|  | 95 |  |  |  |  | 180 |  | 
|  | 95 |  |  |  |  | 2227 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 95 |  |  | 95 |  | 484 | use Test::Stream::Sync; | 
|  | 95 |  |  |  |  | 186 |  | 
|  | 95 |  |  |  |  | 1920 |  | 
| 6 | 95 |  |  | 95 |  | 545 | use Test::Stream::Context(); | 
|  | 95 |  |  |  |  | 184 |  | 
|  | 95 |  |  |  |  | 1659 |  | 
| 7 | 95 |  |  | 95 |  | 526 | use Test::Stream::DebugInfo; | 
|  | 95 |  |  |  |  | 215 |  | 
|  | 95 |  |  |  |  | 2778 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 95 |  |  | 95 |  | 514 | use Carp qw/confess/; | 
|  | 95 |  |  |  |  | 250 |  | 
|  | 95 |  |  |  |  | 4390 |  | 
| 10 | 95 |  |  | 95 |  | 499 | use Scalar::Util qw/reftype/; | 
|  | 95 |  |  |  |  | 183 |  | 
|  | 95 |  |  |  |  | 5949 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | use Test::Stream::HashBase( | 
| 13 | 95 |  |  |  |  | 952 | 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 |  | 532 | ); | 
|  | 95 |  |  |  |  | 211 |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | sub init { | 
| 26 | 344 |  | 100 | 344 | 0 | 1794 | $_[0]->{+META} ||= {}; | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 344 |  |  |  |  | 946 | for (NAME, PACKAGE, FILE, START_LINE, END_LINE) { | 
| 29 | 1716 | 100 |  |  |  | 5544 | confess "$_ is a required attribute" unless defined $_[0]->{$_} | 
| 30 |  |  |  |  |  |  | } | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 343 |  | 100 |  |  | 1878 | $_[0]->{+STASH} ||= {}; | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | sub contains { | 
| 36 | 14 |  |  | 14 | 1 | 31 | my $self = shift; | 
| 37 | 14 |  |  |  |  | 24 | my ($thing) = @_; | 
| 38 | 14 |  |  |  |  | 19 | my ($file, $line, $name); | 
| 39 | 14 | 100 |  |  |  | 68 | if ($thing =~ m/^(\S+) (\d+)$/) { | 
|  |  | 100 |  |  |  |  |  | 
| 40 | 2 |  |  |  |  | 7 | ($file, $line) = ($1, $2); | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  | elsif ($thing =~ m/^\d+$/) { | 
| 43 | 6 |  |  |  |  | 11 | $line = $thing; | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  | else { | 
| 46 | 6 |  |  |  |  | 10 | $name = $thing; | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 14 |  |  |  |  | 32 | return $self->_contains($file, $line, $name); | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | sub _contains { | 
| 53 | 16 |  |  | 16 |  | 21 | my $self = shift; | 
| 54 | 16 |  |  |  |  | 23 | my ($file, $line, $name) = @_; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 16 |  | 100 |  |  | 55 | 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 |  |  | 83 | && ($self->{+END_LINE} . "" eq 'EOF' || $line <= $self->{+END_LINE}) | 
| 62 |  |  |  |  |  |  | ); | 
| 63 |  |  |  |  |  |  |  | 
| 64 | 16 |  |  |  |  | 18 | my $child_ok = 0; | 
| 65 | 16 |  |  |  |  | 40 | for my $stash (MODIFY(), BUILDUP(), PRIMARY(), TEARDOWN()) { | 
| 66 | 64 |  | 100 |  |  | 328 | my $set = $self->$stash || next; | 
| 67 | 2 | 50 | 33 |  |  | 22 | 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 |  |  | 234 | return $child_ok || ($name_ok && $file_ok && $line_ok); | 
| 74 |  |  |  |  |  |  | } | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | sub do_post { | 
| 77 | 54 |  |  | 54 | 1 | 263 | my $self = shift; | 
| 78 |  |  |  |  |  |  |  | 
| 79 | 54 | 100 |  |  |  | 283 | my $post = delete $self->{+POST} or return; | 
| 80 | 19 |  |  |  |  | 101 | $_->($self) for @$post; | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | for my $type (MODIFY(), BUILDUP(), PRIMARY(), TEARDOWN()) { | 
| 84 | 95 |  |  | 95 |  | 603 | no strict 'refs'; | 
|  | 95 |  |  |  |  | 225 |  | 
|  | 95 |  |  |  |  | 4907 |  | 
| 85 |  |  |  |  |  |  | *{"add_$type"} = sub { | 
| 86 | 95 |  |  | 95 |  | 526 | use strict; | 
|  | 95 |  |  |  |  | 217 |  | 
|  | 95 |  |  |  |  | 64708 |  | 
| 87 | 264 |  |  | 264 |  | 433 | my $self = shift; | 
| 88 | 264 |  | 100 |  |  | 873 | $self->{$type} ||= []; | 
| 89 | 264 |  |  |  |  | 344 | push @{$self->{$type}} => @_; | 
|  | 264 |  |  |  |  | 1668 |  | 
| 90 |  |  |  |  |  |  | }; | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | sub adjust_lines { | 
| 94 | 29 |  |  | 29 | 1 | 66 | my $self = shift; | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 29 |  |  |  |  | 57 | my $start = $self->{+START_LINE}; | 
| 97 | 29 |  |  |  |  | 53 | my $end   = $self->{+END_LINE}; | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 29 |  |  |  |  | 82 | for my $stash (MODIFY(), BUILDUP(), PRIMARY(), TEARDOWN()) { | 
| 100 | 116 | 100 |  |  |  | 366 | my $list = $self->{$stash} or next; | 
| 101 | 42 | 50 |  |  |  | 108 | next unless ref $list; | 
| 102 | 42 | 50 |  |  |  | 170 | next unless reftype($list) eq 'ARRAY'; | 
| 103 | 42 | 50 |  |  |  | 104 | next unless @$list; | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 42 | 50 |  |  |  | 115 | my $top = $list->[0] or next; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 42 |  |  |  |  | 140 | my $c_start = $top->start_line; | 
| 108 | 42 |  |  |  |  | 218 | my $c_end   = $top->end_line; | 
| 109 |  |  |  |  |  |  |  | 
| 110 | 42 | 100 | 33 |  |  | 499 | $start = $c_start | 
|  |  |  | 66 |  |  |  |  | 
| 111 |  |  |  |  |  |  | if defined($c_start) | 
| 112 |  |  |  |  |  |  | && $c_start =~ m/^\d+$/ | 
| 113 |  |  |  |  |  |  | && $c_start < $start; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 42 | 50 | 33 |  |  | 229 | next if $end && "$end" eq 'EOF'; | 
| 116 | 42 | 50 |  |  |  | 99 | next unless defined $c_end; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 42 | 100 | 100 |  |  | 469 | $end = $c_end | 
|  |  |  | 100 |  |  |  |  | 
| 119 |  |  |  |  |  |  | if ($c_end =~ m/^\d+$/ && $c_end > $end) | 
| 120 |  |  |  |  |  |  | || "$c_end" eq 'EOF'; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 29 | 100 |  |  |  | 101 | if ("$end" eq 'EOF') { | 
| 124 | 1 | 50 |  |  |  | 10 | $start -= 1 if $start != $self->{+START_LINE}; | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  | else { | 
| 127 | 28 | 100 | 100 |  |  | 157 | $start -= 1 if $start != $end && $start != $self->{+START_LINE}; | 
| 128 | 28 | 100 | 100 |  |  | 167 | $end   += 1 if $end != $start && $end   != $self->{+END_LINE}; | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 29 |  |  |  |  | 58 | $self->{+START_LINE} = $start; | 
| 132 | 29 |  |  |  |  | 85 | $self->{+END_LINE}   = $end; | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | sub add_post { | 
| 136 | 27 |  |  | 27 | 1 | 63 | my $self = shift; | 
| 137 | 27 | 50 |  |  |  | 96 | confess "post units only apply to group units" | 
| 138 |  |  |  |  |  |  | unless $self->type eq 'group'; | 
| 139 | 27 |  | 100 |  |  | 247 | $self->{post} ||= []; | 
| 140 | 27 |  |  |  |  | 40 | push @{$self->{post}} => @_; | 
|  | 27 |  |  |  |  | 106 |  | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | sub debug { | 
| 144 | 745 |  |  | 745 | 1 | 1067 | my $self = shift; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 745 |  |  |  |  | 2098 | my $stack = Test::Stream::Sync->stack; | 
| 147 | 745 |  |  |  |  | 2125 | 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 |  |  |  |  | 4261 | 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 | 1099 | my $self = shift; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 745 |  |  |  |  | 2964 | my $stack = Test::Stream::Sync->stack; | 
| 161 | 745 |  |  |  |  | 2459 | my $hub   = $stack->top; | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 745 |  |  |  |  | 1061 | my $ref; | 
| 164 | 745 | 100 |  |  |  | 2205 | if(my $todo = $self->meta->{todo}) { | 
| 165 | 9 |  |  |  |  | 77 | $ref = $hub->set_todo($todo); | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 | 745 |  |  |  |  | 4175 | my $dbg = $self->debug; | 
| 169 |  |  |  |  |  |  |  | 
| 170 | 745 |  |  |  |  | 4121 | 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 |  |  |  |  | 1350 | $ctx->{_todo_ref} = $ref; | 
| 178 |  |  |  |  |  |  |  | 
| 179 | 745 |  |  |  |  | 2044 | return $ctx; | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | 1; | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | __END__ |