12 if ($] >= 5.008 and $INC{'threads.pm'}) {
13 my $use_ithreads = do {
16 $Config::Config{useithreads};
19 require threads::shared;
20 *THREADSAFE = sub () { 1 };
23 unless (defined &Test::Leaner::THREADSAFE) {
24 *THREADSAFE = sub () { 0 }
28 my $TAP_STREAM = *STDOUT;
29 my $DIAG_STREAM = *STDERR;
31 for ($TAP_STREAM, $DIAG_STREAM) {
37 my ($plan, $test, $failed, $no_diag, $done_testing);
40 sub SKIP_ALL () { -2 }
44 threads::shared::share($_) for $plan, $test, $failed, $no_diag, $done_testing;
47 lock $plan if THREADSAFE;
55 my $level = 1 + ($Test::Builder::Level || 0);
56 my ($file, $line) = (caller $level)[1, 2];
57 warn @_, " at $file line $line.\n";
61 my $level = 1 + ($Test::Builder::Level || 0);
62 my ($file, $line) = (caller $level)[1, 2];
63 die @_, " at $file line $line.\n";
66 sub sanitize_comment {
73 my ($key, $value) = @_;
77 lock $plan if THREADSAFE;
79 croak("You tried to plan twice") if defined $plan;
83 if ($key eq 'no_plan') {
84 croak("no_plan takes no arguments") if $value;
86 } elsif ($key eq 'tests') {
87 croak("Got an undefined number of tests") unless defined $value;
88 croak("You said to run 0 tests") unless $value;
89 croak("Number of tests must be a positive integer. You gave it '$value'")
90 unless $value =~ /^\+?[0-9]+$/;
92 $plan_str = "1..$value";
93 } elsif ($key eq 'skip_all') {
95 $plan_str = '1..0 # SKIP';
97 sanitize_comment($value);
98 $plan_str .= " $value" if length $value;
101 my @args = grep defined, $key, $value;
102 croak("plan() doesn't understand @args");
105 if (defined $plan_str) {
107 print $TAP_STREAM "$plan_str\n";
110 exit 0 if $plan == SKIP_ALL;
142 if ($item eq 'import') {
143 push @imports, @{ $_[$i+1] };
145 } elsif ($item eq 'no_diag') {
146 lock $plan if THREADSAFE;
152 splice @_, $i, $splice;
159 local $Test::Builder::Level = ($Test::Builder::Level || 0) + 1;
163 @_ = ($class, @imports);
164 goto &Exporter::import;
168 @_ = (skip_all => $_[0]);
173 my ($reason, $count) = @_;
175 lock $plan if THREADSAFE;
177 if (not defined $count) {
178 carp("skip() needs to know \$how_many tests are in the block")
179 unless defined $plan and $plan == NO_PLAN;
181 } elsif ($count =~ /[^0-9]/) {
182 carp('skip() was passed a non-numeric number of tests. Did you get the arguments backwards?');
189 my $skip_str = "ok $test # skip";
190 if (defined $reason) {
191 sanitize_comment($reason);
192 $skip_str .= " $reason" if length $reason;
196 print $TAP_STREAM "$skip_str\n";
199 no warnings 'exiting';
206 lock $plan if THREADSAFE;
208 $count = $test unless defined $count;
209 croak("Number of tests must be a positive integer. You gave it '$count'")
210 unless $count =~ /^\+?[0-9]+$/;
212 if (not defined $plan or $plan == NO_PLAN) {
213 $plan = $count; # $plan can't be NO_PLAN anymore
216 print $TAP_STREAM "1..$plan\n";
219 @_ = ('done_testing() was already called');
221 } elsif ($plan != $count) {
222 @_ = ("planned to run $plan tests but done_testing() expects $count");
231 my ($ok, $desc) = @_;
233 lock $plan if THREADSAFE;
237 my $test_str = "ok $test";
239 $test_str = "not $test_str";
243 sanitize_comment($desc);
244 $test_str .= " - $desc" if length $desc;
248 print $TAP_STREAM "$test_str\n";
264 my ($got, $expected, $desc) = @_;
265 no warnings 'uninitialized';
267 (not(defined $got xor defined $expected) and $got eq $expected),
274 my ($got, $expected, $desc) = @_;
275 no warnings 'uninitialized';
277 ((defined $got xor defined $expected) or $got ne $expected),
309 '~~' => 'smartmatch',
314 sub _create_binop_handler {
316 my $name = $binops{$op};
317 croak("Operator $op not supported") unless defined $name;
321 sub is_$name (\$\$;\$) {
322 my (\$got, \$expected, \$desc) = \@_;
323 \@_ = ((\$got $op \$expected), \$desc);
329 $binop_handlers{$op} = do {
331 \&{__PACKAGE__."::is_$name"};
337 *like = _create_binop_handler('=~');
338 *unlike = _create_binop_handler('!~');
342 my ($got, $op, $expected, $desc) = @_;
343 my $handler = $binop_handlers{$op};
345 local $Test::More::Level = ($Test::More::Level || 0) + 1;
346 $handler = _create_binop_handler($op);
348 @_ = ($got, $expected, $desc);
357 lock $plan if THREADSAFE;
360 my $msg = join '', map { defined($_) ? $_ : 'undef' } @_;
361 sanitize_comment($msg);
362 return unless length $msg;
365 print $fh "# $msg\n";
371 unshift @_, $DIAG_STREAM;
376 unshift @_, $TAP_STREAM;
383 lock $plan if THREADSAFE;
385 my $bail_out_str = 'Bail out!';
387 sanitize_comment($desc);
388 $bail_out_str .= " $desc" if length $desc; # Two spaces
392 print $TAP_STREAM "$bail_out_str\n";
399 lock $plan if THREADSAFE;
403 $? = $failed <= 254 ? $failed : 254;
404 } elsif ($plan >= 0) {
405 $? = $test == $plan ? 0 : 255;
406 } elsif ($plan == NO_PLAN) {
408 print $TAP_STREAM "1..$test\n";
414 1; # End of Test::Leaner