7 tests => (1 * 3 + 2 * 4 + 3 * 5) * 2 + 7 + 7 + (5 + 6 + 5 + 6 + 5);
9 use Scope::Upper qw<uplevel HERE UP TOP>;
16 my ($depth, $code) = @_;
18 $target = $cxt[$depth];
19 &uplevel($code => $target);
20 pass("$desc: reached end of three()");
26 pass("$desc: reached end of \$two");
32 pass("$desc: reached end of one()");
36 is(HERE, $target, "$desc: right context");
39 my $tester_anon = sub {
40 is(HERE, $target, "$desc: right context");
43 my @subs = (\&three, $two, \&one);
45 for my $height (0 .. 2) {
46 my $base = $subs[$height];
49 my $code = $anon ? $tester_anon : \&tester_sub;
51 for my $depth (0 .. $height) {
53 local $desc = "uplevel at depth $depth/$height";
54 $desc .= $anon ? ' (anonymous callback)' : ' (named callback)';
57 eval { $base->($depth, $code) };
58 is $@, '', "$desc: no error";
64 my $desc = 'uplevel called without a code reference';
68 fail "$desc: uplevel should have croaked";
70 like $@, qr/^First argument to uplevel must be a code reference/,"$desc: dies";
76 uplevel { is HERE, $cxt, "$desc: right context" };
77 pass "$desc: reached end of four()";
81 my $desc = 'uplevel called without a target';
86 is $@, '', "$desc: no error";
90 my $desc = 'uplevel to top';
93 uplevel sub { fail "$desc: uplevel body should not be executed" }, TOP;
94 fail "$desc: uplevel should have croaked";
96 like $@, qr/^Can't uplevel outside a subroutine/, "$desc: dies";
100 my $desc = 'uplevel to eval 1';
103 uplevel sub { fail "$desc: uplevel body should not be executed" }, HERE;
104 fail "$desc: uplevel should have croaked";
106 like $@, qr/^Can't uplevel to an eval frame/, "$desc: dies";
110 my $desc = 'uplevel to eval 2';
115 fail "$desc: uplevel body should not be executed"
117 fail "$desc: uplevel should have croaked";
121 like $@, qr/^Can't uplevel to an eval frame/, "$desc: dies";
127 my $desc = 'uplevel to XS 1';
132 pass "$desc: before";
133 &uplevel(\&HERE => $cxt);
134 is HERE, $cxt, "$desc: after";
137 is $@, '', "$desc: no error";
141 my $desc = 'uplevel to XS 1';
147 is UP, $up, "$desc: before";
148 &uplevel(\&HERE => $up);
149 isnt HERE, $up, "$desc: after 1";
151 is HERE, $up, "$desc: after 2";
154 is $@, '', "$desc: no error";
161 sub Scope::Upper::TestCodeDestruction::DESTROY { ++$destroyed }
165 local $destroyed = 0;
166 my $desc = 'target destruction 1';
175 $target = bless $target, 'Scope::Upper::TestCodeDestruction';
181 is $destroyed, 0, "$desc: not yet 1";
183 is $destroyed, 0, "$desc: not yet 2";
187 is $@, '', "$desc: no error";
188 is $destroyed, 0, "$desc: not yet 3";
191 is $destroyed, 1, "$desc: target is detroyed";
195 skip 'This fails even with a plain subroutine call on 5.8.x' => 6
198 local $destroyed = 0;
199 my $desc = 'target destruction 2';
208 $target = bless $target, 'Scope::Upper::TestCodeDestruction';
215 is $destroyed, 0, "$desc: not yet 1";
217 is $destroyed, 0, "$desc: not yet 2";
219 is $destroyed, 0, "$desc: not yet 3";
223 is $@, '', "$desc: no error";
224 is $destroyed, 0, "$desc: not yet 4";
227 is $destroyed, 1, "$desc: target is detroyed";
232 local $destroyed = 0;
233 my $desc = 'target destruction 3';
243 is $destroyed, 0, "$desc: not yet 1";
246 $target = bless $target, 'Scope::Upper::TestCodeDestruction';
251 &uplevel($target => UP);
252 is $destroyed, 0, "$desc: not yet 2";
256 is $@, '', "$desc: no error";
257 is $destroyed, 0, "$desc: not yet 3";
260 is $destroyed, 1, "$desc: target is detroyed";
264 skip 'This fails even with a plain subroutine call on 5.8.x' => 6
267 local $destroyed = 0;
268 my $desc = 'code destruction';
274 is $destroyed, 0, "$desc: not yet 1";
276 $code = bless $code, 'Scope::Upper::TestCodeDestruction';
282 is $destroyed, 0, "$desc: not yet 2";
284 is $destroyed, 0, "$desc: not yet 2";
287 is $@, '', "$desc: no error";
288 is $destroyed, 0, "$desc: not yet 3";
291 is $destroyed, 1, "$desc: code is destroyed";
295 skip 'This fails even with a plain subroutine call on 5.8.x' => 5
298 local $destroyed = 0;
299 my $desc = 'code destruction and goto';
305 is $destroyed, 0, "$desc: not yet 1";
307 $cb = bless $cb, 'Scope::Upper::TestCodeDestruction';
311 &uplevel(sub { goto $cb } => HERE);
312 is $destroyed, 0, "$desc: not yet 2";
315 is $@, '', "$desc: no error";
316 is $destroyed, 0, "$desc: not yet 3";
319 is $destroyed, 1, "$desc: code is destroyed";