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 => 43; my $CLASS = 'Tree'; use_ok( $CLASS, 'use_weak_refs' ) or Test::More->builder->BAILOUT( "Cannot load $CLASS" ); { #diag "parental connections are weak"; my $tree2 = $CLASS->new(); ok($tree2->is_root(), '... tree2 is a ROOT'); { my $tree1 = $CLASS->new("1"); $tree1->add_child($tree2); ok(!$tree2->is_root(), '... now tree2 is not a ROOT'); weakened_memory_cycle_exists($tree2, '... there is a weakened cycle in tree2'); } weakened_memory_cycle_ok($tree2, '... tree2 is no longer connected to tree1'); ok($tree2->is_root(), '... now tree2 is a ROOT again'); ok(!$tree2->parent(), '... now tree2s parent is no longer defined'); } { #diag "expand the problem to check child connections"; my $tree2 = $CLASS->new("2"); ok($tree2->is_root(), '... tree2 is a ROOT'); ok($tree2->is_leaf(), '... tree2 is a Leaf'); my $tree3 = $CLASS->new("3"); ok($tree3->is_root(), '... tree3 is a ROOT'); ok($tree3->is_leaf(), '... tree3 is a Leaf'); { my $tree1 = $CLASS->new("1"); $tree1->add_child($tree2); ok(!$tree2->is_root(), '... now tree2 is not a ROOT'); $tree2->add_child($tree3); ok(!$tree2->is_leaf(), '... now tree2 is not a Leaf'); ok(!$tree3->is_root(), '... tree3 is no longer a ROOT'); ok($tree3->is_leaf(), '... but tree3 is still a Leaf'); weakened_memory_cycle_exists($tree1, '... there is a cycle in tree1'); weakened_memory_cycle_exists($tree2, '... there is a cycle in tree2'); weakened_memory_cycle_exists($tree3, '... there is a cycle in tree3'); } weakened_memory_cycle_exists($tree2, '... calling DESTORY on tree1 broke the connection with tree2'); ok($tree2->is_root(), '... now tree2 is a ROOT again'); ok(!$tree2->is_leaf(), '... now tree2 is a not a leaf again'); ok(!$tree2->parent(), '... now tree2s parent is no longer defined'); cmp_ok($tree2->children(), '==', 1, '... now tree2 has one child'); weakened_memory_cycle_exists($tree3, '... calling DESTORY on tree1 did not break the connection betwee tree2 and tree3'); ok(!$tree3->is_root(), '... now tree3 is not a ROOT'); ok($tree3->is_leaf(), '... now tree3 is still a leaf'); ok(defined($tree3->parent()), '... now tree3s parent is still defined'); is($tree3->parent(), $tree2, '... now tree3s parent is still tree2'); } { #diag "child connections are strong"; my $tree1 = $CLASS->new("1"); my $tree2_string; { my $tree2 = $CLASS->new("2"); $tree1->add_child($tree2); $tree2_string = $tree2 . ""; weakened_memory_cycle_exists($tree1, '... tree1 is connected to tree2'); weakened_memory_cycle_exists($tree2, '... tree2 is connected to tree1'); } weakened_memory_cycle_exists($tree1, '... tree2 is still connected to tree1 because child connections are strong'); is($tree1->children(0) . "", $tree2_string, '... tree2 is still connected to tree1'); is($tree1->children(0)->parent(), $tree1, '... tree2s parent is tree1'); cmp_ok($tree1->children(), '==', 1, '... tree1 has a child count of 1'); } { #diag "expand upon this issue"; my $tree1 = $CLASS->new("1"); my $tree2_string; my $tree3 = $CLASS->new("3"); { my $tree2 = $CLASS->new("2"); $tree1->add_child($tree2); $tree2_string = $tree2 . ""; $tree2->add_child($tree3); weakened_memory_cycle_exists($tree1, '... tree1 is connected to tree2'); weakened_memory_cycle_exists($tree2, '... tree2 is connected to tree1'); weakened_memory_cycle_exists($tree3, '... tree3 is connected to tree2'); } weakened_memory_cycle_exists($tree1, '... tree2 is still connected to tree1 because child connections are strong'); is($tree1->children(0) . "", $tree2_string, '... tree2 is still connected to tree1'); is($tree1->children(0)->parent(), $tree1, '... tree2s parent is tree1'); cmp_ok($tree1->children(), '==', 1, '... tree1 has a child count of 1'); cmp_ok($tree1->children(0)->children(), '==', 1, '... tree2 is still connected to tree3'); is($tree1->children(0)->children(0), $tree3, '... tree2 is still connected to tree3'); }