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
|
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
eval "use Test::Memory::Cycle 1.02";
plan skip_all => "Test::Memory::Cycle required for testing memory leaks" if $@;
plan tests => 51;
use_ok('Tree::Simple');
#diag "parental connections must be destroyed manually";
{ #diag "verify the problem exists";
my $tree2 = Tree::Simple->new("2");
ok($tree2->isRoot(), '... tree2 is a ROOT');
my $tree1_UID;
{
my $tree1 = Tree::Simple->new("1");
$tree1_UID = $tree1->getUID();
$tree1->addChild($tree2);
ok(!$tree2->isRoot(), '... now tree2 is not a ROOT');
memory_cycle_exists($tree2, '... there is a cycle in tree2');
}
memory_cycle_exists($tree2, '... tree1 is still connected with tree2');
ok(!$tree2->isRoot(), '... now tree2 is not a ROOT');
ok(defined($tree2->getParent()), '... now tree2s parent is still defined');
is($tree2->getParent()->getUID(), $tree1_UID, '... and tree2s parent is tree1');
}
{ #diag "this fixes the problem";
my $tree2 = Tree::Simple->new("2");
ok($tree2->isRoot(), '... tree2 is a ROOT');
{
my $tree1 = Tree::Simple->new("1");
$tree1->addChild($tree2);
ok(!$tree2->isRoot(), '... now tree2 is not a ROOT');
memory_cycle_exists($tree2, '... there is a cycle in tree2');
$tree1->DESTROY();
}
memory_cycle_ok($tree2, '... calling DESTORY on tree1 broke the connection with tree2');
ok($tree2->isRoot(), '... now tree2 is a ROOT again');
ok(!defined($tree2->getParent()), '... now tree2s parent is no longer defined');
}
#diag "expand the original problem and see how it effects children";
{
my $tree2 = Tree::Simple->new("2");
ok($tree2->isRoot(), '... tree2 is a ROOT');
ok($tree2->isLeaf(), '... tree2 is a Leaf');
my $tree3 = Tree::Simple->new("3");
ok($tree3->isRoot(), '... tree3 is a ROOT');
ok($tree3->isLeaf(), '... tree3 is a Leaf');
{
my $tree1 = Tree::Simple->new("1");
$tree1->addChild($tree2);
ok(!$tree2->isRoot(), '... now tree2 is not a ROOT');
$tree2->addChild($tree3);
ok(!$tree2->isLeaf(), '... now tree2 is not a Leaf');
ok(!$tree3->isRoot(), '... tree3 is no longer a ROOT');
ok($tree3->isLeaf(), '... but tree3 is still a Leaf');
memory_cycle_exists($tree1, '... there is a cycle in tree1');
memory_cycle_exists($tree2, '... there is a cycle in tree2');
memory_cycle_exists($tree3, '... there is a cycle in tree3');
$tree1->DESTROY();
memory_cycle_exists($tree1, '... there is still a cycle in tree1 because of the children');
}
memory_cycle_exists($tree2, '... calling DESTORY on tree1 broke the connection with tree2');
ok($tree2->isRoot(), '... now tree2 is a ROOT again');
ok(!$tree2->isLeaf(), '... now tree2 is not a leaf again');
ok(!defined($tree2->getParent()), '... now tree2s parent is no longer defined');
cmp_ok($tree2->getChildCount(), '==', 1, '... now tree2 has one child');
memory_cycle_exists($tree3, '... calling DESTORY on tree1 did not break the connection betwee tree2 and tree3');
ok(!$tree3->isRoot(), '... now tree3 is not a ROOT');
ok($tree3->isLeaf(), '... now tree3 is still a leaf');
ok(defined($tree3->getParent()), '... now tree3s parent is still defined');
is($tree3->getParent(), $tree2, '... now tree3s parent is still tree2');
}
#diag "child connections are strong";
{
my $tree1 = Tree::Simple->new("1");
my $tree2_UID;
{
my $tree2 = Tree::Simple->new("2");
$tree1->addChild($tree2);
$tree2_UID = $tree2->getUID();
memory_cycle_exists($tree1, '... tree1 is connected to tree2');
memory_cycle_exists($tree2, '... tree2 is connected to tree1');
$tree2->DESTROY(); # this doesn't make sense to do
}
memory_cycle_exists($tree1, '... tree2 is still connected to tree1 because child connections are strong');
is($tree1->getChild(0)->getUID(), $tree2_UID, '... tree2 is still connected to tree1');
is($tree1->getChild(0)->getParent(), $tree1, '... tree2s parent is tree1');
cmp_ok($tree1->getChildCount(), '==', 1, '... tree1 has a child count of 1');
}
#diag "expand upon this issue";
{
my $tree1 = Tree::Simple->new("1");
my $tree2_UID;
my $tree3 = Tree::Simple->new("3");
{
my $tree2 = Tree::Simple->new("2");
$tree1->addChild($tree2);
$tree2_UID = $tree2->getUID();
$tree2->addChild($tree3);
memory_cycle_exists($tree1, '... tree1 is connected to tree2');
memory_cycle_exists($tree2, '... tree2 is connected to tree1');
memory_cycle_exists($tree3, '... tree3 is connected to tree2');
$tree2->DESTROY(); # this doesn't make sense to do
}
memory_cycle_exists($tree1, '... tree2 is still connected to tree1 because child connections are strong');
is($tree1->getChild(0)->getUID(), $tree2_UID, '... tree2 is still connected to tree1');
is($tree1->getChild(0)->getParent(), $tree1, '... tree2s parent is tree1');
cmp_ok($tree1->getChildCount(), '==', 1, '... tree1 has a child count of 1');
cmp_ok($tree1->getChild(0)->getChildCount(), '==', 1, '... tree2 is still connected to tree3');
is($tree1->getChild(0)->getChild(0), $tree3, '... tree2 is still connected to tree3');
}
|