use lib ; use Test; use Test::Helpers; plan 51; # https://github.com/Raku/old-issue-tracker/issues/5707 throws-like '1++', X::Multi::NoMatch, message => /'but require mutable arguments'/, 'point out matching `is rw` candidates when passing non-rw'; subtest 'curly quotes are not called smart quotes' => { my @quotes = 「‘」, 「‚」, 「’」, 「“」, 「„」, 「”」; plan +@quotes; for @quotes -> $q { throws-like $q, Exception, :message{ not .contains('smart') and .contains('curly') }, "$q (U+$q.ord.base(16)) quote is called curly, not smart"; } } # https://github.com/Raku/old-issue-tracker/issues/6052 throws-like 'sub infix:<$>() return Nil {}', X::AdHoc, :message{ .contains("'returns'") }, 'typing "return" instead of "returns" gives a fixing hint'; # https://github.com/Raku/old-issue-tracker/issues/6014 throws-like 「'4x'.Rat.nude」, X::Str::Numeric, :message{ not .contains("Metamodel.nqp") }, '.Rat.nude on non-numeric string does not reference guts in error'; # https://github.com/Raku/old-issue-tracker/issues/5982 throws-like 「…」, X::StubCode, :message{ not .contains('CORE.setting') }, 'stub code does not reference guts when executed'; # https://github.com/Raku/old-issue-tracker/issues/4477 subtest 'chr with large codepoints throws useful error' => { my @tests = 'chr 2⁶³-1', '(2⁶³-1).chr', 'chr 2⁶³', '2⁶³.chr', 'chr 2¹⁰⁰', '(2¹⁰⁰).chr'; plan +@tests; for @tests { throws-like $^code, Exception, :message{ .contains('Codepoint') && .contains('out of bounds') && .contains('chr') }, "$code.raku()"; } } # https://colabti.org/irclogger/irclogger_log/perl6?date=2017-03-14#l1018 throws-like 「m: my @a = for 1..3 <-> { $_ }」, Exception, :message(/«'do for'»/), '<-> does not prevent an error suggesting to use `do for`'; # https://colabti.org/irclogger/irclogger_log/perl6-dev?date=2017-04-14#l101 # https://github.com/Raku/old-issue-tracker/issues/2262 { my $param = '$bar'; throws-like { EVAL q[ sub foo(\qq{$param}? is rw) {} ] }, Exception, message => "Cannot use 'is rw' on optional parameter '$param'.", 'making an "is rw" parameter optional dies with adequate error message and mentions the parameter name'; throws-like { EVAL q[ sub foo(\qq{$param} is rw = 42) {} ] }, Exception, message => "Cannot use 'is rw' on optional parameter '$param'.", 'making an "is rw" parameter optional dies with adequate error message and mentions the parameter name'; } # https://github.com/Raku/old-issue-tracker/issues/2808 { is-run 「multi MAIN(q|foo bar|) {}」, :err(qq|Usage:\n -e '...' 'foo bar'\n|), :exitcode(*), 'a space in a literal param to a MAIN() multi makes the suggestion quoted'; if $*DISTRO.is-win { # https://github.com/Raku/old-issue-tracker/issues/6591 skip "Test routine quoting doesn't work right on Windows" } else { is-run 「multi MAIN(q|foo"bar|) {}」, :err(qq|Usage:\n -e '...' 'foo"bar'\n|), :exitcode(*), 'a double qoute in a literal param to a MAIN() multi makes the suggestion quoted'; } is-run 「multi MAIN(q|foo'bar|) {}」, :err(qq|Usage:\n -e '...' 'foo'"'"'bar'\n|), :exitcode(*), 'a single qoute in a literal param to a MAIN() multi makes the suggestion quoted'; } # https://github.com/Raku/old-issue-tracker/issues/3152 { throws-like { EVAL q|role R { method a {...}; method b { say "b" }; method c {...} }; class C is R {}| }, Exception, message => all(/<<'C'>>/, /<<'R'>>/, /<<'a,' \s* 'c'>>/, /<<'does'>>/), 'The message when trying to pun a role with required methods should have the names of the child, parent, required methods, and suggest "does"'; } # https://github.com/Raku/old-issue-tracker/issues/4569 # adapted from S06-signature/types.t { throws-like { sub f(Mu:D $a) {}; f(Int) }, Exception, message => all(/Parameter/, /\W '$a'>>/, /<<'f'>>/, /<>/, /<>/, /<<'Mu'>>/, /<<'Int'>>/, /\W '.new'>>/), 'types and names shown in the exception message are correct'; throws-like { sub f(Mu:U $a) {}; f(123) }, Exception, message => all(/'Parameter'/, /\W '$a'>>/, /<<'f'>>/, /<>/, /<>/, /<<'Mu'>>/, /<<'Int'>>/, /<<'multi'>>/), 'types shown in the exception message are correct'; } # adapted from S32-exceptions/misc.t for -> $meth { throws-like 'X::NYI.' ~ $meth, Exception, message => all(/'Invocant'/, /<<$meth>>/, /<<'must be an object instance'>>/, /<<'not a type object'>>/, /<<'Exception'>>/, /<<'X::NYI'>>/, /\W '.new'>>/), } # https://github.com/Raku/old-issue-tracker/issues/2712 { throws-like q|3 ==> &sin ==> &say|, Exception, message => /<<'sin()'\W/, 'sinking to a code object in a feed suggests calling the routine'; } # https://github.com/Raku/old-issue-tracker/issues/3428 { throws-like { my class RT122232::B {}; RT122232.new }, Exception, message => /'cannot create' .+ «RT122232»/, 'trying to instantiate a non-class gives the name in the error'; throws-like { my subset RT122232 of Int where * > 42; RT122232.new }, Exception, message => /'cannot create' .+ «RT122232»/, 'trying to instantiate a non-class gives the name in the error'; } subtest 'non-ASCII digits > 7 in leading-zero-octal warning' => { plan 2; todo "dies at compile time with: '୯' is not a valid number", 2 if $*VM.name eq 'jvm'; with run $*EXECUTABLE, '-e', 'say 0୯', :err, :out { is .out.slurp(:close), "9\n", 'STDOUT is right'; like .err.slurp(:close), /'୯ is not a valid octal number'/, 'STDERR mentions the end-result is not valid octal'; } } # https://github.com/Raku/old-issue-tracker/issues/3572 { throws-like { sub foo([$head, $tail]) {}; foo([3, 4], [3]) }, Exception, message => all(/<<'Too many'>>/, /<<'expected 1'>>/, /<<'got 2'>>/), 'wrong arity in a signature has correct values in error message'; throws-like { sub foo([$head, $tail], [$foo]) {}; foo([3, 4]) }, Exception, message => all(/<<'Too few'>>/, /<<'expected 2'>>/, /<<'got 1'>>/), 'wrong arity in a signature has correct values in error message'; throws-like { sub foo([$head]) {}; foo([3, 4]) }, Exception, message => all(/<<'Too many'>>/, /<<'expected 1'>>/, /<<'got 2'>>/, /<<'sub-signature'>>/), 'wrong arity in a sub-signature has correct values in error message'; throws-like { sub foo(@bar ($head, $tail)) {}; foo([3]) }, Exception, message => all(/<<'Too few'>>/, /<<'expected 2'>>/, /<<'got 1'>>/, /<<'sub-signature'>>/, /<<'parameter @bar'>>/), 'wrong arity in a sub-signature with a named parameter has correct values in error message'; } # https://github.com/Raku/old-issue-tracker/issues/6275 { throws-like { sub foo([$head, $tail]) {}; foo([3, 4], [3]) }, Exception, message => /<<'foo'>>/, 'wrong arity in a signature mentions the name of the sub'; throws-like { class A { sub foo([$head, $tail]) {} }; A.foo([3, 4], [3]) }, Exception, message => /<<'foo'>>/, 'wrong arity in a signature mentions the name of the method'; } { # https://colabti.org/irclogger/irclogger_log/perl6-dev?date=2017-05-31#l169 todo "X::Method::NotFound doesn't offer suggestions here", 2 if $*VM.name eq 'jvm'; throws-like '42.length ', Exception, '.length on non-List Cool', :message{ .contains: .all & none }; throws-like '[].length ', Exception, '.length on List', :message{ .contains: 'elems' & none }; throws-like 'bag(1).length ', Exception, '.length on non-Cool', :message{ .contains: .all & none 'graphs' }; throws-like 'length 42 ', Exception, '&length', :message{ .contains: .all & none 'graphs' }; } # https://github.com/Raku/old-issue-tracker/issues/6206 throws-like { class { proto method x(|) {*} }.new.x }, X::Multi::NoMatch, :message{ .contains: 'only the proto' & none 'none of these signatures' }, 'error points out only only proto is defined'; # https://github.com/Raku/old-issue-tracker/issues/6271 throws-like { Blob.split }, X::Multi::NoMatch, :message{ .contains: 'only the proto' & none 'none of these signatures' }, 'error points out only only proto is defined (Blob.split)'; # https://github.com/Raku/old-issue-tracker/issues/6271 throws-like { Blob.splice }, X::Multi::NoMatch, :message{ .contains: 'only the proto' & none 'none of these signatures' }, 'error points out only only proto is defined (Blob.splice)'; # https://github.com/Raku/old-issue-tracker/issues/5093 # https://github.com/Raku/old-issue-tracker/issues/3569 { todo "X::Method::NotFound doesn't offer suggestions here", 1 if $*VM.name eq 'jvm'; throws-like q| class RT123078_1 { method foo { self.bar }; method !bar { }; method baz { } }; RT123078_1.new.foo |, X::Method::NotFound, message => all(/<<"No such method 'bar'" \W/, /<<'RT123078_1'>>/, /\W '!bar'>>/, /<<'baz'>>/), 'a private method of the same name as the public missing method is suggested'; throws-like q| class RT123078_2 { method foo { self!bar }; method bar { }; method baz { } } |, X::Method::NotFound, message => all(/<<"No such private method '!bar'" \W/, /<<'RT123078_2'>>/, /<<'bar'>>/, /<<'baz'>>/), 'a public method of the same name as the missing private method is suggested'; todo "X::Method::NotFound doesn't offer suggestions here", 3 if $*VM.name eq 'jvm'; throws-like q| class RT123078_3 { method !bar { }; method baz { } }; RT123078_3.new.bar |, X::Method::NotFound, message => all(/<<"No such method 'bar'" \W/, /<<'RT123078_3'>>/, /\s+ Did \s+ you \s+ mean/), suggestions => , 'a private method of the same name as the public missing method is not suggested for out-of-class call'; throws-like q| .uniq |, X::Method::NotFound, message => all(/<<"No such method 'uniq'" \W/, /<<'unique'>>/), 'potentially common misspelling gives the right suggestion'; throws-like q| ‘foo’.starts-wizh(‘f’) |, X::Method::NotFound, message => all(/<<"No such method 'starts-wizh'" \W/, /<<'starts-with'>>/), 'longer method names are suggested also'; } # https://github.com/rakudo/rakudo/issues/1758 { throws-like q| class GH1758_1 { submethod x { }; }; class B is GH1758_1 {}; B.new._ |, X::Method::NotFound, :message{ !.contains: "Did you mean 'x'" }, 'Ancestor submethods should not be typo-suggested'; todo "X::Method::NotFound doesn't offer suggestions here", 1 if $*VM.name eq 'jvm'; throws-like q| class GH1758_2 { submethod x { };}; GH1758_2.new._ |, X::Method::NotFound, message => /"Did you mean 'x'"/, 'Submethods at the same inheritance level should be typo-suggested'; } subtest '`IO::Socket::INET.new: :listen` fails with useful error' => { plan 3; my $res = IO::Socket::INET.new: :listen; isa-ok $res, Failure, 'got a Failure'; ok $res.handled.not, 'Failure is unhandled'; $res.so; like $res.exception.message, /'Invalid port'/, 'error mentions port'; } throws-like 「use v5」, X::Language::Unsupported, '`use v5` in code does not try to load non-existent modules'; # https://github.com/Raku/old-issue-tracker/issues/5074 is-run 'Duration.new: Inf; Duration.new: "meow"', :out{not .contains: '$!tai'}, :err{not .contains: '$!tai'}, :exitcode(*), 'Duration.new with bad args does not reference guts'; # https://github.com/Raku/old-issue-tracker/issues/4488 is-run 「my Str where 'foo' $test」, :exitcode(*), :err{.contains: 「forget a variable」 and not .contains: 「Did you mean 'Str'」}, 'sane error when missing variables with my and where'; # https://github.com/Raku/old-issue-tracker/issues/6604 throws-like 「Blob[num32].new: 2e0」, Exception, :message{ .contains: 「Can only parameterize」 & 「num32」 and not .contains: 「got null」 }, 'sane NYI error for num32 Blob'; # https://github.com/Raku/old-issue-tracker/issues/2151 throws-like 「callframe.callframe(1).my.raku」, X::NYI, 'callframe.my throws sane NYI error message'; subtest '.new on native types works (deprecated; will die)' => { my @types := int, int8, int16, int32, int64, num, num32, num64, str; plan 2 * @types; for @types -> \T { throws-like { T.new }, Exception, :message{ .contains: "Cannot instantiate" }, T.^name ~ ' no args'; throws-like { T.new: 42 }, Exception, :message{ .contains: "Cannot instantiate" }, T.^name ~ ' with args'; } } #### THIS FILE ALREADY LOTS OF TESTS ADD NEW TESTS TO THE NEXT error.t FILE # vim: expandtab shiftwidth=4