10
my @test_more_exports;
12
@test_more_exports = qw(
13
ok isnt like unlike is_deeply cmp_ok
14
skip todo_skip pass fail
15
eq_array eq_hash eq_set
16
plan can_ok isa_ok diag
22
use Test::More import => \@test_more_exports;
25
our @EXPORT = (@test_more_exports, qw(
28
blocks next_block first_block
29
delimiters spec_file spec_string
30
filters filters_delay filter_arguments
31
run run_compare run_is run_is_deeply run_like run_unlike
32
skip_all_unless_require is_deep run_is_deep
34
tie_output no_diag_on_only
36
find_my_self default_object
38
croak carp cluck confess
43
field _filters => [qw(norm trim)];
44
field _filters_map => {};
46
-init => '$self->_spec_init';
48
-init => '$self->_block_list_init';
49
field _next_list => [];
51
-init => '$self->block_delim_default';
53
-init => '$self->data_delim_default';
54
field _filters_delay => 0;
55
field _no_diag_on_only => 0;
57
field block_delim_default => '===';
58
field data_delim_default => '---';
62
my $reserved_section_names = {};
65
$default_object ||= $default_class->new;
66
return $default_object;
69
my $import_called = 0;
72
my $class = (grep /^-base$/i, @_)
75
if (not defined $default_class) {
76
$default_class = $class;
79
# croak "Can't use $class after using $default_class"
80
# unless $default_class->isa($class);
83
unless (grep /^-base$/i, @_) {
85
for (my $ii = 1; $ii <= $#_; ++$ii) {
86
if ($_[$ii] eq '-package') {
92
Test::More->import(import => \@test_more_exports, @args)
100
# Wrap Test::Builder::plan
101
my $plan_code = \&Test::Builder::plan;
104
no warnings 'redefine';
105
*Test::Builder::plan = sub {
112
$SIG{__DIE__} = sub { $DIED = 1; die @_ };
114
sub block_class { $self->find_class('Block') }
115
sub filter_class { $self->find_class('Filter') }
119
my $class = ref($self) . "::$suffix";
120
return $class if $class->can('new');
121
$class = __PACKAGE__ . "::$suffix";
122
return $class if $class->can('new');
123
eval "require $class";
124
return $class if $class->can('new');
125
die "Can't find a class for $suffix";
129
if ($self->{block_list}) {
130
my $caller = (caller(1))[3];
132
croak "Too late to call $caller()"
137
my $self = ref($_[0]) eq $default_class
144
(my ($self), @_) = find_my_self(@_);
146
croak "Invalid arguments passed to 'blocks'"
148
croak sprintf("'%s' is invalid argument to blocks()", shift(@_))
149
if @_ && $_[0] !~ /^[a-zA-Z]\w*$/;
151
my $blocks = $self->block_list;
153
my $section_name = shift || '';
154
my @blocks = $section_name
155
? (grep { exists $_->{$section_name} } @$blocks)
158
return scalar(@blocks) unless wantarray;
160
return (@blocks) if $self->_filters_delay;
162
for my $block (@blocks) {
164
unless $block->is_filtered;
171
(my ($self), @_) = find_my_self(@_);
172
my $list = $self->_next_list;
174
$list = [@{$self->block_list}, undef];
175
$self->_next_list($list);
177
my $block = shift @$list;
178
if (defined $block and not $block->is_filtered) {
185
(my ($self), @_) = find_my_self(@_);
186
$self->_next_list([]);
190
sub filters_delay() {
191
(my ($self), @_) = find_my_self(@_);
192
$self->_filters_delay(defined $_[0] ? shift : 1);
195
sub no_diag_on_only() {
196
(my ($self), @_) = find_my_self(@_);
197
$self->_no_diag_on_only(defined $_[0] ? shift : 1);
201
(my ($self), @_) = find_my_self(@_);
203
my ($block_delimiter, $data_delimiter) = @_;
204
$block_delimiter ||= $self->block_delim_default;
205
$data_delimiter ||= $self->data_delim_default;
206
$self->block_delim($block_delimiter);
207
$self->data_delim($data_delimiter);
212
(my ($self), @_) = find_my_self(@_);
214
$self->_spec_file(shift);
219
(my ($self), @_) = find_my_self(@_);
221
$self->_spec_string(shift);
226
(my ($self), @_) = find_my_self(@_);
227
if (ref($_[0]) eq 'HASH') {
228
$self->_filters_map(shift);
231
my $filters = $self->_filters;
237
sub filter_arguments() {
238
$Test::Base::Filter::arguments;
242
eval { require Text::Diff; 1 } &&
243
$Text::Diff::VERSION >= 0.35 &&
244
$Algorithm::Diff::VERSION >= 1.15;
248
(my ($self), @_) = find_my_self(@_);
249
my ($actual, $expected, $name) = @_;
250
local $Test::Builder::Level = $Test::Builder::Level + 1;
251
if ($ENV{TEST_SHOW_NO_DIFFS} or
252
not defined $actual or
253
not defined $expected or
254
$actual eq $expected or
255
not($self->have_text_diff) or
258
Test::More::is($actual, $expected, $name);
261
$name = '' unless defined $name;
262
ok $actual eq $expected,
263
$name . "\n" . Text::Diff::diff(\$expected, \$actual);
268
(my ($self), @_) = find_my_self(@_);
269
my $callback = shift;
270
for my $block (@{$self->block_list}) {
271
$block->run_filters unless $block->is_filtered;
272
&{$callback}($block);
276
my $name_error = "Can't determine section names";
278
return @_ if @_ == 2;
279
my $block = $self->first_block
280
or croak $name_error;
282
$_ !~ /^(ONLY|LAST|SKIP)$/;
283
} @{$block->{_section_order}[0] || []};
284
croak "$name_error. Need two sections in first block"
290
plan('no_plan') unless $Have_Plan;
294
run_compare() unless $Have_Plan or $DIED or not $import_called;
298
(my ($self), @_) = find_my_self(@_);
300
my ($x, $y) = $self->_section_names(@_);
301
local $Test::Builder::Level = $Test::Builder::Level + 1;
302
for my $block (@{$self->block_list}) {
303
next unless exists($block->{$x}) and exists($block->{$y});
304
$block->run_filters unless $block->is_filtered;
305
if (ref $block->$x) {
306
is_deeply($block->$x, $block->$y,
307
$block->name ? $block->name : ());
309
elsif (ref $block->$y eq 'Regexp') {
310
my $regexp = ref $y ? $y : $block->$y;
311
like($block->$x, $regexp, $block->name ? $block->name : ());
314
is($block->$x, $block->$y, $block->name ? $block->name : ());
320
(my ($self), @_) = find_my_self(@_);
322
my ($x, $y) = $self->_section_names(@_);
323
local $Test::Builder::Level = $Test::Builder::Level + 1;
324
for my $block (@{$self->block_list}) {
325
next unless exists($block->{$x}) and exists($block->{$y});
326
$block->run_filters unless $block->is_filtered;
327
is($block->$x, $block->$y,
328
$block->name ? $block->name : ()
333
sub run_is_deeply() {
334
(my ($self), @_) = find_my_self(@_);
336
my ($x, $y) = $self->_section_names(@_);
337
for my $block (@{$self->block_list}) {
338
next unless exists($block->{$x}) and exists($block->{$y});
339
$block->run_filters unless $block->is_filtered;
340
is_deeply($block->$x, $block->$y,
341
$block->name ? $block->name : ()
347
(my ($self), @_) = find_my_self(@_);
349
my ($x, $y) = $self->_section_names(@_);
350
for my $block (@{$self->block_list}) {
351
next unless exists($block->{$x}) and defined($y);
352
$block->run_filters unless $block->is_filtered;
353
my $regexp = ref $y ? $y : $block->$y;
354
like($block->$x, $regexp,
355
$block->name ? $block->name : ()
361
(my ($self), @_) = find_my_self(@_);
363
my ($x, $y) = $self->_section_names(@_);
364
for my $block (@{$self->block_list}) {
365
next unless exists($block->{$x}) and defined($y);
366
$block->run_filters unless $block->is_filtered;
367
my $regexp = ref $y ? $y : $block->$y;
368
unlike($block->$x, $regexp,
369
$block->name ? $block->name : ()
374
sub skip_all_unless_require() {
375
(my ($self), @_) = find_my_self(@_);
377
eval "require $module; 1"
379
skip_all => "$module failed to load"
384
(my ($self), @_) = find_my_self(@_);
386
Test::Deep::cmp_deeply(@_);
390
(my ($self), @_) = find_my_self(@_);
392
my ($x, $y) = $self->_section_names(@_);
393
for my $block (@{$self->block_list}) {
394
next unless exists($block->{$x}) and exists($block->{$y});
395
$block->run_filters unless $block->is_filtered;
396
is_deep($block->$x, $block->$y,
397
$block->name ? $block->name : ()
404
return $spec unless $spec =~
405
s/\A\s*<<<(.*?)>>>\s*$//sm;
407
eval "package main; $eval_code";
412
sub _block_list_init {
413
my $spec = $self->spec;
414
$spec = $self->_pre_eval($spec);
415
my $cd = $self->block_delim;
416
my @hunks = ($spec =~ /^(\Q${cd}\E.*?(?=^\Q${cd}\E|\z))/msg);
417
my $blocks = $self->_choose_blocks(@hunks);
418
$self->block_list($blocks); # Need to set early for possible filter use
420
for my $block (@$blocks) {
421
$block->blocks_object($self);
422
$block->seq_num($seq++);
430
my $block = $self->_make_block($hunk);
431
if (exists $block->{ONLY}) {
432
diag "I found ONLY: maybe you're debugging?"
433
unless $self->_no_diag_on_only;
436
next if exists $block->{SKIP};
437
push @$blocks, $block;
438
if (exists $block->{LAST}) {
445
sub _check_reserved {
447
croak "'$id' is a reserved name. Use something else.\n"
448
if $reserved_section_names->{$id} or
454
my $cd = $self->block_delim;
455
my $dd = $self->data_delim;
456
my $block = $self->block_class->new;
457
$hunk =~ s/\A\Q${cd}\E[ \t]*(.*)\s+// or die;
459
my @parts = split /^\Q${dd}\E +\(?(\w+)\)? *(.*)?\n/m, $hunk;
460
my $description = shift @parts;
462
unless ($description =~ /\S/) {
463
$description = $name;
465
$description =~ s/\s*\z//;
466
$block->set_value(description => $description);
468
my $section_map = {};
469
my $section_order = [];
471
my ($type, $filters, $value) = splice(@parts, 0, 3);
472
$self->_check_reserved($type);
473
$value = '' unless defined $value;
474
$filters = '' unless defined $filters;
475
if ($filters =~ /:(\s|\z)/) {
476
croak "Extra lines not allowed in '$type' section"
478
($filters, $value) = split /\s*:(?:\s+|\z)/, $filters, 2;
479
$value = '' unless defined $value;
480
$value =~ s/^\s*(.*?)\s*$/$1/;
482
$section_map->{$type} = {
485
push @$section_order, $type;
486
$block->set_value($type, $value);
488
$block->set_value(name => $name);
489
$block->set_value(_section_map => $section_map);
490
$block->set_value(_section_order => $section_order);
495
return $self->_spec_string
496
if $self->_spec_string;
499
if (my $spec_file = $self->_spec_file) {
500
open FILE, $spec_file or die $!;
514
sub _strict_warnings() {
515
require Filter::Util::Call;
517
Filter::Util::Call::filter_add(
520
my ($data, $end) = ('', '');
521
while (my $status = Filter::Util::Call::filter_read()) {
522
return $status if $status < 0;
523
if (/^__(?:END|DATA)__\r?$/) {
530
$_ = "use strict;use warnings;$data$end";
538
die "No buffer to tie" unless @_;
539
tie $handle, 'Test::Base::Handle', $_[0];
543
$ENV{TEST_SHOW_NO_DIFFS} = 1;
546
package Test::Base::Handle;
550
bless \ $_[0], $class;
557
#===============================================================================
560
# This is the default class for accessing a Test::Base block object.
561
#===============================================================================
562
package Test::Base::Block;
563
our @ISA = qw(Spiffy);
565
our @EXPORT = qw(block_accessor);
571
sub block_accessor() {
572
my $accessor = shift;
574
return if defined &$accessor;
578
Carp::croak "Not allowed to set values for '$accessor'";
580
my @list = @{$self->{$accessor} || []};
587
block_accessor 'name';
588
block_accessor 'description';
589
Spiffy::field 'seq_num';
590
Spiffy::field 'is_filtered';
591
Spiffy::field 'blocks_object';
592
Spiffy::field 'original_values' => {};
596
my $accessor = shift;
597
block_accessor $accessor
598
unless defined &$accessor;
599
$self->{$accessor} = [@_];
603
my $map = $self->_section_map;
604
my $order = $self->_section_order;
605
Carp::croak "Attempt to filter a block twice"
606
if $self->is_filtered;
607
for my $type (@$order) {
608
my $filters = $map->{$type}{filters};
609
my @value = $self->$type;
610
$self->original_values->{$type} = $value[0];
611
for my $filter ($self->_get_filters($type, $filters)) {
612
$Test::Base::Filter::arguments =
613
$filter =~ s/=(.*)$// ? $1 : undef;
614
my $function = "main::$filter";
616
if (defined &$function) {
618
(@value == 1 and not defined($value[0])) ? undef :
621
@value = &$function(@value);
623
@value == 1 and defined($value[0]) and $value[0] =~ /\A(\d+|)\z/
625
if ($value[0] && $_ eq $old) {
626
Test::Base::diag("Filters returning numbers are supposed to do munging \$_: your filter '$function' apparently doesn't.");
632
my $filter_object = $self->blocks_object->filter_class->new;
633
die "Can't find a function or method for '$filter' filter\n"
634
unless $filter_object->can($filter);
635
$filter_object->current_block($self);
636
@value = $filter_object->$filter(@value);
638
# Set the value after each filter since other filters may be
640
$self->set_value($type, @value);
643
$self->is_filtered(1);
648
my $string = shift || '';
649
$string =~ s/\s*(.*?)\s*/$1/;
651
my $map_filters = $self->blocks_object->_filters_map->{$type} || [];
652
$map_filters = [ $map_filters ] unless ref $map_filters;
655
@{$self->blocks_object->_filters},
657
split(/\s+/, $string),
660
last unless length $filter;
661
if ($filter =~ s/^-//) {
662
@filters = grep { $_ ne $filter } @filters;
664
elsif ($filter =~ s/^\+//) {
665
push @append, $filter;
668
push @filters, $filter;
671
return @filters, @append;
675
%$reserved_section_names = map {
677
} keys(%Test::Base::Block::), qw( new DESTROY );