File Coverage

inc/Test/Builder.pm
Criterion Covered Total %
statement 295 911 32.3
branch 71 428 16.5
condition 25 252 9.9
subroutine 55 114 48.2
pod 48 53 90.5
total 494 1758 28.1


line stmt bran cond sub pod time code
1             #line 1
2              
3 6     6   82 use 5.006;
  6         19  
4 6     6   44 use strict;
  6         10  
  6         98  
5 6     6   23 use warnings;
  6         9  
  6         403  
6              
7             our $VERSION = '1.302170';
8              
9             BEGIN {
10 6 50   6   184 if( $] < 5.008 ) {
11 0         0 require Test::Builder::IO::Scalar;
12             }
13             }
14              
15 6     6   28 use Scalar::Util qw/blessed reftype weaken/;
  6         10  
  6         816  
16              
17 6     6   2671 use Test2::Util qw/USE_THREADS try get_tid/;
  6         59348  
  6         530  
18 6     6   3679 use Test2::API qw/context release/;
  6         53140  
  6         1003  
19             # Make Test::Builder thread-safe for ithreads.
20             BEGIN {
21 6 50 33 6   38 warn "Test::Builder was loaded after Test2 initialization, this is not recommended."
22             if Test2::API::test2_init_done() || Test2::API::test2_load_done();
23              
24 6         239 if (USE_THREADS && ! Test2::API::test2_ipc_disabled()) {
25             require Test2::IPC;
26             require Test2::IPC::Driver::Files;
27             Test2::IPC::Driver::Files->import;
28             Test2::API::test2_ipc_enable_polling();
29             Test2::API::test2_no_wait(1);
30             }
31             }
32              
33 6     6   47 use Test2::Event::Subtest;
  6         21  
  6         169  
34 6     6   27 use Test2::Hub::Subtest;
  6         13  
  6         195  
35              
36 6     6   2902 use Test::Builder::Formatter;
  6         31262  
  6         50  
37 6     6   3145 use Test::Builder::TodoDiag;
  6         1270  
  6         620  
38              
39             our $Level = 1;
40             our $Test = $ENV{TB_NO_EARLY_INIT} ? undef : Test::Builder->new;
41              
42             my $self = shift;
43 6     6   11  
44             my $hub = $self->{Stack}->top;
45 6         22  
46             # Take a reference to the hash key, we do this to avoid closing over $self
47             # which is the singleton. We use a reference because the value could change
48             # in rare cases.
49             my $epkgr = \$self->{Exported_To};
50 6         38  
51             #$hub->add_context_aquire(sub {$_[0]->{level} += $Level - 1});
52              
53             $hub->pre_filter(sub {
54             my ($active_hub, $e) = @_;
55 22     22   3279  
56             my $epkg = $$epkgr;
57 22         53 my $cpkg = $e->{trace} ? $e->{trace}->{frame}->[0] : undef;
58 22 50       76  
59             no strict 'refs';
60 6     6   36 no warnings 'once';
  6         11  
  6         170  
61 6     6   27 my $todo;
  6         12  
  6         1566  
62 22         33 $todo = ${"$cpkg\::TODO"} if $cpkg;
63 22 50       58 $todo = ${"$epkg\::TODO"} if $epkg && !$todo;
  22         90  
64 22 50 33     109  
  22         69  
65             return $e unless defined($todo);
66 22 50       73 return $e unless length($todo);
67 0 0       0  
68             # Turn a diag into a todo diag
69             return Test::Builder::TodoDiag->new(%$e) if ref($e) eq 'Test2::Event::Diag';
70 0 0       0  
71             $e->set_todo($todo) if $e->can('set_todo');
72 0 0       0 $e->add_amnesty({tag => 'TODO', details => $todo});
73 0         0  
74             # Set todo on ok's
75             if ($e->isa('Test2::Event::Ok')) {
76 0 0       0 $e->set_effective_pass(1);
77 0         0  
78             if (my $result = $e->get_meta(__PACKAGE__)) {
79 0 0       0 $result->{reason} ||= $todo;
80 0   0     0 $result->{type} ||= 'todo';
81 0   0     0 $result->{ok} = 1;
82 0         0 }
83             }
84              
85             return $e;
86 0         0 }, inherit => 1);
87 6         53 }
88              
89             {
90             no warnings;
91 6     6   37 INIT {
  6         17  
  6         250  
92             use warnings;
93 6     6   32 Test2::API::test2_load() unless Test2::API::test2_in_preload();
  6         12  
  6         17675  
94 6 50   6   497 }
95             }
96              
97             my($class) = shift;
98             unless($Test) {
99 36     36 1 85 $Test = $class->create(singleton => 1);
100 36 100       127  
101 6         24 Test2::API::test2_add_callback_post_load(
102             sub {
103             $Test->{Original_Pid} = $$ if !$Test->{Original_Pid} || $Test->{Original_Pid} == 0;
104             $Test->reset(singleton => 1);
105 6 50 33 6   941 $Test->_add_ts_hooks;
106 6         28 }
107 6         54 );
108              
109 6         44 # Non-TB tools normally expect 0 added to the level. $Level is normally 1. So
110             # we only want the level to change if $Level != 1.
111             # TB->ctx compensates for this later.
112             Test2::API::test2_add_callback_context_aquire(sub { $_[0]->{level} += $Level - 1 });
113              
114 6     73   165 Test2::API::test2_add_callback_exit(sub { $Test->_ending(@_) });
  73         4429  
115              
116 6     6   148 Test2::API::test2_ipc()->set_no_fatal(1) if Test2::API::test2_has_ipc();
  6         2268  
117             }
118 6 50       105 return $Test;
119             }
120 36         136  
121             my $class = shift;
122             my %params = @_;
123              
124 6     6 1 12 my $self = bless {}, $class;
125 6         27 if ($params{singleton}) {
126             $self->{Stack} = Test2::API::test2_stack();
127 6         22 }
128 6 50       31 else {
129 6         33 $self->{Stack} = Test2::API::Stack->new;
130             $self->{Stack}->new_hub(
131             formatter => Test::Builder::Formatter->new,
132 0         0 ipc => Test2::API::test2_ipc(),
133             );
134 0         0  
135             $self->reset(%params);
136             $self->_add_ts_hooks;
137             }
138 0         0  
139 0         0 return $self;
140             }
141              
142 6         123 my $self = shift;
143             context(
144             # 1 for our frame, another for the -1 off of $Level in our hook at the top.
145             level => 2,
146 73     73 0 109 fudge => 1,
147             stack => $self->{Stack},
148             hub => $self->{Hub},
149             wrapped => 1,
150             @_
151             );
152             }
153 73         347  
154             my $self = shift;
155             my $ctx = $self->ctx;
156             my $chub = $self->{Hub} || $ctx->hub;
157             $ctx->release;
158              
159 0     0 0 0 my $meta = $chub->meta(__PACKAGE__, {});
160 0         0 my $parent = $meta->{parent};
161 0   0     0  
162 0         0 return undef unless $parent;
163              
164 0         0 return bless {
165 0         0 Original_Pid => $$,
166             Stack => $self->{Stack},
167 0 0       0 Hub => $parent,
168             }, blessed($self);
169             }
170              
171             my( $self, $name ) = @_;
172 0         0  
173             $name ||= "Child of " . $self->name;
174             my $ctx = $self->ctx;
175              
176             my $parent = $ctx->hub;
177 0     0 0 0 my $pmeta = $parent->meta(__PACKAGE__, {});
178             $self->croak("You already have a child named ($pmeta->{child}) running")
179 0   0     0 if $pmeta->{child};
180 0         0  
181             $pmeta->{child} = $name;
182 0         0  
183 0         0 # Clear $TODO for the child.
184             my $orig_TODO = $self->find_TODO(undef, 1, undef);
185 0 0       0  
186             my $subevents = [];
187 0         0  
188             my $hub = $ctx->stack->new_hub(
189             class => 'Test2::Hub::Subtest',
190 0         0 );
191              
192 0         0 $hub->pre_filter(sub {
193             my ($active_hub, $e) = @_;
194 0         0  
195             # Turn a diag into a todo diag
196             return Test::Builder::TodoDiag->new(%$e) if ref($e) eq 'Test2::Event::Diag';
197              
198             return $e;
199 0     0   0 }, inherit => 1) if $orig_TODO;
200              
201             $hub->listen(sub { push @$subevents => $_[1] });
202 0 0       0  
203             $hub->set_nested( $parent->nested + 1 );
204 0         0  
205 0 0       0 my $meta = $hub->meta(__PACKAGE__, {});
206             $meta->{Name} = $name;
207 0     0   0 $meta->{TODO} = $orig_TODO;
  0         0  
208             $meta->{TODO_PKG} = $ctx->trace->package;
209 0         0 $meta->{parent} = $parent;
210             $meta->{Test_Results} = [];
211 0         0 $meta->{subevents} = $subevents;
212 0         0 $meta->{subtest_id} = $hub->id;
213 0         0 $meta->{subtest_uuid} = $hub->uuid;
214 0         0 $meta->{subtest_buffered} = $parent->format ? 0 : 1;
215 0         0  
216 0         0 $self->_add_ts_hooks;
217 0         0  
218 0         0 $ctx->release;
219 0         0 return bless { Original_Pid => $$, Stack => $self->{Stack}, Hub => $hub, no_log_results => $self->{no_log_results} }, blessed($self);
220 0 0       0 }
221              
222 0         0 my $self = shift;
223             my $ok = 1;
224 0         0 ($ok) = @_ if @_;
225 0         0  
226             my $st_ctx = $self->ctx;
227             my $chub = $self->{Hub} || return $st_ctx->release;
228              
229 0     0 0 0 my $meta = $chub->meta(__PACKAGE__, {});
230 0         0 if ($meta->{child}) {
231 0 0       0 $self->croak("Can't call finalize() with child ($meta->{child}) active");
232             }
233 0         0  
234 0   0     0 local $? = 0; # don't fail if $subtests happened to set $? nonzero
235              
236 0         0 $self->{Stack}->pop($chub);
237 0 0       0  
238 0         0 $self->find_TODO($meta->{TODO_PKG}, 1, $meta->{TODO});
239              
240             my $parent = $self->parent;
241 0         0 my $ctx = $parent->ctx;
242             my $trace = $ctx->trace;
243 0         0 delete $ctx->hub->meta(__PACKAGE__, {})->{child};
244              
245 0         0 $chub->finalize($trace->snapshot(hid => $chub->hid, nested => $chub->nested), 1)
246             if $ok
247 0         0 && $chub->count
248 0         0 && !$chub->no_ending
249 0         0 && !$chub->ended;
250 0         0  
251             my $plan = $chub->plan || 0;
252 0 0 0     0 my $count = $chub->count;
      0        
      0        
253             my $failed = $chub->failed;
254             my $passed = $chub->is_passing;
255              
256             my $num_extra = $plan =~ m/\D/ ? 0 : $count - $plan;
257             if ($count && $num_extra != 0) {
258 0   0     0 my $s = $plan == 1 ? '' : 's';
259 0         0 $st_ctx->diag(<<"FAIL");
260 0         0 Looks like you planned $plan test$s but ran $count.
261 0         0 FAIL
262             }
263 0 0       0  
264 0 0 0     0 if ($failed) {
265 0 0       0 my $s = $failed == 1 ? '' : 's';
266 0         0  
267             my $qualifier = $num_extra == 0 ? '' : ' run';
268              
269             $st_ctx->diag(<<"FAIL");
270             Looks like you failed $failed test$s of $count$qualifier.
271 0 0       0 FAIL
272 0 0       0 }
273              
274 0 0       0 if (!$passed && !$failed && $count && !$num_extra) {
275             $st_ctx->diag(<<"FAIL");
276 0         0 All assertions inside the subtest passed, but errors were encountered.
277             FAIL
278             }
279              
280             $st_ctx->release;
281 0 0 0     0  
      0        
      0        
282 0         0 unless ($chub->bailed_out) {
283             my $plan = $chub->plan;
284             if ( $plan && $plan eq 'SKIP' ) {
285             $parent->skip($chub->skip_reason, $meta->{Name});
286             }
287 0         0 elsif ( !$chub->count ) {
288             $parent->ok( 0, sprintf q[No tests run for subtest "%s"], $meta->{Name} );
289 0 0       0 }
290 0         0 else {
291 0 0 0     0 $parent->{subevents} = $meta->{subevents};
    0          
292 0         0 $parent->{subtest_id} = $meta->{subtest_id};
293             $parent->{subtest_uuid} = $meta->{subtest_uuid};
294             $parent->{subtest_buffered} = $meta->{subtest_buffered};
295 0         0 $parent->ok( $chub->is_passing, $meta->{Name} );
296             }
297             }
298 0         0  
299 0         0 $ctx->release;
300 0         0 return $chub->is_passing;
301 0         0 }
302 0         0  
303             my $self = shift;
304             my ($name, $code, @args) = @_;
305             my $ctx = $self->ctx;
306 0         0 $ctx->throw("subtest()'s second argument must be a code ref")
307 0         0 unless $code && reftype($code) eq 'CODE';
308              
309             $name ||= "Child of " . $self->name;
310              
311 0     0 1 0  
312 0         0 $_->($name,$code,@args)
313 0         0 for Test2::API::test2_list_pre_subtest_callbacks();
314 0 0 0     0  
315             $ctx->note("Subtest: $name");
316              
317 0   0     0 my $child = $self->child($name);
318              
319             my $start_pid = $$;
320             my $st_ctx;
321 0         0 my ($ok, $err, $finished, $child_error);
322             T2_SUBTEST_WRAPPER: {
323 0         0 my $ctx = $self->ctx;
324             $st_ctx = $ctx->snapshot;
325 0         0 $ctx->release;
326             $ok = eval { local $Level = 1; $code->(@args); 1 };
327 0         0 ($err, $child_error) = ($@, $?);
328 0         0  
329 0         0 # They might have done 'BEGIN { skip_all => "whatever" }'
330             if (!$ok && $err =~ m/Label not found for "last T2_SUBTEST_WRAPPER"/ || (blessed($err) && blessed($err) eq 'Test::Builder::Exception')) {
331 0         0 $ok = undef;
  0         0  
332 0         0 $err = undef;
333 0         0 }
334 0         0 else {
  0         0  
  0         0  
  0         0  
335 0         0 $finished = 1;
336             }
337             }
338 0 0 0     0  
      0        
      0        
339 0         0 if ($start_pid != $$ && !$INC{'Test2/IPC.pm'}) {
340 0         0 warn $ok ? "Forked inside subtest, but subtest never finished!\n" : $err;
341             exit 255;
342             }
343 0         0  
344             my $trace = $ctx->trace;
345              
346             if (!$finished) {
347 0 0 0     0 if(my $bailed = $st_ctx->hub->bailed_out) {
348 0 0       0 my $chub = $child->{Hub};
349 0         0 $self->{Stack}->pop($chub);
350             $ctx->bail($bailed->reason);
351             }
352 0         0 my $code = $st_ctx->hub->exit_code;
353             $ok = !$code;
354 0 0       0 $err = "Subtest ended with exit code $code" if $code;
355 0 0       0 }
356 0         0  
357 0         0 my $st_hub = $st_ctx->hub;
358 0         0 my $plan = $st_hub->plan;
359             my $count = $st_hub->count;
360 0         0  
361 0         0 if (!$count && (!defined($plan) || "$plan" ne 'SKIP')) {
362 0 0       0 $st_ctx->plan(0) unless defined $plan;
363             $st_ctx->diag('No tests run!');
364             }
365 0         0  
366 0         0 $child->finalize($st_ctx->trace);
367 0         0  
368             $ctx->release;
369 0 0 0     0  
      0        
370 0 0       0 die $err unless $ok;
371 0         0  
372             $? = $child_error if defined $child_error;
373              
374 0         0 return $st_hub->is_passing;
375             }
376 0         0  
377             my $self = shift;
378 0 0       0 my $ctx = $self->ctx;
379             release $ctx, $ctx->hub->meta(__PACKAGE__, {})->{Name};
380 0 0       0 }
381              
382 0         0 my ($self, %params) = @_;
383              
384             Test2::API::test2_unset_is_end();
385              
386 0     0 1 0 # We leave this a global because it has to be localized and localizing
387 0         0 # hash keys is just asking for pain. Also, it was documented.
388 0         0 $Level = 1;
389              
390             $self->{no_log_results} = $ENV{TEST_NO_LOG_RESULTS} ? 1 : 0
391             unless $params{singleton};
392 6     6 1 25  
393             $self->{Original_Pid} = Test2::API::test2_in_preload() ? -1 : $$;
394 6         33  
395             my $ctx = $self->ctx;
396             my $hub = $ctx->hub;
397             $ctx->release;
398 6         31 unless ($params{singleton}) {
399             $hub->reset_state();
400             $hub->_tb_reset();
401 6 0       24 }
    50          
402              
403 6 50       17 $ctx = $self->ctx;
404              
405 6         53 my $meta = $ctx->hub->meta(__PACKAGE__, {});
406 6         610 %$meta = (
407 6         64 Name => $0,
408 6 50       183 Ending => 0,
409 0         0 Done_Testing => undef,
410 0         0 Skip_All => 0,
411             Test_Results => [],
412             parent => $meta->{parent},
413 6         19 );
414              
415 6         501 $self->{Exported_To} = undef unless $params{singleton};
416              
417             $self->{Orig_Handles} ||= do {
418             my $format = $ctx->hub->format;
419             my $out;
420             if ($format && $format->isa('Test2::Formatter::TAP')) {
421             $out = $format->handles;
422             }
423 6         204 $out ? [@$out] : [];
424             };
425 6 50       32  
426             $self->use_numbers(1);
427 6   33     27 $self->no_header(0) unless $params{singleton};
428 6         48 $self->no_ending(0) unless $params{singleton};
429 6         58 $self->reset_outputs;
430 6 50 33     121  
431 6         69 $ctx->release;
432              
433 6 50       49 return;
434             }
435              
436 6         30  
437 6 50       168 my %plan_cmds = (
438 6 50       21 no_plan => \&no_plan,
439 6         30 skip_all => \&skip_all,
440             tests => \&_plan_tests,
441 6         38 );
442              
443 6         123 my( $self, $cmd, $arg ) = @_;
444              
445             return unless $cmd;
446              
447             my $ctx = $self->ctx;
448             my $hub = $ctx->hub;
449              
450             $ctx->throw("You tried to plan twice") if $hub->plan;
451              
452             local $Level = $Level + 1;
453              
454 1     1 1 2 if( my $method = $plan_cmds{$cmd} ) {
455             local $Level = $Level + 1;
456 1 50       2 $self->$method($arg);
457             }
458 1         3 else {
459 1         55 my @args = grep { defined } ( $cmd, $arg );
460             $ctx->throw("plan() doesn't understand @args");
461 1 50       5 }
462              
463 1         7 release $ctx, 1;
464             }
465 1 50       10  
466 1         2  
467 1         2 my($self, $arg) = @_;
468              
469             my $ctx = $self->ctx;
470 0         0  
  0         0  
471 0         0 if($arg) {
472             local $Level = $Level + 1;
473             $self->expected_tests($arg);
474 1         12 }
475             elsif( !defined $arg ) {
476             $ctx->throw("Got an undefined number of tests");
477             }
478             else {
479 3     3   7 $ctx->throw("You said to run 0 tests");
480             }
481 3         18  
482             $ctx->release;
483 3 50       130 }
    0          
484 3         7  
485 3         10  
486             my $self = shift;
487             my($max) = @_;
488 0         0  
489             my $ctx = $self->ctx;
490              
491 0         0 if(@_) {
492             $self->croak("Number of tests must be a positive integer. You gave it '$max'")
493             unless $max =~ /^\+?\d+$/;
494 3         24  
495             $ctx->plan($max);
496             }
497              
498             my $hub = $ctx->hub;
499 3     3 1 5  
500 3         7 $ctx->release;
501              
502 3         7 my $plan = $hub->plan;
503             return 0 unless $plan;
504 3 50       99 return 0 if $plan =~ m/\D/;
505 3 50       21 return $plan;
506             }
507              
508 3         23  
509             my($self, $arg) = @_;
510              
511 3         1163 my $ctx = $self->ctx;
512              
513 3         543 if (defined $ctx->hub->plan) {
514             warn "Plan already set, no_plan() is a no-op, this will change to a hard failure in the future.";
515 3         45 $ctx->release;
516 3 50       20 return;
517 3 50       15 }
518 3         15  
519             $ctx->alert("no_plan takes no arguments") if $arg;
520              
521             $ctx->hub->plan('NO PLAN');
522              
523 0     0 1 0 release $ctx, 1;
524             }
525 0         0  
526              
527 0 0       0 my($self, $num_tests) = @_;
528 0         0  
529 0         0 my $ctx = $self->ctx;
530 0         0  
531             my $meta = $ctx->hub->meta(__PACKAGE__, {});
532              
533 0 0       0 if ($meta->{Done_Testing}) {
534             my ($file, $line) = @{$meta->{Done_Testing}}[1,2];
535 0         0 local $ctx->hub->{ended}; # OMG This is awful.
536             $self->ok(0, "done_testing() was already called at $file line $line");
537 0         0 $ctx->release;
538             return;
539             }
540             $meta->{Done_Testing} = [$ctx->trace->call];
541              
542 0     0 1 0 my $plan = $ctx->hub->plan;
543             my $count = $ctx->hub->count;
544 0         0  
545             # If done_testing() specified the number of tests, shut off no_plan
546 0         0 if( defined $num_tests ) {
547             $ctx->plan($num_tests) if !$plan || $plan eq 'NO PLAN';
548 0 0       0 }
549 0         0 elsif ($count && defined $num_tests && $count != $num_tests) {
  0         0  
550 0         0 $self->ok(0, "planned to run @{[ $self->expected_tests ]} but done_testing() expects $num_tests");
551 0         0 }
552 0         0 else {
553 0         0 $num_tests = $self->current_test;
554             }
555 0         0  
556             if( $self->expected_tests && $num_tests != $self->expected_tests ) {
557 0         0 $self->ok(0, "planned to run @{[ $self->expected_tests ]} ".
558 0         0 "but done_testing() expects $num_tests");
559             }
560              
561 0 0 0     0 $ctx->plan($num_tests) if $ctx->hub->plan && $ctx->hub->plan eq 'NO PLAN';
    0 0        
562 0 0 0     0  
563             $ctx->hub->finalize($ctx->trace, 1);
564              
565 0         0 release $ctx, 1;
  0         0  
566             }
567              
568 0         0  
569             my $self = shift;
570              
571 0 0 0     0 my $ctx = $self->ctx;
572 0         0 my $plan = $ctx->hub->plan;
  0         0  
573             $ctx->release;
574              
575             return( $plan ) if $plan && $plan !~ m/\D/;
576 0 0 0     0 return('no_plan') if $plan && $plan eq 'NO PLAN';
577             return(undef);
578 0         0 }
579              
580 0         0  
581             my( $self, $reason ) = @_;
582              
583             my $ctx = $self->ctx;
584              
585 0     0 1 0 $ctx->hub->meta(__PACKAGE__, {})->{Skip_All} = $reason || 1;
586              
587 0         0 # Work around old perl bug
588 0         0 if ($] < 5.020000) {
589 0         0 my $begin = 0;
590             my $level = 0;
591 0 0 0     0 while (my @call = caller($level++)) {
592 0 0 0     0 last unless @call && $call[0];
593 0         0 next unless $call[3] =~ m/::BEGIN$/;
594             $begin++;
595             last;
596             }
597             # HACK!
598 3     3 1 12 die 'Label not found for "last T2_SUBTEST_WRAPPER"' if $begin && $ctx->hub->meta(__PACKAGE__, {})->{parent};
599             }
600 3         9  
601             $ctx->plan(0, SKIP => $reason);
602 3   50     213 }
603              
604              
605 3 50       101 my( $self, $pack ) = @_;
606 0         0  
607 0         0 if( defined $pack ) {
608 0         0 $self->{Exported_To} = $pack;
609 0 0 0     0 }
610 0 0       0 return $self->{Exported_To};
611 0         0 }
612 0         0  
613              
614             my( $self, $test, $name ) = @_;
615 0 0 0     0  
616             my $ctx = $self->ctx;
617              
618 3         23 # $test might contain an object which we don't want to accidentally
619             # store, so we turn it into a boolean.
620             $test = $test ? 1 : 0;
621              
622             # In case $name is a string overloaded object, force it to stringify.
623 12     12 1 28 no warnings qw/uninitialized numeric/;
624             $name = "$name" if defined $name;
625 12 100       69  
626 6         18 # Profiling showed that the regex here was a huge time waster, doing the
627             # numeric addition first cuts our profile time from ~300ms to ~50ms
628 12         26 $self->diag(<<" ERR") if 0 + $name && $name =~ /^[\d\s]+$/;
629             You named your test '$name'. You shouldn't use numbers for your test names.
630             Very confusing.
631             ERR
632             use warnings qw/uninitialized numeric/;
633 12     12 1 27  
634             my $trace = $ctx->{trace};
635 12         45 my $hub = $ctx->{hub};
636              
637             my $result = {
638             ok => $test,
639 12 50       493 actual_ok => $test,
640             reason => '',
641             type => '',
642 6     6   75 (name => defined($name) ? $name : ''),
  6         12  
  6         856  
643 12 50       36 };
644              
645             $hub->{_meta}->{+__PACKAGE__}->{Test_Results}[ $hub->{count} ] = $result unless $self->{no_log_results};
646              
647 12 50 33     70 my $orig_name = $name;
648              
649             my @attrs;
650             my $subevents = delete $self->{subevents};
651 6     6   41 my $subtest_id = delete $self->{subtest_id};
  6         12  
  6         3908  
652             my $subtest_uuid = delete $self->{subtest_uuid};
653 12         24 my $subtest_buffered = delete $self->{subtest_buffered};
654 12         18 my $epkg = 'Test2::Event::Ok';
655             if ($subevents) {
656 12 50       64 $epkg = 'Test2::Event::Subtest';
657             push @attrs => (subevents => $subevents, subtest_id => $subtest_id, subtest_uuid => $subtest_uuid, buffered => $subtest_buffered);
658             }
659              
660             my $e = bless {
661             trace => bless( {%$trace}, 'Test2::EventFacet::Trace'),
662             pass => $test,
663             name => $name,
664 12 50       56 _meta => {'Test::Builder' => $result},
665             effective_pass => $test,
666 12         20 @attrs,
667             }, $epkg;
668 12         15 $hub->send($e);
669 12         22  
670 12         19 $self->_ok_debug($trace, $orig_name) unless($test);
671 12         20  
672 12         15 $ctx->release;
673 12         17 return $test;
674 12 50       28 }
675 0         0  
676 0         0 my $self = shift;
677             my ($trace, $orig_name) = @_;
678              
679 12         124 my $is_todo = $self->in_todo;
680              
681             my $msg = $is_todo ? "Failed (TODO)" : "Failed";
682              
683             my (undef, $file, $line) = $trace->call;
684             if (defined $orig_name) {
685             $self->diag(qq[ $msg test '$orig_name'\n at $file line $line.\n]);
686             }
687 12         58 else {
688             $self->diag(qq[ $msg test at $file line $line.\n]);
689 12 50       3000 }
690             }
691 12         66  
692 12         243 my $self = shift;
693             local $Level = $Level + 1;
694             return $self->in_todo ? $self->todo_output : $self->failure_output;
695             }
696 0     0   0  
697 0         0 my ($self, $type, $thing) = @_;
698              
699 0         0 return unless ref $$thing;
700             return unless blessed($$thing) || scalar $self->_try(sub{ $$thing->isa('UNIVERSAL') });
701 0 0       0 {
702             local ($!, $@);
703 0         0 require overload;
704 0 0       0 }
705 0         0 my $string_meth = overload::Method( $$thing, $type ) || return;
706             $$thing = $$thing->$string_meth();
707             }
708 0         0  
709             my $self = shift;
710              
711             $self->_unoverload( q[""], $_ ) for @_;
712             }
713 0     0   0  
714 0         0 my $self = shift;
715 0 0       0  
716             $self->_unoverload( '0+', $_ ) for @_;
717              
718             for my $val (@_) {
719 8     8   298 next unless $self->_is_dualvar($$val);
720             $$val = $$val + 0;
721 8 50       16 }
722 8 0 50 0   28 }
  0         0  
723              
724 8         10 # This is a hack to detect a dualvar such as $!
  8         57  
725 8         51 my( $self, $val ) = @_;
726              
727 8   50     25 # Objects are not dualvars.
728 8         451 return 0 if ref $val;
729              
730             no warnings 'numeric';
731             my $numval = $val + 0;
732 4     4   23 return ($numval != 0 and $numval ne $val ? 1 : 0);
733             }
734 4         17  
735              
736             my( $self, $got, $expect, $name ) = @_;
737              
738 0     0   0 my $ctx = $self->ctx;
739              
740 0         0 local $Level = $Level + 1;
741              
742 0         0 if( !defined $got || !defined $expect ) {
743 0 0       0 # undef only matches undef and nothing else
744 0         0 my $test = !defined $got && !defined $expect;
745              
746             $self->ok( $test, $name );
747             $self->_is_diag( $got, 'eq', $expect ) unless $test;
748             $ctx->release;
749             return $test;
750 0     0   0 }
751              
752             release $ctx, $self->cmp_ok( $got, 'eq', $expect, $name );
753 0 0       0 }
754              
755 6     6   42  
  6         16  
  6         6452  
756 0         0 my( $self, $got, $expect, $name ) = @_;
757 0   0     0 my $ctx = $self->ctx;
758             local $Level = $Level + 1;
759              
760             if( !defined $got || !defined $expect ) {
761             # undef only matches undef and nothing else
762 11     11 1 29 my $test = !defined $got && !defined $expect;
763              
764 11         29 $self->ok( $test, $name );
765             $self->_is_diag( $got, '==', $expect ) unless $test;
766 11         784 $ctx->release;
767             return $test;
768 11 100 66     48 }
769              
770 1   33     8 release $ctx, $self->cmp_ok( $got, '==', $expect, $name );
771             }
772 1         4  
773 1 50       8  
774 1         4 my( $self, $type, $val ) = @_;
775 1         23  
776             if( defined $$val ) {
777             if( $type eq 'eq' or $type eq 'ne' ) {
778 10         34 # quote and force string context
779             $$val = "'$$val'";
780             }
781             else {
782             # force numeric context
783 0     0 1 0 $self->_unoverload_num($val);
784 0         0 }
785 0         0 }
786             else {
787 0 0 0     0 $$val = 'undef';
788             }
789 0   0     0  
790             return;
791 0         0 }
792 0 0       0  
793 0         0  
794 0         0 my( $self, $got, $type, $expect ) = @_;
795              
796             $self->_diag_fmt( $type, $_ ) for \$got, \$expect;
797 0         0  
798             local $Level = $Level + 1;
799             return $self->diag(<<"DIAGNOSTIC");
800             got: $got
801             expected: $expect
802 0     0   0 DIAGNOSTIC
803              
804 0 0       0 }
805 0 0 0     0  
806             my( $self, $got, $type ) = @_;
807 0         0  
808             $self->_diag_fmt( $type, \$got );
809              
810             local $Level = $Level + 1;
811 0         0 return $self->diag(<<"DIAGNOSTIC");
812             got: $got
813             expected: anything else
814             DIAGNOSTIC
815 0         0 }
816              
817              
818 0         0 my( $self, $got, $dont_expect, $name ) = @_;
819             my $ctx = $self->ctx;
820             local $Level = $Level + 1;
821              
822             if( !defined $got || !defined $dont_expect ) {
823 0     0   0 # undef only matches undef and nothing else
824             my $test = defined $got || defined $dont_expect;
825 0         0  
826             $self->ok( $test, $name );
827 0         0 $self->_isnt_diag( $got, 'ne' ) unless $test;
828 0         0 $ctx->release;
829             return $test;
830             }
831              
832             release $ctx, $self->cmp_ok( $got, 'ne', $dont_expect, $name );
833             }
834              
835             my( $self, $got, $dont_expect, $name ) = @_;
836 0     0   0 my $ctx = $self->ctx;
837             local $Level = $Level + 1;
838 0         0  
839             if( !defined $got || !defined $dont_expect ) {
840 0         0 # undef only matches undef and nothing else
841 0         0 my $test = defined $got || defined $dont_expect;
842              
843             $self->ok( $test, $name );
844             $self->_isnt_diag( $got, '!=' ) unless $test;
845             $ctx->release;
846             return $test;
847             }
848              
849 0     0 1 0 release $ctx, $self->cmp_ok( $got, '!=', $dont_expect, $name );
850 0         0 }
851 0         0  
852              
853 0 0 0     0 my( $self, $thing, $regex, $name ) = @_;
854             my $ctx = $self->ctx;
855 0   0     0  
856             local $Level = $Level + 1;
857 0         0  
858 0 0       0 release $ctx, $self->_regex_ok( $thing, $regex, '=~', $name );
859 0         0 }
860 0         0  
861             my( $self, $thing, $regex, $name ) = @_;
862             my $ctx = $self->ctx;
863 0         0  
864             local $Level = $Level + 1;
865              
866             release $ctx, $self->_regex_ok( $thing, $regex, '!~', $name );
867 0     0 1 0 }
868 0         0  
869 0         0  
870             my %numeric_cmps = map { ( $_, 1 ) } ( "<", "<=", ">", ">=", "==", "!=", "<=>" );
871 0 0 0     0  
872             # Bad, these are not comparison operators. Should we include more?
873 0   0     0 my %cmp_ok_bl = map { ( $_, 1 ) } ( "=", "+=", ".=", "x=", "^=", "|=", "||=", "&&=", "...");
874              
875 0         0 my( $self, $got, $type, $expect, $name ) = @_;
876 0 0       0 my $ctx = $self->ctx;
877 0         0  
878 0         0 if ($cmp_ok_bl{$type}) {
879             $ctx->throw("$type is not a valid comparison operator in cmp_ok()");
880             }
881 0         0  
882             my ($test, $succ);
883             my $error;
884             {
885             ## no critic (BuiltinFunctions::ProhibitStringyEval)
886 0     0 1 0  
887 0         0 local( $@, $!, $SIG{__DIE__} ); # isolate eval
888              
889 0         0 my($pack, $file, $line) = $ctx->trace->call();
890              
891 0         0 # This is so that warnings come out at the caller's level
892             $succ = eval qq[
893             #line $line "(eval in cmp_ok) $file"
894             \$test = (\$got $type \$expect);
895 0     0 1 0 1;
896 0         0 ];
897             $error = $@;
898 0         0 }
899             local $Level = $Level + 1;
900 0         0 my $ok = $self->ok( $test, $name );
901              
902             # Treat overloaded objects as numbers if we're asked to do a
903             # numeric comparison.
904             my $unoverload
905             = $numeric_cmps{$type}
906             ? '_unoverload_num'
907             : '_unoverload_str';
908              
909             $self->diag(<<"END") unless $succ;
910 10     10 1 25 An error occurred while using $type:
911 10         16 ------------------------------------
912             $error
913 10 50       364 ------------------------------------
914 0         0 END
915              
916             unless($ok) {
917 10         65 $self->$unoverload( \$got, \$expect );
918 10         0  
919             if( $type =~ /^(eq|==)$/ ) {
920             $self->_is_diag( $got, $type, $expect );
921             }
922 10         15 elsif( $type =~ /^(ne|!=)$/ ) {
  10         58  
923             no warnings;
924 10         42 my $eq = ($got eq $expect || $got == $expect)
925             && (
926             (defined($got) xor defined($expect))
927 10         787 || (length($got) != length($expect))
928             );
929             use warnings;
930              
931             if ($eq) {
932 10         153 $self->_cmp_diag( $got, $type, $expect );
933             }
934 10         20 else {
935 10         39 $self->_isnt_diag( $got, $type );
936             }
937             }
938             else {
939             $self->_cmp_diag( $got, $type, $expect );
940 10 50       74 }
941             }
942             return release $ctx, $ok;
943             }
944 10 50       44  
945             my( $self, $got, $type, $expect ) = @_;
946              
947             $got = defined $got ? "'$got'" : 'undef';
948             $expect = defined $expect ? "'$expect'" : 'undef';
949              
950             local $Level = $Level + 1;
951 10 50       20 return $self->diag(<<"DIAGNOSTIC");
952 0         0 $got
953             $type
954 0 0       0 $expect
    0          
955 0         0 DIAGNOSTIC
956             }
957              
958 6     6   47 my $self = shift;
  6         12  
  6         391  
959 0   0     0  
960             my( $pack, $file, $line ) = $self->caller(1);
961              
962             my $code = '';
963             $code .= "#line $line $file\n" if defined $file and defined $line;
964 6     6   49  
  6         20  
  6         1934  
965             return $code;
966 0 0       0 }
967 0         0  
968              
969             my( $self, $reason ) = @_;
970 0         0  
971             my $ctx = $self->ctx;
972              
973             $self->{Bailed_Out} = 1;
974 0         0  
975             $ctx->bail($reason);
976             }
977 10         34  
978              
979             {
980             no warnings 'once';
981 0     0   0 *BAILOUT = \&BAIL_OUT;
982             }
983 0 0       0  
984 0 0       0 my( $self, $why, $name ) = @_;
985             $why ||= '';
986 0         0 $name = '' unless defined $name;
987 0         0 $self->_unoverload_str( \$why );
988              
989             my $ctx = $self->ctx;
990              
991             $ctx->hub->meta(__PACKAGE__, {})->{Test_Results}[ $ctx->hub->count ] = {
992             'ok' => 1,
993             actual_ok => 1,
994             name => $name,
995 0     0   0 type => 'skip',
996             reason => $why,
997 0         0 } unless $self->{no_log_results};
998              
999 0         0 $name =~ s|#|\\#|g; # # in a name can confuse Test::Harness.
1000 0 0 0     0 $name =~ s{\n}{\n# }sg;
1001             $why =~ s{\n}{\n# }sg;
1002 0         0  
1003             my $tctx = $ctx->snapshot;
1004             $tctx->skip('', $why);
1005              
1006             return release $ctx, 1;
1007 0     0 1 0 }
1008              
1009 0         0  
1010             my( $self, $why ) = @_;
1011 0         0 $why ||= '';
1012              
1013 0         0 my $ctx = $self->ctx;
1014              
1015             $ctx->hub->meta(__PACKAGE__, {})->{Test_Results}[ $ctx->hub->count ] = {
1016             'ok' => 1,
1017             actual_ok => 0,
1018 6     6   81 name => '',
  6         15  
  6         4214  
1019             type => 'todo_skip',
1020             reason => $why,
1021             } unless $self->{no_log_results};
1022              
1023 0     0 1 0 $why =~ s{\n}{\n# }sg;
1024 0   0     0 my $tctx = $ctx->snapshot;
1025 0 0       0 $tctx->send_event( 'Skip', todo => $why, todo_diag => 1, reason => $why, pass => 0);
1026 0         0  
1027             return release $ctx, 1;
1028 0         0 }
1029              
1030              
1031             my( $self, $regex ) = @_;
1032             my $usable_regex = undef;
1033              
1034             return $usable_regex unless defined $regex;
1035              
1036 0 0       0 my( $re, $opts );
1037              
1038 0         0 # Check for qr/foo/
1039 0         0 if( _is_qr($regex) ) {
1040 0         0 $usable_regex = $regex;
1041             }
1042 0         0 # Check for '/foo/' or 'm,foo,'
1043 0         0 elsif(( $re, $opts ) = $regex =~ m{^ /(.*)/ (\w*) $ }sx or
1044             ( undef, $re, $opts ) = $regex =~ m,^ m([^\w\s]) (.+) \1 (\w*) $,sx
1045 0         0 )
1046             {
1047             $usable_regex = length $opts ? "(?$opts)$re" : $re;
1048             }
1049              
1050 0     0 1 0 return $usable_regex;
1051 0   0     0 }
1052              
1053 0         0 my $regex = shift;
1054              
1055             # is_regexp() checks for regexes in a robust manner, say if they're
1056             # blessed.
1057             return re::is_regexp($regex) if defined &re::is_regexp;
1058             return ref $regex eq 'Regexp';
1059             }
1060              
1061 0 0       0 my( $self, $thing, $regex, $cmp, $name ) = @_;
1062              
1063 0         0 my $ok = 0;
1064 0         0 my $usable_regex = $self->maybe_regex($regex);
1065 0         0 unless( defined $usable_regex ) {
1066             local $Level = $Level + 1;
1067 0         0 $ok = $self->ok( 0, $name );
1068             $self->diag(" '$regex' doesn't look much like a regex to me.");
1069             return $ok;
1070             }
1071              
1072 0     0 1 0 {
1073 0         0 my $test;
1074             my $context = $self->_caller_context;
1075 0 0       0  
1076             {
1077 0         0 ## no critic (BuiltinFunctions::ProhibitStringyEval)
1078              
1079             local( $@, $!, $SIG{__DIE__} ); # isolate eval
1080 0 0 0     0  
    0          
1081 0         0 # No point in issuing an uninit warning, they'll see it in the diagnostics
1082             no warnings 'uninitialized';
1083              
1084             $test = eval $context . q{$test = $thing =~ /$usable_regex/ ? 1 : 0};
1085             }
1086              
1087             $test = !$test if $cmp eq '!~';
1088 0 0       0  
1089             local $Level = $Level + 1;
1090             $ok = $self->ok( $test, $name );
1091 0         0 }
1092              
1093             unless($ok) {
1094             $thing = defined $thing ? "'$thing'" : 'undef';
1095 0     0   0 my $match = $cmp eq '=~' ? "doesn't match" : "matches";
1096              
1097             local $Level = $Level + 1;
1098             $self->diag( sprintf <<'DIAGNOSTIC', $thing, $match, $regex );
1099 0 0       0 %s
1100 0         0 %13s '%s'
1101             DIAGNOSTIC
1102              
1103             }
1104 0     0   0  
1105             return $ok;
1106 0         0 }
1107 0         0  
1108 0 0       0  
1109 0         0 my $self = shift;
1110 0         0 my $maybe_fh = shift;
1111 0         0 return 0 unless defined $maybe_fh;
1112 0         0  
1113             return 1 if ref $maybe_fh eq 'GLOB'; # its a glob ref
1114             return 1 if ref \$maybe_fh eq 'GLOB'; # its a glob
1115              
1116 0         0 return eval { $maybe_fh->isa("IO::Handle") } ||
  0         0  
1117 0         0 eval { tied($maybe_fh)->can('TIEHANDLE') };
1118             }
1119              
1120              
1121             my( $self, $level ) = @_;
1122 0         0  
  0         0  
1123             if( defined $level ) {
1124             $Level = $level;
1125 6     6   47 }
  6         11  
  6         3002  
1126             return $Level;
1127 0         0 }
1128              
1129              
1130 0 0       0 my( $self, $use_nums ) = @_;
1131              
1132 0         0 my $ctx = $self->ctx;
1133 0         0 my $format = $ctx->hub->format;
1134             unless ($format && $format->can('no_numbers') && $format->can('set_no_numbers')) {
1135             warn "The current formatter does not support 'use_numbers'" if $format;
1136 0 0       0 return release $ctx, 0;
1137 0 0       0 }
1138 0 0       0  
1139             $format->set_no_numbers(!$use_nums) if defined $use_nums;
1140 0         0  
1141 0         0 return release $ctx, $format->no_numbers ? 0 : 1;
1142             }
1143              
1144             BEGIN {
1145             for my $method (qw(no_header no_diag)) {
1146             my $set = "set_$method";
1147             my $code = sub {
1148 0         0 my( $self, $no ) = @_;
1149              
1150             my $ctx = $self->ctx;
1151             my $format = $ctx->hub->format;
1152             unless ($format && $format->can($set)) {
1153 0     0 1 0 warn "The current formatter does not support '$method'" if $format;
1154 0         0 $ctx->release;
1155 0 0       0 return
1156             }
1157 0 0       0  
1158 0 0       0 $format->$set($no) if defined $no;
1159              
1160             return release $ctx, $format->$method ? 1 : 0;
1161 0   0     0 };
1162              
1163             no strict 'refs'; ## no critic
1164             *$method = $code;
1165             }
1166 0     0 1 0 }
1167              
1168 0 0       0 my( $self, $no ) = @_;
1169 0         0  
1170             my $ctx = $self->ctx;
1171 0         0  
1172             $ctx->hub->set_no_ending($no) if defined $no;
1173              
1174             return release $ctx, $ctx->hub->no_ending;
1175             }
1176 6     6 1 19  
1177             my $self = shift;
1178 6         29 return unless @_;
1179 6         324  
1180 6 50 33     136 my $text = join '' => map {defined($_) ? $_ : 'undef'} @_;
      33        
1181 0 0       0  
1182 0         0 if (Test2::API::test2_in_preload()) {
1183             chomp($text);
1184             $text =~ s/^/# /msg;
1185 6 50       41 print STDERR $text, "\n";
1186             return 0;
1187 6 50       51 }
1188              
1189             my $ctx = $self->ctx;
1190             $ctx->diag($text);
1191 6     6   19 $ctx->release;
1192 12         31 return 0;
1193             }
1194 0     0   0  
1195              
1196 0         0 my $self = shift;
1197 0         0 return unless @_;
1198 0 0 0     0  
1199 0 0       0 my $text = join '' => map {defined($_) ? $_ : 'undef'} @_;
1200 0         0  
1201             if (Test2::API::test2_in_preload()) {
1202 0         0 chomp($text);
1203             $text =~ s/^/# /msg;
1204 0 0       0 print STDOUT $text, "\n";
1205             return 0;
1206 0 0       0 }
1207 12         54  
1208             my $ctx = $self->ctx;
1209 6     6   46 $ctx->note($text);
  6         12  
  6         206  
1210 12         8324 $ctx->release;
1211             return 0;
1212             }
1213              
1214              
1215 0     0 1 0 my $self = shift;
1216              
1217 0         0 local ($@, $!);
1218             require Data::Dumper;
1219 0 0       0  
1220             return map {
1221 0         0 ref $_
1222             ? do {
1223             my $dumper = Data::Dumper->new( [$_] );
1224             $dumper->Indent(1)->Terse(1);
1225 1     1 1 2 $dumper->Sortkeys(1) if $dumper->can("Sortkeys");
1226 1 50       4 $dumper->Dump;
1227             }
1228 1 50       2 : $_
  1         7  
1229             } @_;
1230 1 50       5 }
1231 0         0  
1232 0         0  
1233 0         0 my( $self, $fh ) = @_;
1234 0         0  
1235             my $ctx = $self->ctx;
1236             my $format = $ctx->hub->format;
1237 1         46 $ctx->release;
1238 1         90 return unless $format && $format->isa('Test2::Formatter::TAP');
1239 1         278  
1240 1         35 $format->handles->[Test2::Formatter::TAP::OUT_STD()] = $self->_new_fh($fh)
1241             if defined $fh;
1242              
1243             return $format->handles->[Test2::Formatter::TAP::OUT_STD()];
1244             }
1245 0     0 1 0  
1246 0 0       0 my( $self, $fh ) = @_;
1247              
1248 0 0       0 my $ctx = $self->ctx;
  0         0  
1249             my $format = $ctx->hub->format;
1250 0 0       0 $ctx->release;
1251 0         0 return unless $format && $format->isa('Test2::Formatter::TAP');
1252 0         0  
1253 0         0 $format->handles->[Test2::Formatter::TAP::OUT_ERR()] = $self->_new_fh($fh)
1254 0         0 if defined $fh;
1255              
1256             return $format->handles->[Test2::Formatter::TAP::OUT_ERR()];
1257 0         0 }
1258 0         0  
1259 0         0 my( $self, $fh ) = @_;
1260 0         0  
1261             my $ctx = $self->ctx;
1262             my $format = $ctx->hub->format;
1263             $ctx->release;
1264             return unless $format && $format->isa('Test::Builder::Formatter');
1265 0     0 1 0  
1266             $format->handles->[Test::Builder::Formatter::OUT_TODO()] = $self->_new_fh($fh)
1267 0         0 if defined $fh;
1268 0         0  
1269             return $format->handles->[Test::Builder::Formatter::OUT_TODO()];
1270             }
1271 0         0  
1272 0 0       0 my $self = shift;
1273 0         0 my($file_or_fh) = shift;
1274 0         0  
1275 0 0       0 my $fh;
1276 0         0 if( $self->is_fh($file_or_fh) ) {
1277             $fh = $file_or_fh;
1278             }
1279             elsif( ref $file_or_fh eq 'SCALAR' ) {
1280             # Scalar refs as filehandles was added in 5.8.
1281             if( $] >= 5.008 ) {
1282             open $fh, ">>", $file_or_fh
1283             or $self->croak("Can't open scalar ref $file_or_fh: $!");
1284 0     0 1 0 }
1285             # Emulate scalar ref filehandles with a tie.
1286 0         0 else {
1287 0         0 $fh = Test::Builder::IO::Scalar->new($file_or_fh)
1288 0         0 or $self->croak("Can't tie scalar ref $file_or_fh");
1289 0 0 0     0 }
1290             }
1291 0 0       0 else {
1292             open $fh, ">", $file_or_fh
1293             or $self->croak("Can't open test output log $file_or_fh: $!");
1294 0         0 _autoflush($fh);
1295             }
1296              
1297             return $fh;
1298 0     0 1 0 }
1299              
1300 0         0 my($fh) = shift;
1301 0         0 my $old_fh = select $fh;
1302 0         0 $| = 1;
1303 0 0 0     0 select $old_fh;
1304              
1305 0 0       0 return;
1306             }
1307              
1308 0         0  
1309             my $self = shift;
1310              
1311             my $ctx = $self->ctx;
1312 0     0 1 0 my $format = $ctx->hub->format;
1313             $ctx->release;
1314 0         0 return unless $format && $format->isa('Test2::Formatter::TAP');
1315 0         0 $format->set_handles([@{$self->{Orig_Handles}}]) if $self->{Orig_Handles};
1316 0         0  
1317 0 0 0     0 return;
1318             }
1319 0 0       0  
1320              
1321             my $self = shift;
1322 0         0 my $ctx = $self->ctx;
1323             $ctx->alert(join "", @_);
1324             $ctx->release;
1325             }
1326 0     0   0  
1327 0         0 my $self = shift;
1328             my $ctx = $self->ctx;
1329 0         0 $ctx->throw(join "", @_);
1330 0 0       0 $ctx->release;
    0          
1331 0         0 }
1332              
1333              
1334             my( $self, $num ) = @_;
1335 0 0       0  
1336 0 0       0 my $ctx = $self->ctx;
1337             my $hub = $ctx->hub;
1338              
1339             if( defined $num ) {
1340             $hub->set_count($num);
1341 0 0       0  
1342             unless ($self->{no_log_results}) {
1343             # If the test counter is being pushed forward fill in the details.
1344             my $test_results = $ctx->hub->meta(__PACKAGE__, {})->{Test_Results};
1345             if ($num > @$test_results) {
1346 0 0       0 my $start = @$test_results ? @$test_results : 0;
1347             for ($start .. $num - 1) {
1348 0         0 $test_results->[$_] = {
1349             'ok' => 1,
1350             actual_ok => undef,
1351 0         0 reason => 'incrementing test number',
1352             type => 'unknown',
1353             name => undef
1354             };
1355 0     0   0 }
1356 0         0 }
1357 0         0 # If backward, wipe history. Its their funeral.
1358 0         0 elsif ($num < @$test_results) {
1359             $#{$test_results} = $num - 1;
1360 0         0 }
1361             }
1362             }
1363             return release $ctx, $hub->count;
1364             }
1365 6     6 1 21  
1366              
1367 6         17 my $self = shift;
1368 6         263  
1369 6         72 my $ctx = $self->ctx;
1370 6 50 33     78 my $hub = $ctx->hub;
1371 6 50       21  
  6         55  
1372             if( @_ ) {
1373 6         34 my ($bool) = @_;
1374             $hub->set_failed(0) if $bool;
1375             $hub->is_passing($bool);
1376             }
1377              
1378 0     0 1 0 return release $ctx, $hub->is_passing;
1379 0         0 }
1380 0         0  
1381 0         0  
1382             my($self) = shift;
1383              
1384             return if $self->{no_log_results};
1385 0     0 1 0  
1386 0         0 my $ctx = $self->ctx;
1387 0         0 my $data = $ctx->hub->meta(__PACKAGE__, {})->{Test_Results};
1388 0         0 $ctx->release;
1389             return map { $_ ? $_->{'ok'} : () } @$data;
1390             }
1391              
1392              
1393 0     0 1 0 my $self = shift;
1394              
1395 0         0 return if $self->{no_log_results};
1396 0         0  
1397             my $ctx = $self->ctx;
1398 0 0       0 my $data = $ctx->hub->meta(__PACKAGE__, {})->{Test_Results};
1399 0         0 $ctx->release;
1400             return @$data;
1401 0 0       0 }
1402              
1403 0         0  
1404 0 0       0 my( $self, $pack, $set, $new_value ) = @_;
    0          
1405 0 0       0  
1406 0         0 my $ctx = $self->ctx;
1407 0         0  
1408             $pack ||= $ctx->trace->package || $self->exported_to;
1409             $ctx->release;
1410              
1411             return unless $pack;
1412              
1413             no strict 'refs'; ## no critic
1414             no warnings 'once';
1415             my $old_value = ${ $pack . '::TODO' };
1416             $set and ${ $pack . '::TODO' } = $new_value;
1417             return $old_value;
1418 0         0 }
  0         0  
1419              
1420             my( $self, $pack ) = @_;
1421              
1422 0         0 local $Level = $Level + 1;
1423             my $ctx = $self->ctx;
1424             $ctx->release;
1425              
1426             my $meta = $ctx->hub->meta(__PACKAGE__, {todo => []})->{todo};
1427 0     0 1 0 return $meta->[-1]->[1] if $meta && @$meta;
1428              
1429 0         0 $pack ||= $ctx->trace->package;
1430 0         0  
1431             return unless $pack;
1432 0 0       0  
1433 0         0 no strict 'refs'; ## no critic
1434 0 0       0 no warnings 'once';
1435 0         0 return ${ $pack . '::TODO' };
1436             }
1437              
1438 0         0 my $self = shift;
1439              
1440             local $Level = $Level + 1;
1441             my $ctx = $self->ctx;
1442             $ctx->release;
1443 0     0 1 0  
1444             my $meta = $ctx->hub->meta(__PACKAGE__, {todo => []})->{todo};
1445 0 0       0 return 1 if $meta && @$meta;
1446              
1447 0         0 my $pack = $ctx->trace->package || return 0;
1448 0         0  
1449 0         0 no strict 'refs'; ## no critic
1450 0 0       0 no warnings 'once';
  0         0  
1451             my $todo = ${ $pack . '::TODO' };
1452              
1453             return 0 unless defined $todo;
1454             return 0 if "$todo" eq '';
1455 0     0 1 0 return 1;
1456             }
1457 0 0       0  
1458             my $self = shift;
1459 0         0 my $message = @_ ? shift : '';
1460 0         0  
1461 0         0 my $ctx = $self->ctx;
1462 0         0  
1463             my $hub = $ctx->hub;
1464             my $filter = $hub->pre_filter(sub {
1465             my ($active_hub, $e) = @_;
1466              
1467 0     0 1 0 # Turn a diag into a todo diag
1468             return Test::Builder::TodoDiag->new(%$e) if ref($e) eq 'Test2::Event::Diag';
1469 0         0  
1470             # Set todo on ok's
1471 0   0     0 if ($hub == $active_hub && $e->isa('Test2::Event::Ok')) {
      0        
1472 0         0 $e->set_todo($message);
1473             $e->set_effective_pass(1);
1474 0 0       0  
1475             if (my $result = $e->get_meta(__PACKAGE__)) {
1476 6     6   54 $result->{reason} ||= $message;
  6         12  
  6         185  
1477 6     6   28 $result->{type} ||= 'todo';
  6         29  
  6         883  
1478 0         0 $result->{ok} = 1;
  0         0  
1479 0 0       0 }
  0         0  
1480 0         0 }
1481              
1482             return $e;
1483             }, inherit => 1);
1484 0     0 1 0  
1485             push @{$ctx->hub->meta(__PACKAGE__, {todo => []})->{todo}} => [$filter, $message];
1486 0         0  
1487 0         0 $ctx->release;
1488 0         0  
1489             return;
1490 0         0 }
1491 0 0 0     0  
1492             my $self = shift;
1493 0   0     0  
1494             my $ctx = $self->ctx;
1495 0 0       0  
1496             my $set = pop @{$ctx->hub->meta(__PACKAGE__, {todo => []})->{todo}};
1497 6     6   45  
  6         20  
  6         205  
1498 6     6   32 $ctx->throw('todo_end() called without todo_start()') unless $set;
  6         13  
  6         705  
1499 0         0  
  0         0  
1500             $ctx->hub->pre_unfilter($set->[0]);
1501              
1502             $ctx->release;
1503 0     0 1 0  
1504             return;
1505 0         0 }
1506 0         0  
1507 0         0  
1508             my( $self ) = @_;
1509 0         0  
1510 0 0 0     0 my $ctx = $self->ctx;
1511              
1512 0   0     0 my $trace = $ctx->trace;
1513             $ctx->release;
1514 6     6   38 return wantarray ? $trace->call : $trace->package;
  6         13  
  6         174  
1515 6     6   27 }
  6         55  
  6         6820  
1516 0         0  
  0         0  
1517              
1518 0 0       0 my( $self, $code, %opts ) = @_;
1519 0 0       0  
1520 0         0 my $error;
1521             my $return;
1522             {
1523             local $!; # eval can mess up $!
1524 0     0 1 0 local $@; # don't set $@ in the test
1525 0 0       0 local $SIG{__DIE__}; # don't trip an outside DIE handler.
1526             $return = eval { $code->() };
1527 0         0 $error = $@;
1528             }
1529 0         0  
1530             die $error if $error and $opts{die_on_fail};
1531 0     0   0  
1532             return wantarray ? ( $return, $error ) : $return;
1533             }
1534 0 0       0  
1535             my $self = shift;
1536             my ($ctx, $real_exit_code, $new) = @_;
1537 0 0 0     0  
1538 0         0 unless ($ctx) {
1539 0         0 my $octx = $self->ctx;
1540             $ctx = $octx->snapshot;
1541 0 0       0 $octx->release;
1542 0   0     0 }
1543 0   0     0  
1544 0         0 return if $ctx->hub->no_ending;
1545             return if $ctx->hub->meta(__PACKAGE__, {})->{Ending}++;
1546              
1547             # Don't bother with an ending if this is a forked copy. Only the parent
1548 0         0 # should do the ending.
1549 0         0 return unless $self->{Original_Pid} == $$;
1550              
1551 0         0 my $hub = $ctx->hub;
  0         0  
1552             return if $hub->bailed_out;
1553 0         0  
1554             my $plan = $hub->plan;
1555 0         0 my $count = $hub->count;
1556             my $failed = $hub->failed;
1557             my $passed = $hub->is_passing;
1558             return unless $plan || $count || $failed;
1559 0     0 1 0  
1560             # Ran tests but never declared a plan or hit done_testing
1561 0         0 if( !$hub->plan and $hub->count ) {
1562             $self->diag("Tests were run but no plan was declared and done_testing() was not seen.");
1563 0         0  
  0         0  
1564             if($real_exit_code) {
1565 0 0       0 $self->diag(<<"FAIL");
1566             Looks like your test exited with $real_exit_code just after $count.
1567 0         0 FAIL
1568             $$new ||= $real_exit_code;
1569 0         0 return;
1570             }
1571 0         0  
1572             # But if the tests ran, handle exit code.
1573             if($failed > 0) {
1574             my $exit_code = $failed <= 254 ? $failed : 254;
1575             $$new ||= $exit_code;
1576 0     0 1 0 return;
1577             }
1578 0         0  
1579             $$new ||= 254;
1580 0         0 return;
1581 0         0 }
1582 0 0       0  
1583             if ($real_exit_code && !$count) {
1584             $self->diag("Looks like your test exited with $real_exit_code before it could output anything.");
1585             $$new ||= $real_exit_code;
1586             return;
1587 0     0   0 }
1588              
1589 0         0 return if $plan && "$plan" eq 'SKIP';
1590              
1591             if (!$count) {
1592 0         0 $self->diag('No tests run!');
  0         0  
1593 0         0 $$new ||= 255;
1594 0         0 return;
1595 0         0 }
  0         0  
1596 0         0  
1597             if ($real_exit_code) {
1598             $self->diag(<<"FAIL");
1599 0 0 0     0 Looks like your test exited with $real_exit_code just after $count.
1600             FAIL
1601 0 0       0 $$new ||= $real_exit_code;
1602             return;
1603             }
1604              
1605 6     6   18 if ($plan eq 'NO PLAN') {
1606 6         19 $ctx->plan( $count );
1607             $plan = $hub->plan;
1608 6 50       46 }
1609 0         0  
1610 0         0 # Figure out if we passed or failed and print helpful messages.
1611 0         0 my $num_extra = $count - $plan;
1612              
1613             if ($num_extra != 0) {
1614 6 50       26 my $s = $plan == 1 ? '' : 's';
1615 6 50       52 $self->diag(<<"FAIL");
1616             Looks like you planned $plan test$s but ran $count.
1617             FAIL
1618             }
1619 6 50       164  
1620             if ($failed) {
1621 6         24 my $s = $failed == 1 ? '' : 's';
1622 6 50       36  
1623             my $qualifier = $num_extra == 0 ? '' : ' run';
1624 6         38  
1625 6         43 $self->diag(<<"FAIL");
1626 6         36 Looks like you failed $failed test$s of $count$qualifier.
1627 6         30 FAIL
1628 6 0 33     105 }
      33        
1629              
1630             if (!$passed && !$failed && $count && !$num_extra) {
1631 6 50 33     20 $ctx->diag(<<"FAIL");
1632 0         0 All assertions passed, but errors were encountered.
1633             FAIL
1634 0 0       0 }
1635 0         0  
1636             my $exit_code = 0;
1637             if ($failed) {
1638 0   0     0 $exit_code = $failed <= 254 ? $failed : 254;
1639 0         0 }
1640             elsif ($num_extra != 0) {
1641             $exit_code = 255;
1642             }
1643 0 0       0 elsif (!$passed) {
1644 0 0       0 $exit_code = 255;
1645 0   0     0 }
1646 0         0  
1647             $$new ||= $exit_code;
1648             return;
1649 0   0     0 }
1650 0         0  
1651             # Some things used this even though it was private... I am looking at you
1652             # Test::Builder::Prefix...
1653 6 50 33     61 my( $self, $fh, @msgs ) = @_;
1654 0         0  
1655 0   0     0 return if $self->no_diag;
1656 0         0 return unless @msgs;
1657              
1658             # Prevent printing headers when compiling (i.e. -c)
1659 6 100 66     49 return if $^C;
1660              
1661 3 50       12 # Smash args together like print does.
1662 0         0 # Convert undef to 'undef' so its readable.
1663 0   0     0 my $msg = join '', map { defined($_) ? $_ : 'undef' } @msgs;
1664 0         0  
1665             # Escape the beginning, _print will take care of the rest.
1666             $msg =~ s/^/# /;
1667 3 50       8  
1668 0         0 local( $\, $", $, ) = ( undef, ' ', '' );
1669             print $fh $msg;
1670              
1671 0   0     0 return 0;
1672 0         0 }
1673              
1674             # This is used by Test::SharedFork to turn on IPC after the fact. Not
1675 3 50       11 # documenting because I do not want it used. The method name is borrowed from
1676 0         0 # Test::Builder 2
1677 0         0 # Once Test2 stuff goes stable this method will be removed and Test::SharedFork
1678             # will be made smarter.
1679             my $self = shift;
1680              
1681 3         7 {
1682             local ($@, $!);
1683 3 50       9 require Test2::IPC;
1684 0 0       0 }
1685 0         0 Test2::IPC->import;
1686             Test2::API::test2_ipc_enable_polling();
1687             Test2::API::test2_load();
1688             my $ipc = Test2::IPC::apply_ipc($self->{Stack});
1689             $ipc->set_no_fatal(1);
1690 3 50       7 Test2::API::test2_no_wait(1);
1691 0 0       0 }
1692              
1693 0 0       0  
1694             1;
1695 0         0  
1696              
1697             #line 2121
1698              
1699