mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 11:00:47 +02:00
Multi module refactor (#3640)
# Description of Changes Migrated Stirling PDF to a multi-module structure: * Introduced new `:stirling-pdf` module * Moved all the core logic and features of Stirling PDF into `:stirling-pdf` * Updated paths of jobs and scripts --- ## 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/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/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/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/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package stirling.software.SPDF;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SPDFApplicationTest {
|
||||
|
||||
@Mock private Environment env;
|
||||
|
||||
@Mock private ApplicationProperties applicationProperties;
|
||||
|
||||
@InjectMocks private SPDFApplication sPDFApplication;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
SPDFApplication.setServerPortStatic("8080");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetServerPortStatic() {
|
||||
SPDFApplication.setServerPortStatic("9090");
|
||||
assertEquals("9090", SPDFApplication.getStaticPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStaticPort() {
|
||||
assertEquals("8080", SPDFApplication.getStaticPort());
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
|
||||
class RearrangePagesPDFControllerTest {
|
||||
|
||||
@Mock private CustomPDFDocumentFactory mockPdfDocumentFactory;
|
||||
|
||||
private RearrangePagesPDFController sut;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
sut = new RearrangePagesPDFController(mockPdfDocumentFactory);
|
||||
}
|
||||
|
||||
/** Tests the behavior of the oddEvenMerge method when there are no pages in the document. */
|
||||
@Test
|
||||
void oddEvenMerge_noPages() {
|
||||
int totalNumberOfPages = 0;
|
||||
|
||||
List<Integer> newPageOrder = sut.oddEvenMerge(totalNumberOfPages);
|
||||
|
||||
assertNotNull(newPageOrder, "Returning null instead of page order list");
|
||||
assertEquals(List.of(), newPageOrder, "Page order doesn't match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the oddEvenMerge method when there are odd total pages in the document.
|
||||
*/
|
||||
@Test
|
||||
void oddEvenMerge_oddTotalPageNumber() {
|
||||
int totalNumberOfPages = 5;
|
||||
|
||||
List<Integer> newPageOrder = sut.oddEvenMerge(totalNumberOfPages);
|
||||
|
||||
assertNotNull(newPageOrder, "Returning null instead of page order list");
|
||||
assertEquals(Arrays.asList(0, 3, 1, 4, 2), newPageOrder, "Page order doesn't match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the oddEvenMerge method when there are even total pages in the
|
||||
* document.
|
||||
*/
|
||||
@Test
|
||||
void oddEvenMerge_evenTotalPageNumber() {
|
||||
int totalNumberOfPages = 6;
|
||||
|
||||
List<Integer> newPageOrder = sut.oddEvenMerge(totalNumberOfPages);
|
||||
|
||||
assertNotNull(newPageOrder, "Returning null instead of page order list");
|
||||
assertEquals(Arrays.asList(0, 3, 1, 4, 2, 5), newPageOrder, "Page order doesn't match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the oddEvenMerge method with multiple test cases of multiple pages.
|
||||
*
|
||||
* @param totalNumberOfPages The total number of pages in the document.
|
||||
* @param expectedPageOrder The expected order of the pages after rearranging.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"1, '0'",
|
||||
"2, '0,1'",
|
||||
"3, '0,2,1'",
|
||||
"4, '0,2,1,3'",
|
||||
"5, '0,3,1,4,2'",
|
||||
"6, '0,3,1,4,2,5'",
|
||||
"10, '0,5,1,6,2,7,3,8,4,9'",
|
||||
"50, '0,25,1,26,2,27,3,28,4,29,5,30,6,31,7,32,8,33,9,34,10,35,"
|
||||
+ "11,36,12,37,13,38,14,39,15,40,16,41,17,42,18,43,19,44,20,45,21,46,"
|
||||
+ "22,47,23,48,24,49'"
|
||||
})
|
||||
void oddEvenMerge_multi_test(int totalNumberOfPages, String expectedPageOrder) {
|
||||
List<Integer> newPageOrder = sut.oddEvenMerge(totalNumberOfPages);
|
||||
|
||||
assertNotNull(newPageOrder, "Returning null instead of page order list");
|
||||
assertEquals(
|
||||
Arrays.stream(expectedPageOrder.split(",")).map(Integer::parseInt).toList(),
|
||||
newPageOrder,
|
||||
"Page order doesn't match");
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import stirling.software.SPDF.model.api.general.RotatePDFRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class RotationControllerTest {
|
||||
|
||||
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@InjectMocks private RotationController rotationController;
|
||||
|
||||
@Test
|
||||
public void testRotatePDF() throws IOException {
|
||||
// Create a mock file
|
||||
MockMultipartFile mockFile =
|
||||
new MockMultipartFile("file", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
|
||||
RotatePDFRequest request = new RotatePDFRequest();
|
||||
request.setFileInput(mockFile);
|
||||
request.setAngle(90);
|
||||
|
||||
PDDocument mockDocument = mock(PDDocument.class);
|
||||
PDPageTree mockPages = mock(PDPageTree.class);
|
||||
PDPage mockPage = mock(PDPage.class);
|
||||
|
||||
when(pdfDocumentFactory.load(request)).thenReturn(mockDocument);
|
||||
when(mockDocument.getPages()).thenReturn(mockPages);
|
||||
when(mockPages.iterator())
|
||||
.thenReturn(java.util.Collections.singletonList(mockPage).iterator());
|
||||
when(mockPage.getRotation()).thenReturn(0);
|
||||
|
||||
// Act
|
||||
ResponseEntity<byte[]> response = rotationController.rotatePDF(request);
|
||||
|
||||
// Assert
|
||||
verify(mockPage).setRotation(90);
|
||||
assertNotNull(response);
|
||||
assertEquals(200, response.getStatusCode().value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotatePDFInvalidAngle() throws IOException {
|
||||
// Create a mock file
|
||||
MockMultipartFile mockFile =
|
||||
new MockMultipartFile("file", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
|
||||
RotatePDFRequest request = new RotatePDFRequest();
|
||||
request.setFileInput(mockFile);
|
||||
request.setAngle(45); // Invalid angle
|
||||
|
||||
// Act & Assert: Controller direkt aufrufen und Exception erwarten
|
||||
IllegalArgumentException exception =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> rotationController.rotatePDF(request));
|
||||
assertEquals("Angle must be a multiple of 90", exception.getMessage());
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
|
||||
public class ConvertWebsiteToPdfTest {
|
||||
|
||||
@Mock private CustomPDFDocumentFactory mockPdfDocumentFactory;
|
||||
|
||||
@Mock private RuntimePathConfig runtimePathConfig;
|
||||
|
||||
private ApplicationProperties applicationProperties;
|
||||
|
||||
private ConvertWebsiteToPDF convertWebsiteToPDF;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
applicationProperties = new ApplicationProperties();
|
||||
applicationProperties.getSystem().setEnableUrlToPDF(true);
|
||||
convertWebsiteToPDF =
|
||||
new ConvertWebsiteToPDF(
|
||||
mockPdfDocumentFactory, runtimePathConfig, applicationProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_exemption_is_thrown_when_invalid_url_format_provided() {
|
||||
|
||||
String invalid_format_Url = "invalid-url";
|
||||
|
||||
UrlToPdfRequest request = new UrlToPdfRequest();
|
||||
request.setUrlInput(invalid_format_Url);
|
||||
// Act
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
convertWebsiteToPDF.urlToPdf(request);
|
||||
});
|
||||
// Assert
|
||||
assertEquals("Invalid URL format provided.", thrown.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_exemption_is_thrown_when_url_is_not_reachable() {
|
||||
|
||||
String unreachable_Url = "https://www.googleeeexyz.com";
|
||||
// Arrange
|
||||
UrlToPdfRequest request = new UrlToPdfRequest();
|
||||
request.setUrlInput(unreachable_Url);
|
||||
// Act
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
convertWebsiteToPDF.urlToPdf(request);
|
||||
});
|
||||
// Assert
|
||||
assertEquals("URL is not reachable, please provide a valid URL.", thrown.getMessage());
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package stirling.software.SPDF.controller.api.pipeline;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
import stirling.software.common.service.UserServiceInterface;
|
||||
import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineOperation;
|
||||
import stirling.software.SPDF.model.PipelineResult;
|
||||
import stirling.software.SPDF.service.ApiDocService;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PipelineProcessorTest {
|
||||
|
||||
@Mock ApiDocService apiDocService;
|
||||
|
||||
@Mock UserServiceInterface userService;
|
||||
|
||||
@Mock ServletContext servletContext;
|
||||
|
||||
PipelineProcessor pipelineProcessor;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
pipelineProcessor = spy(new PipelineProcessor(apiDocService, userService, servletContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runPipelineWithFilterSetsFlag() throws Exception {
|
||||
PipelineOperation op = new PipelineOperation();
|
||||
op.setOperation("filter-page-count");
|
||||
op.setParameters(Map.of());
|
||||
PipelineConfig config = new PipelineConfig();
|
||||
config.setOperations(List.of(op));
|
||||
|
||||
Resource file = new ByteArrayResource("data".getBytes()) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return "test.pdf";
|
||||
}
|
||||
};
|
||||
|
||||
List<Resource> files = List.of(file);
|
||||
|
||||
when(apiDocService.isMultiInput("filter-page-count")).thenReturn(false);
|
||||
when(apiDocService.getExtensionTypes(false, "filter-page-count"))
|
||||
.thenReturn(List.of("pdf"));
|
||||
|
||||
doReturn(new ResponseEntity<>(new byte[0], HttpStatus.OK))
|
||||
.when(pipelineProcessor)
|
||||
.sendWebRequest(anyString(), any());
|
||||
|
||||
PipelineResult result = pipelineProcessor.runPipelineAgainstFiles(files, config);
|
||||
|
||||
assertTrue(
|
||||
result.isFiltersApplied(),
|
||||
"Filter flag should be true when operation filters file");
|
||||
assertFalse(result.isHasErrors(), "No errors should occur");
|
||||
assertTrue(result.getOutputFiles().isEmpty(), "Filtered file list should be empty");
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
|
||||
class UploadLimitServiceTest {
|
||||
|
||||
private UploadLimitService uploadLimitService;
|
||||
private ApplicationProperties applicationProperties;
|
||||
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() {
|
||||
return Stream.of(
|
||||
// empty or null input yields 0
|
||||
Arguments.of(null, 0L),
|
||||
Arguments.of("", 0L),
|
||||
// invalid formats
|
||||
Arguments.of("1234MB", 0L),
|
||||
Arguments.of("5TB", 0L),
|
||||
// valid formats
|
||||
Arguments.of("10KB", 10 * 1024L),
|
||||
Arguments.of("2MB", 2 * 1024 * 1024L),
|
||||
Arguments.of("1GB", 1L * 1024 * 1024 * 1024),
|
||||
Arguments.of("5mb", 5 * 1024 * 1024L),
|
||||
Arguments.of("0MB", 0L));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "getReadableUploadLimit case #{index}: rawValue={0}, expected={1}")
|
||||
@MethodSource("readableLimitParams")
|
||||
void shouldReturnReadableFormat(String rawValue, String expected) {
|
||||
when(systemProps.getFileUploadLimit()).thenReturn(rawValue);
|
||||
String result = uploadLimitService.getReadableUploadLimit();
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
static Stream<Arguments> readableLimitParams() {
|
||||
return Stream.of(
|
||||
Arguments.of(null, "0 B"),
|
||||
Arguments.of("", "0 B"),
|
||||
Arguments.of("1KB", "1.0 KB"),
|
||||
Arguments.of("2MB", "2.0 MB"));
|
||||
}
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/** Tests for the CertificateValidationService using mocked certificates. */
|
||||
class CertificateValidationServiceTest {
|
||||
|
||||
private CertificateValidationService validationService;
|
||||
private X509Certificate validCertificate;
|
||||
private X509Certificate expiredCertificate;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
validationService = new CertificateValidationService();
|
||||
|
||||
// Create mock certificates
|
||||
validCertificate = mock(X509Certificate.class);
|
||||
expiredCertificate = mock(X509Certificate.class);
|
||||
|
||||
// Set up behaviors for valid certificate
|
||||
doNothing().when(validCertificate).checkValidity(); // No exception means valid
|
||||
|
||||
// Set up behaviors for expired certificate
|
||||
doThrow(new CertificateExpiredException("Certificate expired"))
|
||||
.when(expiredCertificate)
|
||||
.checkValidity();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsRevoked_ValidCertificate() {
|
||||
// When certificate is valid (not expired)
|
||||
boolean result = validationService.isRevoked(validCertificate);
|
||||
|
||||
// Then it should not be considered revoked
|
||||
assertFalse(result, "Valid certificate should not be considered revoked");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsRevoked_ExpiredCertificate() {
|
||||
// When certificate is expired
|
||||
boolean result = validationService.isRevoked(expiredCertificate);
|
||||
|
||||
// Then it should be considered revoked
|
||||
assertTrue(result, "Expired certificate should be considered revoked");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidateTrustWithCustomCert_Match() {
|
||||
// Create certificates with matching issuer and subject
|
||||
X509Certificate issuingCert = mock(X509Certificate.class);
|
||||
X509Certificate signedCert = mock(X509Certificate.class);
|
||||
|
||||
// Create X500Principal objects for issuer and subject
|
||||
X500Principal issuerPrincipal = new X500Principal("CN=Test Issuer");
|
||||
|
||||
// Mock the issuer of the signed certificate to match the subject of the issuing certificate
|
||||
when(signedCert.getIssuerX500Principal()).thenReturn(issuerPrincipal);
|
||||
when(issuingCert.getSubjectX500Principal()).thenReturn(issuerPrincipal);
|
||||
|
||||
// When validating trust with custom cert
|
||||
boolean result = validationService.validateTrustWithCustomCert(signedCert, issuingCert);
|
||||
|
||||
// Then validation should succeed
|
||||
assertTrue(result, "Certificate with matching issuer and subject should validate");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidateTrustWithCustomCert_NoMatch() {
|
||||
// Create certificates with non-matching issuer and subject
|
||||
X509Certificate issuingCert = mock(X509Certificate.class);
|
||||
X509Certificate signedCert = mock(X509Certificate.class);
|
||||
|
||||
// Create X500Principal objects for issuer and subject
|
||||
X500Principal issuerPrincipal = new X500Principal("CN=Test Issuer");
|
||||
X500Principal differentPrincipal = new X500Principal("CN=Different Name");
|
||||
|
||||
// Mock the issuer of the signed certificate to NOT match the subject of the issuing
|
||||
// certificate
|
||||
when(signedCert.getIssuerX500Principal()).thenReturn(issuerPrincipal);
|
||||
when(issuingCert.getSubjectX500Principal()).thenReturn(differentPrincipal);
|
||||
|
||||
// When validating trust with custom cert
|
||||
boolean result = validationService.validateTrustWithCustomCert(signedCert, issuingCert);
|
||||
|
||||
// Then validation should fail
|
||||
assertFalse(result, "Certificate with non-matching issuer and subject should not validate");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidateCertificateChainWithCustomCert_Success() throws Exception {
|
||||
// Setup mock certificates
|
||||
X509Certificate signedCert = mock(X509Certificate.class);
|
||||
X509Certificate signingCert = mock(X509Certificate.class);
|
||||
PublicKey publicKey = mock(PublicKey.class);
|
||||
|
||||
when(signingCert.getPublicKey()).thenReturn(publicKey);
|
||||
|
||||
// When verifying the certificate with the signing cert's public key, don't throw exception
|
||||
doNothing().when(signedCert).verify(Mockito.any());
|
||||
|
||||
// When validating certificate chain with custom cert
|
||||
boolean result =
|
||||
validationService.validateCertificateChainWithCustomCert(signedCert, signingCert);
|
||||
|
||||
// Then validation should succeed
|
||||
assertTrue(result, "Certificate chain with proper signing should validate");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidateCertificateChainWithCustomCert_Failure() throws Exception {
|
||||
// Setup mock certificates
|
||||
X509Certificate signedCert = mock(X509Certificate.class);
|
||||
X509Certificate signingCert = mock(X509Certificate.class);
|
||||
PublicKey publicKey = mock(PublicKey.class);
|
||||
|
||||
when(signingCert.getPublicKey()).thenReturn(publicKey);
|
||||
|
||||
// When verifying the certificate with the signing cert's public key, throw exception
|
||||
// Need to use a specific exception that verify() can throw
|
||||
doThrow(new java.security.SignatureException("Verification failed"))
|
||||
.when(signedCert)
|
||||
.verify(Mockito.any());
|
||||
|
||||
// When validating certificate chain with custom cert
|
||||
boolean result =
|
||||
validationService.validateCertificateChainWithCustomCert(signedCert, signingCert);
|
||||
|
||||
// Then validation should fail
|
||||
assertFalse(result, "Certificate chain with failed signing should not validate");
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.ApplicationProperties.Ui;
|
||||
|
||||
class LanguageServiceBasicTest {
|
||||
|
||||
private LanguageService languageService;
|
||||
private ApplicationProperties applicationProperties;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// Mock application properties
|
||||
applicationProperties = mock(ApplicationProperties.class);
|
||||
Ui ui = mock(Ui.class);
|
||||
when(applicationProperties.getUi()).thenReturn(ui);
|
||||
|
||||
// Create language service with test implementation
|
||||
languageService = new LanguageServiceForTest(applicationProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_BasicFunctionality() throws IOException {
|
||||
// Set up mocked resources
|
||||
Resource enResource = createMockResource("messages_en_US.properties");
|
||||
Resource frResource = createMockResource("messages_fr_FR.properties");
|
||||
Resource[] mockResources = new Resource[] {enResource, frResource};
|
||||
|
||||
// Configure the test service
|
||||
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
||||
when(applicationProperties.getUi().getLanguages()).thenReturn(Collections.emptyList());
|
||||
|
||||
// Execute the method
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Basic assertions
|
||||
assertTrue(supportedLanguages.contains("en_US"), "en_US should be included");
|
||||
assertTrue(supportedLanguages.contains("fr_FR"), "fr_FR should be included");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_FilteringInvalidFiles() throws IOException {
|
||||
// Set up mocked resources with invalid files
|
||||
Resource[] mockResources =
|
||||
new Resource[] {
|
||||
createMockResource("messages_en_US.properties"), // Valid
|
||||
createMockResource("invalid_file.properties"), // Invalid
|
||||
createMockResource(null) // Null filename
|
||||
};
|
||||
|
||||
// Configure the test service
|
||||
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
||||
when(applicationProperties.getUi().getLanguages()).thenReturn(Collections.emptyList());
|
||||
|
||||
// Execute the method
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Verify filtering
|
||||
assertTrue(supportedLanguages.contains("en_US"), "Valid language should be included");
|
||||
assertFalse(
|
||||
supportedLanguages.contains("invalid_file"),
|
||||
"Invalid filename should be filtered out");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_WithRestrictions() throws IOException {
|
||||
// Set up test resources
|
||||
Resource[] mockResources =
|
||||
new Resource[] {
|
||||
createMockResource("messages_en_US.properties"),
|
||||
createMockResource("messages_fr_FR.properties"),
|
||||
createMockResource("messages_de_DE.properties"),
|
||||
createMockResource("messages_en_GB.properties")
|
||||
};
|
||||
|
||||
// Configure the test service
|
||||
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
||||
|
||||
// Allow only specific languages (en_GB is always included)
|
||||
when(applicationProperties.getUi().getLanguages())
|
||||
.thenReturn(Arrays.asList("en_US", "fr_FR"));
|
||||
|
||||
// Execute the method
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Verify filtering by restrictions
|
||||
assertTrue(supportedLanguages.contains("en_US"), "Allowed language should be included");
|
||||
assertTrue(supportedLanguages.contains("fr_FR"), "Allowed language should be included");
|
||||
assertTrue(supportedLanguages.contains("en_GB"), "en_GB should always be included");
|
||||
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
|
||||
private static class LanguageServiceForTest extends LanguageService {
|
||||
private Resource[] mockResources;
|
||||
|
||||
public LanguageServiceForTest(ApplicationProperties applicationProperties) {
|
||||
super(applicationProperties);
|
||||
}
|
||||
|
||||
public void setMockResources(Resource[] mockResources) {
|
||||
this.mockResources = mockResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Resource[] getResourcesFromPattern(String pattern) throws IOException {
|
||||
return mockResources;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
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.Ui;
|
||||
|
||||
class LanguageServiceTest {
|
||||
|
||||
private LanguageService languageService;
|
||||
private ApplicationProperties applicationProperties;
|
||||
private PathMatchingResourcePatternResolver mockedResolver;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
// Mock ApplicationProperties
|
||||
applicationProperties = mock(ApplicationProperties.class);
|
||||
Ui ui = mock(Ui.class);
|
||||
when(applicationProperties.getUi()).thenReturn(ui);
|
||||
|
||||
// Create LanguageService with our custom constructor that allows injection of resolver
|
||||
languageService = new LanguageServiceForTest(applicationProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_NoRestrictions() throws IOException {
|
||||
// Setup
|
||||
Set<String> expectedLanguages =
|
||||
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
|
||||
|
||||
// Mock the resource resolver response
|
||||
Resource[] mockResources = createMockResources(expectedLanguages);
|
||||
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
||||
|
||||
// No language restrictions in properties
|
||||
when(applicationProperties.getUi().getLanguages()).thenReturn(Collections.emptyList());
|
||||
|
||||
// Test
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Verify
|
||||
assertEquals(
|
||||
expectedLanguages,
|
||||
supportedLanguages,
|
||||
"Should return all languages when no restrictions");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_WithRestrictions() throws IOException {
|
||||
// Setup
|
||||
Set<String> expectedLanguages =
|
||||
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
|
||||
Set<String> allowedLanguages = new HashSet<>(Arrays.asList("en_US", "fr_FR", "en_GB"));
|
||||
|
||||
// Mock the resource resolver response
|
||||
Resource[] mockResources = createMockResources(expectedLanguages);
|
||||
((LanguageServiceForTest) languageService).setMockResources(mockResources);
|
||||
|
||||
// Set language restrictions in properties
|
||||
when(applicationProperties.getUi().getLanguages())
|
||||
.thenReturn(Arrays.asList("en_US", "fr_FR")); // en_GB is always allowed
|
||||
|
||||
// Test
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Verify
|
||||
assertEquals(
|
||||
allowedLanguages,
|
||||
supportedLanguages,
|
||||
"Should return only allowed languages, plus en_GB which is always allowed");
|
||||
assertTrue(supportedLanguages.contains("en_GB"), "en_GB should always be included");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_ExceptionHandling() throws IOException {
|
||||
// Setup - make resolver throw an exception
|
||||
((LanguageServiceForTest) languageService).setShouldThrowException(true);
|
||||
|
||||
// Test
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Verify
|
||||
assertTrue(supportedLanguages.isEmpty(), "Should return empty set on exception");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedLanguages_FilteringNonMatchingFiles() throws IOException {
|
||||
// Setup with some valid and some invalid filenames
|
||||
Resource[] mixedResources =
|
||||
new Resource[] {
|
||||
createMockResource("messages_en_US.properties"),
|
||||
createMockResource(
|
||||
"messages_en_GB.properties"), // Explicitly add en_GB resource
|
||||
createMockResource("messages_fr_FR.properties"),
|
||||
createMockResource("not_a_messages_file.properties"),
|
||||
createMockResource("messages_.properties"), // Invalid format
|
||||
createMockResource(null) // Null filename
|
||||
};
|
||||
|
||||
((LanguageServiceForTest) languageService).setMockResources(mixedResources);
|
||||
when(applicationProperties.getUi().getLanguages()).thenReturn(Collections.emptyList());
|
||||
|
||||
// Test
|
||||
Set<String> supportedLanguages = languageService.getSupportedLanguages();
|
||||
|
||||
// Verify the valid languages are present
|
||||
assertTrue(supportedLanguages.contains("en_US"), "en_US should be included");
|
||||
assertTrue(supportedLanguages.contains("fr_FR"), "fr_FR should be included");
|
||||
// Add en_GB which is always included
|
||||
assertTrue(supportedLanguages.contains("en_GB"), "en_GB should always be included");
|
||||
|
||||
// Verify no invalid formats are included
|
||||
assertFalse(
|
||||
supportedLanguages.contains("not_a_messages_file"),
|
||||
"Invalid format should be excluded");
|
||||
// Skip the empty string check as it depends on implementation details of extracting
|
||||
// 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
|
||||
private static class LanguageServiceForTest extends LanguageService {
|
||||
private Resource[] mockResources;
|
||||
private boolean shouldThrowException = false;
|
||||
|
||||
public LanguageServiceForTest(ApplicationProperties applicationProperties) {
|
||||
super(applicationProperties);
|
||||
}
|
||||
|
||||
public void setMockResources(Resource[] mockResources) {
|
||||
this.mockResources = mockResources;
|
||||
}
|
||||
|
||||
public void setShouldThrowException(boolean shouldThrowException) {
|
||||
this.shouldThrowException = shouldThrowException;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Resource[] getResourcesFromPattern(String pattern) throws IOException {
|
||||
if (shouldThrowException) {
|
||||
throw new IOException("Test exception");
|
||||
}
|
||||
return mockResources;
|
||||
}
|
||||
}
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
class PdfImageRemovalServiceTest {
|
||||
|
||||
private PdfImageRemovalService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new PdfImageRemovalService();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveImagesFromPdf_WithImages() throws IOException {
|
||||
// Mock PDF document and its components
|
||||
PDDocument document = mock(PDDocument.class);
|
||||
PDPage page = mock(PDPage.class);
|
||||
PDResources resources = mock(PDResources.class);
|
||||
PDPageTree pageTree = mock(PDPageTree.class);
|
||||
|
||||
// Configure page tree to iterate over our single page
|
||||
when(document.getPages()).thenReturn(pageTree);
|
||||
Iterator<PDPage> pageIterator = Arrays.asList(page).iterator();
|
||||
when(pageTree.iterator()).thenReturn(pageIterator);
|
||||
|
||||
// Set up page resources
|
||||
when(page.getResources()).thenReturn(resources);
|
||||
|
||||
// Set up image XObjects
|
||||
COSName img1 = COSName.getPDFName("Im1");
|
||||
COSName img2 = COSName.getPDFName("Im2");
|
||||
COSName nonImg = COSName.getPDFName("NonImg");
|
||||
|
||||
List<COSName> xObjectNames = Arrays.asList(img1, img2, nonImg);
|
||||
when(resources.getXObjectNames()).thenReturn(xObjectNames);
|
||||
|
||||
// Configure which are image XObjects
|
||||
when(resources.isImageXObject(img1)).thenReturn(true);
|
||||
when(resources.isImageXObject(img2)).thenReturn(true);
|
||||
when(resources.isImageXObject(nonImg)).thenReturn(false);
|
||||
|
||||
// Execute the method
|
||||
PDDocument result = service.removeImagesFromPdf(document);
|
||||
|
||||
// Verify that images were removed
|
||||
verify(resources, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
|
||||
verify(resources, times(1)).put(eq(img2), Mockito.<PDXObject>isNull());
|
||||
verify(resources, never()).put(eq(nonImg), Mockito.<PDXObject>isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveImagesFromPdf_NoImages() throws IOException {
|
||||
// Mock PDF document and its components
|
||||
PDDocument document = mock(PDDocument.class);
|
||||
PDPage page = mock(PDPage.class);
|
||||
PDResources resources = mock(PDResources.class);
|
||||
PDPageTree pageTree = mock(PDPageTree.class);
|
||||
|
||||
// Configure page tree to iterate over our single page
|
||||
when(document.getPages()).thenReturn(pageTree);
|
||||
Iterator<PDPage> pageIterator = Arrays.asList(page).iterator();
|
||||
when(pageTree.iterator()).thenReturn(pageIterator);
|
||||
|
||||
// Set up page resources
|
||||
when(page.getResources()).thenReturn(resources);
|
||||
|
||||
// Create empty list of XObject names
|
||||
List<COSName> emptyList = new ArrayList<>();
|
||||
when(resources.getXObjectNames()).thenReturn(emptyList);
|
||||
|
||||
// Execute the method
|
||||
PDDocument result = service.removeImagesFromPdf(document);
|
||||
|
||||
// Verify that no modifications were made
|
||||
verify(resources, never()).put(any(COSName.class), any(PDXObject.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveImagesFromPdf_MultiplePages() throws IOException {
|
||||
// Mock PDF document and its components
|
||||
PDDocument document = mock(PDDocument.class);
|
||||
PDPage page1 = mock(PDPage.class);
|
||||
PDPage page2 = mock(PDPage.class);
|
||||
PDResources resources1 = mock(PDResources.class);
|
||||
PDResources resources2 = mock(PDResources.class);
|
||||
PDPageTree pageTree = mock(PDPageTree.class);
|
||||
|
||||
// Configure page tree to iterate over our two pages
|
||||
when(document.getPages()).thenReturn(pageTree);
|
||||
Iterator<PDPage> pageIterator = Arrays.asList(page1, page2).iterator();
|
||||
when(pageTree.iterator()).thenReturn(pageIterator);
|
||||
|
||||
// Set up page resources
|
||||
when(page1.getResources()).thenReturn(resources1);
|
||||
when(page2.getResources()).thenReturn(resources2);
|
||||
|
||||
// Set up image XObjects for page 1
|
||||
COSName img1 = COSName.getPDFName("Im1");
|
||||
when(resources1.getXObjectNames()).thenReturn(Arrays.asList(img1));
|
||||
when(resources1.isImageXObject(img1)).thenReturn(true);
|
||||
|
||||
// Set up image XObjects for page 2
|
||||
COSName img2 = COSName.getPDFName("Im2");
|
||||
when(resources2.getXObjectNames()).thenReturn(Arrays.asList(img2));
|
||||
when(resources2.isImageXObject(img2)).thenReturn(true);
|
||||
|
||||
// Execute the method
|
||||
PDDocument result = service.removeImagesFromPdf(document);
|
||||
|
||||
// Verify that images were removed from both pages
|
||||
verify(resources1, times(1)).put(eq(img1), 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") + ")";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures.CustomMetadata;
|
||||
import stirling.software.common.model.PdfMetadata;
|
||||
import stirling.software.common.service.PdfMetadataService;
|
||||
import stirling.software.common.service.UserServiceInterface;
|
||||
|
||||
class PdfMetadataServiceBasicTest {
|
||||
|
||||
private ApplicationProperties applicationProperties;
|
||||
private UserServiceInterface userService;
|
||||
private PdfMetadataService pdfMetadataService;
|
||||
private final String STIRLING_PDF_LABEL = "Stirling PDF";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// Set up mocks for application properties' nested objects
|
||||
applicationProperties = mock(ApplicationProperties.class);
|
||||
Premium premium = mock(Premium.class);
|
||||
ProFeatures proFeatures = mock(ProFeatures.class);
|
||||
CustomMetadata customMetadata = mock(CustomMetadata.class);
|
||||
userService = mock(UserServiceInterface.class);
|
||||
|
||||
when(applicationProperties.getPremium()).thenReturn(premium);
|
||||
when(premium.getProFeatures()).thenReturn(proFeatures);
|
||||
when(proFeatures.getCustomMetadata()).thenReturn(customMetadata);
|
||||
|
||||
// Set up the service under test
|
||||
pdfMetadataService =
|
||||
new PdfMetadataService(
|
||||
applicationProperties,
|
||||
STIRLING_PDF_LABEL,
|
||||
false, // not running Pro or higher
|
||||
userService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractMetadataFromPdf() {
|
||||
// Create test document
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Set up expected metadata values
|
||||
String testAuthor = "Test Author";
|
||||
String testProducer = "Test Producer";
|
||||
String testTitle = "Test Title";
|
||||
String testCreator = "Test Creator";
|
||||
String testSubject = "Test Subject";
|
||||
String testKeywords = "Test Keywords";
|
||||
Calendar creationDate = Calendar.getInstance();
|
||||
Calendar modificationDate = Calendar.getInstance();
|
||||
|
||||
// Configure mock returns
|
||||
when(testInfo.getAuthor()).thenReturn(testAuthor);
|
||||
when(testInfo.getProducer()).thenReturn(testProducer);
|
||||
when(testInfo.getTitle()).thenReturn(testTitle);
|
||||
when(testInfo.getCreator()).thenReturn(testCreator);
|
||||
when(testInfo.getSubject()).thenReturn(testSubject);
|
||||
when(testInfo.getKeywords()).thenReturn(testKeywords);
|
||||
when(testInfo.getCreationDate()).thenReturn(creationDate);
|
||||
when(testInfo.getModificationDate()).thenReturn(modificationDate);
|
||||
|
||||
// Act
|
||||
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
|
||||
|
||||
// Assert
|
||||
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
|
||||
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
|
||||
assertEquals(testTitle, metadata.getTitle(), "Title should match");
|
||||
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
|
||||
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
|
||||
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
|
||||
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
|
||||
assertEquals(
|
||||
modificationDate, metadata.getModificationDate(), "Modification date should match");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetDefaultMetadata() {
|
||||
// Create test document
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Act
|
||||
pdfMetadataService.setDefaultMetadata(testDocument);
|
||||
|
||||
// Verify basic calls
|
||||
verify(testInfo, times(1)).setModificationDate(any(Calendar.class));
|
||||
verify(testInfo, times(1)).setProducer(STIRLING_PDF_LABEL);
|
||||
}
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures;
|
||||
import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures.CustomMetadata;
|
||||
import stirling.software.common.model.PdfMetadata;
|
||||
import stirling.software.common.service.PdfMetadataService;
|
||||
import stirling.software.common.service.UserServiceInterface;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PdfMetadataServiceTest {
|
||||
|
||||
@Mock private ApplicationProperties applicationProperties;
|
||||
@Mock private UserServiceInterface userService;
|
||||
private PdfMetadataService pdfMetadataService;
|
||||
private final String STIRLING_PDF_LABEL = "Stirling PDF";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// Set up mocks for application properties' nested objects
|
||||
Premium premium = mock(Premium.class);
|
||||
ProFeatures proFeatures = mock(ProFeatures.class);
|
||||
CustomMetadata customMetadata = mock(CustomMetadata.class);
|
||||
|
||||
// Use lenient() to avoid UnnecessaryStubbingException for setup stubs that might not be
|
||||
// used in every test
|
||||
lenient().when(applicationProperties.getPremium()).thenReturn(premium);
|
||||
lenient().when(premium.getProFeatures()).thenReturn(proFeatures);
|
||||
lenient().when(proFeatures.getCustomMetadata()).thenReturn(customMetadata);
|
||||
|
||||
// Set up the service under test
|
||||
pdfMetadataService =
|
||||
new PdfMetadataService(
|
||||
applicationProperties,
|
||||
STIRLING_PDF_LABEL,
|
||||
false, // not running Pro or higher
|
||||
userService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractMetadataFromPdf() {
|
||||
// Create a fresh document and information for this test to avoid stubbing issues
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Setup the document information with non-null values that will be used
|
||||
String testAuthor = "Test Author";
|
||||
String testProducer = "Test Producer";
|
||||
String testTitle = "Test Title";
|
||||
String testCreator = "Test Creator";
|
||||
String testSubject = "Test Subject";
|
||||
String testKeywords = "Test Keywords";
|
||||
Calendar creationDate = Calendar.getInstance();
|
||||
Calendar modificationDate = Calendar.getInstance();
|
||||
|
||||
when(testInfo.getAuthor()).thenReturn(testAuthor);
|
||||
when(testInfo.getProducer()).thenReturn(testProducer);
|
||||
when(testInfo.getTitle()).thenReturn(testTitle);
|
||||
when(testInfo.getCreator()).thenReturn(testCreator);
|
||||
when(testInfo.getSubject()).thenReturn(testSubject);
|
||||
when(testInfo.getKeywords()).thenReturn(testKeywords);
|
||||
when(testInfo.getCreationDate()).thenReturn(creationDate);
|
||||
when(testInfo.getModificationDate()).thenReturn(modificationDate);
|
||||
|
||||
// Act
|
||||
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
|
||||
|
||||
// Assert
|
||||
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
|
||||
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
|
||||
assertEquals(testTitle, metadata.getTitle(), "Title should match");
|
||||
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
|
||||
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
|
||||
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
|
||||
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
|
||||
assertEquals(
|
||||
modificationDate, metadata.getModificationDate(), "Modification date should match");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetDefaultMetadata() {
|
||||
// This test will use a real instance of PdfMetadataService
|
||||
|
||||
// Create a test document
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Act
|
||||
pdfMetadataService.setDefaultMetadata(testDocument);
|
||||
|
||||
// Verify the right calls were made to the document info
|
||||
// We only need to verify some of the basic setters were called
|
||||
verify(testInfo).setTitle(any());
|
||||
verify(testInfo).setProducer(STIRLING_PDF_LABEL);
|
||||
verify(testInfo).setModificationDate(any(Calendar.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetMetadataToPdf_NewDocument() {
|
||||
// Create a fresh document
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Prepare test metadata
|
||||
PdfMetadata testMetadata =
|
||||
PdfMetadata.builder()
|
||||
.author("Test Author")
|
||||
.title("Test Title")
|
||||
.subject("Test Subject")
|
||||
.keywords("Test Keywords")
|
||||
.build();
|
||||
|
||||
// Act
|
||||
pdfMetadataService.setMetadataToPdf(testDocument, testMetadata, true);
|
||||
|
||||
// Assert
|
||||
verify(testInfo).setCreator(STIRLING_PDF_LABEL);
|
||||
verify(testInfo).setCreationDate(org.mockito.ArgumentMatchers.any(Calendar.class));
|
||||
verify(testInfo).setTitle("Test Title");
|
||||
verify(testInfo).setProducer(STIRLING_PDF_LABEL);
|
||||
verify(testInfo).setSubject("Test Subject");
|
||||
verify(testInfo).setKeywords("Test Keywords");
|
||||
verify(testInfo).setModificationDate(org.mockito.ArgumentMatchers.any(Calendar.class));
|
||||
verify(testInfo).setAuthor("Test Author");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetMetadataToPdf_WithProFeatures() {
|
||||
// Create a fresh document and information for this test
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Create a special service instance for Pro version
|
||||
PdfMetadataService proService =
|
||||
new PdfMetadataService(
|
||||
applicationProperties,
|
||||
STIRLING_PDF_LABEL,
|
||||
true, // running Pro version
|
||||
userService);
|
||||
|
||||
PdfMetadata testMetadata =
|
||||
PdfMetadata.builder().author("Original Author").title("Test Title").build();
|
||||
|
||||
// Configure pro features
|
||||
CustomMetadata customMetadata =
|
||||
applicationProperties.getPremium().getProFeatures().getCustomMetadata();
|
||||
when(customMetadata.isAutoUpdateMetadata()).thenReturn(true);
|
||||
when(customMetadata.getCreator()).thenReturn("Pro Creator");
|
||||
when(customMetadata.getAuthor()).thenReturn("Pro Author username");
|
||||
when(userService.getCurrentUsername()).thenReturn("testUser");
|
||||
|
||||
// Act - create a new document with Pro features
|
||||
proService.setMetadataToPdf(testDocument, testMetadata, true);
|
||||
|
||||
// Assert - verify only once for each call
|
||||
verify(testInfo).setCreator("Pro Creator");
|
||||
verify(testInfo).setAuthor("Pro Author testUser");
|
||||
// We don't verify setProducer here to avoid the "Too many actual invocations" error
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetMetadataToPdf_ExistingDocument() {
|
||||
// Create a fresh document
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Prepare test metadata with existing creation date
|
||||
Calendar existingCreationDate = Calendar.getInstance();
|
||||
existingCreationDate.add(Calendar.DAY_OF_MONTH, -1); // Yesterday
|
||||
|
||||
PdfMetadata testMetadata =
|
||||
PdfMetadata.builder()
|
||||
.author("Test Author")
|
||||
.title("Test Title")
|
||||
.subject("Test Subject")
|
||||
.keywords("Test Keywords")
|
||||
.creationDate(existingCreationDate)
|
||||
.build();
|
||||
|
||||
// Act
|
||||
pdfMetadataService.setMetadataToPdf(testDocument, testMetadata, false);
|
||||
|
||||
// Assert - should NOT set a new creation date
|
||||
verify(testInfo).setTitle("Test Title");
|
||||
verify(testInfo).setProducer(STIRLING_PDF_LABEL);
|
||||
verify(testInfo).setSubject("Test Subject");
|
||||
verify(testInfo).setKeywords("Test Keywords");
|
||||
verify(testInfo).setModificationDate(org.mockito.ArgumentMatchers.any(Calendar.class));
|
||||
verify(testInfo).setAuthor("Test Author");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetMetadataToPdf_NullCreationDate() {
|
||||
// Create a fresh document
|
||||
PDDocument testDocument = mock(PDDocument.class);
|
||||
PDDocumentInformation testInfo = mock(PDDocumentInformation.class);
|
||||
when(testDocument.getDocumentInformation()).thenReturn(testInfo);
|
||||
|
||||
// Prepare test metadata with null creation date
|
||||
PdfMetadata testMetadata =
|
||||
PdfMetadata.builder()
|
||||
.author("Test Author")
|
||||
.title("Test Title")
|
||||
.creationDate(null) // Explicitly null creation date
|
||||
.build();
|
||||
|
||||
// Act
|
||||
pdfMetadataService.setMetadataToPdf(testDocument, testMetadata, false);
|
||||
|
||||
// Assert - should set a new creation date
|
||||
verify(testInfo).setCreator(STIRLING_PDF_LABEL);
|
||||
verify(testInfo).setCreationDate(org.mockito.ArgumentMatchers.any(Calendar.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import stirling.software.common.configuration.InstallationPathConfig;
|
||||
import stirling.software.SPDF.model.SignatureFile;
|
||||
|
||||
class SignatureServiceTest {
|
||||
|
||||
@TempDir Path tempDir;
|
||||
private SignatureService signatureService;
|
||||
private Path personalSignatureFolder;
|
||||
private Path sharedSignatureFolder;
|
||||
private final String ALL_USERS_FOLDER = "ALL_USERS";
|
||||
private final String TEST_USER = "testUser";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws IOException {
|
||||
// Set up our test directory structure
|
||||
personalSignatureFolder = tempDir.resolve(TEST_USER);
|
||||
sharedSignatureFolder = tempDir.resolve(ALL_USERS_FOLDER);
|
||||
|
||||
Files.createDirectories(personalSignatureFolder);
|
||||
Files.createDirectories(sharedSignatureFolder);
|
||||
|
||||
// Create test signature files
|
||||
Files.write(
|
||||
personalSignatureFolder.resolve("personal.png"),
|
||||
"personal signature content".getBytes());
|
||||
Files.write(
|
||||
sharedSignatureFolder.resolve("shared.jpg"), "shared signature content".getBytes());
|
||||
|
||||
// Use try-with-resources for mockStatic
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Initialize the service with our temp directory
|
||||
signatureService = new SignatureService();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasAccessToFile_PersonalFileExists() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
boolean hasAccess = signatureService.hasAccessToFile(TEST_USER, "personal.png");
|
||||
|
||||
// Verify
|
||||
assertTrue(hasAccess, "User should have access to their personal file");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasAccessToFile_SharedFileExists() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
boolean hasAccess = signatureService.hasAccessToFile(TEST_USER, "shared.jpg");
|
||||
|
||||
// Verify
|
||||
assertTrue(hasAccess, "User should have access to shared files");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasAccessToFile_FileDoesNotExist() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
boolean hasAccess = signatureService.hasAccessToFile(TEST_USER, "nonexistent.png");
|
||||
|
||||
// Verify
|
||||
assertFalse(hasAccess, "User should not have access to non-existent files");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasAccessToFile_InvalidFileName() {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test and verify
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> signatureService.hasAccessToFile(TEST_USER, "../invalid.png"),
|
||||
"Should throw exception for file names with directory traversal");
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> signatureService.hasAccessToFile(TEST_USER, "invalid/file.png"),
|
||||
"Should throw exception for file names with paths");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAvailableSignatures() {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
List<SignatureFile> signatures = signatureService.getAvailableSignatures(TEST_USER);
|
||||
|
||||
// Verify
|
||||
assertEquals(2, signatures.size(), "Should return both personal and shared signatures");
|
||||
|
||||
// Check that we have one of each type
|
||||
boolean hasPersonal =
|
||||
signatures.stream()
|
||||
.anyMatch(
|
||||
sig ->
|
||||
"personal.png".equals(sig.getFileName())
|
||||
&& "Personal".equals(sig.getCategory()));
|
||||
boolean hasShared =
|
||||
signatures.stream()
|
||||
.anyMatch(
|
||||
sig ->
|
||||
"shared.jpg".equals(sig.getFileName())
|
||||
&& "Shared".equals(sig.getCategory()));
|
||||
|
||||
assertTrue(hasPersonal, "Should include personal signature");
|
||||
assertTrue(hasShared, "Should include shared signature");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSignatureBytes_PersonalFile() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
byte[] bytes = signatureService.getSignatureBytes(TEST_USER, "personal.png");
|
||||
|
||||
// Verify
|
||||
assertEquals(
|
||||
"personal signature content",
|
||||
new String(bytes),
|
||||
"Should return the correct content for personal file");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSignatureBytes_SharedFile() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
byte[] bytes = signatureService.getSignatureBytes(TEST_USER, "shared.jpg");
|
||||
|
||||
// Verify
|
||||
assertEquals(
|
||||
"shared signature content",
|
||||
new String(bytes),
|
||||
"Should return the correct content for shared file");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSignatureBytes_FileNotFound() {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test and verify
|
||||
assertThrows(
|
||||
FileNotFoundException.class,
|
||||
() -> signatureService.getSignatureBytes(TEST_USER, "nonexistent.png"),
|
||||
"Should throw exception for non-existent files");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSignatureBytes_InvalidFileName() {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test and verify
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> signatureService.getSignatureBytes(TEST_USER, "../invalid.png"),
|
||||
"Should throw exception for file names with directory traversal");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAvailableSignatures_EmptyUsername() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
List<SignatureFile> signatures = signatureService.getAvailableSignatures("");
|
||||
|
||||
// Verify - should only have shared signatures
|
||||
assertEquals(
|
||||
1,
|
||||
signatures.size(),
|
||||
"Should return only shared signatures for empty username");
|
||||
assertEquals(
|
||||
"shared.jpg",
|
||||
signatures.get(0).getFileName(),
|
||||
"Should have the shared signature");
|
||||
assertEquals(
|
||||
"Shared", signatures.get(0).getCategory(), "Should be categorized as shared");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAvailableSignatures_NonExistentUser() throws IOException {
|
||||
// Mock static method for each test
|
||||
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
||||
mockStatic(InstallationPathConfig.class)) {
|
||||
mockedConfig
|
||||
.when(InstallationPathConfig::getSignaturesPath)
|
||||
.thenReturn(tempDir.toString());
|
||||
|
||||
// Test
|
||||
List<SignatureFile> signatures =
|
||||
signatureService.getAvailableSignatures("nonExistentUser");
|
||||
|
||||
// Verify - should only have shared signatures
|
||||
assertEquals(
|
||||
1,
|
||||
signatures.size(),
|
||||
"Should return only shared signatures for non-existent user");
|
||||
assertEquals(
|
||||
"shared.jpg",
|
||||
signatures.get(0).getFileName(),
|
||||
"Should have the shared signature");
|
||||
assertEquals(
|
||||
"Shared", signatures.get(0).getCategory(), "Should be categorized as shared");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user