Index: branches/eam_branches/ipp-20191011/Nebulous-Server/t/05_server_replicate_object.t
===================================================================
--- branches/eam_branches/ipp-20191011/Nebulous-Server/t/05_server_replicate_object.t	(revision 41017)
+++ branches/eam_branches/ipp-20191011/Nebulous-Server/t/05_server_replicate_object.t	(revision 41018)
@@ -8,5 +8,5 @@
 use warnings FATAL => qw( all );
 
-use Test::More tests => 25;
+use Test::More tests => 43;
 
 use lib qw( ./t ./lib );
@@ -28,5 +28,4 @@
 
 Test::Nebulous->setup;
-
 {
     # key
@@ -45,5 +44,4 @@
 
 Test::Nebulous->setup;
-
 {
     # key, $volume
@@ -62,5 +60,4 @@
 
 Test::Nebulous->setup;
-
 {
     # key, $volume is undef
@@ -79,5 +76,4 @@
 
 Test::Nebulous->setup;
-
 {
     # key, $volume
@@ -147,4 +143,166 @@
 }
 
+# hard_volume tests:
+
+# replication with hard_volume:
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object: hard_volume as node target
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "~node02");
+
+    my $locations = $neb->find_instances("foo");
+    my $Nloc = @$locations;
+
+    is($Nloc, 2, "found 2 instances");
+    
+    my $loc1 = $locations->[0];
+    my $loc2 = $locations->[1];
+
+    like($loc1, qr/$nodedirs[0]/, "instance matches expected node");
+    like($loc2, qr/$nodedirs[1]/, "instance matches expected node");
+}
+
+# replication to unknown volume: should succeed
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object, does this logic make sense?
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "dummy");
+
+    my $locations = $neb->find_instances("foo");
+    my $Nloc = @$locations;
+
+    is($Nloc, 2, "found 2 instances");
+    
+    my $loc1 = $locations->[0];
+    my $loc2 = $locations->[1];
+
+    like($loc1, qr/$nodedirs[0]/, "instance matches expected node");
+    uri_scheme_ok($loc2, 'file');
+}
+
+# replication to unknown volume with hard_volume: should fail
+Test::Nebulous->setup;
+eval {
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object, does this logic make sense?
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "~dummy");
+
+    my $locations = $neb->find_instances("foo");
+};
+like($@, qr/is not a valid volume name/, "replicate to unknown node with hard_volume should fail");
+
+# replication to unavailable volume: should succeed
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object, does this logic make sense?
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "node04");
+
+    my $locations = $neb->find_instances("foo");
+    my $Nloc = @$locations;
+
+    is($Nloc, 2, "found 2 instances");
+    
+    my $loc1 = $locations->[0];
+    my $loc2 = $locations->[1];
+
+    like($loc1, qr/$nodedirs[0]/, "instance matches expected node");
+    uri_scheme_ok($loc2, 'file');
+}
+
+# replication to unavailable volume with hard_volume: should fail
+Test::Nebulous->setup;
+eval {
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object, does this logic make sense?
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo", "~node04");
+
+    my $locations = $neb->find_instances("foo");
+};
+like($@, qr/is not available/, "replicate to unknown node with hard_volume should fail");
+
+### END hard_volume tests
+
+### location-aware tests (do we respect the cab_id / vol_id exclusions?)
+
+# here are the volume definitions (Test/Nebulous.pm):
+# name   : vol_id : cab_id : site_id : xattr
+# node01 :      1 :      1 :       1 :     0
+# node02 :      2 :      2 :       1 :     0
+# node03 :      3 :      3 :       2 :     0
+# node04 :      4 :      1 :       1 :     0
+# node05 :      5 :      1 :       1 :     0
+# node06 :      6 :      1 :       1 :     0
+# node07 :      7 :      1 :       1 :     0
+# node08 :      8 :      4 :       2 :     0
+
+# replication without volume 
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object: hard_volume as node target
+    my $uri1 = $neb->create_object("foo", "~node01");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $locations = $neb->find_instances("foo");
+    my $Nloc = @$locations;
+
+    is($Nloc, 2, "found 2 instances");
+    
+    my $loc1 = $locations->[0];
+    my $loc2 = $locations->[1];
+
+    # if the volume is not explicitly specified, then the first copy
+    # should go to a different volume, cabinet, and site
+    # if first is one node01, replication should go to node03 or node08
+    # since those both have different site_id values
+    like($loc1, qr/$nodedirs[0]/, "instance matches expected node");
+
+    my $isnode03 = $loc2 =~ m/$nodedirs[2]/;
+    my $isnode08 = $loc2 =~ m/$nodedirs[7]/;
+    ok($isnode03 || $isnode08, "instance matches expected node");
+}
+
+# replication without volume
+Test::Nebulous->setup;
+{
+    my @nodedirs = Test::Nebulous->get_node_dirs();
+
+    # checking on replicate_object, does this logic make sense?
+    my $uri1 = $neb->create_object("foo", "~node03");
+    my $uri2 = $neb->replicate_object("foo");
+
+    my $locations = $neb->find_instances("foo");
+    my $Nloc = @$locations;
+
+    is($Nloc, 2, "found 2 instances");
+    
+    my $loc1 = $locations->[0];
+    my $loc2 = $locations->[1];
+
+    # if the volume is not explicitly specified, then the first copy
+    # should go to a different volume, cabinet, and site
+    # if first is one node03, replication should go to node01 or node02
+    # since those both have different site_id values
+    like($loc1, qr/$nodedirs[2]/, "instance matches expected node");
+
+    my $isnode01 = $loc2 =~ m/$nodedirs[0]/;
+    my $isnode02 = $loc2 =~ m/$nodedirs[1]/;
+    ok($isnode01 || $isnode02, "instance matches expected node");
+}
+
 Test::Nebulous->setup;
 
