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 ($plan, $test, $failed, $no_diag);
31 sub SKIP_ALL () { -2 }
34 threads::shared::share($plan), lock $plan if THREADSAFE;
41 my $TAP_STREAM = *STDOUT;
42 my $DIAG_STREAM = *STDERR;
45 my $level = 1 + ($Test::Builder::Level || 0);
46 my ($file, $line) = (caller $level)[1, 2];
47 warn @_, " at $file line $line.\n";
51 my $level = 1 + ($Test::Builder::Level || 0);
52 my ($file, $line) = (caller $level)[1, 2];
53 die @_, " at $file line $line.\n";
56 sub sanitize_comment {
63 my ($key, $value) = @_;
67 lock $plan if THREADSAFE;
69 croak("You tried to plan twice") if defined $plan;
73 if ($key eq 'no_plan') {
74 croak("no_plan takes no arguments") if $value;
76 } elsif ($key eq 'tests') {
77 croak("Got an undefined number of tests") unless defined $value;
78 croak("You said to run 0 tests") unless $value;
79 croak("Number of tests must be a positive integer. You gave it '$value'")
80 unless $value =~ /^\+?[0-9]+$/;
82 $plan_str = "1..$value";
83 } elsif ($key eq 'skip_all') {
85 $plan_str = '1..0 # SKIP';
87 sanitize_comment($value);
88 $plan_str .= " $value" if length $value;
91 my @args = grep defined, $key, $value;
92 croak("plan() doesn't understand @args");
96 my $fh = select $TAP_STREAM;
101 if (defined $plan_str) {
103 print $TAP_STREAM "$plan_str\n";
106 exit 0 if $plan == SKIP_ALL;
137 if ($item eq 'import') {
138 push @imports, @{ $_[$i+1] };
140 } elsif ($item eq 'no_diag') {
146 splice @_, $i, $splice;
153 local $Test::Builder::Level = ($Test::Builder::Level || 0) + 1;
157 @_ = ($class, @imports);
158 goto &Exporter::import;
162 @_ = (skip_all => $_[0]);
167 my ($reason, $count) = @_;
169 lock $plan if THREADSAFE;
171 if (not defined $count) {
172 carp("skip() needs to know \$how_many tests are in the block")
173 unless defined $plan and $plan == NO_PLAN;
175 } elsif ($count =~ /[^0-9]/) {
176 carp('skip() was passed a non-numeric number of tests. Did you get the arguments backwards?');
181 my $skip_str = "ok $test # skip";
182 if (defined $reason) {
183 sanitize_comment($reason);
184 $skip_str .= " $reason" if length $reason;
188 print $TAP_STREAM "$skip_str\n";
193 no warnings 'exiting';
202 lock $plan if THREADSAFE;
204 $count = $test unless defined $count;
205 croak("Number of tests must be a positive integer. You gave it '$count'")
206 unless $count =~ /^\+?[0-9]+$/;
208 if (not defined $plan or $plan == NO_PLAN) {
209 $plan = $count; # $plan can't be NO_PLAN anymore
212 print $TAP_STREAM "1..$plan\n";
215 @_ = ('done_testing() was already called');
217 } elsif ($plan != $count) {
218 @_ = ("planned to run $plan tests but done_testing() expects $count");
227 my ($ok, $desc) = @_;
229 lock $plan if THREADSAFE;
233 my $test_str = "ok $test";
235 $test_str = "not $test_str";
239 sanitize_comment($desc);
240 $test_str .= " - $desc" if length $desc;
244 print $TAP_STREAM "$test_str\n";
287 '~~' => 'smartmatch',
290 for my $op (sort keys %binops) {
291 my $name = $binops{$op};
294 sub is_$name (\$\$;\$) {
295 my (\$x, \$y, \$desc) = \@_;
296 no warnings 'uninitialized';
298 (not(defined \$x xor defined \$y) and \$x $op \$y),
312 *unlike = \&is_unlike;
316 my ($x, $y, $desc) = @_;
317 no warnings 'uninitialized';
319 ((defined $x xor defined $y) or $x ne $y),
326 my ($x, $op, $y, $desc) = @_;
327 my $name = $binops{$op};
328 croak("Operator $op not supported") unless defined $name;
329 @_ = ($x, $y, $desc);
331 goto &{__PACKAGE__."is_$name"};
339 lock $plan if THREADSAFE;
342 my $msg = join '', map { defined($_) ? $_ : 'undef' } @_;
343 sanitize_comment($msg);
344 return unless length $msg;
347 print $fh "# $msg\n";
353 unshift @_, $DIAG_STREAM;
358 unshift @_, $TAP_STREAM;
365 lock $plan if THREADSAFE;
367 my $bail_out_str = 'Bail out!';
369 sanitize_comment($desc);
370 $bail_out_str .= " $desc" if length $desc; # Two spaces
374 print $TAP_STREAM "$bail_out_str\n";
381 lock $plan if THREADSAFE;
385 $? = $failed <= 254 ? $failed : 254;
386 } elsif ($plan >= 0) {
387 $? = $test == $plan ? 0 : 255;
388 } elsif ($plan == NO_PLAN) {
390 print $TAP_STREAM "1..$test\n";
396 1; # End of Test::Leaner