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