Skip to content

Commit 16b5acd

Browse files
author
Branislav Zahradník
committed
[tests] New tests focused on scope behaviour of loop variables
be it control variable of `for (;;)` variant or cursor variable(s) of `for $var () { } continue { }` Tests test: - visibility of variable in for loop - visibility of variable in continue loop - behaviour after loop
1 parent e286876 commit 16b5acd

File tree

3 files changed

+239
-0
lines changed

3 files changed

+239
-0
lines changed

MANIFEST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6349,7 +6349,9 @@ t/op/filetest_stack_ok.t See if file tests leave their argument on the stack
63496349
t/op/filetest_t.t See if -t file test works
63506350
t/op/flip.t See if range operator works
63516351
t/op/for.t See if for loops work
6352+
t/op/for-control-scope.t See if scope of for-control control variable(s) works
63526353
t/op/for-many.t See if n-at-a-time for loops work
6354+
t/op/for-over-scope.t See if scope of for-over cursor variable(s) works
63536355
t/op/fork.t See if fork works
63546356
t/op/fresh_perl_utf8.t UTF8 tests for pads and gvs
63556357
t/op/getpid.t See if $$ and getppid work with threads

t/op/for-control-scope.t

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!./perl
2+
3+
# Test lexical scope of `for` statement, variant: `for (init; control condition; post iterate)`
4+
5+
BEGIN {
6+
chdir 't' if -d 't';
7+
require "./test.pl";
8+
set_up_inc('../lib');
9+
}
10+
11+
use v5.38;
12+
13+
assume q ([for-control] modifies global variable)
14+
=> expect => q (3)
15+
=> eval => q {
16+
no strict;
17+
no warnings;
18+
19+
for ($control_global = 1; $control_global < 3; ++$control_global) { }
20+
21+
$control_global // q (undef);
22+
};
23+
24+
assume q ([for-control] `my` variable is restricted into `for`'s lexical scope)
25+
=> expect => q (42)
26+
=> eval => q {
27+
use strict;
28+
use warnings FATAL => q (all);
29+
30+
my $control_my = 42;
31+
32+
for (my $control_my = 1; $control_my < 3; ++$control_my) { }
33+
34+
$control_my;
35+
};
36+
37+
assume q ([for-control] `our` variable declared inside `for` scope isn't visible outside)
38+
=> throws => qr (^Variable ".control_our" is not imported)
39+
=> eval => q {
40+
use strict;
41+
use warnings FATAL => q (all);
42+
43+
for (our $control_our = 1; $control_our < 3; ++$control_our) { }
44+
45+
$control_our;
46+
};
47+
48+
assume q ([for-control] `our` variable inside `for` scope redeclares outer variable)
49+
=> throws => qr (^"our" variable .control_redeclared redeclared)
50+
=> eval => q {
51+
use strict;
52+
use warnings FATAL => q (all);
53+
54+
our $control_redeclared = 42;
55+
56+
for (our $control_redeclared = 1; $control_redeclared < 3; ++$control_redeclared) { }
57+
58+
$control_redeclared;
59+
};
60+
61+
assume q ([for-control] `local` localizes variable )
62+
=> expect => q (3)
63+
=> eval => q {
64+
use strict;
65+
use warnings FATAL => q (all);
66+
67+
our $control_local = 42;
68+
69+
for (local $control_local = 1; $control_local < 3; ++$control_local) { }
70+
71+
$control_local;
72+
};
73+
74+
done_testing;

t/op/for-over-scope.t

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!./perl
2+
3+
# Test lexical scope of `for` statement, variant: `for $var (@array)` (foreach)
4+
# Tested behaviour:
5+
# - capability to declare / use given cursor
6+
# - visibility of given cursor in both for-block and continue-block
7+
# - behaviour of cursor after for-loop (exists? what value?)
8+
9+
BEGIN {
10+
chdir 't' if -d 't';
11+
require "./test.pl";
12+
set_up_inc('../lib');
13+
}
14+
15+
use v5.38;
16+
17+
assume q ([for-over] global cursor is visible in `continue` block and its original value is preserved)
18+
=> expect => q (/Foo.Foo=42)
19+
=> eval => q {
20+
my $cursor_global = 42;
21+
22+
for $cursor_global (qw (Foo)) {
23+
$result .= q (/) . $cursor_global;
24+
} continue {
25+
$result .= q (.) . $cursor_global;
26+
}
27+
28+
$result .= q (=) . ($cursor_global // q ([undef]));
29+
};
30+
31+
assume q ([for-over] `our` cursor is visible in continue block)
32+
=> expect => q (/Foo.Foo)
33+
=> eval => q {
34+
use warnings FATAL => q (all);
35+
36+
for our $cursor_our_continue (qw (Foo)) {
37+
$result .= q (/) . $cursor_our_continue;
38+
} continue {
39+
$result .= q (.) . $cursor_our_continue;
40+
}
41+
42+
$result;
43+
};
44+
45+
assume q ([for-over] `our` cursor is not visible after `for` loop)
46+
=> throws => qr (^Variable "\$cursor_our_after" is not imported)
47+
=> eval => q {
48+
use warnings FATAL => q (all);
49+
50+
for our $cursor_our_after (qw (Foo)) {
51+
}
52+
53+
$result .= $cursor_our_after;
54+
};
55+
56+
assume q ([for-over] `our` cursor redeclares already declared global variable)
57+
=> throws => qr (^"our" variable .cursor_redeclared redeclared)
58+
=> eval => q {
59+
use warnings FATAL => q (all);
60+
61+
our $cursor_redeclared = 42;
62+
63+
for our $cursor_redeclared () {
64+
}
65+
};
66+
67+
assume q ([for-over] `my` cursor is visible in `continue` block)
68+
=> expect => q (/Foo.Foo)
69+
=> eval => q {
70+
use warnings FATAL => q (all);
71+
72+
for my $cursor_my (q (Foo)) {
73+
$result .= q (/) . $cursor_my;
74+
} continue {
75+
$result .= q (.) . $cursor_my;
76+
}
77+
78+
$result;
79+
};
80+
81+
assume q ([for-over] `my` cursor is not visible after `for` loop)
82+
=> throws => qr (^Global symbol "\$cursor_my_after" requires explicit package name)
83+
=> eval => q {
84+
use strict;
85+
use warnings;
86+
87+
for my $cursor_my_after (q (Foo)) {
88+
}
89+
90+
$cursor_my_after;
91+
};
92+
93+
assume q ([for-over] `my` multi-cursors are visible in `continue` block)
94+
=> expect => q (/FooBar.FooBar)
95+
=> eval => q {
96+
use warnings FATAL => q (all);
97+
98+
for my ($cursor_multi_1, $cursor_multi_2) (qw (Foo Bar)) {
99+
$result .= q (/) . $cursor_multi_1 . $cursor_multi_2;
100+
} continue {
101+
$result .= q (.) . $cursor_multi_1 . $cursor_multi_2;
102+
}
103+
104+
$result;
105+
};
106+
107+
assume q ([for-over] `my` multi-cursors are not visible after `for` loop)
108+
=> throws => qr (^Global symbol "\$cursor_my_multi_1" requires explicit package name)
109+
=> eval => q {
110+
use warnings FATAL => q (all);
111+
112+
for my ($cursor_my_multi_1, $cursor_my_multi_2) (qw (Foo Bar)) {
113+
} continue {
114+
}
115+
116+
$cursor_my_multi_1;
117+
};
118+
119+
assume q ([for-over] `refaliasing` global cursor doesn't preserve it's original value)
120+
=> expect => q (/Foo.Foo=Foo)
121+
=> eval => q {
122+
use warnings FATAL => q (all);
123+
use experimental qw (refaliasing);
124+
125+
my $cursor_refalias = 42;
126+
127+
for \ $cursor_refalias (\ qw (Foo)) {
128+
$result .= q (/) . $cursor_refalias;
129+
} continue {
130+
$result .= q (.) . $cursor_refalias;
131+
}
132+
133+
$result . q (=) . $cursor_refalias;
134+
};
135+
136+
assume q ([for-over] `declared_refs` is visible in continue block)
137+
=> expect => q (/Foo.Foo)
138+
=> eval => q {
139+
use warnings FATAL => q (all);
140+
use experimental qw (declared_refs);
141+
142+
for my \ $cursor_refs (\ qw (Foo)) {
143+
$result .= q (/) . $cursor_refs;
144+
} continue {
145+
$result .= q (.) . $cursor_refs;
146+
}
147+
148+
$result;
149+
};
150+
151+
assume q ([for-over] `declared_refs` is not visible after loop)
152+
=> throws => qr (^Global symbol "\$cursor_refs_after" requires explicit package name)
153+
=> eval => q {
154+
use warnings FATAL => q (all);
155+
use experimental qw (declared_refs);
156+
157+
for my \ $cursor_refs_after (\ qw (Foo)) {
158+
}
159+
160+
$cursor_refs_after;
161+
};
162+
163+
done_testing;

0 commit comments

Comments
 (0)