3 # Tests for the source filters in coderef-in-@INC
9 skip_all_if_miniperl('no dynamic loading on miniperl, no Filter::Util::Call');
10 skip_all_without_perlio();
14 use Filter::Util::Call;
19 no warnings 'uninitialized';
20 ref $_[1] eq 'ARRAY' ? @{$_[1]} : $_[1];
25 open $fh, "<", \'pass("Can return file handles from \@INC");';
28 my @origlines = ("# This is a blank line\n",
29 "pass('Can return generators from \@INC');\n",
30 "pass('Which return multiple lines');\n",
33 my @lines = @origlines;
36 # Return of 0 marks EOF
37 return defined $_ ? 1 : 0;
40 do \&generator or die;
43 # Check that the array dereferencing works ready for the more complex tests:
44 do [\&generator] or die;
46 sub generator_with_state {
48 is (ref $param, 'ARRAY', "Got our parameter");
50 return defined $_ ? 1 : 0;
53 do [\&generator_with_state,
54 ["pass('Can return generators which take state');\n",
55 "pass('And return multiple lines');\n",
59 open $fh, "<", \'fail("File handles and filters work from \@INC");';
61 do [$fh, sub {s/fail/pass/; return;}] or die;
63 open $fh, "<", \'fail("File handles and filters with state work from \@INC");';
65 do [$fh, sub {s/$_[1]/pass/; return;}, 'fail'] or die;
67 print "# 2 tests with pipes from subprocesses.\n";
69 my ($echo_command, $pass_arg, $fail_arg);
72 $echo_command = 'write sys$output';
77 if ($^O =~ /android/) {
78 $echo_command = q{sh -c 'echo $@' -- };
81 $echo_command = 'echo';
87 open $fh, "$echo_command $pass_arg|" or die $!;
91 open $fh, "$echo_command $fail_arg|" or die $!;
93 do [$fh, sub {s/$_[1]/pass/; return;}, 'fail'] or die;
97 my $status = filter_read();
98 tr/A-Za-z/N-ZA-Mn-za-m/;
103 open $fh, "<", \<<'EOC';
104 BEGIN {rot13_filter};
105 cnff("This will rot13'ed prepend");
110 open $fh, "<", \<<'EOC';
111 ORTVA {ebg13_svygre};
112 pass("This will rot13'ed twice");
115 do [$fh, sub {tr/A-Za-z/N-ZA-Mn-za-m/; return;}] or die;
118 sub prepend_rot13_filter {
121 # Filters should append to any existing data in $_
122 # But (logically) shouldn't filter it twice.
125 my $status = filter_read();
126 my $got = substr $_, 0, length $test, '';
127 is $got, $test, "Upstream didn't alter existing data";
128 tr/A-Za-z/N-ZA-Mn-za-m/;
130 die "Looping infinitely" unless $count--;
135 open $fh, "<", \<<'EOC';
136 ORTVA {cercraq_ebg13_svygre};
137 pass("This will rot13'ed twice");
140 do [$fh, sub {tr/A-Za-z/N-ZA-Mn-za-m/; return;}] or die;
142 # This generates a heck of a lot of oks, but I think it's necessary.
144 sub prepend_block_counting_filter {
150 my $status = filter_read($amount);
151 cmp_ok (length $_, '<=', $amount, "block mode works?");
153 if ($status <= 0 or /\n/s) {
158 die "Looping infinitely";
163 open $fh, "<", \<<'EOC';
164 BEGIN {prepend_block_counting_filter};
169 do [$fh, sub {return;}] or die;
171 open $fh, "<", \<<'EOC';
172 BEGIN {prepend_block_counting_filter};
173 pas("SSS make s fast SSS");
177 todo_skip "disabled under -Dmad", 50 if $Config{mad};
178 do [$fh, sub {s/s/ss/gs; s/([\nS])/$1$1$1/gs; return;}] or die;
181 sub prepend_line_counting_filter {
185 my $status = filter_read();
186 my $newlines = tr/\n//;
187 cmp_ok ($newlines, '<=', 1, "1 line at most?");
188 $_ = $output . $_ if defined $output;
193 open $fh, "<", \<<'EOC';
194 BEGIN {prepend_line_counting_filter};
195 pass("You should see this line thrice");
198 do [$fh, sub {$_ .= $_ . $_; return;}] or die;
200 do \"pass\n(\n'Scalar references are treated as initial file contents'\n)\n"
203 use constant scalarreffee =>
204 "pass\n(\n'Scalar references are treated as initial file contents'\n)\n";
205 do \scalarreffee or die;
207 "pass\n(\n'Scalar references are treated as initial file contents'\n)\n",
208 'and are not gobbled up when read-only';
211 local $SIG{__WARN__} = sub {}; # ignore deprecation warning from ?...?
213 pass "No crash (perhaps) when regexp ref is returned from inc filter";
214 # Even if that outputs "ok", it may not have passed, as the crash
215 # occurs during globular destruction. But the crash will result in
216 # this script failing.
219 open $fh, "<", \"ss('The file is concatenated');";
221 do [\'pa', $fh] or die;
223 open $fh, "<", \"ff('Gur svygre vf bayl eha ba gur svyr');";
225 do [\'pa', $fh, sub {tr/A-Za-z/N-ZA-Mn-za-m/; return;}] or die;
227 open $fh, "<", \"SS('State also works');";
229 do [\'pa', $fh, sub {s/($_[1])/lc $1/ge; return;}, "S"] or die;
231 @lines = ('ss', '(', "'you can use a generator'", ')');
233 do [\'pa', \&generator] or die;
235 do [\'pa', \&generator_with_state,
236 ["ss('And generators which take state');\n",
237 "pass('And return multiple lines');\n",
240 @origlines = keys %{{ "1\n+\n2\n" => 1 }};
242 do \&generator or die;
243 is $origlines[0], "1\n+\n2\n", 'ink filters do not mangle cow buffers';
245 @lines = ('$::the_array = "', [], '"');
246 do \&generator or die;
247 like ${$::{the_array}}, qr/^ARRAY\(0x.*\)\z/,
248 'setting $_ to ref in inc filter';
249 @lines = ('$::the_array = "', do { no warnings 'once'; *foo}, '"');
250 do \&generator or die;
251 is ${$::{the_array}}, "*main::foo", 'setting $_ to glob in inc filter';
254 do { no strict; no warnings; *{"foo\nbar"}},
256 do \&generator or die;
257 is ${$::{the_array}}, "*main::foo\nbar",
258 'setting $_ to multiline glob in inc filter';
260 sub TIESCALAR { bless \(my $thing = pop), shift }
265 tie $_, "main", '$::the_scalar = 98732';
268 is ${$::{the_scalar}}, 98732, 'tying $_ in inc filter';
269 @lines = ('$::the_scalar', '= "12345"');
270 tie my $ret, "main", 1;
272 return 0 unless @lines;
276 is ${$::{the_scalar}}, 12345, 'returning tied val from inc filter';
279 # d8723a6a74b2c12e wasn't perfect, as the char * returned by SvPV*() can be
280 # a temporary, freed at the next FREETMPS. And there is a FREETMPS in
284 # Need both alternatives on the regexp, because currently the logic in
285 # pp_require for what is written to %INC is somewhat confused
287 \'like(__FILE__, qr/(?:GLOB|CODE)\(0x[0-9a-f]+\)/, "__FILE__ is valid");';
291 # [perl #91880] $_ having the wrong refcount inside a
293 local @INC; local $|;
294 unshift @INC, sub { sub { undef *_; --$| }};
296 pass '$_ has the right refcount inside a filter sub';