Skip to content
Snippets Groups Projects
Commit 2df69c87 authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

refactored delete service tests

parent c7ae8d2e
No related branches found
No related tags found
1 merge request!1Immutable
......@@ -6,14 +6,7 @@
package it.inaf.oats.vospace;
import it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.exception.LinkFoundException;
import it.inaf.oats.vospace.exception.NodeNotFoundException;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.vospace.v2.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -23,7 +16,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DeleteNodeController extends BaseNodeController {
......@@ -39,20 +31,10 @@ public class DeleteNodeController extends BaseNodeController {
String path = getPath();
LOG.debug("deleteNode called for path {}", path);
try {
deleteNodeService.doPreliminaryChecks(path);
deleteNodeService.deleteNode(path, principal);
return ResponseEntity.ok("Node deleted");
} catch(Exception ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
}
......@@ -14,8 +14,6 @@ import java.util.List;
import net.ivoa.xml.vospace.v2.Node;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
......@@ -63,7 +61,7 @@ public class DeleteNodeService {
}
public void doPreliminaryChecks(String path) throws Exception {
public void doPreliminaryChecks(String path) {
// Check if the node is present,
// if the node does not exist the service SHALL throw a HTTP 404 status code
// including a NodeNotFound fault in the entity-body
......@@ -76,13 +74,13 @@ public class DeleteNodeService {
// For example, given the URI path /a/b/c, the service must throw a HTTP 400
// status code including a LinkFound fault in the entity-body if either /a
// or /a/b are LinkNodes.
List<String> pathComponents = NodeUtils.subPathComponents(path);
if (pathComponents.isEmpty()) {
if (path.equals("/")) {
// Manage root node
throw PermissionDeniedException.forPath("/");
} else {
List<String> pathComponents = NodeUtils.subPathComponents(path);
// Manage all precursors in full path
for (int i = 0; i < pathComponents.size(); i++) {
......
/*
* 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.oats.vospace.datamodel.NodeProperties;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.util.List;
import java.util.Optional;
import net.ivoa.xml.vospace.v2.ContainerNode;
import net.ivoa.xml.vospace.v2.DataNode;
import net.ivoa.xml.vospace.v2.LinkNode;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Property;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@ContextConfiguration(classes = {TokenFilterConfig.class})
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
@AutoConfigureMockMvc
public class DeleteNodeControllerTest {
private static final String URI_PREFIX = "vos://example.com!vospace";
@MockBean
private NodeDAO nodeDao;
@Autowired
private MockMvc mockMvc;
@Test
public void testDeleteRootNode() throws Exception {
when(nodeDao.listNode(eq("/"))).thenReturn(getRootNode());
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isForbidden());
}
@Test
public void testDeleteFirstLevelNode() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode()));
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes/mynode")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isOk());
}
@Test
public void testDeleteMoreLevelNode() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode")));
when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode")));
when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt")));
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes/mynode/middlenode/myfile.txt")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isOk());
}
@Test
public void testLeafNodeNotFound() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode")));
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes/mynode/notexisting")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isNotFound());
}
@Test
public void testMiddleLevelNodeNotFound() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode")));
when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt")));
mockMvc.perform(MockMvcRequestBuilders
.delete("/mynode/middlenode/myfile.txt")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isNotFound());
}
@Test
public void testLinkNodeLeafDelete() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableLinkNode("/mynode")));
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes/mynode")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isOk());
}
@Test
public void testMiddleLevelLinkNodeDelete() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode")));
when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableLinkNode("/mynode/middlenode")));
when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt")));
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes/mynode/middlenode/myfile.txt")
.header("Authorization", "Bearer user2_token"))
.andExpect(status().isBadRequest());
}
@Test
public void testDeleteMoreLevelNodeNotAllowed() throws Exception {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode")));
when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode")));
when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt")));
mockMvc.perform(MockMvcRequestBuilders
.delete("/nodes/mynode/middlenode/myfile.txt"))
.andExpect(status().isForbidden());
}
private Optional<Node> getRootNode() {
ContainerNode root = new ContainerNode();
root.setUri(URI_PREFIX + "/");
root.getNodes().add(getWritableDataNode());
return Optional.of(root);
}
private Node getWritableDataNode() {
DataNode node = new DataNode();
List nodeProperties = node.getProperties();
Property groupWriteProp = new Property();
groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI);
groupWriteProp.setValue("group1");
nodeProperties.add(groupWriteProp);
node.setUri(URI_PREFIX + "/mynode");
return node;
}
private Node getWritableDataNode(String path) {
DataNode node = new DataNode();
List nodeProperties = node.getProperties();
Property groupWriteProp = new Property();
groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI);
groupWriteProp.setValue("group1");
nodeProperties.add(groupWriteProp);
node.setUri(URI_PREFIX + path);
return node;
}
private LinkNode getWritableLinkNode(String path) {
LinkNode myNode = new LinkNode();
// Set parent node address at /
myNode.setUri("vos://example.com!vospace" + path);
// Set groupwrite property
Property groups = new Property();
groups.setUri("ivo://ivoa.net/vospace/core#groupwrite");
groups.setValue("group1");
myNode.setProperties(List.of(groups));
return myNode;
}
}
/*
* 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.InternalFaultException;
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.Optional;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.annotation.DirtiesContext;
@SpringBootTest
@AutoConfigureMockMvc
@ContextConfiguration(classes = DataSourceConfigSingleton.class)
@TestPropertySource(locations = "classpath:test.properties", properties = {"vospace-authority=example.com!vospace", "file-service-url=http://file-service"})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class DeleteNodeServiceTest {
@Autowired
private DeleteNodeService deleteNodeService;
@Autowired
private NodeDAO nodeDao;
@Test
public void testPreliminaryCheckOnRoot() {
assertThrows(PermissionDeniedException.class, ()->{
deleteNodeService.doPreliminaryChecks("/");
});
}
@Test
public void testPreliminaryNodeNotFound() {
assertThrows(NodeNotFoundException.class, ()->{
deleteNodeService.doPreliminaryChecks("/nonexistent/node");
});
}
@Test
public void deleteBranchTest() {
User user = mock(User.class);
when(user.getName()).thenReturn("user3");
Optional<Long> sourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(sourceId.isPresent());
Optional<Long> childId = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(childId.isPresent());
// Delete
deleteNodeService.deleteNode("/test3/m1", user);
Optional<Long> checkSourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(checkSourceId.isEmpty());
Optional<Long> checkSourceIdChild = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(checkSourceIdChild.isEmpty());
}
@Test
public void deleteStopOnImmutableTest() {
User user = mock(User.class);
when(user.getName()).thenReturn("user3");
Optional<Long> sourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(sourceId.isPresent());
Optional<Long> childId = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(childId.isPresent());
nodeDao.setBranchImmutable(childId.get(), true);
// Delete
assertThrows(InternalFaultException.class,
()->{ deleteNodeService.deleteNode("/test3/m1", user);}
);
Optional<Long> checkSourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(checkSourceId.isPresent());
Optional<Long> checkSourceIdChild = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(checkSourceIdChild.isPresent());
}
@Test
public void deleteStopOnBusyTest() {
User user = mock(User.class);
when(user.getName()).thenReturn("user3");
Optional<Long> sourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(sourceId.isPresent());
Optional<Long> childId = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(childId.isPresent());
nodeDao.setBranchJobId(childId.get(), "pippo");
// Delete
assertThrows(NodeBusyException.class,
()->{ deleteNodeService.deleteNode("/test3/m1", user);}
);
Optional<Long> checkSourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(checkSourceId.isPresent());
Optional<Long> checkSourceIdChild = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(checkSourceIdChild.isPresent());
}
@Test
public void deleteStopOnPermissionDeniedTest() {
User user = mock(User.class);
when(user.getName()).thenReturn("user-pippo");
Optional<Long> sourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(sourceId.isPresent());
Optional<Long> childId = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(childId.isPresent());
// Delete
assertThrows(PermissionDeniedException.class,
()->{ deleteNodeService.deleteNode("/test3/m1", user);}
);
Optional<Long> checkSourceId = nodeDao.getNodeId("/test3/m1");
assertTrue(checkSourceId.isPresent());
Optional<Long> checkSourceIdChild = nodeDao.getNodeId("/test3/m1/m2");
assertTrue(checkSourceIdChild.isPresent());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment