File: 01.cloning.t

package info (click to toggle)
libclass-std-storable-perl 0.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 100 kB
  • sloc: perl: 111; makefile: 2
file content (149 lines) | stat: -rw-r--r-- 4,509 bytes parent folder | download | duplicates (4)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main;
use Test::More tests => 43;
use strict;

package TestClass;
use Class::Std::Storable;
{
    my %name_of :ATTR( :get<name> :set<name> );
    my %flavor_of :ATTR( :get<flavor> :set<flavor> );
}

package LinkedList;
use Class::Std::Storable;
{
    my %info_of :ATTR( :get<info> :set<info> );
    my %next_node_for :ATTR( :get<next_node> :set<next_node> );
}

package TestMISubClass;
use Class::Std::Storable;
use base qw( TestClass LinkedList );
{
    my %ref_copy_for :ATTR( :get<ref_copy> );
    my %unknown1 :ATTR; #for testing with no attr name given
    my %unknown2 :ATTR; #for testing with no attr name given
    sub set_next_node {
        my $self = shift;
        my $id = ident $self;
        die "no param provided" unless @_;
        my $next_node = shift;
        $ref_copy_for{$id} = $next_node;
        $self->SUPER::set_next_node($next_node);
        return;
    }
    sub set_unknown1 {
        my $id = ident shift;
        $unknown1{$id} = shift;
    }
    sub get_unknown1 {
        return $unknown1{ident shift};
    }
    sub set_unknown2 {
        my $id = ident shift;
        $unknown2{$id} = shift;
    }
    sub get_unknown2 {
        return $unknown2{ident shift};
    }
}

package main;
use Class::Std::Storable;
use Storable;
use Carp;
use Data::Dumper;

##########################################################
# very basic testing of a single object
my $object = TestClass->new;
$object->set_name("Vanilla Bean");
$object->set_flavor("vanilla");

my $clone = Storable::dclone($object);
is( $clone->get_name, "Vanilla Bean", "properties successfully cloned");
is( $clone->get_flavor, "vanilla", "properties successfully cloned");

##########################################################
# testing a nested structure
my $first_node = LinkedList->new;
$first_node->set_info(1);
for my $i (2..10) {
    my $next_node = LinkedList->new;
    $next_node->set_info($i);
    $next_node->set_next_node($first_node);
    $first_node = $next_node;
}

my $id = ident($first_node);
$first_node = Storable::dclone($first_node);

isnt($id, ident($first_node), "should in fact be a different object");
for my $i (reverse 1..10) {
    is($first_node->get_info, $i, "values in the nodes all match");
    $first_node = $first_node->get_next_node;
}


##########################################################
# testing MI and structural integrity

my @flavors = qw( vanilla chocolate strawberry mango peach grape );
my $obj;
for my $flavor ( @flavors ) {
    my $next = TestMISubClass->new;
    $next->set_flavor($flavor);
    $next->set_info($flavor);
    $next->set_unknown1("1_$flavor");
    $next->set_unknown2("2_$flavor");
    $next->set_next_node($obj);
    $obj = $next;
}

$clone = Storable::freeze($obj);
undef $obj; #should destroy the whole list
$clone = Storable::thaw($clone);
for my $flavor ( reverse @flavors ) {
    is($flavor, $clone->get_flavor, "flavor cloned the same");
    is("1_$flavor", $clone->get_unknown1, "unknown1 cloned the same");
    is("2_$flavor", $clone->get_unknown2, "unknown2 cloned the same");
    my $next = $clone->get_next_node;
    my $copy = $clone->get_ref_copy;
    last unless $next;
    is(ident($next), ident($copy), "clones of same object should be the same");
    $clone = $next;
}

##########################################################
# generating diagnostics
$object = TestClass->new;
$object->set_name("Vanilla Bean");
$object->set_flavor("vanilla");

eval { $object->STORABLE_thaw(0, 0, {TestClass => { name => "foo" } } ) };
like($@, qr{trying to modify existing attributes}, "block attempted manipulation");

eval { $object->STORABLE_thaw(0, 0, {TestClass => { unknown => "foo" } } ) };
like($@, qr{unknown attribute}, "error on unknown attribute");

eval { $object->STORABLE_thaw(0, 0, {unknown => {} } ) };
like($@, qr{unknown base class}, "error on unknown base class");

##########################################################
# calling hooks

my($freeze_pre, $freeze_post, $thaw_pre, $thaw_post);

{ no warnings; #ignore spurious "only used once" warnings
*TestClass::STORABLE_freeze_pre = sub { $freeze_pre = 1 };
*TestClass::STORABLE_freeze_post = sub { $freeze_post = 1 };
*TestClass::STORABLE_thaw_pre = sub { $thaw_pre = 1 };
*TestClass::STORABLE_thaw_post = sub { $thaw_post = 1 };
}

Storable::dclone($object);
ok( $freeze_pre, "STORABLE_freeze_pre called");
ok( $freeze_post, "STORABLE_freeze_post called");
ok( $thaw_pre, "STORABLE_thaw_pre called");
ok( $thaw_post, "STORABLE_thaw_post called");