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