mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-12-03 20:04:28 +01:00
refactor(tests): replaced redundant setups, simplified exception handling, and optimized code readability. (#4710)
# Description of Changes This pull request primarily refactors and improves the test code across several modules, focusing on modernization, simplification, and consistency of assertions and test setup. The changes include formatting updates and improvements to utility methods. These updates help make the tests easier to maintain and read, and ensure they use current best practices. **Test code modernization and assertion improvements:** * Replaced legacy assertion methods such as `assertTrue(x instanceof Y)` with more specific `assertInstanceOf` assertions in multiple test files, improving clarity and type safety. * Updated exception assertion checks to use `assertInstanceOf` for error types instead of `assertTrue`, ensuring more precise test validation. * Refactored test setup in `ResourceMonitorTest` to use `final` for `AtomicReference` fields, clarifying intent and thread safety. * Changed some test method signatures to remove unnecessary `throws Exception` clauses, simplifying the test code. **Test code simplification and cleanup:** * Removed unused mock fields and simplified array initializations in `AutoJobPostMappingIntegrationTest`, streamlining test setup and reducing clutter. * Updated YAML string initialization in `ApplicationPropertiesDynamicYamlPropertySourceTest` to use Java text blocks for improved readability. * Improved null handling in assertions for collection validity checks. * Updated byte array encoding to use `StandardCharsets.UTF_8` for reliability and clarity. **PDF document factory test refactoring:** * Refactored `CustomPDFDocumentFactoryTest` to move helper methods for inflating PDFs and writing temp files to the top of the class, and restructured parameterized tests for better organization and maintainability. <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
parent
83922c4131
commit
a7900aead8
@ -31,8 +31,6 @@ import stirling.software.common.aop.AutoJobAspect;
|
|||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
import stirling.software.common.service.FileStorage;
|
import stirling.software.common.service.FileStorage;
|
||||||
import stirling.software.common.service.JobExecutorService;
|
import stirling.software.common.service.JobExecutorService;
|
||||||
import stirling.software.common.service.JobQueue;
|
|
||||||
import stirling.software.common.service.ResourceMonitor;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class AutoJobPostMappingIntegrationTest {
|
class AutoJobPostMappingIntegrationTest {
|
||||||
@ -45,10 +43,6 @@ class AutoJobPostMappingIntegrationTest {
|
|||||||
|
|
||||||
@Mock private FileStorage fileStorage;
|
@Mock private FileStorage fileStorage;
|
||||||
|
|
||||||
@Mock private ResourceMonitor resourceMonitor;
|
|
||||||
|
|
||||||
@Mock private JobQueue jobQueue;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
autoJobAspect = new AutoJobAspect(jobExecutorService, request, fileStorage);
|
autoJobAspect = new AutoJobAspect(jobExecutorService, request, fileStorage);
|
||||||
@ -73,7 +67,7 @@ class AutoJobPostMappingIntegrationTest {
|
|||||||
// Given
|
// Given
|
||||||
PDFFile pdfFile = new PDFFile();
|
PDFFile pdfFile = new PDFFile();
|
||||||
pdfFile.setFileId("test-file-id");
|
pdfFile.setFileId("test-file-id");
|
||||||
Object[] args = new Object[] {pdfFile};
|
Object[] args = {pdfFile};
|
||||||
|
|
||||||
when(joinPoint.getArgs()).thenReturn(args);
|
when(joinPoint.getArgs()).thenReturn(args);
|
||||||
when(request.getParameter("async")).thenReturn("true");
|
when(request.getParameter("async")).thenReturn("true");
|
||||||
@ -153,7 +147,7 @@ class AutoJobPostMappingIntegrationTest {
|
|||||||
// Given
|
// Given
|
||||||
PDFFile pdfFile = new PDFFile();
|
PDFFile pdfFile = new PDFFile();
|
||||||
pdfFile.setFileInput(mock(MultipartFile.class));
|
pdfFile.setFileInput(mock(MultipartFile.class));
|
||||||
Object[] args = new Object[] {pdfFile};
|
Object[] args = {pdfFile};
|
||||||
|
|
||||||
when(joinPoint.getArgs()).thenReturn(args);
|
when(joinPoint.getArgs()).thenReturn(args);
|
||||||
when(request.getParameter("async")).thenReturn("true");
|
when(request.getParameter("async")).thenReturn("true");
|
||||||
|
|||||||
@ -20,11 +20,13 @@ class ApplicationPropertiesDynamicYamlPropertySourceTest {
|
|||||||
void loads_yaml_into_environment() throws Exception {
|
void loads_yaml_into_environment() throws Exception {
|
||||||
// YAML-Config in Temp-Datei schreiben
|
// YAML-Config in Temp-Datei schreiben
|
||||||
String yaml =
|
String yaml =
|
||||||
""
|
"""
|
||||||
+ "ui:\n"
|
\
|
||||||
+ " appName: \"My App\"\n"
|
ui:
|
||||||
+ "system:\n"
|
appName: "My App"
|
||||||
+ " enableAnalytics: true\n";
|
system:
|
||||||
|
enableAnalytics: true
|
||||||
|
""";
|
||||||
Path tmp = Files.createTempFile("spdf-settings-", ".yml");
|
Path tmp = Files.createTempFile("spdf-settings-", ".yml");
|
||||||
Files.writeString(tmp, yaml);
|
Files.writeString(tmp, yaml);
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ class ApplicationPropertiesDynamicYamlPropertySourceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void throws_when_settings_file_missing() throws Exception {
|
void throws_when_settings_file_missing() {
|
||||||
String missing = "/path/does/not/exist/spdf.yml";
|
String missing = "/path/does/not/exist/spdf.yml";
|
||||||
try (MockedStatic<InstallationPathConfig> mocked =
|
try (MockedStatic<InstallationPathConfig> mocked =
|
||||||
Mockito.mockStatic(InstallationPathConfig.class)) {
|
Mockito.mockStatic(InstallationPathConfig.class)) {
|
||||||
|
|||||||
@ -232,7 +232,7 @@ class ApplicationPropertiesLogicTest {
|
|||||||
Collection<String> nullColl = null;
|
Collection<String> nullColl = null;
|
||||||
Collection<String> empty = List.of();
|
Collection<String> empty = List.of();
|
||||||
|
|
||||||
assertFalse(oauth2.isValid(nullColl, "scopes"));
|
assertFalse(oauth2.isValid((Collection<String>) null, "scopes"));
|
||||||
assertFalse(oauth2.isValid(empty, "scopes"));
|
assertFalse(oauth2.isValid(empty, "scopes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ class ApplicationPropertiesSaml2HttpTest {
|
|||||||
Resource r = s.getSpCert();
|
Resource r = s.getSpCert();
|
||||||
|
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
assertTrue(r instanceof FileSystemResource, "Expected FileSystemResource for FS path");
|
assertInstanceOf(FileSystemResource.class, r, "Expected FileSystemResource for FS path");
|
||||||
assertTrue(r.exists(), "Temp file should exist");
|
assertTrue(r.exists(), "Temp file should exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ class ApplicationPropertiesSaml2HttpTest {
|
|||||||
Resource r = s.getIdpCert();
|
Resource r = s.getIdpCert();
|
||||||
|
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
assertTrue(r instanceof FileSystemResource, "Expected FileSystemResource for FS path");
|
assertInstanceOf(FileSystemResource.class, r, "Expected FileSystemResource for FS path");
|
||||||
assertFalse(r.exists(), "Resource should not exist for missing file");
|
assertFalse(r.exists(), "Resource should not exist for missing file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import java.io.InputStream;
|
|||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -47,7 +48,7 @@ public class InputStreamTemplateResourceTest {
|
|||||||
@Test
|
@Test
|
||||||
void readerReturnsCorrectContent() throws Exception {
|
void readerReturnsCorrectContent() throws Exception {
|
||||||
String content = "Hello, world!";
|
String content = "Hello, world!";
|
||||||
InputStream is = new ByteArrayInputStream(content.getBytes("UTF-8"));
|
InputStream is = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
|
||||||
InputStreamTemplateResource resource = new InputStreamTemplateResource(is, "UTF-8");
|
InputStreamTemplateResource resource = new InputStreamTemplateResource(is, "UTF-8");
|
||||||
|
|
||||||
try (Reader reader = resource.reader()) {
|
try (Reader reader = resource.reader()) {
|
||||||
|
|||||||
@ -41,58 +41,7 @@ class CustomPDFDocumentFactoryTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
private static byte[] inflatePdf(byte[] input, int sizeInMB) throws IOException {
|
||||||
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
|
||||||
void testStrategy_FileInput(int sizeMB, StrategyType expected) throws IOException {
|
|
||||||
File file = writeTempFile(inflatePdf(basePdfBytes, sizeMB));
|
|
||||||
try (PDDocument doc = factory.load(file)) {
|
|
||||||
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
|
||||||
void testStrategy_ByteArray(int sizeMB, StrategyType expected) throws IOException {
|
|
||||||
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
|
||||||
try (PDDocument doc = factory.load(inflated)) {
|
|
||||||
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
|
||||||
void testStrategy_InputStream(int sizeMB, StrategyType expected) throws IOException {
|
|
||||||
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
|
||||||
try (PDDocument doc = factory.load(new ByteArrayInputStream(inflated))) {
|
|
||||||
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
|
||||||
void testStrategy_MultipartFile(int sizeMB, StrategyType expected) throws IOException {
|
|
||||||
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
|
||||||
MockMultipartFile multipart =
|
|
||||||
new MockMultipartFile("file", "doc.pdf", MediaType.APPLICATION_PDF_VALUE, inflated);
|
|
||||||
try (PDDocument doc = factory.load(multipart)) {
|
|
||||||
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
|
||||||
void testStrategy_PDFFile(int sizeMB, StrategyType expected) throws IOException {
|
|
||||||
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
|
||||||
MockMultipartFile multipart =
|
|
||||||
new MockMultipartFile("file", "doc.pdf", MediaType.APPLICATION_PDF_VALUE, inflated);
|
|
||||||
PDFFile pdfFile = new PDFFile();
|
|
||||||
pdfFile.setFileInput(multipart);
|
|
||||||
try (PDDocument doc = factory.load(pdfFile)) {
|
|
||||||
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] inflatePdf(byte[] input, int sizeInMB) throws IOException {
|
|
||||||
try (PDDocument doc = Loader.loadPDF(input)) {
|
try (PDDocument doc = Loader.loadPDF(input)) {
|
||||||
byte[] largeData = new byte[sizeInMB * 1024 * 1024];
|
byte[] largeData = new byte[sizeInMB * 1024 * 1024];
|
||||||
Arrays.fill(largeData, (byte) 'A');
|
Arrays.fill(largeData, (byte) 'A');
|
||||||
@ -111,6 +60,46 @@ class CustomPDFDocumentFactoryTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static File writeTempFile(byte[] content) throws IOException {
|
||||||
|
File file = Files.createTempFile("pdf-test-", ".pdf").toFile();
|
||||||
|
Files.write(file.toPath(), content);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
||||||
|
void testStrategy_FileInput(int sizeMB, StrategyType expected) throws IOException {
|
||||||
|
File file = writeTempFile(inflatePdf(basePdfBytes, sizeMB));
|
||||||
|
factory.load(file);
|
||||||
|
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
||||||
|
void testStrategy_ByteArray(int sizeMB, StrategyType expected) throws IOException {
|
||||||
|
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
||||||
|
factory.load(inflated);
|
||||||
|
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
||||||
|
void testStrategy_InputStream(int sizeMB, StrategyType expected) throws IOException {
|
||||||
|
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
||||||
|
factory.load(new ByteArrayInputStream(inflated));
|
||||||
|
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
||||||
|
void testStrategy_MultipartFile(int sizeMB, StrategyType expected) throws IOException {
|
||||||
|
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
||||||
|
MockMultipartFile multipart =
|
||||||
|
new MockMultipartFile("file", "doc.pdf", MediaType.APPLICATION_PDF_VALUE, inflated);
|
||||||
|
factory.load(multipart);
|
||||||
|
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testLoadFromPath() throws IOException {
|
void testLoadFromPath() throws IOException {
|
||||||
File file = writeTempFile(inflatePdf(basePdfBytes, 5));
|
File file = writeTempFile(inflatePdf(basePdfBytes, 5));
|
||||||
@ -210,10 +199,16 @@ class CustomPDFDocumentFactoryTest {
|
|||||||
assertTrue(newBytes.length > 0);
|
assertTrue(newBytes.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File writeTempFile(byte[] content) throws IOException {
|
@ParameterizedTest
|
||||||
File file = Files.createTempFile("pdf-test-", ".pdf").toFile();
|
@CsvSource({"5,MEMORY_ONLY", "20,MIXED", "60,TEMP_FILE"})
|
||||||
Files.write(file.toPath(), content);
|
void testStrategy_PDFFile(int sizeMB, StrategyType expected) throws IOException {
|
||||||
return file;
|
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
||||||
|
MockMultipartFile multipart =
|
||||||
|
new MockMultipartFile("file", "doc.pdf", MediaType.APPLICATION_PDF_VALUE, inflated);
|
||||||
|
PDFFile pdfFile = new PDFFile();
|
||||||
|
pdfFile.setFileInput(multipart);
|
||||||
|
factory.load(pdfFile);
|
||||||
|
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
package stirling.software.common.service;
|
package stirling.software.common.service;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
@ -63,7 +61,7 @@ class JobExecutorServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRunSyncJobSuccessfully() throws Exception {
|
void shouldRunSyncJobSuccessfully() {
|
||||||
// Given
|
// Given
|
||||||
Supplier<Object> work = () -> "test-result";
|
Supplier<Object> work = () -> "test-result";
|
||||||
|
|
||||||
@ -79,7 +77,7 @@ class JobExecutorServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRunAsyncJobSuccessfully() throws Exception {
|
void shouldRunAsyncJobSuccessfully() {
|
||||||
// Given
|
// Given
|
||||||
Supplier<Object> work = () -> "test-result";
|
Supplier<Object> work = () -> "test-result";
|
||||||
|
|
||||||
@ -88,7 +86,7 @@ class JobExecutorServiceTest {
|
|||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
assertTrue(response.getBody() instanceof JobResponse);
|
assertInstanceOf(JobResponse.class, response.getBody());
|
||||||
JobResponse<?> jobResponse = (JobResponse<?>) response.getBody();
|
JobResponse<?> jobResponse = (JobResponse<?>) response.getBody();
|
||||||
assertTrue(jobResponse.isAsync());
|
assertTrue(jobResponse.isAsync());
|
||||||
assertNotNull(jobResponse.getJobId());
|
assertNotNull(jobResponse.getJobId());
|
||||||
@ -113,6 +111,7 @@ class JobExecutorServiceTest {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> errorMap = (Map<String, String>) response.getBody();
|
Map<String, String> errorMap = (Map<String, String>) response.getBody();
|
||||||
|
assertNotNull(errorMap);
|
||||||
assertEquals("Job failed: Test error", errorMap.get("error"));
|
assertEquals("Job failed: Test error", errorMap.get("error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +132,7 @@ class JobExecutorServiceTest {
|
|||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
assertTrue(response.getBody() instanceof JobResponse);
|
assertInstanceOf(JobResponse.class, response.getBody());
|
||||||
|
|
||||||
// Verify job was queued
|
// Verify job was queued
|
||||||
verify(jobQueue).queueJob(anyString(), eq(80), any(), eq(5000L));
|
verify(jobQueue).queueJob(anyString(), eq(80), any(), eq(5000L));
|
||||||
@ -186,7 +185,7 @@ class JobExecutorServiceTest {
|
|||||||
try {
|
try {
|
||||||
executeMethod.invoke(jobExecutorService, work, 1L); // Very short timeout
|
executeMethod.invoke(jobExecutorService, work, 1L); // Very short timeout
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
assertTrue(e.getCause() instanceof TimeoutException);
|
assertInstanceOf(TimeoutException.class, e.getCause());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,11 +33,11 @@ class ResourceMonitorTest {
|
|||||||
@Mock private MemoryMXBean memoryMXBean;
|
@Mock private MemoryMXBean memoryMXBean;
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
private AtomicReference<ResourceStatus> currentStatus =
|
private final AtomicReference<ResourceStatus> currentStatus =
|
||||||
new AtomicReference<>(ResourceStatus.OK);
|
new AtomicReference<>(ResourceStatus.OK);
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
private AtomicReference<ResourceMetrics> latestMetrics =
|
private final AtomicReference<ResourceMetrics> latestMetrics =
|
||||||
new AtomicReference<>(new ResourceMetrics());
|
new AtomicReference<>(new ResourceMetrics());
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|||||||
@ -215,7 +215,7 @@ class TaskManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCleanupOldJobs() throws Exception {
|
void testCleanupOldJobs() {
|
||||||
// Arrange
|
// Arrange
|
||||||
// 1. Create a recent completed job
|
// 1. Create a recent completed job
|
||||||
String recentJobId = "recent-job";
|
String recentJobId = "recent-job";
|
||||||
@ -253,6 +253,7 @@ class TaskManagerTest {
|
|||||||
taskManager.createTask(activeJobId);
|
taskManager.createTask(activeJobId);
|
||||||
|
|
||||||
// Verify all jobs are in the map
|
// Verify all jobs are in the map
|
||||||
|
assertNotNull(jobResultsMap);
|
||||||
assertTrue(jobResultsMap.containsKey(recentJobId));
|
assertTrue(jobResultsMap.containsKey(recentJobId));
|
||||||
assertTrue(jobResultsMap.containsKey(oldJobId));
|
assertTrue(jobResultsMap.containsKey(oldJobId));
|
||||||
assertTrue(jobResultsMap.containsKey(activeJobId));
|
assertTrue(jobResultsMap.containsKey(activeJobId));
|
||||||
@ -268,7 +269,7 @@ class TaskManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testShutdown() throws Exception {
|
void testShutdown() {
|
||||||
// This mainly tests that the shutdown method doesn't throw exceptions
|
// This mainly tests that the shutdown method doesn't throw exceptions
|
||||||
taskManager.shutdown();
|
taskManager.shutdown();
|
||||||
|
|
||||||
|
|||||||
@ -219,9 +219,9 @@ public class TempFileCleanupServiceTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Act - set containerMode to false for this test
|
// Act - set containerMode to false for this test
|
||||||
invokeCleanupDirectoryStreaming(systemTempDir, false, 0, 3600000);
|
invokeCleanupDirectoryStreaming(systemTempDir, false, 3600000);
|
||||||
invokeCleanupDirectoryStreaming(customTempDir, false, 0, 3600000);
|
invokeCleanupDirectoryStreaming(customTempDir, false, 3600000);
|
||||||
invokeCleanupDirectoryStreaming(libreOfficeTempDir, false, 0, 3600000);
|
invokeCleanupDirectoryStreaming(libreOfficeTempDir, false, 3600000);
|
||||||
|
|
||||||
// Assert - Only old temp files and empty files should be deleted
|
// Assert - Only old temp files and empty files should be deleted
|
||||||
assertTrue(deletedFiles.contains(oldTempFile), "Old temp file should be deleted");
|
assertTrue(deletedFiles.contains(oldTempFile), "Old temp file should be deleted");
|
||||||
@ -306,7 +306,7 @@ public class TempFileCleanupServiceTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Act - set containerMode to true and maxAgeMillis to 0 for container startup cleanup
|
// Act - set containerMode to true and maxAgeMillis to 0 for container startup cleanup
|
||||||
invokeCleanupDirectoryStreaming(systemTempDir, true, 0, 0);
|
invokeCleanupDirectoryStreaming(systemTempDir, true, 0);
|
||||||
|
|
||||||
// Assert - In container mode, both our temp files and system temp files should be
|
// Assert - In container mode, both our temp files and system temp files should be
|
||||||
// deleted
|
// deleted
|
||||||
@ -379,7 +379,7 @@ public class TempFileCleanupServiceTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
invokeCleanupDirectoryStreaming(systemTempDir, false, 0, 3600000);
|
invokeCleanupDirectoryStreaming(systemTempDir, false, 3600000);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertTrue(
|
assertTrue(
|
||||||
@ -462,7 +462,7 @@ public class TempFileCleanupServiceTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
invokeCleanupDirectoryStreaming(systemTempDir, false, 0, 3600000);
|
invokeCleanupDirectoryStreaming(systemTempDir, false, 3600000);
|
||||||
|
|
||||||
// Debug - print what was deleted
|
// Debug - print what was deleted
|
||||||
System.out.println("Deleted files: " + deletedFiles);
|
System.out.println("Deleted files: " + deletedFiles);
|
||||||
@ -479,8 +479,7 @@ public class TempFileCleanupServiceTest {
|
|||||||
|
|
||||||
/** Helper method to invoke the private cleanupDirectoryStreaming method using reflection */
|
/** Helper method to invoke the private cleanupDirectoryStreaming method using reflection */
|
||||||
private void invokeCleanupDirectoryStreaming(
|
private void invokeCleanupDirectoryStreaming(
|
||||||
Path directory, boolean containerMode, int depth, long maxAgeMillis)
|
Path directory, boolean containerMode, long maxAgeMillis) {
|
||||||
throws IOException {
|
|
||||||
try {
|
try {
|
||||||
// Create a consumer that tracks deleted files
|
// Create a consumer that tracks deleted files
|
||||||
AtomicInteger deleteCount = new AtomicInteger(0);
|
AtomicInteger deleteCount = new AtomicInteger(0);
|
||||||
@ -503,7 +502,7 @@ public class TempFileCleanupServiceTest {
|
|||||||
cleanupService,
|
cleanupService,
|
||||||
directory,
|
directory,
|
||||||
containerMode,
|
containerMode,
|
||||||
depth,
|
0,
|
||||||
maxAgeMillis,
|
maxAgeMillis,
|
||||||
false,
|
false,
|
||||||
deleteCallback);
|
deleteCallback);
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class CheckProgramInstallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Reset static fields in the CheckProgramInstall class using reflection */
|
/** Reset static fields in the CheckProgramInstall class using reflection */
|
||||||
private void resetStaticFields() throws Exception {
|
private static void resetStaticFields() throws Exception {
|
||||||
Field pythonAvailableCheckedField =
|
Field pythonAvailableCheckedField =
|
||||||
CheckProgramInstall.class.getDeclaredField("pythonAvailableChecked");
|
CheckProgramInstall.class.getDeclaredField("pythonAvailableChecked");
|
||||||
pythonAvailableCheckedField.setAccessible(true);
|
pythonAvailableCheckedField.setAccessible(true);
|
||||||
@ -108,8 +108,7 @@ class CheckProgramInstallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetAvailablePythonCommand_WhenPythonReturnsNonZeroExitCode()
|
void testGetAvailablePythonCommand_WhenPythonReturnsNonZeroExitCode() throws Exception {
|
||||||
throws IOException, InterruptedException, Exception {
|
|
||||||
// Arrange
|
// Arrange
|
||||||
// Reset the static fields again to ensure clean state
|
// Reset the static fields again to ensure clean state
|
||||||
resetStaticFields();
|
resetStaticFields();
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public class ChecksumUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
void crc32_unsignedFormatting_highBitSet() throws Exception {
|
void crc32_unsignedFormatting_highBitSet() throws Exception {
|
||||||
// CRC32 of single zero byte (0x00) is 0xD202EF8D (>= 0x8000_0000)
|
// CRC32 of single zero byte (0x00) is 0xD202EF8D (>= 0x8000_0000)
|
||||||
byte[] data = new byte[] {0x00};
|
byte[] data = {0x00};
|
||||||
|
|
||||||
// Hex (unsigned, 8 chars, lowercase)
|
// Hex (unsigned, 8 chars, lowercase)
|
||||||
try (InputStream is = new ByteArrayInputStream(data)) {
|
try (InputStream is = new ByteArrayInputStream(data)) {
|
||||||
|
|||||||
@ -765,7 +765,7 @@ class EmlToPdfTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
private String getTimestamp() {
|
private static String getTimestamp() {
|
||||||
java.time.ZonedDateTime fixedDateTime =
|
java.time.ZonedDateTime fixedDateTime =
|
||||||
java.time.ZonedDateTime.of(2023, 1, 1, 12, 0, 0, 0, java.time.ZoneId.of("GMT"));
|
java.time.ZonedDateTime.of(2023, 1, 1, 12, 0, 0, 0, java.time.ZoneId.of("GMT"));
|
||||||
return java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(fixedDateTime);
|
return java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(fixedDateTime);
|
||||||
@ -1039,13 +1039,13 @@ class EmlToPdfTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates a basic EmlToPdfRequest with default settings
|
// Creates a basic EmlToPdfRequest with default settings
|
||||||
private EmlToPdfRequest createBasicRequest() {
|
private static EmlToPdfRequest createBasicRequest() {
|
||||||
EmlToPdfRequest request = new EmlToPdfRequest();
|
EmlToPdfRequest request = new EmlToPdfRequest();
|
||||||
request.setIncludeAttachments(false);
|
request.setIncludeAttachments(false);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmlToPdfRequest createRequestWithAttachments() {
|
private static EmlToPdfRequest createRequestWithAttachments() {
|
||||||
EmlToPdfRequest request = new EmlToPdfRequest();
|
EmlToPdfRequest request = new EmlToPdfRequest();
|
||||||
request.setIncludeAttachments(true);
|
request.setIncludeAttachments(true);
|
||||||
request.setMaxAttachmentSizeMB(10);
|
request.setMaxAttachmentSizeMB(10);
|
||||||
|
|||||||
@ -11,10 +11,18 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
public class ImageProcessingUtilsTest {
|
public class ImageProcessingUtilsTest {
|
||||||
|
|
||||||
|
private static void fillImageWithColor(BufferedImage image) {
|
||||||
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
|
image.setRGB(x, y, Color.RED.getRGB());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testConvertColorTypeToGreyscale() {
|
void testConvertColorTypeToGreyscale() {
|
||||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||||
fillImageWithColor(sourceImage, Color.RED);
|
fillImageWithColor(sourceImage);
|
||||||
|
|
||||||
BufferedImage convertedImage =
|
BufferedImage convertedImage =
|
||||||
ImageProcessingUtils.convertColorType(sourceImage, "greyscale");
|
ImageProcessingUtils.convertColorType(sourceImage, "greyscale");
|
||||||
@ -33,7 +41,7 @@ public class ImageProcessingUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
void testConvertColorTypeToBlackWhite() {
|
void testConvertColorTypeToBlackWhite() {
|
||||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||||
fillImageWithColor(sourceImage, Color.RED);
|
fillImageWithColor(sourceImage);
|
||||||
|
|
||||||
BufferedImage convertedImage =
|
BufferedImage convertedImage =
|
||||||
ImageProcessingUtils.convertColorType(sourceImage, "blackwhite");
|
ImageProcessingUtils.convertColorType(sourceImage, "blackwhite");
|
||||||
@ -51,7 +59,7 @@ public class ImageProcessingUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
void testConvertColorTypeToFullColor() {
|
void testConvertColorTypeToFullColor() {
|
||||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||||
fillImageWithColor(sourceImage, Color.RED);
|
fillImageWithColor(sourceImage);
|
||||||
|
|
||||||
BufferedImage convertedImage =
|
BufferedImage convertedImage =
|
||||||
ImageProcessingUtils.convertColorType(sourceImage, "fullcolor");
|
ImageProcessingUtils.convertColorType(sourceImage, "fullcolor");
|
||||||
@ -63,7 +71,7 @@ public class ImageProcessingUtilsTest {
|
|||||||
@Test
|
@Test
|
||||||
void testConvertColorTypeInvalid() {
|
void testConvertColorTypeInvalid() {
|
||||||
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
|
||||||
fillImageWithColor(sourceImage, Color.RED);
|
fillImageWithColor(sourceImage);
|
||||||
|
|
||||||
BufferedImage convertedImage =
|
BufferedImage convertedImage =
|
||||||
ImageProcessingUtils.convertColorType(sourceImage, "invalidtype");
|
ImageProcessingUtils.convertColorType(sourceImage, "invalidtype");
|
||||||
@ -71,12 +79,4 @@ public class ImageProcessingUtilsTest {
|
|||||||
assertNotNull(convertedImage);
|
assertNotNull(convertedImage);
|
||||||
assertEquals(sourceImage, convertedImage);
|
assertEquals(sourceImage, convertedImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillImageWithColor(BufferedImage image, Color color) {
|
|
||||||
for (int y = 0; y < image.getHeight(); y++) {
|
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
|
||||||
image.setRGB(x, y, color.getRGB());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -329,12 +329,10 @@ class PDFToFileTest {
|
|||||||
boolean foundImage = false;
|
boolean foundImage = false;
|
||||||
|
|
||||||
while ((entry = zipStream.getNextEntry()) != null) {
|
while ((entry = zipStream.getNextEntry()) != null) {
|
||||||
if ("test.html".equals(entry.getName())) {
|
switch (entry.getName()) {
|
||||||
foundMainHtml = true;
|
case "test.html" -> foundMainHtml = true;
|
||||||
} else if ("test_ind.html".equals(entry.getName())) {
|
case "test_ind.html" -> foundIndexHtml = true;
|
||||||
foundIndexHtml = true;
|
case "test_img.png" -> foundImage = true;
|
||||||
} else if ("test_img.png".equals(entry.getName())) {
|
|
||||||
foundImage = true;
|
|
||||||
}
|
}
|
||||||
zipStream.closeEntry();
|
zipStream.closeEntry();
|
||||||
}
|
}
|
||||||
@ -382,6 +380,7 @@ class PDFToFileTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create output file
|
// Create output file
|
||||||
|
assertNotNull(outDir);
|
||||||
Files.write(
|
Files.write(
|
||||||
Path.of(outDir, "document.docx"),
|
Path.of(outDir, "document.docx"),
|
||||||
"Fake DOCX content".getBytes());
|
"Fake DOCX content".getBytes());
|
||||||
@ -442,6 +441,7 @@ class PDFToFileTest {
|
|||||||
|
|
||||||
// Create multiple output files (simulating a presentation with
|
// Create multiple output files (simulating a presentation with
|
||||||
// multiple files)
|
// multiple files)
|
||||||
|
assertNotNull(outDir);
|
||||||
Files.write(
|
Files.write(
|
||||||
Path.of(outDir, "document.odp"),
|
Path.of(outDir, "document.odp"),
|
||||||
"Fake ODP content".getBytes());
|
"Fake ODP content".getBytes());
|
||||||
@ -530,6 +530,7 @@ class PDFToFileTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create text output file
|
// Create text output file
|
||||||
|
assertNotNull(outDir);
|
||||||
Files.write(
|
Files.write(
|
||||||
Path.of(outDir, "document.txt"),
|
Path.of(outDir, "document.txt"),
|
||||||
"Extracted text content".getBytes());
|
"Extracted text content".getBytes());
|
||||||
@ -587,6 +588,7 @@ class PDFToFileTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create output file - uses default name
|
// Create output file - uses default name
|
||||||
|
assertNotNull(outDir);
|
||||||
Files.write(
|
Files.write(
|
||||||
Path.of(outDir, "output.docx"),
|
Path.of(outDir, "output.docx"),
|
||||||
"Fake DOCX content".getBytes());
|
"Fake DOCX content".getBytes());
|
||||||
|
|||||||
@ -48,9 +48,7 @@ public class ProcessExecutorTest {
|
|||||||
IOException thrown =
|
IOException thrown =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IOException.class,
|
IOException.class,
|
||||||
() -> {
|
() -> processExecutor.runCommandWithOutputHandling(command));
|
||||||
processExecutor.runCommandWithOutputHandling(command);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check the exception message to ensure it indicates the command was not found
|
// Check the exception message to ensure it indicates the command was not found
|
||||||
String errorMessage = thrown.getMessage();
|
String errorMessage = thrown.getMessage();
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package stirling.software.common.util;
|
package stirling.software.common.util;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -22,7 +23,7 @@ public class PropertyConfigsTest {
|
|||||||
boolean result = PropertyConfigs.getBooleanValue(keys, defaultValue);
|
boolean result = PropertyConfigs.getBooleanValue(keys, defaultValue);
|
||||||
|
|
||||||
// Verify the result
|
// Verify the result
|
||||||
assertEquals(true, result);
|
assertTrue(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -51,7 +52,7 @@ public class PropertyConfigsTest {
|
|||||||
boolean result = PropertyConfigs.getBooleanValue(key, defaultValue);
|
boolean result = PropertyConfigs.getBooleanValue(key, defaultValue);
|
||||||
|
|
||||||
// Verify the result
|
// Verify the result
|
||||||
assertEquals(true, result);
|
assertTrue(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -62,17 +62,11 @@ public class RegexPatternUtilsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNullRegexHandling() {
|
void testNullRegexHandling() {
|
||||||
assertThrows(
|
assertThrows(IllegalArgumentException.class, () -> utils.getPattern(null));
|
||||||
IllegalArgumentException.class,
|
|
||||||
() -> {
|
|
||||||
utils.getPattern(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> {
|
() -> utils.getPattern(null, Pattern.CASE_INSENSITIVE));
|
||||||
utils.getPattern(null, Pattern.CASE_INSENSITIVE);
|
|
||||||
});
|
|
||||||
|
|
||||||
assertFalse(utils.isCached(null));
|
assertFalse(utils.isCached(null));
|
||||||
assertFalse(utils.removeFromCache(null));
|
assertFalse(utils.removeFromCache(null));
|
||||||
|
|||||||
@ -57,8 +57,7 @@ class SpringContextHolderTest {
|
|||||||
void testGetBean_BeanNotFound() {
|
void testGetBean_BeanNotFound() {
|
||||||
// Arrange
|
// Arrange
|
||||||
contextHolder.setApplicationContext(mockApplicationContext);
|
contextHolder.setApplicationContext(mockApplicationContext);
|
||||||
when(mockApplicationContext.getBean(TestBean.class))
|
when(mockApplicationContext.getBean(TestBean.class)).thenThrow(new MyBeansException());
|
||||||
.thenThrow(new org.springframework.beans.BeansException("Bean not found") {});
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
TestBean result = SpringContextHolder.getBean(TestBean.class);
|
TestBean result = SpringContextHolder.getBean(TestBean.class);
|
||||||
@ -69,4 +68,10 @@ class SpringContextHolderTest {
|
|||||||
|
|
||||||
// Simple test class
|
// Simple test class
|
||||||
private static class TestBean {}
|
private static class TestBean {}
|
||||||
|
|
||||||
|
private static class MyBeansException extends org.springframework.beans.BeansException {
|
||||||
|
public MyBeansException() {
|
||||||
|
super("Bean not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,22 +33,9 @@ import stirling.software.common.model.api.misc.ReplaceAndInvert;
|
|||||||
class InvertFullColorStrategyTest {
|
class InvertFullColorStrategyTest {
|
||||||
|
|
||||||
private InvertFullColorStrategy strategy;
|
private InvertFullColorStrategy strategy;
|
||||||
private MultipartFile mockPdfFile;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() throws Exception {
|
|
||||||
// Create a simple PDF document for testing
|
|
||||||
byte[] pdfBytes = createSimplePdfWithRectangle();
|
|
||||||
mockPdfFile =
|
|
||||||
new MockMultipartFile(
|
|
||||||
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
|
||||||
|
|
||||||
// Create the strategy instance
|
|
||||||
strategy = new InvertFullColorStrategy(mockPdfFile, ReplaceAndInvert.FULL_INVERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper method to create a simple PDF with a colored rectangle for testing */
|
/** Helper method to create a simple PDF with a colored rectangle for testing */
|
||||||
private byte[] createSimplePdfWithRectangle() throws IOException {
|
private static byte[] createSimplePdfWithRectangle() throws IOException {
|
||||||
PDDocument document = new PDDocument();
|
PDDocument document = new PDDocument();
|
||||||
PDPage page = new PDPage(PDRectangle.A4);
|
PDPage page = new PDPage(PDRectangle.A4);
|
||||||
document.addPage(page);
|
document.addPage(page);
|
||||||
@ -68,6 +55,18 @@ class InvertFullColorStrategyTest {
|
|||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws Exception {
|
||||||
|
// Create a simple PDF document for testing
|
||||||
|
byte[] pdfBytes = createSimplePdfWithRectangle();
|
||||||
|
MultipartFile mockPdfFile =
|
||||||
|
new MockMultipartFile(
|
||||||
|
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||||
|
|
||||||
|
// Create the strategy instance
|
||||||
|
strategy = new InvertFullColorStrategy(mockPdfFile, ReplaceAndInvert.FULL_INVERSION);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testReplace() throws IOException {
|
void testReplace() throws IOException {
|
||||||
// Test the replace method
|
// Test the replace method
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package stirling.software.common.util.misc;
|
package stirling.software.common.util.misc;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ -16,7 +15,6 @@ class PdfTextStripperCustomTest {
|
|||||||
|
|
||||||
private PdfTextStripperCustom stripper;
|
private PdfTextStripperCustom stripper;
|
||||||
private PDPage mockPage;
|
private PDPage mockPage;
|
||||||
private PDRectangle mockMediaBox;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() throws IOException {
|
void setUp() throws IOException {
|
||||||
@ -25,7 +23,7 @@ class PdfTextStripperCustomTest {
|
|||||||
|
|
||||||
// Create mock objects
|
// Create mock objects
|
||||||
mockPage = mock(PDPage.class);
|
mockPage = mock(PDPage.class);
|
||||||
mockMediaBox = mock(PDRectangle.class);
|
PDRectangle mockMediaBox = mock(PDRectangle.class);
|
||||||
|
|
||||||
// Configure mock behavior
|
// Configure mock behavior
|
||||||
when(mockPage.getMediaBox()).thenReturn(mockMediaBox);
|
when(mockPage.getMediaBox()).thenReturn(mockMediaBox);
|
||||||
@ -43,14 +41,14 @@ class PdfTextStripperCustomTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testBasicFunctionality() throws IOException {
|
void testBasicFunctionality() {
|
||||||
// Simply test that the method runs without exceptions
|
// Simply test that the method runs without exceptions
|
||||||
try {
|
try {
|
||||||
stripper.addRegion("testRegion", new java.awt.geom.Rectangle2D.Float(0, 0, 100, 100));
|
stripper.addRegion("testRegion", new java.awt.geom.Rectangle2D.Float(0, 0, 100, 100));
|
||||||
stripper.extractRegions(mockPage);
|
stripper.extractRegions(mockPage);
|
||||||
assertTrue(true, "Should execute without errors");
|
assertTrue(true, "Should execute without errors");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
assertTrue(false, "Method should not throw exception: " + e.getMessage());
|
fail("Method should not throw exception: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
package stirling.software.common.util.propertyeditor;
|
package stirling.software.common.util.propertyeditor;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
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 java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -33,7 +30,7 @@ class StringToArrayListPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof List, "Value should be a List");
|
assertInstanceOf(List.class, value, "Value should be a List");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<RedactionArea> list = (List<RedactionArea>) value;
|
List<RedactionArea> list = (List<RedactionArea>) value;
|
||||||
@ -63,7 +60,7 @@ class StringToArrayListPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof List, "Value should be a List");
|
assertInstanceOf(List.class, value, "Value should be a List");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<RedactionArea> list = (List<RedactionArea>) value;
|
List<RedactionArea> list = (List<RedactionArea>) value;
|
||||||
@ -91,7 +88,7 @@ class StringToArrayListPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof List, "Value should be a List");
|
assertInstanceOf(List.class, value, "Value should be a List");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<RedactionArea> list = (List<RedactionArea>) value;
|
List<RedactionArea> list = (List<RedactionArea>) value;
|
||||||
@ -106,7 +103,7 @@ class StringToArrayListPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof List, "Value should be a List");
|
assertInstanceOf(List.class, value, "Value should be a List");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<RedactionArea> list = (List<RedactionArea>) value;
|
List<RedactionArea> list = (List<RedactionArea>) value;
|
||||||
@ -125,7 +122,7 @@ class StringToArrayListPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof List, "Value should be a List");
|
assertInstanceOf(List.class, value, "Value should be a List");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<RedactionArea> list = (List<RedactionArea>) value;
|
List<RedactionArea> list = (List<RedactionArea>) value;
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
package stirling.software.common.util.propertyeditor;
|
package stirling.software.common.util.propertyeditor;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
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 java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -30,7 +27,7 @@ class StringToMapPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof Map, "Value should be a Map");
|
assertInstanceOf(Map.class, value, "Value should be a Map");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> map = (Map<String, String>) value;
|
Map<String, String> map = (Map<String, String>) value;
|
||||||
@ -50,7 +47,7 @@ class StringToMapPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof Map, "Value should be a Map");
|
assertInstanceOf(Map.class, value, "Value should be a Map");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> map = (Map<String, String>) value;
|
Map<String, String> map = (Map<String, String>) value;
|
||||||
@ -68,7 +65,7 @@ class StringToMapPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof Map, "Value should be a Map");
|
assertInstanceOf(Map.class, value, "Value should be a Map");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> map = (Map<String, String>) value;
|
Map<String, String> map = (Map<String, String>) value;
|
||||||
@ -87,7 +84,7 @@ class StringToMapPropertyEditorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(value, "Value should not be null");
|
assertNotNull(value, "Value should not be null");
|
||||||
assertTrue(value instanceof Map, "Value should be a Map");
|
assertInstanceOf(Map.class, value, "Value should be a Map");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> map = (Map<String, String>) value;
|
Map<String, String> map = (Map<String, String>) value;
|
||||||
|
|||||||
@ -5,22 +5,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
public class SPDFApplicationTest {
|
public class SPDFApplicationTest {
|
||||||
|
|
||||||
@Mock private Environment env;
|
|
||||||
|
|
||||||
@Mock private ApplicationProperties applicationProperties;
|
|
||||||
|
|
||||||
@InjectMocks private SPDFApplication sPDFApplication;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
SPDFApplication.setServerPortStatic("8080");
|
SPDFApplication.setServerPortStatic("8080");
|
||||||
|
|||||||
@ -37,10 +37,8 @@ class MergeControllerTest {
|
|||||||
private MockMultipartFile mockFile1;
|
private MockMultipartFile mockFile1;
|
||||||
private MockMultipartFile mockFile2;
|
private MockMultipartFile mockFile2;
|
||||||
private MockMultipartFile mockFile3;
|
private MockMultipartFile mockFile3;
|
||||||
private PDDocument mockDocument;
|
|
||||||
private PDDocument mockMergedDocument;
|
private PDDocument mockMergedDocument;
|
||||||
private PDDocumentCatalog mockCatalog;
|
private PDDocumentCatalog mockCatalog;
|
||||||
private PDPageTree mockPages;
|
|
||||||
private PDPage mockPage1;
|
private PDPage mockPage1;
|
||||||
private PDPage mockPage2;
|
private PDPage mockPage2;
|
||||||
|
|
||||||
@ -65,10 +63,10 @@ class MergeControllerTest {
|
|||||||
MediaType.APPLICATION_PDF_VALUE,
|
MediaType.APPLICATION_PDF_VALUE,
|
||||||
"PDF content 3".getBytes());
|
"PDF content 3".getBytes());
|
||||||
|
|
||||||
mockDocument = mock(PDDocument.class);
|
PDDocument mockDocument = mock(PDDocument.class);
|
||||||
mockMergedDocument = mock(PDDocument.class);
|
mockMergedDocument = mock(PDDocument.class);
|
||||||
mockCatalog = mock(PDDocumentCatalog.class);
|
mockCatalog = mock(PDDocumentCatalog.class);
|
||||||
mockPages = mock(PDPageTree.class);
|
PDPageTree mockPages = mock(PDPageTree.class);
|
||||||
mockPage1 = mock(PDPage.class);
|
mockPage1 = mock(PDPage.class);
|
||||||
mockPage2 = mock(PDPage.class);
|
mockPage2 = mock(PDPage.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ public class RotationControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRotatePDFInvalidAngle() throws IOException {
|
public void testRotatePDFInvalidAngle() {
|
||||||
// Create a mock file
|
// Create a mock file
|
||||||
MockMultipartFile mockFile =
|
MockMultipartFile mockFile =
|
||||||
new MockMultipartFile(
|
new MockMultipartFile(
|
||||||
|
|||||||
@ -213,7 +213,6 @@ public class ConvertWebsiteToPdfTest {
|
|||||||
assertNotNull(outPathStr);
|
assertNotNull(outPathStr);
|
||||||
|
|
||||||
// Temp file must be deleted in finally
|
// Temp file must be deleted in finally
|
||||||
Path outPath = Path.of(outPathStr);
|
|
||||||
assertFalse(
|
assertFalse(
|
||||||
Files.exists(Path.of(htmlPathStr)),
|
Files.exists(Path.of(htmlPathStr)),
|
||||||
"Temp HTML file should be deleted after the call");
|
"Temp HTML file should be deleted after the call");
|
||||||
@ -283,6 +282,24 @@ public class ConvertWebsiteToPdfTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MockedStatic<HttpClient> mockHttpClientReturning(String body) throws Exception {
|
||||||
|
MockedStatic<HttpClient> httpClientStatic = Mockito.mockStatic(HttpClient.class);
|
||||||
|
HttpClient.Builder builder = Mockito.mock(HttpClient.Builder.class);
|
||||||
|
HttpClient client = Mockito.mock(HttpClient.class);
|
||||||
|
HttpResponse<String> response = Mockito.mock();
|
||||||
|
|
||||||
|
httpClientStatic.when(HttpClient::newBuilder).thenReturn(builder);
|
||||||
|
when(builder.followRedirects(HttpClient.Redirect.NORMAL)).thenReturn(builder);
|
||||||
|
when(builder.connectTimeout(any(Duration.class))).thenReturn(builder);
|
||||||
|
when(builder.build()).thenReturn(client);
|
||||||
|
|
||||||
|
Mockito.doReturn(response).when(client).send(any(HttpRequest.class), any());
|
||||||
|
when(response.statusCode()).thenReturn(200);
|
||||||
|
when(response.body()).thenReturn(body);
|
||||||
|
|
||||||
|
return httpClientStatic;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void redirect_with_error_when_disallowed_content_detected() throws Exception {
|
void redirect_with_error_when_disallowed_content_detected() throws Exception {
|
||||||
UrlToPdfRequest request = new UrlToPdfRequest();
|
UrlToPdfRequest request = new UrlToPdfRequest();
|
||||||
@ -291,7 +308,7 @@ public class ConvertWebsiteToPdfTest {
|
|||||||
try (MockedStatic<GeneralUtils> gu = Mockito.mockStatic(GeneralUtils.class);
|
try (MockedStatic<GeneralUtils> gu = Mockito.mockStatic(GeneralUtils.class);
|
||||||
MockedStatic<HttpClient> httpClient =
|
MockedStatic<HttpClient> httpClient =
|
||||||
mockHttpClientReturning(
|
mockHttpClientReturning(
|
||||||
"<link rel=\"attachment\" href=\"file:///etc/passwd\">"); ) {
|
"<link rel=\"attachment\" href=\"file:///etc/passwd\">")) {
|
||||||
|
|
||||||
gu.when(() -> GeneralUtils.isValidURL("https://example.com")).thenReturn(true);
|
gu.when(() -> GeneralUtils.isValidURL("https://example.com")).thenReturn(true);
|
||||||
gu.when(() -> GeneralUtils.isURLReachable("https://example.com")).thenReturn(true);
|
gu.when(() -> GeneralUtils.isURLReachable("https://example.com")).thenReturn(true);
|
||||||
@ -306,23 +323,4 @@ public class ConvertWebsiteToPdfTest {
|
|||||||
&& location.getQuery().contains("error=error.disallowedUrlContent"));
|
&& location.getQuery().contains("error=error.disallowedUrlContent"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MockedStatic<HttpClient> mockHttpClientReturning(String body) throws Exception {
|
|
||||||
MockedStatic<HttpClient> httpClientStatic = Mockito.mockStatic(HttpClient.class);
|
|
||||||
HttpClient.Builder builder = Mockito.mock(HttpClient.Builder.class);
|
|
||||||
HttpClient client = Mockito.mock(HttpClient.class);
|
|
||||||
HttpResponse<String> response = Mockito.mock(HttpResponse.class);
|
|
||||||
|
|
||||||
httpClientStatic.when(HttpClient::newBuilder).thenReturn(builder);
|
|
||||||
when(builder.followRedirects(HttpClient.Redirect.NORMAL)).thenReturn(builder);
|
|
||||||
when(builder.connectTimeout(any(Duration.class))).thenReturn(builder);
|
|
||||||
when(builder.build()).thenReturn(client);
|
|
||||||
|
|
||||||
when(client.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class)))
|
|
||||||
.thenReturn(response);
|
|
||||||
when(response.statusCode()).thenReturn(200);
|
|
||||||
when(response.body()).thenReturn(body);
|
|
||||||
|
|
||||||
return httpClientStatic;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,9 +42,7 @@ public class PdfToCbzUtilsTest {
|
|||||||
IllegalArgumentException exception =
|
IllegalArgumentException exception =
|
||||||
Assertions.assertThrows(
|
Assertions.assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> {
|
() -> PdfToCbzUtils.convertPdfToCbz(null, 300, pdfDocumentFactory));
|
||||||
PdfToCbzUtils.convertPdfToCbz(null, 300, pdfDocumentFactory);
|
|
||||||
});
|
|
||||||
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
|
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,9 +54,7 @@ public class PdfToCbzUtilsTest {
|
|||||||
IllegalArgumentException exception =
|
IllegalArgumentException exception =
|
||||||
Assertions.assertThrows(
|
Assertions.assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> {
|
() -> PdfToCbzUtils.convertPdfToCbz(emptyFile, 300, pdfDocumentFactory));
|
||||||
PdfToCbzUtils.convertPdfToCbz(emptyFile, 300, pdfDocumentFactory);
|
|
||||||
});
|
|
||||||
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
|
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,9 +66,7 @@ public class PdfToCbzUtilsTest {
|
|||||||
IllegalArgumentException exception =
|
IllegalArgumentException exception =
|
||||||
Assertions.assertThrows(
|
Assertions.assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> {
|
() -> PdfToCbzUtils.convertPdfToCbz(nonPdfFile, 300, pdfDocumentFactory));
|
||||||
PdfToCbzUtils.convertPdfToCbz(nonPdfFile, 300, pdfDocumentFactory);
|
|
||||||
});
|
|
||||||
Assertions.assertEquals("File must be a PDF", exception.getMessage());
|
Assertions.assertEquals("File must be a PDF", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,9 +84,7 @@ public class PdfToCbzUtilsTest {
|
|||||||
// structure
|
// structure
|
||||||
Assertions.assertThrows(
|
Assertions.assertThrows(
|
||||||
Exception.class,
|
Exception.class,
|
||||||
() -> {
|
() -> PdfToCbzUtils.convertPdfToCbz(pdfFile, 300, pdfDocumentFactory));
|
||||||
PdfToCbzUtils.convertPdfToCbz(pdfFile, 300, pdfDocumentFactory);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verify that load was called
|
// Verify that load was called
|
||||||
Mockito.verify(pdfDocumentFactory).load(pdfFile);
|
Mockito.verify(pdfDocumentFactory).load(pdfFile);
|
||||||
|
|||||||
@ -116,7 +116,7 @@ class PdfVectorExportControllerTest {
|
|||||||
void convertGhostscript_pdfPassThrough_success() throws Exception {
|
void convertGhostscript_pdfPassThrough_success() throws Exception {
|
||||||
when(endpointConfiguration.isGroupEnabled("Ghostscript")).thenReturn(false);
|
when(endpointConfiguration.isGroupEnabled("Ghostscript")).thenReturn(false);
|
||||||
|
|
||||||
byte[] content = new byte[] {1};
|
byte[] content = {1};
|
||||||
MockMultipartFile file =
|
MockMultipartFile file =
|
||||||
new MockMultipartFile(
|
new MockMultipartFile(
|
||||||
"fileInput", "input.pdf", MediaType.APPLICATION_PDF_VALUE, content);
|
"fileInput", "input.pdf", MediaType.APPLICATION_PDF_VALUE, content);
|
||||||
@ -131,7 +131,7 @@ class PdfVectorExportControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void convertGhostscript_unsupportedFormatThrows() throws Exception {
|
void convertGhostscript_unsupportedFormatThrows() {
|
||||||
when(endpointConfiguration.isGroupEnabled("Ghostscript")).thenReturn(false);
|
when(endpointConfiguration.isGroupEnabled("Ghostscript")).thenReturn(false);
|
||||||
MockMultipartFile file =
|
MockMultipartFile file =
|
||||||
new MockMultipartFile(
|
new MockMultipartFile(
|
||||||
|
|||||||
@ -49,13 +49,7 @@ class PipelineProcessorTest {
|
|||||||
PipelineConfig config = new PipelineConfig();
|
PipelineConfig config = new PipelineConfig();
|
||||||
config.setOperations(List.of(op));
|
config.setOperations(List.of(op));
|
||||||
|
|
||||||
Resource file =
|
Resource file = new MyFileByteArrayResource();
|
||||||
new ByteArrayResource("data".getBytes()) {
|
|
||||||
@Override
|
|
||||||
public String getFilename() {
|
|
||||||
return "test.pdf";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
List<Resource> files = List.of(file);
|
List<Resource> files = List.of(file);
|
||||||
|
|
||||||
@ -77,4 +71,15 @@ class PipelineProcessorTest {
|
|||||||
assertFalse(result.isHasErrors(), "No errors should occur");
|
assertFalse(result.isHasErrors(), "No errors should occur");
|
||||||
assertTrue(result.getOutputFiles().isEmpty(), "Filtered file list should be empty");
|
assertTrue(result.getOutputFiles().isEmpty(), "Filtered file list should be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class MyFileByteArrayResource extends ByteArrayResource {
|
||||||
|
public MyFileByteArrayResource() {
|
||||||
|
super("data".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFilename() {
|
||||||
|
return "test.pdf";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,61 +69,45 @@ class RedactControllerTest {
|
|||||||
private PDDocument realDocument;
|
private PDDocument realDocument;
|
||||||
private PDPage realPage;
|
private PDPage realPage;
|
||||||
|
|
||||||
// Helpers
|
private static byte[] createSimplePdfContent() throws IOException {
|
||||||
private void testAutoRedaction(
|
try (PDDocument doc = new PDDocument()) {
|
||||||
String searchText,
|
PDPage page = new PDPage(PDRectangle.A4);
|
||||||
boolean useRegex,
|
doc.addPage(page);
|
||||||
boolean wholeWordSearch,
|
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
|
||||||
String redactColor,
|
contentStream.beginText();
|
||||||
float padding,
|
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 12);
|
||||||
boolean convertToImage,
|
contentStream.newLineAtOffset(100, 700);
|
||||||
boolean expectSuccess)
|
contentStream.showText("This is a simple PDF.");
|
||||||
throws Exception {
|
contentStream.endText();
|
||||||
RedactPdfRequest request = createRedactPdfRequest();
|
|
||||||
request.setListOfText(searchText);
|
|
||||||
request.setUseRegex(useRegex);
|
|
||||||
request.setWholeWordSearch(wholeWordSearch);
|
|
||||||
request.setRedactColor(redactColor);
|
|
||||||
request.setCustomPadding(padding);
|
|
||||||
request.setConvertPDFToImage(convertToImage);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ResponseEntity<byte[]> 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));
|
|
||||||
verify(mockDocument, times(1)).close();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (expectSuccess) {
|
|
||||||
log.info("Redaction test completed with graceful handling: {}", e.getMessage());
|
|
||||||
} else {
|
|
||||||
assertNotNull(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
doc.save(baos);
|
||||||
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testManualRedaction(List<RedactionArea> redactionAreas, boolean convertToImage)
|
private static List<RedactionArea> createValidRedactionAreas() {
|
||||||
throws Exception {
|
List<RedactionArea> areas = new ArrayList<>();
|
||||||
ManualRedactPdfRequest request = createManualRedactPdfRequest();
|
|
||||||
request.setRedactions(redactionAreas);
|
|
||||||
request.setConvertPDFToImage(convertToImage);
|
|
||||||
|
|
||||||
try {
|
RedactionArea area1 = new RedactionArea();
|
||||||
ResponseEntity<byte[]> response = redactController.redactPDF(request);
|
area1.setPage(1);
|
||||||
|
area1.setX(100.0);
|
||||||
|
area1.setY(100.0);
|
||||||
|
area1.setWidth(200.0);
|
||||||
|
area1.setHeight(50.0);
|
||||||
|
area1.setColor("000000");
|
||||||
|
areas.add(area1);
|
||||||
|
|
||||||
if (response != null) {
|
RedactionArea area2 = new RedactionArea();
|
||||||
assertNotNull(response);
|
area2.setPage(1);
|
||||||
assertEquals(200, response.getStatusCode().value());
|
area2.setX(300.0);
|
||||||
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
|
area2.setY(200.0);
|
||||||
}
|
area2.setWidth(150.0);
|
||||||
} catch (Exception e) {
|
area2.setHeight(30.0);
|
||||||
log.info("Manual redaction test completed with graceful handling: {}", e.getMessage());
|
area2.setColor("FF0000");
|
||||||
}
|
areas.add(area2);
|
||||||
|
|
||||||
|
return areas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@ -189,16 +173,18 @@ class RedactControllerTest {
|
|||||||
setupRealDocument();
|
setupRealDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRealDocument() throws IOException {
|
private static List<RedactionArea> createInvalidRedactionAreas() {
|
||||||
realDocument = new PDDocument();
|
List<RedactionArea> areas = new ArrayList<>();
|
||||||
realPage = new PDPage(PDRectangle.A4);
|
|
||||||
realDocument.addPage(realPage);
|
|
||||||
|
|
||||||
// Set up basic page resources
|
RedactionArea invalidArea = new RedactionArea();
|
||||||
PDResources resources = new PDResources();
|
invalidArea.setPage(null); // Invalid - null page
|
||||||
resources.put(
|
invalidArea.setX(100.0);
|
||||||
COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
invalidArea.setY(100.0);
|
||||||
realPage.setResources(resources);
|
invalidArea.setWidth(200.0);
|
||||||
|
invalidArea.setHeight(50.0);
|
||||||
|
areas.add(invalidArea);
|
||||||
|
|
||||||
|
return areas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
@ -607,13 +593,266 @@ class RedactControllerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<RedactionArea> createMultipleRedactionAreas() {
|
||||||
|
List<RedactionArea> areas = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
RedactionArea area = new RedactionArea();
|
||||||
|
area.setPage(1);
|
||||||
|
area.setX(50.0 + (i * 60));
|
||||||
|
area.setY(50.0 + (i * 40));
|
||||||
|
area.setWidth(50.0);
|
||||||
|
area.setHeight(30.0);
|
||||||
|
area.setColor(String.format("%06X", i * 0x333333));
|
||||||
|
areas.add(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
return areas;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<RedactionArea> createOverlappingRedactionAreas() {
|
||||||
|
List<RedactionArea> areas = new ArrayList<>();
|
||||||
|
|
||||||
|
RedactionArea area1 = new RedactionArea();
|
||||||
|
area1.setPage(1);
|
||||||
|
area1.setX(100.0);
|
||||||
|
area1.setY(100.0);
|
||||||
|
area1.setWidth(200.0);
|
||||||
|
area1.setHeight(100.0);
|
||||||
|
area1.setColor("FF0000");
|
||||||
|
areas.add(area1);
|
||||||
|
|
||||||
|
RedactionArea area2 = new RedactionArea();
|
||||||
|
area2.setPage(1);
|
||||||
|
area2.setX(150.0); // Overlaps with area1
|
||||||
|
area2.setY(150.0); // Overlaps with area1
|
||||||
|
area2.setWidth(200.0);
|
||||||
|
area2.setHeight(100.0);
|
||||||
|
area2.setColor("00FF00");
|
||||||
|
areas.add(area2);
|
||||||
|
|
||||||
|
return areas;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper for token creation
|
||||||
|
private static List<Object> createSampleTokenList() {
|
||||||
|
return List.of(
|
||||||
|
Operator.getOperator("BT"),
|
||||||
|
COSName.getPDFName("F1"),
|
||||||
|
new COSFloat(12),
|
||||||
|
Operator.getOperator("Tf"),
|
||||||
|
new COSString("Sample text"),
|
||||||
|
Operator.getOperator("Tj"),
|
||||||
|
Operator.getOperator("ET"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private RedactPdfRequest createRedactPdfRequest() {
|
||||||
|
RedactPdfRequest request = new RedactPdfRequest();
|
||||||
|
request.setFileInput(mockPdfFile);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ManualRedactPdfRequest createManualRedactPdfRequest() {
|
||||||
|
ManualRedactPdfRequest request = new ManualRedactPdfRequest();
|
||||||
|
request.setFileInput(mockPdfFile);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String extractTextFromTokens(List<Object> tokens) {
|
||||||
|
StringBuilder text = new StringBuilder();
|
||||||
|
for (Object token : tokens) {
|
||||||
|
if (token instanceof COSString cosString) {
|
||||||
|
text.append(cosString.getString());
|
||||||
|
} else if (token instanceof COSArray array) {
|
||||||
|
for (int i = 0; i < array.size(); i++) {
|
||||||
|
if (array.getObject(i) instanceof COSString cosString) {
|
||||||
|
text.append(cosString.getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] readAllBytes(InputStream inputStream) throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
int nRead;
|
||||||
|
byte[] data = new byte[1024];
|
||||||
|
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||||
|
buffer.write(data, 0, nRead);
|
||||||
|
}
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
private void testAutoRedaction(
|
||||||
|
String searchText,
|
||||||
|
boolean useRegex,
|
||||||
|
boolean wholeWordSearch,
|
||||||
|
String redactColor,
|
||||||
|
float padding,
|
||||||
|
boolean convertToImage,
|
||||||
|
boolean expectSuccess) {
|
||||||
|
RedactPdfRequest request = createRedactPdfRequest();
|
||||||
|
request.setListOfText(searchText);
|
||||||
|
request.setUseRegex(useRegex);
|
||||||
|
request.setWholeWordSearch(wholeWordSearch);
|
||||||
|
request.setRedactColor(redactColor);
|
||||||
|
request.setCustomPadding(padding);
|
||||||
|
request.setConvertPDFToImage(convertToImage);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResponseEntity<byte[]> 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));
|
||||||
|
verify(mockDocument, times(1)).close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (expectSuccess) {
|
||||||
|
log.info("Redaction test completed with graceful handling: {}", e.getMessage());
|
||||||
|
} else {
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testManualRedaction(List<RedactionArea> redactionAreas, boolean convertToImage) {
|
||||||
|
ManualRedactPdfRequest request = createManualRedactPdfRequest();
|
||||||
|
request.setRedactions(redactionAreas);
|
||||||
|
request.setConvertPDFToImage(convertToImage);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResponseEntity<byte[]> response = redactController.redactPDF(request);
|
||||||
|
|
||||||
|
if (response != null) {
|
||||||
|
assertNotNull(response);
|
||||||
|
assertEquals(200, response.getStatusCode().value());
|
||||||
|
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info("Manual redaction test completed with graceful handling: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupRealDocument() {
|
||||||
|
realDocument = new PDDocument();
|
||||||
|
realPage = new PDPage(PDRectangle.A4);
|
||||||
|
realDocument.addPage(realPage);
|
||||||
|
|
||||||
|
// Set up basic page resources
|
||||||
|
PDResources resources = new PDResources();
|
||||||
|
resources.put(
|
||||||
|
COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
||||||
|
realPage.setResources(resources);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods for real PDF content creation
|
||||||
|
private void createRealPageWithSimpleText(String text) throws IOException {
|
||||||
|
realPage = new PDPage(PDRectangle.A4);
|
||||||
|
while (realDocument.getNumberOfPages() > 0) {
|
||||||
|
realDocument.removePage(0);
|
||||||
|
}
|
||||||
|
realDocument.addPage(realPage);
|
||||||
|
realPage.setResources(new PDResources());
|
||||||
|
realPage.getResources()
|
||||||
|
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
||||||
|
|
||||||
|
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
||||||
|
contentStream.beginText();
|
||||||
|
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
||||||
|
contentStream.newLineAtOffset(50, 750);
|
||||||
|
contentStream.showText(text);
|
||||||
|
contentStream.endText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRealPageWithTJArrayText() throws IOException {
|
||||||
|
realPage = new PDPage(PDRectangle.A4);
|
||||||
|
while (realDocument.getNumberOfPages() > 0) {
|
||||||
|
realDocument.removePage(0);
|
||||||
|
}
|
||||||
|
realDocument.addPage(realPage);
|
||||||
|
realPage.setResources(new PDResources());
|
||||||
|
realPage.getResources()
|
||||||
|
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
||||||
|
|
||||||
|
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
||||||
|
contentStream.beginText();
|
||||||
|
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
||||||
|
contentStream.newLineAtOffset(50, 750);
|
||||||
|
|
||||||
|
contentStream.showText("This is ");
|
||||||
|
contentStream.newLineAtOffset(-10, 0); // Simulate positioning
|
||||||
|
contentStream.showText("secret");
|
||||||
|
contentStream.newLineAtOffset(10, 0); // Reset positioning
|
||||||
|
contentStream.showText(" information");
|
||||||
|
contentStream.endText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRealPageWithMixedContent() throws IOException {
|
||||||
|
realPage = new PDPage(PDRectangle.A4);
|
||||||
|
while (realDocument.getNumberOfPages() > 0) {
|
||||||
|
realDocument.removePage(0);
|
||||||
|
}
|
||||||
|
realDocument.addPage(realPage);
|
||||||
|
realPage.setResources(new PDResources());
|
||||||
|
realPage.getResources()
|
||||||
|
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
||||||
|
|
||||||
|
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
||||||
|
contentStream.setLineWidth(2);
|
||||||
|
contentStream.moveTo(100, 100);
|
||||||
|
contentStream.lineTo(200, 200);
|
||||||
|
contentStream.stroke();
|
||||||
|
|
||||||
|
contentStream.beginText();
|
||||||
|
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
||||||
|
contentStream.newLineAtOffset(50, 750);
|
||||||
|
contentStream.showText("Please redact this content");
|
||||||
|
contentStream.endText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRealPageWithSpecificOperator(String operatorName) throws IOException {
|
||||||
|
createRealPageWithSimpleText("sensitive data");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRealPageWithPositionedText() throws IOException {
|
||||||
|
realPage = new PDPage(PDRectangle.A4);
|
||||||
|
while (realDocument.getNumberOfPages() > 0) {
|
||||||
|
realDocument.removePage(0);
|
||||||
|
}
|
||||||
|
realDocument.addPage(realPage);
|
||||||
|
realPage.setResources(new PDResources());
|
||||||
|
realPage.getResources()
|
||||||
|
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
||||||
|
|
||||||
|
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
||||||
|
contentStream.beginText();
|
||||||
|
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
||||||
|
contentStream.newLineAtOffset(50, 750);
|
||||||
|
contentStream.showText("Normal text ");
|
||||||
|
contentStream.newLineAtOffset(100, 0);
|
||||||
|
contentStream.showText("confidential");
|
||||||
|
contentStream.newLineAtOffset(100, 0);
|
||||||
|
contentStream.showText(" more text");
|
||||||
|
contentStream.endText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Error Handling and Edge Cases")
|
@DisplayName("Error Handling and Edge Cases")
|
||||||
class ErrorHandlingTests {
|
class ErrorHandlingTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should handle null file input gracefully")
|
@DisplayName("Should handle null file input gracefully")
|
||||||
void handleNullFileInput() throws Exception {
|
void handleNullFileInput() {
|
||||||
RedactPdfRequest request = new RedactPdfRequest();
|
RedactPdfRequest request = new RedactPdfRequest();
|
||||||
request.setFileInput(null);
|
request.setFileInput(null);
|
||||||
request.setListOfText("test");
|
request.setListOfText("test");
|
||||||
@ -630,7 +869,7 @@ class RedactControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should handle malformed PDF gracefully")
|
@DisplayName("Should handle malformed PDF gracefully")
|
||||||
void handleMalformedPdfGracefully() throws Exception {
|
void handleMalformedPdfGracefully() {
|
||||||
MockMultipartFile malformedFile =
|
MockMultipartFile malformedFile =
|
||||||
new MockMultipartFile(
|
new MockMultipartFile(
|
||||||
"fileInput",
|
"fileInput",
|
||||||
@ -674,7 +913,7 @@ class RedactControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should handle null redact color gracefully")
|
@DisplayName("Should handle null redact color gracefully")
|
||||||
void handleNullRedactColor() throws Exception {
|
void handleNullRedactColor() {
|
||||||
RedactPdfRequest request = createRedactPdfRequest();
|
RedactPdfRequest request = createRedactPdfRequest();
|
||||||
request.setListOfText("test");
|
request.setListOfText("test");
|
||||||
request.setRedactColor(null);
|
request.setRedactColor(null);
|
||||||
@ -722,34 +961,50 @@ class RedactControllerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Object> getOriginalTokens() throws Exception {
|
||||||
|
// Create a new page to avoid side effects from other tests
|
||||||
|
PDPage pageForTokenExtraction = new PDPage(PDRectangle.A4);
|
||||||
|
pageForTokenExtraction.setResources(realPage.getResources());
|
||||||
|
try (PDPageContentStream contentStream =
|
||||||
|
new PDPageContentStream(realDocument, pageForTokenExtraction)) {
|
||||||
|
contentStream.beginText();
|
||||||
|
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
||||||
|
contentStream.newLineAtOffset(50, 750);
|
||||||
|
contentStream.showText("Original content");
|
||||||
|
contentStream.endText();
|
||||||
|
}
|
||||||
|
return redactController.createTokensWithoutTargetText(
|
||||||
|
realDocument, pageForTokenExtraction, Collections.emptySet(), false, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Color Decoding Utility Tests")
|
@DisplayName("Color Decoding Utility Tests")
|
||||||
class ColorDecodingTests {
|
class ColorDecodingTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should decode valid hex color with hash")
|
@DisplayName("Should decode valid hex color with hash")
|
||||||
void decodeValidHexColorWithHash() throws Exception {
|
void decodeValidHexColorWithHash() {
|
||||||
Color result = redactController.decodeOrDefault("#FF0000");
|
Color result = redactController.decodeOrDefault("#FF0000");
|
||||||
assertEquals(Color.RED, result);
|
assertEquals(Color.RED, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should decode valid hex color without hash")
|
@DisplayName("Should decode valid hex color without hash")
|
||||||
void decodeValidHexColorWithoutHash() throws Exception {
|
void decodeValidHexColorWithoutHash() {
|
||||||
Color result = redactController.decodeOrDefault("FF0000");
|
Color result = redactController.decodeOrDefault("FF0000");
|
||||||
assertEquals(Color.RED, result);
|
assertEquals(Color.RED, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should default to black for null color")
|
@DisplayName("Should default to black for null color")
|
||||||
void defaultToBlackForNullColor() throws Exception {
|
void defaultToBlackForNullColor() {
|
||||||
Color result = redactController.decodeOrDefault(null);
|
Color result = redactController.decodeOrDefault(null);
|
||||||
assertEquals(Color.BLACK, result);
|
assertEquals(Color.BLACK, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should default to black for invalid color")
|
@DisplayName("Should default to black for invalid color")
|
||||||
void defaultToBlackForInvalidColor() throws Exception {
|
void defaultToBlackForInvalidColor() {
|
||||||
Color result = redactController.decodeOrDefault("invalid-color");
|
Color result = redactController.decodeOrDefault("invalid-color");
|
||||||
assertEquals(Color.BLACK, result);
|
assertEquals(Color.BLACK, result);
|
||||||
}
|
}
|
||||||
@ -761,7 +1016,7 @@ class RedactControllerTest {
|
|||||||
"0000FF"
|
"0000FF"
|
||||||
})
|
})
|
||||||
@DisplayName("Should handle various valid color formats")
|
@DisplayName("Should handle various valid color formats")
|
||||||
void handleVariousValidColorFormats(String colorInput) throws Exception {
|
void handleVariousValidColorFormats(String colorInput) {
|
||||||
Color result = redactController.decodeOrDefault(colorInput);
|
Color result = redactController.decodeOrDefault(colorInput);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
@ -777,7 +1032,7 @@ class RedactControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should handle short hex codes appropriately")
|
@DisplayName("Should handle short hex codes appropriately")
|
||||||
void handleShortHexCodes() throws Exception {
|
void handleShortHexCodes() {
|
||||||
Color result1 = redactController.decodeOrDefault("123");
|
Color result1 = redactController.decodeOrDefault("123");
|
||||||
Color result2 = redactController.decodeOrDefault("#12");
|
Color result2 = redactController.decodeOrDefault("#12");
|
||||||
|
|
||||||
@ -786,6 +1041,15 @@ class RedactControllerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String extractTextFromModifiedPage(PDPage page) throws IOException {
|
||||||
|
if (page.getContents() != null) {
|
||||||
|
try (InputStream inputStream = page.getContents()) {
|
||||||
|
return new String(readAllBytes(inputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Content Stream Unit Tests")
|
@DisplayName("Content Stream Unit Tests")
|
||||||
class ContentStreamUnitTests {
|
class ContentStreamUnitTests {
|
||||||
@ -974,7 +1238,7 @@ class RedactControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Placeholder creation should maintain text width")
|
@DisplayName("Placeholder creation should maintain text width")
|
||||||
void shouldCreateWidthMatchingPlaceholder() throws Exception {
|
void shouldCreateWidthMatchingPlaceholder() {
|
||||||
String originalText = "confidential";
|
String originalText = "confidential";
|
||||||
String placeholder =
|
String placeholder =
|
||||||
redactController.createPlaceholderWithFont(
|
redactController.createPlaceholderWithFont(
|
||||||
@ -988,7 +1252,7 @@ class RedactControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Placeholder should handle special characters")
|
@DisplayName("Placeholder should handle special characters")
|
||||||
void shouldHandleSpecialCharactersInPlaceholder() throws Exception {
|
void shouldHandleSpecialCharactersInPlaceholder() {
|
||||||
String originalText = "café naïve";
|
String originalText = "café naïve";
|
||||||
String placeholder =
|
String placeholder =
|
||||||
redactController.createPlaceholderWithFont(
|
redactController.createPlaceholderWithFont(
|
||||||
@ -1163,270 +1427,4 @@ class RedactControllerTest {
|
|||||||
assertTrue(response.getBody().length > 0);
|
assertTrue(response.getBody().length > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RedactPdfRequest createRedactPdfRequest() {
|
|
||||||
RedactPdfRequest request = new RedactPdfRequest();
|
|
||||||
request.setFileInput(mockPdfFile);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ManualRedactPdfRequest createManualRedactPdfRequest() {
|
|
||||||
ManualRedactPdfRequest request = new ManualRedactPdfRequest();
|
|
||||||
request.setFileInput(mockPdfFile);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] createSimplePdfContent() throws IOException {
|
|
||||||
try (PDDocument doc = new PDDocument()) {
|
|
||||||
PDPage page = new PDPage(PDRectangle.A4);
|
|
||||||
doc.addPage(page);
|
|
||||||
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
|
|
||||||
contentStream.beginText();
|
|
||||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 12);
|
|
||||||
contentStream.newLineAtOffset(100, 700);
|
|
||||||
contentStream.showText("This is a simple PDF.");
|
|
||||||
contentStream.endText();
|
|
||||||
}
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
doc.save(baos);
|
|
||||||
return baos.toByteArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RedactionArea> createValidRedactionAreas() {
|
|
||||||
List<RedactionArea> areas = new ArrayList<>();
|
|
||||||
|
|
||||||
RedactionArea area1 = new RedactionArea();
|
|
||||||
area1.setPage(1);
|
|
||||||
area1.setX(100.0);
|
|
||||||
area1.setY(100.0);
|
|
||||||
area1.setWidth(200.0);
|
|
||||||
area1.setHeight(50.0);
|
|
||||||
area1.setColor("000000");
|
|
||||||
areas.add(area1);
|
|
||||||
|
|
||||||
RedactionArea area2 = new RedactionArea();
|
|
||||||
area2.setPage(1);
|
|
||||||
area2.setX(300.0);
|
|
||||||
area2.setY(200.0);
|
|
||||||
area2.setWidth(150.0);
|
|
||||||
area2.setHeight(30.0);
|
|
||||||
area2.setColor("FF0000");
|
|
||||||
areas.add(area2);
|
|
||||||
|
|
||||||
return areas;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RedactionArea> createInvalidRedactionAreas() {
|
|
||||||
List<RedactionArea> areas = new ArrayList<>();
|
|
||||||
|
|
||||||
RedactionArea invalidArea = new RedactionArea();
|
|
||||||
invalidArea.setPage(null); // Invalid - null page
|
|
||||||
invalidArea.setX(100.0);
|
|
||||||
invalidArea.setY(100.0);
|
|
||||||
invalidArea.setWidth(200.0);
|
|
||||||
invalidArea.setHeight(50.0);
|
|
||||||
areas.add(invalidArea);
|
|
||||||
|
|
||||||
return areas;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RedactionArea> createMultipleRedactionAreas() {
|
|
||||||
List<RedactionArea> areas = new ArrayList<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
RedactionArea area = new RedactionArea();
|
|
||||||
area.setPage(1);
|
|
||||||
area.setX(50.0 + (i * 60));
|
|
||||||
area.setY(50.0 + (i * 40));
|
|
||||||
area.setWidth(50.0);
|
|
||||||
area.setHeight(30.0);
|
|
||||||
area.setColor(String.format("%06X", i * 0x333333));
|
|
||||||
areas.add(area);
|
|
||||||
}
|
|
||||||
|
|
||||||
return areas;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RedactionArea> createOverlappingRedactionAreas() {
|
|
||||||
List<RedactionArea> areas = new ArrayList<>();
|
|
||||||
|
|
||||||
RedactionArea area1 = new RedactionArea();
|
|
||||||
area1.setPage(1);
|
|
||||||
area1.setX(100.0);
|
|
||||||
area1.setY(100.0);
|
|
||||||
area1.setWidth(200.0);
|
|
||||||
area1.setHeight(100.0);
|
|
||||||
area1.setColor("FF0000");
|
|
||||||
areas.add(area1);
|
|
||||||
|
|
||||||
RedactionArea area2 = new RedactionArea();
|
|
||||||
area2.setPage(1);
|
|
||||||
area2.setX(150.0); // Overlaps with area1
|
|
||||||
area2.setY(150.0); // Overlaps with area1
|
|
||||||
area2.setWidth(200.0);
|
|
||||||
area2.setHeight(100.0);
|
|
||||||
area2.setColor("00FF00");
|
|
||||||
areas.add(area2);
|
|
||||||
|
|
||||||
return areas;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper methods for real PDF content creation
|
|
||||||
private void createRealPageWithSimpleText(String text) throws IOException {
|
|
||||||
realPage = new PDPage(PDRectangle.A4);
|
|
||||||
while (realDocument.getNumberOfPages() > 0) {
|
|
||||||
realDocument.removePage(0);
|
|
||||||
}
|
|
||||||
realDocument.addPage(realPage);
|
|
||||||
realPage.setResources(new PDResources());
|
|
||||||
realPage.getResources()
|
|
||||||
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
|
||||||
|
|
||||||
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
|
||||||
contentStream.beginText();
|
|
||||||
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
|
||||||
contentStream.newLineAtOffset(50, 750);
|
|
||||||
contentStream.showText(text);
|
|
||||||
contentStream.endText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRealPageWithTJArrayText() throws IOException {
|
|
||||||
realPage = new PDPage(PDRectangle.A4);
|
|
||||||
while (realDocument.getNumberOfPages() > 0) {
|
|
||||||
realDocument.removePage(0);
|
|
||||||
}
|
|
||||||
realDocument.addPage(realPage);
|
|
||||||
realPage.setResources(new PDResources());
|
|
||||||
realPage.getResources()
|
|
||||||
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
|
||||||
|
|
||||||
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
|
||||||
contentStream.beginText();
|
|
||||||
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
|
||||||
contentStream.newLineAtOffset(50, 750);
|
|
||||||
|
|
||||||
contentStream.showText("This is ");
|
|
||||||
contentStream.newLineAtOffset(-10, 0); // Simulate positioning
|
|
||||||
contentStream.showText("secret");
|
|
||||||
contentStream.newLineAtOffset(10, 0); // Reset positioning
|
|
||||||
contentStream.showText(" information");
|
|
||||||
contentStream.endText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRealPageWithMixedContent() throws IOException {
|
|
||||||
realPage = new PDPage(PDRectangle.A4);
|
|
||||||
while (realDocument.getNumberOfPages() > 0) {
|
|
||||||
realDocument.removePage(0);
|
|
||||||
}
|
|
||||||
realDocument.addPage(realPage);
|
|
||||||
realPage.setResources(new PDResources());
|
|
||||||
realPage.getResources()
|
|
||||||
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
|
||||||
|
|
||||||
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
|
||||||
contentStream.setLineWidth(2);
|
|
||||||
contentStream.moveTo(100, 100);
|
|
||||||
contentStream.lineTo(200, 200);
|
|
||||||
contentStream.stroke();
|
|
||||||
|
|
||||||
contentStream.beginText();
|
|
||||||
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
|
||||||
contentStream.newLineAtOffset(50, 750);
|
|
||||||
contentStream.showText("Please redact this content");
|
|
||||||
contentStream.endText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRealPageWithSpecificOperator(String operatorName) throws IOException {
|
|
||||||
createRealPageWithSimpleText("sensitive data");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRealPageWithPositionedText() throws IOException {
|
|
||||||
realPage = new PDPage(PDRectangle.A4);
|
|
||||||
while (realDocument.getNumberOfPages() > 0) {
|
|
||||||
realDocument.removePage(0);
|
|
||||||
}
|
|
||||||
realDocument.addPage(realPage);
|
|
||||||
realPage.setResources(new PDResources());
|
|
||||||
realPage.getResources()
|
|
||||||
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
|
|
||||||
|
|
||||||
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
|
|
||||||
contentStream.beginText();
|
|
||||||
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
|
||||||
contentStream.newLineAtOffset(50, 750);
|
|
||||||
contentStream.showText("Normal text ");
|
|
||||||
contentStream.newLineAtOffset(100, 0);
|
|
||||||
contentStream.showText("confidential");
|
|
||||||
contentStream.newLineAtOffset(100, 0);
|
|
||||||
contentStream.showText(" more text");
|
|
||||||
contentStream.endText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper for token creation
|
|
||||||
private List<Object> createSampleTokenList() {
|
|
||||||
return List.of(
|
|
||||||
Operator.getOperator("BT"),
|
|
||||||
COSName.getPDFName("F1"),
|
|
||||||
new COSFloat(12),
|
|
||||||
Operator.getOperator("Tf"),
|
|
||||||
new COSString("Sample text"),
|
|
||||||
Operator.getOperator("Tj"),
|
|
||||||
Operator.getOperator("ET"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Object> getOriginalTokens() throws Exception {
|
|
||||||
// Create a new page to avoid side effects from other tests
|
|
||||||
PDPage pageForTokenExtraction = new PDPage(PDRectangle.A4);
|
|
||||||
pageForTokenExtraction.setResources(realPage.getResources());
|
|
||||||
try (PDPageContentStream contentStream =
|
|
||||||
new PDPageContentStream(realDocument, pageForTokenExtraction)) {
|
|
||||||
contentStream.beginText();
|
|
||||||
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
|
|
||||||
contentStream.newLineAtOffset(50, 750);
|
|
||||||
contentStream.showText("Original content");
|
|
||||||
contentStream.endText();
|
|
||||||
}
|
|
||||||
return redactController.createTokensWithoutTargetText(
|
|
||||||
realDocument, pageForTokenExtraction, Collections.emptySet(), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String extractTextFromTokens(List<Object> tokens) {
|
|
||||||
StringBuilder text = new StringBuilder();
|
|
||||||
for (Object token : tokens) {
|
|
||||||
if (token instanceof COSString cosString) {
|
|
||||||
text.append(cosString.getString());
|
|
||||||
} else if (token instanceof COSArray array) {
|
|
||||||
for (int i = 0; i < array.size(); i++) {
|
|
||||||
if (array.getObject(i) instanceof COSString cosString) {
|
|
||||||
text.append(cosString.getString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return text.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String extractTextFromModifiedPage(PDPage page) throws IOException {
|
|
||||||
if (page.getContents() != null) {
|
|
||||||
try (InputStream inputStream = page.getContents()) {
|
|
||||||
return new String(readAllBytes(inputStream));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] readAllBytes(InputStream inputStream) throws IOException {
|
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
|
||||||
int nRead;
|
|
||||||
byte[] data = new byte[1024];
|
|
||||||
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
|
||||||
buffer.write(data, 0, nRead);
|
|
||||||
}
|
|
||||||
return buffer.toByteArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,35 +16,8 @@ import stirling.software.common.model.ApplicationProperties;
|
|||||||
class UploadLimitServiceTest {
|
class UploadLimitServiceTest {
|
||||||
|
|
||||||
private UploadLimitService uploadLimitService;
|
private UploadLimitService uploadLimitService;
|
||||||
private ApplicationProperties applicationProperties;
|
|
||||||
private ApplicationProperties.System systemProps;
|
private ApplicationProperties.System systemProps;
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
applicationProperties = mock(ApplicationProperties.class);
|
|
||||||
systemProps = mock(ApplicationProperties.System.class);
|
|
||||||
when(applicationProperties.getSystem()).thenReturn(systemProps);
|
|
||||||
|
|
||||||
uploadLimitService = new UploadLimitService();
|
|
||||||
// inject mock
|
|
||||||
try {
|
|
||||||
var field = UploadLimitService.class.getDeclaredField("applicationProperties");
|
|
||||||
field.setAccessible(true);
|
|
||||||
field.set(uploadLimitService, applicationProperties);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest(name = "getUploadLimit case #{index}: input={0}, expected={1}")
|
|
||||||
@MethodSource("uploadLimitParams")
|
|
||||||
void shouldComputeUploadLimitCorrectly(String input, long expected) {
|
|
||||||
when(systemProps.getFileUploadLimit()).thenReturn(input);
|
|
||||||
|
|
||||||
long result = uploadLimitService.getUploadLimit();
|
|
||||||
assertEquals(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Stream<Arguments> uploadLimitParams() {
|
static Stream<Arguments> uploadLimitParams() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
// empty or null input yields 0
|
// empty or null input yields 0
|
||||||
@ -56,11 +29,37 @@ class UploadLimitServiceTest {
|
|||||||
// valid formats
|
// valid formats
|
||||||
Arguments.of("10KB", 10 * 1024L),
|
Arguments.of("10KB", 10 * 1024L),
|
||||||
Arguments.of("2MB", 2 * 1024 * 1024L),
|
Arguments.of("2MB", 2 * 1024 * 1024L),
|
||||||
Arguments.of("1GB", 1L * 1024 * 1024 * 1024),
|
Arguments.of("1GB", (long) 1024 * 1024 * 1024),
|
||||||
Arguments.of("5mb", 5 * 1024 * 1024L),
|
Arguments.of("5mb", 5 * 1024 * 1024L),
|
||||||
Arguments.of("0MB", 0L));
|
Arguments.of("0MB", 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "getUploadLimit case #{index}: input={0}, expected={1}")
|
||||||
|
@MethodSource("uploadLimitParams")
|
||||||
|
void shouldComputeUploadLimitCorrectly(String input, long expected) {
|
||||||
|
when(systemProps.getFileUploadLimit()).thenReturn(input);
|
||||||
|
|
||||||
|
long result = uploadLimitService.getUploadLimit();
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
ApplicationProperties applicationProperties = mock(ApplicationProperties.class);
|
||||||
|
systemProps = mock(ApplicationProperties.System.class);
|
||||||
|
when(applicationProperties.getSystem()).thenReturn(systemProps);
|
||||||
|
|
||||||
|
uploadLimitService = new UploadLimitService();
|
||||||
|
// inject mock
|
||||||
|
try {
|
||||||
|
var field = UploadLimitService.class.getDeclaredField("applicationProperties");
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(uploadLimitService, applicationProperties);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "getReadableUploadLimit case #{index}: rawValue={0}, expected={1}")
|
@ParameterizedTest(name = "getReadableUploadLimit case #{index}: rawValue={0}, expected={1}")
|
||||||
@MethodSource("readableLimitParams")
|
@MethodSource("readableLimitParams")
|
||||||
void shouldReturnReadableFormat(String rawValue, String expected) {
|
void shouldReturnReadableFormat(String rawValue, String expected) {
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -33,12 +32,19 @@ class LanguageServiceBasicTest {
|
|||||||
languageService = new LanguageServiceForTest(applicationProperties);
|
languageService = new LanguageServiceForTest(applicationProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper methods
|
||||||
|
private static Resource createMockResource(String filename) {
|
||||||
|
Resource mockResource = mock(Resource.class);
|
||||||
|
when(mockResource.getFilename()).thenReturn(filename);
|
||||||
|
return mockResource;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_BasicFunctionality() throws IOException {
|
void testGetSupportedLanguages_BasicFunctionality() {
|
||||||
// Set up mocked resources
|
// Set up mocked resources
|
||||||
Resource enResource = createMockResource("messages_en_US.properties");
|
Resource enResource = createMockResource("messages_en_US.properties");
|
||||||
Resource frResource = createMockResource("messages_fr_FR.properties");
|
Resource frResource = createMockResource("messages_fr_FR.properties");
|
||||||
Resource[] mockResources = new Resource[] {enResource, frResource};
|
Resource[] mockResources = {enResource, frResource};
|
||||||
|
|
||||||
// Configure the test service
|
// Configure the test service
|
||||||
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
||||||
@ -53,10 +59,9 @@ class LanguageServiceBasicTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_FilteringInvalidFiles() throws IOException {
|
void testGetSupportedLanguages_FilteringInvalidFiles() {
|
||||||
// Set up mocked resources with invalid files
|
// Set up mocked resources with invalid files
|
||||||
Resource[] mockResources =
|
Resource[] mockResources = {
|
||||||
new Resource[] {
|
|
||||||
createMockResource("messages_en_US.properties"), // Valid
|
createMockResource("messages_en_US.properties"), // Valid
|
||||||
createMockResource("invalid_file.properties"), // Invalid
|
createMockResource("invalid_file.properties"), // Invalid
|
||||||
createMockResource(null) // Null filename
|
createMockResource(null) // Null filename
|
||||||
@ -77,10 +82,9 @@ class LanguageServiceBasicTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_WithRestrictions() throws IOException {
|
void testGetSupportedLanguages_WithRestrictions() {
|
||||||
// Set up test resources
|
// Set up test resources
|
||||||
Resource[] mockResources =
|
Resource[] mockResources = {
|
||||||
new Resource[] {
|
|
||||||
createMockResource("messages_en_US.properties"),
|
createMockResource("messages_en_US.properties"),
|
||||||
createMockResource("messages_fr_FR.properties"),
|
createMockResource("messages_fr_FR.properties"),
|
||||||
createMockResource("messages_de_DE.properties"),
|
createMockResource("messages_de_DE.properties"),
|
||||||
@ -104,13 +108,6 @@ class LanguageServiceBasicTest {
|
|||||||
assertFalse(supportedLanguages.contains("de_DE"), "Restricted language should be excluded");
|
assertFalse(supportedLanguages.contains("de_DE"), "Restricted language should be excluded");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper methods
|
|
||||||
private Resource createMockResource(String filename) {
|
|
||||||
Resource mockResource = mock(Resource.class);
|
|
||||||
when(mockResource.getFilename()).thenReturn(filename);
|
|
||||||
return mockResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test subclass
|
// Test subclass
|
||||||
private static class LanguageServiceForTest extends LanguageService {
|
private static class LanguageServiceForTest extends LanguageService {
|
||||||
private Resource[] mockResources;
|
private Resource[] mockResources;
|
||||||
@ -124,7 +121,7 @@ class LanguageServiceBasicTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Resource[] getResourcesFromPattern(String pattern) throws IOException {
|
protected Resource[] getResourcesFromPattern(String pattern) {
|
||||||
return mockResources;
|
return mockResources;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import java.util.Set;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.common.model.ApplicationProperties.Ui;
|
import stirling.software.common.model.ApplicationProperties.Ui;
|
||||||
@ -24,10 +23,15 @@ class LanguageServiceTest {
|
|||||||
|
|
||||||
private LanguageService languageService;
|
private LanguageService languageService;
|
||||||
private ApplicationProperties applicationProperties;
|
private ApplicationProperties applicationProperties;
|
||||||
private PathMatchingResourcePatternResolver mockedResolver;
|
|
||||||
|
private static Resource createMockResource(String filename) {
|
||||||
|
Resource mockResource = mock(Resource.class);
|
||||||
|
when(mockResource.getFilename()).thenReturn(filename);
|
||||||
|
return mockResource;
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() throws Exception {
|
void setUp() {
|
||||||
// Mock ApplicationProperties
|
// Mock ApplicationProperties
|
||||||
applicationProperties = mock(ApplicationProperties.class);
|
applicationProperties = mock(ApplicationProperties.class);
|
||||||
Ui ui = mock(Ui.class);
|
Ui ui = mock(Ui.class);
|
||||||
@ -38,7 +42,7 @@ class LanguageServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_NoRestrictions() throws IOException {
|
void testGetSupportedLanguages_NoRestrictions() {
|
||||||
// Setup
|
// Setup
|
||||||
Set<String> expectedLanguages =
|
Set<String> expectedLanguages =
|
||||||
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
|
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
|
||||||
@ -61,7 +65,7 @@ class LanguageServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_WithRestrictions() throws IOException {
|
void testGetSupportedLanguages_WithRestrictions() {
|
||||||
// Setup
|
// Setup
|
||||||
Set<String> expectedLanguages =
|
Set<String> expectedLanguages =
|
||||||
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
|
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
|
||||||
@ -87,7 +91,7 @@ class LanguageServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_ExceptionHandling() throws IOException {
|
void testGetSupportedLanguages_ExceptionHandling() {
|
||||||
// Setup - make resolver throw an exception
|
// Setup - make resolver throw an exception
|
||||||
((LanguageServiceForTest) languageService).setShouldThrowException(true);
|
((LanguageServiceForTest) languageService).setShouldThrowException(true);
|
||||||
|
|
||||||
@ -98,14 +102,19 @@ class LanguageServiceTest {
|
|||||||
assertTrue(supportedLanguages.isEmpty(), "Should return empty set on exception");
|
assertTrue(supportedLanguages.isEmpty(), "Should return empty set on exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper methods to create mock resources
|
||||||
|
private Resource[] createMockResources(Set<String> languages) {
|
||||||
|
return languages.stream()
|
||||||
|
.map(lang -> createMockResource("messages_" + lang + ".properties"))
|
||||||
|
.toArray(Resource[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetSupportedLanguages_FilteringNonMatchingFiles() throws IOException {
|
void testGetSupportedLanguages_FilteringNonMatchingFiles() {
|
||||||
// Setup with some valid and some invalid filenames
|
// Setup with some valid and some invalid filenames
|
||||||
Resource[] mixedResources =
|
Resource[] mixedResources = {
|
||||||
new Resource[] {
|
|
||||||
createMockResource("messages_en_US.properties"),
|
createMockResource("messages_en_US.properties"),
|
||||||
createMockResource(
|
createMockResource("messages_en_GB.properties"), // Explicitly add en_GB resource
|
||||||
"messages_en_GB.properties"), // Explicitly add en_GB resource
|
|
||||||
createMockResource("messages_fr_FR.properties"),
|
createMockResource("messages_fr_FR.properties"),
|
||||||
createMockResource("not_a_messages_file.properties"),
|
createMockResource("not_a_messages_file.properties"),
|
||||||
createMockResource("messages_.properties"), // Invalid format
|
createMockResource("messages_.properties"), // Invalid format
|
||||||
@ -132,19 +141,6 @@ class LanguageServiceTest {
|
|||||||
// language codes
|
// language codes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper methods to create mock resources
|
|
||||||
private Resource[] createMockResources(Set<String> languages) {
|
|
||||||
return languages.stream()
|
|
||||||
.map(lang -> createMockResource("messages_" + lang + ".properties"))
|
|
||||||
.toArray(Resource[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Resource createMockResource(String filename) {
|
|
||||||
Resource mockResource = mock(Resource.class);
|
|
||||||
when(mockResource.getFilename()).thenReturn(filename);
|
|
||||||
return mockResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test subclass that allows us to control the resource resolver
|
// Test subclass that allows us to control the resource resolver
|
||||||
private static class LanguageServiceForTest extends LanguageService {
|
private static class LanguageServiceForTest extends LanguageService {
|
||||||
private Resource[] mockResources;
|
private Resource[] mockResources;
|
||||||
|
|||||||
@ -24,6 +24,24 @@ class PdfImageRemovalServiceTest {
|
|||||||
service = new PdfImageRemovalService();
|
service = new PdfImageRemovalService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper method for matching COSName in verification
|
||||||
|
private static COSName eq(final COSName value) {
|
||||||
|
return Mockito.argThat(
|
||||||
|
new org.mockito.ArgumentMatcher<>() {
|
||||||
|
@Override
|
||||||
|
public boolean matches(COSName argument) {
|
||||||
|
if (argument == null && value == null) return true;
|
||||||
|
if (argument == null || value == null) return false;
|
||||||
|
return argument.getName().equals(value.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "eq(" + (value != null ? value.getName() : "null") + ")";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testRemoveImagesFromPdf_WithImages() throws IOException {
|
void testRemoveImagesFromPdf_WithImages() throws IOException {
|
||||||
// Mock PDF document and its components
|
// Mock PDF document and its components
|
||||||
@ -54,7 +72,7 @@ class PdfImageRemovalServiceTest {
|
|||||||
when(resources.isImageXObject(nonImg)).thenReturn(false);
|
when(resources.isImageXObject(nonImg)).thenReturn(false);
|
||||||
|
|
||||||
// Execute the method
|
// Execute the method
|
||||||
PDDocument result = service.removeImagesFromPdf(document);
|
service.removeImagesFromPdf(document);
|
||||||
|
|
||||||
// Verify that images were removed
|
// Verify that images were removed
|
||||||
verify(resources, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
|
verify(resources, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
|
||||||
@ -83,7 +101,7 @@ class PdfImageRemovalServiceTest {
|
|||||||
when(resources.getXObjectNames()).thenReturn(emptyList);
|
when(resources.getXObjectNames()).thenReturn(emptyList);
|
||||||
|
|
||||||
// Execute the method
|
// Execute the method
|
||||||
PDDocument result = service.removeImagesFromPdf(document);
|
service.removeImagesFromPdf(document);
|
||||||
|
|
||||||
// Verify that no modifications were made
|
// Verify that no modifications were made
|
||||||
verify(resources, never()).put(any(COSName.class), any(PDXObject.class));
|
verify(resources, never()).put(any(COSName.class), any(PDXObject.class));
|
||||||
@ -119,28 +137,10 @@ class PdfImageRemovalServiceTest {
|
|||||||
when(resources2.isImageXObject(img2)).thenReturn(true);
|
when(resources2.isImageXObject(img2)).thenReturn(true);
|
||||||
|
|
||||||
// Execute the method
|
// Execute the method
|
||||||
PDDocument result = service.removeImagesFromPdf(document);
|
service.removeImagesFromPdf(document);
|
||||||
|
|
||||||
// Verify that images were removed from both pages
|
// Verify that images were removed from both pages
|
||||||
verify(resources1, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
|
verify(resources1, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
|
||||||
verify(resources2, times(1)).put(eq(img2), Mockito.<PDXObject>isNull());
|
verify(resources2, times(1)).put(eq(img2), Mockito.<PDXObject>isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method for matching COSName in verification
|
|
||||||
private static COSName eq(final COSName value) {
|
|
||||||
return Mockito.argThat(
|
|
||||||
new org.mockito.ArgumentMatcher<COSName>() {
|
|
||||||
@Override
|
|
||||||
public boolean matches(COSName argument) {
|
|
||||||
if (argument == null && value == null) return true;
|
|
||||||
if (argument == null || value == null) return false;
|
|
||||||
return argument.getName().equals(value.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "eq(" + (value != null ? value.getName() : "null") + ")";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,19 +26,17 @@ import stirling.software.common.service.UserServiceInterface;
|
|||||||
|
|
||||||
class PdfMetadataServiceBasicTest {
|
class PdfMetadataServiceBasicTest {
|
||||||
|
|
||||||
private ApplicationProperties applicationProperties;
|
|
||||||
private UserServiceInterface userService;
|
|
||||||
private PdfMetadataService pdfMetadataService;
|
private PdfMetadataService pdfMetadataService;
|
||||||
private final String STIRLING_PDF_LABEL = "Stirling PDF";
|
private final String STIRLING_PDF_LABEL = "Stirling PDF";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
// Set up mocks for application properties' nested objects
|
// Set up mocks for application properties' nested objects
|
||||||
applicationProperties = mock(ApplicationProperties.class);
|
ApplicationProperties applicationProperties = mock(ApplicationProperties.class);
|
||||||
Premium premium = mock(Premium.class);
|
Premium premium = mock(Premium.class);
|
||||||
ProFeatures proFeatures = mock(ProFeatures.class);
|
ProFeatures proFeatures = mock(ProFeatures.class);
|
||||||
CustomMetadata customMetadata = mock(CustomMetadata.class);
|
CustomMetadata customMetadata = mock(CustomMetadata.class);
|
||||||
userService = mock(UserServiceInterface.class);
|
UserServiceInterface userService = mock(UserServiceInterface.class);
|
||||||
|
|
||||||
when(applicationProperties.getPremium()).thenReturn(premium);
|
when(applicationProperties.getPremium()).thenReturn(premium);
|
||||||
when(premium.getProFeatures()).thenReturn(proFeatures);
|
when(premium.getProFeatures()).thenReturn(proFeatures);
|
||||||
|
|||||||
@ -24,16 +24,14 @@ class SignatureServiceTest {
|
|||||||
|
|
||||||
@TempDir Path tempDir;
|
@TempDir Path tempDir;
|
||||||
private SignatureService signatureService;
|
private SignatureService signatureService;
|
||||||
private Path personalSignatureFolder;
|
|
||||||
private Path sharedSignatureFolder;
|
|
||||||
private final String ALL_USERS_FOLDER = "ALL_USERS";
|
|
||||||
private final String TEST_USER = "testUser";
|
private final String TEST_USER = "testUser";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() throws IOException {
|
void setUp() throws IOException {
|
||||||
// Set up our test directory structure
|
// Set up our test directory structure
|
||||||
personalSignatureFolder = tempDir.resolve(TEST_USER);
|
Path personalSignatureFolder = tempDir.resolve(TEST_USER);
|
||||||
sharedSignatureFolder = tempDir.resolve(ALL_USERS_FOLDER);
|
String ALL_USERS_FOLDER = "ALL_USERS";
|
||||||
|
Path sharedSignatureFolder = tempDir.resolve(ALL_USERS_FOLDER);
|
||||||
|
|
||||||
Files.createDirectories(personalSignatureFolder);
|
Files.createDirectories(personalSignatureFolder);
|
||||||
Files.createDirectories(sharedSignatureFolder);
|
Files.createDirectories(sharedSignatureFolder);
|
||||||
@ -239,7 +237,7 @@ class SignatureServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetAvailableSignatures_EmptyUsername() throws IOException {
|
void testGetAvailableSignatures_EmptyUsername() {
|
||||||
// Mock static method for each test
|
// Mock static method for each test
|
||||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||||
mockStatic(InstallationPathConfig.class)) {
|
mockStatic(InstallationPathConfig.class)) {
|
||||||
@ -265,7 +263,7 @@ class SignatureServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetAvailableSignatures_NonExistentUser() throws IOException {
|
void testGetAvailableSignatures_NonExistentUser() {
|
||||||
// Mock static method for each test
|
// Mock static method for each test
|
||||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||||
mockStatic(InstallationPathConfig.class)) {
|
mockStatic(InstallationPathConfig.class)) {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -80,7 +81,7 @@ class JobControllerTest {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
||||||
assertEquals(mockResult, responseBody.get("jobResult"));
|
assertEquals(mockResult, Objects.requireNonNull(responseBody).get("jobResult"));
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> queueInfo = (Map<String, Object>) responseBody.get("queueInfo");
|
Map<String, Object> queueInfo = (Map<String, Object>) responseBody.get("queueInfo");
|
||||||
@ -145,7 +146,8 @@ class JobControllerTest {
|
|||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
assertEquals(contentType, response.getHeaders().getFirst("Content-Type"));
|
assertEquals(contentType, response.getHeaders().getFirst("Content-Type"));
|
||||||
assertTrue(
|
assertTrue(
|
||||||
response.getHeaders().getFirst("Content-Disposition").contains(originalFileName));
|
Objects.requireNonNull(response.getHeaders().getFirst("Content-Disposition"))
|
||||||
|
.contains(originalFileName));
|
||||||
assertEquals(fileContent, response.getBody());
|
assertEquals(fileContent, response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +168,7 @@ class JobControllerTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
|
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
|
||||||
assertTrue(response.getBody().toString().contains(errorMessage));
|
assertTrue(Objects.requireNonNull(response.getBody()).toString().contains(errorMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -185,7 +187,7 @@ class JobControllerTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
|
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
|
||||||
assertTrue(response.getBody().toString().contains("not complete"));
|
assertTrue(Objects.requireNonNull(response.getBody()).toString().contains("not complete"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -221,7 +223,10 @@ class JobControllerTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
|
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
|
||||||
assertTrue(response.getBody().toString().contains("Error retrieving file"));
|
assertTrue(
|
||||||
|
Objects.requireNonNull(response.getBody())
|
||||||
|
.toString()
|
||||||
|
.contains("Error retrieving file"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -285,7 +290,8 @@ class JobControllerTest {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
||||||
assertEquals("Job cancelled successfully", responseBody.get("message"));
|
assertEquals(
|
||||||
|
"Job cancelled successfully", Objects.requireNonNull(responseBody).get("message"));
|
||||||
assertTrue((Boolean) responseBody.get("wasQueued"));
|
assertTrue((Boolean) responseBody.get("wasQueued"));
|
||||||
assertEquals(2, responseBody.get("queuePosition"));
|
assertEquals(2, responseBody.get("queuePosition"));
|
||||||
|
|
||||||
@ -317,7 +323,8 @@ class JobControllerTest {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
||||||
assertEquals("Job cancelled successfully", responseBody.get("message"));
|
assertEquals(
|
||||||
|
"Job cancelled successfully", Objects.requireNonNull(responseBody).get("message"));
|
||||||
assertFalse((Boolean) responseBody.get("wasQueued"));
|
assertFalse((Boolean) responseBody.get("wasQueued"));
|
||||||
assertEquals("n/a", responseBody.get("queuePosition"));
|
assertEquals("n/a", responseBody.get("queuePosition"));
|
||||||
|
|
||||||
@ -369,7 +376,9 @@ class JobControllerTest {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
||||||
assertEquals("Cannot cancel job that is already complete", responseBody.get("message"));
|
assertEquals(
|
||||||
|
"Cannot cancel job that is already complete",
|
||||||
|
Objects.requireNonNull(responseBody).get("message"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -391,7 +400,9 @@ class JobControllerTest {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
|
||||||
assertEquals("You are not authorized to cancel this job", responseBody.get("message"));
|
assertEquals(
|
||||||
|
"You are not authorized to cancel this job",
|
||||||
|
Objects.requireNonNull(responseBody).get("message"));
|
||||||
|
|
||||||
// Verify no cancellation attempts were made
|
// Verify no cancellation attempts were made
|
||||||
verify(jobQueue, never()).isJobQueued(anyString());
|
verify(jobQueue, never()).isJobQueued(anyString());
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import stirling.software.common.configuration.AppConfig;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.proprietary.security.service.JwtServiceInterface;
|
import stirling.software.proprietary.security.service.JwtServiceInterface;
|
||||||
|
|
||||||
@ -23,8 +22,6 @@ class CustomLogoutSuccessHandlerTest {
|
|||||||
|
|
||||||
@Mock private ApplicationProperties.Security securityProperties;
|
@Mock private ApplicationProperties.Security securityProperties;
|
||||||
|
|
||||||
@Mock private AppConfig appConfig;
|
|
||||||
|
|
||||||
@Mock private JwtServiceInterface jwtService;
|
@Mock private JwtServiceInterface jwtService;
|
||||||
|
|
||||||
@InjectMocks private CustomLogoutSuccessHandler customLogoutSuccessHandler;
|
@InjectMocks private CustomLogoutSuccessHandler customLogoutSuccessHandler;
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class LicenseKeyCheckerTest {
|
|||||||
|
|
||||||
ApplicationProperties props = new ApplicationProperties();
|
ApplicationProperties props = new ApplicationProperties();
|
||||||
props.getPremium().setEnabled(true);
|
props.getPremium().setEnabled(true);
|
||||||
props.getPremium().setKey("file:" + file.toString());
|
props.getPremium().setKey("file:" + file);
|
||||||
when(verifier.verifyLicense("filekey")).thenReturn(License.ENTERPRISE);
|
when(verifier.verifyLicense("filekey")).thenReturn(License.ENTERPRISE);
|
||||||
|
|
||||||
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
||||||
@ -69,7 +69,7 @@ class LicenseKeyCheckerTest {
|
|||||||
Path file = temp.resolve("missing.txt");
|
Path file = temp.resolve("missing.txt");
|
||||||
ApplicationProperties props = new ApplicationProperties();
|
ApplicationProperties props = new ApplicationProperties();
|
||||||
props.getPremium().setEnabled(true);
|
props.getPremium().setEnabled(true);
|
||||||
props.getPremium().setKey("file:" + file.toString());
|
props.getPremium().setKey("file:" + file);
|
||||||
|
|
||||||
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
||||||
|
|
||||||
|
|||||||
@ -35,11 +35,9 @@ import jakarta.servlet.ServletException;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
|
||||||
import stirling.software.proprietary.security.model.exception.AuthenticationFailureException;
|
import stirling.software.proprietary.security.model.exception.AuthenticationFailureException;
|
||||||
import stirling.software.proprietary.security.service.CustomUserDetailsService;
|
import stirling.software.proprietary.security.service.CustomUserDetailsService;
|
||||||
import stirling.software.proprietary.security.service.JwtServiceInterface;
|
import stirling.software.proprietary.security.service.JwtServiceInterface;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
|
||||||
|
|
||||||
@Disabled
|
@Disabled
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
@ -49,10 +47,6 @@ class JwtAuthenticationFilterTest {
|
|||||||
|
|
||||||
@Mock private CustomUserDetailsService userDetailsService;
|
@Mock private CustomUserDetailsService userDetailsService;
|
||||||
|
|
||||||
@Mock private UserService userService;
|
|
||||||
|
|
||||||
@Mock private ApplicationProperties.Security securityProperties;
|
|
||||||
|
|
||||||
@Mock private HttpServletRequest request;
|
@Mock private HttpServletRequest request;
|
||||||
|
|
||||||
@Mock private HttpServletResponse response;
|
@Mock private HttpServletResponse response;
|
||||||
|
|||||||
@ -62,7 +62,6 @@ class JwtSaml2AuthenticationRequestRepositoryTest {
|
|||||||
String id = "testId";
|
String id = "testId";
|
||||||
String relayState = "testRelayState";
|
String relayState = "testRelayState";
|
||||||
String authnRequestUri = "example.com/authnRequest";
|
String authnRequestUri = "example.com/authnRequest";
|
||||||
Map<String, Object> claims = Map.of();
|
|
||||||
String samlRequest = "testSamlRequest";
|
String samlRequest = "testSamlRequest";
|
||||||
String relyingPartyRegistrationId = "stirling-pdf";
|
String relyingPartyRegistrationId = "stirling-pdf";
|
||||||
|
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public class EmailServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFilename() throws MessagingException {
|
void testSendEmailWithAttachmentThrowsExceptionForMissingFilename() {
|
||||||
Email email = new Email();
|
Email email = new Email();
|
||||||
email.setTo("test@example.com");
|
email.setTo("test@example.com");
|
||||||
email.setSubject("Test Email");
|
email.setSubject("Test Email");
|
||||||
@ -82,8 +82,7 @@ public class EmailServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFilenameNull()
|
void testSendEmailWithAttachmentThrowsExceptionForMissingFilenameNull() {
|
||||||
throws MessagingException {
|
|
||||||
Email email = new Email();
|
Email email = new Email();
|
||||||
email.setTo("test@example.com");
|
email.setTo("test@example.com");
|
||||||
email.setSubject("Test Email");
|
email.setSubject("Test Email");
|
||||||
@ -102,7 +101,7 @@ public class EmailServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFile() throws MessagingException {
|
void testSendEmailWithAttachmentThrowsExceptionForMissingFile() {
|
||||||
Email email = new Email();
|
Email email = new Email();
|
||||||
email.setTo("test@example.com");
|
email.setTo("test@example.com");
|
||||||
email.setSubject("Test Email");
|
email.setSubject("Test Email");
|
||||||
@ -120,7 +119,7 @@ public class EmailServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFileNull() throws MessagingException {
|
void testSendEmailWithAttachmentThrowsExceptionForMissingFileNull() {
|
||||||
Email email = new Email();
|
Email email = new Email();
|
||||||
email.setTo("test@example.com");
|
email.setTo("test@example.com");
|
||||||
email.setSubject("Test Email");
|
email.setSubject("Test Email");
|
||||||
@ -136,8 +135,7 @@ public class EmailServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSendEmailWithAttachmentThrowsExceptionForInvalidAddressNull()
|
void testSendEmailWithAttachmentThrowsExceptionForInvalidAddressNull() {
|
||||||
throws MessagingException {
|
|
||||||
Email email = new Email();
|
Email email = new Email();
|
||||||
email.setTo(null); // Invalid address
|
email.setTo(null); // Invalid address
|
||||||
email.setSubject("Test Email");
|
email.setSubject("Test Email");
|
||||||
@ -153,8 +151,7 @@ public class EmailServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSendEmailWithAttachmentThrowsExceptionForInvalidAddressEmpty()
|
void testSendEmailWithAttachmentThrowsExceptionForInvalidAddressEmpty() {
|
||||||
throws MessagingException {
|
|
||||||
Email email = new Email();
|
Email email = new Email();
|
||||||
email.setTo(""); // Invalid address
|
email.setTo(""); // Invalid address
|
||||||
email.setSubject("Test Email");
|
email.setSubject("Test Email");
|
||||||
|
|||||||
@ -138,9 +138,7 @@ class JwtServiceTest {
|
|||||||
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
AuthenticationFailureException.class,
|
AuthenticationFailureException.class,
|
||||||
() -> {
|
() -> jwtService.validateToken("invalid-token"));
|
||||||
jwtService.validateToken("invalid-token");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -152,9 +150,7 @@ class JwtServiceTest {
|
|||||||
AuthenticationFailureException exception =
|
AuthenticationFailureException exception =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
AuthenticationFailureException.class,
|
AuthenticationFailureException.class,
|
||||||
() -> {
|
() -> jwtService.validateToken("malformed.token"));
|
||||||
jwtService.validateToken("malformed.token");
|
|
||||||
});
|
|
||||||
|
|
||||||
assertTrue(exception.getMessage().contains("Invalid"));
|
assertTrue(exception.getMessage().contains("Invalid"));
|
||||||
}
|
}
|
||||||
@ -167,10 +163,7 @@ class JwtServiceTest {
|
|||||||
|
|
||||||
AuthenticationFailureException exception =
|
AuthenticationFailureException exception =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
AuthenticationFailureException.class,
|
AuthenticationFailureException.class, () -> jwtService.validateToken(""));
|
||||||
() -> {
|
|
||||||
jwtService.validateToken("");
|
|
||||||
});
|
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
exception.getMessage().contains("Claims are empty")
|
exception.getMessage().contains("Claims are empty")
|
||||||
@ -296,7 +289,7 @@ class JwtServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGenerateTokenWithKeyId() throws Exception {
|
void testGenerateTokenWithKeyId() {
|
||||||
String username = "testuser";
|
String username = "testuser";
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import static org.mockito.Mockito.lenient;
|
|||||||
import static org.mockito.Mockito.mockStatic;
|
import static org.mockito.Mockito.mockStatic;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
@ -84,7 +83,7 @@ class KeyPersistenceServiceInterfaceTest {
|
|||||||
String privateKeyBase64 =
|
String privateKeyBase64 =
|
||||||
Base64.getEncoder().encodeToString(testKeyPair.getPrivate().getEncoded());
|
Base64.getEncoder().encodeToString(testKeyPair.getPrivate().getEncoded());
|
||||||
|
|
||||||
JwtVerificationKey existingKey = new JwtVerificationKey(keyId, publicKeyBase64);
|
new JwtVerificationKey(keyId, publicKeyBase64);
|
||||||
|
|
||||||
Path keyFile = tempDir.resolve(keyId + ".key");
|
Path keyFile = tempDir.resolve(keyId + ".key");
|
||||||
Files.writeString(keyFile, privateKeyBase64);
|
Files.writeString(keyFile, privateKeyBase64);
|
||||||
@ -129,6 +128,7 @@ class KeyPersistenceServiceInterfaceTest {
|
|||||||
.getDeclaredField("verifyingKeyCache")
|
.getDeclaredField("verifyingKeyCache")
|
||||||
.setAccessible(true);
|
.setAccessible(true);
|
||||||
var cache = cacheManager.getCache("verifyingKeys");
|
var cache = cacheManager.getCache("verifyingKeys");
|
||||||
|
assertNotNull(cache);
|
||||||
cache.put(keyId, signingKey);
|
cache.put(keyId, signingKey);
|
||||||
|
|
||||||
Optional<KeyPair> result = keyPersistenceService.getKeyPair(keyId);
|
Optional<KeyPair> result = keyPersistenceService.getKeyPair(keyId);
|
||||||
@ -174,7 +174,7 @@ class KeyPersistenceServiceInterfaceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testInitializeKeystoreCreatesDirectory() throws IOException {
|
void testInitializeKeystoreCreatesDirectory() {
|
||||||
try (MockedStatic<InstallationPathConfig> mockedStatic =
|
try (MockedStatic<InstallationPathConfig> mockedStatic =
|
||||||
mockStatic(InstallationPathConfig.class)) {
|
mockStatic(InstallationPathConfig.class)) {
|
||||||
mockedStatic
|
mockedStatic
|
||||||
@ -189,12 +189,12 @@ class KeyPersistenceServiceInterfaceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testLoadExistingKeypairWithMissingPrivateKeyFile() throws Exception {
|
void testLoadExistingKeypairWithMissingPrivateKeyFile() {
|
||||||
String keyId = "test-key-missing-file";
|
String keyId = "test-key-missing-file";
|
||||||
String publicKeyBase64 =
|
String publicKeyBase64 =
|
||||||
Base64.getEncoder().encodeToString(testKeyPair.getPublic().getEncoded());
|
Base64.getEncoder().encodeToString(testKeyPair.getPublic().getEncoded());
|
||||||
|
|
||||||
JwtVerificationKey existingKey = new JwtVerificationKey(keyId, publicKeyBase64);
|
new JwtVerificationKey(keyId, publicKeyBase64);
|
||||||
|
|
||||||
try (MockedStatic<InstallationPathConfig> mockedStatic =
|
try (MockedStatic<InstallationPathConfig> mockedStatic =
|
||||||
mockStatic(InstallationPathConfig.class)) {
|
mockStatic(InstallationPathConfig.class)) {
|
||||||
|
|||||||
@ -133,7 +133,6 @@ class UserServiceTest {
|
|||||||
AuthenticationType authType = AuthenticationType.WEB;
|
AuthenticationType authType = AuthenticationType.WEB;
|
||||||
|
|
||||||
// When & Then
|
// When & Then
|
||||||
IllegalArgumentException exception =
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> userService.saveUser(invalidUsername, authType));
|
() -> userService.saveUser(invalidUsername, authType));
|
||||||
@ -208,7 +207,6 @@ class UserServiceTest {
|
|||||||
AuthenticationType authType = AuthenticationType.WEB;
|
AuthenticationType authType = AuthenticationType.WEB;
|
||||||
|
|
||||||
// When & Then
|
// When & Then
|
||||||
IllegalArgumentException exception =
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> userService.saveUser(reservedUsername, authType));
|
() -> userService.saveUser(reservedUsername, authType));
|
||||||
@ -224,7 +222,6 @@ class UserServiceTest {
|
|||||||
AuthenticationType authType = AuthenticationType.WEB;
|
AuthenticationType authType = AuthenticationType.WEB;
|
||||||
|
|
||||||
// When & Then
|
// When & Then
|
||||||
IllegalArgumentException exception =
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> userService.saveUser(anonymousUsername, authType));
|
() -> userService.saveUser(anonymousUsername, authType));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user