File Coverage

inc/Test/Base.pm
Criterion Covered Total %
statement 220 384 57.2
branch 56 202 27.7
condition 20 83 24.1
subroutine 38 63 60.3
pod 0 29 0.0
total 334 761 43.8


line stmt bran cond sub pod time code
1             #line 1
2             package Test::Base;
3             our $VERSION = '0.89';
4 5     5   4280  
  5         14  
  5         20  
5 5     5   60 use Spiffy -Base;
  5     5   8  
  5     5   106  
  5         20  
  5         8  
  5         144  
  5         19  
  5         8  
  5         17  
6             use Spiffy ':XXX';
7              
8             my $HAS_PROVIDER;
9 5     5   265 BEGIN {
10             $HAS_PROVIDER = eval "require Test::Builder::Provider; 1";
11 5 50       35  
12 0         0 if ($HAS_PROVIDER) {
13             Test::Builder::Provider->import('provides');
14             }
15 5     5   229 else {
  5         7  
16             *provides = sub { 1 };
17             }
18             }
19              
20              
21             my @test_more_exports;
22 5     5   111 BEGIN {
23             @test_more_exports = qw(
24             ok isnt like unlike is_deeply cmp_ok
25             skip todo_skip pass fail
26             eq_array eq_hash eq_set
27             plan can_ok isa_ok diag
28             use_ok
29             $TODO
30             );
31             }
32 5     5   2547  
  5         13  
  5         49  
33 5     5   31 use Test::More import => \@test_more_exports;
  5         8  
  5         2052  
34             use Carp;
35              
36             our @EXPORT = (@test_more_exports, qw(
37             is no_diff
38              
39             blocks next_block first_block
40             delimiters spec_file spec_string
41             filters filters_delay filter_arguments
42             run run_compare run_is run_is_deeply run_like run_unlike
43             skip_all_unless_require is_deep run_is_deep
44             WWW XXX YYY ZZZ
45             tie_output no_diag_on_only
46              
47             find_my_self default_object
48              
49             croak carp cluck confess
50             ));
51              
52             field '_spec_file';
53             field '_spec_string';
54             field _filters => [qw(norm trim)];
55             field _filters_map => {};
56             field spec =>
57             -init => '$self->_spec_init';
58             field block_list =>
59             -init => '$self->_block_list_init';
60             field _next_list => [];
61             field block_delim =>
62             -init => '$self->block_delim_default';
63             field data_delim =>
64             -init => '$self->data_delim_default';
65             field _filters_delay => 0;
66             field _no_diag_on_only => 0;
67              
68             field block_delim_default => '===';
69             field data_delim_default => '---';
70              
71             my $default_class;
72             my $default_object;
73             my $reserved_section_names = {};
74 12     12 0 19  
75 12   66     43 sub default_object {
76 12         16 $default_object ||= $default_class->new;
77             return $default_object;
78             }
79              
80             my $import_called = 0;
81 5     5   36 sub import() {
82 5 50       32 $import_called = 1;
83             my $class = (grep /^-base$/i, @_)
84             ? scalar(caller)
85 5 50       27 : $_[0];
86 5         9 if (not defined $default_class) {
87             $default_class = $class;
88             }
89             # else {
90             # croak "Can't use $class after using $default_class"
91             # unless $default_class->isa($class);
92             # }
93 5 50       17  
94 5         11 unless (grep /^-base$/i, @_) {
95 5         21 my @args;
96 0 0       0 for (my $ii = 1; $ii <= $#_; ++$ii) {
97 0         0 if ($_[$ii] eq '-package') {
98             ++$ii;
99 0         0 } else {
100             push @args, $_[$ii];
101             }
102 5 50       17 }
103             Test::More->import(import => \@test_more_exports, @args)
104             if @args;
105             }
106 5         18  
107 5         99 _strict_warnings();
108             goto &Spiffy::import;
109             }
110              
111             # Wrap Test::Builder::plan
112             my $plan_code = \&Test::Builder::plan;
113             my $Have_Plan = 0;
114 5     5   34 {
  5         7  
  5         17753  
115             no warnings 'redefine';
116 5     5   14 *Test::Builder::plan = sub {
117 5         22 $Have_Plan = 1;
118             goto &$plan_code;
119             };
120             }
121              
122             my $DIED = 0;
123             $SIG{__DIE__} = sub { $DIED = 1; die @_ };
124 3     3 0 5  
  3         8  
125 28     28 0 40 sub block_class { $self->find_class('Block') }
  28         41  
126             sub filter_class { $self->find_class('Filter') }
127 31     31 0 38  
128 31         34 sub find_class {
129 31         58 my $suffix = shift;
130 31 100       97 my $class = ref($self) . "::$suffix";
131 2         7 return $class if $class->can('new');
132 2 50       8 $class = __PACKAGE__ . "::$suffix";
133 2         110 return $class if $class->can('new');
134 2 50       14 eval "require $class";
135 0         0 return $class if $class->can('new');
136             die "Can't find a class for $suffix";
137             }
138 0     0 0 0  
139 0 0       0 sub check_late {
140 0         0 if ($self->{block_list}) {
141 0         0 my $caller = (caller(1))[3];
142 0         0 $caller =~ s/.*:://;
143             croak "Too late to call $caller()"
144             }
145             }
146              
147 12 50   12 0 40 sub find_my_self() {
148             my $self = ref($_[0]) eq $default_class
149             ? splice(@_, 0, 1)
150 12         35 : default_object();
151             return $self, @_;
152             }
153              
154 2     2 0 63 sub blocks() {
155             (my ($self), @_) = find_my_self(@_);
156 2 50       8  
157             croak "Invalid arguments passed to 'blocks'"
158 2 50 33     8 if @_ > 1;
159             croak sprintf("'%s' is invalid argument to blocks()", shift(@_))
160             if @_ && $_[0] !~ /^[a-zA-Z]\w*$/;
161 2         46  
162             my $blocks = $self->block_list;
163 2   50     14  
164             my $section_name = shift || '';
165 2 50       9 my @blocks = $section_name
  0         0  
166             ? (grep { exists $_->{$section_name} } @$blocks)
167             : (@$blocks);
168 2 50       14  
169             return scalar(@blocks) unless wantarray;
170 0 0       0  
171             return (@blocks) if $self->_filters_delay;
172 0         0  
173 0 0       0 for my $block (@blocks) {
174             $block->run_filters
175             unless $block->is_filtered;
176             }
177 0         0  
178             return (@blocks);
179             }
180              
181 0     0 0 0 sub next_block() {
182 0         0 (my ($self), @_) = find_my_self(@_);
183 0 0       0 my $list = $self->_next_list;
184 0         0 if (@$list == 0) {
  0         0  
185 0         0 $list = [@{$self->block_list}, undef];
186             $self->_next_list($list);
187 0         0 }
188 0 0 0     0 my $block = shift @$list;
189 0         0 if (defined $block and not $block->is_filtered) {
190             $block->run_filters;
191 0         0 }
192             return $block;
193             }
194              
195 0     0 0 0 sub first_block() {
196 0         0 (my ($self), @_) = find_my_self(@_);
197 0         0 $self->_next_list([]);
198             $self->next_block;
199             }
200              
201 0     0 0 0 sub filters_delay() {
202 0 0       0 (my ($self), @_) = find_my_self(@_);
203             $self->_filters_delay(defined $_[0] ? shift : 1);
204             }
205              
206 0     0 0 0 sub no_diag_on_only() {
207 0 0       0 (my ($self), @_) = find_my_self(@_);
208             $self->_no_diag_on_only(defined $_[0] ? shift : 1);
209             }
210              
211 0     0 0 0 sub delimiters() {
212 0         0 (my ($self), @_) = find_my_self(@_);
213 0         0 $self->check_late;
214 0   0     0 my ($block_delimiter, $data_delimiter) = @_;
215 0   0     0 $block_delimiter ||= $self->block_delim_default;
216 0         0 $data_delimiter ||= $self->data_delim_default;
217 0         0 $self->block_delim($block_delimiter);
218 0         0 $self->data_delim($data_delimiter);
219             return $self;
220             }
221              
222 0     0 0 0 sub spec_file() {
223 0         0 (my ($self), @_) = find_my_self(@_);
224 0         0 $self->check_late;
225 0         0 $self->_spec_file(shift);
226             return $self;
227             }
228              
229 0     0 0 0 sub spec_string() {
230 0         0 (my ($self), @_) = find_my_self(@_);
231 0         0 $self->check_late;
232 0         0 $self->_spec_string(shift);
233             return $self;
234             }
235              
236 1     1 0 3 sub filters() {
237 1 50       4 (my ($self), @_) = find_my_self(@_);
238 1         33 if (ref($_[0]) eq 'HASH') {
239             $self->_filters_map(shift);
240             }
241 0         0 else {
242 0         0 my $filters = $self->_filters;
243             push @$filters, @_;
244 1         3 }
245             return $self;
246             }
247              
248 0     0 0 0 sub filter_arguments() {
249             $Test::Base::Filter::arguments;
250             }
251 0     0 0 0  
252 0 0 0     0 sub have_text_diff {
  0         0  
  0         0  
253             eval { require Text::Diff; 1 } &&
254             $Text::Diff::VERSION >= 0.35 &&
255             $Algorithm::Diff::VERSION >= 1.15;
256             }
257              
258             provides 'is';
259 7     7 0 17 sub is($$;$) {
260 7         15 (my ($self), @_) = find_my_self(@_);
261 7 50       17 my ($actual, $expected, $name) = @_;
262 7 50 66     58 local $Test::Builder::Level = $Test::Builder::Level + 1 unless $HAS_PROVIDER;
      66        
      66        
      33        
      33        
263             if ($ENV{TEST_SHOW_NO_DIFFS} or
264             not defined $actual or
265             not defined $expected or
266             $actual eq $expected or
267             not($self->have_text_diff) or
268             $expected !~ /\n./s
269 7         19 ) {
270             Test::More::is($actual, $expected, $name);
271             }
272 0 0       0 else {
273 0         0 $name = '' unless defined $name;
274 0         0 ok $actual eq $expected, $name;
275             diag Text::Diff::diff(\$expected, \$actual);
276             }
277             }
278              
279 2     2 0 6 sub run(&;$) {
280 2         3 (my ($self), @_) = find_my_self(@_);
281 2         5 my $callback = shift;
  2         40  
282 3 50       103 for my $block (@{$self->block_list}) {
283 3         5 $block->run_filters unless $block->is_filtered;
  3         9  
284             &{$callback}($block);
285             }
286             }
287              
288 0     0   0 my $name_error = "Can't determine section names";
289 0 0       0 sub _section_names {
290 0 0       0 return unless defined $self->spec;
291 0 0       0 return @_ if @_ == 2;
292             my $block = $self->first_block
293             or croak $name_error;
294 0         0 my @names = grep {
295 0 0       0 $_ !~ /^(ONLY|LAST|SKIP)$/;
  0         0  
296 0 0       0 } @{$block->{_section_order}[0] || []};
297             croak "$name_error. Need two sections in first block"
298 0         0 unless @names == 2;
299             return @names;
300             }
301 0     0   0  
302 0 0       0 sub _assert_plan {
303             plan('no_plan') unless $Have_Plan;
304             }
305 5     5   2611  
306 5 0 33     125 sub END {
      33        
307             run_compare() unless $Have_Plan or $DIED or not $import_called;
308             }
309              
310 0     0 0 0 sub run_compare() {
311 0 0       0 (my ($self), @_) = find_my_self(@_);
312 0         0 return unless defined $self->spec;
313 0         0 $self->_assert_plan;
314 0         0 my ($x, $y) = $self->_section_names(@_);
315 0         0 local $Test::Builder::Level = $Test::Builder::Level + 1;
  0         0  
316 0 0 0     0 for my $block (@{$self->block_list}) {
317 0 0       0 next unless exists($block->{$x}) and exists($block->{$y});
318 0 0       0 $block->run_filters unless $block->is_filtered;
    0          
319 0 0       0 if (ref $block->$x) {
320             is_deeply($block->$x, $block->$y,
321             $block->name ? $block->name : ());
322             }
323 0 0       0 elsif (ref $block->$y eq 'Regexp') {
324 0 0       0 my $regexp = ref $y ? $y : $block->$y;
325             like($block->$x, $regexp, $block->name ? $block->name : ());
326             }
327 0 0       0 else {
328             is($block->$x, $block->$y, $block->name ? $block->name : ());
329             }
330             }
331             }
332              
333 0     0 0 0 sub run_is() {
334 0         0 (my ($self), @_) = find_my_self(@_);
335 0         0 $self->_assert_plan;
336 0         0 my ($x, $y) = $self->_section_names(@_);
337 0         0 local $Test::Builder::Level = $Test::Builder::Level + 1;
  0         0  
338 0 0 0     0 for my $block (@{$self->block_list}) {
339 0 0       0 next unless exists($block->{$x}) and exists($block->{$y});
340 0 0       0 $block->run_filters unless $block->is_filtered;
341             is($block->$x, $block->$y,
342             $block->name ? $block->name : ()
343             );
344             }
345             }
346              
347 0     0 0 0 sub run_is_deeply() {
348 0         0 (my ($self), @_) = find_my_self(@_);
349 0         0 $self->_assert_plan;
350 0         0 my ($x, $y) = $self->_section_names(@_);
  0         0  
351 0 0 0     0 for my $block (@{$self->block_list}) {
352 0 0       0 next unless exists($block->{$x}) and exists($block->{$y});
353 0 0       0 $block->run_filters unless $block->is_filtered;
354             is_deeply($block->$x, $block->$y,
355             $block->name ? $block->name : ()
356             );
357             }
358             }
359              
360 0     0 0 0 sub run_like() {
361 0         0 (my ($self), @_) = find_my_self(@_);
362 0         0 $self->_assert_plan;
363 0         0 my ($x, $y) = $self->_section_names(@_);
  0         0  
364 0 0 0     0 for my $block (@{$self->block_list}) {
365 0 0       0 next unless exists($block->{$x}) and defined($y);
366 0 0       0 $block->run_filters unless $block->is_filtered;
367 0 0       0 my $regexp = ref $y ? $y : $block->$y;
368             like($block->$x, $regexp,
369             $block->name ? $block->name : ()
370             );
371             }
372             }
373              
374 0     0 0 0 sub run_unlike() {
375 0         0 (my ($self), @_) = find_my_self(@_);
376 0         0 $self->_assert_plan;
377 0         0 my ($x, $y) = $self->_section_names(@_);
  0         0  
378 0 0 0     0 for my $block (@{$self->block_list}) {
379 0 0       0 next unless exists($block->{$x}) and defined($y);
380 0 0       0 $block->run_filters unless $block->is_filtered;
381 0 0       0 my $regexp = ref $y ? $y : $block->$y;
382             unlike($block->$x, $regexp,
383             $block->name ? $block->name : ()
384             );
385             }
386             }
387              
388 0     0 0 0 sub skip_all_unless_require() {
389 0         0 (my ($self), @_) = find_my_self(@_);
390 0 0       0 my $module = shift;
391             eval "require $module; 1"
392             or Test::More::plan(
393             skip_all => "$module failed to load"
394             );
395             }
396              
397 0     0 0 0 sub is_deep() {
398 0         0 (my ($self), @_) = find_my_self(@_);
399 0         0 require Test::Deep;
400             Test::Deep::cmp_deeply(@_);
401             }
402              
403 0     0 0 0 sub run_is_deep() {
404 0         0 (my ($self), @_) = find_my_self(@_);
405 0         0 $self->_assert_plan;
406 0         0 my ($x, $y) = $self->_section_names(@_);
  0         0  
407 0 0 0     0 for my $block (@{$self->block_list}) {
408 0 0       0 next unless exists($block->{$x}) and exists($block->{$y});
409 0 0       0 $block->run_filters unless $block->is_filtered;
410             is_deep($block->$x, $block->$y,
411             $block->name ? $block->name : ()
412             );
413             }
414             }
415 2     2   5  
416 2         3 sub _pre_eval {
417 2 50       6 my $spec = shift;
418 2 50       11 return unless defined $spec;
419             return $spec unless $spec =~
420 0         0 s/\A\s*<<<(.*?)>>>\s*$//sm;
421 0         0 my $eval_code = $1;
422 0 0       0 eval "package main; $eval_code";
423 0         0 croak $@ if $@;
424             return $spec;
425             }
426 2     2   4  
427 2         35 sub _block_list_init {
428 2 50       8 my $spec = $self->spec;
429 2         7 return [] unless defined $spec;
430 2         43 $spec = $self->_pre_eval($spec);
431 2         81 my $cd = $self->block_delim;
432 2         9 my @hunks = ($spec =~ /^(\Q${cd}\E.*?(?=^\Q${cd}\E|\z))/msg);
433 2         61 my $blocks = $self->_choose_blocks(@hunks);
434 2         4 $self->block_list($blocks); # Need to set early for possible filter use
435 2         5 my $seq = 1;
436 3         60 for my $block (@$blocks) {
437 3         47 $block->blocks_object($self);
438             $block->seq_num($seq++);
439 2         9 }
440             return $blocks;
441             }
442 2     2   3  
443 2         5 sub _choose_blocks {
444 2         6 my $blocks = [];
445 3         9 for my $hunk (@_) {
446 3 50       9 my $block = $self->_make_block($hunk);
447 0 0       0 if (exists $block->{ONLY}) {
448             diag "I found ONLY: maybe you're debugging?"
449 0         0 unless $self->_no_diag_on_only;
450             return [$block];
451 3 50       9 }
452 3         13 next if exists $block->{SKIP};
453 3 50       11 push @$blocks, $block;
454 0         0 if (exists $block->{LAST}) {
455             return $blocks;
456             }
457 2         4 }
458             return $blocks;
459             }
460 11     11   13  
461 11         21 sub _check_reserved {
462             my $id = shift;
463 11 50 33     41 croak "'$id' is a reserved name. Use something else.\n"
464             if $reserved_section_names->{$id} or
465             $id =~ /^_/;
466             }
467 3     3   6  
468 3         4 sub _make_block {
469 3         62 my $hunk = shift;
470 3         48 my $cd = $self->block_delim;
471 3         10 my $dd = $self->data_delim;
472 3 50       52 my $block = $self->block_class->new;
473 3         10 $hunk =~ s/\A\Q${cd}\E[ \t]*(.*)\s+// or die;
474 3         69 my $name = $1;
475 3         7 my @parts = split /^\Q${dd}\E +\(?(\w+)\)? *(.*)?\n/m, $hunk;
476 3   50     15 my $description = shift @parts;
477 3 50       7 $description ||= '';
478 3         6 unless ($description =~ /\S/) {
479             $description = $name;
480 3         15 }
481 3         11 $description =~ s/\s*\z//;
482             $block->set_value(description => $description);
483 3         6  
484 3         13 my $section_map = {};
485 3         9 my $section_order = [];
486 11         26 while (@parts) {
487 11         25 my ($type, $filters, $value) = splice(@parts, 0, 3);
488 11 100       23 $self->_check_reserved($type);
489 11 50       17 $value = '' unless defined $value;
490 11 100       29 $filters = '' unless defined $filters;
491 6 50       13 if ($filters =~ /:(\s|\z)/) {
492             croak "Extra lines not allowed in '$type' section"
493 6         23 if $value =~ /\S/;
494 6 50       15 ($filters, $value) = split /\s*:(?:\s+|\z)/, $filters, 2;
495 6         27 $value = '' unless defined $value;
496             $value =~ s/^\s*(.*?)\s*$/$1/;
497 11         29 }
498             $section_map->{$type} = {
499             filters => $filters,
500 11         21 };
501 11         17 push @$section_order, $type;
502             $block->set_value($type, $value);
503 3         10 }
504 3         8 $block->set_value(name => $name);
505 3         9 $block->set_value(_section_map => $section_map);
506 3         8 $block->set_value(_section_order => $section_order);
507             return $block;
508             }
509 2     2   4  
510 2 50       34 sub _spec_init {
511             return $self->_spec_string
512 2         7 if $self->_spec_string;
513 2         4 local $/;
514 2 50       32 my $spec;
515 0 0       0 if (my $spec_file = $self->_spec_file) {
516 0         0 open FILE, $spec_file or die $!;
517 0         0 $spec = <FILE>;
518             close FILE;
519             }
520 2         11 else {
521 2         10 require Scalar::Util;
522 2 50       7 my $handle = Scalar::Util::openhandle( \*main::DATA );
523 2         38 if ($handle) {
524             $spec = <$handle>;
525             }
526 2         18 }
527             return $spec;
528             }
529              
530 5     5   26 sub _strict_warnings() {
531 5         10 require Filter::Util::Call;
532             my $done = 0;
533             Filter::Util::Call::filter_add(
534 5 50   5   25 sub {
535 5         14 return 0 if $done;
536 5         79 my ($data, $end) = ('', '');
537 268 50       333 while (my $status = Filter::Util::Call::filter_read()) {
538 268 100       413 return $status if $status < 0;
539 5         10 if (/^__(?:END|DATA)__\r?$/) {
540 5         14 $end = $_;
541             last;
542 263         264 }
543 263         425 $data .= $_;
544             $_ = '';
545 5         46 }
546 5         169 $_ = "use strict;use warnings;$data$end";
547             $done = 1;
548 5         39 }
549             );
550             }
551              
552 0     0 0 0 sub tie_output() {
553 0 0       0 my $handle = shift;
554 0         0 die "No buffer to tie" unless @_;
555             tie *$handle, 'Test::Base::Handle', $_[0];
556             }
557 0     0 0 0  
558 0         0 sub no_diff {
559             $ENV{TEST_SHOW_NO_DIFFS} = 1;
560             }
561              
562             package Test::Base::Handle;
563              
564 0     0   0 sub TIEHANDLE() {
565 0         0 my $class = shift;
566             bless \ $_[0], $class;
567             }
568 0     0   0  
569 0         0 sub PRINT {
570             $$self .= $_ for @_;
571             }
572              
573             #===============================================================================
574             # Test::Base::Block
575             #
576             # This is the default class for accessing a Test::Base block object.
577             #===============================================================================
578             package Test::Base::Block;
579             our @ISA = qw(Spiffy);
580              
581             our @EXPORT = qw(block_accessor);
582 0     0   0  
583 0         0 sub AUTOLOAD {
584             return;
585             }
586              
587 23     23   34 sub block_accessor() {
588 5     5   63 my $accessor = shift;
  5         10  
  5         840  
589 23 50       103 no strict 'refs';
590             return if defined &$accessor;
591 36     36   323 *$accessor = sub {
592 36 50       61 my $self = shift;
593 0         0 if (@_) {
594             Carp::croak "Not allowed to set values for '$accessor'";
595 36 50       40 }
  36         98  
596             my @list = @{$self->{$accessor} || []};
597 36 100       124 return wantarray
598             ? (@list)
599 23         121 : $list[0];
600             };
601             }
602              
603             block_accessor 'name';
604             block_accessor 'description';
605             Spiffy::field 'seq_num';
606             Spiffy::field 'is_filtered';
607             Spiffy::field 'blocks_object';
608             Spiffy::field 'original_values' => {};
609 51     51   58  
610 5     5   31 sub set_value {
  5         11  
  5         921  
611 51         58 no strict 'refs';
612 51 100       172 my $accessor = shift;
613             block_accessor $accessor
614 51         176 unless defined &$accessor;
615             $self->{$accessor} = [@_];
616             }
617 3     3   5  
618 3         7 sub run_filters {
619 3         16 my $map = $self->_section_map;
620 3 50       50 my $order = $self->_section_order;
621             Carp::croak "Attempt to filter a block twice"
622 3         15 if $self->is_filtered;
623 11         32 for my $type (@$order) {
624 11         50 my $filters = $map->{$type}{filters};
625 11         192 my @value = $self->$type;
626 11         27 $self->original_values->{$type} = $value[0];
627 28 50       55 for my $filter ($self->_get_filters($type, $filters)) {
628             $Test::Base::Filter::arguments =
629 28         44 $filter =~ s/=(.*)$// ? $1 : undef;
630 5     5   33 my $function = "main::$filter";
  5         9  
  5         2468  
631 28 50       92 no strict 'refs';
632 0 0 0     0 if (defined &$function) {
633             local $_ =
634             (@value == 1 and not defined($value[0])) ? undef :
635 0         0 join '', @value;
636 0         0 my $old = $_;
637 0 0 0     0 @value = &$function(@value);
      0        
      0        
638             if (not(@value) or
639             @value == 1 and defined($value[0]) and $value[0] =~ /\A(\d+|)\z/
640 0 0 0     0 ) {
641 0         0 if ($value[0] && $_ eq $old) {
642             Test::Base::diag("Filters returning numbers are supposed to do munging \$_: your filter '$function' apparently doesn't.");
643 0         0 }
644             @value = ($_);
645             }
646             }
647 28         442 else {
648 28 50       51 my $filter_object = $self->blocks_object->filter_class->new;
649             die "Can't find a function or method for '$filter' filter\n"
650 28         483 unless $filter_object->can($filter);
651 28         71 $filter_object->current_block($self);
652             @value = $filter_object->$filter(@value);
653             }
654             # Set the value after each filter since other filters may be
655 28         57 # introspecting.
656             $self->set_value($type, @value);
657             }
658 3         56 }
659             $self->is_filtered(1);
660             }
661 11     11   14  
662 11         15 sub _get_filters {
663 11   100     31 my $type = shift;
664 11         39 my $string = shift || '';
665 11         18 $string =~ s/\s*(.*?)\s*/$1/;
666 11   100     203 my @filters = ();
667 11 50       26 my $map_filters = $self->blocks_object->_filters_map->{$type} || [];
668 11         15 $map_filters = [ $map_filters ] unless ref $map_filters;
669 11         12 my @append = ();
670 11         153 for (
671             @{$self->blocks_object->_filters},
672             @$map_filters,
673             split(/\s+/, $string),
674 28         34 ) {
675 28 50       42 my $filter = $_;
676 28 50       69 last unless length $filter;
    50          
677 0         0 if ($filter =~ s/^-//) {
  0         0  
678             @filters = grep { $_ ne $filter } @filters;
679             }
680 0         0 elsif ($filter =~ s/^\+//) {
681             push @append, $filter;
682             }
683 28         48 else {
684             push @filters, $filter;
685             }
686 11         39 }
687             return @filters, @append;
688             }
689              
690             {
691             %$reserved_section_names = map {
692             ($_, 1);
693             } keys(%Test::Base::Block::), qw( new DESTROY );
694             }
695              
696             1;