Index: branches/eam_branches/ipp-20191011/Nebulous-Server/t/08_server_find_instances.t
===================================================================
--- branches/eam_branches/ipp-20191011/Nebulous-Server/t/08_server_find_instances.t	(revision 41018)
+++ branches/eam_branches/ipp-20191011/Nebulous-Server/t/08_server_find_instances.t	(revision 41019)
@@ -8,5 +8,5 @@
 use warnings FATAL => qw( all );
 
-use Test::More tests => 25;
+use Test::More tests => 44;
 
 use lib qw( ./t ./lib );
@@ -31,4 +31,9 @@
 Test::Nebulous->cleanup; # make sure the database is reset before running any tests
 
+# for (my $i = 0; $i < $Nloc; $i++) {
+#	my $loc = $locations->[$i];
+#	print "location: $loc\n";
+#}
+
 Test::Nebulous->setup;
 {
@@ -101,5 +106,5 @@
 }
 
-# object exists but instance is on a different volume
+# request from a hard_volume returns an instance which is not on the hard volume if available
 Test::Nebulous->setup;
 eval {
@@ -110,14 +115,23 @@
     uri_scheme_ok($locations->[0], 'file');
     is($uri, $locations->[0], "URIs match");
-
-    # print "uri: $uri\n";
-    # print "result: $locations->[0]\n";
-};
-# die "quick check";
-# print "answer: $_[0]\n";
-# like($@, qr/no instances on storage volume/, 'instances on a different volume');
-
-# request from a soft_volume for an instance which is on an invalid node (find_invalid = 1) 
-# XXX should return the INVALID instance (currently 2019.10.24 does not)
+};
+is($@, "", "instance on different node (as hard_volume) returned");
+
+# request from a hard_volume returns an instance which is not on the hard volume if available
+Test::Nebulous->setup;
+eval {
+    # key, volume
+    my $uri = $neb->create_object('foo', '~node01');
+    my $locations = $neb->find_instances('foo', '~node02');
+
+    uri_scheme_ok($locations->[0], 'file');
+    is($uri, $locations->[0], "URIs match");
+};
+is($@, "", "instance on different node (as hard_volume) returned");
+
+### TESTS FOR INSTANCE ON INVALID NODE
+diag ("TESTS FOR INSTANCE ON INVALID NODE");
+
+# request from a soft_volume for an instance which is on an invalid node (find_invalid = 1) [SOFT, 1]
 Test::Nebulous->setup;
 eval {
@@ -130,9 +144,7 @@
     is($uri, $locations->[0], "URIs match");
 };
-is($@, "", "instance on invalid node (as hard_volume) returned with find_invalid is set");
-#like($@, qr/database error/, "instance on invalid node (as hard_volume) not returned");
-
-# request from a soft_volume for an instance which is on an invalid node (find_invalid = 0) 
-# XXX should return the INVALID instance (currently 2019.10.24 does not)
+is($@, "", "instance on invalid node (as soft_volume) returned with find_invalid = 1");
+
+# request from a soft_volume for an instance which is on an invalid node (find_invalid = 0) [SOFT, 0]
 Test::Nebulous->setup;
 eval {
@@ -143,10 +155,42 @@
     my $locations = $neb->find_instances('foo', 'node02', 0);
 };
-#is($@, "", "instance on invalid node (as hard_volume) returned with find_invalid is set");
-like($@, qr/database error/, "instance on invalid node (as soft_volume) not returned");
-
-#### tests with a hard_volume:
-
-# request from a hard_volume for an instance which is on an invalid node (find_instance not supplied)
+like($@, qr/database error/, "instance on invalid node (as soft_volume) not returned (find_invalid = 0)");
+
+# request from a hard_volume for an instance which is on an invalid node (find_instance not supplied) [SOFT, X]
+Test::Nebulous->setup;
+eval {
+    # key, volume
+    my $uri = $neb->create_object('foo', '~node02');
+    Test::Nebulous->switch_node_state;
+
+    my $locations = $neb->find_instances('foo', 'node02');
+};
+like($@, qr/no instances available for key/, "instance on invalid node (as soft_volume) not returned (find_invalid not set)");
+
+# request from a hard_volume for an instance which is on an invalid node (find_invalid = 1) [HARD, 1]
+Test::Nebulous->setup;
+eval {
+    # key, volume
+    my $uri = $neb->create_object('foo', '~node02');
+    Test::Nebulous->switch_node_state;
+
+    my $locations = $neb->find_instances('foo', '~node02', 1);
+    uri_scheme_ok($locations->[0], 'file');
+    is($uri, $locations->[0], "URIs match");
+};
+is($@, "", "instance on invalid node (as hard_volume) returned with find_invalid = 1");
+
+# request from a hard_volume for an instance which is on an invalid node (find_invalid = 0) [HARD, 0]
+Test::Nebulous->setup;
+eval {
+    # key, volume
+    my $uri = $neb->create_object('foo', '~node02');
+    Test::Nebulous->switch_node_state;
+
+    my $locations = $neb->find_instances('foo', '~node02', 0);
+};
+like($@, qr/no instances on storage volume/, "instance on invalid node (as hard_volume) not returned (find_invalid = 0)");
+
+# request from a hard_volume for an instance which is on an invalid node [HARD, X]
 Test::Nebulous->setup;
 eval {
@@ -157,55 +201,61 @@
     my $locations = $neb->find_instances('foo', '~node02');
 };
-like($@, qr/no instances on storage volume/, "instance on invalid node (as hard_volume) not returned");
-
-# request from a hard_volume for an instance which is on an invalid node (find_invalid = 1) 
-Test::Nebulous->setup;
-eval {
-    # key, volume
-    my $uri = $neb->create_object('foo', '~node02');
-    Test::Nebulous->switch_node_state;
-
-    my $locations = $neb->find_instances('foo', '~node02', 1);
-    uri_scheme_ok($locations->[0], 'file');
-    is($uri, $locations->[0], "URIs match");
-};
-is($@, "", "instance on invalid node (as hard_volume) returned with find_invalid is set");
-#like($@, qr/database error/, "instance on invalid node (as hard_volume) not returned");
-
-# request from a hard_volume for an instance which is on an invalid node (find_invalid = 0)
-Test::Nebulous->setup;
-eval {
-    # key, volume
-    my $uri = $neb->create_object('foo', '~node02');
-    Test::Nebulous->switch_node_state;
-
-    my $locations = $neb->find_instances('foo', '~node02', 0);
-};
-like($@, qr/no instances on storage volume/, "instance on invalid node (as hard_volume) not returned");
-
-# request from a hard_volume for an instance which is on an invalid node 
-Test::Nebulous->setup;
-eval {
-    # key, volume
-    my $uri = $neb->create_object('foo', '~node02');
-    Test::Nebulous->switch_node_state;
-
-    my $locations = $neb->find_instances('foo', '~node02', 1);
-
-    uri_scheme_ok($locations->[0], 'file');
-    is($uri, $locations->[0], "URIs match");
-};
-
-# request from a hard_volume returns an instance which is not on the hard volume if available
-Test::Nebulous->setup;
-eval {
-    # key, volume
-    my $uri = $neb->create_object('foo', '~node01');
-
-    my $locations = $neb->find_instances('foo', '~node02');
-
-    uri_scheme_ok($locations->[0], 'file');
-    is($uri, $locations->[0], "URIs match");
-};
+like($@, qr/no instances on storage volume/, "instance on invalid node (as hard_volume) not returned (find_invalid not set)");
+
+#### TESTING the instance proximity analysis
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # place 4 instances on specific nodes (hard targets works):
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "~node02");
+    my $uri3 = $neb->replicate_object("foo", "~node03");
+    my $uri4 = $neb->replicate_object("foo", "~node08");
+
+    my $locations = $neb->find_instances("foo", "node01");
+    my $Nloc = @$locations;
+
+    is($Nloc, 4, "found 4 instances");
+    
+    my $loc1 = $locations->[0];
+    my $loc2 = $locations->[1];
+    my $loc3 = $locations->[2];
+    my $loc4 = $locations->[3];
+
+    # choosing instance relative to node01 yields:
+    like($loc1, qr/$nodedirs[0]/, "node01 is closest to node01");    
+    like($loc2, qr/$nodedirs[1]/, "node02 is 2nd closest to node01");
+    like($loc3, qr/$nodedirs[2]/, "node03 is 3rd closest to node01");
+    like($loc4, qr/$nodedirs[7]/, "node08 is 4th closest to node01");
+}
+
+#### TESTING the instance proximity analysis
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # place 4 instances on specific nodes (hard targets works):
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "~node02");
+    my $uri3 = $neb->replicate_object("foo", "~node03");
+    my $uri4 = $neb->replicate_object("foo", "~node08");
+
+    my $locations = $neb->find_instances("foo", "node03");
+    my $Nloc = @$locations;
+
+    is($Nloc, 4, "found 4 instances");
+    
+    my $loc1 = $locations->[0]; # 
+    my $loc2 = $locations->[1]; # 
+    my $loc3 = $locations->[2]; # 
+    my $loc4 = $locations->[3]; # 
+
+    # choosing instance relative to node01 yields:
+    like($loc1, qr/$nodedirs[2]/, "node03 is closest to node03");
+    like($loc2, qr/$nodedirs[7]/, "node08 is 2nd closest to node03");
+    like($loc3, qr/$nodedirs[1]/, "node02 is 3rd closest to node03");
+    like($loc4, qr/$nodedirs[0]/, "node08 is 4th closest to node03");
+}
 
 ########
