1256a93a4Safresh1#!./perl 2256a93a4Safresh1 3256a93a4Safresh1BEGIN { 4256a93a4Safresh1 chdir 't' if -d 't'; 5256a93a4Safresh1 require './test.pl'; 6256a93a4Safresh1 set_up_inc('../lib'); 7256a93a4Safresh1 require Config; 8256a93a4Safresh1} 9256a93a4Safresh1 10256a93a4Safresh1use strict; 11256a93a4Safresh1use warnings; 12256a93a4Safresh1use feature 'try'; 13256a93a4Safresh1 14256a93a4Safresh1{ 15256a93a4Safresh1 my $x; 16256a93a4Safresh1 try { 17256a93a4Safresh1 $x .= "try"; 18256a93a4Safresh1 } 19256a93a4Safresh1 catch ($e) { 20256a93a4Safresh1 $x .= "catch"; 21256a93a4Safresh1 } 22256a93a4Safresh1 is($x, "try", 'successful try/catch runs try but not catch'); 23256a93a4Safresh1} 24256a93a4Safresh1 25256a93a4Safresh1{ 26256a93a4Safresh1 my $x; 27256a93a4Safresh1 my $caught; 28256a93a4Safresh1 try { 29256a93a4Safresh1 $x .= "try"; 30256a93a4Safresh1 die "Oopsie\n"; 31256a93a4Safresh1 } 32256a93a4Safresh1 catch ($e) { 33256a93a4Safresh1 $x .= "catch"; 34256a93a4Safresh1 $caught = $e; 35256a93a4Safresh1 is($@, "", '$@ is empty within catch block'); 36256a93a4Safresh1 } 37256a93a4Safresh1 is($x, "trycatch", 'die in try runs catch block'); 38256a93a4Safresh1 is($caught, "Oopsie\n", 'catch block saw exception value'); 39256a93a4Safresh1} 40256a93a4Safresh1 41256a93a4Safresh1# return inside try {} makes containing function return 42256a93a4Safresh1{ 43256a93a4Safresh1 sub f 44256a93a4Safresh1 { 45256a93a4Safresh1 try { 46256a93a4Safresh1 return "return inside try"; 47256a93a4Safresh1 } 48256a93a4Safresh1 catch ($e) { } 49256a93a4Safresh1 return "return from func"; 50256a93a4Safresh1 } 51256a93a4Safresh1 is(f(), "return inside try", 'return inside try'); 52256a93a4Safresh1} 53256a93a4Safresh1 54256a93a4Safresh1# wantarray inside try 55256a93a4Safresh1{ 56256a93a4Safresh1 my $context; 57256a93a4Safresh1 sub whatcontext 58256a93a4Safresh1 { 59256a93a4Safresh1 try { 60256a93a4Safresh1 $context = wantarray ? "list" : 61256a93a4Safresh1 defined wantarray ? "scalar" : "void"; 62256a93a4Safresh1 } 63256a93a4Safresh1 catch ($e) { } 64256a93a4Safresh1 } 65256a93a4Safresh1 66256a93a4Safresh1 whatcontext(); 67256a93a4Safresh1 is($context, "void", 'sub {try} in void'); 68256a93a4Safresh1 69256a93a4Safresh1 my $scalar = whatcontext(); 70256a93a4Safresh1 is($context, "scalar", 'sub {try} in scalar'); 71256a93a4Safresh1 72256a93a4Safresh1 my @array = whatcontext(); 73256a93a4Safresh1 is($context, "list", 'sub {try} in list'); 74256a93a4Safresh1} 75256a93a4Safresh1 76256a93a4Safresh1# Loop controls inside try {} do not emit warnings 77256a93a4Safresh1{ 78256a93a4Safresh1 my $warnings = ""; 79256a93a4Safresh1 local $SIG{__WARN__} = sub { $warnings .= $_[0] }; 80256a93a4Safresh1 81256a93a4Safresh1 { 82256a93a4Safresh1 try { 83256a93a4Safresh1 last; 84256a93a4Safresh1 } 85256a93a4Safresh1 catch ($e) { } 86256a93a4Safresh1 } 87256a93a4Safresh1 88256a93a4Safresh1 { 89256a93a4Safresh1 try { 90256a93a4Safresh1 next; 91256a93a4Safresh1 } 92256a93a4Safresh1 catch ($e) { } 93256a93a4Safresh1 } 94256a93a4Safresh1 95256a93a4Safresh1 my $count = 0; 96256a93a4Safresh1 { 97256a93a4Safresh1 try { 98256a93a4Safresh1 $count++; 99256a93a4Safresh1 redo if $count < 2; 100256a93a4Safresh1 } 101256a93a4Safresh1 catch ($e) { } 102256a93a4Safresh1 } 103256a93a4Safresh1 104256a93a4Safresh1 is($warnings, "", 'No warnings emitted by next/last/redo inside try'); 105256a93a4Safresh1 106256a93a4Safresh1 $warnings = ""; 107256a93a4Safresh1 108256a93a4Safresh1 LOOP_L: { 109256a93a4Safresh1 try { 110256a93a4Safresh1 last LOOP_L; 111256a93a4Safresh1 } 112256a93a4Safresh1 catch ($e) { } 113256a93a4Safresh1 } 114256a93a4Safresh1 115256a93a4Safresh1 LOOP_N: { 116256a93a4Safresh1 try { 117256a93a4Safresh1 next LOOP_N; 118256a93a4Safresh1 } 119256a93a4Safresh1 catch ($e) { } 120256a93a4Safresh1 } 121256a93a4Safresh1 122256a93a4Safresh1 $count = 0; 123256a93a4Safresh1 LOOP_R: { 124256a93a4Safresh1 try { 125256a93a4Safresh1 $count++; 126256a93a4Safresh1 redo LOOP_R if $count < 2; 127256a93a4Safresh1 } 128256a93a4Safresh1 catch ($e) { } 129256a93a4Safresh1 } 130256a93a4Safresh1 131256a93a4Safresh1 is($warnings, "", 'No warnings emitted by next/last/redo LABEL inside try'); 132256a93a4Safresh1} 133256a93a4Safresh1 134256a93a4Safresh1# try/catch should localise $@ 135256a93a4Safresh1{ 136256a93a4Safresh1 eval { die "Value before\n"; }; 137256a93a4Safresh1 138256a93a4Safresh1 try { die "Localized value\n" } catch ($e) {} 139256a93a4Safresh1 140256a93a4Safresh1 is($@, "Value before\n", 'try/catch localized $@'); 141256a93a4Safresh1} 142256a93a4Safresh1 143256a93a4Safresh1# try/catch is not confused by false values 144256a93a4Safresh1{ 145256a93a4Safresh1 my $caught; 146256a93a4Safresh1 try { 147256a93a4Safresh1 die 0; 148256a93a4Safresh1 } 149256a93a4Safresh1 catch ($e) { 150256a93a4Safresh1 $caught++; 151256a93a4Safresh1 } 152256a93a4Safresh1 153256a93a4Safresh1 ok( $caught, 'catch{} sees a false exception' ); 154256a93a4Safresh1} 155256a93a4Safresh1 156256a93a4Safresh1# try/catch is not confused by always-false objects 157256a93a4Safresh1{ 158256a93a4Safresh1 my $caught; 159256a93a4Safresh1 try { 160256a93a4Safresh1 die FALSE->new; 161256a93a4Safresh1 } 162256a93a4Safresh1 catch ($e) { 163256a93a4Safresh1 $caught++; 164256a93a4Safresh1 } 165256a93a4Safresh1 166256a93a4Safresh1 ok( $caught, 'catch{} sees a false-overload exception object' ); 167256a93a4Safresh1 168256a93a4Safresh1 { 169256a93a4Safresh1 package FALSE; 170256a93a4Safresh1 use overload 'bool' => sub { 0 }; 171256a93a4Safresh1 sub new { bless [], shift } 172256a93a4Safresh1 } 173256a93a4Safresh1} 174256a93a4Safresh1 175256a93a4Safresh1# return from try is correct even for :lvalue subs 176256a93a4Safresh1# https://github.com/Perl/perl5/issues/18553 177256a93a4Safresh1{ 178256a93a4Safresh1 my $scalar; 179256a93a4Safresh1 sub fscalar :lvalue 180256a93a4Safresh1 { 181256a93a4Safresh1 try { return $scalar } 182256a93a4Safresh1 catch ($e) { } 183256a93a4Safresh1 } 184256a93a4Safresh1 185256a93a4Safresh1 fscalar = 123; 186256a93a4Safresh1 is($scalar, 123, 'try { return } in :lvalue sub in scalar context' ); 187256a93a4Safresh1 188256a93a4Safresh1 my @array; 189256a93a4Safresh1 sub flist :lvalue 190256a93a4Safresh1 { 191256a93a4Safresh1 try { return @array } 192256a93a4Safresh1 catch ($e) { } 193256a93a4Safresh1 } 194256a93a4Safresh1 195256a93a4Safresh1 (flist) = (4, 5, 6); 196256a93a4Safresh1 ok(eq_array(\@array, [4, 5, 6]), 'try { return } in :lvalue sub in list context' ); 197256a93a4Safresh1} 198256a93a4Safresh1 199256a93a4Safresh1# try as final expression yields correct value 200256a93a4Safresh1{ 201256a93a4Safresh1 my $scalar = do { 202256a93a4Safresh1 try { 123 } 203256a93a4Safresh1 catch ($e) { 456 } 204256a93a4Safresh1 }; 205256a93a4Safresh1 is($scalar, 123, 'do { try } in scalar context'); 206256a93a4Safresh1 207256a93a4Safresh1 my @list = do { 208256a93a4Safresh1 try { 1, 2, 3 } 209256a93a4Safresh1 catch ($e) { 4, 5, 6 } 210256a93a4Safresh1 }; 211256a93a4Safresh1 ok(eq_array(\@list, [1, 2, 3]), 'do { try } in list context'); 212256a93a4Safresh1 213256a93a4Safresh1 # Regression test related to 214256a93a4Safresh1 # https://github.com/Perl/perl5/issues/18855 215256a93a4Safresh1 $scalar = do { 216256a93a4Safresh1 try { my $x = 123; 456 } 217256a93a4Safresh1 catch ($e) { 789 } 218256a93a4Safresh1 }; 219256a93a4Safresh1 is($scalar, 456, 'do { try } with multiple statements'); 220256a93a4Safresh1} 221256a93a4Safresh1 222256a93a4Safresh1# catch as final expression yields correct value 223256a93a4Safresh1{ 224256a93a4Safresh1 my $scalar = do { 225256a93a4Safresh1 try { die "Oops" } 226256a93a4Safresh1 catch ($e) { 456 } 227256a93a4Safresh1 }; 228256a93a4Safresh1 is($scalar, 456, 'do { try/catch } in scalar context'); 229256a93a4Safresh1 230256a93a4Safresh1 my @list = do { 231256a93a4Safresh1 try { die "Oops" } 232256a93a4Safresh1 catch ($e) { 4, 5, 6 } 233256a93a4Safresh1 }; 234256a93a4Safresh1 ok(eq_array(\@list, [4, 5, 6]), 'do { try/catch } in list context'); 235256a93a4Safresh1 236256a93a4Safresh1 # Regression test 237256a93a4Safresh1 # https://github.com/Perl/perl5/issues/18855 238256a93a4Safresh1 $scalar = do { 239256a93a4Safresh1 try { die "Oops" } 240256a93a4Safresh1 catch ($e) { my $x = 123; "result" } 241256a93a4Safresh1 }; 242256a93a4Safresh1 is($scalar, "result", 'do { try/catch } with multiple statements'); 243256a93a4Safresh1} 244256a93a4Safresh1 245256a93a4Safresh1# try{} blocks should be invisible to caller() 246256a93a4Safresh1{ 247256a93a4Safresh1 my $caller; 248256a93a4Safresh1 sub A { $caller = sprintf "%s (%s line %d)", (caller 1)[3,1,2]; } 249256a93a4Safresh1 250256a93a4Safresh1 sub B { 251256a93a4Safresh1 try { A(); } 252256a93a4Safresh1 catch ($e) {} 253256a93a4Safresh1 } 254256a93a4Safresh1 255256a93a4Safresh1 my $LINE = __LINE__+1; 256256a93a4Safresh1 B(); 257256a93a4Safresh1 258256a93a4Safresh1 is($caller, "main::B ($0 line $LINE)", 'try {} block is invisible to caller()'); 259256a93a4Safresh1} 260256a93a4Safresh1 261256a93a4Safresh1# try/catch/finally 262*5486feefSafresh1 263*5486feefSafresh1# experimental warnings 264*5486feefSafresh1{ 265*5486feefSafresh1 my $warnings; 266*5486feefSafresh1 BEGIN { $SIG{__WARN__} = sub { $warnings .= shift; }; } 267*5486feefSafresh1 268*5486feefSafresh1 my ($lfinally) = (__LINE__+5); 269*5486feefSafresh1 try { 270*5486feefSafresh1 } 271*5486feefSafresh1 catch ($e) { 272*5486feefSafresh1 } 273*5486feefSafresh1 finally { 274*5486feefSafresh1 } 275*5486feefSafresh1 276*5486feefSafresh1 is($warnings, "try/catch/finally is experimental at $0 line $lfinally.\n", 277*5486feefSafresh1 'compiletime warnings'); 278*5486feefSafresh1 BEGIN { undef $SIG{__WARN__}; } 279*5486feefSafresh1} 280*5486feefSafresh1 281*5486feefSafresh1no warnings 'experimental::try'; 282*5486feefSafresh1 283256a93a4Safresh1{ 284256a93a4Safresh1 my $x; 285256a93a4Safresh1 try { 286256a93a4Safresh1 $x .= "try"; 287256a93a4Safresh1 } 288256a93a4Safresh1 catch ($e) { 289256a93a4Safresh1 $x .= "catch"; 290256a93a4Safresh1 } 291256a93a4Safresh1 finally { 292256a93a4Safresh1 $x .= "finally"; 293256a93a4Safresh1 } 294256a93a4Safresh1 is($x, "tryfinally", 'successful try/catch/finally runs try+finally but not catch'); 295256a93a4Safresh1} 296256a93a4Safresh1 297256a93a4Safresh1{ 298256a93a4Safresh1 my $x; 299256a93a4Safresh1 try { 300256a93a4Safresh1 $x .= "try"; 301256a93a4Safresh1 die "Oopsie\n"; 302256a93a4Safresh1 } 303256a93a4Safresh1 catch ($e) { 304256a93a4Safresh1 $x .= "catch"; 305256a93a4Safresh1 } 306256a93a4Safresh1 finally { 307256a93a4Safresh1 $x .= "finally"; 308256a93a4Safresh1 } 309256a93a4Safresh1 is($x, "trycatchfinally", 'try/catch/finally runs try+catch+finally on failure'); 310256a93a4Safresh1} 311256a93a4Safresh1 312256a93a4Safresh1{ 313256a93a4Safresh1 my $finally_invoked; 314256a93a4Safresh1 sub ff 315256a93a4Safresh1 { 316256a93a4Safresh1 try { 317256a93a4Safresh1 return "return inside try+finally"; 318256a93a4Safresh1 } 319256a93a4Safresh1 catch ($e) {} 320256a93a4Safresh1 finally { $finally_invoked++; "last value" } 321256a93a4Safresh1 return "return from func"; 322256a93a4Safresh1 } 323256a93a4Safresh1 is(ff(), "return inside try+finally", 'return inside try+finally'); 324256a93a4Safresh1 ok($finally_invoked, 'finally block still invoked for side-effects'); 325256a93a4Safresh1} 326256a93a4Safresh1 327f2a19305Safresh1# Nicer compiletime errors 328256a93a4Safresh1{ 329256a93a4Safresh1 my $e; 330256a93a4Safresh1 331f2a19305Safresh1 $e = defined eval 'try { A() } catch { B() }; 1;' ? undef : $@; 332f2a19305Safresh1 like($e, qr/^catch block requires a \(VAR\) at /, 333f2a19305Safresh1 'Parse error for catch without (VAR)'); 334256a93a4Safresh1} 335256a93a4Safresh1 336256a93a4Safresh1done_testing; 337