Cleanup work + stream endpoints to reduce memory usage (#6106)

This commit is contained in:
Anthony Stirling
2026-04-15 15:34:17 +01:00
committed by GitHub
parent 702f4e5c2c
commit cc5a0b8def
116 changed files with 3005 additions and 1512 deletions
@@ -1,8 +1,10 @@
package stirling.software.SPDF.controller.api;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -11,6 +13,7 @@ import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -21,17 +24,47 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.general.BookletImpositionRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class BookletImpositionControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private BookletImpositionController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private MockMultipartFile createRealPdf(int numPages) throws IOException {
Path path = tempDir.resolve("test.pdf");
try (PDDocument doc = new PDDocument()) {
@@ -61,11 +94,12 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
try (PDDocument result = Loader.loadPDF(response.getBody())) {
assertThat(drainBody(response)).isNotEmpty();
try (PDDocument result = Loader.loadPDF(drainBody(response))) {
assertThat(result.getNumberOfPages()).isGreaterThan(0);
}
}
@@ -92,10 +126,11 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
}
@Test
@@ -109,7 +144,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -126,7 +162,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -143,7 +180,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -160,7 +198,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -177,7 +216,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -192,7 +232,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -220,7 +261,8 @@ class BookletImpositionControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(sourceDoc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.createBookletImposition(request);
ResponseEntity<StreamingResponseBody> response =
controller.createBookletImposition(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -1,9 +1,11 @@
package stirling.software.SPDF.controller.api;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
@@ -29,21 +31,47 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.general.CropPdfForm;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
@DisplayName("CropController Tests")
class CropControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private CropController cropController;
private TestPdfFactory pdfFactory;
@BeforeEach
void setUp() {
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
pdfFactory = new TestPdfFactory();
}
@@ -177,7 +205,7 @@ class CropControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDocument))
.thenReturn(newDocument);
ResponseEntity<byte[]> response = cropController.cropPdf(request);
ResponseEntity<StreamingResponseBody> response = cropController.cropPdf(request);
assertThat(response)
.isNotNull()
@@ -214,7 +242,7 @@ class CropControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDocument))
.thenReturn(newDocument);
ResponseEntity<byte[]> response = cropController.cropPdf(request);
ResponseEntity<StreamingResponseBody> response = cropController.cropPdf(request);
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
@@ -234,7 +262,7 @@ class CropControllerTest {
private TestPdfFactory autoCropPdfFactory;
@BeforeEach
void setUp() {
void setUp() throws Exception {
autoCropPdfFactory = new TestPdfFactory();
}
@@ -254,13 +282,13 @@ class CropControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc))
.thenReturn(newDoc);
ResponseEntity<byte[]> response = cropController.cropPdf(request);
ResponseEntity<StreamingResponseBody> response = cropController.cropPdf(request);
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
try (PDDocument result = Loader.loadPDF(response.getBody())) {
try (PDDocument result = Loader.loadPDF(drainBody(response))) {
assertThat(result.getNumberOfPages()).isEqualTo(1);
PDPage page = result.getPage(0);
@@ -285,13 +313,13 @@ class CropControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDoc))
.thenReturn(newDoc);
ResponseEntity<byte[]> response = cropController.cropPdf(request);
ResponseEntity<StreamingResponseBody> response = cropController.cropPdf(request);
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
Assertions.assertNotNull(response.getBody());
try (PDDocument result = Loader.loadPDF(response.getBody())) {
try (PDDocument result = Loader.loadPDF(drainBody(response))) {
assertThat(result.getNumberOfPages()).isEqualTo(1);
}
}
@@ -648,7 +676,7 @@ class CropControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDocument))
.thenReturn(newDocument);
ResponseEntity<byte[]> response = cropController.cropPdf(request);
ResponseEntity<StreamingResponseBody> response = cropController.cropPdf(request);
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
@@ -676,7 +704,7 @@ class CropControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDocument))
.thenReturn(newDocument);
ResponseEntity<byte[]> response = cropController.cropPdf(request);
ResponseEntity<StreamingResponseBody> response = cropController.cropPdf(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
verify(mockDocument, times(1)).close();
@@ -1,10 +1,12 @@
package stirling.software.SPDF.controller.api;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -26,10 +28,13 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.controller.api.EditTableOfContentsController.BookmarkItem;
import stirling.software.SPDF.model.api.EditTableOfContentsRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.ObjectMapper;
@@ -40,6 +45,7 @@ class EditTableOfContentsControllerTest {
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private ObjectMapper objectMapper;
@Mock private TempFileManager tempFileManager;
@InjectMocks private EditTableOfContentsController editTableOfContentsController;
@@ -53,7 +59,19 @@ class EditTableOfContentsControllerTest {
private PDOutlineItem mockOutlineItem;
@BeforeEach
void setUp() {
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
mockFile =
new MockMultipartFile(
"file",
@@ -226,18 +244,19 @@ class EditTableOfContentsControllerTest {
when(mockDocument.getNumberOfPages()).thenReturn(5);
when(mockDocument.getPage(0)).thenReturn(mockPage1);
// Mock saving behavior
doAnswer(
invocation -> {
ByteArrayOutputStream baos = invocation.getArgument(0);
baos.write("mocked pdf content".getBytes());
lenient()
.doAnswer(
inv -> {
File f = inv.getArgument(0);
java.nio.file.Files.write(f.toPath(), "mock pdf".getBytes());
return null;
})
.when(mockDocument)
.save(any(ByteArrayOutputStream.class));
.save(any(File.class));
// When
ResponseEntity<byte[]> result = editTableOfContentsController.editTableOfContents(request);
ResponseEntity<StreamingResponseBody> result =
editTableOfContentsController.editTableOfContents(request);
// Then
assertNotNull(result);
@@ -289,17 +308,19 @@ class EditTableOfContentsControllerTest {
when(mockDocument.getPage(0)).thenReturn(mockPage1);
when(mockDocument.getPage(1)).thenReturn(mockPage2);
doAnswer(
invocation -> {
ByteArrayOutputStream baos = invocation.getArgument(0);
baos.write("mocked pdf content".getBytes());
lenient()
.doAnswer(
inv -> {
File f = inv.getArgument(0);
java.nio.file.Files.write(f.toPath(), "mock pdf".getBytes());
return null;
})
.when(mockDocument)
.save(any(ByteArrayOutputStream.class));
.save(any(File.class));
// When
ResponseEntity<byte[]> result = editTableOfContentsController.editTableOfContents(request);
ResponseEntity<StreamingResponseBody> result =
editTableOfContentsController.editTableOfContents(request);
// Then
assertNotNull(result);
@@ -341,17 +362,19 @@ class EditTableOfContentsControllerTest {
when(mockDocument.getPage(0)).thenReturn(mockPage1); // For negative page number
when(mockDocument.getPage(4)).thenReturn(mockPage2); // For page number exceeding bounds
doAnswer(
invocation -> {
ByteArrayOutputStream baos = invocation.getArgument(0);
baos.write("mocked pdf content".getBytes());
lenient()
.doAnswer(
inv -> {
File f = inv.getArgument(0);
java.nio.file.Files.write(f.toPath(), "mock pdf".getBytes());
return null;
})
.when(mockDocument)
.save(any(ByteArrayOutputStream.class));
.save(any(File.class));
// When
ResponseEntity<byte[]> result = editTableOfContentsController.editTableOfContents(request);
ResponseEntity<StreamingResponseBody> result =
editTableOfContentsController.editTableOfContents(request);
// Then
assertNotNull(result);
@@ -1,5 +1,12 @@
package stirling.software.SPDF.controller.api;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.junit.jupiter.api.Assertions;
@@ -15,14 +22,28 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.general.MergeMultiplePagesRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class MultiPageLayoutControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private MultiPageLayoutController controller;
@@ -30,7 +51,19 @@ class MultiPageLayoutControllerTest {
private MockMultipartFile fileNoExt;
@BeforeEach
void setup() {
void setup() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
fileWithExt =
new MockMultipartFile(
"fileInput", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
@@ -64,11 +97,11 @@ class MultiPageLayoutControllerTest {
req.setAddBorder(Boolean.FALSE);
req.setFileInput(fileWithExt);
ResponseEntity<byte[]> resp = controller.mergeMultiplePagesIntoOne(req);
ResponseEntity<StreamingResponseBody> resp = controller.mergeMultiplePagesIntoOne(req);
Assertions.assertEquals(HttpStatus.OK, resp.getStatusCode());
Assertions.assertEquals(MediaType.APPLICATION_PDF, resp.getHeaders().getContentType());
Assertions.assertNotNull(resp.getBody());
Assertions.assertTrue(resp.getBody().length > 0);
Assertions.assertTrue(drainBody(resp).length > 0);
Assertions.assertEquals(
"test_multi_page_layout.pdf",
resp.getHeaders().getContentDisposition().getFilename());
@@ -89,11 +122,11 @@ class MultiPageLayoutControllerTest {
req.setAddBorder(Boolean.TRUE);
req.setFileInput(fileWithExt);
ResponseEntity<byte[]> resp = controller.mergeMultiplePagesIntoOne(req);
ResponseEntity<StreamingResponseBody> resp = controller.mergeMultiplePagesIntoOne(req);
Assertions.assertEquals(HttpStatus.OK, resp.getStatusCode());
Assertions.assertEquals(MediaType.APPLICATION_PDF, resp.getHeaders().getContentType());
Assertions.assertNotNull(resp.getBody());
Assertions.assertTrue(resp.getBody().length > 0);
Assertions.assertTrue(drainBody(resp).length > 0);
}
@Test
@@ -112,7 +145,7 @@ class MultiPageLayoutControllerTest {
req.setAddBorder(Boolean.TRUE);
req.setFileInput(fileNoExt);
ResponseEntity<byte[]> resp = controller.mergeMultiplePagesIntoOne(req);
ResponseEntity<StreamingResponseBody> resp = controller.mergeMultiplePagesIntoOne(req);
Assertions.assertEquals(
"name_multi_page_layout.pdf",
resp.getHeaders().getContentDisposition().getFilename());
@@ -2,16 +2,22 @@ package stirling.software.SPDF.controller.api;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -24,17 +30,47 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.general.OverlayPdfsRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class PdfOverlayControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private PdfOverlayController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private byte[] createPdf(int numPages) throws IOException {
try (PDDocument doc = new PDDocument()) {
for (int i = 0; i < numPages; i++) {
@@ -71,12 +107,12 @@ class PdfOverlayControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(((MultipartFile) inv.getArgument(0)).getBytes()));
ResponseEntity<byte[]> response = controller.overlayPdfs(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayPdfs(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -105,7 +141,7 @@ class PdfOverlayControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(((MultipartFile) inv.getArgument(0)).getBytes()));
ResponseEntity<byte[]> response = controller.overlayPdfs(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayPdfs(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -137,7 +173,7 @@ class PdfOverlayControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(((MultipartFile) inv.getArgument(0)).getBytes()));
ResponseEntity<byte[]> response = controller.overlayPdfs(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayPdfs(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -168,7 +204,7 @@ class PdfOverlayControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(((MultipartFile) inv.getArgument(0)).getBytes()));
ResponseEntity<byte[]> response = controller.overlayPdfs(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayPdfs(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -258,7 +294,7 @@ class PdfOverlayControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(((MultipartFile) inv.getArgument(0)).getBytes()));
ResponseEntity<byte[]> response = controller.overlayPdfs(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayPdfs(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -291,7 +327,7 @@ class PdfOverlayControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(((MultipartFile) inv.getArgument(0)).getBytes()));
ResponseEntity<byte[]> response = controller.overlayPdfs(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayPdfs(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -1,12 +1,16 @@
package stirling.software.SPDF.controller.api;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -15,18 +19,38 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.SPDF.model.api.general.RearrangePagesRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class RearrangePagesPDFControllerTest {
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private RearrangePagesPDFController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private MockMultipartFile createMockPdf() {
return new MockMultipartFile(
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, new byte[] {1, 2, 3});
@@ -43,7 +67,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(mockDoc);
when(mockDoc.getNumberOfPages()).thenReturn(5);
ResponseEntity<byte[]> response = controller.deletePages(request);
ResponseEntity<StreamingResponseBody> response = controller.deletePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -73,7 +97,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -103,7 +127,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
verify(mockNewDoc).addPage(page1);
@@ -131,7 +155,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
verify(mockNewDoc).addPage(page0);
@@ -157,7 +181,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -184,7 +208,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -208,7 +232,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -232,7 +256,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -260,7 +284,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -284,7 +308,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
// 2 pages * 3 duplicates = 6 addPage calls
@@ -309,7 +333,7 @@ class RearrangePagesPDFControllerTest {
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(mockDoc))
.thenReturn(mockNewDoc);
ResponseEntity<byte[]> response = controller.rearrangePages(request);
ResponseEntity<StreamingResponseBody> response = controller.rearrangePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -1,15 +1,20 @@
package stirling.software.SPDF.controller.api;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -18,17 +23,37 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.general.RotatePDFRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
public class RotationControllerTest {
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private RotationController rotationController;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
public void testRotatePDF() throws IOException {
// Create a mock file
@@ -50,7 +75,7 @@ public class RotationControllerTest {
when(mockPage.getRotation()).thenReturn(0);
// Act
ResponseEntity<byte[]> response = rotationController.rotatePDF(request);
ResponseEntity<StreamingResponseBody> response = rotationController.rotatePDF(request);
// Assert
verify(mockPage).setRotation(90);
@@ -2,8 +2,10 @@ package stirling.software.SPDF.controller.api;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -11,6 +13,7 @@ import java.nio.file.Path;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -21,17 +24,47 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.general.ScalePagesRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class ScalePagesControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private ScalePagesController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private byte[] createRealPdf(PDRectangle pageSize, int numPages) throws IOException {
try (PDDocument doc = new PDDocument()) {
for (int i = 0; i < numPages; i++) {
@@ -68,12 +101,12 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -90,7 +123,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -110,7 +143,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -130,7 +163,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -150,7 +183,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -187,7 +220,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -207,7 +240,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -248,7 +281,7 @@ class ScalePagesControllerTest {
setupFactory();
ResponseEntity<byte[]> response = controller.scalePages(request);
ResponseEntity<StreamingResponseBody> response = controller.scalePages(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -4,8 +4,11 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -31,6 +34,7 @@ import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
@@ -44,6 +48,18 @@ class SplitPdfBySectionsControllerTest {
@BeforeEach
void setUp() throws IOException {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
when(tempFileManager.createTempFile(anyString()))
.thenAnswer(
inv -> {
@@ -5,7 +5,10 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
@@ -19,6 +22,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
@@ -29,6 +33,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.model.api.converters.ConvertEbookToPdfRequest;
@@ -37,11 +42,22 @@ import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.ProcessExecutor;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.util.ProcessExecutor.Processes;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertEbookToPDFControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@@ -49,6 +65,22 @@ class ConvertEbookToPDFControllerTest {
@InjectMocks private ConvertEbookToPDFController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void convertEbookToPdf_buildsCalibreCommandAndCleansUp() throws Exception {
when(endpointConfiguration.isGroupEnabled("Calibre")).thenReturn(true);
@@ -113,16 +145,14 @@ class ConvertEbookToPDFControllerTest {
return execResult;
});
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("result".getBytes());
wr.when(
() ->
WebResponseUtils.pdfDocToWebResponse(
mockDocument, "ebook_convertedToPDF.pdf"))
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("result".getBytes());
wr.when(() -> WebResponseUtils.pdfFileToWebResponse(any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
gu.when(() -> GeneralUtils.generateFilename("ebook.epub", "_convertedToPDF.pdf"))
.thenReturn("ebook_convertedToPDF.pdf");
ResponseEntity<byte[]> response = controller.convertEbookToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEbookToPdf(request);
assertSame(expectedResponse, response);
@@ -232,14 +262,11 @@ class ConvertEbookToPDFControllerTest {
gu.when(() -> GeneralUtils.optimizePdfWithGhostscript(Mockito.any(byte[].class)))
.thenReturn(optimizedBytes);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(optimizedBytes);
wr.when(
() ->
WebResponseUtils.bytesToWebResponse(
optimizedBytes, "ebook_convertedToPDF.pdf"))
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(optimizedBytes);
wr.when(() -> WebResponseUtils.pdfFileToWebResponse(any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertEbookToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEbookToPdf(request);
assertSame(expectedResponse, response);
gu.verify(() -> GeneralUtils.optimizePdfWithGhostscript(Mockito.any(byte[].class)));
@@ -4,12 +4,18 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -21,17 +27,29 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.converters.EmlToPdfRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.CustomHtmlSanitizer;
import stirling.software.common.util.EmlToPdf;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertEmlToPDFTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private RuntimePathConfig runtimePathConfig;
@@ -40,35 +58,51 @@ class ConvertEmlToPDFTest {
@InjectMocks private ConvertEmlToPDF controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void convertEmlToPdf_emptyFileReturnsBadRequest() {
void convertEmlToPdf_emptyFileReturnsBadRequest() throws java.io.IOException {
MockMultipartFile emptyFile =
new MockMultipartFile("fileInput", "test.eml", "message/rfc822", new byte[0]);
EmlToPdfRequest request = new EmlToPdfRequest();
request.setFileInput(emptyFile);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8)
new String(drainBody(response), StandardCharsets.UTF_8)
.contains("No file provided"));
}
@Test
void convertEmlToPdf_nullFilenameReturnsBadRequest() {
void convertEmlToPdf_nullFilenameReturnsBadRequest() throws java.io.IOException {
MockMultipartFile file =
new MockMultipartFile("fileInput", null, "message/rfc822", "content".getBytes());
EmlToPdfRequest request = new EmlToPdfRequest();
request.setFileInput(file);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8).contains("valid filename"));
new String(drainBody(response), StandardCharsets.UTF_8).contains("valid filename"));
}
@Test
@@ -79,24 +113,24 @@ class ConvertEmlToPDFTest {
EmlToPdfRequest request = new EmlToPdfRequest();
request.setFileInput(file);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
@Test
void convertEmlToPdf_invalidFileTypeReturnsBadRequest() {
void convertEmlToPdf_invalidFileTypeReturnsBadRequest() throws java.io.IOException {
MockMultipartFile file =
new MockMultipartFile("fileInput", "test.txt", "text/plain", "content".getBytes());
EmlToPdfRequest request = new EmlToPdfRequest();
request.setFileInput(file);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8)
new String(drainBody(response), StandardCharsets.UTF_8)
.contains("valid EML or MSG"));
}
@@ -112,7 +146,7 @@ class ConvertEmlToPDFTest {
when(runtimePathConfig.getWeasyPrintPath()).thenReturn("/usr/bin/weasyprint");
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(pdfBytes);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(pdfBytes);
try (MockedStatic<EmlToPdf> emlMock = Mockito.mockStatic(EmlToPdf.class);
MockedStatic<WebResponseUtils> wrMock =
@@ -132,14 +166,14 @@ class ConvertEmlToPDFTest {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
pdfBytes, "test.eml.pdf", MediaType.APPLICATION_PDF))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertArrayEquals(pdfBytes, response.getBody());
assertArrayEquals(pdfBytes, drainBody(response));
}
}
@@ -154,8 +188,8 @@ class ConvertEmlToPDFTest {
request.setFileInput(file);
request.setDownloadHtml(true);
ResponseEntity<byte[]> expectedResponse =
ResponseEntity.ok(htmlContent.getBytes(StandardCharsets.UTF_8));
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk(htmlContent.getBytes(StandardCharsets.UTF_8));
try (MockedStatic<EmlToPdf> emlMock = Mockito.mockStatic(EmlToPdf.class);
MockedStatic<WebResponseUtils> wrMock =
@@ -171,13 +205,11 @@ class ConvertEmlToPDFTest {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
htmlContent.getBytes(StandardCharsets.UTF_8),
"test.eml.html",
MediaType.TEXT_HTML))
WebResponseUtils.fileToWebResponse(
any(TempFile.class), anyString(), any(MediaType.class)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -203,11 +235,11 @@ class ConvertEmlToPDFTest {
eq(customHtmlSanitizer)))
.thenThrow(new IOException("Parse error"));
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8)
new String(drainBody(response), StandardCharsets.UTF_8)
.contains("HTML conversion failed"));
}
}
@@ -231,11 +263,11 @@ class ConvertEmlToPDFTest {
any(), any(), any(), any(), any(), any(), any()))
.thenReturn(null);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8)
new String(drainBody(response), StandardCharsets.UTF_8)
.contains("empty output"));
}
}
@@ -255,7 +287,7 @@ class ConvertEmlToPDFTest {
when(runtimePathConfig.getWeasyPrintPath()).thenReturn("/usr/bin/weasyprint");
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(pdfBytes);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(pdfBytes);
try (MockedStatic<EmlToPdf> emlMock = Mockito.mockStatic(EmlToPdf.class);
MockedStatic<WebResponseUtils> wrMock =
@@ -269,13 +301,11 @@ class ConvertEmlToPDFTest {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
any(String.class),
any(MediaType.class)))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -300,11 +330,12 @@ class ConvertEmlToPDFTest {
any(), any(), any(), any(), any(), any(), any()))
.thenThrow(new InterruptedException("interrupted"));
ResponseEntity<byte[]> response = controller.convertEmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertEmlToPdf(request);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8).contains("interrupted"));
new String(drainBody(response), StandardCharsets.UTF_8)
.contains("interrupted"));
}
}
}
@@ -3,9 +3,16 @@ package stirling.software.SPDF.controller.api.converters;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.nio.file.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -16,6 +23,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.converters.HTMLToPdfRequest;
@@ -23,11 +31,22 @@ import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.CustomHtmlSanitizer;
import stirling.software.common.util.FileToPdf;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertHtmlToPDFTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private RuntimePathConfig runtimePathConfig;
@@ -36,6 +55,22 @@ class ConvertHtmlToPDFTest {
@InjectMocks private ConvertHtmlToPDF controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void htmlToPdf_nullFileInputThrows() {
HTMLToPdfRequest request = new HTMLToPdfRequest();
@@ -69,7 +104,7 @@ class ConvertHtmlToPDFTest {
when(pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes))
.thenReturn(processedPdf);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(processedPdf);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(processedPdf);
try (MockedStatic<FileToPdf> ftpMock = Mockito.mockStatic(FileToPdf.class);
MockedStatic<GeneralUtils> guMock = Mockito.mockStatic(GeneralUtils.class);
@@ -90,10 +125,13 @@ class ConvertHtmlToPDFTest {
guMock.when(() -> GeneralUtils.generateFilename("test.html", ".pdf"))
.thenReturn("test.pdf");
wrMock.when(() -> WebResponseUtils.bytesToWebResponse(processedPdf, "test.pdf"))
wrMock.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.HtmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.HtmlToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -114,7 +152,7 @@ class ConvertHtmlToPDFTest {
when(pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes))
.thenReturn(processedPdf);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(processedPdf);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(processedPdf);
try (MockedStatic<FileToPdf> ftpMock = Mockito.mockStatic(FileToPdf.class);
MockedStatic<GeneralUtils> guMock = Mockito.mockStatic(GeneralUtils.class);
@@ -135,10 +173,13 @@ class ConvertHtmlToPDFTest {
guMock.when(() -> GeneralUtils.generateFilename("archive.zip", ".pdf"))
.thenReturn("archive.pdf");
wrMock.when(() -> WebResponseUtils.bytesToWebResponse(processedPdf, "archive.pdf"))
wrMock.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.HtmlToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.HtmlToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -14,6 +14,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
@@ -25,6 +26,16 @@ import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertImgPDFControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@@ -4,10 +4,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.nio.file.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -18,6 +25,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.GeneralFile;
@@ -25,11 +33,22 @@ import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.CustomHtmlSanitizer;
import stirling.software.common.util.FileToPdf;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertMarkdownToPdfTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private RuntimePathConfig runtimePathConfig;
@@ -38,6 +57,22 @@ class ConvertMarkdownToPdfTest {
@InjectMocks private ConvertMarkdownToPdf controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void markdownToPdf_nullFileInputThrows() {
GeneralFile generalFile = new GeneralFile();
@@ -71,7 +106,7 @@ class ConvertMarkdownToPdfTest {
when(pdfDocumentFactory.createNewBytesBasedOnOldDocument(any(byte[].class)))
.thenReturn(processedPdf);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(processedPdf);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(processedPdf);
try (MockedStatic<FileToPdf> ftpMock = Mockito.mockStatic(FileToPdf.class);
MockedStatic<GeneralUtils> guMock = Mockito.mockStatic(GeneralUtils.class);
@@ -92,10 +127,13 @@ class ConvertMarkdownToPdfTest {
guMock.when(() -> GeneralUtils.generateFilename("readme.md", ".pdf"))
.thenReturn("readme.pdf");
wrMock.when(() -> WebResponseUtils.bytesToWebResponse(processedPdf, "readme.pdf"))
wrMock.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.markdownToPdf(generalFile);
ResponseEntity<StreamingResponseBody> response = controller.markdownToPdf(generalFile);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -3,12 +3,15 @@ package stirling.software.SPDF.controller.api.converters;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -18,6 +21,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
@@ -29,6 +33,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.model.api.converters.ConvertPdfToEpubRequest;
@@ -38,10 +43,21 @@ import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.ProcessExecutor;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.util.ProcessExecutor.Processes;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class ConvertPDFToEpubControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
private static final MediaType EPUB_MEDIA_TYPE = MediaType.valueOf("application/epub+zip");
@@ -50,6 +66,22 @@ class ConvertPDFToEpubControllerTest {
@InjectMocks private ConvertPDFToEpubController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void convertPdfToEpub_buildsGoldenCommandAndCleansUp() throws Exception {
when(endpointConfiguration.isGroupEnabled("Calibre")).thenReturn(true);
@@ -110,7 +142,7 @@ class ConvertPDFToEpubControllerTest {
gu.when(() -> GeneralUtils.generateFilename("novel.pdf", "_convertedToEPUB.epub"))
.thenReturn("novel_convertedToEPUB.epub");
ResponseEntity<byte[]> response = controller.convertPdfToEpub(request);
ResponseEntity<StreamingResponseBody> response = controller.convertPdfToEpub(request);
List<String> command = commandCaptor.getValue();
assertEquals(13, command.size());
@@ -134,7 +166,7 @@ class ConvertPDFToEpubControllerTest {
assertEquals(
"novel_convertedToEPUB.epub",
response.getHeaders().getContentDisposition().getFilename());
assertEquals("epub", new String(response.getBody(), StandardCharsets.UTF_8));
assertEquals("epub", new String(drainBody(response), StandardCharsets.UTF_8));
verify(tempFileManager).deleteTempDirectory(workingDir);
assertEquals(workingDir, deletedDir.get());
@@ -202,7 +234,7 @@ class ConvertPDFToEpubControllerTest {
gu.when(() -> GeneralUtils.generateFilename("story.pdf", "_convertedToEPUB.epub"))
.thenReturn("story_convertedToEPUB.epub");
ResponseEntity<byte[]> response = controller.convertPdfToEpub(request);
ResponseEntity<StreamingResponseBody> response = controller.convertPdfToEpub(request);
List<String> command = commandCaptor.getValue();
assertTrue(command.stream().noneMatch(arg -> "--chapter".equals(arg)));
@@ -220,7 +252,7 @@ class ConvertPDFToEpubControllerTest {
assertEquals(
"story_convertedToEPUB.epub",
response.getHeaders().getContentDisposition().getFilename());
assertEquals("epub", new String(response.getBody(), StandardCharsets.UTF_8));
assertEquals("epub", new String(drainBody(response), StandardCharsets.UTF_8));
} finally {
deleteIfExists(workingDir);
}
@@ -287,7 +319,7 @@ class ConvertPDFToEpubControllerTest {
gu.when(() -> GeneralUtils.generateFilename("book.pdf", "_convertedToAZW3.azw3"))
.thenReturn("book_convertedToAZW3.azw3");
ResponseEntity<byte[]> response = controller.convertPdfToEpub(request);
ResponseEntity<StreamingResponseBody> response = controller.convertPdfToEpub(request);
List<String> command = commandCaptor.getValue();
assertEquals("ebook-convert", command.get(0));
@@ -308,7 +340,7 @@ class ConvertPDFToEpubControllerTest {
assertEquals(
"book_convertedToAZW3.azw3",
response.getHeaders().getContentDisposition().getFilename());
assertEquals("azw3", new String(response.getBody(), StandardCharsets.UTF_8));
assertEquals("azw3", new String(drainBody(response), StandardCharsets.UTF_8));
verify(tempFileManager).deleteTempDirectory(workingDir);
} finally {
@@ -2,11 +2,17 @@ package stirling.software.SPDF.controller.api.converters;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -17,18 +23,38 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class ConvertPDFToExcelControllerTest {
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private ConvertPDFToExcelController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void pdfToExcel_noTablesReturnsNoContent() throws Exception {
MockMultipartFile pdfFile =
@@ -55,7 +81,7 @@ class ConvertPDFToExcelControllerTest {
Mockito.eq(true)))
.thenReturn(List.of(1));
ResponseEntity<byte[]> response = controller.pdfToExcel(request);
ResponseEntity<StreamingResponseBody> response = controller.pdfToExcel(request);
// tabula may or may not find tables in an empty page
assertNotNull(response);
@@ -4,10 +4,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -18,6 +24,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest;
import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest;
@@ -27,11 +34,22 @@ import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.PDFToFile;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertPDFToOfficeTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@@ -39,6 +57,22 @@ class ConvertPDFToOfficeTest {
@InjectMocks private ConvertPDFToOffice controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private MockMultipartFile createPdfFile() {
return new MockMultipartFile(
"fileInput", "document.pdf", "application/pdf", "pdf-content".getBytes());
@@ -51,7 +85,8 @@ class ConvertPDFToOfficeTest {
request.setFileInput(pdfFile);
request.setOutputFormat("pptx");
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("pptx-content".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("pptx-content".getBytes());
try (MockedStatic<PDFToFile> mock =
Mockito.mockStatic(PDFToFile.class, Mockito.CALLS_REAL_METHODS)) {
@@ -80,7 +115,8 @@ class ConvertPDFToOfficeTest {
realDoc.addPage(new org.apache.pdfbox.pdmodel.PDPage());
when(pdfDocumentFactory.load(pdfFile)).thenReturn(realDoc);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("text content".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("text content".getBytes());
try (MockedStatic<GeneralUtils> guMock = Mockito.mockStatic(GeneralUtils.class);
MockedStatic<WebResponseUtils> wrMock =
@@ -91,13 +127,12 @@ class ConvertPDFToOfficeTest {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
eq("document.txt"),
eq(MediaType.TEXT_PLAIN)))
WebResponseUtils.fileToWebResponse(
any(TempFile.class), anyString(), any(MediaType.class)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.processPdfToRTForTXT(request);
ResponseEntity<StreamingResponseBody> response =
controller.processPdfToRTForTXT(request);
assertSame(expectedResponse, response);
}
@@ -4,34 +4,67 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.service.PdfJsonConversionService;
import stirling.software.common.model.api.GeneralFile;
import stirling.software.common.model.api.PDFFile;
import stirling.software.common.util.WebResponseUtils;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class ConvertPdfJsonControllerTest {
@Mock private PdfJsonConversionService pdfJsonConversionService;
@Mock private TempFileManager tempFileManager;
@InjectMocks private ConvertPdfJsonController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Test
void convertPdfToJson_nullFileInputThrows() {
PDFFile request = new PDFFile();
@@ -51,19 +84,11 @@ class ConvertPdfJsonControllerTest {
when(pdfJsonConversionService.convertPdfToJson(pdfFile, false)).thenReturn(jsonBytes);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(jsonBytes);
ResponseEntity<StreamingResponseBody> response =
controller.convertPdfToJson(request, false);
try (MockedStatic<WebResponseUtils> wrMock = Mockito.mockStatic(WebResponseUtils.class)) {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
jsonBytes, "doc.json", MediaType.APPLICATION_JSON))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertPdfToJson(request, false);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
}
@Test
@@ -77,20 +102,10 @@ class ConvertPdfJsonControllerTest {
when(pdfJsonConversionService.convertPdfToJson(pdfFile, true)).thenReturn(jsonBytes);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(jsonBytes);
ResponseEntity<StreamingResponseBody> response = controller.convertPdfToJson(request, true);
try (MockedStatic<WebResponseUtils> wrMock = Mockito.mockStatic(WebResponseUtils.class)) {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
jsonBytes, "doc.json", MediaType.APPLICATION_JSON))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertPdfToJson(request, true);
assertEquals(HttpStatus.OK, response.getStatusCode());
verify(pdfJsonConversionService).convertPdfToJson(pdfFile, true);
}
assertEquals(HttpStatus.OK, response.getStatusCode());
verify(pdfJsonConversionService).convertPdfToJson(pdfFile, true);
}
@Test
@@ -112,16 +127,10 @@ class ConvertPdfJsonControllerTest {
when(pdfJsonConversionService.convertJsonToPdf(jsonFile)).thenReturn(pdfBytes);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(pdfBytes);
ResponseEntity<StreamingResponseBody> response = controller.convertJsonToPdf(request);
try (MockedStatic<WebResponseUtils> wrMock = Mockito.mockStatic(WebResponseUtils.class)) {
wrMock.when(() -> WebResponseUtils.bytesToWebResponse(pdfBytes, "doc.pdf"))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertJsonToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
}
@Test
@@ -144,7 +153,7 @@ class ConvertPdfJsonControllerTest {
when(pdfJsonConversionService.extractDocumentMetadata(eq(pdfFile), any(String.class)))
.thenReturn(jsonBytes);
ResponseEntity<byte[]> response = controller.extractPdfMetadata(request);
ResponseEntity<StreamingResponseBody> response = controller.extractPdfMetadata(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(MediaType.APPLICATION_JSON, response.getHeaders().getContentType());
@@ -168,19 +177,10 @@ class ConvertPdfJsonControllerTest {
when(pdfJsonConversionService.extractSinglePage(jobId, 1)).thenReturn(jsonBytes);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(jsonBytes);
ResponseEntity<StreamingResponseBody> response = controller.extractSinglePage(jobId, 1);
try (MockedStatic<WebResponseUtils> wrMock = Mockito.mockStatic(WebResponseUtils.class)) {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
jsonBytes, "page_1.json", MediaType.APPLICATION_JSON))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.extractSinglePage(jobId, 1);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
}
@Test
@@ -190,20 +190,9 @@ class ConvertPdfJsonControllerTest {
when(pdfJsonConversionService.extractPageFonts(jobId, 1)).thenReturn(jsonBytes);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(jsonBytes);
ResponseEntity<StreamingResponseBody> response = controller.extractPageFonts(jobId, 1);
try (MockedStatic<WebResponseUtils> wrMock = Mockito.mockStatic(WebResponseUtils.class)) {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
jsonBytes,
"page_fonts_1.json",
MediaType.APPLICATION_JSON))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.extractPageFonts(jobId, 1);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
}
}
@@ -3,11 +3,17 @@ package stirling.software.SPDF.controller.api.converters;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -16,20 +22,31 @@ import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.converters.SvgToPdfRequest;
import stirling.software.SPDF.utils.SvgToPdf;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.SvgSanitizer;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ConvertSvgToPDFTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private SvgSanitizer svgSanitizer;
@@ -37,16 +54,32 @@ class ConvertSvgToPDFTest {
@InjectMocks private ConvertSvgToPDF controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
@Test
void convertSvgToPdf_nullFilesReturnsBadRequest() {
void convertSvgToPdf_nullFilesReturnsBadRequest() throws java.io.IOException {
SvgToPdfRequest request = new SvgToPdfRequest();
request.setFileInput(null);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(
new String(response.getBody(), StandardCharsets.UTF_8)
new String(drainBody(response), StandardCharsets.UTF_8)
.contains("No files provided"));
}
@@ -55,7 +88,7 @@ class ConvertSvgToPDFTest {
SvgToPdfRequest request = new SvgToPdfRequest();
request.setFileInput(new MockMultipartFile[0]);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
@@ -69,10 +102,11 @@ class ConvertSvgToPDFTest {
request.setFileInput(new MockMultipartFile[] {txtFile});
request.setCombineIntoSinglePdf(false);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(new String(response.getBody(), StandardCharsets.UTF_8).contains("No valid SVG"));
assertTrue(
new String(drainBody(response), StandardCharsets.UTF_8).contains("No valid SVG"));
}
@Test
@@ -84,7 +118,7 @@ class ConvertSvgToPDFTest {
request.setFileInput(new MockMultipartFile[] {emptyFile});
request.setCombineIntoSinglePdf(false);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
@@ -107,7 +141,7 @@ class ConvertSvgToPDFTest {
when(pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes))
.thenReturn(processedPdf);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(processedPdf);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(processedPdf);
try (MockedStatic<SvgToPdf> svgMock = Mockito.mockStatic(SvgToPdf.class);
MockedStatic<GeneralUtils> guMock = Mockito.mockStatic(GeneralUtils.class);
@@ -121,11 +155,11 @@ class ConvertSvgToPDFTest {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
processedPdf, "drawing.pdf", MediaType.APPLICATION_PDF))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -154,7 +188,7 @@ class ConvertSvgToPDFTest {
when(pdfDocumentFactory.createNewBytesBasedOnOldDocument(combinedPdf))
.thenReturn(processedPdf);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(processedPdf);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(processedPdf);
try (MockedStatic<SvgToPdf> svgMock = Mockito.mockStatic(SvgToPdf.class);
MockedStatic<GeneralUtils> guMock = Mockito.mockStatic(GeneralUtils.class);
@@ -168,13 +202,11 @@ class ConvertSvgToPDFTest {
wrMock.when(
() ->
WebResponseUtils.bytesToWebResponse(
processedPdf,
"a_combined.pdf",
MediaType.APPLICATION_PDF))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -189,7 +221,7 @@ class ConvertSvgToPDFTest {
request.setFileInput(new MockMultipartFile[] {nullNameFile});
request.setCombineIntoSinglePdf(false);
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
@@ -206,7 +238,7 @@ class ConvertSvgToPDFTest {
when(svgSanitizer.sanitize(svgContent)).thenThrow(new IOException("sanitization error"));
ResponseEntity<byte[]> response = controller.convertSvgToPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.convertSvgToPdf(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
@@ -4,9 +4,10 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -34,6 +35,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
import stirling.software.common.configuration.RuntimePathConfig;
@@ -43,13 +45,25 @@ import stirling.software.common.util.GeneralUtils;
import stirling.software.common.util.ProcessExecutor;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.util.ProcessExecutor.Processes;
import stirling.software.common.util.WebResponseUtils;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
public class ConvertWebsiteToPdfTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
private static final Pattern PDF_FILENAME_PATTERN = Pattern.compile("[A-Za-z0-9_]+\\.pdf");
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private RuntimePathConfig runtimePathConfig;
@Mock private TempFileManager tempFileManager;
private ApplicationProperties applicationProperties;
private ConvertWebsiteToPDF sut;
@@ -58,6 +72,18 @@ public class ConvertWebsiteToPdfTest {
@BeforeEach
void setUp() throws Exception {
mocks = MockitoAnnotations.openMocks(this);
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
// Enable feature (adjust structure for your project if necessary)
applicationProperties = new ApplicationProperties();
@@ -68,7 +94,12 @@ public class ConvertWebsiteToPdfTest {
when(pdfDocumentFactory.load(any(File.class))).thenReturn(new PDDocument());
// Build SUT
sut = new ConvertWebsiteToPDF(pdfDocumentFactory, runtimePathConfig, applicationProperties);
sut =
new ConvertWebsiteToPDF(
pdfDocumentFactory,
runtimePathConfig,
applicationProperties,
tempFileManager);
// Provide RequestContext for ServletUriComponentsBuilder
MockHttpServletRequest req = new MockHttpServletRequest();
@@ -172,38 +203,29 @@ public class ConvertWebsiteToPdfTest {
request.setUrlInput("https://example.com");
try (MockedStatic<ProcessExecutor> pe = Mockito.mockStatic(ProcessExecutor.class);
MockedStatic<WebResponseUtils> wr = Mockito.mockStatic(WebResponseUtils.class);
MockedStatic<GeneralUtils> gu = Mockito.mockStatic(GeneralUtils.class);
MockedStatic<HttpClient> httpClient = mockHttpClientReturning("<html></html>")) {
// Force URL checks to be positive
gu.when(() -> GeneralUtils.isValidURL("https://example.com")).thenReturn(true);
gu.when(() -> GeneralUtils.isURLReachable("https://example.com")).thenReturn(true);
gu.when(() -> GeneralUtils.convertToFileName(anyString())).thenReturn("example_com");
gu.when(() -> GeneralUtils.generateFilename(anyString(), anyString()))
.thenAnswer(inv -> inv.<String>getArgument(0) + inv.<String>getArgument(1));
// correct ProcessExecutor!
ProcessExecutor mockExec = Mockito.mock(ProcessExecutor.class);
pe.when(() -> ProcessExecutor.getInstance(Processes.WEASYPRINT)).thenReturn(mockExec);
@SuppressWarnings("unchecked")
ArgumentCaptor<List<String>> cmdCaptor = ArgumentCaptor.forClass(List.class);
// Return value of correct type
ProcessExecutorResult dummyResult = Mockito.mock(ProcessExecutorResult.class);
when(mockExec.runCommandWithOutputHandling(cmdCaptor.capture()))
.thenReturn(dummyResult);
ResponseEntity<byte[]> fakeResponse = ResponseEntity.ok(new byte[0]);
wr.when(
() ->
WebResponseUtils.baosToWebResponse(
any(ByteArrayOutputStream.class), any()))
.thenReturn(fakeResponse);
// Act
ResponseEntity<?> resp = sut.urlToPdf(request);
// Assert Response OK
// Assert
assertNotNull(resp);
assertEquals(HttpStatus.OK, resp.getStatusCode());
// Assert WeasyPrint command correct
@@ -236,17 +258,19 @@ public class ConvertWebsiteToPdfTest {
try (MockedStatic<GeneralUtils> gu = Mockito.mockStatic(GeneralUtils.class);
MockedStatic<ProcessExecutor> pe = Mockito.mockStatic(ProcessExecutor.class);
MockedStatic<WebResponseUtils> wr = Mockito.mockStatic(WebResponseUtils.class);
MockedStatic<Files> files = Mockito.mockStatic(Files.class);
MockedStatic<HttpClient> httpClient = mockHttpClientReturning("<html></html>")) {
// Force URL checks to be positive
gu.when(() -> GeneralUtils.isValidURL("https://example.com")).thenReturn(true);
gu.when(() -> GeneralUtils.isURLReachable("https://example.com")).thenReturn(true);
gu.when(() -> GeneralUtils.convertToFileName(anyString())).thenReturn("example_com");
gu.when(() -> GeneralUtils.generateFilename(anyString(), anyString()))
.thenAnswer(inv -> inv.<String>getArgument(0) + inv.<String>getArgument(1));
// Force temp files + provoke delete error
files.when(() -> Files.createTempFile("url_input_", ".html")).thenReturn(htmlTemp);
files.when(() -> Files.createTempFile("output_", ".pdf")).thenReturn(preCreatedTemp);
files.when(() -> Files.createTempFile(eq("test"), anyString()))
.thenReturn(preCreatedTemp);
files.when(
() ->
Files.writeString(
@@ -257,26 +281,20 @@ public class ConvertWebsiteToPdfTest {
files.when(() -> Files.deleteIfExists(htmlTemp)).thenReturn(true);
files.when(() -> Files.deleteIfExists(preCreatedTemp))
.thenThrow(new IOException("fail delete"));
files.when(() -> Files.exists(preCreatedTemp)).thenReturn(true); // for the assert
files.when(() -> Files.exists(preCreatedTemp)).thenReturn(true);
files.when(() -> Files.size(any(Path.class))).thenReturn(100L);
files.when(() -> Files.copy(any(Path.class), any(java.io.OutputStream.class)))
.thenReturn(0L);
files.when(() -> Files.newOutputStream(any(Path.class)))
.thenAnswer(inv -> new java.io.ByteArrayOutputStream());
// ProcessExecutor
ProcessExecutor mockExec = Mockito.mock(ProcessExecutor.class);
pe.when(() -> ProcessExecutor.getInstance(Processes.WEASYPRINT)).thenReturn(mockExec);
ProcessExecutorResult dummy = Mockito.mock(ProcessExecutorResult.class);
when(mockExec.runCommandWithOutputHandling(Mockito.<List>any())).thenReturn(dummy);
// WebResponseUtils
ResponseEntity<byte[]> fakeResponse = ResponseEntity.ok(new byte[0]);
wr.when(
() ->
WebResponseUtils.baosToWebResponse(
any(ByteArrayOutputStream.class), any()))
.thenReturn(fakeResponse);
// Act: should not throw and should return a Response
ResponseEntity<?> resp = assertDoesNotThrow(() -> sut.urlToPdf(request));
// Assert
assertNotNull(resp, "Response should not be null");
assertEquals(HttpStatus.OK, resp.getStatusCode());
assertTrue(
@@ -3,11 +3,13 @@ package stirling.software.SPDF.controller.api.converters;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import java.io.File;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -25,11 +27,13 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.model.api.converters.PdfVectorExportRequest;
import stirling.software.common.util.ProcessExecutor;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
@@ -44,6 +48,18 @@ class PdfVectorExportControllerTest {
@BeforeEach
void setup() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
when(tempFileManager.createTempFile(any()))
.thenAnswer(
invocation -> {
@@ -106,7 +122,8 @@ class PdfVectorExportControllerTest {
PdfVectorExportRequest request = new PdfVectorExportRequest();
request.setFileInput(file);
ResponseEntity<byte[]> response = controller.convertGhostscriptInputsToPdf(request);
ResponseEntity<StreamingResponseBody> response =
controller.convertGhostscriptInputsToPdf(request);
assertThat(response.getStatusCode()).isEqualTo(org.springframework.http.HttpStatus.OK);
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PDF);
@@ -123,11 +140,14 @@ class PdfVectorExportControllerTest {
PdfVectorExportRequest request = new PdfVectorExportRequest();
request.setFileInput(file);
ResponseEntity<byte[]> response = controller.convertGhostscriptInputsToPdf(request);
ResponseEntity<StreamingResponseBody> response =
controller.convertGhostscriptInputsToPdf(request);
assertThat(response.getStatusCode()).isEqualTo(org.springframework.http.HttpStatus.OK);
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PDF);
assertThat(response.getBody()).contains(content);
java.io.ByteArrayOutputStream baosVerify = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baosVerify);
assertThat(baosVerify.toByteArray()).contains(content);
}
@Test
@@ -17,6 +17,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.PDFComparisonAndCount;
import stirling.software.SPDF.model.api.PDFWithPageNums;
@@ -26,12 +27,24 @@ import stirling.software.SPDF.model.api.filter.PageRotationRequest;
import stirling.software.SPDF.model.api.filter.PageSizeRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.PdfUtils;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class FilterControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private FilterController filterController;
@@ -59,19 +72,22 @@ class FilterControllerTest {
PDDocument mockDoc = mock(PDDocument.class);
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDoc);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(new byte[] {1, 2, 3});
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(new byte[] {1, 2, 3});
try (MockedStatic<PdfUtils> pdfUtilsMock = mockStatic(PdfUtils.class);
MockedStatic<WebResponseUtils> webMock = mockStatic(WebResponseUtils.class)) {
pdfUtilsMock.when(() -> PdfUtils.hasText(mockDoc, "all", "hello")).thenReturn(true);
webMock.when(() -> WebResponseUtils.pdfDocToWebResponse(mockDoc, "test.pdf"))
webMock.when(
() ->
WebResponseUtils.pdfDocToWebResponse(
mockDoc, "test.pdf", tempFileManager))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> result = filterController.containsText(request);
ResponseEntity<StreamingResponseBody> result = filterController.containsText(request);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertArrayEquals(new byte[] {1, 2, 3}, result.getBody());
assertArrayEquals(new byte[] {1, 2, 3}, drainBody(result));
}
}
@@ -88,7 +104,7 @@ class FilterControllerTest {
try (MockedStatic<PdfUtils> pdfUtilsMock = mockStatic(PdfUtils.class)) {
pdfUtilsMock.when(() -> PdfUtils.hasText(mockDoc, "all", "missing")).thenReturn(false);
ResponseEntity<byte[]> result = filterController.containsText(request);
ResponseEntity<StreamingResponseBody> result = filterController.containsText(request);
assertEquals(HttpStatus.NO_CONTENT, result.getStatusCode());
assertNull(result.getBody());
@@ -106,19 +122,22 @@ class FilterControllerTest {
PDDocument mockDoc = mock(PDDocument.class);
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDoc);
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(new byte[] {4, 5, 6});
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(new byte[] {4, 5, 6});
try (MockedStatic<PdfUtils> pdfUtilsMock = mockStatic(PdfUtils.class);
MockedStatic<WebResponseUtils> webMock = mockStatic(WebResponseUtils.class)) {
pdfUtilsMock.when(() -> PdfUtils.hasImages(mockDoc, "all")).thenReturn(true);
webMock.when(() -> WebResponseUtils.pdfDocToWebResponse(mockDoc, "test.pdf"))
webMock.when(
() ->
WebResponseUtils.pdfDocToWebResponse(
mockDoc, "test.pdf", tempFileManager))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> result = filterController.containsImage(request);
ResponseEntity<StreamingResponseBody> result = filterController.containsImage(request);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertArrayEquals(new byte[] {4, 5, 6}, result.getBody());
assertArrayEquals(new byte[] {4, 5, 6}, drainBody(result));
}
}
@@ -134,7 +153,7 @@ class FilterControllerTest {
try (MockedStatic<PdfUtils> pdfUtilsMock = mockStatic(PdfUtils.class)) {
pdfUtilsMock.when(() -> PdfUtils.hasImages(mockDoc, "1")).thenReturn(false);
ResponseEntity<byte[]> result = filterController.containsImage(request);
ResponseEntity<StreamingResponseBody> result = filterController.containsImage(request);
assertEquals(HttpStatus.NO_CONTENT, result.getStatusCode());
}
@@ -2,10 +2,13 @@ package stirling.software.SPDF.controller.api.form;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
@@ -22,8 +25,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
@@ -31,8 +37,19 @@ import tools.jackson.databind.json.JsonMapper;
@ExtendWith(MockitoExtension.class)
@DisplayName("FormFillController Tests")
class FormFillControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
private ObjectMapper realObjectMapper;
@@ -40,6 +57,18 @@ class FormFillControllerTest {
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
realObjectMapper = JsonMapper.builder().build();
// Inject real ObjectMapper via reflection since @InjectMocks uses the mock
var field = FormFillController.class.getDeclaredField("objectMapper");
@@ -203,7 +232,8 @@ class FormFillControllerTest {
when(pdfDocumentFactory.load(eq(file))).thenReturn(doc);
byte[] payload = "{\"field1\":\"value1\"}".getBytes();
ResponseEntity<byte[]> response = controller.fillForm(file, payload, false);
ResponseEntity<StreamingResponseBody> response =
controller.fillForm(file, payload, false);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotNull();
@@ -216,7 +246,7 @@ class FormFillControllerTest {
PDDocument doc = createMinimalPdf();
when(pdfDocumentFactory.load(eq(file))).thenReturn(doc);
ResponseEntity<byte[]> response = controller.fillForm(file, null, false);
ResponseEntity<StreamingResponseBody> response = controller.fillForm(file, null, false);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -257,7 +287,7 @@ class FormFillControllerTest {
when(pdfDocumentFactory.load(eq(file))).thenReturn(doc);
byte[] payload = "[\"field1\"]".getBytes();
ResponseEntity<byte[]> response = controller.deleteFields(file, payload);
ResponseEntity<StreamingResponseBody> response = controller.deleteFields(file, payload);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -293,7 +323,8 @@ class FormFillControllerTest {
String json =
"[{\"targetName\":\"f1\",\"name\":null,\"label\":null,\"type\":null,"
+ "\"required\":null,\"multiSelect\":null,\"options\":null,\"defaultValue\":\"newVal\",\"tooltip\":null}]";
ResponseEntity<byte[]> response = controller.modifyFields(file, json.getBytes());
ResponseEntity<StreamingResponseBody> response =
controller.modifyFields(file, json.getBytes());
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -1,9 +1,12 @@
package stirling.software.SPDF.controller.api.misc;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -19,18 +22,32 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.misc.AddAttachmentRequest;
import stirling.software.SPDF.service.AttachmentServiceInterface;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class AttachmentControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private AttachmentServiceInterface pdfAttachmentService;
@Mock private TempFileManager tempFileManager;
@InjectMocks private AttachmentController attachmentController;
@@ -42,7 +59,19 @@ class AttachmentControllerTest {
private PDDocument modifiedMockDocument;
@BeforeEach
void setUp() {
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
pdfFile =
new MockMultipartFile(
"fileInput",
@@ -71,8 +100,8 @@ class AttachmentControllerTest {
List<MultipartFile> attachments = List.of(attachment1, attachment2);
request.setAttachments(attachments);
request.setFileInput(pdfFile);
ResponseEntity<byte[]> expectedResponse =
ResponseEntity.ok("modified PDF content".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("modified PDF content".getBytes());
when(pdfDocumentFactory.load(request, false)).thenReturn(mockDocument);
when(pdfAttachmentService.addAttachment(mockDocument, attachments))
@@ -84,10 +113,13 @@ class AttachmentControllerTest {
.when(
() ->
WebResponseUtils.pdfDocToWebResponse(
eq(mockDocument), eq("test_with_attachments.pdf")))
any(PDDocument.class),
anyString(),
any(TempFileManager.class)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = attachmentController.addAttachments(request);
ResponseEntity<StreamingResponseBody> response =
attachmentController.addAttachments(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -102,8 +134,8 @@ class AttachmentControllerTest {
List<MultipartFile> attachments = List.of(attachment1);
request.setAttachments(attachments);
request.setFileInput(pdfFile);
ResponseEntity<byte[]> expectedResponse =
ResponseEntity.ok("modified PDF content".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("modified PDF content".getBytes());
when(pdfDocumentFactory.load(request, false)).thenReturn(mockDocument);
when(pdfAttachmentService.addAttachment(mockDocument, attachments))
@@ -115,10 +147,13 @@ class AttachmentControllerTest {
.when(
() ->
WebResponseUtils.pdfDocToWebResponse(
eq(mockDocument), eq("test_with_attachments.pdf")))
any(PDDocument.class),
anyString(),
any(TempFileManager.class)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = attachmentController.addAttachments(request);
ResponseEntity<StreamingResponseBody> response =
attachmentController.addAttachments(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -1,8 +1,10 @@
package stirling.software.SPDF.controller.api.misc;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -14,6 +16,7 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -24,17 +27,47 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.misc.ExtractHeaderRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class AutoRenameControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private AutoRenameController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private MockMultipartFile createPdfWithText(String text, float fontSize) throws IOException {
Path path = tempDir.resolve("test.pdf");
try (PDDocument doc = new PDDocument()) {
@@ -68,10 +101,10 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
String contentDisposition = response.getHeaders().getFirst("Content-Disposition");
assertThat(contentDisposition).contains(".pdf");
}
@@ -94,7 +127,7 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -107,7 +140,7 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -155,7 +188,7 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
// The largest font text should be used as title (URL-encoded in Content-Disposition)
@@ -173,7 +206,7 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
// Should fallback to original filename since header is too long
@@ -189,7 +222,7 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
// Special characters should be sanitized
@@ -215,7 +248,7 @@ class AutoRenameControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = controller.extractHeader(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -1,8 +1,10 @@
package stirling.software.SPDF.controller.api.misc;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -14,6 +16,7 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -24,17 +27,47 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class DecompressPdfControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private DecompressPdfController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private MockMultipartFile createRealPdf(String content) throws IOException {
Path path = tempDir.resolve("test.pdf");
try (PDDocument doc = new PDDocument()) {
@@ -64,12 +97,12 @@ class DecompressPdfControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.decompressPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.decompressPdf(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
// Verify the result is a valid PDF
try (PDDocument result = Loader.loadPDF(response.getBody())) {
try (PDDocument result = Loader.loadPDF(drainBody(response))) {
assertThat(result.getNumberOfPages()).isEqualTo(1);
}
}
@@ -83,10 +116,10 @@ class DecompressPdfControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.decompressPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.decompressPdf(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
}
@Test
@@ -114,7 +147,7 @@ class DecompressPdfControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.decompressPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.decompressPdf(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
String contentDisposition = response.getHeaders().getFirst("Content-Disposition");
@@ -150,10 +183,10 @@ class DecompressPdfControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.decompressPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.decompressPdf(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
try (PDDocument result = Loader.loadPDF(response.getBody())) {
try (PDDocument result = Loader.loadPDF(drainBody(response))) {
assertThat(result.getNumberOfPages()).isEqualTo(3);
}
}
@@ -167,11 +200,11 @@ class DecompressPdfControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.decompressPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.decompressPdf(request);
assertThat(response.getBody()).isNotNull();
// Decompressed PDF should generally be larger or equal to compressed
assertThat(response.getBody().length).isGreaterThan(0);
assertThat(drainBody(response).length).isGreaterThan(0);
}
@Test
@@ -183,7 +216,7 @@ class DecompressPdfControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.decompressPdf(request);
ResponseEntity<StreamingResponseBody> response = controller.decompressPdf(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -1,8 +1,10 @@
package stirling.software.SPDF.controller.api.misc;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -16,6 +18,7 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -26,17 +29,47 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.misc.FlattenRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class FlattenControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@TempDir Path tempDir;
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private FlattenController controller;
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
}
private MockMultipartFile createPdf() throws IOException {
Path path = tempDir.resolve("test.pdf");
try (PDDocument doc = new PDDocument()) {
@@ -65,10 +98,10 @@ class FlattenControllerTest {
PDDocument doc = Loader.loadPDF(file.getBytes());
when(pdfDocumentFactory.load(file)).thenReturn(doc);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
}
@Test
@@ -85,7 +118,7 @@ class FlattenControllerTest {
when(doc.getDocumentCatalog()).thenReturn(catalog);
when(catalog.getAcroForm()).thenReturn(null);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
verify(doc).close();
@@ -105,7 +138,7 @@ class FlattenControllerTest {
when(doc.getDocumentCatalog()).thenReturn(catalog);
when(catalog.getAcroForm()).thenReturn(form);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
verify(form).flatten();
@@ -137,10 +170,10 @@ class FlattenControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(doc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(doc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotEmpty();
assertThat(drainBody(response)).isNotEmpty();
}
@Test
@@ -155,7 +188,7 @@ class FlattenControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(doc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(doc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -173,7 +206,7 @@ class FlattenControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(doc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(doc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -191,7 +224,7 @@ class FlattenControllerTest {
when(pdfDocumentFactory.load(file)).thenReturn(doc);
when(pdfDocumentFactory.createNewDocumentBasedOnOldDocument(doc)).thenReturn(newDoc);
ResponseEntity<byte[]> response = controller.flatten(request);
ResponseEntity<StreamingResponseBody> response = controller.flatten(request);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@@ -2,11 +2,14 @@ package stirling.software.SPDF.controller.api.misc;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.imageio.ImageIO;
@@ -24,15 +27,29 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.misc.OverlayImageRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class OverlayImageControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private OverlayImageController controller;
@@ -41,6 +58,18 @@ class OverlayImageControllerTest {
@BeforeEach
void setUp() throws IOException {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
pdfFile =
new MockMultipartFile(
"fileInput",
@@ -79,12 +108,16 @@ class OverlayImageControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("result".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("result".getBytes());
mockedWebResponse
.when(() -> WebResponseUtils.bytesToWebResponse(any(byte[].class), anyString()))
.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.overlayImage(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayImage(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -103,7 +136,7 @@ class OverlayImageControllerTest {
when(pdfDocumentFactory.load(any(byte[].class))).thenThrow(new IOException("bad PDF"));
ResponseEntity<byte[]> response = controller.overlayImage(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayImage(request);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
@@ -124,12 +157,16 @@ class OverlayImageControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("result".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("result".getBytes());
mockedWebResponse
.when(() -> WebResponseUtils.bytesToWebResponse(any(byte[].class), anyString()))
.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.overlayImage(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayImage(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -152,12 +189,16 @@ class OverlayImageControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("result".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("result".getBytes());
mockedWebResponse
.when(() -> WebResponseUtils.bytesToWebResponse(any(byte[].class), anyString()))
.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.overlayImage(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayImage(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -180,13 +221,17 @@ class OverlayImageControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("result".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("result".getBytes());
mockedWebResponse
.when(() -> WebResponseUtils.bytesToWebResponse(any(byte[].class), anyString()))
.when(
() ->
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
// Should not throw - coordinates are passed to contentStream.drawImage
ResponseEntity<byte[]> response = controller.overlayImage(request);
ResponseEntity<StreamingResponseBody> response = controller.overlayImage(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -2,10 +2,13 @@ package stirling.software.SPDF.controller.api.misc;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -19,17 +22,31 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.misc.ReplaceAndInvertColorRequest;
import stirling.software.SPDF.service.misc.ReplaceAndInvertColorService;
import stirling.software.common.model.api.misc.HighContrastColorCombination;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ReplaceAndInvertColorControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private ReplaceAndInvertColorService replaceAndInvertColorService;
@Mock private TempFileManager tempFileManager;
@InjectMocks private ReplaceAndInvertColorController controller;
@@ -37,7 +54,19 @@ class ReplaceAndInvertColorControllerTest {
private ReplaceAndInvertColorRequest request;
@BeforeEach
void setUp() {
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
pdfFile =
new MockMultipartFile(
"fileInput",
@@ -67,17 +96,16 @@ class ReplaceAndInvertColorControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(resultBytes);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(resultBytes);
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
anyString(),
eq(MediaType.APPLICATION_PDF)))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.replaceAndInvertColor(request);
ResponseEntity<StreamingResponseBody> response =
controller.replaceAndInvertColor(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -104,17 +132,16 @@ class ReplaceAndInvertColorControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(resultBytes);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(resultBytes);
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
anyString(),
eq(MediaType.APPLICATION_PDF)))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.replaceAndInvertColor(request);
ResponseEntity<StreamingResponseBody> response =
controller.replaceAndInvertColor(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -139,17 +166,16 @@ class ReplaceAndInvertColorControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(resultBytes);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(resultBytes);
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
anyString(),
eq(MediaType.APPLICATION_PDF)))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = controller.replaceAndInvertColor(request);
ResponseEntity<StreamingResponseBody> response =
controller.replaceAndInvertColor(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -179,24 +205,18 @@ class ReplaceAndInvertColorControllerTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok(resultBytes);
ResponseEntity<StreamingResponseBody> expectedResponse = streamingOk(resultBytes);
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
contains("_inverted.pdf"),
eq(MediaType.APPLICATION_PDF)))
WebResponseUtils.pdfFileToWebResponse(
any(TempFile.class), anyString()))
.thenReturn(expectedResponse);
controller.replaceAndInvertColor(request);
mockedWebResponse.verify(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
contains("_inverted.pdf"),
eq(MediaType.APPLICATION_PDF)));
() -> WebResponseUtils.pdfFileToWebResponse(any(TempFile.class), anyString()));
}
}
}
@@ -1,9 +1,11 @@
package stirling.software.SPDF.controller.api.misc;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.nio.charset.StandardCharsets;
import java.io.File;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
@@ -21,15 +23,29 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
import stirling.software.common.util.WebResponseUtils;
@ExtendWith(MockitoExtension.class)
class ShowJavascriptTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private ShowJavascript showJavascript;
@@ -37,7 +53,19 @@ class ShowJavascriptTest {
private PDFFile request;
@BeforeEach
void setUp() {
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
pdfFile =
new MockMultipartFile(
"fileInput",
@@ -58,31 +86,25 @@ class ShowJavascriptTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("no js".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("no js".getBytes());
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
WebResponseUtils.fileToWebResponse(
any(TempFile.class),
eq("test.pdf.js"),
eq(MediaType.TEXT_PLAIN)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = showJavascript.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = showJavascript.extractHeader(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
// Verify the bytes passed contain the "does not contain" message
mockedWebResponse.verify(
() ->
WebResponseUtils.bytesToWebResponse(
argThat(
bytes -> {
String content =
new String(bytes, StandardCharsets.UTF_8);
return content.contains(
"does not contain Javascript");
}),
WebResponseUtils.fileToWebResponse(
any(TempFile.class),
eq("test.pdf.js"),
eq(MediaType.TEXT_PLAIN)));
}
@@ -107,30 +129,24 @@ class ShowJavascriptTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("js content".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("js content".getBytes());
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
WebResponseUtils.fileToWebResponse(
any(TempFile.class),
eq("test.pdf.js"),
eq(MediaType.TEXT_PLAIN)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = showJavascript.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = showJavascript.extractHeader(request);
assertNotNull(response);
// Verify the bytes passed contain the script content
mockedWebResponse.verify(
() ->
WebResponseUtils.bytesToWebResponse(
argThat(
bytes -> {
String content =
new String(bytes, StandardCharsets.UTF_8);
return content.contains("alert('hello');")
&& content.contains("Script1");
}),
WebResponseUtils.fileToWebResponse(
any(TempFile.class),
eq("test.pdf.js"),
eq(MediaType.TEXT_PLAIN)));
}
@@ -144,31 +160,24 @@ class ShowJavascriptTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("no js".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("no js".getBytes());
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
WebResponseUtils.fileToWebResponse(
any(TempFile.class),
anyString(),
eq(MediaType.TEXT_PLAIN)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = showJavascript.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = showJavascript.extractHeader(request);
assertNotNull(response);
mockedWebResponse.verify(
() ->
WebResponseUtils.bytesToWebResponse(
argThat(
bytes -> {
String content =
new String(bytes, StandardCharsets.UTF_8);
return content.contains(
"does not contain Javascript");
}),
anyString(),
eq(MediaType.TEXT_PLAIN)));
WebResponseUtils.fileToWebResponse(
any(TempFile.class), anyString(), eq(MediaType.TEXT_PLAIN)));
}
}
@@ -191,31 +200,24 @@ class ShowJavascriptTest {
try (MockedStatic<WebResponseUtils> mockedWebResponse =
mockStatic(WebResponseUtils.class)) {
ResponseEntity<byte[]> expectedResponse = ResponseEntity.ok("no js".getBytes());
ResponseEntity<StreamingResponseBody> expectedResponse =
streamingOk("no js".getBytes());
mockedWebResponse
.when(
() ->
WebResponseUtils.bytesToWebResponse(
any(byte[].class),
WebResponseUtils.fileToWebResponse(
any(TempFile.class),
anyString(),
eq(MediaType.TEXT_PLAIN)))
.thenReturn(expectedResponse);
ResponseEntity<byte[]> response = showJavascript.extractHeader(request);
ResponseEntity<StreamingResponseBody> response = showJavascript.extractHeader(request);
assertNotNull(response);
mockedWebResponse.verify(
() ->
WebResponseUtils.bytesToWebResponse(
argThat(
bytes -> {
String content =
new String(bytes, StandardCharsets.UTF_8);
return content.contains(
"does not contain Javascript");
}),
anyString(),
eq(MediaType.TEXT_PLAIN)));
WebResponseUtils.fileToWebResponse(
any(TempFile.class), anyString(), eq(MediaType.TEXT_PLAIN)));
}
}
@@ -2,8 +2,12 @@ package stirling.software.SPDF.controller.api.misc;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
@@ -14,22 +18,38 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class UnlockPDFFormsControllerTest {
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
private UnlockPDFFormsController controller;
private MockMultipartFile mockPdfFile;
@BeforeEach
void setUp() {
controller = new UnlockPDFFormsController(pdfDocumentFactory);
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
controller = new UnlockPDFFormsController(pdfDocumentFactory, tempFileManager);
mockPdfFile =
new MockMultipartFile(
"fileInput",
@@ -47,7 +67,7 @@ class UnlockPDFFormsControllerTest {
PDFFile file = new PDFFile();
file.setFileInput(mockPdfFile);
ResponseEntity<byte[]> response = controller.unlockPDFForms(file);
ResponseEntity<StreamingResponseBody> response = controller.unlockPDFForms(file);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -65,7 +85,7 @@ class UnlockPDFFormsControllerTest {
PDFFile file = new PDFFile();
file.setFileInput(mockPdfFile);
ResponseEntity<byte[]> response = controller.unlockPDFForms(file);
ResponseEntity<StreamingResponseBody> response = controller.unlockPDFForms(file);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -79,7 +99,7 @@ class UnlockPDFFormsControllerTest {
PDFFile file = new PDFFile();
file.setFileInput(mockPdfFile);
ResponseEntity<byte[]> response = controller.unlockPDFForms(file);
ResponseEntity<StreamingResponseBody> response = controller.unlockPDFForms(file);
// Controller catches exceptions and returns null
assertNull(response);
@@ -94,7 +114,7 @@ class UnlockPDFFormsControllerTest {
PDFFile file = new PDFFile();
file.setFileInput(mockPdfFile);
ResponseEntity<byte[]> response = controller.unlockPDFForms(file);
ResponseEntity<StreamingResponseBody> response = controller.unlockPDFForms(file);
assertNotNull(response);
String contentDisposition = response.getHeaders().getFirst("Content-Disposition");
@@ -113,7 +133,7 @@ class UnlockPDFFormsControllerTest {
PDFFile file = new PDFFile();
file.setFileInput(mockPdfFile);
ResponseEntity<byte[]> response = controller.unlockPDFForms(file);
ResponseEntity<StreamingResponseBody> response = controller.unlockPDFForms(file);
assertNotNull(response);
assertTrue(acroForm.getNeedAppearances());
@@ -49,7 +49,7 @@ class PipelineProcessorTest {
PipelineProcessor pipelineProcessor;
@BeforeEach
void setUp() {
void setUp() throws Exception {
pipelineProcessor =
spy(
new PipelineProcessor(
@@ -4,10 +4,14 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -23,14 +27,28 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@ExtendWith(MockitoExtension.class)
class CertSignControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private CertSignController certSignController;
@@ -47,6 +65,18 @@ class CertSignControllerTest {
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
try (PDDocument doc = new PDDocument()) {
doc.addPage(new PDPage());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -137,10 +167,11 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -163,10 +194,11 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -215,10 +247,11 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -246,10 +279,11 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -277,10 +311,11 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -308,10 +343,11 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -339,9 +375,10 @@ class CertSignControllerTest {
request.setPageNumber(1);
request.setShowLogo(false);
ResponseEntity<byte[]> response = certSignController.signPDFWithCert(request);
ResponseEntity<StreamingResponseBody> response =
certSignController.signPDFWithCert(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
}
@@ -3,10 +3,14 @@ package stirling.software.SPDF.controller.api.security;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -28,17 +32,31 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.security.AddPasswordRequest;
import stirling.software.SPDF.model.api.security.PDFPasswordRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@DisplayName("PasswordController Tests")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class PasswordControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private PasswordController passwordController;
@@ -46,6 +64,18 @@ class PasswordControllerTest {
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
try (PDDocument doc = new PDDocument()) {
doc.addPage(new PDPage());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -90,10 +120,11 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyString()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.removePassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.removePassword(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -114,7 +145,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyString()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.removePassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.removePassword(request);
assertNotNull(response);
assertNotNull(response.getBody());
@@ -177,7 +209,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyString()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.removePassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.removePassword(request);
assertNotNull(response.getBody());
}
@@ -195,7 +228,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyString()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.removePassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.removePassword(request);
assertNotNull(response.getBody());
}
}
@@ -223,10 +257,11 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -248,7 +283,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
}
@@ -274,7 +310,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
}
@@ -297,7 +334,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
}
@@ -328,9 +366,10 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -353,7 +392,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
}
@@ -376,7 +416,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
}
@@ -399,7 +440,8 @@ class PasswordControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = passwordController.addPassword(request);
ResponseEntity<StreamingResponseBody> response =
passwordController.addPassword(request);
assertNotNull(response.getBody());
}
}
@@ -1,13 +1,16 @@
package stirling.software.SPDF.controller.api.security;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -44,20 +47,34 @@ import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.security.ManualRedactPdfRequest;
import stirling.software.SPDF.model.api.security.RedactPdfRequest;
import stirling.software.common.model.api.security.RedactionArea;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@DisplayName("PDF Redaction Controller tests")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class RedactControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
private static final Logger log = LoggerFactory.getLogger(RedactControllerTest.class);
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private RedactController redactController;
@@ -112,6 +129,18 @@ class RedactControllerTest {
@BeforeEach
void setUp() throws IOException {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
mockPdfFile =
new MockMultipartFile(
"fileInput",
@@ -159,14 +188,15 @@ class RedactControllerTest {
when(mockCOSStream.createOutputStream()).thenReturn(mockOutputStream);
when(mockCOSStream.createOutputStream(any())).thenReturn(mockOutputStream);
doAnswer(
invocation -> {
ByteArrayOutputStream baos = invocation.getArgument(0);
baos.write("Mock PDF Content".getBytes());
lenient()
.doAnswer(
inv -> {
File f = inv.getArgument(0);
java.nio.file.Files.write(f.toPath(), "mock pdf".getBytes());
return null;
})
.when(mockDocument)
.save(any(ByteArrayOutputStream.class));
.save(any(File.class));
doNothing().when(mockDocument).close();
// Initialize a real document for unit tests
@@ -298,12 +328,12 @@ class RedactControllerTest {
mock(org.apache.pdfbox.pdmodel.PDDocumentInformation.class);
when(mockDocument.getDocumentInformation()).thenReturn(mockInfo);
ResponseEntity<byte[]> response = redactController.redactPdf(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPdf(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
verify(mockDocument).save(any(ByteArrayOutputStream.class));
verify(mockDocument).save(any(File.class));
verify(mockDocument).close();
}
}
@@ -702,14 +732,14 @@ class RedactControllerTest {
request.setConvertPDFToImage(convertToImage);
try {
ResponseEntity<byte[]> response = redactController.redactPdf(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPdf(request);
if (expectSuccess && response != null) {
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
assertTrue(drainBody(response).length > 0);
verify(mockDocument, times(1)).save(any(File.class));
verify(mockDocument, times(1)).close();
}
} catch (Exception e) {
@@ -727,12 +757,12 @@ class RedactControllerTest {
request.setConvertPDFToImage(convertToImage);
try {
ResponseEntity<byte[]> response = redactController.redactPDF(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPDF(request);
if (response != null) {
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
verify(mockDocument, times(1)).save(any(File.class));
}
} catch (Exception e) {
log.info("Manual redaction test completed with graceful handling: {}", e.getMessage());
@@ -918,7 +948,7 @@ class RedactControllerTest {
request.setListOfText("test");
request.setRedactColor(null);
ResponseEntity<byte[]> response = redactController.redactPdf(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPdf(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -942,7 +972,7 @@ class RedactControllerTest {
ManualRedactPdfRequest request = createManualRedactPdfRequest();
request.setRedactions(null);
ResponseEntity<byte[]> response = redactController.redactPDF(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPDF(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -954,7 +984,7 @@ class RedactControllerTest {
ManualRedactPdfRequest request = createManualRedactPdfRequest();
request.setPageNumbers("100-200");
ResponseEntity<byte[]> response = redactController.redactPDF(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPDF(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
@@ -1419,12 +1449,12 @@ class RedactControllerTest {
request.setUseRegex(false);
request.setWholeWordSearch(false);
ResponseEntity<byte[]> response = redactController.redactPdf(request);
ResponseEntity<StreamingResponseBody> response = redactController.redactPdf(request);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
}
}
@@ -2,10 +2,15 @@ package stirling.software.SPDF.controller.api.security;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -27,16 +32,30 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@DisplayName("RemoveCertSignController Tests")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class RemoveCertSignControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private RemoveCertSignController removeCertSignController;
@@ -44,6 +63,18 @@ class RemoveCertSignControllerTest {
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
try (PDDocument doc = new PDDocument()) {
doc.addPage(new PDPage());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -72,10 +103,11 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -95,7 +127,8 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response.getBody());
}
@@ -126,7 +159,8 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(pdfWithAcroForm));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response.getBody());
}
@@ -156,7 +190,8 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(pdfWithSig));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response.getBody());
}
@@ -176,7 +211,8 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -194,7 +230,8 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response.getBody());
}
@@ -224,7 +261,8 @@ class RemoveCertSignControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(multiPagePdf));
ResponseEntity<byte[]> response = removeCertSignController.removeCertSignPDF(request);
ResponseEntity<StreamingResponseBody> response =
removeCertSignController.removeCertSignPDF(request);
assertNotNull(response.getBody());
}
@@ -3,10 +3,15 @@ package stirling.software.SPDF.controller.api.security;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -35,16 +40,30 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.security.SanitizePdfRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@DisplayName("SanitizeController Tests")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class SanitizeControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private SanitizeController sanitizeController;
@@ -52,6 +71,18 @@ class SanitizeControllerTest {
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage(PDRectangle.A4);
doc.addPage(page);
@@ -139,7 +170,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(jsBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -167,7 +199,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
}
@@ -196,9 +229,10 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(linkBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
}
@@ -226,7 +260,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(metaBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
@@ -252,7 +287,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
}
@@ -283,7 +319,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
}
@@ -312,9 +349,10 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(jsBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
@Test
@@ -339,7 +377,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
@@ -360,7 +399,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
@@ -386,7 +426,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response.getBody());
}
@@ -412,7 +453,8 @@ class SanitizeControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class), anyBoolean()))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = sanitizeController.sanitizePDF(request);
ResponseEntity<StreamingResponseBody> response =
sanitizeController.sanitizePDF(request);
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -2,9 +2,14 @@ package stirling.software.SPDF.controller.api.security;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.file.Files;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
@@ -28,16 +33,30 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.SPDF.model.api.security.AddWatermarkRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@DisplayName("WatermarkController Tests")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class WatermarkControllerTest {
private static ResponseEntity<StreamingResponseBody> streamingOk(byte[] bytes) {
return ResponseEntity.ok(out -> out.write(bytes));
}
private static byte[] drainBody(ResponseEntity<StreamingResponseBody> response)
throws java.io.IOException {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
response.getBody().writeTo(baos);
return baos.toByteArray();
}
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
@Mock private TempFileManager tempFileManager;
@InjectMocks private WatermarkController watermarkController;
@@ -45,6 +64,18 @@ class WatermarkControllerTest {
@BeforeEach
void setUp() throws Exception {
lenient()
.when(tempFileManager.createManagedTempFile(anyString()))
.thenAnswer(
inv -> {
File f =
Files.createTempFile("test", inv.<String>getArgument(0))
.toFile();
TempFile tf = mock(TempFile.class);
lenient().when(tf.getFile()).thenReturn(f);
lenient().when(tf.getPath()).thenReturn(f.toPath());
return tf;
});
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage(PDRectangle.A4);
doc.addPage(page);
@@ -91,10 +122,11 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@@ -124,7 +156,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
@@ -154,7 +187,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
@@ -184,7 +218,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
@@ -214,7 +249,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
}
@@ -350,9 +386,10 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(multiPagePdf));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
assertTrue(drainBody(response).length > 0);
}
}
@@ -391,7 +428,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
@@ -418,7 +456,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
@@ -448,7 +487,8 @@ class WatermarkControllerTest {
when(pdfDocumentFactory.load(any(MultipartFile.class)))
.thenAnswer(inv -> Loader.loadPDF(simplePdfBytes));
ResponseEntity<byte[]> response = watermarkController.addWatermark(request);
ResponseEntity<StreamingResponseBody> response =
watermarkController.addWatermark(request);
assertNotNull(response.getBody());
}
}
@@ -1,5 +1,6 @@
package stirling.software.SPDF.model.api.converters;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@@ -20,6 +21,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import stirling.software.common.util.PDFToFile;
@@ -34,10 +36,11 @@ class ConvertPDFToMarkdownTest {
@RestControllerAdvice
static class GlobalErrorHandler {
@ExceptionHandler(Exception.class)
ResponseEntity<byte[]> handle(Exception ex) {
ResponseEntity<StreamingResponseBody> handle(Exception ex) {
String message = ex.getMessage();
byte[] body = message != null ? message.getBytes(StandardCharsets.UTF_8) : new byte[0];
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
StreamingResponseBody stream = out -> out.write(body);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(stream);
}
}
@@ -49,12 +52,13 @@ class ConvertPDFToMarkdownTest {
Mockito.mockConstruction(
PDFToFile.class,
(mock, ctx) -> {
StreamingResponseBody stream = out -> out.write(md);
when(mock.processPdfToMarkdown(any(MultipartFile.class)))
.thenAnswer(
inv ->
ResponseEntity.ok()
.header("Content-Type", "text/markdown")
.body(md));
.body(stream));
})) {
MockMvc mvc = mockMvc();
@@ -69,7 +73,11 @@ class ConvertPDFToMarkdownTest {
mvc.perform(multipart("/api/v1/convert/pdf/markdown").file(file))
.andExpect(status().isOk())
.andExpect(header().string("Content-Type", "text/markdown"))
.andExpect(content().bytes(md));
.andExpect(
result -> {
byte[] actual = result.getResponse().getContentAsByteArray();
assertArrayEquals(md, actual);
});
// Verify that exactly one instance was created
assert construction.constructed().size() == 1;