1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
#!/usr/bin/env perl
use strict;
use warnings;
use lib 't/lib';
use Test::More;
use Test::Fatal;
{
package My::Package::Stash;
use strict;
use warnings;
use base 'Package::Stash';
use Symbol 'gensym';
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{namespace} = {};
return $self;
}
sub add_symbol {
my ($self, $variable, $initial_value) = @_;
(my $name = $variable) =~ s/^[\$\@\%\&]//;
my $glob = gensym();
*{$glob} = $initial_value if defined $initial_value;
$self->namespace->{$name} = *{$glob};
}
}
# No actually package Foo exists :)
my $foo_stash = My::Package::Stash->new('Foo');
isa_ok($foo_stash, 'My::Package::Stash');
isa_ok($foo_stash, 'Package::Stash');
ok(!defined($Foo::{foo}), '... the %foo slot has not been created yet');
ok(!$foo_stash->has_symbol('%foo'), '... the foo_stash agrees');
is(exception {
$foo_stash->add_symbol('%foo' => { one => 1 });
}, undef, '... the %foo symbol is created succcessfully');
ok(!defined($Foo::{foo}), '... the %foo slot has not been created in the actual Foo package');
ok($foo_stash->has_symbol('%foo'), '... the foo_stash agrees');
my $foo = $foo_stash->get_symbol('%foo');
is_deeply({ one => 1 }, $foo, '... got the right package variable back');
$foo->{two} = 2;
is($foo, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the foo_stashs');
ok(!defined($Foo::{bar}), '... the @bar slot has not been created yet');
is(exception {
$foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
}, undef, '... created @Foo::bar successfully');
ok(!defined($Foo::{bar}), '... the @bar slot has still not been created');
ok(!defined($Foo::{baz}), '... the %baz slot has not been created yet');
is(exception {
$foo_stash->add_symbol('%baz');
}, undef, '... created %Foo::baz successfully');
ok(!defined($Foo::{baz}), '... the %baz slot has still not been created');
done_testing;
|