File Coverage

blib/lib/Test/Base/Filter.pm
Criterion Covered Total %
statement 190 248 76.6
branch 33 62 53.2
condition 4 9 44.4
subroutine 37 51 72.5
pod 29 39 74.3
total 293 409 71.6


line stmt bran cond sub pod time code
1             #===============================================================================
2             # This is the default class for handling Test::Base data filtering.
3             #===============================================================================
4             package Test::Base::Filter;
5 67     67   8635 use Spiffy -Base;
  67         135  
  67         588  
6 67     67   136385 use Spiffy ':XXX';
  67     67   152  
  67     67   2579  
  67         377  
  67         282  
  67         2333  
  67         325  
  67         114  
  67         305  
7              
8             field 'current_block';
9              
10             our $arguments;
11 19     19 0 37 sub current_arguments {
12 19 100       90 return undef unless defined $arguments;
13 10         25 my $args = $arguments;
14 10         22 $args =~ s/(\\s)/ /g;
15 10         21 $args =~ s/(\\[a-z])/'"' . $1 . '"'/gee;
  2         87  
16 10         28 return $args;
17             }
18              
19 290     290 0 568 sub assert_scalar {
20 290 100       946 return if @_ == 1;
21 1         7 require Carp;
22 1         7 my $filter = (caller(1))[3];
23 1         5 $filter =~ s/.*:://;
24 1         188 Carp::croak "Input to the '$filter' filter must be a scalar, not a list";
25             }
26              
27 2     2   2 sub _apply_deepest {
28 2         4 my $method = shift;
29 2 50       6 return () unless @_;
30 2 100       7 if (ref $_[0] eq 'ARRAY') {
31 1         2 for my $aref (@_) {
32 1         7 @$aref = $self->_apply_deepest($method, @$aref);
33             }
34 1         5 return @_;
35             }
36 1         4 $self->$method(@_);
37             }
38              
39 0     0   0 sub _split_array {
40 0         0 map {
41 0         0 [$self->split($_)];
42             } @_;
43             }
44              
45 0     0   0 sub _peel_deepest {
46 0 0       0 return () unless @_;
47 0 0       0 if (ref $_[0] eq 'ARRAY') {
48 0 0       0 if (ref $_[0]->[0] eq 'ARRAY') {
49 0         0 for my $aref (@_) {
50 0         0 @$aref = $self->_peel_deepest(@$aref);
51             }
52 0         0 return @_;
53             }
54 0         0 return map { $_->[0] } @_;
  0         0  
55             }
56 0         0 return @_;
57             }
58              
59             #===============================================================================
60             # these filters work on the leaves of nested arrays
61             #===============================================================================
62 0     0 1 0 sub Join { $self->_peel_deepest($self->_apply_deepest(join => @_)) }
  0         0  
63 1     1 1 3 sub Reverse { $self->_apply_deepest(reverse => @_) }
  1         6  
64 0     0 0 0 sub Split { $self->_apply_deepest(_split_array => @_) }
  0         0  
65 0     0 1 0 sub Sort { $self->_apply_deepest(sort => @_) }
  0         0  
66              
67              
68 1     1 1 2 sub append {
69 1         4 my $suffix = $self->current_arguments;
70 1         3 map { $_ . $suffix } @_;
  1         6  
71             }
72              
73 12     12 1 21 sub array {
74 12         113 return [@_];
75             }
76              
77 1     1 1 1 sub base64_decode {
78 1         3 $self->assert_scalar(@_);
79 1         891 require MIME::Base64;
80 1         1922 MIME::Base64::decode_base64(shift);
81             }
82              
83 1     1 1 2 sub base64_encode {
84 1         3 $self->assert_scalar(@_);
85 1         7 require MIME::Base64;
86 1         8 MIME::Base64::encode_base64(shift);
87             }
88              
89 61     61 1 109 sub chomp {
90 61         113 map { CORE::chomp; $_ } @_;
  87         173  
  87         389  
91             }
92              
93 4     4 1 8 sub chop {
94 4         8 map { CORE::chop; $_ } @_;
  8         14  
  8         30  
95             }
96              
97 2     2 1 5 sub dumper {
98 67     67   87888 no warnings 'once';
  67         156  
  67         29856  
99 2         23 require Data::Dumper;
100 2         5 local $Data::Dumper::Sortkeys = 1;
101 2         3 local $Data::Dumper::Indent = 1;
102 2         6 local $Data::Dumper::Terse = 1;
103 2         10 Data::Dumper::Dumper(@_);
104             }
105              
106 2     2 1 3 sub escape {
107 2         8 $self->assert_scalar(@_);
108 2         2 my $text = shift;
109 2         10 $text =~ s/(\\.)/eval "qq{$1}"/ge;
  4         211  
110 2         15 return $text;
111             }
112              
113 22     22 1 39 sub eval {
114 22         104 $self->assert_scalar(@_);
115 22         1479 my @return = CORE::eval(shift);
116 22 50       98 return $@ if $@;
117 22         105 return @return;
118             }
119              
120 2     2 1 4 sub eval_all {
121 2         6 $self->assert_scalar(@_);
122 2         3 my $out = '';
123 2         3 my $err = '';
124 2         7 Test::Base::tie_output(*STDOUT, $out);
125 2         7 Test::Base::tie_output(*STDERR, $err);
126 2         157 my $return = CORE::eval(shift);
127 67     67   567 no warnings;
  67         182  
  67         8684  
128 2         11 untie *STDOUT;
129 2         5 untie *STDERR;
130 2         20 return $return, $@, $out, $err;
131             }
132              
133 1     1 1 2 sub eval_stderr {
134 1         5 $self->assert_scalar(@_);
135 1         3 my $output = '';
136 1         6 Test::Base::tie_output(*STDERR, $output);
137 1         99 CORE::eval(shift);
138 67     67   372 no warnings;
  67         146  
  67         6957  
139 1         9 untie *STDERR;
140 1         14 return $output;
141             }
142              
143 1     1 1 2 sub eval_stdout {
144 1         4 $self->assert_scalar(@_);
145 1         2 my $output = '';
146 1         5 Test::Base::tie_output(*STDOUT, $output);
147 1         130 CORE::eval(shift);
148 67     67   400 no warnings;
  67         298  
  67         165931  
149 1         8 untie *STDOUT;
150 1         11 return $output;
151             }
152              
153 1     1 1 2 sub exec_perl_stdout {
154 1         6 my $tmpfile = "/tmp/test-blocks-$$";
155 1         5 $self->_write_to($tmpfile, @_);
156 1 50       2942 open my $execution, "$^X $tmpfile 2>&1 |"
157             or die "Couldn't open subprocess: $!\n";
158 1         39 local $/;
159 1         108333 my $output = <$execution>;
160 1         99 close $execution;
161 1 50       245 unlink($tmpfile)
162             or die "Couldn't unlink $tmpfile: $!\n";
163 1         99 return $output;
164             }
165              
166 4     4 1 6 sub flatten {
167 4         9 $self->assert_scalar(@_);
168 3         4 my $ref = shift;
169 3 100       10 if (ref($ref) eq 'HASH') {
170 3         17 return map {
171 1         5 ($_, $ref->{$_});
172             } sort keys %$ref;
173             }
174 2 100       6 if (ref($ref) eq 'ARRAY') {
175 1         6 return @$ref;
176             }
177 1         9 die "Can only flatten a hash or array ref";
178             }
179              
180 0     0 1 0 sub get_url {
181 0         0 $self->assert_scalar(@_);
182 0         0 my $url = shift;
183 0         0 CORE::chomp($url);
184 0         0 require LWP::Simple;
185 0         0 LWP::Simple::get($url);
186             }
187              
188 0     0 1 0 sub hash {
189 0         0 return +{ @_ };
190             }
191              
192 0     0 0 0 sub head {
193 0   0     0 my $size = $self->current_arguments || 1;
194 0         0 return splice(@_, 0, $size);
195             }
196              
197 8     8 1 14 sub join {
198 8         25 my $string = $self->current_arguments;
199 8 100       24 $string = '' unless defined $string;
200 8         49 CORE::join $string, @_;
201             }
202              
203 18     18 1 33 sub lines {
204 18         48 $self->assert_scalar(@_);
205 18         23 my $text = shift;
206 18 100       60 return () unless length $text;
207 17         125 my @lines = ($text =~ /^(.*\n?)/gm);
208 17         131 return @lines;
209             }
210              
211 230     230 1 383 sub norm {
212 230         649 $self->assert_scalar(@_);
213 230         371 my $text = shift;
214 230 50       614 $text = '' unless defined $text;
215 230         392 $text =~ s/\015\012/\n/g;
216 230         374 $text =~ s/\r/\n/g;
217 230         1621 return $text;
218             }
219              
220 0     0 0 0 sub prepend {
221 0         0 my $prefix = $self->current_arguments;
222 0         0 map { $prefix . $_ } @_;
  0         0  
223             }
224              
225 0     0 1 0 sub read_file {
226 0         0 $self->assert_scalar(@_);
227 0         0 my $file = shift;
228 0         0 CORE::chomp $file;
229 0 0       0 open my $fh, $file
230             or die "Can't open '$file' for input:\n$!";
231 0         0 CORE::join '', <$fh>;
232             }
233              
234 4     4 0 9 sub regexp {
235 4         13 $self->assert_scalar(@_);
236 4         6 my $text = shift;
237 4         12 my $flags = $self->current_arguments;
238 4 100       17 if ($text =~ /\n.*?\n/s) {
239 1 50       5 $flags = 'xism'
240             unless defined $flags;
241             }
242             else {
243 3         11 CORE::chomp($text);
244             }
245 4   100     26 $flags ||= '';
246 4         269 my $regexp = eval "qr{$text}$flags";
247 4 50       21 die $@ if $@;
248 4         16 return $regexp;
249             }
250              
251 1     1 1 2 sub reverse {
252 1         5 CORE::reverse(@_);
253             }
254              
255 0     0 0 0 sub slice {
256 0 0       0 die "Invalid args for slice"
257             unless $self->current_arguments =~ /^(\d+)(?:,(\d))?$/;
258 0         0 my ($x, $y) = ($1, $2);
259 0 0       0 $y = $x if not defined $y;
260 0 0       0 die "Invalid args for slice"
261             if $x > $y;
262 0         0 return splice(@_, $x, 1 + $y - $x);
263             }
264              
265 1     1 1 1 sub sort {
266 1         10 CORE::sort(@_);
267             }
268              
269 4     4 0 8 sub split {
270 4         13 $self->assert_scalar(@_);
271 4         14 my $separator = $self->current_arguments;
272 4 50 66     21 if (defined $separator and $separator =~ s{^/(.*)/$}{$1}) {
273 0         0 my $regexp = $1;
274 0         0 $separator = qr{$regexp};
275             }
276 4 100       21 $separator = qr/\s+/ unless $separator;
277 4         45 CORE::split $separator, shift;
278             }
279              
280 0     0 1 0 sub strict {
281 0         0 $self->assert_scalar(@_);
282 0         0 <<'...' . shift;
283             use strict;
284             use warnings;
285             ...
286             }
287              
288 0     0 0 0 sub tail {
289 0   0     0 my $size = $self->current_arguments || 1;
290 0         0 return splice(@_, @_ - $size, $size);
291             }
292              
293 229     229 1 360 sub trim {
294 229         775 map {
295 229         457 s/\A([ \t]*\n)+//;
296 229         1621 s/(?<=\n)\s*\z//g;
297 229         1244 $_;
298             } @_;
299             }
300              
301 1     1 1 2 sub unchomp {
302 1         3 map { $_ . "\n" } @_;
  3         10  
303             }
304              
305 1     1 0 2 sub write_file {
306 1 50       4 my $file = $self->current_arguments
307             or die "No file specified for write_file filter";
308 1 50       6 if ($file =~ /(.*)[\\\/]/) {
309 1         3 my $dir = $1;
310 1 50       23 if (not -e $dir) {
311 1         7 require File::Path;
312 1 50       351 File::Path::mkpath($dir)
313             or die "Can't create $dir";
314             }
315             }
316 1 50       100 open my $fh, ">$file"
317             or die "Can't open '$file' for output\n:$!";
318 1         8 print $fh @_;
319 1         61 close $fh;
320 1         14 return $file;
321             }
322              
323 0     0 1 0 sub yaml {
324 0         0 $self->assert_scalar(@_);
325 0         0 require YAML;
326 0         0 return YAML::Load(shift);
327             }
328              
329 1     1   2 sub _write_to {
330 1         2 my $filename = shift;
331 1 50       230 open my $script, ">$filename"
332             or die "Couldn't open $filename: $!\n";
333 1         18 print $script @_;
334 1 50       80 close $script
335             or die "Couldn't close $filename: $!\n";
336             }
337              
338             1;