File Coverage

inc/Test/Base.pm
Criterion Covered Total %
statement 218 378 57.6
branch 51 188 27.1
condition 16 83 19.2
subroutine 38 63 60.3
pod 20 29 68.9
total 343 741 46.2


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