xref: /openbsd/gnu/usr.bin/perl/t/op/closure.t (revision 404b540a)
1#!./perl
2#                              -*- Mode: Perl -*-
3# closure.t:
4#   Original written by Ulrich Pfeifer on 2 Jan 1997.
5#   Greatly extended by Tom Phoenix <rootbeer@teleport.com> on 28 Jan 1997.
6#
7#   Run with -debug for debugging output.
8
9BEGIN {
10    chdir 't' if -d 't';
11    @INC = '../lib';
12}
13
14use Config;
15require './test.pl'; # for runperl()
16
17print "1..188\n";
18
19my $test = 1;
20sub test (&) {
21  my $ok = &{$_[0]};
22  print $ok ? "ok $test\n" : "not ok $test\n";
23  printf "# Failed at line %d\n", (caller)[2] unless $ok;
24  $test++;
25}
26
27my $i = 1;
28sub foo { $i = shift if @_; $i }
29
30# no closure
31test { foo == 1 };
32foo(2);
33test { foo == 2 };
34
35# closure: lexical outside sub
36my $foo = sub {$i = shift if @_; $i };
37my $bar = sub {$i = shift if @_; $i };
38test {&$foo() == 2 };
39&$foo(3);
40test {&$foo() == 3 };
41# did the lexical change?
42test { foo == 3 and $i == 3};
43# did the second closure notice?
44test {&$bar() == 3 };
45
46# closure: lexical inside sub
47sub bar {
48  my $i = shift;
49  sub { $i = shift if @_; $i }
50}
51
52$foo = bar(4);
53$bar = bar(5);
54test {&$foo() == 4 };
55&$foo(6);
56test {&$foo() == 6 };
57test {&$bar() == 5 };
58
59# nested closures
60sub bizz {
61  my $i = 7;
62  if (@_) {
63    my $i = shift;
64    sub {$i = shift if @_; $i };
65  } else {
66    my $i = $i;
67    sub {$i = shift if @_; $i };
68  }
69}
70$foo = bizz();
71$bar = bizz();
72test {&$foo() == 7 };
73&$foo(8);
74test {&$foo() == 8 };
75test {&$bar() == 7 };
76
77$foo = bizz(9);
78$bar = bizz(10);
79test {&$foo(11)-1 == &$bar()};
80
81my @foo;
82for (qw(0 1 2 3 4)) {
83  my $i = $_;
84  $foo[$_] = sub {$i = shift if @_; $i };
85}
86
87test {
88  &{$foo[0]}() == 0 and
89  &{$foo[1]}() == 1 and
90  &{$foo[2]}() == 2 and
91  &{$foo[3]}() == 3 and
92  &{$foo[4]}() == 4
93  };
94
95for (0 .. 4) {
96  &{$foo[$_]}(4-$_);
97}
98
99test {
100  &{$foo[0]}() == 4 and
101  &{$foo[1]}() == 3 and
102  &{$foo[2]}() == 2 and
103  &{$foo[3]}() == 1 and
104  &{$foo[4]}() == 0
105  };
106
107sub barf {
108  my @foo;
109  for (qw(0 1 2 3 4)) {
110    my $i = $_;
111    $foo[$_] = sub {$i = shift if @_; $i };
112  }
113  @foo;
114}
115
116@foo = barf();
117test {
118  &{$foo[0]}() == 0 and
119  &{$foo[1]}() == 1 and
120  &{$foo[2]}() == 2 and
121  &{$foo[3]}() == 3 and
122  &{$foo[4]}() == 4
123  };
124
125for (0 .. 4) {
126  &{$foo[$_]}(4-$_);
127}
128
129test {
130  &{$foo[0]}() == 4 and
131  &{$foo[1]}() == 3 and
132  &{$foo[2]}() == 2 and
133  &{$foo[3]}() == 1 and
134  &{$foo[4]}() == 0
135  };
136
137# test if closures get created in optimized for loops
138
139my %foo;
140for my $n ('A'..'E') {
141    $foo{$n} = sub { $n eq $_[0] };
142}
143
144test {
145  &{$foo{A}}('A') and
146  &{$foo{B}}('B') and
147  &{$foo{C}}('C') and
148  &{$foo{D}}('D') and
149  &{$foo{E}}('E')
150};
151
152for my $n (0..4) {
153    $foo[$n] = sub { $n == $_[0] };
154}
155
156test {
157  &{$foo[0]}(0) and
158  &{$foo[1]}(1) and
159  &{$foo[2]}(2) and
160  &{$foo[3]}(3) and
161  &{$foo[4]}(4)
162};
163
164for my $n (0..4) {
165    $foo[$n] = sub {
166                     # no intervening reference to $n here
167                     sub { $n == $_[0] }
168		   };
169}
170
171test {
172  $foo[0]->()->(0) and
173  $foo[1]->()->(1) and
174  $foo[2]->()->(2) and
175  $foo[3]->()->(3) and
176  $foo[4]->()->(4)
177};
178
179{
180    my $w;
181    $w = sub {
182	my ($i) = @_;
183	test { $i == 10 };
184	sub { $w };
185    };
186    $w->(10);
187}
188
189# Additional tests by Tom Phoenix <rootbeer@teleport.com>.
190
191{
192    use strict;
193
194    use vars qw!$test!;
195    my($debugging, %expected, $inner_type, $where_declared, $within);
196    my($nc_attempt, $call_outer, $call_inner, $undef_outer);
197    my($code, $inner_sub_test, $expected, $line, $errors, $output);
198    my(@inners, $sub_test, $pid);
199    $debugging = 1 if defined($ARGV[0]) and $ARGV[0] eq '-debug';
200
201    # The expected values for these tests
202    %expected = (
203	'global_scalar'	=> 1001,
204	'global_array'	=> 2101,
205	'global_hash'	=> 3004,
206	'fs_scalar'	=> 4001,
207	'fs_array'	=> 5101,
208	'fs_hash'	=> 6004,
209	'sub_scalar'	=> 7001,
210	'sub_array'	=> 8101,
211	'sub_hash'	=> 9004,
212	'foreach'	=> 10011,
213    );
214
215    # Our innermost sub is either named or anonymous
216    for $inner_type (qw!named anon!) {
217      # And it may be declared at filescope, within a named
218      # sub, or within an anon sub
219      for $where_declared (qw!filescope in_named in_anon!) {
220	# And that, in turn, may be within a foreach loop,
221	# a naked block, or another named sub
222	for $within (qw!foreach naked other_sub!) {
223
224	  # Here are a number of variables which show what's
225	  # going on, in a way.
226	  $nc_attempt = 0+		# Named closure attempted
227	      ( ($inner_type eq 'named') ||
228	      ($within eq 'other_sub') ) ;
229	  $call_inner = 0+		# Need to call &inner
230	      ( ($inner_type eq 'anon') &&
231	      ($within eq 'other_sub') ) ;
232	  $call_outer = 0+		# Need to call &outer or &$outer
233	      ( ($inner_type eq 'anon') &&
234	      ($within ne 'other_sub') ) ;
235	  $undef_outer = 0+		# $outer is created but unused
236	      ( ($where_declared eq 'in_anon') &&
237	      (not $call_outer) ) ;
238
239	  $code = "# This is a test script built by t/op/closure.t\n\n";
240
241	  print <<"DEBUG_INFO" if $debugging;
242# inner_type:     $inner_type
243# where_declared: $where_declared
244# within:         $within
245# nc_attempt:     $nc_attempt
246# call_inner:     $call_inner
247# call_outer:     $call_outer
248# undef_outer:    $undef_outer
249DEBUG_INFO
250
251	  $code .= <<"END_MARK_ONE";
252
253BEGIN { \$SIG{__WARN__} = sub {
254    my \$msg = \$_[0];
255END_MARK_ONE
256
257	  $code .=  <<"END_MARK_TWO" if $nc_attempt;
258    return if index(\$msg, 'will not stay shared') != -1;
259    return if index(\$msg, 'is not available') != -1;
260END_MARK_TWO
261
262	  $code .= <<"END_MARK_THREE";		# Backwhack a lot!
263    print "not ok: got unexpected warning \$msg\\n";
264} }
265
266{
267    my \$test = $test;
268    sub test (&) {
269      my \$ok = &{\$_[0]};
270      print \$ok ? "ok \$test\n" : "not ok \$test\n";
271      printf "# Failed at line %d\n", (caller)[2] unless \$ok;
272      \$test++;
273    }
274}
275
276# some of the variables which the closure will access
277\$global_scalar = 1000;
278\@global_array = (2000, 2100, 2200, 2300);
279%global_hash = 3000..3009;
280
281my \$fs_scalar = 4000;
282my \@fs_array = (5000, 5100, 5200, 5300);
283my %fs_hash = 6000..6009;
284
285END_MARK_THREE
286
287	  if ($where_declared eq 'filescope') {
288	    # Nothing here
289	  } elsif ($where_declared eq 'in_named') {
290	    $code .= <<'END';
291sub outer {
292  my $sub_scalar = 7000;
293  my @sub_array = (8000, 8100, 8200, 8300);
294  my %sub_hash = 9000..9009;
295END
296    # }
297	  } elsif ($where_declared eq 'in_anon') {
298	    $code .= <<'END';
299$outer = sub {
300  my $sub_scalar = 7000;
301  my @sub_array = (8000, 8100, 8200, 8300);
302  my %sub_hash = 9000..9009;
303END
304    # }
305	  } else {
306	    die "What was $where_declared?"
307	  }
308
309	  if ($within eq 'foreach') {
310	    $code .= "
311      my \$foreach = 12000;
312      my \@list = (10000, 10010);
313      foreach \$foreach (\@list) {
314    " # }
315	  } elsif ($within eq 'naked') {
316	    $code .= "  { # naked block\n"	# }
317	  } elsif ($within eq 'other_sub') {
318	    $code .= "  sub inner_sub {\n"	# }
319	  } else {
320	    die "What was $within?"
321	  }
322
323	  $sub_test = $test;
324	  @inners = ( qw!global_scalar global_array global_hash! ,
325	    qw!fs_scalar fs_array fs_hash! );
326	  push @inners, 'foreach' if $within eq 'foreach';
327	  if ($where_declared ne 'filescope') {
328	    push @inners, qw!sub_scalar sub_array sub_hash!;
329	  }
330	  for $inner_sub_test (@inners) {
331
332	    if ($inner_type eq 'named') {
333	      $code .= "    sub named_$sub_test "
334	    } elsif ($inner_type eq 'anon') {
335	      $code .= "    \$anon_$sub_test = sub "
336	    } else {
337	      die "What was $inner_type?"
338	    }
339
340	    # Now to write the body of the test sub
341	    if ($inner_sub_test eq 'global_scalar') {
342	      $code .= '{ ++$global_scalar }'
343	    } elsif ($inner_sub_test eq 'fs_scalar') {
344	      $code .= '{ ++$fs_scalar }'
345	    } elsif ($inner_sub_test eq 'sub_scalar') {
346	      $code .= '{ ++$sub_scalar }'
347	    } elsif ($inner_sub_test eq 'global_array') {
348	      $code .= '{ ++$global_array[1] }'
349	    } elsif ($inner_sub_test eq 'fs_array') {
350	      $code .= '{ ++$fs_array[1] }'
351	    } elsif ($inner_sub_test eq 'sub_array') {
352	      $code .= '{ ++$sub_array[1] }'
353	    } elsif ($inner_sub_test eq 'global_hash') {
354	      $code .= '{ ++$global_hash{3002} }'
355	    } elsif ($inner_sub_test eq 'fs_hash') {
356	      $code .= '{ ++$fs_hash{6002} }'
357	    } elsif ($inner_sub_test eq 'sub_hash') {
358	      $code .= '{ ++$sub_hash{9002} }'
359	    } elsif ($inner_sub_test eq 'foreach') {
360	      $code .= '{ ++$foreach }'
361	    } else {
362	      die "What was $inner_sub_test?"
363	    }
364
365	    # Close up
366	    if ($inner_type eq 'anon') {
367	      $code .= ';'
368	    }
369	    $code .= "\n";
370	    $sub_test++;	# sub name sequence number
371
372	  } # End of foreach $inner_sub_test
373
374	  # Close up $within block		# {
375	  $code .= "  }\n\n";
376
377	  # Close up $where_declared block
378	  if ($where_declared eq 'in_named') {	# {
379	    $code .= "}\n\n";
380	  } elsif ($where_declared eq 'in_anon') {	# {
381	    $code .= "};\n\n";
382	  }
383
384	  # We may need to do something with the sub we just made...
385	  $code .= "undef \$outer;\n" if $undef_outer;
386	  $code .= "&inner_sub;\n" if $call_inner;
387	  if ($call_outer) {
388	    if ($where_declared eq 'in_named') {
389	      $code .= "&outer;\n\n";
390	    } elsif ($where_declared eq 'in_anon') {
391	      $code .= "&\$outer;\n\n"
392	    }
393	  }
394
395	  # Now, we can actually prep to run the tests.
396	  for $inner_sub_test (@inners) {
397	    $expected = $expected{$inner_sub_test} or
398	      die "expected $inner_sub_test missing";
399
400	    # Named closures won't access the expected vars
401	    if ( $nc_attempt and
402		substr($inner_sub_test, 0, 4) eq "sub_" ) {
403	      $expected = 1;
404	    }
405
406	    # If you make a sub within a foreach loop,
407	    # what happens if it tries to access the
408	    # foreach index variable? If it's a named
409	    # sub, it gets the var from "outside" the loop,
410	    # but if it's anon, it gets the value to which
411	    # the index variable is aliased.
412	    #
413	    # Of course, if the value was set only
414	    # within another sub which was never called,
415	    # the value has not been set yet.
416	    #
417	    if ($inner_sub_test eq 'foreach') {
418	      if ($inner_type eq 'named') {
419		if ($call_outer || ($where_declared eq 'filescope')) {
420		  $expected = 12001
421		} else {
422		  $expected = 1
423		}
424	      }
425	    }
426
427	    # Here's the test:
428	    if ($inner_type eq 'anon') {
429	      $code .= "test { &\$anon_$test == $expected };\n"
430	    } else {
431	      $code .= "test { &named_$test == $expected };\n"
432	    }
433	    $test++;
434	  }
435
436	  if ($Config{d_fork} and $^O ne 'VMS' and $^O ne 'MSWin32' and $^O ne 'NetWare') {
437	    # Fork off a new perl to run the tests.
438	    # (This is so we can catch spurious warnings.)
439	    $| = 1; print ""; $| = 0; # flush output before forking
440	    pipe READ, WRITE or die "Can't make pipe: $!";
441	    pipe READ2, WRITE2 or die "Can't make second pipe: $!";
442	    die "Can't fork: $!" unless defined($pid = open PERL, "|-");
443	    unless ($pid) {
444	      # Child process here. We're going to send errors back
445	      # through the extra pipe.
446	      close READ;
447	      close READ2;
448	      open STDOUT, ">&WRITE"  or die "Can't redirect STDOUT: $!";
449	      open STDERR, ">&WRITE2" or die "Can't redirect STDERR: $!";
450	      exec which_perl(), '-w', '-'
451		or die "Can't exec perl: $!";
452	    } else {
453	      # Parent process here.
454	      close WRITE;
455	      close WRITE2;
456	      print PERL $code;
457	      close PERL;
458	      { local $/;
459	        $output = join '', <READ>;
460	        $errors = join '', <READ2>; }
461	      close READ;
462	      close READ2;
463	    }
464	  } else {
465	    # No fork().  Do it the hard way.
466	    my $cmdfile = tempfile();
467	    my $errfile = tempfile();
468	    open CMD, ">$cmdfile"; print CMD $code; close CMD;
469	    my $cmd = which_perl();
470	    $cmd .= " -w $cmdfile 2>$errfile";
471	    if ($^O eq 'VMS' or $^O eq 'MSWin32' or $^O eq 'NetWare') {
472	      # Use pipe instead of system so we don't inherit STD* from
473	      # this process, and then foul our pipe back to parent by
474	      # redirecting output in the child.
475	      open PERL,"$cmd |" or die "Can't open pipe: $!\n";
476	      { local $/; $output = join '', <PERL> }
477	      close PERL;
478	    } else {
479	      my $outfile = tempfile();
480	      system "$cmd >$outfile";
481	      { local $/; open IN, $outfile; $output = <IN>; close IN }
482	    }
483	    if ($?) {
484	      printf "not ok: exited with error code %04X\n", $?;
485	      exit;
486	    }
487	    { local $/; open IN, $errfile; $errors = <IN>; close IN }
488	  }
489	  print $output;
490	  print STDERR $errors;
491	  if ($debugging && ($errors || $? || ($output =~ /not ok/))) {
492	    my $lnum = 0;
493	    for $line (split '\n', $code) {
494	      printf "%3d:  %s\n", ++$lnum, $line;
495	    }
496	  }
497	  printf "not ok: exited with error code %04X\n", $? if $?;
498	  print '#', "-" x 30, "\n" if $debugging;
499
500	}	# End of foreach $within
501      }	# End of foreach $where_declared
502    }	# End of foreach $inner_type
503
504}
505
506# The following dumps core with perl <= 5.8.0 (bugid 9535) ...
507BEGIN { $vanishing_pad = sub { eval $_[0] } }
508$some_var = 123;
509test { $vanishing_pad->( '$some_var' ) == 123 };
510
511# ... and here's another coredump variant - this time we explicitly
512# delete the sub rather than using a BEGIN ...
513
514sub deleteme { $a = sub { eval '$newvar' } }
515deleteme();
516*deleteme = sub {}; # delete the sub
517$newvar = 123; # realloc the SV of the freed CV
518test { $a->() == 123 };
519
520# ... and a further coredump variant - the fixup of the anon sub's
521# CvOUTSIDE pointer when the middle eval is freed, wasn't good enough to
522# survive the outer eval also being freed.
523
524$x = 123;
525$a = eval q(
526    eval q[
527	sub { eval '$x' }
528    ]
529);
530@a = ('\1\1\1\1\1\1\1') x 100; # realloc recently-freed CVs
531test { $a->() == 123 };
532
533# this coredumped on <= 5.8.0 because evaling the closure caused
534# an SvFAKE to be added to the outer anon's pad, which was then grown.
535my $outer;
536sub {
537    my $x;
538    $x = eval 'sub { $outer }';
539    $x->();
540    $a = [ 99 ];
541    $x->();
542}->();
543test {1};
544
545# [perl #17605] found that an empty block called in scalar context
546# can lead to stack corruption
547{
548    my $x = "foooobar";
549    $x =~ s/o//eg;
550    test { $x eq 'fbar' }
551}
552
553# DAPM 24-Nov-02
554# SvFAKE lexicals should be visible thoughout a function.
555# On <= 5.8.0, the third test failed,  eg bugid #18286
556
557{
558    my $x = 1;
559    sub fake {
560		test { sub {eval'$x'}->() == 1 };
561	{ $x;	test { sub {eval'$x'}->() == 1 } }
562		test { sub {eval'$x'}->() == 1 };
563    }
564}
565fake();
566
567# undefining a sub shouldn't alter visibility of outer lexicals
568
569{
570    $x = 1;
571    my $x = 2;
572    sub tmp { sub { eval '$x' } }
573    my $a = tmp();
574    undef &tmp;
575    test { $a->() == 2 };
576}
577
578# handy class: $x = Watch->new(\$foo,'bar')
579# causes 'bar' to be appended to $foo when $x is destroyed
580sub Watch::new { bless [ $_[1], $_[2] ], $_[0] }
581sub Watch::DESTROY { ${$_[0][0]} .= $_[0][1] }
582
583
584# bugid 1028:
585# nested anon subs (and associated lexicals) not freed early enough
586
587sub linger {
588    my $x = Watch->new($_[0], '2');
589    sub {
590	$x;
591	my $y;
592	sub { $y; };
593    };
594}
595{
596    my $watch = '1';
597    linger(\$watch);
598    test { $watch eq '12' }
599}
600
601# bugid 10085
602# obj not freed early enough
603
604sub linger2 {
605    my $obj = Watch->new($_[0], '2');
606    sub { sub { $obj } };
607}
608{
609    my $watch = '1';
610    linger2(\$watch);
611    test { $watch eq '12' }
612}
613
614# bugid 16302 - named subs didn't capture lexicals on behalf of inner subs
615
616{
617    my $x = 1;
618    sub f16302 {
619	sub {
620	    test { defined $x and $x == 1 }
621	}->();
622    }
623}
624f16302();
625
626# The presence of an eval should turn cloneless anon subs into clonable
627# subs - otherwise the CvOUTSIDE of that sub may be wrong
628
629{
630    my %a;
631    for my $x (7,11) {
632	$a{$x} = sub { $x=$x; sub { eval '$x' } };
633    }
634    test { $a{7}->()->() + $a{11}->()->() == 18 };
635}
636
637{
638   # bugid #23265 - this used to coredump during destruction of PL_maincv
639   # and its children
640
641    my $progfile = "b23265.pl";
642    open(T, ">$progfile") or die "$0: $!\n";
643    print T << '__EOF__';
644        print
645            sub {$_[0]->(@_)} -> (
646                sub {
647                    $_[1]
648                        ?  $_[0]->($_[0], $_[1] - 1) .  sub {"x"}->()
649                        : "y"
650                },
651                2
652            )
653            , "\n"
654        ;
655__EOF__
656    close T;
657    my $got = runperl(progfile => $progfile);
658    test { chomp $got; $got eq "yxx" };
659    END { 1 while unlink $progfile }
660}
661
662{
663    # bugid #24914 = used to coredump restoring PL_comppad in the
664    # savestack, due to the early freeing of the anon closure
665
666    my $got = runperl(stderr => 1, prog =>
667'sub d {die} my $f; $f = sub {my $x=1; $f = 0; d}; eval{$f->()}; print qq(ok\n)'
668    );
669    test { $got eq "ok\n" };
670}
671
672# After newsub is redefined outside the BEGIN, it's CvOUTSIDE should point
673# to main rather than BEGIN, and BEGIN should be freed.
674
675{
676    my $flag = 0;
677    sub  X::DESTROY { $flag = 1 }
678    {
679	my $x;
680	BEGIN {$x = \&newsub }
681	sub newsub {};
682	$x = bless {}, 'X';
683    }
684    test { $flag == 1 };
685}
686
687# don't copy a stale lexical; crate a fresh undef one instead
688
689sub f {
690    my $x if $_[0];
691    sub { \$x }
692}
693
694{
695    f(1);
696    my $c1= f(0);
697    my $c2= f(0);
698
699    my $r1 = $c1->();
700    my $r2 = $c2->();
701    test { $r1 != $r2 };
702}
703
704
705
706
707