6 set_up_inc( qw(../lib) );
15 # Dedupe @INC. In a future patch we /may/ refuse to process items
16 # more than once and deduping here will prevent the tests from failing
17 # should we make that change.
18 my %seen; @INC = grep {!$seen{$_}++} @INC;
20 my $nonfile = tempfile();
22 # The tests for ' ' and '.h' never did fail, but previously the error reporting
23 # code would read memory before the start of the SV's buffer
25 for my $file ($nonfile, ' ') {
30 like $@, qr/^Can't locate $file in \@INC \(\@INC[\w ]+: \Q@INC\E\) at/,
31 "correct error message for require '$file'";
34 # Check that the "(you may need to install..) hint is included in the
35 # error message where (and only where) appropriate.
37 # Basically the hint should be issued for any filename where converting
38 # back from Foo/Bar.pm to Foo::Bar gives you a legal bare word which could
39 # follow "require" in source code.
43 # may be any letter of an identifier
44 my $I = "\x{393}"; # "\N{GREEK CAPITAL LETTER GAMMA}"
45 # Continuation char: may only be 2nd+ letter of an identifier
46 my $C = "\x{387}"; # "\N{GREEK ANO TELEIA}"
49 # thing to require pathname in err mesg err includes hint?
50 [ "No::Such::Module1", "No/Such/Module1.pm", 1 ],
51 [ "'No/Such/Module1.pm'", "No/Such/Module1.pm", 1 ],
52 [ "_No::Such::Module1", "_No/Such/Module1.pm", 1 ],
53 [ "'_No/Such/Module1.pm'", "_No/Such/Module1.pm", 1 ],
54 [ "'No/Such./Module.pm'", "No/Such./Module.pm", 0 ],
55 [ "No::1Such::Module", "No/1Such/Module.pm", 1 ],
56 [ "'No/1Such/Module.pm'", "No/1Such/Module.pm", 1 ],
57 [ "1No::Such::Module", undef, 0 ],
58 [ "'1No/Such/Module.pm'", "1No/Such/Module.pm", 0 ],
61 [ "No::Such${I}::Module1", "No/Such${I}/Module1.pm", 1 ],
62 [ "'No/Such${I}/Module1.pm'", "No/Such${I}/Module1.pm", 1 ],
63 [ "_No::Such${I}::Module1", "_No/Such${I}/Module1.pm", 1 ],
64 [ "'_No/Such${I}/Module1.pm'", "_No/Such${I}/Module1.pm", 1 ],
65 [ "'No/Such${I}./Module.pm'", "No/Such${I}./Module.pm", 0 ],
66 [ "No::1Such${I}::Module", "No/1Such${I}/Module.pm", 1 ],
67 [ "'No/1Such${I}/Module.pm'", "No/1Such${I}/Module.pm", 1 ],
68 [ "1No::Such${I}::Module", undef, 0 ],
69 [ "'1No/Such${I}/Module.pm'", "1No/Such${I}/Module.pm", 0 ],
71 # utf8 with continuation char in 1st position
72 [ "No::${C}Such::Module1", undef, 0 ],
73 [ "'No/${C}Such/Module1.pm'", "No/${C}Such/Module1.pm", 0 ],
74 [ "_No::${C}Such::Module1", undef, 0 ],
75 [ "'_No/${C}Such/Module1.pm'", "_No/${C}Such/Module1.pm", 0 ],
76 [ "'No/${C}Such./Module.pm'", "No/${C}Such./Module.pm", 0 ],
77 [ "No::${C}1Such::Module", undef, 0 ],
78 [ "'No/${C}1Such/Module.pm'", "No/${C}1Such/Module.pm", 0 ],
79 [ "1No::${C}Such::Module", undef, 0 ],
80 [ "'1No/${C}Such/Module.pm'", "1No/${C}Such/Module.pm", 0 ],
83 my ($require_arg, $err_path, $has_hint) = @$test_data;
86 if (defined $err_path) {
87 $exp = "Can't locate $err_path in \@INC";
92 $exp .= " (you may need to install the $hint module)";
94 $exp .= " (\@INC entries checked: @INC) at";
97 # undef implies a require which doesn't compile,
98 # rather than one which triggers a run-time error.
99 # We'll set exp to a suitable value later;
105 no warnings qw(syntax utf8);
106 if ($require_arg =~ /[^\x00-\xff]/) {
107 eval "require $require_arg";
112 eval "require $require_arg";
117 for ($err, $exp, $require_arg) {
118 s/([^\x00-\xff])/sprintf"\\x{%x}",ord($1)/ge;
121 $exp = qr/^\Q$exp\E/;
124 $exp = qr/syntax error at|Unrecognized character/;
127 "err for require $require_arg";
133 eval "require ::$nonfile";
135 like $@, qr/^Bareword in require must not start with a double-colon:/,
136 "correct error message for require ::$nonfile";
139 require "$nonfile.ph";
142 like $@, qr/^Can't locate $nonfile\.ph in \@INC \(did you run h2ph\?\) \(\@INC[\w ]+: @INC\) at/;
144 for my $file ("$nonfile.h", ".h") {
149 like $@, qr/^Can't locate \Q$file\E in \@INC \(change \.h to \.ph maybe\?\) \(did you run h2ph\?\) \(\@INC[\w ]+: @INC\) at/,
150 "correct error message for require '$file'";
153 for my $file ("$nonfile.ph", ".ph") {
158 like $@, qr/^Can't locate \Q$file\E in \@INC \(did you run h2ph\?\) \(\@INC[\w ]+: @INC\) at/,
159 "correct error message for require '$file'";
162 eval 'require <foom>';
163 like $@, qr/^<> at require-statement should be quotes at /, 'require <> error';
165 my $module = tempfile();
166 my $mod_file = "$module.pm";
168 open my $module_fh, ">", $mod_file or die $!;
169 print { $module_fh } "print 1; 1;\n";
172 chmod 0333, $mod_file;
175 skip_if_miniperl("these modules may not be available to miniperl", 2);
179 require File::Spec::Functions;
180 if ($^O eq 'cygwin') {
184 # Going to try to switch away from root. Might not work.
185 # (stolen from t/op/stat.t)
188 skip "Can't test permissions meaningfully if you're superuser", 2
189 if ($^O eq 'cygwin' ? Win32::IsAdminUser() : $> == 0);
194 qr<^\QCan't locate $mod_file:>,
195 "special error message if the file exists but can't be opened";
198 skip "Can't make the path absolute", 1
199 if !defined(Cwd::getcwd());
201 my $file = File::Spec::Functions::catfile(Cwd::getcwd(), $mod_file);
206 qr<^\QCan't locate $file:>,
207 "...even if we use a full path";
210 # switch uid back (may not be implemented)
211 eval { $> = $olduid; };
214 1 while unlink $mod_file;
216 # I can't see how to test the EMFILE case
217 # I can't see how to test the case of not displaying @INC in the message.
218 # (and does that only happen on VMS?)
220 # fail and print the full filename
221 eval { no warnings 'syscalls'; require "strict.pm\0invalid"; };
222 like $@, qr/^Can't locate strict\.pm\\0invalid: /, 'require nul check [perl #117265]';
225 local $SIG{__WARN__} = sub { $WARN = shift };
227 my $ret = do "strict.pm\0invalid";
230 is $ret, undef, 'do nulstring returns undef';
231 is $exc, '', 'do nulstring clears $@';
233 ok $!{ENOENT}, 'do nulstring fails with ENOENT';
234 like $WARN, qr{^Invalid \\0 character in pathname for do: strict\.pm\\0invalid at }, 'do nulstring warning';
238 eval { require "strict.pm\0invalid"; };
239 like $WARN, qr{^Invalid \\0 character in pathname for require: strict\.pm\\0invalid at }, 'nul warning';
240 like $@, qr{^Can't locate strict\.pm\\0invalid: }, 'nul error';
244 set_up_inc( "lib\0invalid" );
245 eval { require "unknown.pm" };
246 like $WARN, qr{^Invalid \\0 character in \@INC entry for require: lib\\0invalid at }, 'nul warning';
248 eval "require strict\0::invalid;";
249 like $@, qr/^syntax error at \(eval \d+\) line 1/, 'parse error with \0 in barewords module names';
251 # Refs and globs that stringify with embedded nulls
252 # These crashed from 5.20 to 5.24 [perl #128182].
253 eval { no warnings 'syscalls'; require eval "qr/\0/" };
254 like $@, qr/^Can't locate \(\?\^:\\0\):/,
255 'require ref that stringifies with embedded null';
256 eval { no strict; no warnings 'syscalls'; require *{"\0a"} };
257 like $@, qr/^Can't locate \*main::\\0a:/,
258 'require ref that stringifies with embedded null';
260 eval { require undef };
261 like $@, qr/^Missing or undefined argument to require /;
264 like $@, qr/^Missing or undefined argument to do /;
267 like $@, qr/^Missing or undefined argument to require /;
270 like $@, qr/^Missing or undefined argument to do /;
272 # non-searchable pathnames shouldn't mention @INC in the error
274 my $nonsearch = "./no_such_file.pm";
276 eval "require \"$nonsearch\"";
278 like $@, qr/^Can't locate \Q$nonsearch\E at/,
279 "correct error message for require $nonsearch";
282 # make sure require doesn't treat a non-PL_sv_undef undef as
286 ok(!eval { require CannotParse; }, "should fail to load");
287 local %INC = %INC; # copies \&PL_sv_undef into a new undef
288 ok(!eval { require CannotParse; },
289 "check the second attempt also fails");
290 like $@, qr/Attempt to reload/, "check we failed for the right reason";
295 'unshift @INC, sub { sub { 0 } }; require "asdasd";',
296 qr/asdasd did not return a true value/,
297 { }, '@INC hook blocks do not cause segfault');
301 # make sure that modifications to %INC during an INC hooks lifetime
302 # don't result in us having an empty string for the cop_file.
303 # Older perls will output "error at line 1".
306 'use lib qq(./lib); BEGIN{ unshift @INC, '
307 .'sub { if ($_[1] eq "CannotParse.pm" and !$seen++) { '
308 .'eval q(require $_[1]); warn $@; my $code= qq[die qq(error)];'
309 .'open my $fh,"<", q(lib/Dies.pm); return $fh } } } require CannotParse;',
310 qr!\Asyntax error.*?^error at /loader/0x[A-Fa-f0-9]+/CannotParse\.pm line 1\.!ms,
311 { }, 'Inc hooks have the correct cop_file');
314 # this can segfault or assert prior to @INC hardening.
316 'unshift @INC, sub { *INC=["a","b"] }; '
317 .'eval "require Frobnitz" or print $@',
318 qr!\(\@INC[\w ]+: CODE\(0x[A-Fa-f0-9]+\) b\)!,
319 { }, 'INC hooks do not segfault when overwritten');
322 # this is the defined behavior, but in older perls the error message
323 # would lie and say "contains: a b", which is true in the sense that
324 # it is the value of @INC after the require, but not the directory
325 # list that was looked at.
327 '@INC = (sub { @INC=("a","b"); () }, "z"); '
328 .'eval "require Frobnitz" or print $@',
329 qr!\(\@INC[\w ]+: CODE\(0x[A-Fa-f0-9]+\) b\)!,
330 { }, 'INC hooks that overwrite @INC continue as expected (skips a and z)');
335 '@INC = (sub { @INC=qw(a b); undef $INC }, "z"); '
336 .'eval "require Frobnitz" or print $@',
337 qr!\(\@INC[\w ]+: CODE\(0x[A-Fa-f0-9]+\) a b\)!,
338 { }, 'INC hooks that overwrite @INC and undef $INC continue at start');
343 'sub CB::INCDIR { return "b", "c","d" }; '
344 .'@INC = ("a",bless({},"CB"),"e");'
345 .'eval "require Frobnitz" or print $@',
346 qr!\(\@INC[\w ]+: a CB=HASH\(0x[A-Fa-f0-9]+\) b c d e\)!,
347 { }, 'INCDIR works as expected');
352 '@INC = ("a",bless({},"CB"),"e");'
353 .'eval "require Frobnitz" or print $@',
354 qr!Can't locate object method "INC", nor "INCDIR" nor string overload via package "CB" in object hook in \@INC!,
355 { }, 'Objects with no INC or INCDIR method and no overload throw an error');
360 'package CB { use overload q("") => sub { "Fnorble" };} @INC = ("a",bless({},"CB"),"e");'
361 .'eval "require Frobnitz" or print $@',
362 qr!\(\@INC[\w ]+: a Fnorble e\)!,
363 { }, 'Objects with no INC or INCDIR method but with an overload are stringified');
368 'package CB { use overload q(0+) => sub { 12345 }, fallback=>1;} @INC = ("a",bless({},"CB"),"e");'
369 .'eval "require Frobnitz" or print $@',
370 qr!\(\@INC[\w ]+: a 12345 e\)!,
371 { }, 'Objects with no INC or INCDIR method but with an overload with fallback are stringified');
376 '{package CB; use overload qw("")=>sub { "blorg"};} '
377 .'@INC = ("a",bless({},"CB"),"e");'
378 .'eval "require Frobnitz" or print $@',
379 qr!\(\@INC[\w ]+: a blorg e\)!,
380 { }, 'Objects with overload and no INC or INCDIR method are stringified');
385 '@INC = ("a",bless(sub { warn "blessed sub called" },"CB"),"e");'
386 .'eval "require Frobnitz" or print $@',
387 qr!blessed sub called.*\(\@INC[\w ]+: a CB=CODE\(0x[a-fA-F0-9]+\) e\)!s,
388 { }, 'Blessed subs with no hook methods are executed');
393 '@INC = ("a",bless(sub { die "blessed sub called" },"CB"),"e");'
394 .'eval "require Frobnitz" or print $@',
395 qr!INC sub hook died--halting \@INC search!s,
396 { }, 'Blessed subs that die produce expected extra message');
401 'sub CB::INC { die "bad mojo" } '
402 .'@INC = ("a",bless(sub { die "blessed sub called" },"CB"),"e");'
403 .'eval "require Frobnitz" or print $@',
404 qr!bad mojo.*INC method hook died--halting \@INC search!s,
405 { }, 'Blessed subs with methods call method and produce expected message');
410 '@INC = ("a",[bless([],"CB"),1],"e");'
411 .'eval "require Frobnitz" or print $@',
412 qr!Can't locate object method "INC", nor "INCDIR" nor string overload via package "CB" in object in ARRAY hook in \@INC!s,
413 { }, 'Blessed objects with no hook methods in array form produce expected exception');
418 'sub CB::INCDIR { "i" } sub CB2::INCDIR { }'
419 .'@INC = ("a",bless(sub{"b"},"CB"),bless(sub{"c"},"CB2"),"e");'
420 .'eval "require Frobnitz" or print $@',
421 qr!\(\@INC[\w ]+: a CB=CODE\(0x[a-fA-F0-9]+\) i CB2=CODE\(0x[a-fA-F0-9]+\) e\)!s,
422 { }, 'Blessed subs with INCDIR methods call INCDIR');
427 'sub CB::INCDIR { return @{$_[2]} }'
428 .'@INC = ("a",[bless([],"CB"),"b"],"c");'
429 .'eval "require Frobnitz" or print $@',
430 qr!\(\@INC[\w ]+: a ARRAY\(0x[a-fA-F0-9]+\) CB=ARRAY\(0x[a-fA-F0-9]+\) b c\)!s,
431 { }, 'INCDIR ref returns are stringified');