Skip to content
TransferControllerTest.java 7.85 KiB
Newer Older
package it.inaf.oats.vospace;

import it.inaf.ia2.aa.data.User;
import static it.inaf.oats.vospace.VOSpaceXmlTestUtil.loadDocument;
import it.inaf.oats.vospace.persistence.JobDAO;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.vospace.v2.DataNode;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Property;
import net.ivoa.xml.vospace.v2.Protocol;
import net.ivoa.xml.vospace.v2.Transfer;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.matchesPattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
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.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.w3c.dom.Document;

@SpringBootTest
@AutoConfigureMockMvc
@ContextConfiguration(classes = {TokenFilterConfig.class})
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
public class TransferControllerTest {

    @MockBean
    private JobDAO jobDao;

    @MockBean
    private NodeDAO nodeDao;

    @MockBean
    private TapeService tapeService;

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testPullFromVoSpaceAsync() throws Exception {

        Node node = mockPublicDataNode();
        when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));

        String requestBody = getResourceFileContent("pullFromVoSpace.xml");

        String redirect = mockMvc.perform(post("/transfers?PHASE=RUN")
                .content(requestBody)
                .contentType(MediaType.APPLICATION_XML)
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().is3xxRedirection())
                .andReturn().getResponse().getHeader("Location");

        assertThat(redirect, matchesPattern("^/transfers/.*"));
    }

    @Test
    public void testPullFromVoSpaceSync() throws Exception {

        Node node = mockPublicDataNode();
        when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));

        String requestBody = getResourceFileContent("pullFromVoSpace.xml");

        String redirect = mockMvc.perform(post("/synctrans")
                .content(requestBody)
                .contentType(MediaType.APPLICATION_XML)
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().is3xxRedirection())
                .andReturn().getResponse().getHeader("Location");

        assertThat(redirect, matchesPattern("^/transfers/.*/results/transferDetails"));
    }

    @Test
    public void testPullToVoSpace() throws Exception {

        String requestBody = getResourceFileContent("pullToVoSpace.xml");

        String redirect = mockMvc.perform(post("/transfers?PHASE=RUN")
                .content(requestBody)
                .contentType(MediaType.APPLICATION_XML)
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().is3xxRedirection())
                .andReturn().getResponse().getHeader("Location");

        assertThat(redirect, matchesPattern("^/transfers/.*"));

        verify(tapeService, times(1)).startJob(any());
    }

    @Test
    public void testSetJobPhase() throws Exception {

        Node node = mockPublicDataNode();
        when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));

        JobSummary job = getFakePendingJob();
        when(jobDao.getJob(eq("123"))).thenReturn(Optional.of(job));

        User user = new User();
        user.setUserId("ownerId");

        String redirect = mockMvc.perform(post("/transfers/123/phase")
                .header("Authorization", "Bearer user1_token")
                .param("PHASE", "RUN")
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().is3xxRedirection())
                .andReturn().getResponse().getHeader("Location");

        verify(jobDao, times(1)).updateJob(any());

        assertThat(redirect, matchesPattern("^/transfers/.*"));
    }

    @Test
    public void testGetTransferDetails() throws Exception {

        JobSummary job = getFakePendingJob();
        when(jobDao.getJob(eq("123"))).thenReturn(Optional.of(job));

        mockMvc.perform(get("/transfers/123/results/transferDetails")
                .header("Authorization", "Bearer user1_token")
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().isOk());
    }

    @Test
    public void testGetJobPhase() throws Exception {

        JobSummary job = getFakePendingJob();
        when(jobDao.getJob(eq("123"))).thenReturn(Optional.of(job));

        String phase = mockMvc.perform(get("/transfers/123/phase")
                .header("Authorization", "Bearer user1_token"))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString();

        assertEquals("PENDING", phase);
    }

    private Node mockPublicDataNode() {
        Node node = new DataNode();
        Property property = new Property();
        property.setUri("ivo://ivoa.net/vospace/core#publicread");
        property.setValue("true");
        node.getProperties().add(property);
        return node;
    }

    @Test
    public void testGetJob() throws Exception {

        JobSummary job = new JobSummary();

        when(jobDao.getJob(eq("123"))).thenReturn(Optional.of(job));

        String xml = mockMvc.perform(get("/transfers/123")
                .accept(MediaType.APPLICATION_XML))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString();

        Document doc = loadDocument(xml);
        assertEquals("uws:job", doc.getDocumentElement().getNodeName());

        verify(jobDao, times(1)).getJob(eq("123"));
    }

    private JobSummary getFakePendingJob() {
        JobSummary job = new JobSummary();
        job.setPhase(ExecutionPhase.PENDING);
        job.setOwnerId("user1");

        Transfer transfer = new Transfer();
        transfer.setDirection("pullFromVoSpace");
        transfer.setTarget("vos://example.com!vospace/mynode");
        Protocol protocol = new Protocol();
        protocol.setUri("ivo://ivoa.net/vospace/core#httpget");
        transfer.getProtocols().add(protocol);

        JobSummary.JobInfo jobInfo = new JobSummary.JobInfo();
        jobInfo.getAny().add(transfer);

        job.setJobInfo(jobInfo);
        return job;
    }

    protected static String getResourceFileContent(String fileName) throws Exception {
        try ( InputStream in = TransferControllerTest.class.getClassLoader().getResourceAsStream(fileName)) {
            return new String(in.readAllBytes(), StandardCharsets.UTF_8);
        }