X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=t%2F58-yield-misc.t;h=e89e8926ceb5cbac39232c04f780d14b6e0b4780;hb=eef3f2764e7018e3eaf2f1d11f249b510d023a2d;hp=2eb222ff8e6c07a11715ff57bba2f9b2de2f2a63;hpb=be1d59463692da1b5ef787aeffd0aedbef65664e;p=perl%2Fmodules%2FScope-Upper.git diff --git a/t/58-yield-misc.t b/t/58-yield-misc.t index 2eb222f..e89e892 100644 --- a/t/58-yield-misc.t +++ b/t/58-yield-misc.t @@ -3,12 +3,12 @@ use strict; use warnings; -use Test::More tests => 4 * 3 + 3; +use Test::More tests => 4 * 3 + 1 + 3 + 7; use lib 't/lib'; use VPIT::TestHelpers; -use Scope::Upper qw; +use Scope::Upper qw; # Test timely destruction of values returned from yield() @@ -75,6 +75,34 @@ sub guard { VPIT::TestHelpers::Guard->new(sub { ++$destroyed }) } is $destroyed, 1, "$desc: destroyed 2"; } +# Test 'return from do' in special cases + +{ + no warnings 'void'; + my @res = (1, do { + my $cxt = HERE; + my $thing = (777, do { + my @stuff = (888, do { + yield 2, 3 => $cxt; + map { my $x; $_ x 3 } qw + }, 999); + if (@stuff) { + my $y; + ++$y; + 'YYY'; + } else { + die 'not reached'; + } + }); + if (1) { + my $z; + 'ZZZ'; + } + 'VVV' + }, 4); + is "@res", '1 2 3 4', 'yield() found the op to return to'; +} + # Test leave { @@ -93,7 +121,9 @@ sub guard { VPIT::TestHelpers::Guard->new(sub { ++$destroyed }) } is "@res", '1 2 3 4', 'leave with arguments'; } -{ +SKIP: { + skip '"eval { $str =~ s/./die q[foo]/e }" breaks havoc on perl 5.8 and below' + => 1 if "$]" < 5.010; my $s = 'a'; local $@; eval { @@ -102,6 +132,52 @@ sub guard { VPIT::TestHelpers::Guard->new(sub { ++$destroyed }) } my $err = $@; my $line = __LINE__-3; like $err, - qr/^leave\(\) cannot target a substitution context at \Q$0\E line $line/, + qr/^leave\(\) can't target a substitution context at \Q$0\E line $line/, 'leave() cannot exit subst'; } + +{ + my @destroyed; + + { + package Scope::Upper::TestTimelyDestruction; + + sub new { + my ($class, $label) = @_; + bless { label => $label }, $class; + } + + sub label { $_[0]->{label} } + + sub DESTROY { + push @destroyed, $_[0]->label; + } + } + + sub SU_TTD () { 'Scope::Upper::TestTimelyDestruction' } + + sub foo { + my $r = SU_TTD->new('a'); + my @x = (SU_TTD->new('c'), SU_TTD->new('d')); + yield 123, $r, SU_TTD->new('b'), @x, sub { SU_TTD->new('e') }->() => UP SUB; + } + + sub bar { + foo(); + die 'not reached'; + } + + { + my $desc = sub { "yielding @_ across a sub" }; + my @res = bar(); + is $res[0], 123, $desc->('a constant literal'); + is $res[1]->label, 'a', $desc->('a lexical'); + is $res[2]->label, 'b', $desc->('a temporary object'); + is $res[3]->label, 'c', $desc->('the contents of a lexical array (1)'); + is $res[4]->label, 'd', $desc->('the contents of a lexical array (2)'); + is $res[5]->label, 'e', $desc->('a temporary object returned by a sub'); + } + + is_deeply \@destroyed, [ qw ], + 'all these objects were properly destroyed'; +}