zhizhijie
2026-10-06 bee9e18c3af284ff432a4472f1d409f5a6dc09a7
traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java
New file
@@ -0,0 +1,136 @@
package com.trafficaudit.holiday.service;
import org.junit.jupiter.api.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
class HolidayTrendChartServiceTest {
    @Test
    void rendersLinePieAndStackedChartsAsPng() throws Exception {
        HolidayTrendChartService service = new HolidayTrendChartService();
        HolidayTrendChartService.ChartSeries first = new HolidayTrendChartService.ChartSeries();
        first.setName("2026年");
        first.setValues(java.util.Arrays.asList(
                java.math.BigDecimal.ONE, java.math.BigDecimal.TEN, null));
        HolidayTrendChartService.ChartSeries second = new HolidayTrendChartService.ChartSeries();
        second.setName("2025年");
        second.setValues(java.util.Arrays.asList(
                java.math.BigDecimal.valueOf(2), java.math.BigDecimal.valueOf(8),
                java.math.BigDecimal.valueOf(4)));
        byte[] line = service.lineChart("万人次", java.util.Arrays.asList(first, second), false);
        assertPng(line);
        assertNoLargeLightGrayBackground(line);
        HolidayTrendChartService.ChartCategory category = new HolidayTrendChartService.ChartCategory();
        category.setName("铁路");
        category.setValue(java.math.BigDecimal.TEN);
        byte[] pie = service.pieChart("人次", java.util.Collections.singletonList(category), 400, 300);
        assertPng(pie);
        byte[] stacked = service.stackedBarChart("占比", java.util.Arrays.asList("10月1日", "10月2日"),
                java.util.Arrays.asList(first, second), true, 500, 320);
        assertPng(stacked);
        assertNoLargeLightGrayBackground(stacked);
    }
    @Test
    void roundsLineDataToTheSamePrecisionAsLabels() {
        assertEquals(new BigDecimal("0.49"),
                HolidayTrendChartService.displayValue(new BigDecimal("0.4904"), false, 2));
        assertEquals(new BigDecimal("0.49"),
                HolidayTrendChartService.displayValue(new BigDecimal("0.4911"), false, 2));
        assertEquals(new BigDecimal("0.491"),
                HolidayTrendChartService.displayValue(new BigDecimal("0.4911"), false, 3));
        assertEquals(new BigDecimal("0.123"),
                HolidayTrendChartService.displayValue(new BigDecimal("0.1234"), true, 2));
    }
    @Test
    void rendersSameGeometryWhenValuesRoundToSameLabel() {
        HolidayTrendChartService service = new HolidayTrendChartService();
        HolidayTrendChartService.ChartSeries first = new HolidayTrendChartService.ChartSeries();
        first.setName("平均拥挤度");
        first.setValues(java.util.Arrays.asList(
                new BigDecimal("0.4904"), new BigDecimal("0.4923"), new BigDecimal("0.5100")));
        HolidayTrendChartService.ChartSeries second = new HolidayTrendChartService.ChartSeries();
        second.setName("平均拥挤度");
        second.setValues(java.util.Arrays.asList(
                new BigDecimal("0.4911"), new BigDecimal("0.4934"), new BigDecimal("0.5100")));
        byte[] firstChart = service.lineChart("拥挤度",
                java.util.Collections.singletonList(first), false, 2, 1100, 590);
        byte[] secondChart = service.lineChart("拥挤度",
                java.util.Collections.singletonList(second), false, 2, 1100, 590);
        assertPng(firstChart);
        assertPng(secondChart);
        assertArrayEquals(firstChart, secondChart);
    }
    @Test
    void scalesLineChartHeightForBetterVerticalSeparation() throws Exception {
        HolidayTrendChartService service = new HolidayTrendChartService();
        HolidayTrendChartService.ChartSeries series = new HolidayTrendChartService.ChartSeries();
        series.setName("测试");
        series.setValues(java.util.Arrays.asList(
                new BigDecimal("1.00"), new BigDecimal("2.00"), new BigDecimal("3.00")));
        byte[] png = service.lineChart("万人次",
                java.util.Collections.singletonList(series), false, 1100, 590);
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(png));
        assertNotNull(image);
        assertEquals(HolidayTrendChartService.scaleLineChartHeight(590), image.getHeight());
    }
    @Test
    void rendersHigherPrecisionLineLabelsWhenRequested() {
        HolidayTrendChartService service = new HolidayTrendChartService();
        HolidayTrendChartService.ChartSeries congestion = new HolidayTrendChartService.ChartSeries();
        congestion.setName("平均拥挤度");
        congestion.setValues(java.util.Arrays.asList(
                new java.math.BigDecimal("0.467029"),
                new java.math.BigDecimal("0.490890"),
                new java.math.BigDecimal("0.492414")));
        byte[] twoDecimals = service.lineChart("拥挤度",
                java.util.Collections.singletonList(congestion), false, 2, 1100, 590);
        byte[] threeDecimals = service.lineChart("拥挤度",
                java.util.Collections.singletonList(congestion), false, 3, 1100, 590);
        assertPng(twoDecimals);
        assertPng(threeDecimals);
        assertFalse(java.util.Arrays.equals(twoDecimals, threeDecimals));
    }
    private void assertNoLargeLightGrayBackground(byte[] data) throws Exception {
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(data));
        int matches = 0;
        for (int y = 0; y < image.getHeight(); y++) {
            for (int x = 0; x < image.getWidth(); x++) {
                int rgb = image.getRGB(x, y) & 0xFFFFFF;
                if (rgb == 0xF3F4F3) matches++;
            }
        }
        assertTrue(matches < image.getWidth() * image.getHeight() / 20,
                "chart still contains a large light-gray background area");
    }
    private void assertPng(byte[] data) {
        assertNotNull(data);
        assertTrue(data.length > 100);
        assertTrue(data[0] == (byte) 0x89 && data[1] == 0x50
                && data[2] == 0x4e && data[3] == 0x47);
    }
}