Newer
Older
/*
* This file is part of vospace-rest
* Copyright (C) 2021 Istituto Nazionale di Astrofisica
* SPDX-License-Identifier: GPL-3.0-or-later
*/
Sonia Zorba
committed
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.nio.charset.StandardCharsets;
import net.ivoa.xml.vospace.v2.Property;
Nicola Fulvio Calabria
committed
import it.inaf.oats.vospace.datamodel.NodeProperties;
import net.ivoa.xml.vospace.v2.UnstructuredDataNode;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.argThat;
Nicola Fulvio Calabria
committed
import static org.mockito.ArgumentMatchers.eq;
Nicola Fulvio Calabria
committed
import static org.mockito.Mockito.when;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
Sonia Zorba
committed
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Sonia Zorba
committed
import static org.mockito.ArgumentMatchers.any;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
Nicola Fulvio Calabria
committed
import net.ivoa.xml.vospace.v2.ContainerNode;
import net.ivoa.xml.vospace.v2.LinkNode;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.mockito.ArgumentCaptor;
import static org.mockito.Mockito.times;
Nicola Fulvio Calabria
committed
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
Sonia Zorba
committed
@SpringBootTest
Nicola Fulvio Calabria
committed
@ContextConfiguration(classes = {TokenFilterConfig.class})
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
@AutoConfigureMockMvc
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
@MockBean
private NodeDAO nodeDao;
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
@SpyBean
@Autowired
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
@Autowired
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
private ContainerNode getContainerParentNode(String path) {
ContainerNode parentNode = new ContainerNode();
// Set parent node address at /
parentNode.setUri("vos://example.com!vospace" + path);
// Set groupwrite property
Property groups = new Property();
groups.setUri("ivo://ivoa.net/vospace/core#groupwrite");
Nicola Fulvio Calabria
committed
groups.setValue("group1 group2");
Nicola Fulvio Calabria
committed
parentNode.setProperties(List.of(groups));
return parentNode;
}
Nicola Fulvio Calabria
committed
private ContainerNode getContainerParentNodeWithCreator(String path) {
Nicola Fulvio Calabria
committed
ContainerNode parentNode = new ContainerNode();
// Set parent node address at /
parentNode.setUri("vos://example.com!vospace" + path);
Property creator = new Property();
creator.setUri("ivo://ivoa.net/vospace/core#creator");
creator.setValue("user2");
Nicola Fulvio Calabria
committed
parentNode.setProperties(List.of(creator));
Nicola Fulvio Calabria
committed
return parentNode;
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
private LinkNode getLinkParentNode(String path) {
LinkNode parentNode = new LinkNode();
// Set parent node address at /
parentNode.setUri("vos://example.com!vospace" + path);
// Set groupwrite property
Property groups = new Property();
groups.setUri("ivo://ivoa.net/vospace/core#groupwrite");
Nicola Fulvio Calabria
committed
groups.setValue("group1 group2");
Nicola Fulvio Calabria
committed
parentNode.setProperties(List.of(groups));
return parentNode;
}
Nicola Fulvio Calabria
committed
@Test
public void testFromJsonToXml() throws Exception {
Nicola Fulvio Calabria
committed
String requestBody
= getResourceFileContent("create-unstructured-data-node.json");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNode("/")));
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().isOk());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testFromXmlToJson() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNode("/")));
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
Nicola Fulvio Calabria
committed
verify(nodeDao, times(1)).createNode(any());
Nicola Fulvio Calabria
committed
@Test
public void testFromXmlToXml() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNode("/")));
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().isOk());
Nicola Fulvio Calabria
committed
verify(nodeDao, times(1)).createNode(any());
Nicola Fulvio Calabria
committed
@Test
public void testFromJsonToJson() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.json");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNode("/")));
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
Nicola Fulvio Calabria
committed
verify(nodeDao, times(1)).createNode(any());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testURIConsistence() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNode("/")));
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata2")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
Nicola Fulvio Calabria
committed
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
verifyArguments();
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testNodeAlreadyExisting() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNode("/")));
when(nodeDao.listNode(eq("/mydata1")))
.thenReturn(Optional.of(getContainerParentNode("/mydata1")));
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
Nicola Fulvio Calabria
committed
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
verifyArguments();
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testContainerNotFound() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.ofNullable(null));
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
Nicola Fulvio Calabria
committed
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
verifyArguments();
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testLinkNodeFound() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getLinkParentNode("/")));
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
Nicola Fulvio Calabria
committed
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
verifyArguments();
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testPermissionDenied() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
Nicola Fulvio Calabria
committed
.thenReturn(Optional.of(getContainerParentNode("/")));
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user1_token")
Nicola Fulvio Calabria
committed
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
verifyArguments();
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testWriteWithOnlyOwnership() throws Exception {
String requestBody = getResourceFileContent("create-unstructured-data-node.xml");
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata1")
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is2xxSuccessful());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
verifyArguments();
verify(nodeDao, times(1)).createNode(any());
Nicola Fulvio Calabria
committed
}
Nicola Fulvio Calabria
committed
@Test
public void testWriteOwnerAbsent() throws Exception {
Nicola Fulvio Calabria
committed
String requestBody
= getResourceFileContent("create-unstructured-data-node.xml");
when(nodeDao.listNode(eq("/")))
Nicola Fulvio Calabria
committed
.thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
Nicola Fulvio Calabria
committed
// no node creator specified in xml file
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is2xxSuccessful());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
// assert creator properties now matches user2
Nicola Fulvio Calabria
committed
verify(nodeDao, times(1)).createNode(argThat(node -> {
UnstructuredDataNode udn = (UnstructuredDataNode) node;
String creator = NodeProperties.getNodePropertyByURI(
udn, NodeProperties.CREATOR_URI);
return (creator != null && creator.equals("user2"));
Nicola Fulvio Calabria
committed
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
}
@Test
public void testGroupPropertiesAbsent() throws Exception {
String requestBody
= getResourceFileContent("create-unstructured-data-node.xml");
ContainerNode cdn = getContainerParentNode("/");
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(cdn));
// no node creator specified in xml file
mockMvc.perform(put("/nodes/mydata1")
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is2xxSuccessful());
// assert creator properties now matches user2
verify(nodeDao, times(1)).createNode(argThat(node -> {
UnstructuredDataNode udn = (UnstructuredDataNode) node;
String groupRead = NodeProperties.getNodePropertyByURI(
udn, NodeProperties.GROUP_READ_URI);
String groupWrite = NodeProperties.getNodePropertyByURI(
udn, NodeProperties.GROUP_WRITE_URI);
return (groupRead == null && groupWrite.equals("group1 group2"));
Nicola Fulvio Calabria
committed
}
@Test
public void testWriteOwnerMismatch() throws Exception {
Nicola Fulvio Calabria
committed
String requestBody
= getResourceFileContent("create-unstructured-data-node-user1.xml");
when(nodeDao.listNode(eq("/")))
Nicola Fulvio Calabria
committed
.thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
Nicola Fulvio Calabria
committed
// no node creator specified in xml file
mockMvc.perform(put("/nodes/mydata1")
Nicola Fulvio Calabria
committed
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
// assert createNode is not called
Nicola Fulvio Calabria
committed
verify(nodeDao, times(0)).createNode(any());
Nicola Fulvio Calabria
committed
}
Nicola Fulvio Calabria
committed
Nicola Fulvio Calabria
committed
@Test
public void testSubPath() throws Exception {
Nicola Fulvio Calabria
committed
String requestBody = getResourceFileContent("create-unstructured-data-node.xml")
.replace("/mydata1", "/mydata1/anothernode");
Nicola Fulvio Calabria
committed
mockMvc.perform(put("/nodes/mydata1/anothernode")
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().isNotFound());
// Using ArgumentCaptor for verifying multiple method invocations
ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);
Nicola Fulvio Calabria
committed
verify(nodeDao, times(2)).listNode(argCaptor.capture());
Nicola Fulvio Calabria
committed
assertEquals("/mydata1/anothernode", argCaptor.getAllValues().get(0));
assertEquals("/mydata1", argCaptor.getAllValues().get(1));
}
@Test
public void testIllegalChars() throws Exception {
Nicola Fulvio Calabria
committed
String requestBody = getResourceFileContent("create-unstructured-data-node.xml")
.replace("/mydata1", "/mydata1/?anothernode");
Nicola Fulvio Calabria
committed
String message = mockMvc.perform(put(new URI("/nodes/mydata1/%3Fanothernode"))
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().isBadRequest())
.andReturn().getResolvedException().getMessage();
Nicola Fulvio Calabria
committed
assertTrue(message.contains("contains an illegal character"));
}
Nicola Fulvio Calabria
committed
Sonia Zorba
committed
verify(controller).createNode(
argThat(node -> {
UnstructuredDataNode udn = (UnstructuredDataNode) node;
Property property = udn.getProperties().get(0);
return "vos:UnstructuredDataNode".equals(udn.getType())
&& "test value".equals(property.getValue())
&& "ivo://ivoa.net/vospace/core#description".equals(property.getUri());
Sonia Zorba
committed
}), any());
Nicola Fulvio Calabria
committed
protected static String getResourceFileContent(String fileName) throws Exception {
Nicola Fulvio Calabria
committed
try (InputStream in = CreateNodeControllerTest.class.getClassLoader().getResourceAsStream(fileName)) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
}
}