| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test2::Tools::xUnit 0.006; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 13 |  |  | 13 |  | 58991 | use v5.12; | 
|  | 13 |  |  |  |  | 69 |  | 
| 4 | 13 |  |  | 13 |  | 75 | use warnings; | 
|  | 13 |  |  |  |  | 24 |  | 
|  | 13 |  |  |  |  | 434 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 13 |  |  | 13 |  | 97 | use B; | 
|  | 13 |  |  |  |  | 32 |  | 
|  | 13 |  |  |  |  | 581 |  | 
| 7 | 13 |  |  | 13 |  | 6280 | use Test2::Workflow; | 
|  | 13 |  |  |  |  | 362817 |  | 
|  | 13 |  |  |  |  | 629 |  | 
| 8 | 13 |  |  | 13 |  | 6424 | use Test2::Workflow::Runner; | 
|  | 13 |  |  |  |  | 496173 |  | 
|  | 13 |  |  |  |  | 414 |  | 
| 9 | 13 |  |  | 13 |  | 120 | use Test2::Workflow::Task::Action; | 
|  | 13 |  |  |  |  | 30 |  | 
|  | 13 |  |  |  |  | 6681 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | sub import { | 
| 12 | 13 |  |  | 13 |  | 196 | my @caller = caller; | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | # This sets up the root Test2::Workflow::Build for the package we are | 
| 15 |  |  |  |  |  |  | # being called from.  All tests will be added as actions later. | 
| 16 |  |  |  |  |  |  | my $root = Test2::Workflow::init_root( | 
| 17 |  |  |  |  |  |  | $caller[0], | 
| 18 |  |  |  | 0 |  |  | code  => sub { }, | 
| 19 | 13 |  |  |  |  | 103 | frame => \@caller, | 
| 20 |  |  |  |  |  |  | ); | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # Each test method is run in its own instance.  This setup action will | 
| 23 |  |  |  |  |  |  | # be called before each test method is invoked, and instantiates a new | 
| 24 |  |  |  |  |  |  | # object. | 
| 25 |  |  |  |  |  |  | # | 
| 26 |  |  |  |  |  |  | # If the caller does not provide a "new" constructor, we bless a hashref | 
| 27 |  |  |  |  |  |  | # into the calling package and use that. | 
| 28 |  |  |  |  |  |  | # | 
| 29 |  |  |  |  |  |  | # Each coderef is called with the Test2::Workflow::Runner as the first | 
| 30 |  |  |  |  |  |  | # argument.  We abuse this so that we can pass the same instance variable | 
| 31 |  |  |  |  |  |  | # to the setup, test and teardown methods. | 
| 32 |  |  |  |  |  |  | $root->add_primary_setup( | 
| 33 |  |  |  |  |  |  | Test2::Workflow::Task::Action->new( | 
| 34 |  |  |  |  |  |  | code => sub { | 
| 35 |  |  |  |  |  |  | shift->{xUnit} | 
| 36 | 21 | 100 |  | 21 |  | 53394 | = $caller[0]->can('new') | 
| 37 |  |  |  |  |  |  | ? $caller[0]->new | 
| 38 |  |  |  |  |  |  | : bless {}, $caller[0]; | 
| 39 |  |  |  |  |  |  | }, | 
| 40 | 13 |  |  |  |  | 4874 | name     => 'object_construction', | 
| 41 |  |  |  |  |  |  | frame    => \@caller, | 
| 42 |  |  |  |  |  |  | scaffold => 1, | 
| 43 |  |  |  |  |  |  | ) | 
| 44 |  |  |  |  |  |  | ); | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | # We add a follow-up task to the top hub in the stack, which will be | 
| 47 |  |  |  |  |  |  | # executed when done_testing or END is seen. | 
| 48 |  |  |  |  |  |  | Test2::API::test2_stack->top->follow_up( | 
| 49 | 13 |  |  | 13 |  | 4226 | sub { Test2::Workflow::Runner->new( task => $root->compile )->run } ); | 
|  | 13 |  |  |  |  | 10210 |  | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 13 |  |  |  |  | 149223 | my $orig = $caller[0]->can('MODIFY_CODE_ATTRIBUTES'); | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | # This sub will be called whenever the Perl interpreter hits a subroutine | 
| 54 |  |  |  |  |  |  | # with attributes in our caller. | 
| 55 |  |  |  |  |  |  | # | 
| 56 |  |  |  |  |  |  | # It closes over $root so that it can add the actions, and @caller so that | 
| 57 |  |  |  |  |  |  | # it knows which package it's in. | 
| 58 |  |  |  |  |  |  | my $modify_code_attributes = sub { | 
| 59 | 33 |  |  | 33 |  | 437047 | my ( $pkg, $code, @attrs ) = @_; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 33 |  |  |  |  | 437 | my $name = B::svref_2object($code)->GV->NAME; | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 33 |  |  |  |  | 219 | my ( $method, $class_method, %options, @unhandled ); | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 33 |  |  |  |  | 85 | for (@attrs) { | 
| 66 | 39 | 100 |  |  |  | 206 | if ( $_ eq 'Test' ) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 67 | 22 |  |  |  |  | 54 | $method = 'add_primary'; | 
| 68 |  |  |  |  |  |  | } | 
| 69 |  |  |  |  |  |  | # All the setup methods count as 'scaffolding'. | 
| 70 |  |  |  |  |  |  | # Test2::Workflow docs are light on what this actually does; | 
| 71 |  |  |  |  |  |  | # something to do with filtering out the events?  Anyway, | 
| 72 |  |  |  |  |  |  | # Test2::Tools::Spec does it. | 
| 73 |  |  |  |  |  |  | elsif ( $_ eq 'BeforeEach' ) { | 
| 74 | 2 |  |  |  |  | 3 | $method = 'add_primary_setup'; | 
| 75 | 2 |  |  |  |  | 4 | $options{scaffold} = 1; | 
| 76 |  |  |  |  |  |  | } | 
| 77 |  |  |  |  |  |  | elsif ( $_ eq 'AfterEach' ) { | 
| 78 | 2 |  |  |  |  | 4 | $method = 'add_primary_teardown'; | 
| 79 | 2 |  |  |  |  | 6 | $options{scaffold} = 1; | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  | # BeforeAll/AfterAll are called as class methods, not instance | 
| 82 |  |  |  |  |  |  | # methods. | 
| 83 |  |  |  |  |  |  | elsif ( $_ eq 'BeforeAll' ) { | 
| 84 | 1 |  |  |  |  | 2 | $method            = 'add_setup'; | 
| 85 | 1 |  |  |  |  | 2 | $options{scaffold} = 1; | 
| 86 | 1 |  |  |  |  | 2 | $class_method      = 1; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  | elsif ( $_ eq 'AfterAll' ) { | 
| 89 | 1 |  |  |  |  | 3 | $method            = 'add_teardown'; | 
| 90 | 1 |  |  |  |  | 2 | $options{scaffold} = 1; | 
| 91 | 1 |  |  |  |  | 2 | $class_method      = 1; | 
| 92 |  |  |  |  |  |  | } | 
| 93 |  |  |  |  |  |  | # We default to the name of the current method if no reason is | 
| 94 |  |  |  |  |  |  | # given for Skip/Todo. | 
| 95 |  |  |  |  |  |  | elsif (/^Skip(?:\((.+)\))?/) { | 
| 96 | 3 |  |  |  |  | 4 | $method = 'add_primary'; | 
| 97 | 3 |  | 66 |  |  | 21 | $options{skip} = $1 || $name; | 
| 98 |  |  |  |  |  |  | } | 
| 99 |  |  |  |  |  |  | elsif (/^Todo(?:\((.+)\))?/) { | 
| 100 | 4 |  |  |  |  | 7 | $method = 'add_primary'; | 
| 101 | 4 |  | 66 |  |  | 26 | $options{todo} = $1 || $name; | 
| 102 |  |  |  |  |  |  | } | 
| 103 |  |  |  |  |  |  | # All unhandled attributes are returned for someone else to | 
| 104 |  |  |  |  |  |  | # deal with. | 
| 105 |  |  |  |  |  |  | else { | 
| 106 | 4 |  |  |  |  | 11 | push @unhandled, $_; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  | } | 
| 109 |  |  |  |  |  |  |  | 
| 110 | 33 | 100 |  |  |  | 419 | if ($method) { | 
| 111 |  |  |  |  |  |  | my $task = Test2::Workflow::Task::Action->new( | 
| 112 |  |  |  |  |  |  | code => $class_method | 
| 113 | 2 |  |  | 2 |  | 3242 | ? sub { $caller[0]->$code } | 
| 114 | 29 |  |  | 29 |  | 10160 | : sub { shift->{xUnit}->$code }, | 
| 115 | 30 | 100 |  |  |  | 372 | frame => \@caller, | 
| 116 |  |  |  |  |  |  | name  => $name, | 
| 117 |  |  |  |  |  |  | %options, | 
| 118 |  |  |  |  |  |  | ); | 
| 119 |  |  |  |  |  |  |  | 
| 120 | 30 |  |  |  |  | 5593 | $root->$method($task); | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 33 |  |  |  |  | 264 | @_ = ( $pkg, $code, @unhandled ); | 
| 124 | 33 | 100 |  |  |  | 105 | if ($orig) { | 
| 125 | 1 |  |  |  |  | 7 | goto $orig; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  | else { | 
| 128 |  |  |  |  |  |  | # A package like Attribute::Handlers might have modified @ISA | 
| 129 |  |  |  |  |  |  | # after we were imported. Note that SUPER won't work because it | 
| 130 |  |  |  |  |  |  | # finds the compile-time package of this sub. | 
| 131 | 13 |  |  | 13 |  | 148 | no strict 'refs'; | 
|  | 13 |  |  |  |  | 33 |  | 
|  | 13 |  |  |  |  | 2189 |  | 
| 132 | 32 |  |  |  |  | 52 | my @parents = @{ $pkg . '::ISA' }; | 
|  | 32 |  |  |  |  | 146 |  | 
| 133 | 32 | 100 |  |  |  | 123 | @parents = 'UNIVERSAL' unless @parents; | 
| 134 | 32 |  |  |  |  | 77 | for my $parent (@parents) { | 
| 135 | 32 | 100 |  |  |  | 231 | if ( my $subref = $parent->can('MODIFY_CODE_ATTRIBUTES') ) { | 
| 136 | 4 |  |  |  |  | 25 | goto $subref; | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 28 |  |  |  |  | 121 | return @unhandled; | 
| 142 | 13 |  |  |  |  | 98 | }; | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 13 |  |  | 13 |  | 102 | no strict 'refs'; | 
|  | 13 |  |  |  |  | 34 |  | 
|  | 13 |  |  |  |  | 459 |  | 
| 145 | 13 |  |  | 13 |  | 114 | no warnings 'redefine'; | 
|  | 13 |  |  |  |  | 48 |  | 
|  | 13 |  |  |  |  | 1304 |  | 
| 146 |  |  |  |  |  |  |  | 
| 147 | 13 |  |  |  |  | 175 | *{"$caller[0]::MODIFY_CODE_ATTRIBUTES"} = $modify_code_attributes; | 
|  | 13 |  |  |  |  | 470 |  | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | 1; |