don't rely on the ::PP BROKEN_ constants existing in tests
[gitmo/Package-Stash.git] / t / anon-basic.t
CommitLineData
31cd651f 1#!/usr/bin/env perl
2use strict;
3use warnings;
4use lib 't/lib';
5use Test::More;
6use Test::Fatal;
7
8use Test::Requires 'Package::Anon';
9use Package::Stash;
10use Symbol;
11
d93368f6 12plan skip_all => "Anonymous stashes in PP need at least perl 5.14"
acbc69c4 13 if $] < 5.014
ace6563d 14 && $Package::Stash::IMPLEMENTATION eq 'PP';
d93368f6 15
31cd651f 16my $Foo = Package::Anon->new('Foo');
17$Foo->{SOME_CONSTANT} = \1;
18
19# ----------------------------------------------------------------------
20## tests adding a HASH
21
22my $foo_stash = Package::Stash->new($Foo);
23ok(!defined($Foo->{foo}), '... the %foo slot has not been created yet');
24ok(!$foo_stash->has_symbol('%foo'), '... the object agrees');
25ok(!defined($Foo->{foo}), '... checking doesn\'t vivify');
26
27is(exception {
28 $foo_stash->add_symbol('%foo' => { one => 1 });
29}, undef, '... created %Foo::foo successfully');
30
31# ... scalar should NOT be created here
32
33ok(!$foo_stash->has_symbol('$foo'), '... SCALAR shouldnt have been created too');
34ok(!$foo_stash->has_symbol('@foo'), '... ARRAY shouldnt have been created too');
35ok(!$foo_stash->has_symbol('&foo'), '... CODE shouldnt have been created too');
36
37ok(defined($Foo->{foo}), '... the %foo slot was created successfully');
38ok($foo_stash->has_symbol('%foo'), '... the meta agrees');
39
40# check the value ...
41
42ok(exists $Foo->{foo}{one}, '... our %foo was initialized correctly');
43is($Foo->{foo}{one}, 1, '... our %foo was initialized correctly');
44
45my $foo = $foo_stash->get_symbol('%foo');
46is_deeply({ one => 1 }, $foo, '... got the right package variable back');
47
48# ... make sure changes propogate up
49
50$foo->{two} = 2;
51
52is(\%{ $Foo->{foo} }, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the metas');
53
54ok(exists ${ $Foo->{foo} }{two}, '... our %foo was updated correctly');
55is(${ $Foo->{foo} }{two}, 2, '... our %foo was updated correctly');
56
57# ----------------------------------------------------------------------
58## test adding an ARRAY
59
60ok(!defined($Foo->{bar}), '... the @bar slot has not been created yet');
61
62is(exception {
63 $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
64}, undef, '... created @Foo::bar successfully');
65
66ok(defined($Foo->{bar}), '... the @bar slot was created successfully');
67ok($foo_stash->has_symbol('@bar'), '... the meta agrees');
68
69# ... why does this not work ...
70
71ok(!$foo_stash->has_symbol('$bar'), '... SCALAR shouldnt have been created too');
72ok(!$foo_stash->has_symbol('%bar'), '... HASH shouldnt have been created too');
73ok(!$foo_stash->has_symbol('&bar'), '... CODE shouldnt have been created too');
74
75# check the value itself
76
77is(scalar @{ $Foo->{bar} }, 3, '... our @bar was initialized correctly');
78is($Foo->{bar}[1], 2, '... our @bar was initialized correctly');
79
80# ----------------------------------------------------------------------
81## test adding a SCALAR
82
83ok(!defined($Foo->{baz}), '... the $baz slot has not been created yet');
84
85is(exception {
86 $foo_stash->add_symbol('$baz' => 10);
87}, undef, '... created $Foo::baz successfully');
88
89ok(defined($Foo->{baz}), '... the $baz slot was created successfully');
90ok($foo_stash->has_symbol('$baz'), '... the meta agrees');
91
92ok(!$foo_stash->has_symbol('@baz'), '... ARRAY shouldnt have been created too');
93ok(!$foo_stash->has_symbol('%baz'), '... HASH shouldnt have been created too');
94ok(!$foo_stash->has_symbol('&baz'), '... CODE shouldnt have been created too');
95
96is(${$foo_stash->get_symbol('$baz')}, 10, '... got the right value back');
97
98${ $Foo->{baz} } = 1;
99
100is(${ $Foo->{baz} }, 1, '... our $baz was assigned to correctly');
101is(${$foo_stash->get_symbol('$baz')}, 1, '... the meta agrees');
102
103# ----------------------------------------------------------------------
104## test adding a CODE
105
106ok(!defined($Foo->{funk}), '... the &funk slot has not been created yet');
107
108is(exception {
109 $foo_stash->add_symbol('&funk' => sub { "Foo::funk" });
110}, undef, '... created &Foo::funk successfully');
111
112ok(defined($Foo->{funk}), '... the &funk slot was created successfully');
113ok($foo_stash->has_symbol('&funk'), '... the meta agrees');
114
115ok(!$foo_stash->has_symbol('$funk'), '... SCALAR shouldnt have been created too');
116ok(!$foo_stash->has_symbol('@funk'), '... ARRAY shouldnt have been created too');
117ok(!$foo_stash->has_symbol('%funk'), '... HASH shouldnt have been created too');
118
119ok(defined &{ $Foo->{funk} }, '... our &funk exists');
120
121is($Foo->bless({})->funk(), 'Foo::funk', '... got the right value from the function');
122
123# ----------------------------------------------------------------------
124## test multiple slots in the glob
125
126my $ARRAY = [ 1, 2, 3 ];
127my $CODE = sub { "Foo::foo" };
128
129is(exception {
130 $foo_stash->add_symbol('@foo' => $ARRAY);
131}, undef, '... created @Foo::foo successfully');
132
133ok($foo_stash->has_symbol('@foo'), '... the @foo slot was added successfully');
134is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
135
136is(exception {
137 $foo_stash->add_symbol('&foo' => $CODE);
138}, undef, '... created &Foo::foo successfully');
139
140ok($foo_stash->has_symbol('&foo'), '... the meta agrees');
141is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
142
143is(exception {
144 $foo_stash->add_symbol('$foo' => 'Foo::foo');
145}, undef, '... created $Foo::foo successfully');
146
147ok($foo_stash->has_symbol('$foo'), '... the meta agrees');
148my $SCALAR = $foo_stash->get_symbol('$foo');
149is($$SCALAR, 'Foo::foo', '... got the right scalar value back');
150
151is(${ $Foo->{foo} }, 'Foo::foo', '... got the right value from the scalar');
152
153is(exception {
154 $foo_stash->remove_symbol('%foo');
155}, undef, '... removed %Foo::foo successfully');
156
157ok(!$foo_stash->has_symbol('%foo'), '... the %foo slot was removed successfully');
158ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
159ok($foo_stash->has_symbol('&foo'), '... the &foo slot still exists');
160ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
161
162is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
163is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
164is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
165
166ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
167ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
168ok(defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has NOT been removed');
169ok(defined(${ $Foo->{foo} }), '... the $foo slot has NOT been removed');
170
171is(exception {
172 $foo_stash->remove_symbol('&foo');
173}, undef, '... removed &Foo::foo successfully');
174
175ok(!$foo_stash->has_symbol('&foo'), '... the &foo slot no longer exists');
176
177ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
178ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
179
180is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
181is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
182
183ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
184ok(!defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has now been removed');
185ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
186ok(defined(${ $Foo->{foo} }), '... the $foo slot has NOT been removed');
187
188is(exception {
189 $foo_stash->remove_symbol('$foo');
190}, undef, '... removed $Foo::foo successfully');
191
192ok(!$foo_stash->has_symbol('$foo'), '... the $foo slot no longer exists');
193
194ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
195
196is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
197
198ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
199ok(!defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has now been removed');
200ok(!defined(${ $Foo->{foo} }), '... the $foo slot has now been removed');
201ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
202
203{
204 my $syms = $foo_stash->get_all_symbols;
205 is_deeply(
206 [ sort keys %{ $syms } ],
207 [ sort $foo_stash->list_all_symbols ],
208 '... the fetched symbols are the same as the listed ones'
209 );
210}
211
212{
213 my $syms = $foo_stash->get_all_symbols('CODE');
214
215 is_deeply(
216 [ sort keys %{ $syms } ],
217 [ sort $foo_stash->list_all_symbols('CODE') ],
218 '... the fetched symbols are the same as the listed ones'
219 );
220
221 foreach my $symbol (keys %{ $syms }) {
222 is($syms->{$symbol}, $foo_stash->get_symbol('&' . $symbol), '... got the right symbol');
223 }
224}
225
226{
227 $foo_stash->add_symbol('%bare');
228 ok(!$foo_stash->has_symbol('$bare'),
229 "add_symbol with single argument doesn't vivify scalar slot");
230}
231
232{
233 $foo_stash->add_symbol('%zork', {});
234
235 my $syms = $foo_stash->get_all_symbols('HASH');
236
237 is_deeply(
238 [ sort keys %{ $syms } ],
239 [ sort $foo_stash->list_all_symbols('HASH') ],
240 '... the fetched symbols are the same as the listed ones'
241 );
242
243 foreach my $symbol (keys %{ $syms }) {
244 is($syms->{$symbol}, $foo_stash->get_symbol('%' . $symbol), '... got the right symbol');
245 }
246
247 is_deeply(
248 $syms,
249 { zork => *{ $Foo->{zork} }{HASH} },
250 "got the right ones",
251 );
252}
253
254# check some errors
255
256like(exception {
257 $foo_stash->add_symbol('@bar', {})
258}, qr/HASH.*is not of type ARRAY/, "can't initialize a slot with the wrong type of value");
259
260like(exception {
261 $foo_stash->add_symbol('bar', [])
262}, qr/ARRAY.*is not of type IO/, "can't initialize a slot with the wrong type of value");
263
264like(exception {
265 $foo_stash->add_symbol('$bar', sub { })
266}, qr/CODE.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
267
268like(exception {
269 $foo_stash->add_symbol('$bar', *{ Symbol::geniosym() }{IO})
270}, qr/IO.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
271
272is_deeply([Package::Stash->new('Foo')->list_all_symbols], [],
273 "Foo:: isn't touched");
274
275my $Quux = Package::Anon->new('Quux');
276$Quux->{foo} = *{ Symbol::gensym() };
277*{ $Quux->{foo} } = \23;
278*{ $Quux->{foo} } = ["bar"];
279*{ $Quux->{foo} } = { baz => 1 };
280*{ $Quux->{foo} } = sub { };
281*{ $Quux->{foo} } = *{ Symbol::geniosym() }{IO};
282
283{
284 my $stash = Package::Stash->new($Quux);
285
286 my %expect = (
287 '$foo' => \23,
288 '@foo' => ["bar"],
289 '%foo' => { baz => 1 },
290 '&foo' => \&{ $Quux->{foo} },
291 'foo' => *{ $Quux->{foo} }{IO},
292 );
293
294 for my $sym ( sort keys %expect ) {
295 is_deeply(
296 $stash->get_symbol($sym),
297 $expect{$sym},
298 "got expected value for $sym"
299 );
300 }
301
302 $stash->add_symbol('%bar' => {x => 42});
303
304 $expect{'%bar'} = {x => 42};
305
306 for my $sym ( sort keys %expect ) {
307 is_deeply(
308 $stash->get_symbol($sym),
309 $expect{$sym},
310 "got expected value for $sym"
311 );
312 }
313
314 $stash->add_symbol('%bar' => {x => 43});
315
316 $expect{'%bar'} = {x => 43};
317
318 for my $sym ( sort keys %expect ) {
319 is_deeply(
320 $stash->get_symbol($sym),
321 $expect{$sym},
322 "got expected value for $sym"
323 );
324 }
325}
326
327is_deeply([Package::Stash->new('Quux')->list_all_symbols], [],
328 "Quux:: isn't touched");
329
330my $Quuux = Package::Anon->new('Quuux');
331
332$Quuux->{foo} = *{ Symbol::gensym() };
333*{ $Quuux->{foo} } = \(my $scalar);
334*{ $Quuux->{foo} } = [];
335
336$Quuux->{bar} = *{ Symbol::gensym() };
337*{ $Quuux->{bar} } = [];
338
339$Quuux->{baz} = *{ Symbol::gensym() };
340*{ $Quuux->{baz} } = {};
341*{ $Quuux->{baz} } = sub { };
342
343$Quuux->{quux} = \1;
344
345$Quuux->{quuux} = \[];
346
347$Quuux->{quuuux} = -1;
348
349{
350 my $quuux = Package::Stash->new($Quuux);
351 is_deeply(
352 # Package::Anon adds a couple methods
353 [grep { $_ ne 'isa' && $_ ne 'can' } sort $quuux->list_all_symbols],
354 [qw(bar baz foo quuuux quuux quux)],
355 "list_all_symbols",
356 );
357 { local $TODO = $] < 5.010
358 ? "undef scalars aren't visible on 5.8"
359 : undef;
360 is_deeply(
361 [sort $quuux->list_all_symbols('SCALAR')],
362 [qw(foo)],
363 "list_all_symbols SCALAR",
364 );
365 }
366 is_deeply(
367 [sort $quuux->list_all_symbols('ARRAY')],
368 [qw(bar foo)],
369 "list_all_symbols ARRAY",
370 );
371 is_deeply(
372 [sort $quuux->list_all_symbols('HASH')],
373 [qw(baz)],
374 "list_all_symbols HASH",
375 );
376 is_deeply(
377 # Package::Anon adds a couple methods
378 [grep { $_ ne 'isa' && $_ ne 'can' } sort $quuux->list_all_symbols('CODE')],
379 [qw(baz quuuux quuux quux)],
380 "list_all_symbols CODE",
381 );
382}
383
384is_deeply([Package::Stash->new('Quuux')->list_all_symbols], [],
385 "Quuux:: isn't touched");
386
387done_testing;