diff --git a/src/main/java/it/inaf/ia2/transfer/auth/GmsClient.java b/src/main/java/it/inaf/ia2/transfer/auth/GmsClient.java index 781311aa100dec744c65e5ec5f4be29c977ceda0..8b0adc3a16883bcb77577f5105a617d20b02c795 100644 --- a/src/main/java/it/inaf/ia2/transfer/auth/GmsClient.java +++ b/src/main/java/it/inaf/ia2/transfer/auth/GmsClient.java @@ -31,8 +31,8 @@ public class GmsClient { private final RestTemplate restTemplate; @Autowired - public GmsClient() { - restTemplate = new RestTemplate(); + public GmsClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; } @Cacheable("gms_cache") diff --git a/src/test/java/it/inaf/ia2/transfer/auth/GmsClientTest.java b/src/test/java/it/inaf/ia2/transfer/auth/GmsClientTest.java new file mode 100644 index 0000000000000000000000000000000000000000..32f57f3a8c7ec0d4728c944054798499aee4b1b7 --- /dev/null +++ b/src/test/java/it/inaf/ia2/transfer/auth/GmsClientTest.java @@ -0,0 +1,52 @@ +/* + * This file is part of vospace-file-service + * Copyright (C) 2021 Istituto Nazionale di Astrofisica + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package it.inaf.ia2.transfer.auth; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +@ExtendWith(MockitoExtension.class) +public class GmsClientTest { + + @Mock + private RestTemplate restTemplate; + + @InjectMocks + private GmsClient gmsClient; + + @Test + public void testIsMemberOf() { + mockGmsResponse("group1\n"); + assertTrue(gmsClient.isMemberOf("<token>", "group1")); + } + + @Test + public void testIsNotMemberOf() { + mockGmsResponse(""); + assertFalse(gmsClient.isMemberOf("<token>", "group1")); + } + + private void mockGmsResponse(String body) { + + ResponseEntity<String> mockedResponse = mock(ResponseEntity.class); + when(mockedResponse.getBody()).thenReturn(body); + + when(restTemplate.exchange(any(String.class), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))).thenReturn(mockedResponse); + } +} diff --git a/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java b/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java index f15b20d23f0e93f269bb292d589e777051089aab..5214787b24d049e19e1c92fb1118d8195060fa16 100644 --- a/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java +++ b/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java @@ -8,18 +8,23 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.persistence.model.FileInfo; import it.inaf.ia2.aa.jwt.TokenParser; import it.inaf.ia2.transfer.auth.GmsClient; +import it.inaf.ia2.transfer.exception.JobException; import it.inaf.ia2.transfer.persistence.FileDAO; +import it.inaf.ia2.transfer.persistence.JobDAO; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import net.ivoa.xml.uws.v1.ExecutionPhase; import org.assertj.core.util.Files; import org.junit.jupiter.api.AfterEach; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; 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; @@ -44,6 +49,9 @@ public class GetFileControllerTest { @MockBean private FileDAO fileDao; + @MockBean + private JobDAO jobDAO; + @Autowired private MockMvc mockMvc; @@ -135,23 +143,6 @@ public class GetFileControllerTest { verify(gmsClient).isMemberOf(eq("<token>"), eq("group1")); } - private void prepareMocksForPrivateFile() { - - Map<String, Object> claims = new HashMap<>(); - claims.put("sub", "123"); - - when(tokenParser.getClaims(any())).thenReturn(claims); - - when(gmsClient.isMemberOf(any(), any())).thenReturn(true); - - FileInfo fileInfo = new FileInfo(); - fileInfo.setOsPath(tempFile.getAbsolutePath()); - fileInfo.setVirtualPath("/path/to/myfile"); - fileInfo.setGroupRead(Collections.singletonList("group1")); - - when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo)); - } - @Test public void getPrivateFileByOwnerId() throws Exception { @@ -185,4 +176,80 @@ public class GetFileControllerTest { .andDo(print()) .andExpect(status().isForbidden()); } + + @Test + public void testGetFileWithJobId() throws Exception { + + FileInfo fileInfo = new FileInfo(); + fileInfo.setOsPath(tempFile.getAbsolutePath()); + fileInfo.setVirtualPath("/path/to/myfile"); + fileInfo.setPublic(true); + + when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo)); + + when(jobDAO.isJobExisting(eq("abcdef"))).thenReturn(true); + + mockMvc.perform(get("/path/to/myfile") + .param("jobId", "abcdef")) + .andDo(print()) + .andExpect(status().isOk()); + + verify(jobDAO, times(1)).updateJobPhase(eq(ExecutionPhase.COMPLETED), eq("abcdef")); + } + + @Test + public void testGetFileWithInvalidJobId() throws Exception { + + mockMvc.perform(get("/path/to/myfile") + .param("jobId", "abcdef")) + .andDo(print()) + .andExpect(status().isBadRequest()); + } + + @Test + public void testGetFileNotReadable() throws Exception { + + File unreadableFile = Files.newTemporaryFile(); + + try { + + unreadableFile.setReadable(false); + + FileInfo fileInfo = new FileInfo(); + fileInfo.setOsPath(unreadableFile.getAbsolutePath()); + fileInfo.setVirtualPath("/path/to/myfile"); + fileInfo.setPublic(true); + + when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo)); + + Exception ex = mockMvc.perform(get("/path/to/myfile")) + .andDo(print()) + .andReturn().getResolvedException(); + + assertTrue(ex instanceof JobException); + JobException jobEx = (JobException) ex; + assertTrue(jobEx.getErrorDetail().contains("not readable"), jobEx.getErrorDetail()); + } catch (Throwable t) { + throw t; + } finally { + assertTrue(unreadableFile.delete()); + } + } + + private void prepareMocksForPrivateFile() { + + Map<String, Object> claims = new HashMap<>(); + claims.put("sub", "123"); + + when(tokenParser.getClaims(any())).thenReturn(claims); + + when(gmsClient.isMemberOf(any(), any())).thenReturn(true); + + FileInfo fileInfo = new FileInfo(); + fileInfo.setOsPath(tempFile.getAbsolutePath()); + fileInfo.setVirtualPath("/path/to/myfile"); + fileInfo.setGroupRead(Collections.singletonList("group1")); + + when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo)); + } } diff --git a/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java b/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java index 90531f8cb8d536a4c146aef9765663eec7764af0..9fe0554eb418098a137e90154ea8c54c0fd0557a 100644 --- a/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java +++ b/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,9 +33,11 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.RequestPostProcessor; +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; import org.springframework.util.FileSystemUtils; @@ -94,7 +97,7 @@ public class PutFileControllerTest { putGenericFileWithNameConflict("test", "test-1", "test-2"); } - public void putGenericFileWithNameConflict(String name1, String name2, String name3) throws Exception { + private void putGenericFileWithNameConflict(String name1, String name2, String name3) throws Exception { createBaseFileInfo(name1); @@ -172,6 +175,58 @@ public class PutFileControllerTest { assertTrue(file.delete()); } + @Test + public void testPutFileWithoutNodeInDatabase() throws Exception { + + MockMultipartFile fakeFile = new MockMultipartFile("file", "foo.txt", "text/plain", "content".getBytes()); + + mockMvc.perform(putMultipart("/path/to/foo.txt") + .file(fakeFile)) + .andDo(print()) + .andExpect(status().isNotFound()); + } + + @Test + public void testPutWithInputStream() throws Exception { + + createBaseFileInfo(); + + mockMvc.perform(put("/path/to/stream.txt")) + .andDo(print()) + .andExpect(status().isOk()); + } + + @Test + public void testJobError() throws Exception { + + createBaseFileInfo(); + + when(jobDAO.isJobExisting(eq("abcdef"))).thenReturn(true); + + MockHttpServletRequestBuilder errorBuilder = put("/path/to/error"); + errorBuilder.with(new RequestPostProcessor() { + @Override + public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { + MockHttpServletRequest spyRequest = spy(request); + when(spyRequest.getInputStream()).thenThrow(new RuntimeException()); + return spyRequest; + } + }); + + try { + mockMvc.perform(errorBuilder + .param("jobId", "abcdef")); + } catch (Exception ex) { + } + + verify(jobDAO, times(1)).setJobError(eq("abcdef"), any()); + } + + private FileInfo createBaseFileInfo() { + String randomFileName = UUID.randomUUID().toString(); + return createBaseFileInfo(randomFileName); + } + private FileInfo createBaseFileInfo(String fileName) { FileInfo fileInfo = new FileInfo(); fileInfo.setOsPath(getTestFilePath(fileName)); @@ -183,7 +238,7 @@ public class PutFileControllerTest { } private String getTestFilePath(String fileName) { - return temporaryDirectory.toPath().resolve(fileName).toFile().getAbsolutePath(); + return temporaryDirectory.toPath().resolve("subdir").resolve(fileName).toFile().getAbsolutePath(); } private MockMultipartHttpServletRequestBuilder putMultipart(String uri) {