| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test::Leaner; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 26 |  |  | 26 |  | 402631 | use 5.006; | 
|  | 26 |  |  |  |  | 101 |  | 
|  | 26 |  |  |  |  | 1211 |  | 
| 4 | 26 |  |  | 26 |  | 619 | use strict; | 
|  | 26 |  |  |  |  | 62 |  | 
|  | 26 |  |  |  |  | 836 |  | 
| 5 | 26 |  |  | 26 |  | 135 | use warnings; | 
|  | 26 |  |  |  |  | 134 |  | 
|  | 26 |  |  |  |  | 1881 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | =head1 NAME | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | Test::Leaner - A slimmer Test::More for when you favor performance over completeness. | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | =head1 VERSION | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | Version 0.05 | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | =cut | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | our $VERSION = '0.05'; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | use Test::Leaner tests => 10_000; | 
| 22 |  |  |  |  |  |  | for (1 .. 10_000) { | 
| 23 |  |  |  |  |  |  | ... | 
| 24 |  |  |  |  |  |  | is $one, 1, "checking situation $_"; | 
| 25 |  |  |  |  |  |  | } | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | When profiling some L<Test::More>-based test script that contained about 10 000 unit tests, I realized that 60% of the time was spent in L<Test::Builder> itself, even though every single test actually involved a costly C<eval STRING>. | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | This module aims to be a partial replacement to L<Test::More> in those situations where you want to run a large number of simple tests. | 
| 33 |  |  |  |  |  |  | Its functions behave the same as their L<Test::More> counterparts, except for the following differences : | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | =over 4 | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | =item * | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | Stringification isn't forced on the test operands. | 
| 40 |  |  |  |  |  |  | However, L</ok> honors C<'bool'> overloading, L</is> and L</is_deeply> honor C<'eq'> overloading (and just that one), L</isnt> honors C<'ne'> overloading, and L</cmp_ok> honors whichever overloading category corresponds to the specified operator. | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | =item * | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | L</pass>, L</fail>, L</ok>, L</is>, L</isnt>, L</like>, L</unlike>, L</cmp_ok> and L</is_deeply> are all guaranteed to return the truth value of the test. | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | =item * | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | C<isn't> (the sub C<t> in package C<isn>) is not aliased to L</isnt>. | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | =item * | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | L</like> and L</unlike> don't special case regular expressions that are passed as C<'/.../'> strings. | 
| 53 |  |  |  |  |  |  | A string regexp argument is always treated as the source of the regexp, making C<like $text, $rx> and C<like $text, qr[$rx]> equivalent to each other and to C<cmp_ok $text, '=~', $rx> (and likewise for C<unlike>). | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | =item * | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | L</cmp_ok> throws an exception if the given operator isn't a valid Perl binary operator (except C<'='> and variants). | 
| 58 |  |  |  |  |  |  | It also tests in scalar context, so C<'..'> will be treated as the flip-flop operator and not the range operator. | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | =item * | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | L</is_deeply> doesn't guard for memory cycles. | 
| 63 |  |  |  |  |  |  | If the two first arguments present parallel memory cycles, the test may result in an infinite loop. | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | =item * | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | The tests don't output any kind of default diagnostic in case of failure ; the rationale being that if you have a large number of tests and a lot of them are failing, then you don't want to be flooded by diagnostics. | 
| 68 |  |  |  |  |  |  | Moreover, this allows a much faster variant of L</is_deeply>. | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | =item * | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | C<use_ok>, C<require_ok>, C<can_ok>, C<isa_ok>, C<new_ok>, C<subtest>, C<explain>, C<TODO> blocks and C<todo_skip> are not implemented. | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | =back | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | =cut | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 26 |  |  | 26 |  | 145 | use Exporter (); | 
|  | 26 |  |  |  |  | 64 |  | 
|  | 26 |  |  |  |  | 2508 |  | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | my $main_process; | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | BEGIN { | 
| 83 | 26 |  |  | 26 |  | 234 | $main_process = $$; | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 26 | 50 | 33 |  |  | 372 | if ("$]" >= 5.008 and $INC{'threads.pm'}) { | 
| 86 | 0 |  |  |  |  | 0 | my $use_ithreads = do { | 
| 87 | 0 |  |  |  |  | 0 | require Config; | 
| 88 | 26 |  |  | 26 |  | 139 | no warnings 'once'; | 
|  | 26 |  |  |  |  | 54 |  | 
|  | 26 |  |  |  |  | 4204 |  | 
| 89 | 0 |  |  |  |  | 0 | $Config::Config{useithreads}; | 
| 90 |  |  |  |  |  |  | }; | 
| 91 | 0 | 0 |  |  |  | 0 | if ($use_ithreads) { | 
| 92 | 0 |  |  |  |  | 0 | require threads::shared; | 
| 93 | 0 |  |  |  |  | 0 | *THREADSAFE = sub () { 1 }; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | } | 
| 96 | 26 | 50 |  |  |  | 147 | unless (defined &Test::Leaner::THREADSAFE) { | 
| 97 |  |  |  |  |  |  | *THREADSAFE = sub () { 0 } | 
| 98 | 26 |  |  |  |  | 11365 | } | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | my ($TAP_STREAM, $DIAG_STREAM); | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | my ($plan, $test, $failed, $no_diag, $done_testing); | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | our @EXPORT = qw< | 
| 106 |  |  |  |  |  |  | plan | 
| 107 |  |  |  |  |  |  | skip | 
| 108 |  |  |  |  |  |  | done_testing | 
| 109 |  |  |  |  |  |  | pass | 
| 110 |  |  |  |  |  |  | fail | 
| 111 |  |  |  |  |  |  | ok | 
| 112 |  |  |  |  |  |  | is | 
| 113 |  |  |  |  |  |  | isnt | 
| 114 |  |  |  |  |  |  | like | 
| 115 |  |  |  |  |  |  | unlike | 
| 116 |  |  |  |  |  |  | cmp_ok | 
| 117 |  |  |  |  |  |  | is_deeply | 
| 118 |  |  |  |  |  |  | diag | 
| 119 |  |  |  |  |  |  | note | 
| 120 |  |  |  |  |  |  | BAIL_OUT | 
| 121 |  |  |  |  |  |  | >; | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | =head1 ENVIRONMENT | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | =head2 C<PERL_TEST_LEANER_USES_TEST_MORE> | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | If this environment variable is set, L<Test::Leaner> will replace its functions by those from L<Test::More>. | 
| 128 |  |  |  |  |  |  | Moreover, the symbols that are imported when you C<use Test::Leaner> will be those from L<Test::More>, but you can still only import the symbols originally defined in L<Test::Leaner> (hence the functions from L<Test::More> that are not implemented in L<Test::Leaner> will not be imported). | 
| 129 |  |  |  |  |  |  | If your version of L<Test::More> is too old and doesn't have some symbols (like L</note> or L</done_testing>), they will be replaced in L<Test::Leaner> by croaking stubs. | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | This may be useful if your L<Test::Leaner>-based test script fails and you want extra diagnostics. | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | =cut | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | sub _handle_import_args { | 
| 136 | 48 |  |  | 48 |  | 92 | my @imports; | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 48 |  |  |  |  | 91 | my $i = 0; | 
| 139 | 48 |  |  |  |  | 239 | while ($i <= $#_) { | 
| 140 | 54 |  |  |  |  | 107 | my $item = $_[$i]; | 
| 141 | 54 |  |  |  |  | 539 | my $splice; | 
| 142 | 54 | 50 |  |  |  | 172 | if (defined $item) { | 
| 143 | 54 | 100 |  |  |  | 202 | if ($item eq 'import') { | 
|  |  | 50 |  |  |  |  |  | 
| 144 | 37 |  |  |  |  | 59 | push @imports, @{ $_[$i+1] }; | 
|  | 37 |  |  |  |  | 101 |  | 
| 145 | 37 |  |  |  |  | 74 | $splice  = 2; | 
| 146 |  |  |  |  |  |  | } elsif ($item eq 'no_diag') { | 
| 147 | 0 |  |  |  |  | 0 | lock $plan if THREADSAFE; | 
| 148 | 0 |  |  |  |  | 0 | $no_diag = 1; | 
| 149 | 0 |  |  |  |  | 0 | $splice  = 1; | 
| 150 |  |  |  |  |  |  | } | 
| 151 |  |  |  |  |  |  | } | 
| 152 | 54 | 100 |  |  |  | 127 | if ($splice) { | 
| 153 | 37 |  |  |  |  | 165 | splice @_, $i, $splice; | 
| 154 |  |  |  |  |  |  | } else { | 
| 155 | 17 |  |  |  |  | 52 | ++$i; | 
| 156 |  |  |  |  |  |  | } | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 48 |  |  |  |  | 3649 | return @imports; | 
| 160 |  |  |  |  |  |  | } | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | if ($ENV{PERL_TEST_LEANER_USES_TEST_MORE}) { | 
| 163 |  |  |  |  |  |  | require Test::More; | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | my $leaner_stash = \%Test::Leaner::; | 
| 166 |  |  |  |  |  |  | my $more_stash   = \%Test::More::; | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | my %stubbed; | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | for (@EXPORT) { | 
| 171 |  |  |  |  |  |  | my $replacement = exists $more_stash->{$_} ? *{$more_stash->{$_}}{CODE} | 
| 172 |  |  |  |  |  |  | : undef; | 
| 173 |  |  |  |  |  |  | unless (defined $replacement) { | 
| 174 |  |  |  |  |  |  | $stubbed{$_}++; | 
| 175 |  |  |  |  |  |  | $replacement = sub { | 
| 176 |  |  |  |  |  |  | @_ = ("$_ is not implemented in this version of Test::More"); | 
| 177 |  |  |  |  |  |  | goto &croak; | 
| 178 |  |  |  |  |  |  | }; | 
| 179 |  |  |  |  |  |  | } | 
| 180 | 26 |  |  | 26 |  | 180 | no warnings 'redefine'; | 
|  | 26 |  |  |  |  | 50 |  | 
|  | 26 |  |  |  |  | 11154 |  | 
| 181 |  |  |  |  |  |  | $leaner_stash->{$_} = $replacement; | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | my $import = sub { | 
| 185 | 10 |  |  | 10 |  | 59707 | my $class = shift; | 
| 186 |  |  |  |  |  |  |  | 
| 187 | 10 |  |  |  |  | 83 | my @imports = &_handle_import_args; | 
| 188 | 10 | 100 |  |  |  | 55 | if (@imports == grep /^!/, @imports) { | 
| 189 |  |  |  |  |  |  | # All imports are negated, or @imports is empty | 
| 190 | 7 |  |  |  |  | 25 | my %negated; | 
| 191 | 7 |  | 66 |  |  | 71 | /^!(.*)/ and ++$negated{$1} for @imports; | 
| 192 | 7 |  |  |  |  | 139 | push @imports, grep !$negated{$_}, @EXPORT; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  |  | 
| 195 | 13 |  |  |  |  | 25 | my @test_more_imports; | 
| 196 | 13 |  |  |  |  | 32 | for (@imports) { | 
| 197 | 60 | 50 | 100 |  |  | 529 | if ($stubbed{$_}) { | 
|  |  | 100 | 100 |  |  |  |  | 
| 198 | 4 |  |  |  |  | 10 | my $pkg = caller; | 
| 199 | 26 |  |  | 26 |  | 203 | no strict 'refs'; | 
|  | 26 |  |  |  |  | 50 |  | 
|  | 26 |  |  |  |  | 6835 |  | 
| 200 | 4 |  |  |  |  | 11 | *{$pkg."::$_"} = $leaner_stash->{$_}; | 
|  | 4 |  |  |  |  | 121 |  | 
| 201 |  |  |  |  |  |  | } elsif (/^!/ or !exists $more_stash->{$_} or exists $leaner_stash->{$_}) { | 
| 202 | 56 |  |  |  |  | 121 | push @test_more_imports, $_; | 
| 203 |  |  |  |  |  |  | } else { | 
| 204 |  |  |  |  |  |  | # Croak for symbols in Test::More but not in Test::Leaner | 
| 205 | 2 |  |  |  |  | 294 | Exporter::import($class, $_); | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 9 |  |  |  |  | 83 | my $test_more_import = 'Test::More'->can('import'); | 
| 210 | 11 | 50 |  |  |  | 48 | return unless $test_more_import; | 
| 211 |  |  |  |  |  |  |  | 
| 212 | 11 |  |  |  |  | 49 | @_ = ( | 
| 213 |  |  |  |  |  |  | 'Test::More', | 
| 214 |  |  |  |  |  |  | @_, | 
| 215 |  |  |  |  |  |  | import => \@test_more_imports, | 
| 216 |  |  |  |  |  |  | ); | 
| 217 |  |  |  |  |  |  | { | 
| 218 | 11 |  |  |  |  | 26 | lock $plan if THREADSAFE; | 
|  | 12 |  |  |  |  | 16 |  | 
| 219 | 12 | 50 |  |  |  | 44 | push @_, 'no_diag' if $no_diag; | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  |  | 
| 222 | 12 |  |  |  |  | 149 | goto $test_more_import; | 
| 223 |  |  |  |  |  |  | }; | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 26 |  |  | 26 |  | 162 | no warnings 'redefine'; | 
|  | 26 |  |  |  |  | 72 |  | 
|  | 26 |  |  |  |  | 4821 |  | 
| 226 |  |  |  |  |  |  | *import = $import; | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | return 1; | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | sub NO_PLAN  () { -1 } | 
| 232 |  |  |  |  |  |  | sub SKIP_ALL () { -2 } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | BEGIN { | 
| 235 | 26 |  |  | 26 |  | 66 | if (THREADSAFE) { | 
| 236 |  |  |  |  |  |  | threads::shared::share($_) for $plan, $test, $failed, $no_diag, $done_testing; | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 26 |  |  |  |  | 49 | lock $plan if THREADSAFE; | 
| 240 |  |  |  |  |  |  |  | 
| 241 | 26 |  |  |  |  | 63 | $plan   = undef; | 
| 242 | 26 |  |  |  |  | 59 | $test   = 0; | 
| 243 | 26 |  |  |  |  | 30425 | $failed = 0; | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | sub carp { | 
| 247 | 0 |  | 0 | 0 | 0 | 0 | my $level = 1 + ($Test::Builder::Level || 0); | 
| 248 | 0 |  |  |  |  | 0 | my @caller; | 
| 249 | 0 |  | 0 |  |  | 0 | do { | 
| 250 | 0 |  |  |  |  | 0 | @caller = caller $level--; | 
| 251 |  |  |  |  |  |  | } while (!@caller and $level >= 0); | 
| 252 | 0 |  |  |  |  | 0 | my ($file, $line) = @caller[1, 2]; | 
| 253 | 0 |  |  |  |  | 0 | warn @_, " at $file line $line.\n"; | 
| 254 |  |  |  |  |  |  | } | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | sub croak { | 
| 257 | 0 |  | 0 | 0 | 0 | 0 | my $level = 1 + ($Test::Builder::Level || 0); | 
| 258 | 0 |  |  |  |  | 0 | my @caller; | 
| 259 | 0 |  | 0 |  |  | 0 | do { | 
| 260 | 0 |  |  |  |  | 0 | @caller = caller $level--; | 
| 261 |  |  |  |  |  |  | } while (!@caller and $level >= 0); | 
| 262 | 0 |  |  |  |  | 0 | my ($file, $line) = @caller[1, 2]; | 
| 263 | 0 |  |  |  |  | 0 | die @_, " at $file line $line.\n"; | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | sub _sanitize_comment { | 
| 267 | 37 |  |  | 37 |  | 120 | $_[0] =~ s/\n+\z//; | 
| 268 | 37 |  |  |  |  | 81 | $_[0] =~ s/#/\\#/g; | 
| 269 | 37 |  |  |  |  | 89 | $_[0] =~ s/\n/\n# /g; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | =head1 FUNCTIONS | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | The following functions from L<Test::More> are implemented and exported by default. | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | =head2 C<plan> | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | plan tests => $count; | 
| 279 |  |  |  |  |  |  | plan 'no_plan'; | 
| 280 |  |  |  |  |  |  | plan skip_all => $reason; | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | See L<Test::More/plan>. | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | =cut | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | sub plan { | 
| 287 | 16 |  |  | 16 | 1 | 82 | my ($key, $value) = @_; | 
| 288 |  |  |  |  |  |  |  | 
| 289 | 16 | 50 |  |  |  | 65 | return unless $key; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 16 |  |  |  |  | 33 | lock $plan if THREADSAFE; | 
| 292 |  |  |  |  |  |  |  | 
| 293 | 16 | 50 |  |  |  | 57 | croak("You tried to plan twice") if defined $plan; | 
| 294 |  |  |  |  |  |  |  | 
| 295 | 16 |  |  |  |  | 26 | my $plan_str; | 
| 296 |  |  |  |  |  |  |  | 
| 297 | 16 | 100 |  |  |  | 99 | if ($key eq 'no_plan') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 298 | 3 | 50 |  |  |  | 12 | croak("no_plan takes no arguments") if $value; | 
| 299 | 3 |  |  |  |  | 9 | $plan       = NO_PLAN; | 
| 300 |  |  |  |  |  |  | } elsif ($key eq 'tests') { | 
| 301 | 10 | 50 |  |  |  | 33 | croak("Got an undefined number of tests") unless defined $value; | 
| 302 | 10 | 50 |  |  |  | 36 | croak("You said to run 0 tests")          unless $value; | 
| 303 | 10 | 50 |  |  |  | 115 | croak("Number of tests must be a positive integer.  You gave it '$value'") | 
| 304 |  |  |  |  |  |  | unless $value =~ /^\+?[0-9]+$/; | 
| 305 | 10 |  |  |  |  | 21 | $plan       = $value; | 
| 306 | 10 |  |  |  |  | 26 | $plan_str   = "1..$value"; | 
| 307 |  |  |  |  |  |  | } elsif ($key eq 'skip_all') { | 
| 308 | 3 |  |  |  |  | 4 | $plan       = SKIP_ALL; | 
| 309 | 3 |  |  |  |  | 5 | $plan_str   = '1..0 # SKIP'; | 
| 310 | 3 | 50 |  |  |  | 14 | if (defined $value) { | 
| 311 | 3 |  |  |  |  | 13 | _sanitize_comment($value); | 
| 312 | 3 | 50 |  |  |  | 17 | $plan_str .= " $value" if length $value; | 
| 313 |  |  |  |  |  |  | } | 
| 314 |  |  |  |  |  |  | } else { | 
| 315 | 0 |  |  |  |  | 0 | my @args = grep defined, $key, $value; | 
| 316 | 0 |  |  |  |  | 0 | croak("plan() doesn't understand @args"); | 
| 317 |  |  |  |  |  |  | } | 
| 318 |  |  |  |  |  |  |  | 
| 319 | 16 | 100 |  |  |  | 57 | if (defined $plan_str) { | 
| 320 | 13 |  |  |  |  | 53 | local $\; | 
| 321 | 13 |  |  |  |  | 4830 | print $TAP_STREAM "$plan_str\n"; | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  |  | 
| 324 | 16 | 100 |  |  |  | 2223 | exit 0 if $plan == SKIP_ALL; | 
| 325 |  |  |  |  |  |  |  | 
| 326 | 13 |  |  |  |  | 43 | return 1; | 
| 327 |  |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | sub import { | 
| 330 | 39 |  |  | 39 |  | 86619 | my $class = shift; | 
| 331 |  |  |  |  |  |  |  | 
| 332 | 39 |  |  |  |  | 116 | my @imports = &_handle_import_args; | 
| 333 |  |  |  |  |  |  |  | 
| 334 | 39 | 100 |  |  |  | 158 | if (@_) { | 
| 335 | 9 |  | 50 |  |  | 61 | local $Test::Builder::Level = ($Test::Builder::Level || 0) + 1; | 
| 336 | 9 |  |  |  |  | 25 | &plan; | 
| 337 |  |  |  |  |  |  | } | 
| 338 |  |  |  |  |  |  |  | 
| 339 | 38 |  |  |  |  | 123 | @_ = ($class, @imports); | 
| 340 | 38 |  |  |  |  | 38762 | goto &Exporter::import; | 
| 341 |  |  |  |  |  |  | } | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | =head2 C<skip> | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | skip $reason => $count; | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | See L<Test::More/skip>. | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | =cut | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | sub skip { | 
| 352 | 3 |  |  | 3 | 1 | 14 | my ($reason, $count) = @_; | 
| 353 |  |  |  |  |  |  |  | 
| 354 | 3 |  |  |  |  | 4 | lock $plan if THREADSAFE; | 
| 355 |  |  |  |  |  |  |  | 
| 356 | 3 | 50 |  |  |  | 16 | if (not defined $count) { | 
|  |  | 50 |  |  |  |  |  | 
| 357 | 0 | 0 | 0 |  |  | 0 | carp("skip() needs to know \$how_many tests are in the block") | 
| 358 |  |  |  |  |  |  | unless defined $plan and $plan == NO_PLAN; | 
| 359 | 0 |  |  |  |  | 0 | $count = 1; | 
| 360 |  |  |  |  |  |  | } elsif ($count =~ /[^0-9]/) { | 
| 361 | 0 |  |  |  |  | 0 | carp('skip() was passed a non-numeric number of tests.  Did you get the arguments backwards?'); | 
| 362 | 0 |  |  |  |  | 0 | $count = 1; | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 3 |  |  |  |  | 7 | for (1 .. $count) { | 
| 366 | 3 |  |  |  |  | 4 | ++$test; | 
| 367 |  |  |  |  |  |  |  | 
| 368 | 3 |  |  |  |  | 20 | my $skip_str = "ok $test # skip"; | 
| 369 | 3 | 50 |  |  |  | 10 | if (defined $reason) { | 
| 370 | 3 |  |  |  |  | 6 | _sanitize_comment($reason); | 
| 371 | 3 | 50 |  |  |  | 12 | $skip_str  .= " $reason" if length $reason; | 
| 372 |  |  |  |  |  |  | } | 
| 373 |  |  |  |  |  |  |  | 
| 374 | 3 |  |  |  |  | 8 | local $\; | 
| 375 | 3 |  |  |  |  | 23 | print $TAP_STREAM "$skip_str\n"; | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  |  | 
| 378 | 26 |  |  | 26 |  | 192 | no warnings 'exiting'; | 
|  | 26 |  |  |  |  | 48 |  | 
|  | 26 |  |  |  |  | 18079 |  | 
| 379 | 3 |  |  |  |  | 14 | last SKIP; | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  |  | 
| 382 |  |  |  |  |  |  | =head2 C<done_testing> | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | done_testing; | 
| 385 |  |  |  |  |  |  | done_testing $count; | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | See L<Test::More/done_testing>. | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | =cut | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | sub done_testing { | 
| 392 | 2 |  |  | 2 | 1 | 12 | my ($count) = @_; | 
| 393 |  |  |  |  |  |  |  | 
| 394 | 2 |  |  |  |  | 5 | lock $plan if THREADSAFE; | 
| 395 |  |  |  |  |  |  |  | 
| 396 | 2 | 100 |  |  |  | 15 | $count = $test unless defined $count; | 
| 397 | 2 | 50 |  |  |  | 15 | croak("Number of tests must be a positive integer.  You gave it '$count'") | 
| 398 |  |  |  |  |  |  | unless $count =~ /^\+?[0-9]+$/; | 
| 399 |  |  |  |  |  |  |  | 
| 400 | 2 | 100 | 66 |  |  | 22 | if (not defined $plan or $plan == NO_PLAN) { | 
| 401 | 1 |  |  |  |  | 2 | $plan         = $count; # $plan can't be NO_PLAN anymore | 
| 402 | 1 |  |  |  |  | 3 | $done_testing = 1; | 
| 403 | 1 |  |  |  |  | 4 | local $\; | 
| 404 | 1 |  |  |  |  | 241 | print $TAP_STREAM "1..$plan\n"; | 
| 405 |  |  |  |  |  |  | } else { | 
| 406 | 1 | 50 |  |  |  | 17 | if ($done_testing) { | 
|  |  | 50 |  |  |  |  |  | 
| 407 | 0 |  |  |  |  | 0 | @_ = ('done_testing() was already called'); | 
| 408 | 0 |  |  |  |  | 0 | goto &fail; | 
| 409 |  |  |  |  |  |  | } elsif ($plan != $count) { | 
| 410 | 0 |  |  |  |  | 0 | @_ = ("planned to run $plan tests but done_testing() expects $count"); | 
| 411 | 0 |  |  |  |  | 0 | goto &fail; | 
| 412 |  |  |  |  |  |  | } | 
| 413 |  |  |  |  |  |  | } | 
| 414 |  |  |  |  |  |  |  | 
| 415 | 2 |  |  |  |  | 214 | return 1; | 
| 416 |  |  |  |  |  |  | } | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =head2 C<ok> | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | ok $ok; | 
| 421 |  |  |  |  |  |  | ok $ok, $desc; | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | See L<Test::More/ok>. | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | =cut | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  | sub ok ($;$) { | 
| 428 | 246 |  |  | 246 | 1 | 40804 | my ($ok, $desc) = @_; | 
| 429 |  |  |  |  |  |  |  | 
| 430 | 246 |  |  |  |  | 259 | lock $plan if THREADSAFE; | 
| 431 |  |  |  |  |  |  |  | 
| 432 | 246 |  |  |  |  | 312 | ++$test; | 
| 433 |  |  |  |  |  |  |  | 
| 434 | 246 |  |  |  |  | 476 | my $test_str = "ok $test"; | 
| 435 | 246 | 100 |  |  |  | 650 | $ok or do { | 
| 436 | 77 |  |  |  |  | 153 | $test_str   = "not $test_str"; | 
| 437 | 77 |  |  |  |  | 132 | ++$failed; | 
| 438 |  |  |  |  |  |  | }; | 
| 439 | 246 | 100 |  |  |  | 565 | if (defined $desc) { | 
| 440 | 28 |  |  |  |  | 111 | _sanitize_comment($desc); | 
| 441 | 28 | 50 |  |  |  | 143 | $test_str .= " - $desc" if length $desc; | 
| 442 |  |  |  |  |  |  | } | 
| 443 |  |  |  |  |  |  |  | 
| 444 | 246 |  |  |  |  | 669 | local $\; | 
| 445 | 246 |  |  |  |  | 24679 | print $TAP_STREAM "$test_str\n"; | 
| 446 |  |  |  |  |  |  |  | 
| 447 | 246 |  |  |  |  | 4282 | return $ok; | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | =head2 C<pass> | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | pass; | 
| 453 |  |  |  |  |  |  | pass $desc; | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | See L<Test::More/pass>. | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  | =cut | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | sub pass (;$) { | 
| 460 | 17 |  |  | 17 | 1 | 1355 | unshift @_, 1; | 
| 461 | 17 |  |  |  |  | 79 | goto &ok; | 
| 462 |  |  |  |  |  |  | } | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =head2 C<fail> | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | fail; | 
| 467 |  |  |  |  |  |  | fail $desc; | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | See L<Test::More/fail>. | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | =cut | 
| 472 |  |  |  |  |  |  |  | 
| 473 |  |  |  |  |  |  | sub fail (;$) { | 
| 474 | 2 |  |  | 2 | 1 | 1299 | unshift @_, 0; | 
| 475 | 2 |  |  |  |  | 8 | goto &ok; | 
| 476 |  |  |  |  |  |  | } | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | =head2 C<is> | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | is $got, $expected; | 
| 481 |  |  |  |  |  |  | is $got, $expected, $desc; | 
| 482 |  |  |  |  |  |  |  | 
| 483 |  |  |  |  |  |  | See L<Test::More/is>. | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | =cut | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | sub is ($$;$) { | 
| 488 | 4 |  |  | 4 | 1 | 24 | my ($got, $expected, $desc) = @_; | 
| 489 | 26 |  |  | 26 |  | 196 | no warnings 'uninitialized'; | 
|  | 26 |  |  |  |  | 79 |  | 
|  | 26 |  |  |  |  | 4559 |  | 
| 490 | 4 |  | 33 |  |  | 41 | @_ = ( | 
| 491 |  |  |  |  |  |  | (not(defined $got xor defined $expected) and $got eq $expected), | 
| 492 |  |  |  |  |  |  | $desc, | 
| 493 |  |  |  |  |  |  | ); | 
| 494 | 4 |  |  |  |  | 14 | goto &ok; | 
| 495 |  |  |  |  |  |  | } | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | =head2 C<isnt> | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | isnt $got, $expected; | 
| 500 |  |  |  |  |  |  | isnt $got, $expected, $desc; | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | See L<Test::More/isnt>. | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | =cut | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | sub isnt ($$;$) { | 
| 507 | 4 |  |  | 4 | 1 | 20 | my ($got, $expected, $desc) = @_; | 
| 508 | 26 |  |  | 26 |  | 185 | no warnings 'uninitialized'; | 
|  | 26 |  |  |  |  | 76 |  | 
|  | 26 |  |  |  |  | 9754 |  | 
| 509 | 4 |  | 66 |  |  | 30 | @_ = ( | 
| 510 |  |  |  |  |  |  | ((defined $got xor defined $expected) or $got ne $expected), | 
| 511 |  |  |  |  |  |  | $desc, | 
| 512 |  |  |  |  |  |  | ); | 
| 513 | 4 |  |  |  |  | 11 | goto &ok; | 
| 514 |  |  |  |  |  |  | } | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  | my %binops = ( | 
| 517 |  |  |  |  |  |  | 'or'  => 'or', | 
| 518 |  |  |  |  |  |  | 'xor' => 'xor', | 
| 519 |  |  |  |  |  |  | 'and' => 'and', | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | '||'  => 'hor', | 
| 522 |  |  |  |  |  |  | ('//' => 'dor') x ("$]" >= 5.010), | 
| 523 |  |  |  |  |  |  | '&&'  => 'hand', | 
| 524 |  |  |  |  |  |  |  | 
| 525 |  |  |  |  |  |  | '|'   => 'bor', | 
| 526 |  |  |  |  |  |  | '^'   => 'bxor', | 
| 527 |  |  |  |  |  |  | '&'   => 'band', | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | 'lt'  => 'lt', | 
| 530 |  |  |  |  |  |  | 'le'  => 'le', | 
| 531 |  |  |  |  |  |  | 'gt'  => 'gt', | 
| 532 |  |  |  |  |  |  | 'ge'  => 'ge', | 
| 533 |  |  |  |  |  |  | 'eq'  => 'eq', | 
| 534 |  |  |  |  |  |  | 'ne'  => 'ne', | 
| 535 |  |  |  |  |  |  | 'cmp' => 'cmp', | 
| 536 |  |  |  |  |  |  |  | 
| 537 |  |  |  |  |  |  | '<'   => 'nlt', | 
| 538 |  |  |  |  |  |  | '<='  => 'nle', | 
| 539 |  |  |  |  |  |  | '>'   => 'ngt', | 
| 540 |  |  |  |  |  |  | '>='  => 'nge', | 
| 541 |  |  |  |  |  |  | '=='  => 'neq', | 
| 542 |  |  |  |  |  |  | '!='  => 'nne', | 
| 543 |  |  |  |  |  |  | '<=>' => 'ncmp', | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | '=~'  => 'like', | 
| 546 |  |  |  |  |  |  | '!~'  => 'unlike', | 
| 547 |  |  |  |  |  |  | ('~~' => 'smartmatch') x ("$]" >= 5.010), | 
| 548 |  |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | '+'   => 'add', | 
| 550 |  |  |  |  |  |  | '-'   => 'substract', | 
| 551 |  |  |  |  |  |  | '*'   => 'multiply', | 
| 552 |  |  |  |  |  |  | '/'   => 'divide', | 
| 553 |  |  |  |  |  |  | '%'   => 'modulo', | 
| 554 |  |  |  |  |  |  | '<<'  => 'lshift', | 
| 555 |  |  |  |  |  |  | '>>'  => 'rshift', | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | '.'   => 'concat', | 
| 558 |  |  |  |  |  |  | '..'  => 'flipflop', | 
| 559 |  |  |  |  |  |  | '...' => 'altflipflop', | 
| 560 |  |  |  |  |  |  | ','   => 'comma', | 
| 561 |  |  |  |  |  |  | '=>'  => 'fatcomma', | 
| 562 |  |  |  |  |  |  | ); | 
| 563 |  |  |  |  |  |  |  | 
| 564 |  |  |  |  |  |  | my %binop_handlers; | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | sub _create_binop_handler { | 
| 567 | 65 |  |  | 65 |  | 113 | my ($op) = @_; | 
| 568 | 65 |  |  |  |  | 127 | my $name = $binops{$op}; | 
| 569 | 65 | 50 |  |  |  | 196 | croak("Operator $op not supported") unless defined $name; | 
| 570 |  |  |  |  |  |  | { | 
| 571 | 65 |  |  |  |  | 81 | local $@; | 
|  | 65 |  |  |  |  | 86 |  | 
| 572 | 65 |  |  | 0 | 0 | 6347 | eval <<"IS_BINOP"; | 
|  | 0 |  |  | 4 | 0 | 0 |  | 
|  | 0 |  |  | 4 | 0 | 0 |  | 
|  | 0 |  |  | 4 | 0 | 0 |  | 
|  | 4 |  |  | 4 | 0 | 8 |  | 
|  | 4 |  |  | 1 | 0 | 11 |  | 
|  | 4 |  |  | 3 | 0 | 93 |  | 
|  |  |  |  | 4 | 0 |  |  | 
|  |  |  |  |  | 0 |  |  | 
| 573 |  |  |  |  |  |  | sub is_$name (\$\$;\$) { | 
| 574 |  |  |  |  |  |  | my (\$got, \$expected, \$desc) = \@_; | 
| 575 |  |  |  |  |  |  | \@_ = (scalar(\$got $op \$expected), \$desc); | 
| 576 |  |  |  |  |  |  | goto &ok; | 
| 577 |  |  |  |  |  |  | } | 
| 578 |  |  |  |  |  |  | IS_BINOP | 
| 579 | 65 | 50 |  |  |  | 317 | die $@ if $@; | 
| 580 |  |  |  |  |  |  | } | 
| 581 | 65 |  |  |  |  | 88 | $binop_handlers{$op} = do { | 
| 582 | 26 |  |  | 26 |  | 169 | no strict 'refs'; | 
|  | 26 |  |  |  |  | 56 |  | 
|  | 26 |  |  |  |  | 2281 |  | 
| 583 | 65 |  |  |  |  | 83 | \&{__PACKAGE__."::is_$name"}; | 
|  | 65 |  |  |  |  | 406 |  | 
| 584 |  |  |  |  |  |  | } | 
| 585 |  |  |  |  |  |  | } | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | =head2 C<like> | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | like $got, $regexp_expected; | 
| 590 |  |  |  |  |  |  | like $got, $regexp_expected, $desc; | 
| 591 |  |  |  |  |  |  |  | 
| 592 |  |  |  |  |  |  | See L<Test::More/like>. | 
| 593 |  |  |  |  |  |  |  | 
| 594 |  |  |  |  |  |  | =head2 C<unlike> | 
| 595 |  |  |  |  |  |  |  | 
| 596 |  |  |  |  |  |  | unlike $got, $regexp_expected; | 
| 597 |  |  |  |  |  |  | unlike $got, $regexp_expected, $desc; | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | See L<Test::More/unlike>. | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | =cut | 
| 602 |  |  |  |  |  |  |  | 
| 603 |  |  |  |  |  |  | { | 
| 604 | 26 |  |  | 26 |  | 144 | no warnings 'once'; | 
|  | 26 |  |  |  |  | 55 |  | 
|  | 26 |  |  |  |  | 8807 |  | 
| 605 |  |  |  |  |  |  | *like   = _create_binop_handler('=~'); | 
| 606 |  |  |  |  |  |  | *unlike = _create_binop_handler('!~'); | 
| 607 |  |  |  |  |  |  | } | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | =head2 C<cmp_ok> | 
| 610 |  |  |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | cmp_ok $got, $op, $expected; | 
| 612 |  |  |  |  |  |  | cmp_ok $got, $op, $expected, $desc; | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | See L<Test::More/cmp_ok>. | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | =cut | 
| 617 |  |  |  |  |  |  |  | 
| 618 |  |  |  |  |  |  | sub cmp_ok ($$$;$) { | 
| 619 | 118 |  |  | 118 | 1 | 795 | my ($got, $op, $expected, $desc) = @_; | 
| 620 | 118 |  |  |  |  | 200 | my $handler = $binop_handlers{$op}; | 
| 621 | 118 | 100 |  |  |  | 483 | unless ($handler) { | 
| 622 | 31 |  | 75 |  |  | 94 | local $Test::More::Level = ($Test::More::Level || 0) + 1; | 
| 623 | 31 |  |  |  |  | 113 | $handler = _create_binop_handler($op); | 
| 624 |  |  |  |  |  |  | } | 
| 625 | 122 |  |  |  |  | 516 | @_ = ($got, $expected, $desc); | 
| 626 | 122 |  |  |  |  | 3176 | goto $handler; | 
| 627 |  |  |  |  |  |  | } | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | =head2 C<is_deeply> | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | is_deeply $got, $expected; | 
| 632 |  |  |  |  |  |  | is_deeply $got, $expected, $desc; | 
| 633 |  |  |  |  |  |  |  | 
| 634 |  |  |  |  |  |  | See L<Test::More/is_deeply>. | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | =cut | 
| 637 |  |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  | BEGIN { | 
| 639 | 26 |  |  | 26 |  | 64 | local $@; | 
| 640 | 26 | 50 |  |  |  | 53 | if (eval { require Scalar::Util; 1 }) { | 
|  | 26 |  |  |  |  | 160 |  | 
|  | 26 |  |  |  |  | 200 |  | 
| 641 | 26 |  |  |  |  | 1621 | *_reftype = \&Scalar::Util::reftype; | 
| 642 |  |  |  |  |  |  | } else { | 
| 643 |  |  |  |  |  |  | # Stolen from Scalar::Util::PP | 
| 644 | 0 |  |  |  |  | 0 | require B; | 
| 645 | 0 |  |  |  |  | 0 | my %tmap = qw< | 
| 646 |  |  |  |  |  |  | B::NULL   SCALAR | 
| 647 |  |  |  |  |  |  |  | 
| 648 |  |  |  |  |  |  | B::HV     HASH | 
| 649 |  |  |  |  |  |  | B::AV     ARRAY | 
| 650 |  |  |  |  |  |  | B::CV     CODE | 
| 651 |  |  |  |  |  |  | B::IO     IO | 
| 652 |  |  |  |  |  |  | B::GV     GLOB | 
| 653 |  |  |  |  |  |  | B::REGEXP REGEXP | 
| 654 |  |  |  |  |  |  | >; | 
| 655 |  |  |  |  |  |  | *_reftype = sub ($) { | 
| 656 | 0 |  |  |  |  | 0 | my $r = shift; | 
| 657 |  |  |  |  |  |  |  | 
| 658 | 0 | 0 |  |  |  | 0 | return undef unless length ref $r; | 
| 659 |  |  |  |  |  |  |  | 
| 660 | 0 |  |  |  |  | 0 | my $t = ref B::svref_2object($r); | 
| 661 |  |  |  |  |  |  |  | 
| 662 | 0 | 0 |  |  |  | 0 | return exists $tmap{$t} ? $tmap{$t} | 
|  |  | 0 |  |  |  |  |  | 
| 663 |  |  |  |  |  |  | : length ref $$r ? 'REF' | 
| 664 |  |  |  |  |  |  | : 'SCALAR' | 
| 665 |  |  |  |  |  |  | } | 
| 666 | 0 |  |  |  |  | 0 | } | 
| 667 |  |  |  |  |  |  | } | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | sub _deep_ref_check { | 
| 670 | 5443 |  |  | 5443 |  | 8471 | my ($x, $y, $ry) = @_; | 
| 671 |  |  |  |  |  |  |  | 
| 672 | 26 |  |  | 26 |  | 160 | no warnings qw<numeric uninitialized>; | 
|  | 26 |  |  |  |  | 65 |  | 
|  | 26 |  |  |  |  | 12623 |  | 
| 673 |  |  |  |  |  |  |  | 
| 674 | 5443 | 100 | 66 |  |  | 20003 | if ($ry eq 'ARRAY') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 675 | 1153 | 100 |  |  |  | 2952 | return 0 unless $#$x == $#$y; | 
| 676 |  |  |  |  |  |  |  | 
| 677 | 1143 |  |  |  |  | 1471 | my ($ex, $ey); | 
| 678 | 1143 |  |  |  |  | 2504 | for (0 .. $#$y) { | 
| 679 | 3351 |  |  |  |  | 16529 | $ex = $x->[$_]; | 
| 680 | 3351 |  |  |  |  | 4416 | $ey = $y->[$_]; | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | # Inline the beginning of _deep_check | 
| 683 | 3351 | 100 | 100 |  |  | 20777 | return 0 if defined $ex xor defined $ey; | 
| 684 |  |  |  |  |  |  |  | 
| 685 | 3338 | 100 | 50 |  |  | 40141 | next if not(ref $ex xor ref $ey) and $ex eq $ey; | 
|  |  |  | 66 |  |  |  |  | 
| 686 |  |  |  |  |  |  |  | 
| 687 | 2198 |  |  |  |  | 4719 | $ry = _reftype($ey); | 
| 688 | 2198 | 50 |  |  |  | 5471 | return 0 if _reftype($ex) ne $ry; | 
| 689 |  |  |  |  |  |  |  | 
| 690 | 2205 | 100 | 100 |  |  | 7338 | return 0 unless $ry and _deep_ref_check($ex, $ey, $ry); | 
| 691 |  |  |  |  |  |  | } | 
| 692 |  |  |  |  |  |  |  | 
| 693 | 1138 |  |  |  |  | 8611 | return 1; | 
| 694 |  |  |  |  |  |  | } elsif ($ry eq 'HASH') { | 
| 695 | 2137 | 100 |  |  |  | 8147 | return 0 unless keys(%$x) == keys(%$y); | 
| 696 |  |  |  |  |  |  |  | 
| 697 | 2120 |  |  |  |  | 2264 | my ($ex, $ey); | 
| 698 | 2120 |  |  |  |  | 4988 | for (keys %$y) { | 
| 699 | 2124 | 100 |  |  |  | 4434 | return 0 unless exists $x->{$_}; | 
| 700 | 2119 |  |  |  |  | 3065 | $ex = $x->{$_}; | 
| 701 | 2119 |  |  |  |  | 3353 | $ey = $y->{$_}; | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | # Inline the beginning of _deep_check | 
| 704 | 2119 | 100 | 100 |  |  | 8742 | return 0 if defined $ex xor defined $ey; | 
| 705 |  |  |  |  |  |  |  | 
| 706 | 2115 | 100 | 100 |  |  | 15262 | next if not(ref $ex xor ref $ey) and $ex eq $ey; | 
|  |  |  | 100 |  |  |  |  | 
| 707 |  |  |  |  |  |  |  | 
| 708 | 2108 |  |  |  |  | 5207 | $ry = _reftype($ey); | 
| 709 | 2108 | 100 |  |  |  | 5507 | return 0 if _reftype($ex) ne $ry; | 
| 710 |  |  |  |  |  |  |  | 
| 711 | 2106 | 100 | 100 |  |  | 6700 | return 0 unless $ry and _deep_ref_check($ex, $ey, $ry); | 
| 712 |  |  |  |  |  |  | } | 
| 713 |  |  |  |  |  |  |  | 
| 714 | 2101 |  |  |  |  | 13055 | return 1; | 
| 715 |  |  |  |  |  |  | } elsif ($ry eq 'SCALAR' or $ry eq 'REF') { | 
| 716 | 2160 |  |  |  |  | 4144 | return _deep_check($$x, $$y); | 
| 717 |  |  |  |  |  |  | } | 
| 718 |  |  |  |  |  |  |  | 
| 719 | 0 |  |  |  |  | 0 | return 0; | 
| 720 |  |  |  |  |  |  | } | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | sub _deep_check { | 
| 723 | 2258 |  |  | 2272 |  | 3081 | my ($x, $y) = @_; | 
| 724 |  |  |  |  |  |  |  | 
| 725 | 26 |  |  | 26 |  | 161 | no warnings qw<numeric uninitialized>; | 
|  | 26 |  |  |  |  | 50 |  | 
|  | 26 |  |  |  |  | 26626 |  | 
| 726 |  |  |  |  |  |  |  | 
| 727 | 2258 | 100 | 100 |  |  | 9806 | return 0 if defined $x xor defined $y; | 
| 728 |  |  |  |  |  |  |  | 
| 729 |  |  |  |  |  |  | # Try object identity/eq overloading first. It also covers the case where | 
| 730 |  |  |  |  |  |  | # $x and $y are both undefined. | 
| 731 |  |  |  |  |  |  | # If either $x or $y is overloaded but none has eq overloading, the test will | 
| 732 |  |  |  |  |  |  | # break at that point. | 
| 733 | 2254 | 100 | 100 |  |  | 24018 | return 1 if not(ref $x xor ref $y) and $x eq $y; | 
|  |  |  | 100 |  |  |  |  | 
| 734 |  |  |  |  |  |  |  | 
| 735 |  |  |  |  |  |  | # Test::More::is_deeply happily breaks encapsulation if the objects aren't | 
| 736 |  |  |  |  |  |  | # overloaded. | 
| 737 | 1168 |  |  |  |  | 3652 | my $ry = _reftype($y); | 
| 738 | 1168 | 100 |  |  |  | 3024 | return 0 if _reftype($x) ne $ry; | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | # Shortcut if $x and $y are both not references and failed the previous | 
| 741 |  |  |  |  |  |  | # $x eq $y test. | 
| 742 | 1158 | 100 |  |  |  | 2265 | return 0 unless $ry; | 
| 743 |  |  |  |  |  |  |  | 
| 744 |  |  |  |  |  |  | # We know that $x and $y are both references of type $ry, without overloading. | 
| 745 | 1140 |  |  |  |  | 2054 | _deep_ref_check($x, $y, $ry); | 
| 746 |  |  |  |  |  |  | } | 
| 747 |  |  |  |  |  |  |  | 
| 748 |  |  |  |  |  |  | sub is_deeply { | 
| 749 | 98 |  |  | 105 | 1 | 150211 | @_ = ( | 
| 750 |  |  |  |  |  |  | &_deep_check, | 
| 751 |  |  |  |  |  |  | $_[2], | 
| 752 |  |  |  |  |  |  | ); | 
| 753 | 98 |  |  |  |  | 347 | goto &ok; | 
| 754 |  |  |  |  |  |  | } | 
| 755 |  |  |  |  |  |  |  | 
| 756 |  |  |  |  |  |  | sub _diag_fh { | 
| 757 | 2 |  |  | 16 |  | 3 | my $fh = shift; | 
| 758 |  |  |  |  |  |  |  | 
| 759 | 2 | 50 |  |  |  | 6 | return unless @_; | 
| 760 |  |  |  |  |  |  |  | 
| 761 | 2 |  |  |  |  | 3 | lock $plan if THREADSAFE; | 
| 762 | 2 | 50 |  |  |  | 5 | return if $no_diag; | 
| 763 |  |  |  |  |  |  |  | 
| 764 | 2 | 50 |  |  |  | 4 | my $msg = join '', map { defined($_) ? $_ : 'undef' } @_; | 
|  | 2 |  |  |  |  | 11 |  | 
| 765 | 2 |  |  |  |  | 5 | _sanitize_comment($msg); | 
| 766 | 2 | 50 |  |  |  | 4 | return unless length $msg; | 
| 767 |  |  |  |  |  |  |  | 
| 768 | 2 |  |  |  |  | 6 | local $\; | 
| 769 | 2 |  |  |  |  | 55 | print $fh "# $msg\n"; | 
| 770 |  |  |  |  |  |  |  | 
| 771 | 2 |  |  |  |  | 88 | return 0; | 
| 772 |  |  |  |  |  |  | }; | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | =head2 C<diag> | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | diag @lines; | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | See L<Test::More/diag>. | 
| 779 |  |  |  |  |  |  |  | 
| 780 |  |  |  |  |  |  | =cut | 
| 781 |  |  |  |  |  |  |  | 
| 782 |  |  |  |  |  |  | sub diag { | 
| 783 | 1 |  |  | 8 | 1 | 5 | unshift @_, $DIAG_STREAM; | 
| 784 | 1 |  |  |  |  | 2 | goto &_diag_fh; | 
| 785 |  |  |  |  |  |  | } | 
| 786 |  |  |  |  |  |  |  | 
| 787 |  |  |  |  |  |  | =head2 C<note> | 
| 788 |  |  |  |  |  |  |  | 
| 789 |  |  |  |  |  |  | note @lines; | 
| 790 |  |  |  |  |  |  |  | 
| 791 |  |  |  |  |  |  | See L<Test::More/note>. | 
| 792 |  |  |  |  |  |  |  | 
| 793 |  |  |  |  |  |  | =cut | 
| 794 |  |  |  |  |  |  |  | 
| 795 |  |  |  |  |  |  | sub note { | 
| 796 | 1 |  |  | 15 | 1 | 9 | unshift @_, $TAP_STREAM; | 
| 797 | 1 |  |  |  |  | 6 | goto &_diag_fh; | 
| 798 |  |  |  |  |  |  | } | 
| 799 |  |  |  |  |  |  |  | 
| 800 |  |  |  |  |  |  | =head2 C<BAIL_OUT> | 
| 801 |  |  |  |  |  |  |  | 
| 802 |  |  |  |  |  |  | BAIL_OUT; | 
| 803 |  |  |  |  |  |  | BAIL_OUT $desc; | 
| 804 |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  | See L<Test::More/BAIL_OUT>. | 
| 806 |  |  |  |  |  |  |  | 
| 807 |  |  |  |  |  |  | =cut | 
| 808 |  |  |  |  |  |  |  | 
| 809 |  |  |  |  |  |  | sub BAIL_OUT { | 
| 810 | 2 |  |  | 5 | 1 | 1855 | my ($desc) = @_; | 
| 811 |  |  |  |  |  |  |  | 
| 812 | 2 |  |  |  |  | 3 | lock $plan if THREADSAFE; | 
| 813 |  |  |  |  |  |  |  | 
| 814 | 2 |  |  |  |  | 6 | my $bail_out_str = 'Bail out!'; | 
| 815 | 2 | 100 |  |  |  | 9 | if (defined $desc) { | 
| 816 | 1 |  |  |  |  | 6 | _sanitize_comment($desc); | 
| 817 | 1 | 50 |  |  |  | 6 | $bail_out_str  .= "  $desc" if length $desc; # Two spaces | 
| 818 |  |  |  |  |  |  | } | 
| 819 |  |  |  |  |  |  |  | 
| 820 | 2 |  |  |  |  | 6 | local $\; | 
| 821 | 2 |  |  |  |  | 8 | print $TAP_STREAM "$bail_out_str\n"; | 
| 822 |  |  |  |  |  |  |  | 
| 823 | 2 |  |  |  |  | 10 | exit 255; | 
| 824 |  |  |  |  |  |  | } | 
| 825 |  |  |  |  |  |  |  | 
| 826 |  |  |  |  |  |  | END { | 
| 827 | 25 | 50 | 33 | 25 |  | 68412 | if ($main_process == $$ and not $?) { | 
| 828 | 25 |  |  |  |  | 59 | lock $plan if THREADSAFE; | 
| 829 |  |  |  |  |  |  |  | 
| 830 | 25 | 100 |  |  |  | 146 | if (defined $plan) { | 
| 831 | 16 | 50 |  |  |  | 118 | if ($failed) { | 
|  |  | 100 |  |  |  |  |  | 
| 832 | 0 | 0 |  |  |  | 0 | $? = $failed <= 254 ? $failed : 254; | 
| 833 |  |  |  |  |  |  | } elsif ($plan >= 0) { | 
| 834 | 11 | 50 |  |  |  | 61 | $? = $test == $plan ? 0 : 255; | 
| 835 |  |  |  |  |  |  | } | 
| 836 | 16 | 100 |  |  |  | 8 | if ($plan == NO_PLAN) { | 
| 837 | 2 |  |  |  |  | 10 | local $\; | 
| 838 | 2 |  |  |  |  | 0 | print $TAP_STREAM "1..$test\n"; | 
| 839 |  |  |  |  |  |  | } | 
| 840 |  |  |  |  |  |  | } | 
| 841 |  |  |  |  |  |  | } | 
| 842 |  |  |  |  |  |  | } | 
| 843 |  |  |  |  |  |  |  | 
| 844 |  |  |  |  |  |  | =pod | 
| 845 |  |  |  |  |  |  |  | 
| 846 |  |  |  |  |  |  | L<Test::Leaner> also provides some functions of its own, which are never exported. | 
| 847 |  |  |  |  |  |  |  | 
| 848 |  |  |  |  |  |  | =head2 C<tap_stream> | 
| 849 |  |  |  |  |  |  |  | 
| 850 |  |  |  |  |  |  | my $tap_fh = tap_stream; | 
| 851 |  |  |  |  |  |  | tap_stream $fh; | 
| 852 |  |  |  |  |  |  |  | 
| 853 |  |  |  |  |  |  | Read/write accessor for the filehandle to which the tests are outputted. | 
| 854 |  |  |  |  |  |  | On write, it also turns autoflush on onto C<$fh>. | 
| 855 |  |  |  |  |  |  |  | 
| 856 |  |  |  |  |  |  | Note that it can only be used as a write accessor before you start any thread, as L<threads::shared> cannot reliably share filehandles. | 
| 857 |  |  |  |  |  |  |  | 
| 858 |  |  |  |  |  |  | Defaults to C<STDOUT>. | 
| 859 |  |  |  |  |  |  |  | 
| 860 |  |  |  |  |  |  | =cut | 
| 861 |  |  |  |  |  |  |  | 
| 862 |  |  |  |  |  |  | sub tap_stream (;*) { | 
| 863 | 29 | 50 |  | 29 | 1 | 11850 | if (@_) { | 
| 864 | 29 |  |  |  |  | 68 | $TAP_STREAM = $_[0]; | 
| 865 |  |  |  |  |  |  |  | 
| 866 | 29 |  |  |  |  | 126 | my $fh = select $TAP_STREAM; | 
| 867 | 29 |  |  |  |  | 115 | $|++; | 
| 868 | 29 |  |  |  |  | 118 | select $fh; | 
| 869 |  |  |  |  |  |  | } | 
| 870 |  |  |  |  |  |  |  | 
| 871 | 29 |  |  |  |  | 71 | return $TAP_STREAM; | 
| 872 |  |  |  |  |  |  | } | 
| 873 |  |  |  |  |  |  |  | 
| 874 |  |  |  |  |  |  | tap_stream *STDOUT; | 
| 875 |  |  |  |  |  |  |  | 
| 876 |  |  |  |  |  |  | =head2 C<diag_stream> | 
| 877 |  |  |  |  |  |  |  | 
| 878 |  |  |  |  |  |  | my $diag_fh = diag_stream; | 
| 879 |  |  |  |  |  |  | diag_stream $fh; | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | Read/write accessor for the filehandle to which the diagnostics are printed. | 
| 882 |  |  |  |  |  |  | On write, it also turns autoflush on onto C<$fh>. | 
| 883 |  |  |  |  |  |  |  | 
| 884 |  |  |  |  |  |  | Just like L</tap_stream>, it can only be used as a write accessor before you start any thread, as L<threads::shared> cannot reliably share filehandles. | 
| 885 |  |  |  |  |  |  |  | 
| 886 |  |  |  |  |  |  | Defaults to C<STDERR>. | 
| 887 |  |  |  |  |  |  |  | 
| 888 |  |  |  |  |  |  | =cut | 
| 889 |  |  |  |  |  |  |  | 
| 890 |  |  |  |  |  |  | sub diag_stream (;*) { | 
| 891 | 24 | 50 |  | 24 | 1 | 118 | if (@_) { | 
| 892 | 24 |  |  |  |  | 57 | $DIAG_STREAM = $_[0]; | 
| 893 |  |  |  |  |  |  |  | 
| 894 | 24 |  |  |  |  | 83 | my $fh = select $DIAG_STREAM; | 
| 895 | 24 |  |  |  |  | 63 | $|++; | 
| 896 | 24 |  |  |  |  | 454 | select $fh; | 
| 897 |  |  |  |  |  |  | } | 
| 898 |  |  |  |  |  |  |  | 
| 899 | 24 |  |  |  |  | 78 | return $DIAG_STREAM; | 
| 900 |  |  |  |  |  |  | } | 
| 901 |  |  |  |  |  |  |  | 
| 902 |  |  |  |  |  |  | diag_stream *STDERR; | 
| 903 |  |  |  |  |  |  |  | 
| 904 |  |  |  |  |  |  | =head2 C<THREADSAFE> | 
| 905 |  |  |  |  |  |  |  | 
| 906 |  |  |  |  |  |  | This constant evaluates to true if and only if L<Test::Leaner> is thread-safe, i.e. when this version of C<perl> is at least 5.8, has been compiled with C<useithreads> defined, and L<threads> has been loaded B<before> L<Test::Leaner>. | 
| 907 |  |  |  |  |  |  | In that case, it also needs a working L<threads::shared>. | 
| 908 |  |  |  |  |  |  |  | 
| 909 |  |  |  |  |  |  | =head1 DEPENDENCIES | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | L<perl> 5.6. | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | L<Exporter>, L<Test::More>. | 
| 914 |  |  |  |  |  |  |  | 
| 915 |  |  |  |  |  |  | =head1 AUTHOR | 
| 916 |  |  |  |  |  |  |  | 
| 917 |  |  |  |  |  |  | Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>. | 
| 918 |  |  |  |  |  |  |  | 
| 919 |  |  |  |  |  |  | You can contact me by mail or on C<irc.perl.org> (vincent). | 
| 920 |  |  |  |  |  |  |  | 
| 921 |  |  |  |  |  |  | =head1 BUGS | 
| 922 |  |  |  |  |  |  |  | 
| 923 |  |  |  |  |  |  | Please report any bugs or feature requests to C<bug-test-leaner at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Leaner>. | 
| 924 |  |  |  |  |  |  | I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. | 
| 925 |  |  |  |  |  |  |  | 
| 926 |  |  |  |  |  |  | =head1 SUPPORT | 
| 927 |  |  |  |  |  |  |  | 
| 928 |  |  |  |  |  |  | You can find documentation for this module with the perldoc command. | 
| 929 |  |  |  |  |  |  |  | 
| 930 |  |  |  |  |  |  | perldoc Test::Leaner | 
| 931 |  |  |  |  |  |  |  | 
| 932 |  |  |  |  |  |  | =head1 COPYRIGHT & LICENSE | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  | Copyright 2010,2011,2013 Vincent Pit, all rights reserved. | 
| 935 |  |  |  |  |  |  |  | 
| 936 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. | 
| 937 |  |  |  |  |  |  |  | 
| 938 |  |  |  |  |  |  | Except for the fallback implementation of the internal C<_reftype> function, which has been taken from L<Scalar::Util> and is | 
| 939 |  |  |  |  |  |  |  | 
| 940 |  |  |  |  |  |  | Copyright 1997-2007 Graham Barr, all rights reserved. | 
| 941 |  |  |  |  |  |  |  | 
| 942 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. | 
| 943 |  |  |  |  |  |  |  | 
| 944 |  |  |  |  |  |  | =cut | 
| 945 |  |  |  |  |  |  |  | 
| 946 |  |  |  |  |  |  | 1; # End of Test::Leaner |