yeg
2026-09-09 f54b0dff8157c7ef2547ac912d70cab63de50626
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package com.battery.business.report;
 
import static org.junit.jupiter.api.Assertions.*;
import java.util.*;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.battery.business.web.FormationReportController;
import com.ruoyi.common.exception.ServiceException;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.security.access.prepost.PreAuthorize;
 
/** JSON 投影在临时 MySQL 库验证,不能用内存数据库的替代函数证明实际查询正确。 */
@EnabledIfEnvironmentVariable(named="FORMATION_MYSQL_URL", matches=".+")
class FormationReportReadMysqlTest {
    private JdbcTemplate jdbc;
    private FormationReportRepository repository;
    private FormationReportService service;
    private long id;
 
    @BeforeEach void setup() {
        String url=System.getenv("FORMATION_MYSQL_URL"), user=System.getenv("FORMATION_MYSQL_USER"), password=System.getenv("FORMATION_MYSQL_PASSWORD");
        // 建表前核对实际连接的 schema,避免测试误写共享开发库。
        jdbc=new JdbcTemplate(new DriverManagerDataSource(url,user,password));
        assertTrue(jdbc.queryForObject("SELECT DATABASE()",String.class).matches("formation_read_[a-f0-9]{32}"));
        jdbc.execute("DROP TABLE IF EXISTS t_formation_report_version");
        jdbc.execute("DROP TABLE IF EXISTS t_formation_report");
        jdbc.execute("CREATE TABLE t_formation_report(report_id BIGINT AUTO_INCREMENT PRIMARY KEY,report_name VARCHAR(100),creator_id BIGINT,creator_name VARCHAR(100),created_at_utc DATETIME(3))");
        jdbc.execute("CREATE TABLE t_formation_report_version(report_id BIGINT,version_no INT,snapshot_json JSON,operator_id BIGINT,operator_name VARCHAR(100),created_at_utc DATETIME(3),change_summary VARCHAR(500),PRIMARY KEY(report_id,version_no))");
        repository=new FormationReportRepository(jdbc.getDataSource());
        service=new FormationReportService(null,null,repository,null,null);
        id=repository.insert("保存版本一",snapshot(1),1,"操作员",1000);
    }
 
    private String snapshot(int version) {
        List<Map<String,Object>> items=new ArrayList<>();
        for(int index=1;index<=2;index++) {
            var item=new LinkedHashMap<String,Object>();
            item.put("source",Map.of("selection",Map.of("testId",index,"testBatteryId",10+index),"name","测试"+index,"batteryGroup","组"+index,"batteryNo","同名电池"));
            item.put("cycleNos",index==1?List.of(1,3):List.of(1));
            item.put("chargeSteps",Map.of("1",List.of(Map.of("stepNo",1,"direction","CHARGE","endVoltage",4.2))));
            item.put("businessFields",List.of(Map.of("fieldName","F","fieldValue","5")));
            item.put("metrics",Map.of());item.put("cycles",List.of());
            var curves=new LinkedHashMap<String,Object>();
            curves.put("1",Map.of("zeroTime",1000,"records",List.of(Map.of("deviceTime",1000,"stepNo",1,"voltage",version,"current",0),Map.of("deviceTime",2500,"stepNo",1,"voltage",-1))));
            if(index==1)curves.put("3",Map.of("zeroTime",5000,"records",List.of(Map.of("deviceTime",5000,"stepNo",1,"voltage",3))));
            item.put("curves",curves);
            item.put("stepCurves",Map.of("legacyDuplicate","x".repeat(1_000_000)));
            items.add(item);
        }
        return JSON.toJSONString(Map.of("name","保存版本"+version,"items",items,"cycleNos",List.of(1,3),"description","说明",
                "settings",Map.of("values",Map.of("1|11|1|manual","2"),"fields",List.of()),"calculatedValues",Map.of("1|11|1|capacity1v",250)));
    }
 
    @Test void projectsOldSnapshotsWithoutLoadingDuplicatedCurvesOrChangingHistory() {
        String before=repository.get(id,1).snapshotJson();
        assertTrue(before.length()>2_000_000);
        var list=service.list();
        assertEquals("测试1、测试2",list.get(0).testName());
        assertEquals("组1、组2",list.get(0).batteryGroup());
        assertEquals(1,list.get(0).versionNo());
        assertTrue(JSON.toJSONBytes(list).length<2000);
        var first=JSON.parseObject(JSON.toJSONString(service.page(id,1)));
        assertTrue(first.getBooleanValue("curvesDeferred"));
        assertTrue(first.toJSONString().length()<5000);
        assertEquals(2,first.getJSONArray("items").size());
        var expectedItems=JSON.parseObject(before).getJSONArray("items");
        for(int i=0;i<2;i++) {
            JSONObject item=first.getJSONArray("items").getJSONObject(i);
            assertFalse(item.containsKey("curves"));assertFalse(item.containsKey("stepCurves"));
            for(String key:List.of("source","cycleNos","chargeSteps","businessFields","metrics","cycles"))
                assertEquals(expectedItems.getJSONObject(i).get(key),item.get(key));
        }
        repository.append(id,2,"保存版本二",snapshot(2),1,"操作员","追加新版本");
        assertEquals(2,service.page(id,null).get("versionNo"));
        assertEquals(2,service.list().get(0).versionNo());
        var curves=service.cycleCurves(id,1,1);
        assertEquals(2,curves.size());
        assertEquals(expectedItems.getJSONObject(0).getJSONObject("curves").get("1"),curves.get(0).curve());
        assertEquals(Map.of("testId",2,"testBatteryId",12),curves.get(1).selection());
        assertNull(service.cycleCurves(id,1,3).get(1).curve());
        assertThrows(ServiceException.class,()->service.page(999,null));
        assertThrows(ServiceException.class,()->service.cycleCurves(id,99,1));
        assertThrows(ServiceException.class,()->service.cycleCurves(id,1,2));
        assertEquals(before,repository.get(id,1).snapshotJson());
        assertFalse(JSON.toJSONString(repository.list()).contains("snapshot"));
    }
 
    @Test void pageAndPrintKeepSeparatePayloadsAndCurveActionsKeepSeparatePermissions() throws Exception {
        var controller=new FormationReportController(service,repository);
        var page=JSON.parseObject(JSON.toJSONString(controller.get(id))).getJSONObject("data");
        assertTrue(page.toJSONString().length()<5000);
        var print=JSON.parseObject(JSON.toJSONString(controller.print(id,1))).getJSONObject("data");
        assertEquals(List.of(1,3),print.getList("cycleNos",Integer.class));
        assertNotNull(print.getJSONArray("items").getJSONObject(0).getJSONObject("curves").get("3"));
        assertEquals("@ss.hasPermi('system:formation-report:query')",FormationReportController.class.getMethod("cycle",long.class,int.class,int.class).getAnnotation(PreAuthorize.class).value());
        assertEquals("@ss.hasPermi('system:formation-report:edit')",FormationReportController.class.getMethod("editingCycle",long.class,int.class,int.class).getAnnotation(PreAuthorize.class).value());
    }
}