From 8fe93cf567a0d1d21144b2a53bc9396be97546e0 Mon Sep 17 00:00:00 2001 From: OZGCloud <ozgcloud@mgm-tp.com> Date: Mon, 21 Oct 2024 17:38:19 +0200 Subject: [PATCH] OZG-6944 refactor AntragraumGrpcService to use GrpcDownloader --- .../antragraum/AntragraumGrpcService.java | 81 +--- .../antragraum/AntragraumService.java | 8 +- .../common/grpc/GrpcDownloader.java | 3 +- .../antragraum/AntragraumGrpcServiceTest.java | 438 +++--------------- .../common/grpc/GrpcDownloaderTest.java | 5 - 5 files changed, 92 insertions(+), 443 deletions(-) diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java index 0f96740..ab77067 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java @@ -23,30 +23,23 @@ package de.ozgcloud.nachrichten.antragraum; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.time.ZonedDateTime; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; import java.util.stream.Stream; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.task.TaskExecutor; import com.google.protobuf.ByteString; -import de.ozgcloud.apilib.common.errorhandling.NotFoundException; import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.nachrichten.NachrichtenManagerConfiguration; +import de.ozgcloud.nachrichten.common.grpc.GrpcDownloader; import de.ozgcloud.nachrichten.common.vorgang.VorgangService; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; +import io.grpc.stub.CallStreamObserver; import io.grpc.stub.StreamObserver; import lombok.RequiredArgsConstructor; import net.devh.boot.grpc.server.service.GrpcService; @@ -64,6 +57,7 @@ class AntragraumGrpcService extends AntragraumServiceGrpc.AntragraumServiceImplB private final AttachmentFileRequestMapper attachmentFileRequestMapper; @Qualifier(NachrichtenManagerConfiguration.NACHRICHTEN_OZG_CLOUD_FILE_MAPPER) private final OzgCloudFileMapper ozgCloudFileMapper; + private final TaskExecutor taskExecutor; private final VorgangService vorgangService; @@ -136,66 +130,21 @@ class AntragraumGrpcService extends AntragraumServiceGrpc.AntragraumServiceImplB @Override public void getAttachmentContent(GrpcGetAttachmentContentRequest request, StreamObserver<GrpcGetAttachmentContentResponse> responseObserver) { - try (var pipedInputStream = new PipedInputStream(); - var pipedOutputStream = new PipedOutputStream(pipedInputStream); - var executor = Executors.newFixedThreadPool(1);) { - var task = new FutureTask<>(() -> getAttachmentFileContent(request, pipedOutputStream), null); - - executor.execute(task); - sendFileContent(pipedInputStream, responseObserver); - handleExceptionOnRetrievingContent(task); - - } catch (IOException e) { - throw new TechnicalException("Error on sending attachment content!", e); - } + buildAttachmentDownloader(attachmentFileRequestMapper.fromContentRequest(request), responseObserver).start(); } - void getAttachmentFileContent(GrpcGetAttachmentContentRequest request, PipedOutputStream pipedOutputStream) { - service.getAttachmentContent(attachmentFileRequestMapper.fromContentRequest(request), pipedOutputStream); - } - - void sendFileContent(InputStream fileContent, StreamObserver<GrpcGetAttachmentContentResponse> responseObserver) { - var fileChunk = new byte[CHUNK_SIZE]; - int length; - try (var bufferedInputStream = createBufferedInputStream(fileContent)) { - while ((length = bufferedInputStream.read(fileChunk)) != -1) { - sendChunk(responseObserver, fileChunk, length); - } - responseObserver.onCompleted(); - } catch (IOException e) { - handleException(fileContent, e, "Error on sending file!"); - } - } - - InputStream createBufferedInputStream(InputStream fileContent) { - return new BufferedInputStream(fileContent, CHUNK_SIZE); - } - - private void sendChunk(StreamObserver<GrpcGetAttachmentContentResponse> responseObserver, byte[] fileChunk, int length) { - responseObserver.onNext(GrpcGetAttachmentContentResponse.newBuilder() - .setFileContent(ByteString.copyFrom(fileChunk, 0, length)) - .build()); - } - - private void handleException(InputStream inputStream, IOException e, String message) { - IOUtils.closeQuietly(inputStream); - throw new TechnicalException(message, e); + GrpcDownloader<GrpcGetAttachmentContentResponse> buildAttachmentDownloader(AttachmentFileRequest request, + StreamObserver<GrpcGetAttachmentContentResponse> responseObserver) { + return GrpcDownloader.<GrpcGetAttachmentContentResponse>builder() + .callObserver((CallStreamObserver<GrpcGetAttachmentContentResponse>) responseObserver) + .taskExecutor(taskExecutor) + .downloadConsumer(outputStream -> service.getAttachmentContent(request, outputStream)) + .chunkBuilder(this::buildAttachmentChunkResponse) + .build(); } - void handleExceptionOnRetrievingContent(FutureTask<Object> task) { - try { - task.get(); - } catch (InterruptedException e) { // NOSONAR - throw new TechnicalException("Retrieving attachment content was interupted.", e); - } catch (ExecutionException e) { - if (e.getCause() instanceof SecurityException) { - throw (SecurityException) e.getCause(); - } - if (e.getCause() instanceof NotFoundException) { - throw (NotFoundException) e.getCause(); - } - throw new TechnicalException("Error on retrieving attachment content.", e); - } + GrpcGetAttachmentContentResponse buildAttachmentChunkResponse(ByteString chunk) { + return GrpcGetAttachmentContentResponse.newBuilder().setFileContent(chunk).build(); } @Override diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java index 5da9037..d86093c 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java @@ -27,7 +27,7 @@ import static java.util.Objects.*; import java.io.DataOutputStream; import java.io.IOException; -import java.io.PipedOutputStream; +import java.io.OutputStream; import java.time.ZonedDateTime; import java.util.Comparator; import java.util.Optional; @@ -199,15 +199,15 @@ public class AntragraumService { return parser.parse(samlToken); } - public void getAttachmentContent(AttachmentFileRequest request, PipedOutputStream pipedOutputStream) { + public void getAttachmentContent(AttachmentFileRequest request, OutputStream outputStream) { try { verifyAccessToFile(request); } catch (RuntimeException e) { - IOUtils.closeQuietly(pipedOutputStream); + IOUtils.closeQuietly(outputStream); throw e; } - try (var dataOutput = new DataOutputStream(pipedOutputStream)) { + try (var dataOutput = new DataOutputStream(outputStream)) { ozgCloudFileService.writeFileDataToStream(OzgCloudFileId.from(request.getFileId()), dataOutput); } catch (IOException e) { throw new TechnicalException("Error on getting attachment file content.", e); diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloader.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloader.java index 92d6c2b..7f34bd4 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloader.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloader.java @@ -12,7 +12,6 @@ import org.springframework.core.task.TaskExecutor; import com.google.protobuf.ByteString; -import de.ozgcloud.apilib.file.OzgCloudFileId; import de.ozgcloud.common.errorhandling.TechnicalException; import io.grpc.stub.CallStreamObserver; import lombok.Builder; @@ -33,7 +32,7 @@ public class GrpcDownloader<T> { private PipedOutputStream outputStream; @Builder - public GrpcDownloader(CallStreamObserver<T> callObserver, OzgCloudFileId fileId, Function<ByteString, T> chunkBuilder, + public GrpcDownloader(CallStreamObserver<T> callObserver, Function<ByteString, T> chunkBuilder, Consumer<OutputStream> downloadConsumer, TaskExecutor taskExecutor) { this.callObserver = callObserver; this.chunkBuilder = chunkBuilder; diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java index aeb61e1..8584a2d 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java @@ -21,28 +21,19 @@ package de.ozgcloud.nachrichten.antragraum; import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; +import java.io.OutputStream; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Optional; import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.stream.Stream; -import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -53,17 +44,16 @@ import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedConstruction; -import org.mockito.MockedStatic; import org.mockito.Spy; +import org.springframework.core.task.TaskExecutor; import com.google.protobuf.ByteString; import com.thedeanda.lorem.LoremIpsum; -import de.ozgcloud.apilib.common.errorhandling.NotFoundException; import de.ozgcloud.apilib.file.OzgCloudFile; import de.ozgcloud.apilib.file.OzgCloudFileTestFactory; -import de.ozgcloud.common.datatype.StringBasedValue; import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.nachrichten.common.grpc.GrpcDownloader; import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory; import de.ozgcloud.nachrichten.common.vorgang.Vorgang; import de.ozgcloud.nachrichten.common.vorgang.VorgangService; @@ -71,8 +61,8 @@ import de.ozgcloud.nachrichten.common.vorgang.VorgangTestFactory; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory; +import io.grpc.stub.CallStreamObserver; import io.grpc.stub.StreamObserver; -import lombok.SneakyThrows; class AntragraumGrpcServiceTest { @@ -91,6 +81,8 @@ class AntragraumGrpcServiceTest { private VorgangService vorgangService; @Mock private OzgCloudFileMapper ozgCloudFileMapper; + @Mock + private TaskExecutor taskExecutor; @DisplayName("Find rueckfragen") @Nested @@ -480,160 +472,8 @@ class AntragraumGrpcServiceTest { @Mock private StreamObserver<GrpcGetAttachmentContentResponse> responseObserver; - - private final GrpcGetAttachmentContentRequest grpcRequest = GrpcGetAttachmentContentRequestTestFactory.create(); - - @Nested - class OnNoException { - - private PipedInputStream pipedInputStream; - private MockedConstruction<PipedInputStream> mockedConstructionInput; - - private PipedOutputStream pipedOutputStream; - private MockedConstruction<PipedOutputStream> mockedConstructionOutput; - private InputStream connectedInput; - - private MockedConstruction<FutureTask> mockedConstructionFutureTask; // NOSONAR - private FutureTask<Object> futureTask; - private Runnable runnable; - - private MockedStatic<Executors> mockedStaticExecutors; - @Mock - private ExecutorService executor; - - @BeforeEach - void setUpMockedConstruction() { - mockedConstructionInput = mockConstruction(PipedInputStream.class, (pipedInputStream, context) -> { - this.pipedInputStream = pipedInputStream; - doNothing().when(grpcService).sendFileContent(pipedInputStream, responseObserver); - }); - mockedConstructionOutput = mockConstruction(PipedOutputStream.class, (pipedOutputStream, context) -> { - this.pipedOutputStream = pipedOutputStream; - connectedInput = (InputStream) context.arguments().get(0); - }); - mockedConstructionFutureTask = mockConstruction(FutureTask.class, (futureTask, context) -> { - this.futureTask = futureTask; // NOSONAR - runnable = (Runnable) context.arguments().get(0); - }); - mockedStaticExecutors = mockStatic(Executors.class); - mockedStaticExecutors.when(() -> Executors.newFixedThreadPool(1)).thenReturn(executor); - } - - @AfterEach - void closeMocks() { - mockedConstructionInput.close(); - mockedConstructionOutput.close(); - mockedConstructionFutureTask.close(); - mockedStaticExecutors.close(); - } - - @Test - void shouldConstructInputStream() { - callGetAttachmentContent(); - - assertThat(mockedConstructionInput.constructed()).hasSize(1); - } - - @Test - void shouldConstructOutputStream() { - callGetAttachmentContent(); - - assertThat(mockedConstructionOutput.constructed()).hasSize(1); - } - - @Test - void shouldConnectPipes() { - callGetAttachmentContent(); - - assertThat(connectedInput).isEqualTo(pipedInputStream); - } - - @Test - void shouldCreateNewFixedThreadPool() { - callGetAttachmentContent(); - - mockedStaticExecutors.verify(() -> Executors.newFixedThreadPool(1)); - } - - @Test - void shouldConstructFutureTask() { - callGetAttachmentContent(); - - assertThat(mockedConstructionFutureTask.constructed()).hasSize(1); - } - - @Test - void shouldExecuteTask() { - callGetAttachmentContent(); - - verify(executor).execute(futureTask); - } - - @Test - void shouldSendFileContent() { - callGetAttachmentContent(); - - verify(grpcService).sendFileContent(pipedInputStream, responseObserver); - } - - @Test - void shouldCallHandleExceptionOnRetrievingContent() { - callGetAttachmentContent(); - - verify(grpcService).handleExceptionOnRetrievingContent(futureTask); - } - - @Nested - class TestTask { - @Test - void shouldCallGetAttachmentFileContent() { - callGetAttachmentContent(); - - runnable.run(); - - verify(grpcService).getAttachmentFileContent(grpcRequest, pipedOutputStream); - } - } - } - - @Nested - class OnIOException { - - @BeforeEach - void setUpMock() { - doNothing().when(grpcService).sendFileContent(any(), eq(responseObserver)); - } - - @Test - @SneakyThrows - void shouldThrowTechnicalExceptionOnErrorOnInputStream() { - try (var mockedConstructionInput = mockConstruction(PipedInputStream.class, - (mock, context) -> doThrow(IOException.class).when(mock).close())) { - - assertThrows(TechnicalException.class, () -> callGetAttachmentContent()); - } - } - - @Test - @SneakyThrows - void shouldThrowTechnicalExceptionOnErrorOnOutputStream() { - try (var mockedConstructionInput = mockConstruction(PipedOutputStream.class, - (mock, context) -> doThrow(IOException.class).when(mock).close())) { - - assertThrows(TechnicalException.class, () -> callGetAttachmentContent()); - } - } - } - - private void callGetAttachmentContent() { - grpcService.getAttachmentContent(grpcRequest, responseObserver); - } - } - - @Nested - class TestGetAttachmentFileContent { @Mock - private PipedOutputStream pipedOutputStream; + private GrpcDownloader<GrpcGetAttachmentContentResponse> downloader; private final GrpcGetAttachmentContentRequest grpcRequest = GrpcGetAttachmentContentRequestTestFactory.create(); private final AttachmentFileRequest request = AttachmentFileRequestTestFactory.create(); @@ -641,262 +481,128 @@ class AntragraumGrpcServiceTest { @BeforeEach void mock() { when(attachmentFileRequestMapper.fromContentRequest(grpcRequest)).thenReturn(request); + doReturn(downloader).when(grpcService).buildAttachmentDownloader(request, responseObserver); } @Test void shouldMapRequest() { - callGetRueckfrageAttachmentFile(); + callGetAttachmentContent(); verify(attachmentFileRequestMapper).fromContentRequest(grpcRequest); } @Test - void shouldCallServiceToGetAttachmentContent() { - callGetRueckfrageAttachmentFile(); - - verify(service).getAttachmentContent(request, pipedOutputStream); - } + void shouldCallBuildAttachmentDownloader() { + callGetAttachmentContent(); - private void callGetRueckfrageAttachmentFile() { - grpcService.getAttachmentFileContent(grpcRequest, pipedOutputStream); + verify(grpcService).buildAttachmentDownloader(request, responseObserver); } - } - - @Nested - class TestSendFileContent { - - @Mock - private StreamObserver<GrpcGetAttachmentContentResponse> responseObserver; - - @Mock - private InputStream fileContent; - - @Nested - class TestWithByteArrayInputStream { - private final byte[] byteContent = FileContentTestFactory.createContentInByte((int) (AntragraumGrpcService.CHUNK_SIZE * 1.5)); - private final InputStream inputStream = new ByteArrayInputStream(byteContent); - - @BeforeEach - void setUpMock() { - doReturn(inputStream).when(grpcService).createBufferedInputStream(fileContent); - } - - @Test - void shouldCreateBufferedInputStream() { - callSendFileContent(); - verify(grpcService).createBufferedInputStream(fileContent); - } - - @Test - void shouldSendFirstDataChunk() { - callSendFileContent(); - - verify(responseObserver) - .onNext(argThat((response) -> response.getFileContent() - .equals(ByteString.copyFrom(byteContent, 0, AntragraumGrpcService.CHUNK_SIZE)))); - } - - @Test - void shouldSendSecondDataChunk() { - callSendFileContent(); - - verify(responseObserver) - .onNext(argThat((response) -> response.getFileContent() - .equals(ByteString.copyFrom(byteContent, AntragraumGrpcService.CHUNK_SIZE, - byteContent.length - AntragraumGrpcService.CHUNK_SIZE)))); - } - - @Test - void shouldComplete() { - callSendFileContent(); - - verify(responseObserver).onCompleted(); - } - } - - @Nested - class TestWithMockedInputStream { - - @Mock - private BufferedInputStream inputStream; - - @BeforeEach - void setUpMock() { - doReturn(inputStream).when(grpcService).createBufferedInputStream(fileContent); - } - - @Test - @SneakyThrows - void shouldCloseInputStream() { - when(inputStream.read(any())).thenReturn(-1); - - callSendFileContent(); - - verify(inputStream).close(); - } - - @Nested - class OnIOException { - - private MockedStatic<IOUtils> mockedIOUtils; - - @BeforeEach - @SneakyThrows - void setUpMock() { - when(inputStream.read(any())).thenThrow(new IOException()); - mockedIOUtils = mockStatic(IOUtils.class); - } - - @AfterEach - void cleanUp() { - mockedIOUtils.close(); - } - - @Test - void shouldThrowTechnicalException() { - assertThrows(TechnicalException.class, - () -> callSendFileContent()); - } - - @Test - void shouldCloseFileContentStreamQuietly() { - try { - callSendFileContent(); - } catch (TechnicalException e) { - } + @Test + void shouldStartDownloader() { + callGetAttachmentContent(); - mockedIOUtils.verify(() -> IOUtils.closeQuietly(fileContent)); - } - } + verify(downloader).start(); } - private void callSendFileContent() { - grpcService.sendFileContent(fileContent, responseObserver); + private void callGetAttachmentContent() { + grpcService.getAttachmentContent(grpcRequest, responseObserver); } } @Nested - class TestCreateBufferedInputStream { + class TestBuildAttachmentDownloader { + @Mock + private CallStreamObserver<GrpcGetAttachmentContentResponse> responseObserver; + @Mock + private OutputStream outputStream; - private MockedConstruction<BufferedInputStream> mockConstructionBufferedInputStream; - private InputStream passedInputStream; - private BufferedInputStream constructedInputStream; - private int chunkSize; + private MockedConstruction<GrpcDownloader> downloaderMockedConstruction; + private GrpcDownloader<GrpcGetAttachmentContentResponse> downloader; + private StreamObserver<GrpcGetAttachmentContentResponse> setResponseObserver; + private TaskExecutor setTaskExecutor; + private Consumer<OutputStream> setDownloadConsumer; + private Function<ByteString, GrpcGetAttachmentContentResponse> setChunkBuilder; - @Mock - private InputStream fileContent; + private final AttachmentFileRequest request = AttachmentFileRequestTestFactory.create(); + private final ByteString chunk = ByteString.copyFromUtf8(LoremIpsum.getInstance().getWords(5)); + @SuppressWarnings("unchecked") @BeforeEach - void setUpMock() { - mockConstructionBufferedInputStream = mockConstruction(BufferedInputStream.class, (mock, context) -> { - passedInputStream = (InputStream) context.arguments().get(0); - chunkSize = (int) context.arguments().get(1); - constructedInputStream = mock; + void mock() { + downloaderMockedConstruction = mockConstruction(GrpcDownloader.class, (downloader, context) -> { + setResponseObserver = (StreamObserver<GrpcGetAttachmentContentResponse>) context.arguments().get(0); + setChunkBuilder = (Function<ByteString, GrpcGetAttachmentContentResponse>) context.arguments().get(1); + setDownloadConsumer = (Consumer<OutputStream>) context.arguments().get(2); + setTaskExecutor = (TaskExecutor) context.arguments().get(3); + this.downloader = downloader; }); } @AfterEach void closeMock() { - mockConstructionBufferedInputStream.close(); + downloaderMockedConstruction.close(); } @Test - void shouldConstructBufferedInputStream() { - callCreateBufferedInputStream(); + void shouldSetResponseObserver() { + callBuildAttachmentDownloader(); - assertThat(mockConstructionBufferedInputStream.constructed()).hasSize(1); + assertThat(setResponseObserver).isEqualTo(responseObserver); } @Test - void shouldConstructBufferedInputStreamWithFileContent() { - callCreateBufferedInputStream(); + void shouldSetTaskExecutor() { + callBuildAttachmentDownloader(); - assertThat(passedInputStream).isEqualTo(fileContent); + assertThat(setTaskExecutor).isEqualTo(taskExecutor); } @Test - void shouldConstructBufferedInputStreamWithChunkSize() { - callCreateBufferedInputStream(); + void shouldSetDownloadConsumer() { + callBuildAttachmentDownloader(); + + setDownloadConsumer.accept(outputStream); - assertThat(chunkSize).isEqualTo(AntragraumGrpcService.CHUNK_SIZE); + verify(service).getAttachmentContent(request, outputStream); } @Test - void shouldReturnBufferedInputStream() { - var returnedInputStream = callCreateBufferedInputStream(); + void shouldSetChunkBuilder() { + var response = GrpcGetAttachmentContentResponse.newBuilder().setFileContent(chunk).build(); + doReturn(response).when(grpcService).buildAttachmentChunkResponse(chunk); + callBuildAttachmentDownloader(); - assertThat(returnedInputStream).isEqualTo(constructedInputStream); - } + var result = setChunkBuilder.apply(chunk); - private InputStream callCreateBufferedInputStream() { - return grpcService.createBufferedInputStream(fileContent); + assertThat(result).isEqualTo(response); } - } - - @Nested - class TestHandleExceptionOnRetrievingContent { - - @Mock - private FutureTask<Object> futureTask; - - private final StringBasedValue id = new StringBasedValue() { - }; - private final String entityName = LoremIpsum.getInstance().getWords(1); - @Test - @SneakyThrows - void shouldGettaskResult() { - callHandleExceptionOnRetrievingContent(); + void shouldReturnDownloader() { + var returnedDownloader = callBuildAttachmentDownloader(); - verify(futureTask).get(); + assertThat(returnedDownloader).isEqualTo(downloader); } - @Test - @SneakyThrows - void shouldThrowTechnicalExceptionOnInteruption() { - var interruptedException = new InterruptedException(); - when(futureTask.get()).thenThrow(interruptedException); - - assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent()) - .isInstanceOf(TechnicalException.class) - .hasCause(interruptedException); + private GrpcDownloader<GrpcGetAttachmentContentResponse> callBuildAttachmentDownloader() { + return grpcService.buildAttachmentDownloader(request, responseObserver); } + } - @Test - @SneakyThrows - void shouldRethrowSecurityException() { - var securityException = new SecurityException(); - when(futureTask.get()).thenThrow(new ExecutionException(securityException)); + @Nested + class TestBuildAttachmentChunkResponse { - assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent()) - .isInstanceOf(SecurityException.class); - } + private final ByteString chunk = ByteString.copyFromUtf8(LoremIpsum.getInstance().getWords(5)); @Test - @SneakyThrows - void shouldRethrowNotFoundException() { - var notFoundException = new NotFoundException(id, entityName); - when(futureTask.get()).thenThrow(new ExecutionException(notFoundException)); + void shouldReturnResponse() { + var expectedResponse = GrpcGetAttachmentContentResponse.newBuilder().setFileContent(chunk).build(); - assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent()) - .isInstanceOf(NotFoundException.class); - } + var result = grpcService.buildAttachmentChunkResponse(chunk); - @Test - @SneakyThrows - void shouldThrowTechnicalExceptionOtherExecutionException() { - var executionException = new ExecutionException(new Exception()); - when(futureTask.get()).thenThrow(executionException); - - assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent()) - .isInstanceOf(TechnicalException.class) - .hasCause(executionException); - } + assertThat(result).isEqualTo(expectedResponse); - private void callHandleExceptionOnRetrievingContent() { - grpcService.handleExceptionOnRetrievingContent(futureTask); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloaderTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloaderTest.java index 28880fd..4f7c0c5 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloaderTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/GrpcDownloaderTest.java @@ -26,8 +26,6 @@ import org.springframework.test.util.ReflectionTestUtils; import com.google.protobuf.ByteString; -import de.ozgcloud.apilib.file.OzgCloudFileId; -import de.ozgcloud.apilib.file.OzgCloudFileTestFactory; import de.ozgcloud.common.errorhandling.TechnicalException; import io.grpc.stub.ClientCallStreamObserver; import lombok.SneakyThrows; @@ -42,12 +40,9 @@ class GrpcDownloaderTest { private Consumer<OutputStream> downloadConsumer = Mockito.mock(Consumer.class); private TaskExecutor taskExecutor = mock(TaskExecutor.class); - private OzgCloudFileId fileId = OzgCloudFileTestFactory.ID; - @Spy private GrpcDownloader<GrpcResponseDummy> downloader = GrpcDownloader.<GrpcResponseDummy>builder() .callObserver(callObserver) - .fileId(fileId) .downloadConsumer(downloadConsumer) .chunkBuilder(chunkBuilder) .taskExecutor(taskExecutor) -- GitLab