Graph-Layout-Aesthetic
view release on metacpan or search on metacpan
t/02_Aesthetic.t view on Meta::CPAN
like($@, qr!Nr_dimensions must not be negative at!, "Positive dimensionality");
my $aglo = Graph::Layout::Aesthetic->new($topo3);
isa_ok($aglo, "Graph::Layout::Aesthetic", "Created into the right class");
is($aglo->nr_dimensions, 2, "Defaults to two dimensions");
nearly($aglo->temperature, 1e2, "Default temperature is 1e2");
nearly($aglo->end_temperature, 1e-3, "Default end_temperature is 1e-3");
is($aglo->iterations, 1e3, "Default temperature is 1e3");
is($aglo->topology, $topo3, "Topology is available");
$topo3 = undef;
is($topo_destroys, 0, "aglo keeps topology alive");
$force_destroys = 0;
my $force = Graph::Layout::Aesthetic::Force::NodeRepulsion->new;
is($force_destroys, 0, "The force is alive");
$aglo->_add_force($force);
is($force_destroys, 0, "The force is alive");
$force = undef;
is($force_destroys, 0, "The force is alive");
$destroys = 0;
$aglo = undef;
is($destroys, 1, "Cleanup on last reference");
is($topo_destroys, 1, "Toplogy Cleanup on last reference");
is($force_destroys, 1, "The force is gone");
# Recreate topology
$topo_destroys = 0;
$topo3 = Graph::Layout::Aesthetic::Topology->new_vertices(3);
$topo3->add_edge(0, 1);
t/02_Aesthetic.t view on Meta::CPAN
# Play with forces
$aglo = Graph::Layout::Aesthetic->new($topo3, 3);
is($aglo->nr_dimensions, 3, "New listens to nr_dimensions argument");
$aglo = Graph::Layout::Aesthetic->new($topo3, undef);
is($aglo->nr_dimensions, 2, "Undef means two dimensions");
$force_destroys = 0;
$force = Graph::Layout::Aesthetic::Force::NodeRepulsion->new;
$aglo->_add_force($force);
$force = undef;
is($force_destroys, 0, "The force is alive");
$aglo->clear_forces;
is($force_destroys, 1, "The force is dead");
$force_destroys = 0;
my $force1 = Graph::Layout::Aesthetic::Force::NodeRepulsion->new;
$aglo->_add_force($force1);
$force1 = undef;
my $force2 = Graph::Layout::Aesthetic::Force::MinEdgeLength->new;
$aglo->_add_force($force2, 2);
$force2 = undef;
is($force_destroys, 0, "The force is alive");
my @forces = $aglo->forces;
is(@forces, 2, "Two forces");
isa_ok($forces[0][0], "Graph::Layout::Aesthetic::Force::MinEdgeLength",
"Right force type");
is(@{$forces[0]}, 2, "Two element force members");
is($forces[0][1], 2, "Right weight");
isa_ok($forces[1][0], "Graph::Layout::Aesthetic::Force::NodeRepulsion",
"Right force type");
is($forces[1][1], 1, "Right default weight");
KillRef->test($forces[0]);
@forces = ();
is($force_destroys, 0, "The force is alive");
my $forces = $aglo->forces;
is(@$forces, 2, "Two forces");
isa_ok($forces->[0][0], "Graph::Layout::Aesthetic::Force::MinEdgeLength",
"Right force type");
is(@{$forces->[0]}, 2, "Two element force members");
is($forces->[0][1], 2, "Right weight");
isa_ok($forces->[1][0], "Graph::Layout::Aesthetic::Force::NodeRepulsion",
"Right force type");
is($forces->[1][1], 1, "Right default weight");
KillRef->test($forces->[0]);
KillRef->test($forces);
is($force_destroys, 0, "The force is alive");
$aglo = undef;
is($force_destroys, 2, "The force is dead");
# Check cleanup on the list form of forces
$aglo = Graph::Layout::Aesthetic->new($topo3, 3);
$force_destroys = 0;
$force1 = Graph::Layout::Aesthetic::Force::NodeRepulsion->new;
$aglo->_add_force($force1);
$force1 = undef;
$force2 = Graph::Layout::Aesthetic::Force::MinEdgeLength->new;
$aglo->_add_force($force2, 2);
$force2 = undef;
is($force_destroys, 0, "The force is alive");
@forces = $aglo->forces;
$destroys = 0;
$aglo = undef;
is($destroys, 1, "Cleanup on last reference");
is($force_destroys, 0, "The force is alive");
@forces = 0;
is($force_destroys, 2, "The force is alive");
# Check cleanup on the scalar form of forces
$aglo = Graph::Layout::Aesthetic->new($topo3, 3);
$force_destroys = 0;
$force1 = Graph::Layout::Aesthetic::Force::NodeRepulsion->new;
$aglo->_add_force($force1);
$force1 = undef;
$force2 = Graph::Layout::Aesthetic::Force::MinEdgeLength->new;
$aglo->_add_force($force2, 2);
$force2 = undef;
is($force_destroys, 0, "The force is alive");
$forces = $aglo->forces;
$destroys = 0;
$aglo = undef;
is($destroys, 1, "Cleanup on last reference");
is($force_destroys, 0, "The force is alive");
$forces = undef;
is($force_destroys, 2, "The force is alive");
$force_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo3, 3);
eval { $aglo->_add_force(undef) };
like($@, qr!force is undefined at !i, "Proper error message");
eval { $aglo->add_force };
like($@, qr!No force name at !, "Proper error message");
$aglo->add_force("NodeRepulsion");
$aglo->add_force(min_edge_length => 5);
@forces = $aglo->forces;
isa_ok($forces[0][0], "Graph::Layout::Aesthetic::Force::MinEdgeLength",
"Right force type");
is($forces[0][1], 5, "Right weight");
isa_ok($forces[1][0], "Graph::Layout::Aesthetic::Force::NodeRepulsion",
"Right force type");
is($forces[1][1], 1, "Right default weight");
$destroys = 0;
$aglo = undef;
is($destroys, 1, "Cleanup on last reference");
is($force_destroys, 0, "Manager keeps forces alive");
# Getting and setting coordinates
$aglo = Graph::Layout::Aesthetic->new($topo3);
eval { $aglo->coordinates };
like($@, qr!Usage: Graph::Layout::Aesthetic::coordinates\(state, vertex, \.\.\.\) at !,
"Right error message");
eval { $aglo->coordinates(3) };
like($@, qr!Vertex number 3 is invalid, there are only 3 in the topology at !,
"Right error message");
eval { $aglo->coordinates(0, 1) };
t/04_Force.t view on Meta::CPAN
my $topo2 = Graph::Layout::Aesthetic::Topology->new_vertices(2);
$topo2->add_edge(0, 1);
$topo2->finish;
$aglo_destroys = 0;
my $aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 0, "Force still alive");
is($canaries, 0, "No more canaries");
$force = undef;
is($destroys, 1, "Force Gone");
# Now leave force only on aglo
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
$force = undef;
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is alive");
is($canaries, 1, "One canary");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force Gone");
is($canaries, 0, "No canaries");
# Add two forces
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
$force = Graph::Layout::Aesthetic::Force::Test1->new;
$aglo->_add_force($force);
is($canaries, 2, "Two canaries");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "One force still alive");
is($canaries, 0, "No more canaries");
$force = undef;
is($destroys, 2, "All forces gone");
# Add same force twice
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
$aglo->_add_force($force);
is($canaries, 2, "Two canaries");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 0, "Force still alive");
is($canaries, 0, "No more canaries");
$force = undef;
is($destroys, 1, "Force gone");
# Same, but now drop $force first
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
$aglo->_add_force($force);
is($canaries, 2, "Two canaries");
$force = undef;
is($canaries, 2, "Two canaries");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force is gone");
is($canaries, 0, "No more canaries");
# Now drop using clear_forces
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
$aglo->_add_force($force);
is($canaries, 2, "Two canaries");
$force = undef;
is($canaries, 2, "Two canaries");
is($destroys, 0, "Force still alive");
$aglo->clear_forces;
is($aglo_destroys, 0, "Aglo is alive");
is($destroys, 1, "Force is gone");
is($canaries, 0, "No more canaries");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
# Now actually apply the force
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($canaries, 0, "No canaries");
$aglo->_add_force($force);
is($canaries, 1, "One canary");
$force = undef;
is($canaries, 1, "One canary");
is($destroys, 0, "Force still alive");
$aglo->zero;
$aglo->step(100, 0);
is_deeply(scalar $aglo->all_coordinates, [[1, 2], [3, 4]],
"Gradient gets applied properly");
is($canaries, 1, "One canary");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is still alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force is gone");
is($canaries, 0, "No more canaries");
# Check name
is(Graph::Layout::Aesthetic::Force::Test1->name, "Test1", "Default name works as class method");
$force = Graph::Layout::Aesthetic::Force::Test1->new;
is($force->name, "Test1", "Default name works for the basic case");
t/04_Force.t view on Meta::CPAN
is($force->name, "Test1::Foo", "Default name works relative to Graph::Layout::Aesthetic::Force");
$force = undef;
# Checking failure modes of gradient
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2, 3);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Gradient->new;
$aglo->_add_force($force);
$force = undef;
is($destroys, 0, "Force still alive");
$aglo->zero;
$gradient = [[1, 2, 5], [3, 4, 6]];
$aglo->step(100, 0);
is_deeply(scalar $aglo->all_coordinates, [[1, 2, 5], [3, 4, 6]],
"Gradient gets applied properly");
KillRef->test($gradient->[0]);
KillRef->test($gradient);
$gradient = 5;
eval { $aglo->step(100, 0) };
like($@, qr!^Gradient is not a reference anymore at !,
t/04_Force.t view on Meta::CPAN
"All elements must be array references");
$gradient = [1, []];
eval { $aglo->step(100, 0) };
like($@, qr!Gradient for vertex 1 is a reference to an array of size 0, expected 3 at!, "coordinate arrays of size dimension");
my @hole3 = 1..3;
delete $hole3[0];
$gradient = [1, \@hole3];
eval { $aglo->step(100, 0) };
like($@, qr!Gradient for vertex 1, coordinate 0 is unset at !,
"All elements must be filled in");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is still alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force gone");
# Check modifying gradient arguments
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::Morph->new;
$aglo->_add_force($force);
$force = undef;
$aglo->zero;
$gradient = [[1, 2], [3, 4]];
is($destroys, 0, "Force still alive");
$aglo->step(100, 0);
is($destroys, 0,
"Force is still there (needed to hold the adress of ae_cleanup_perl)");
is($aglo_destroys, 0, "Aglo is still alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force gone");
# Failure modes of call
# - No setup
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::NoSetup->new;
eval { $aglo->_add_force($force) };
is($@, "Bad setup\n", "Proper eval drop for setup");
is($destroys, 0, "Force still alive");
$force = undef;
is($destroys, 1, "Force gone");
is($aglo_destroys, 0, "Aglo is still alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force gone");
# - No cleanup
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::NoCleanup->new;
$aglo->_add_force($force, 0);
$aglo->_add_force($force, 1);
$aglo->_add_force($force, 2);
$aglo->_add_force($force, 3);
$force = undef;
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is still alive");
$bad_count = -1;
eval { $aglo->clear_forces };
is($@, "Bad cleanup 0\n", "clear_forces passes on exceptions");
my $forces = $aglo->forces;
is(@$forces, 3, "Three forces left (first one of four died");
isa_ok($forces->[0][0], "Graph::Layout::Aesthetic::Force::NoCleanup", "It's the force we added");
is($forces->[0][1], 2, "Forces were added in reverse order");
is($forces->[1][0], $forces->[0][0], "Added forces are the same");
is($forces->[1][1], 1, "Forces were added in reverse order");
is($forces->[2][0], $forces->[0][0], "Added forces are the same");
is($forces->[2][1], 0, "Forces were added in reverse order");
KillRef->test($forces->[0]);
KillRef->test($forces);
check_warnings;
is($aglo_destroys, 0, "Aglo is still alive");
$@="z1\n";
$aglo = undef;
is($@, "z1
\t(in cleanup) Bad cleanup 1
\t(in cleanup) Bad cleanup 2
\t(in cleanup) Bad cleanup 3\n", 'Errors accumulate in $@');
is(@warnings, 3, "Cleanup warning");
is($warnings[$_-1], "\t(in cleanup) Bad cleanup $_\n",
"implied cleanup done") for 1..3;
@warnings = ();
t/04_Force.t view on Meta::CPAN
is($destroys, 1, "Force gone");
is($canaries, 0, "No more canaries");
# Die in cleanup and DESTROY
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::EndDie->new;
$aglo->_add_force($force);
$force = undef;
is($destroys, 0, "Force still alive");
check_warnings;
is($aglo_destroys, 0, "Aglo is still alive");
$@="z2\n";
$aglo = undef;
is($@, "z2
\t(in cleanup) cleanup die
\t(in cleanup) DESTROY die\n", "Errors accumulate");
is(@warnings, 2, "Both dies are now a warning");
is($warnings[0], "\t(in cleanup) cleanup die\n",
"Also test \$\@ containing \\0");
is($warnings[1], "\t(in cleanup) DESTROY die\n");
@warnings = ();
t/04_Force.t view on Meta::CPAN
is($destroys, 1, "Force gone");
is($canaries, 0, "No more canaries");
# - No gradient
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::NoGradient->new;
$aglo->_add_force($force);
$force = undef;
is($destroys, 0, "Force still alive");
$aglo->zero;
eval { $aglo->step(100, 0) };
like($@, qr!^Can.t locate object method "gradient" via package "Graph::Layout::Aesthetic::Force::NoGradient" at !, "gradient failure gets passed on");
is($destroys, 0, "Force still alive");
is($aglo_destroys, 0, "Aglo is still alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force gone");
# Force suicide
$aglo_destroys = 0;
$aglo = Graph::Layout::Aesthetic->new($topo2);
$destroys = 0;
$force = Graph::Layout::Aesthetic::Force::GradientClear->new;
$aglo->_add_force($force);
$aglo->_add_force($force);
# Don't destroy $force here. There seems to be more chance of problems if
# it's kept around
is($destroys, 0, "Force still alive");
$aglo->zero;
check_warnings;
$aglo->step(100, 0);
is(@warnings, 1);
like($warnings[0], qr!^Forces were cleared during an actual forcing calculation at !, "Proper warning if you clear forces during a gradient call");
@warnings = ();
is($destroys, 0, "Force still alive");
$force = undef;
is($destroys, 1, "Force is gone");
is($aglo_destroys, 0, "Aglo is still alive");
$aglo = undef;
is($aglo_destroys, 1, "Aglo is gone");
is($destroys, 1, "Force gone");
# check register/name2force
$force = Graph::Layout::Aesthetic::Force::Test1->new;
$force->register;
eval { $force->register };
like($@, qr!A force named Test1 already exists at !, "Cannot register twice");
$force->register("baz");
( run in 1.876 second using v1.01-cache-2.11-cpan-39bf76dae61 )