1#!/usr/bin/perl 2 3use strict; 4use warnings; 5 6use Test::More; 7 8eval "use Test::Memory::Cycle 1.02"; 9plan skip_all => "Test::Memory::Cycle required for testing memory leaks" if $@; 10 11plan tests => 51; 12 13use_ok('Tree::Simple'); 14 15#diag "parental connections must be destroyed manually"; 16 17{ #diag "verify the problem exists"; 18 19 my $tree2 = Tree::Simple->new("2"); 20 ok($tree2->isRoot(), '... tree2 is a ROOT'); 21 my $tree1_UID; 22 { 23 my $tree1 = Tree::Simple->new("1"); 24 $tree1_UID = $tree1->getUID(); 25 $tree1->addChild($tree2); 26 ok(!$tree2->isRoot(), '... now tree2 is not a ROOT'); 27 28 memory_cycle_exists($tree2, '... there is a cycle in tree2'); 29 } 30 31 memory_cycle_exists($tree2, '... tree1 is still connected with tree2'); 32 ok(!$tree2->isRoot(), '... now tree2 is not a ROOT'); 33 ok(defined($tree2->getParent()), '... now tree2s parent is still defined'); 34 is($tree2->getParent()->getUID(), $tree1_UID, '... and tree2s parent is tree1'); 35 36} 37 38{ #diag "this fixes the problem"; 39 40 my $tree2 = Tree::Simple->new("2"); 41 ok($tree2->isRoot(), '... tree2 is a ROOT'); 42 43 { 44 my $tree1 = Tree::Simple->new("1"); 45 $tree1->addChild($tree2); 46 ok(!$tree2->isRoot(), '... now tree2 is not a ROOT'); 47 48 memory_cycle_exists($tree2, '... there is a cycle in tree2'); 49 $tree1->DESTROY(); 50 } 51 52 memory_cycle_ok($tree2, '... calling DESTORY on tree1 broke the connection with tree2'); 53 ok($tree2->isRoot(), '... now tree2 is a ROOT again'); 54 ok(!defined($tree2->getParent()), '... now tree2s parent is no longer defined'); 55} 56 57#diag "expand the original problem and see how it effects children"; 58 59{ 60 61 my $tree2 = Tree::Simple->new("2"); 62 ok($tree2->isRoot(), '... tree2 is a ROOT'); 63 ok($tree2->isLeaf(), '... tree2 is a Leaf'); 64 my $tree3 = Tree::Simple->new("3"); 65 ok($tree3->isRoot(), '... tree3 is a ROOT'); 66 ok($tree3->isLeaf(), '... tree3 is a Leaf'); 67 68 { 69 my $tree1 = Tree::Simple->new("1"); 70 $tree1->addChild($tree2); 71 ok(!$tree2->isRoot(), '... now tree2 is not a ROOT'); 72 $tree2->addChild($tree3); 73 ok(!$tree2->isLeaf(), '... now tree2 is not a Leaf'); 74 ok(!$tree3->isRoot(), '... tree3 is no longer a ROOT'); 75 ok($tree3->isLeaf(), '... but tree3 is still a Leaf'); 76 77 memory_cycle_exists($tree1, '... there is a cycle in tree1'); 78 memory_cycle_exists($tree2, '... there is a cycle in tree2'); 79 memory_cycle_exists($tree3, '... there is a cycle in tree3'); 80 $tree1->DESTROY(); 81 82 memory_cycle_exists($tree1, '... there is still a cycle in tree1 because of the children'); 83 } 84 85 memory_cycle_exists($tree2, '... calling DESTORY on tree1 broke the connection with tree2'); 86 ok($tree2->isRoot(), '... now tree2 is a ROOT again'); 87 ok(!$tree2->isLeaf(), '... now tree2 is not a leaf again'); 88 ok(!defined($tree2->getParent()), '... now tree2s parent is no longer defined'); 89 cmp_ok($tree2->getChildCount(), '==', 1, '... now tree2 has one child'); 90 memory_cycle_exists($tree3, '... calling DESTORY on tree1 did not break the connection betwee tree2 and tree3'); 91 ok(!$tree3->isRoot(), '... now tree3 is not a ROOT'); 92 ok($tree3->isLeaf(), '... now tree3 is still a leaf'); 93 ok(defined($tree3->getParent()), '... now tree3s parent is still defined'); 94 is($tree3->getParent(), $tree2, '... now tree3s parent is still tree2'); 95} 96 97#diag "child connections are strong"; 98{ 99 my $tree1 = Tree::Simple->new("1"); 100 my $tree2_UID; 101 102 { 103 my $tree2 = Tree::Simple->new("2"); 104 $tree1->addChild($tree2); 105 $tree2_UID = $tree2->getUID(); 106 107 memory_cycle_exists($tree1, '... tree1 is connected to tree2'); 108 memory_cycle_exists($tree2, '... tree2 is connected to tree1'); 109 110 $tree2->DESTROY(); # this doesn't make sense to do 111 } 112 113 memory_cycle_exists($tree1, '... tree2 is still connected to tree1 because child connections are strong'); 114 is($tree1->getChild(0)->getUID(), $tree2_UID, '... tree2 is still connected to tree1'); 115 is($tree1->getChild(0)->getParent(), $tree1, '... tree2s parent is tree1'); 116 cmp_ok($tree1->getChildCount(), '==', 1, '... tree1 has a child count of 1'); 117} 118 119#diag "expand upon this issue"; 120{ 121 my $tree1 = Tree::Simple->new("1"); 122 my $tree2_UID; 123 my $tree3 = Tree::Simple->new("3"); 124 125 { 126 my $tree2 = Tree::Simple->new("2"); 127 $tree1->addChild($tree2); 128 $tree2_UID = $tree2->getUID(); 129 $tree2->addChild($tree3); 130 131 memory_cycle_exists($tree1, '... tree1 is connected to tree2'); 132 memory_cycle_exists($tree2, '... tree2 is connected to tree1'); 133 memory_cycle_exists($tree3, '... tree3 is connected to tree2'); 134 135 $tree2->DESTROY(); # this doesn't make sense to do 136 } 137 138 memory_cycle_exists($tree1, '... tree2 is still connected to tree1 because child connections are strong'); 139 is($tree1->getChild(0)->getUID(), $tree2_UID, '... tree2 is still connected to tree1'); 140 is($tree1->getChild(0)->getParent(), $tree1, '... tree2s parent is tree1'); 141 cmp_ok($tree1->getChildCount(), '==', 1, '... tree1 has a child count of 1'); 142 cmp_ok($tree1->getChild(0)->getChildCount(), '==', 1, '... tree2 is still connected to tree3'); 143 is($tree1->getChild(0)->getChild(0), $tree3, '... tree2 is still connected to tree3'); 144} 145