]> git.vpit.fr Git - perl/modules/Scope-Upper.git/blob - t/20-localize-target.t
c68a1a3428e2857b47b5f72b523de154d77aa5a7
[perl/modules/Scope-Upper.git] / t / 20-localize-target.t
1 #!perl -T
2
3 use strict;
4 use warnings;
5
6 use Test::More tests => 70 + 4;
7
8 use Scope::Upper qw<localize UP HERE>;
9
10 # Scalars
11
12 our $x;
13
14 {
15  local $x = 2;
16  {
17   localize *x, \1 => HERE;
18   is $x, 1, 'localize *x, \1 => HERE [ok]';
19  }
20  is $x, 2, 'localize *x, \1 => HERE [end]';
21 }
22
23 sub _t { shift->{t} }
24
25 {
26  local $x;
27  {
28   localize *x, \bless({ t => 1 }, 'main') => HERE;
29   is ref($x), 'main', 'localize *x, obj => HERE [ref]';
30   is $x->_t, 1, 'localize *x, obj => HERE [meth]';
31  }
32  is $x, undef, 'localize *x, obj => HERE [end]';
33 }
34
35 our $y;
36
37 {
38  local $x = 1;
39  local $y = 2;
40  {
41   local $y = 3;
42   localize *x, 'y' => HERE;
43   is $x, 3, "localize *x, 'y' => HERE [ok]";
44  }
45  is $x, 1, "localize *x, 'y' => HERE [end]";
46 }
47 undef *x;
48
49 {
50  local $x = 7;
51  {
52   localize '$x', 2 => HERE;
53   is $x, 2, 'localize "$x", 2 => HERE [ok]';
54  }
55  is $x, 7, 'localize "$x", 2 => HERE [end]';
56 }
57
58 {
59  local $x = 8;
60  {
61   localize ' $x', 3 => HERE;
62   is $x, 3, 'localize " $x", 3 => HERE [ok]';
63  }
64  is $x, 8, 'localize " $x", 3 => HERE [end]';
65 }
66
67 SKIP:
68 {
69  skip 'Can\'t localize through a reference before 5.8.1' => 2
70                                                             if "$]" < 5.008_001;
71  eval q{
72   no strict 'refs';
73   local ${''} = 9;
74   {
75    localize '$', 4 => HERE;
76    is ${''}, 4, 'localize "$", 4 => HERE [ok]';
77   }
78   is ${''}, 9, 'localize "$", 4 => HERE [end]';
79  };
80 }
81
82 SKIP:
83 {
84  skip 'Can\'t localize through a reference before 5.8.1' => 2
85                                                             if "$]" < 5.008_001;
86  eval q{
87   no strict 'refs';
88   local ${''} = 10;
89   {
90    localize '', 5 => HERE;
91    is ${''}, 5, 'localize "", 4 => HERE [ok]';
92   }
93   is ${''}, 10, 'localize "", 4 => HERE [end]';
94  };
95 }
96
97 {
98  local $x = 2;
99  {
100   localize 'x', \1 => HERE;
101   is $x, 1, 'localize "x", \1 => HERE [ok]';
102  }
103  is $x, 2, 'localize "x", \1 => HERE [end]';
104 }
105
106 {
107  local $x = 4;
108  {
109   localize 'x', 3 => HERE;
110   is $x, 3, 'localize "x", 3 => HERE [ok]';
111  }
112  is $x, 4, 'localize "x", 3 => HERE [end]';
113 }
114
115 {
116  local $x;
117  {
118   localize 'x', bless({ t => 2 }, 'main') => HERE;
119   is ref($x), 'main', 'localize "x", obj => HERE [ref]';
120   is $x->_t, 2, 'localize "x", obj => HERE [meth]';
121  }
122  is $x, undef, 'localize "x", obj => HERE [end]';
123 }
124
125 sub callthrough (*$) {
126  my ($what, $val) = @_;
127  if (ref $what) {
128   $what = $$what;
129   $val  = eval "\\$val";
130  }
131  local $x = 'x';
132  localize $what, $val => UP;
133  is $x, 'x', 'localize callthrough [not yet]';
134 }
135
136 {
137  package Scope::Upper::Test::Mock1;
138  our $x;
139  {
140   main::callthrough(*x, 4);
141   Test::More::is($x,       4,     'localize glob [ok - SUTM1]');
142   Test::More::is($main::x, undef, 'localize glob [ok - main]');
143  }
144 }
145
146 {
147  package Scope::Upper::Test::Mock2;
148  our $x;
149  {
150   main::callthrough(*main::x, 5);
151   Test::More::is($x,       undef, 'localize qualified glob [ok - SUTM2]');
152   Test::More::is($main::x, 5,     'localize qualified glob [ok - main]');
153  }
154 }
155
156 {
157  package Scope::Upper::Test::Mock3;
158  our $x;
159  {
160   main::callthrough('$main::x', 6);
161   Test::More::is($x,       undef, 'localize fully qualified name [ok - SUTM3]');
162   Test::More::is($main::x, 6,     'localize fully qualified name [ok - main]');
163  }
164 }
165
166 {
167  package Scope::Upper::Test::Mock4;
168  our $x;
169  {
170   main::callthrough('$x', 7);
171   Test::More::is($x,       7,     'localize unqualified name [ok - SUTM4]');
172   Test::More::is($main::x, undef, 'localize unqualified name [ok - main]');
173  }
174 }
175
176 $_ = 'foo';
177 {
178  package Scope::Upper::Test::Mock5;
179  {
180   main::callthrough('$_', 'bar');
181   Test::More::ok(/bar/, 'localize $_ [ok]');
182  }
183 }
184 undef $_;
185
186 # Arrays
187
188 our @a;
189 my $xa = [ 7 .. 9 ];
190
191 {
192  local @a = (4 .. 6);
193  {
194   localize *a, $xa => HERE;
195   is_deeply \@a, $xa, 'localize *a, [ ] => HERE [ok]';
196  }
197  is_deeply \@a, [ 4 .. 6 ], 'localize *a, [ ] => HERE [end]';
198 }
199
200 {
201  local @a = (4 .. 6);
202  {
203   local @a = (5 .. 7);
204   {
205    localize *a, $xa => UP;
206    is_deeply \@a, [ 5 .. 7 ], 'localize *a, [ ] => UP [not yet]';
207   }
208   is_deeply \@a, $xa, 'localize *a, [ ] => UP [ok]';
209  }
210  is_deeply \@a, [ 4 .. 6 ], 'localize *a, [ ] => UP [end]';
211 }
212
213 # Hashes
214
215 our %h;
216 my $xh = { a => 5, c => 7 };
217
218 {
219  local %h = (a => 1, b => 2);
220  {
221   localize *h, $xh => HERE;
222   is_deeply \%h, $xh, 'localize *h, { } => HERE [ok]';
223  }
224  is_deeply \%h, { a => 1, b => 2 }, 'localize *h, { } => HERE [end]';
225 }
226
227 {
228  local %h = (a => 1, b => 2);
229  {
230   local %h = (b => 3, c => 4);
231   {
232    localize *h, $xh => UP;
233    is_deeply \%h, { b => 3, c => 4 }, 'localize *h, { } => UP [not yet]';
234   }
235   is_deeply \%h, $xh, 'localize *h, { } => UP [ok]';
236  }
237  is_deeply \%h, { a => 1, b => 2 }, 'localize *h, { } => UP [end]';
238 }
239
240 # Code
241
242 {
243  local *foo = sub { 7 };
244  {
245   localize *foo, sub { 6 } => UP;
246   is foo(), 7, 'localize *foo, sub { 6 } => UP [not yet]';
247  }
248  is foo(), 6, 'localize *foo, sub { 6 } => UP [ok]';
249 }
250
251 {
252  local *foo = sub { 9 };
253  {
254   localize '&foo', sub { 8 } => UP;
255   is foo(), 9, 'localize "&foo", sub { 8 } => UP [not yet]';
256  }
257  is foo(), 8, 'localize "&foo", sub { 8 } => UP [ok]';
258 }
259
260 {
261  local *foo = sub { 'a' };
262  {
263   {
264    localize *foo, sub { 'b' } => UP;
265    is foo(), 'a', 'localize *foo, sub { "b" } => UP [not yet 1]';
266    {
267     no warnings 'redefine';
268     local *foo = sub { 'c' };
269     is foo(), 'c', 'localize *foo, sub { "b" } => UP [localized 1]';
270    }
271    is foo(), 'a', 'localize *foo, sub { "b" } => UP [not yet 2]';
272   }
273   is foo(), 'b', 'localize *foo, sub { "b" } => UP [ok 1]';
274   {
275    no warnings 'redefine';
276    local *foo = sub { 'd' };
277    is foo(), 'd', 'localize *foo, sub { "b" } => UP [localized 2]';
278   }
279   is foo(), 'b', 'localize *foo, sub { "b" } => UP [ok 2]';
280  }
281  is foo(), 'a', 'localize *foo, sub { "b" } => UP [end]';
282 }
283
284 {
285  local *foo = sub { 'x' };
286  {
287   {
288    localize *foo, sub { 'y' } => UP;
289    is foo(), 'x', 'localize *foo, sub { "y" } => UP [not yet]';
290   }
291   is foo(), 'y', 'localize *foo, sub { "y" } => UP [ok]';
292   no warnings 'redefine';
293   *foo = sub { 'z' };
294   is foo(), 'z', 'localize *foo, sub { "y" } => UP [replaced]';
295  }
296  is foo(), 'x', 'localize *foo, sub { "y" } => UP [end]';
297 }
298
299 sub X::foo { 'X::foo' }
300
301 {
302  {
303   {
304    localize 'X::foo', sub { 'X::foo 2' } => UP;
305    is(X->foo, 'X::foo', 'localize "X::foo", sub { "X::foo 2" } => UP [not yet]')
306   }
307   is(X->foo, 'X::foo 2', 'localize "X::foo", sub { "X::foo 2" } => UP [ok]');
308  }
309  is(X->foo, 'X::foo', 'localize "X::foo", sub { "X::foo 2" } => UP [end]');
310 }
311
312 @Y::ISA = 'X';
313
314 {
315  {
316   {
317    localize 'X::foo', sub { 'X::foo 3' } => UP;
318    is(Y->foo, 'X::foo', 'localize "X::foo", sub { "X::foo 3" } => UP [not yet]')
319   }
320   is(Y->foo, 'X::foo 3', 'localize "X::foo", sub { "X::foo 3" } => UP [ok]');
321  }
322  is(Y->foo, 'X::foo', 'localize "X::foo", sub { "X::foo 2" } => UP [end]');
323 }
324
325 {
326  {
327   {
328    localize 'Y::foo', sub { 'Y::foo' } => UP;
329    is(Y->foo, 'X::foo', 'localize "Y::foo", sub { "Y::foo" } => UP [not yet]');
330   }
331   is(Y->foo, 'Y::foo', 'localize "Y::foo", sub { "Y::foo" } => UP [ok]');
332  }
333  is(Y->foo, 'X::foo', 'localize "Y::foo", sub { "Y::foo" } => UP [end]');
334 }
335
336 # Invalid
337
338 sub invalid_ref { qr/^Invalid \Q$_[0]\E reference as the localization target/ }
339
340 {
341  eval { localize \1, 0 => HERE };
342  like $@, invalid_ref('SCALAR'), 'invalid localize \1, 0 => HERE';
343 }
344
345 {
346  eval { localize [ ], 0 => HERE };
347  like $@, invalid_ref('ARRAY'),  'invalid localize [ ], 0 => HERE';
348 }
349
350 {
351  eval { localize { }, 0 => HERE };
352  like $@, invalid_ref('HASH'),   'invalid localize { }, 0 => HERE';
353 }
354
355 {
356  eval { localize sub { }, 0 => HERE };
357  like $@, invalid_ref('CODE'),   'invalid localize sub { }, 0 => HERE';
358 }