diff --git a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
index b8190999814713677945a5179c68d9e28d8cbb86..c412581c9c91bdd73b76adc54970693812fff9ca 100644
--- a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
+++ b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
@@ -460,8 +460,8 @@ public class NodeDAO {
         String sql = "SELECT COUNT(c.node_id) = 0 "
                 + "FROM node n "
                 + "JOIN node c ON c.path <@ n.path "
-                + "WHERE n.node_id = ? "
-                + "(NOT COALESCE(c.is_public, FALSE) "
+                + "WHERE n.node_id = ? AND "
+                + "NOT COALESCE(c.is_public, FALSE) "
                 + "AND (SELECT COUNT(*) FROM (SELECT UNNEST(?) INTERSECT SELECT UNNEST(c.group_read)) AS allowed_groups) = 0 "
                 + "AND c.creator_id <> ?";
 
diff --git a/src/test/java/it/inaf/oats/vospace/NodeBranchServiceTest.java b/src/test/java/it/inaf/oats/vospace/NodeBranchServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..69d342c85e97a9b94972f4955e9262b01d2f13bf
--- /dev/null
+++ b/src/test/java/it/inaf/oats/vospace/NodeBranchServiceTest.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of vospace-rest
+ * Copyright (C) 2021 Istituto Nazionale di Astrofisica
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.inaf.oats.vospace;
+
+import it.inaf.ia2.aa.data.User;
+import it.inaf.oats.vospace.exception.NodeBusyException;
+import it.inaf.oats.vospace.exception.NodeNotFoundException;
+import it.inaf.oats.vospace.exception.PermissionDeniedException;
+import it.inaf.oats.vospace.persistence.DataSourceConfigSingleton;
+import it.inaf.oats.vospace.persistence.NodeDAO;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import net.ivoa.xml.vospace.v2.Transfer;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@AutoConfigureMockMvc
+@ContextConfiguration(classes = {DataSourceConfigSingleton.class})
+@TestPropertySource(locations = "classpath:test.properties", properties = {"vospace-authority=example.com!vospace", "file-service-url=http://file-service"})
+@TestMethodOrder(OrderAnnotation.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class NodeBranchServiceTest {
+
+    @Value("${vospace-authority}")
+    private String authority;
+
+    @Autowired
+    private MoveService moveService;
+
+    @Autowired
+    private NodeDAO nodeDao;
+
+    @Test
+    @Order(1)
+    public void moveRootTest() {
+
+        assertThrows(IllegalArgumentException.class, () -> {
+            moveService.processMoveJob(getTransfer("/", "/pippo"), getAnonymousUser());
+        }
+        );
+
+        assertThrows(IllegalArgumentException.class, () -> {
+            moveService.processMoveJob(getTransfer("/pippo", "/"), getAnonymousUser());
+        }
+        );
+
+    }
+
+    private Transfer getTransfer(String vosTarget, String vosDestination) {
+        Transfer transfer = new Transfer();
+        transfer.setTarget(Arrays.asList("vos://" + this.authority + vosTarget));
+        transfer.setDirection("vos://" + this.authority + vosDestination);
+        return transfer;
+    }
+
+    private User getAnonymousUser() {
+        return new User().setUserId("anonymous");
+    }
+}
diff --git a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
index 1f0be586a6098ab148cee0ea3f3d367ac6ea413f..eae2766d31afcb6b31b11e1ed07e6f92a113f1bc 100644
--- a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
+++ b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
@@ -49,7 +49,7 @@ public class NodeDAOTest {
         ReflectionTestUtils.setField(dao, "authority", AUTHORITY);
     }
 
-    //@Test
+    @Test
     public void testCreateNode() {
         DataNode dataNode = new DataNode();
 
@@ -66,7 +66,7 @@ public class NodeDAOTest {
         assertEquals(retrievedNode.getProvides().get(0).getUri(), dataNode.getProvides().get(0).getUri());
     }
 
-    //@Test
+    @Test
     public void testListNode() {
         ContainerNode root = (ContainerNode) dao.listNode("/").get();
         assertEquals(4, root.getNodes().size());
@@ -81,7 +81,7 @@ public class NodeDAOTest {
         assertEquals(bTime, NodeProperties.getNodePropertyByURI(root.getNodes().get(0), NodeProperties.DATE_URI));
     }
 
-    //@Test
+    @Test
     public void testListNodeChildren() {
         assertTrue(dao.listNodeChildren("/test4").isEmpty());
         List<String> children = dao.listNodeChildren("/test2");
@@ -90,7 +90,7 @@ public class NodeDAOTest {
         assertTrue(children.containsAll(List.of("f4", "f5")));
     }
 
-    //@Test
+    @Test
     public void testGetNodeId() {
         Optional<Long> id1 = dao.getNodeId("/test1");
         assertTrue(id1.isPresent());
@@ -104,7 +104,7 @@ public class NodeDAOTest {
         assertTrue(id3.isEmpty());
     }
 
-    //@Test
+    @Test
     public void testGetShortNodeDescriptor() {
         String userName = "user3";
         List<String> userGroups = List.of();
@@ -176,7 +176,7 @@ public class NodeDAOTest {
         assertFalse(snd1.isPermissionDenied());
     }
 
-    //@Test
+    @Test
     public void testIsBranchBusy() {
         Optional<Long> optId = dao.getNodeId("/test3/m1");
         assertTrue(optId.isPresent());
@@ -190,7 +190,7 @@ public class NodeDAOTest {
 
     }
 
-    //@Test
+    @Test
     public void testIsBranchWritable() {
 
         List<String> userGroups = List.of("group1");
@@ -210,8 +210,52 @@ public class NodeDAOTest {
         assertTrue(optId.isPresent());
         assertFalse(dao.isBranchWritable(optId.get(), "user1", List.of("group99")));
     }
+    
+    @Test
+    public void testIsBranchReadable() {
+
+        List<String> userGroups = List.of("group1");
+        Optional<Long> optId = dao.getNodeId("/test3/m1");
+        assertTrue(optId.isPresent());
+        assertTrue(dao.isBranchReadable(optId.get(), "user3", userGroups));
 
-    //@Test
+        optId = dao.getNodeId("/test3");
+        assertTrue(optId.isPresent());
+        assertFalse(dao.isBranchReadable(optId.get(), "user2", userGroups));
+
+        optId = dao.getNodeId("/test3/group1");
+        assertTrue(optId.isPresent());
+        assertTrue(dao.isBranchReadable(optId.get(), "user2", userGroups));
+
+        optId = dao.getNodeId("/test3/group1");
+        assertTrue(optId.isPresent());
+        assertFalse(dao.isBranchWritable(optId.get(), "user1", List.of("group99")));
+    }
+    
+    @Test
+    public void testSetJobId(){
+        Optional<Long> optId = dao.getNodeId("/test3/m1");
+        assertTrue(optId.isPresent());
+        
+        assertFalse(dao.isBranchBusy(optId.get()));
+        
+        dao.setBranchJobId(optId.get(), "pippo1");
+        
+        assertTrue(dao.isBranchBusy(optId.get()));
+        
+        Optional<Long> childId = dao.getNodeId("/test3/m1/m2");
+        assertTrue(childId.isPresent());
+        
+        assertTrue(dao.isBranchBusy(childId.get()));
+        
+        dao.setBranchJobId(optId.get(), null);
+        
+        assertFalse(dao.isBranchBusy(optId.get()));
+        assertFalse(dao.isBranchBusy((childId.get())));    
+               
+    }    
+
+    @Test
     public void testMoveNodeBranch() {
         // Let's move /test3/m1 to /test3/group1
         Optional<Long> optSourceId = dao.getNodeId("/test3/m1");
@@ -272,7 +316,7 @@ public class NodeDAOTest {
 
     }
 
-    //@Test
+    @Test
     public void testRenameNode() {
         String oldPath = "/test1/f1";
         String newPath = "/test1/f_pippo";
@@ -304,7 +348,7 @@ public class NodeDAOTest {
         assertEquals("f1", dao.getNodeOsName("/test1/f_pippo_second_rename"));
     }
 
-    //@Test
+    @Test
     public void testCountNodeWithPath() {
         assertEquals(1, dao.countNodesWithPath("/"));
         assertEquals(1, dao.countNodesWithPath("/test1"), "Test db has been changed");
@@ -320,7 +364,7 @@ public class NodeDAOTest {
         assertEquals(0, dao.countNodesWithPath("/pippooo"), "Test db has been changed");
     }
 
-    //@Test
+    @Test
     public void testDeleteNode() {
 
         assertEquals(1, dao.countNodesWithPath("/test1/f1/f2_renamed/f3"), "Test db has been changed");
@@ -333,7 +377,7 @@ public class NodeDAOTest {
 
     }
 
-    //@Test
+    @Test
     public void testSetNodeLocation() {
 
         DataNode dataNode = new DataNode();
@@ -343,7 +387,7 @@ public class NodeDAOTest {
         dao.setNodeLocation("/mydata2", 1, "mydata2");
     }
 
-    //@Test
+    @Test
     public void testSetNodeLocationFailure() {
         boolean exception = false;
         try {
@@ -354,7 +398,7 @@ public class NodeDAOTest {
         assertTrue(exception);
     }
 
-    //@Test
+    @Test
     public void testSetNode() {
 
         Property publicReadProperty = getProperty(NodeProperties.PUBLIC_READ_URI, String.valueOf(false));
@@ -377,7 +421,7 @@ public class NodeDAOTest {
         assertEquals("true", NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI));
     }
 
-    //@Test
+    @Test
     public void testSetNodeRecursiveGroup() {
 
         Property parentGroupRead = getProperty(NodeProperties.GROUP_READ_URI, "group1 group2");
@@ -421,7 +465,7 @@ public class NodeDAOTest {
         checkGroups(NodeProperties.getNodePropertyAsListByURI(child2, NodeProperties.GROUP_WRITE_URI), "group6");
     }
 
-    //@Test
+    @Test
     public void testGetNodeOsName() {
         assertEquals("f2", dao.getNodeOsName("/test1/f1/f2_renamed"));
         assertEquals("f4", dao.getNodeOsName("/test2/f4"));
diff --git a/src/test/resources/test-data.sql b/src/test/resources/test-data.sql
index 3872174c43e0b3270918bd90c8a849657ed0e9da..4b0af3bd45cb04a2b2f1d4739741f3bae4cec594 100644
--- a/src/test/resources/test-data.sql
+++ b/src/test/resources/test-data.sql
@@ -33,7 +33,7 @@ INSERT INTO node (parent_path, parent_relative_path, name, sticky, type, creator
 INSERT INTO node (parent_path, parent_relative_path, name, job_id, type, creator_id, is_public, location_id) VALUES ('9', '', 'mbusy', 'job1234', 'container', 'user3', false, 3);      -- /test3/mbusy
 INSERT INTO node (parent_path, parent_relative_path, name, async_trans, type, creator_id, is_public, location_id) VALUES ('9', '', 'masynctrans', true, 'container', 'user3', false, 3);      -- /test3/masynctrans
 INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, is_public, location_id) VALUES ('9', '', 'asyncloc', 'container', 'user3', false, 1);      -- /test3/asyncloc
-INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, group_write, is_public, location_id) VALUES ('9', '', 'group1', 'container', 'user3','{"group1"}', false, 3);      -- /test3/group1
+INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, group_write, group_read, is_public, location_id) VALUES ('9', '', 'group1', 'container', 'user3', '{"group1"}', '{"group1"}', false, 3);      -- /test3/group1
 
 
 DELETE FROM job;