| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test::Stream::Hub; | 
| 2 | 109 |  |  | 109 |  | 693 | use strict; | 
|  | 109 |  |  |  |  | 113 |  | 
|  | 109 |  |  |  |  | 2388 |  | 
| 3 | 109 |  |  | 109 |  | 327 | use warnings; | 
|  | 109 |  |  |  |  | 102 |  | 
|  | 109 |  |  |  |  | 2247 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 109 |  |  | 109 |  | 308 | use Carp qw/carp croak/; | 
|  | 109 |  |  |  |  | 114 |  | 
|  | 109 |  |  |  |  | 4288 |  | 
| 6 | 109 |  |  | 109 |  | 35866 | use Test::Stream::State(); | 
|  | 109 |  |  |  |  | 172 |  | 
|  | 109 |  |  |  |  | 1984 |  | 
| 7 | 109 |  |  | 109 |  | 494 | use Test::Stream::Util qw/get_tid/; | 
|  | 109 |  |  |  |  | 104 |  | 
|  | 109 |  |  |  |  | 554 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 109 |  |  | 109 |  | 421 | use Scalar::Util qw/weaken/; | 
|  | 109 |  |  |  |  | 114 |  | 
|  | 109 |  |  |  |  | 5360 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | use Test::Stream::HashBase( | 
| 12 | 109 |  |  |  |  | 460 | accessors => [qw{ | 
| 13 |  |  |  |  |  |  | pid tid hid ipc | 
| 14 |  |  |  |  |  |  | state | 
| 15 |  |  |  |  |  |  | no_ending | 
| 16 |  |  |  |  |  |  | _todo _meta parent_todo | 
| 17 |  |  |  |  |  |  | _mungers | 
| 18 |  |  |  |  |  |  | _filters | 
| 19 |  |  |  |  |  |  | _listeners | 
| 20 |  |  |  |  |  |  | _follow_ups | 
| 21 |  |  |  |  |  |  | _formatter | 
| 22 |  |  |  |  |  |  | _context_init | 
| 23 |  |  |  |  |  |  | _context_release | 
| 24 |  |  |  |  |  |  | }], | 
| 25 | 109 |  |  | 109 |  | 389 | ); | 
|  | 109 |  |  |  |  | 122 |  | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | my $ID_POSTFIX = 1; | 
| 28 |  |  |  |  |  |  | sub init { | 
| 29 | 524 |  |  | 524 | 0 | 620 | my $self = shift; | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 524 |  |  |  |  | 1480 | $self->{+PID} = $$; | 
| 32 | 524 |  |  |  |  | 790 | $self->{+TID} = get_tid(); | 
| 33 | 524 |  |  |  |  | 1781 | $self->{+HID} = join '-', $self->{+PID}, $self->{+TID}, $ID_POSTFIX++; | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 524 |  |  |  |  | 947 | $self->{+_TODO} = []; | 
| 36 | 524 |  |  |  |  | 847 | $self->{+_META} = {}; | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 524 |  | 33 |  |  | 3422 | $self->{+STATE} ||= Test::Stream::State->new; | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 524 | 100 |  |  |  | 1154 | if (my $formatter = delete $self->{formatter}) { | 
| 41 | 5 |  |  |  |  | 14 | $self->format($formatter); | 
| 42 |  |  |  |  |  |  | } | 
| 43 |  |  |  |  |  |  |  | 
| 44 | 524 | 100 |  |  |  | 1357 | if (my $ipc = $self->{+IPC}) { | 
| 45 | 137 |  |  |  |  | 415 | $ipc->add_hub($self->{+HID}); | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | sub inherit { | 
| 50 | 241 |  |  | 241 | 1 | 253 | my $self = shift; | 
| 51 | 241 |  |  |  |  | 287 | my ($from, %params) = @_; | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | $self->{+_FORMATTER} = $from->{+_FORMATTER} | 
| 54 | 241 | 100 | 33 |  |  | 967 | unless $self->{+_FORMATTER} || exists($params{formatter}); | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 241 | 100 | 66 |  |  | 1460 | if ($from->{+IPC} && !$self->{+IPC} && !exists($params{ipc})) { | 
|  |  |  | 100 |  |  |  |  | 
| 57 | 233 |  |  |  |  | 238 | my $ipc = $from->{+IPC}; | 
| 58 | 233 |  |  |  |  | 436 | $self->{+IPC} = $ipc; | 
| 59 | 233 |  |  |  |  | 670 | $ipc->add_hub($self->{+HID}); | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  |  | 
| 62 | 241 | 100 |  |  |  | 823 | if (my $ls = $from->{+_LISTENERS}) { | 
| 63 | 222 |  |  |  |  | 254 | push @{$self->{+_LISTENERS}} => grep { $_->{inherit} } @$ls; | 
|  | 222 |  |  |  |  | 710 |  | 
|  | 295 |  |  |  |  | 524 |  | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  |  | 
| 66 | 241 | 50 |  |  |  | 528 | if (my $ms = $from->{+_MUNGERS}) { | 
| 67 | 0 |  |  |  |  | 0 | push @{$self->{+_MUNGERS}} => grep { $_->{inherit} } @$ms; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 68 |  |  |  |  |  |  | } | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 241 | 100 |  |  |  | 809 | if (my $fs = $from->{+_FILTERS}) { | 
| 71 | 12 |  |  |  |  | 9 | push @{$self->{+_FILTERS}} => grep { $_->{inherit} } @$fs; | 
|  | 12 |  |  |  |  | 36 |  | 
|  | 6 |  |  |  |  | 24 |  | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | sub debug_todo { | 
| 76 | 4014 |  |  | 4014 | 0 | 7069 | my ($self) = @_; | 
| 77 | 4014 |  |  |  |  | 4440 | my $array = $self->{+_TODO}; | 
| 78 | 4014 |  | 100 |  |  | 8273 | pop @$array while @$array && !defined $array->[-1]; | 
| 79 |  |  |  |  |  |  | return ( | 
| 80 |  |  |  |  |  |  | parent_todo => $self->{+PARENT_TODO}, | 
| 81 | 4014 | 100 |  |  |  | 22482 | todo        => @$array ? ${$array->[-1]} : undef, | 
|  | 17 |  |  |  |  | 95 |  | 
| 82 |  |  |  |  |  |  | ) | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | sub meta { | 
| 86 | 7 |  |  | 7 | 1 | 22 | my $self = shift; | 
| 87 | 7 |  |  |  |  | 11 | my ($key, $default) = @_; | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 7 | 100 |  |  |  | 161 | croak "Invalid key '" . (defined($key) ? $key : '(UNDEF)') . "'" | 
|  |  | 100 |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | unless $key; | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 5 |  |  |  |  | 30 | my $exists = $self->{+_META}->{$key}; | 
| 93 | 5 | 100 | 100 |  |  | 88 | return undef unless $default || $exists; | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 4 | 100 |  |  |  | 9 | $self->{+_META}->{$key} = $default unless $exists; | 
| 96 |  |  |  |  |  |  |  | 
| 97 | 4 |  |  |  |  | 12 | return $self->{+_META}->{$key}; | 
| 98 |  |  |  |  |  |  | } | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | sub delete_meta { | 
| 101 | 3 |  |  | 3 | 1 | 14 | my $self = shift; | 
| 102 | 3 |  |  |  |  | 3 | my ($key) = @_; | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 3 | 100 |  |  |  | 139 | croak "Invalid key '" . (defined($key) ? $key : '(UNDEF)') . "'" | 
|  |  | 100 |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | unless $key; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 1 |  |  |  |  | 2 | delete $self->{+_META}->{$key}; | 
| 108 |  |  |  |  |  |  | } | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | sub set_todo { | 
| 111 | 22 |  |  | 22 | 1 | 79 | my $self = shift; | 
| 112 | 22 |  |  |  |  | 34 | my ($reason) = @_; | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 22 | 100 |  |  |  | 54 | unless (defined wantarray) { | 
| 115 | 1 |  |  |  |  | 101 | carp "set_todo(...) called in void context, todo not set!"; | 
| 116 | 1 |  |  |  |  | 2 | return; | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 21 | 100 |  |  |  | 50 | unless(defined $reason) { | 
| 120 | 1 |  |  |  |  | 67 | carp "set_todo() called with undefined argument, todo not set!"; | 
| 121 | 1 |  |  |  |  | 3 | return; | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 20 |  |  |  |  | 35 | my $ref = \$reason; | 
| 125 | 20 |  |  |  |  | 29 | push @{$self->{+_TODO}} => $ref; | 
|  | 20 |  |  |  |  | 44 |  | 
| 126 | 20 |  |  |  |  | 63 | weaken($self->{+_TODO}->[-1]); | 
| 127 | 20 |  |  |  |  | 42 | return $ref; | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | sub get_todo { | 
| 131 | 6 |  |  | 6 | 1 | 20 | my $self = shift; | 
| 132 | 6 |  |  |  |  | 6 | my $array = $self->{+_TODO}; | 
| 133 | 6 |  | 100 |  |  | 31 | pop @$array while @$array && !defined($array->[-1]); | 
| 134 | 6 | 100 |  |  |  | 18 | return undef unless @$array; | 
| 135 | 3 |  |  |  |  | 3 | return ${$array->[-1]}; | 
|  | 3 |  |  |  |  | 15 |  | 
| 136 |  |  |  |  |  |  | } | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | sub format { | 
| 139 | 599 |  |  | 599 | 1 | 683 | my $self = shift; | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 599 |  |  |  |  | 761 | my $old = $self->{+_FORMATTER}; | 
| 142 | 599 | 100 |  |  |  | 1506 | ($self->{+_FORMATTER}) = @_ if @_; | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 599 |  |  |  |  | 2062 | return $old; | 
| 145 |  |  |  |  |  |  | } | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | sub is_local { | 
| 148 | 317 |  |  | 317 | 0 | 255 | my $self = shift; | 
| 149 |  |  |  |  |  |  | return $$ == $self->{+PID} | 
| 150 | 317 |  | 33 |  |  | 1996 | && get_tid() == $self->{+TID}; | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | sub listen { | 
| 154 | 684 |  |  | 684 | 1 | 709 | my $self = shift; | 
| 155 | 684 |  |  |  |  | 915 | my ($sub, %params) = @_; | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | carp "Useless addition of a listener in a child process or thread!" | 
| 158 | 684 | 50 | 33 |  |  | 3194 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 684 | 100 | 66 |  |  | 2715 | croak "listen only takes coderefs for arguments, got '$sub'" | 
| 161 |  |  |  |  |  |  | unless ref $sub && ref $sub eq 'CODE'; | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 683 |  |  |  |  | 571 | push @{$self->{+_LISTENERS}} => { %params, code => $sub }; | 
|  | 683 |  |  |  |  | 2007 |  | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 683 |  |  |  |  | 1328 | $sub; # Intentional return. | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | sub unlisten { | 
| 169 | 314 |  |  | 314 | 1 | 320 | my $self = shift; | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | carp "Useless removal of a listener in a child process or thread!" | 
| 172 | 314 | 50 | 33 |  |  | 1337 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 173 |  |  |  |  |  |  |  | 
| 174 | 314 |  |  |  |  | 421 | my %subs = map {$_ => $_} @_; | 
|  | 314 |  |  |  |  | 1047 |  | 
| 175 |  |  |  |  |  |  |  | 
| 176 | 314 |  |  |  |  | 302 | @{$self->{+_LISTENERS}} = grep { !$subs{$_->{code}} } @{$self->{+_LISTENERS}}; | 
|  | 314 |  |  |  |  | 1849 |  | 
|  | 652 |  |  |  |  | 1107 |  | 
|  | 314 |  |  |  |  | 431 |  | 
| 177 |  |  |  |  |  |  | } | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | sub munge { | 
| 180 | 4 |  |  | 4 | 1 | 30 | my $self = shift; | 
| 181 | 4 |  |  |  |  | 6 | my ($sub, %params) = @_; | 
| 182 |  |  |  |  |  |  |  | 
| 183 | 4 |  |  |  |  | 287 | carp "use of mungers is deprecated, look at filters instead. mungers will be removed in the near future."; | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | carp "Useless addition of a munger in a child process or thread!" | 
| 186 | 4 | 50 | 33 |  |  | 270 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 187 |  |  |  |  |  |  |  | 
| 188 | 4 | 100 | 66 |  |  | 107 | croak "munge only takes coderefs for arguments, got '$sub'" | 
| 189 |  |  |  |  |  |  | unless ref $sub && ref $sub eq 'CODE'; | 
| 190 |  |  |  |  |  |  |  | 
| 191 | 3 |  |  |  |  | 5 | push @{$self->{+_MUNGERS}} => { %params, code => $sub }; | 
|  | 3 |  |  |  |  | 10 |  | 
| 192 |  |  |  |  |  |  |  | 
| 193 | 3 |  |  |  |  | 7 | $sub; # Intentional Return | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | sub unmunge { | 
| 197 | 1 |  |  | 1 | 1 | 6 | my $self = shift; | 
| 198 |  |  |  |  |  |  | carp "Useless removal of a munger in a child process or thread!" | 
| 199 | 1 | 50 | 33 |  |  | 11 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 200 | 1 |  |  |  |  | 3 | my %subs = map {$_ => $_} @_; | 
|  | 1 |  |  |  |  | 3 |  | 
| 201 | 1 |  |  |  |  | 2 | @{$self->{+_MUNGERS}} = grep { !$subs{$_->{code}} } @{$self->{+_MUNGERS}}; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | sub filter { | 
| 205 | 10 |  |  | 10 | 0 | 48 | my $self = shift; | 
| 206 | 10 |  |  |  |  | 18 | my ($sub, %params) = @_; | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | carp "Useless addition of a filter in a child process or thread!" | 
| 209 | 10 | 50 | 33 |  |  | 58 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 210 |  |  |  |  |  |  |  | 
| 211 | 10 | 100 | 66 |  |  | 174 | croak "filter only takes coderefs for arguments, got '$sub'" | 
| 212 |  |  |  |  |  |  | unless ref $sub && ref $sub eq 'CODE'; | 
| 213 |  |  |  |  |  |  |  | 
| 214 | 9 |  |  |  |  | 8 | push @{$self->{+_FILTERS}} => { %params, code => $sub }; | 
|  | 9 |  |  |  |  | 41 |  | 
| 215 |  |  |  |  |  |  |  | 
| 216 | 9 |  |  |  |  | 25 | $sub; # Intentional Return | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | sub unfilter { | 
| 220 | 1 |  |  | 1 | 0 | 5 | my $self = shift; | 
| 221 |  |  |  |  |  |  | carp "Useless removal of a filter in a child process or thread!" | 
| 222 | 1 | 50 | 33 |  |  | 12 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 223 | 1 |  |  |  |  | 2 | my %subs = map {$_ => $_} @_; | 
|  | 1 |  |  |  |  | 5 |  | 
| 224 | 1 |  |  |  |  | 2 | @{$self->{+_FILTERS}} = grep { !$subs{$_->{code}} } @{$self->{+_FILTERS}}; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | sub follow_up { | 
| 228 | 38 |  |  | 38 | 0 | 73 | my $self = shift; | 
| 229 | 38 |  |  |  |  | 53 | my ($sub) = @_; | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | carp "Useless addition of a follow-up in a child process or thread!" | 
| 232 | 38 | 50 | 33 |  |  | 263 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 233 |  |  |  |  |  |  |  | 
| 234 | 38 | 100 | 66 |  |  | 467 | croak "follow_up only takes coderefs for arguments, got '$sub'" | 
| 235 |  |  |  |  |  |  | unless ref $sub && ref $sub eq 'CODE'; | 
| 236 |  |  |  |  |  |  |  | 
| 237 | 36 |  |  |  |  | 54 | push @{$self->{+_FOLLOW_UPS}} => $sub; | 
|  | 36 |  |  |  |  | 119 |  | 
| 238 |  |  |  |  |  |  | } | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | sub add_context_init { | 
| 241 | 1 |  |  | 1 | 1 | 8 | my $self = shift; | 
| 242 | 1 |  |  |  |  | 2 | my ($sub) = @_; | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 1 | 50 | 33 |  |  | 6 | croak "add_context_init only takes coderefs for arguments, got '$sub'" | 
| 245 |  |  |  |  |  |  | unless ref $sub && ref $sub eq 'CODE'; | 
| 246 |  |  |  |  |  |  |  | 
| 247 | 1 |  |  |  |  | 2 | push @{$self->{+_CONTEXT_INIT}} => $sub; | 
|  | 1 |  |  |  |  | 4 |  | 
| 248 |  |  |  |  |  |  |  | 
| 249 | 1 |  |  |  |  | 3 | $sub; # Intentional return. | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | sub remove_context_init { | 
| 253 | 1 |  |  | 1 | 1 | 6 | my $self = shift; | 
| 254 | 1 |  |  |  |  | 2 | my %subs = map {$_ => $_} @_; | 
|  | 1 |  |  |  |  | 5 |  | 
| 255 | 1 |  |  |  |  | 2 | @{$self->{+_CONTEXT_INIT}} = grep { !$subs{$_} == $_ } @{$self->{+_CONTEXT_INIT}}; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | sub add_context_release { | 
| 259 | 1 |  |  | 1 | 1 | 6 | my $self = shift; | 
| 260 | 1 |  |  |  |  | 2 | my ($sub) = @_; | 
| 261 |  |  |  |  |  |  |  | 
| 262 | 1 | 50 | 33 |  |  | 11 | croak "add_context_release only takes coderefs for arguments, got '$sub'" | 
| 263 |  |  |  |  |  |  | unless ref $sub && ref $sub eq 'CODE'; | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 1 |  |  |  |  | 1 | push @{$self->{+_CONTEXT_RELEASE}} => $sub; | 
|  | 1 |  |  |  |  | 3 |  | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 1 |  |  |  |  | 2 | $sub; # Intentional return. | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | sub remove_context_release { | 
| 271 | 1 |  |  | 1 | 1 | 4 | my $self = shift; | 
| 272 | 1 |  |  |  |  | 1 | my %subs = map {$_ => $_} @_; | 
|  | 1 |  |  |  |  | 3 |  | 
| 273 | 1 |  |  |  |  | 2 | @{$self->{+_CONTEXT_RELEASE}} = grep { !$subs{$_} == $_ } @{$self->{+_CONTEXT_RELEASE}}; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 274 |  |  |  |  |  |  | } | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | sub send { | 
| 277 | 3636 |  |  | 3636 | 1 | 4608 | my $self = shift; | 
| 278 | 3636 |  |  |  |  | 3164 | my ($e) = @_; | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 3636 |  | 100 |  |  | 6787 | my $ipc = $self->{+IPC} || return $self->process($e); | 
| 281 |  |  |  |  |  |  |  | 
| 282 | 3528 | 100 |  |  |  | 7747 | if($e->global) { | 
| 283 | 25 |  |  |  |  | 77 | $ipc->send('GLOBAL', $e); | 
| 284 | 25 |  |  |  |  | 81 | return $self->process($e); | 
| 285 |  |  |  |  |  |  | } | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | return $ipc->send($self->{+HID}, $e) | 
| 288 | 3503 | 100 | 66 |  |  | 14050 | if $$ != $self->{+PID} || get_tid() != $self->{+TID}; | 
| 289 |  |  |  |  |  |  |  | 
| 290 | 3497 |  |  |  |  | 7037 | $self->process($e); | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | sub process { | 
| 294 | 3635 |  |  | 3635 | 1 | 2907 | my $self = shift; | 
| 295 | 3635 |  |  |  |  | 2942 | my ($e) = @_; | 
| 296 |  |  |  |  |  |  |  | 
| 297 | 3635 | 100 |  |  |  | 5518 | if ($self->{+_MUNGERS}) { | 
| 298 | 6 |  |  |  |  | 5 | for (@{$self->{+_MUNGERS}}) { | 
|  | 6 |  |  |  |  | 14 |  | 
| 299 | 8 |  |  |  |  | 14 | $_->{code}->($self, $e); | 
| 300 | 8 | 100 |  |  |  | 23 | return unless $e; | 
| 301 |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  | } | 
| 303 |  |  |  |  |  |  |  | 
| 304 | 3632 | 100 |  |  |  | 4946 | if ($self->{+_FILTERS}) { | 
| 305 | 12 |  |  |  |  | 18 | for (@{$self->{+_FILTERS}}) { | 
|  | 12 |  |  |  |  | 25 |  | 
| 306 | 14 |  |  |  |  | 31 | $e = $_->{code}->($self, $e); | 
| 307 | 14 | 100 |  |  |  | 70 | return unless $e; | 
| 308 |  |  |  |  |  |  | } | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  |  | 
| 311 | 3623 |  |  |  |  | 3118 | my $state = $self->{+STATE}; | 
| 312 | 3623 |  |  |  |  | 7791 | $e->update_state($state); | 
| 313 | 3623 |  |  |  |  | 7829 | my $count = $state->count; | 
| 314 |  |  |  |  |  |  |  | 
| 315 | 3623 | 100 |  |  |  | 13360 | $self->{+_FORMATTER}->write($e, $count) if $self->{+_FORMATTER}; | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 3623 | 100 |  |  |  | 8067 | if ($self->{+_LISTENERS}) { | 
| 318 | 2044 |  |  |  |  | 1487 | $_->{code}->($self, $e, $count) for @{$self->{+_LISTENERS}}; | 
|  | 2044 |  |  |  |  | 7035 |  | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  |  | 
| 321 | 3623 |  |  |  |  | 8718 | my $code = $e->terminate; | 
| 322 | 3623 | 100 |  |  |  | 5587 | $self->terminate($code, $e) if defined $code; | 
| 323 |  |  |  |  |  |  |  | 
| 324 | 3597 |  |  |  |  | 11305 | return $e; | 
| 325 |  |  |  |  |  |  | } | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | sub terminate { | 
| 328 | 3 |  |  | 3 | 0 | 4 | my $self = shift; | 
| 329 | 3 |  |  |  |  | 4 | my ($code) = @_; | 
| 330 | 3 |  |  |  |  | 22 | exit($code); | 
| 331 |  |  |  |  |  |  | } | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  | sub cull { | 
| 334 | 816 |  |  | 816 | 1 | 813 | my $self = shift; | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 816 |  | 100 |  |  | 1758 | my $ipc = $self->{+IPC} || return; | 
| 337 | 794 | 50 | 33 |  |  | 3472 | return if $self->{+PID} != $$ || $self->{+TID} != get_tid(); | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | # No need to do IPC checks on culled events | 
| 340 | 794 |  |  |  |  | 2319 | $self->process($_) for $ipc->cull($self->{+HID}); | 
| 341 |  |  |  |  |  |  | } | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | sub finalize { | 
| 344 | 349 |  |  | 349 | 0 | 3661 | my $self = shift; | 
| 345 | 349 |  |  |  |  | 821 | my ($dbg, $do_plan) = @_; | 
| 346 |  |  |  |  |  |  |  | 
| 347 | 349 |  |  |  |  | 802 | $self->cull(); | 
| 348 | 349 |  |  |  |  | 591 | my $state = $self->{+STATE}; | 
| 349 |  |  |  |  |  |  |  | 
| 350 | 349 |  |  |  |  | 1483 | my $plan   = $state->plan; | 
| 351 | 349 |  |  |  |  | 933 | my $count  = $state->count; | 
| 352 | 349 |  |  |  |  | 1323 | my $failed = $state->failed; | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | # return if NOTHING was done. | 
| 355 | 349 | 100 | 100 |  |  | 1567 | return unless $do_plan || defined($plan) || $count || $failed; | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 356 |  |  |  |  |  |  |  | 
| 357 | 337 | 100 |  |  |  | 1036 | unless ($state->ended) { | 
| 358 | 335 | 100 |  |  |  | 1591 | if ($self->{+_FOLLOW_UPS}) { | 
| 359 | 33 |  |  |  |  | 50 | $_->($dbg, $self) for reverse @{$self->{+_FOLLOW_UPS}}; | 
|  | 33 |  |  |  |  | 171 |  | 
| 360 |  |  |  |  |  |  | } | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | # These need to be refreshed now | 
| 363 | 334 |  |  |  |  | 753 | $plan   = $state->plan; | 
| 364 | 334 |  |  |  |  | 707 | $count  = $state->count; | 
| 365 | 334 |  |  |  |  | 1018 | $failed = $state->failed; | 
| 366 |  |  |  |  |  |  |  | 
| 367 | 334 | 100 | 100 |  |  | 2676 | if (($plan && $plan eq 'NO PLAN') || ($do_plan && !$plan)) { | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 368 | 317 |  |  |  |  | 2054 | $self->send( | 
| 369 |  |  |  |  |  |  | Test::Stream::Event::Plan->new( | 
| 370 |  |  |  |  |  |  | debug => $dbg, | 
| 371 |  |  |  |  |  |  | max => $count, | 
| 372 |  |  |  |  |  |  | ) | 
| 373 |  |  |  |  |  |  | ); | 
| 374 | 317 |  |  |  |  | 1180 | $plan = $state->plan; | 
| 375 |  |  |  |  |  |  | } | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  |  | 
| 378 | 336 |  |  |  |  | 1045 | $state->finish($dbg->frame); | 
| 379 |  |  |  |  |  |  | } | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | sub DESTROY { | 
| 382 | 415 |  |  | 415 |  | 726 | my $self = shift; | 
| 383 | 415 |  | 100 |  |  | 1132 | my $ipc = $self->{+IPC} || return; | 
| 384 | 381 | 100 |  |  |  | 1058 | return unless $$ == $self->{+PID}; | 
| 385 | 380 | 50 |  |  |  | 718 | return unless get_tid() == $self->{+TID}; | 
| 386 |  |  |  |  |  |  |  | 
| 387 | 380 |  |  |  |  | 994 | local $?; | 
| 388 | 380 |  |  |  |  | 1154 | $ipc->drop_hub($self->{+HID}); | 
| 389 |  |  |  |  |  |  | } | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | 1; | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | __END__ |