格式修改

This commit is contained in:
2026-08-05 10:35:07 +08:00
parent 81c9c92f5d
commit 496fc58a90
241 changed files with 5600 additions and 2088 deletions
@@ -9,6 +9,7 @@ import com.baiyue.print.renderer.InboundMarkV1Renderer;
import com.baiyue.print.renderer.PdfQrRenderer;
import com.baiyue.print.service.InboundMarkPdfService;
import com.baiyue.print.service.PdfGenerationLimiter;
import jakarta.annotation.Resource;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.RGBLuminanceSource;
@@ -29,16 +30,20 @@ import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/** End-to-end renderer acceptance checks. These intentionally exercise the real service, not mocks. */
@SpringJUnitConfig(classes = {InboundMarkPdfService.class, PrintPdfProperties.class,
PdfGenerationLimiter.class, InboundMarkV1Renderer.class, PdfQrRenderer.class})
class InboundMarkPdfAcceptanceTest {
private static final String TEMPLATE = "INBOUND_MARK_V1";
private static final BigDecimal MM_100 = new BigDecimal("100");
@Resource
private InboundMarkPdfService service;
@Test
void generatesOnePageWithExactSizeTextOrderEmbeddedChineseFontAndNoDiskArtifact(@TempDir Path tempDir)
throws Exception {
InboundMarkPdfService service = service();
InboundMarkPdfDtos.Label label = label(1);
String originalTmp = System.getProperty("java.io.tmpdir");
System.setProperty("java.io.tmpdir", tempDir.toString());
@@ -62,13 +67,13 @@ class InboundMarkPdfAcceptanceTest {
@Test
void preservesPageOrderAndDecodableQrOnFirstMiddleAndLastPages() throws Exception {
List<InboundMarkPdfDtos.Label> labels = labels(19);
assertPdf(service().generate(request(labels)).content(), labels);
assertPdf(service.generate(request(labels)).content(), labels);
}
@Test
void generatesTwoHundredEighteenPagesWithExactDimensions() throws Exception {
List<InboundMarkPdfDtos.Label> labels = labels(218);
byte[] pdf = service().generate(request(labels)).content();
byte[] pdf = service.generate(request(labels)).content();
try (PDDocument document = Loader.loadPDF(pdf)) {
assertThat(document.getNumberOfPages()).isEqualTo(218);
for (int i : List.of(0, 108, 217)) {
@@ -82,7 +87,7 @@ class InboundMarkPdfAcceptanceTest {
assumeTrue(Boolean.getBoolean("print.capacity.tests"),
"Enable with -Dprint.capacity.tests=true for the 2000-page capacity acceptance test");
List<InboundMarkPdfDtos.Label> labels = labels(2000);
byte[] pdf = service().generate(request(labels)).content();
byte[] pdf = service.generate(request(labels)).content();
assertThat(pdf).startsWith("%PDF".getBytes(StandardCharsets.US_ASCII));
assertThat(pdf.length).isLessThan(32 * 1024 * 1024);
try (PDDocument document = Loader.loadPDF(pdf)) {
@@ -152,12 +157,6 @@ class InboundMarkPdfAcceptanceTest {
return List.of(0, size / 2, size - 1);
}
private InboundMarkPdfService service() {
PrintPdfProperties properties = new PrintPdfProperties();
return new InboundMarkPdfService(properties, new PdfGenerationLimiter(properties),
new InboundMarkV1Renderer(new PdfQrRenderer()), new PdfQrRenderer());
}
private InboundMarkPdfDtos.Request request(List<InboundMarkPdfDtos.Label> labels) {
return new InboundMarkPdfDtos.Request(TEMPLATE,
new InboundMarkPdfDtos.PageSpec(MM_100, MM_100), "acceptance.pdf", labels);
@@ -4,20 +4,28 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class PrintFontHealthIndicatorTest {
@Test
void reportsUpForPackagedParseableFont() {
PrintPdfProperties properties = new PrintPdfProperties();
assertThat(new PrintFontHealthIndicator(properties).health().getStatus()).isEqualTo(Status.UP);
context("fonts/NotoSansSC-Bold.ttf").run(context -> assertThat(
context.getBean(PrintFontHealthIndicator.class).health().getStatus()).isEqualTo(Status.UP));
}
@Test
void reportsDownForMissingFont() {
PrintPdfProperties properties = new PrintPdfProperties();
properties.setFontResource("fonts/missing.ttf");
context("fonts/missing.ttf").run(context -> assertThat(
context.getBean(PrintFontHealthIndicator.class).health().getStatus()).isEqualTo(Status.DOWN));
}
assertThat(new PrintFontHealthIndicator(properties).health().getStatus()).isEqualTo(Status.DOWN);
private ApplicationContextRunner context(String font) {
return new ApplicationContextRunner()
.withBean(PrintPdfProperties.class, () -> {
PrintPdfProperties properties = new PrintPdfProperties();
properties.setFontResource(font);
return properties;
})
.withBean(PrintFontHealthIndicator.class);
}
}
@@ -5,6 +5,7 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.common.web.GlobalExceptionHandler;
import com.baiyue.print.dto.InboundMarkPdfDtos;
import com.baiyue.print.service.InboundMarkPdfService;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
@@ -12,6 +13,9 @@ import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import java.nio.charset.StandardCharsets;
@@ -28,16 +32,18 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringJUnitConfig(classes = {InternalPdfController.class, InternalServiceTokenGuard.class})
@TestPropertySource(properties = "baiyue.security.internal-service-token=0123456789abcdef0123456789abcdef")
class InternalPdfControllerTest {
private static final String TOKEN = "0123456789abcdef0123456789abcdef";
@MockBean
private InboundMarkPdfService service;
@Resource
private InternalPdfController controller;
private MockMvc mockMvc;
@BeforeEach
void setUp() {
service = mock(InboundMarkPdfService.class);
InternalPdfController controller = new InternalPdfController(
service, new InternalServiceTokenGuard(TOKEN));
mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setControllerAdvice(new GlobalExceptionHandler())
.build();
@@ -3,17 +3,23 @@ package com.baiyue.print.controller;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException;
import org.junit.jupiter.api.Test;
import jakarta.annotation.Resource;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@SpringJUnitConfig(InternalServiceTokenGuard.class)
@TestPropertySource(properties = "baiyue.security.internal-service-token=0123456789abcdef0123456789abcdef")
class InternalServiceTokenGuardTest {
private static final String TOKEN = "0123456789abcdef0123456789abcdef";
@Resource private InternalServiceTokenGuard guard;
@Test
void acceptsOnlyConfiguredToken() {
InternalServiceTokenGuard guard = new InternalServiceTokenGuard(TOKEN);
guard.verify(TOKEN);
assertThatThrownBy(() -> guard.verify(null))
.isInstanceOf(BizException.class)
@@ -27,10 +33,14 @@ class InternalServiceTokenGuardTest {
@Test
void refusesUnsafeConfiguration() {
assertThatThrownBy(() -> new InternalServiceTokenGuard("too-short"))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("at least 32 bytes");
assertThatThrownBy(() -> new InternalServiceTokenGuard(null))
.isInstanceOf(IllegalStateException.class);
new ApplicationContextRunner()
.withBean(PropertySourcesPlaceholderConfigurer.class)
.withBean(InternalServiceTokenGuard.class)
.withPropertyValues("baiyue.security.internal-service-token=too-short")
.run(context -> assertThat(context).hasFailed());
new ApplicationContextRunner()
.withBean(PropertySourcesPlaceholderConfigurer.class)
.withBean(InternalServiceTokenGuard.class)
.run(context -> assertThat(context).hasFailed());
}
}
@@ -10,15 +10,20 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = {PrintRequestSizeFilter.class, PrintPdfProperties.class,
PrintRequestSizeFilterTest.TestConfig.class})
class PrintRequestSizeFilterTest {
private PrintRequestSizeFilter filter;
@Resource private PrintRequestSizeFilter filter;
@Resource private PrintPdfProperties properties;
@BeforeEach
void setUp() {
PrintPdfProperties properties = new PrintPdfProperties();
properties.setMaxRequestBytes(10);
filter = new PrintRequestSizeFilter(properties, new ObjectMapper().findAndRegisterModules());
}
@Test
@@ -86,4 +91,12 @@ class PrintRequestSizeFilterTest {
.contains("Request body exceeds 10 bytes")
.contains("\"requestId\":\"request-123\"");
}
@Configuration
static class TestConfig {
@Bean
ObjectMapper objectMapper() {
return new ObjectMapper().findAndRegisterModules();
}
}
}
@@ -7,6 +7,7 @@ import com.baiyue.print.dto.InboundMarkPdfDtos;
import com.baiyue.print.renderer.InboundMarkV1Renderer;
import com.baiyue.print.renderer.PdfQrRenderer;
import com.baiyue.print.renderer.PdfUnits;
import jakarta.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
@@ -14,17 +15,15 @@ import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.junit.jupiter.api.Test;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = {InboundMarkPdfService.class, PrintPdfProperties.class,
PdfGenerationLimiter.class, InboundMarkV1Renderer.class, PdfQrRenderer.class})
class InboundMarkPdfServiceGenerationTest {
@Resource
private InboundMarkPdfService service;
@Test
void generatesOneStrictHundredMillimeterPagePerLabelInRequestOrder() throws IOException {
PrintPdfProperties properties = new PrintPdfProperties();
PdfQrRenderer qrRenderer = new PdfQrRenderer();
InboundMarkPdfService service = new InboundMarkPdfService(
properties,
new PdfGenerationLimiter(properties),
new InboundMarkV1Renderer(qrRenderer),
qrRenderer);
InboundMarkPdfDtos.Request request = new InboundMarkPdfDtos.Request(
"INBOUND_MARK_V1",
new InboundMarkPdfDtos.PageSpec(new BigDecimal("100"), new BigDecimal("100.0")),
@@ -10,23 +10,20 @@ import com.baiyue.print.config.PrintPdfProperties;
import com.baiyue.print.dto.InboundMarkPdfDtos;
import com.baiyue.print.renderer.InboundMarkV1Renderer;
import com.baiyue.print.renderer.PdfQrRenderer;
import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = {InboundMarkPdfService.class, PrintPdfProperties.class})
class InboundMarkPdfServiceValidationTest {
private InboundMarkPdfService service;
@BeforeEach
void setUp() {
PrintPdfProperties properties = new PrintPdfProperties();
service = new InboundMarkPdfService(
properties,
mock(PdfGenerationLimiter.class),
mock(InboundMarkV1Renderer.class),
mock(PdfQrRenderer.class));
}
@MockBean private PdfGenerationLimiter limiter;
@MockBean private InboundMarkV1Renderer renderer;
@MockBean private PdfQrRenderer qrRenderer;
@Resource private InboundMarkPdfService service;
@Test
void rejectsUnsupportedPageSizeBeforeRendering() {
@@ -7,15 +7,16 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.print.config.PrintPdfProperties;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = {PdfGenerationLimiter.class, PdfGenerationLimiterTest.TestConfig.class})
class PdfGenerationLimiterTest {
@Resource private PdfGenerationLimiter limiter;
@Test
void rejectsWhenAllPermitsAreInUseAndReleasesPermitOnClose() {
PrintPdfProperties properties = new PrintPdfProperties();
properties.setMaxConcurrentGenerations(1);
properties.setAcquireTimeout(Duration.ZERO);
PdfGenerationLimiter limiter = new PdfGenerationLimiter(properties);
PdfGenerationLimiter.Permit permit = limiter.acquire();
assertThatThrownBy(limiter::acquire)
.isInstanceOfSatisfying(BizException.class,
@@ -27,4 +28,15 @@ class PdfGenerationLimiterTest {
// A second acquisition proves that close returned the only permit.
}
}
@Configuration
static class TestConfig {
@Bean
PrintPdfProperties properties() {
PrintPdfProperties properties = new PrintPdfProperties();
properties.setMaxConcurrentGenerations(1);
properties.setAcquireTimeout(Duration.ZERO);
return properties;
}
}
}