按设备绑定关系查询关联测试与通道
以关联测试集合替换当前测试占位,按测试去重并保留各状态和本设备通道。发现候选只返回设备事实,不新增表,保留设备操作校验。
后端全量测试与打包通过,补充内存数据库映射及分页插件验证,规范与需求审查通过。
| | |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Size; |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | import com.battery.business.domain.vo.DeviceRelatedTestVo; |
| | | import org.apache.commons.lang3.builder.ToStringBuilder; |
| | | import org.apache.commons.lang3.builder.ToStringStyle; |
| | | import com.ruoyi.common.core.domain.BaseEntity; |
| | |
| | | /** 在线状态:0离线、1在线 */ |
| | | private String onlineStatus; |
| | | |
| | | /** 测试状态展示值,由测试绑定事实派生,不写入采集器表。 */ |
| | | /** 进行中测试关联标记,供启禁用和删除校验使用,不写入采集器表。 */ |
| | | private String testStatus; |
| | | |
| | | /** 当前测试展示值,由测试绑定事实派生,不写入采集器表。 */ |
| | | private String currentTest; |
| | | /** 关联测试与本采集器绑定通道,由现有绑定关系查询,不写入设备表。 */ |
| | | private List<DeviceRelatedTestVo> relatedTests = List.of(); |
| | | |
| | | /** 兼容旧页面的派生字段,不参与采集器登记持久化。 */ |
| | | private String currentSampleName; |
| | |
| | | this.testStatus = testStatus; |
| | | } |
| | | |
| | | public String getCurrentTest() |
| | | public List<DeviceRelatedTestVo> getRelatedTests() |
| | | { |
| | | return currentTest; |
| | | return relatedTests; |
| | | } |
| | | |
| | | public void setCurrentTest(String currentTest) |
| | | public void setRelatedTests(List<DeviceRelatedTestVo> relatedTests) |
| | | { |
| | | this.currentTest = currentTest; |
| | | this.relatedTests = relatedTests; |
| | | } |
| | | |
| | | public String getCurrentSampleName() |
| | |
| | | .append("channelCount", getChannelCount()) |
| | | .append("onlineStatus", getOnlineStatus()) |
| | | .append("testStatus", getTestStatus()) |
| | | .append("currentTest", getCurrentTest()) |
| | | .append("relatedTests", getRelatedTests()) |
| | | .append("currentSampleName", getCurrentSampleName()) |
| | | .append("status", getStatus()) |
| | | .append("delFlag", getDelFlag()) |
| | |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import com.battery.business.domain.vo.DeviceRelatedTestVo; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import jakarta.validation.constraints.Max; |
| | | import jakarta.validation.constraints.Min; |
| | |
| | | /** 在线状态:0正常,1异常。 */ |
| | | private String onlineStatus; |
| | | |
| | | /** 测试状态展示值,由通道绑定事实派生,不写入检测柜表。 */ |
| | | /** 进行中测试关联标记,供启禁用和删除校验使用,不写入检测柜表。 */ |
| | | private String testStatus; |
| | | |
| | | /** 当前测试展示值,由通道绑定事实派生,不写入检测柜表。 */ |
| | | @Size(max = 200, message = "当前测试内容长度不能超过200个字符") |
| | | private String currentTest; |
| | | /** 关联测试与本柜绑定通道,由现有绑定关系查询,不写入检测柜表。 */ |
| | | private List<DeviceRelatedTestVo> relatedTests = List.of(); |
| | | |
| | | /** 启用状态:0启用,1停用。 */ |
| | | private String status; |
| | |
| | | this.testStatus = testStatus; |
| | | } |
| | | |
| | | public String getCurrentTest() |
| | | public List<DeviceRelatedTestVo> getRelatedTests() |
| | | { |
| | | return currentTest; |
| | | return relatedTests; |
| | | } |
| | | |
| | | public void setCurrentTest(String currentTest) |
| | | public void setRelatedTests(List<DeviceRelatedTestVo> relatedTests) |
| | | { |
| | | this.currentTest = currentTest; |
| | | this.relatedTests = relatedTests; |
| | | } |
| | | |
| | | public String getStatus() |
| | |
| | | ", channelCount=" + channelCount + |
| | | ", onlineStatus='" + onlineStatus + '\'' + |
| | | ", testStatus='" + testStatus + '\'' + |
| | | ", currentTest='" + currentTest + '\'' + |
| | | ", relatedTests=" + relatedTests + |
| | | ", status='" + status + '\'' + |
| | | ", delFlag='" + delFlag + '\'' + |
| | | ", device='" + device + '\'' + |
| New file |
| | |
| | | package com.battery.business.domain.vo; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** 设备关联的测试及该测试绑定的本设备通道,不写入设备表。 */ |
| | | public class DeviceRelatedTestVo |
| | | { |
| | | private Long testId; |
| | | private String testName; |
| | | private String testStatus; |
| | | private List<String> channels = new ArrayList<>(); |
| | | |
| | | public Long getTestId() { return testId; } |
| | | public void setTestId(Long testId) { this.testId = testId; } |
| | | public String getTestName() { return testName; } |
| | | public void setTestName(String testName) { this.testName = testName; } |
| | | public String getTestStatus() { return testStatus; } |
| | | public void setTestStatus(String testStatus) { this.testStatus = testStatus; } |
| | | public List<String> getChannels() { return channels; } |
| | | public void setChannels(List<String> channels) { this.channels = channels; } |
| | | } |
| | |
| | | String manufacturer, |
| | | String model, |
| | | Integer channelCount, |
| | | String onlineStatus, |
| | | String testStatus, |
| | | String currentTest) |
| | | String onlineStatus) |
| | | { |
| | | public String getDeviceCode() { return deviceCode; } |
| | | public String getIp() { return ip; } |
| | |
| | | public String getModel() { return model; } |
| | | public Integer getChannelCount() { return channelCount; } |
| | | public String getOnlineStatus() { return onlineStatus; } |
| | | public String getTestStatus() { return testStatus; } |
| | | public String getCurrentTest() { return currentTest; } |
| | | } |
| | |
| | | /** 在线状态 */ |
| | | private String onlineStatus; |
| | | |
| | | /** 测试状态 */ |
| | | private String testStatus; |
| | | |
| | | /** 当前测试 */ |
| | | private String currentTest; |
| | | |
| | | public DiscoveredCollectorVo() |
| | | { |
| | | } |
| | | |
| | | public DiscoveredCollectorVo(String deviceCode, String ip, String mac, String name, String manufacturer, |
| | | String model, Integer channelCount, String onlineStatus, String testStatus, String currentTest) |
| | | String model, Integer channelCount, String onlineStatus) |
| | | { |
| | | this.deviceCode = deviceCode; |
| | | this.ip = ip; |
| | |
| | | this.model = model; |
| | | this.channelCount = channelCount; |
| | | this.onlineStatus = onlineStatus; |
| | | this.testStatus = testStatus; |
| | | this.currentTest = currentTest; |
| | | } |
| | | |
| | | public String getDeviceCode() |
| | |
| | | this.onlineStatus = onlineStatus; |
| | | } |
| | | |
| | | public String getTestStatus() |
| | | { |
| | | return testStatus; |
| | | } |
| | | |
| | | public void setTestStatus(String testStatus) |
| | | { |
| | | this.testStatus = testStatus; |
| | | } |
| | | |
| | | public String getCurrentTest() |
| | | { |
| | | return currentTest; |
| | | } |
| | | |
| | | public void setCurrentTest(String currentTest) |
| | | { |
| | | this.currentTest = currentTest; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.battery.business.mapper; |
| | | |
| | | import java.util.List; |
| | | import com.battery.business.domain.vo.DeviceRelatedTestVo; |
| | | |
| | | /** 从现有绑定关系读取设备关联测试。 */ |
| | | public interface DeviceRelatedTestMapper |
| | | { |
| | | /** 查询检测柜关联的未删除测试,按测试去重并汇总本柜通道。 */ |
| | | List<DeviceRelatedTestVo> selectCabinetRelatedTests(Long cabinetId); |
| | | |
| | | /** 查询采集器关联的未删除测试,按测试去重并汇总本采集器通道。 */ |
| | | List<DeviceRelatedTestVo> selectCollectorRelatedTests(Long collectorId); |
| | | } |
| | |
| | | collector.setOnlineStatus(OFFLINE); |
| | | // 测试占用由 t_test_collector_channel + t_test 派生,采集器登记表不写入这些字段。 |
| | | collector.setTestStatus(IDLE); |
| | | collector.setCurrentTest(null); |
| | | collector.setRelatedTests(List.of()); |
| | | collector.setCurrentSampleName(null); |
| | | if (StringUtils.isEmpty(collector.getStatus())) |
| | | { |
| | |
| | | private static final String TESTING = "1"; |
| | | private static final String ONLINE = "0"; |
| | | private static final String OFFLINE = "1"; |
| | | private static final Set<DeviceWorkStatus> ACTIVE_WORK_STATUSES = Set.of(DeviceWorkStatus.WORKING, |
| | | DeviceWorkStatus.PAUSED, DeviceWorkStatus.PROTECTED, DeviceWorkStatus.SYNCHRONIZING, |
| | | DeviceWorkStatus.LIT, DeviceWorkStatus.WAITING_TIMEOUT, DeviceWorkStatus.WAITING_START, |
| | | DeviceWorkStatus.LOCKED); |
| | | |
| | | private final TDetectionCabinetMapper detectionCabinetMapper; |
| | | private final DeviceDiscoveryCandidateStore candidateStore; |
| | |
| | | |
| | | /** |
| | | * 读取未过期且未登记的候选,离线设备仍保留身份并可选择。 |
| | | * 测试占用状态由实时通道工作状态聚合;测试归属留待后续绑定闭环确认。 |
| | | * 发现只返回设备事实,不从通道工作状态推断系统测试关系。 |
| | | * |
| | | * @return 可供选择的检测柜设备摘要 |
| | | */ |
| | |
| | | Set<String> registeredCodes = Set.copyOf(detectionCabinetMapper.selectRegisteredCabinetCodes()); |
| | | return candidateStore.snapshot(Instant.now()).cabinets().stream() |
| | | .filter(candidate -> !registeredCodes.contains(candidate.deviceCode())) |
| | | .map(candidate -> { |
| | | boolean active = candidate.online() && isActive(candidate); |
| | | return new DiscoveredCabinetVo( |
| | | .map(candidate -> new DiscoveredCabinetVo( |
| | | candidate.deviceCode(), candidate.ip(), candidate.mac(), candidate.name(), |
| | | candidate.manufacturer(), candidate.model(), candidate.channels().size(), candidate.online() ? "在线" : "离线", |
| | | active ? "测试中" : "空闲", |
| | | active ? "待确认" : "-"); |
| | | }) |
| | | candidate.manufacturer(), candidate.model(), candidate.channels().size(), candidate.online() ? "在线" : "离线")) |
| | | .toList(); |
| | | } |
| | | |
| | |
| | | private String stableCandidateKey(String adapterCode, Integer devtype, Integer devid) |
| | | { |
| | | return adapterCode + "-" + devtype + "-" + devid; |
| | | } |
| | | |
| | | private boolean isActive(CabinetCandidate candidate) |
| | | { |
| | | return candidate.channels().stream().anyMatch(channel -> ACTIVE_WORK_STATUSES.contains(channel.workStatus())); |
| | | } |
| | | |
| | | /** 将设备观测状态转换为最终数据库允许的通道事实状态。 */ |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" ?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.battery.business.mapper.DeviceRelatedTestMapper"> |
| | | <resultMap id="RelatedTestResult" type="com.battery.business.domain.vo.DeviceRelatedTestVo"> |
| | | <id property="testId" column="test_id" /> |
| | | <result property="testName" column="test_name" /> |
| | | <result property="testStatus" column="test_status" /> |
| | | <collection property="channels" ofType="java.lang.String"> |
| | | <result column="channel_label" /> |
| | | </collection> |
| | | </resultMap> |
| | | |
| | | <select id="selectCabinetRelatedTests" parameterType="Long" resultMap="RelatedTestResult"> |
| | | select distinct t.test_id, t.test_name, t.test_status, |
| | | concat(c.subdevid, '-', c.chlid) as channel_label |
| | | from t_test_channel_binding b |
| | | join t_detection_channel c on c.channel_id = b.channel_id |
| | | join t_test t on t.test_id = b.test_id |
| | | where c.cabinet_id = #{cabinetId} and t.del_flag = 0 |
| | | order by t.test_id desc, channel_label |
| | | </select> |
| | | |
| | | <select id="selectCollectorRelatedTests" parameterType="Long" resultMap="RelatedTestResult"> |
| | | select distinct t.test_id, t.test_name, t.test_status, b.channel_code as channel_label |
| | | from t_test_collector_channel b |
| | | join t_test t on t.test_id = b.test_id |
| | | where b.collector_id = #{collectorId} and t.del_flag = 0 |
| | | order by t.test_id desc, channel_label |
| | | </select> |
| | | </mapper> |
| | |
| | | <result property="channelCount" column="channel_count" /> |
| | | <result property="onlineStatus" column="online_status" /> |
| | | <result property="testStatus" column="test_status" /> |
| | | <result property="currentTest" column="current_test" /> |
| | | <result property="lastSeenAtUtc" column="last_seen_at_utc" /> |
| | | <result property="status" column="status" /> |
| | | <result property="delFlag" column="del_flag" /> |
| | |
| | | <result property="updateBy" column="update_by" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | <result property="remark" column="remark" /> |
| | | <collection property="relatedTests" column="collector_id" |
| | | select="com.battery.business.mapper.DeviceRelatedTestMapper.selectCollectorRelatedTests" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectCollectorVo"> |
| | |
| | | and test_fact.del_flag = 0 |
| | | and test_fact.test_status in ('RUNNING', 'PAUSED') |
| | | ) then '1' else '0' end as test_status, |
| | | case when exists ( |
| | | select 1 from t_test_collector_channel mapping |
| | | join t_test test_fact on test_fact.test_id = mapping.test_id |
| | | where mapping.collector_id = c.collector_id |
| | | and test_fact.del_flag = 0 |
| | | and test_fact.test_status in ('RUNNING', 'PAUSED') |
| | | ) then '待确认' else null end as current_test, |
| | | c.status, c.del_flag, c.create_by, |
| | | c.create_time, c.update_by, c.update_time, c.remark |
| | | from t_collector c |
| | |
| | | <result property="channelCount" column="channel_count" /> |
| | | <result property="onlineStatus" column="online_status" /> |
| | | <result property="testStatus" column="test_status" /> |
| | | <result property="currentTest" column="current_test" /> |
| | | <result property="status" column="status" /> |
| | | <result property="createBy" column="create_by" /> |
| | | <result property="createTime" column="create_time" /> |
| | |
| | | <result property="remark" column="remark" /> |
| | | <result property="delFlag" column="del_flag" /> |
| | | <result property="registrationStatus" column="registration_status" /> |
| | | <collection property="relatedTests" column="cabinet_id" |
| | | select="com.battery.business.mapper.DeviceRelatedTestMapper.selectCabinetRelatedTests" /> |
| | | </resultMap> |
| | | |
| | | <sql id="activeCabinetTestExists"> |
| | |
| | | manufacturer, model, capacity, channel_count, |
| | | case when upper(online_status) = 'ONLINE' or online_status = '0' then '0' else '1' end as online_status, |
| | | case when <include refid="activeCabinetTestExists"/> then '1' else '0' end as test_status, |
| | | case when <include refid="activeCabinetTestExists"/> then '待确认' else null end as current_test, |
| | | status, create_by, create_time, update_by, update_time, remark, del_flag, registration_status |
| | | from t_detection_cabinet |
| | | </sql> |
| | |
| | | |
| | | <!-- 核心模块--> |
| | | <dependency> |
| | | <groupId>com.h2database</groupId> |
| | | <artifactId>h2</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-framework</artifactId> |
| | | </dependency> |
| | |
| | | .filter(collector -> !registeredCodes.contains(collector.deviceCode())) |
| | | .map(collector -> new DiscoveredCollectorVo(collector.deviceCode(), collector.ip(), collector.mac(), |
| | | collector.name(), collector.manufacturer(), collector.model(), collector.channelCount(), |
| | | collector.online() ? "在线" : "离线", "空闲", "-")) |
| | | collector.online() ? "在线" : "离线")) |
| | | .toList(); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.battery.business.mapper; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | | import com.github.pagehelper.PageHelper; |
| | | import com.github.pagehelper.PageInfo; |
| | | import com.github.pagehelper.PageInterceptor; |
| | | import org.apache.ibatis.builder.xml.XMLMapperBuilder; |
| | | import org.apache.ibatis.datasource.unpooled.UnpooledDataSource; |
| | | import org.apache.ibatis.mapping.Environment; |
| | | import org.apache.ibatis.session.Configuration; |
| | | import org.apache.ibatis.session.SqlSession; |
| | | import org.apache.ibatis.session.SqlSessionFactoryBuilder; |
| | | import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; |
| | | import org.junit.jupiter.api.AfterEach; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.battery.business.domain.TCollector; |
| | | import com.battery.business.domain.TDetectionCabinet; |
| | | import com.battery.business.domain.vo.DeviceRelatedTestVo; |
| | | |
| | | /** 使用真实映射和内存数据库验证绑定查询,不连接共享开发库。 */ |
| | | class DeviceRelatedTestMapperTest |
| | | { |
| | | private SqlSession session; |
| | | |
| | | @BeforeEach |
| | | void setUp() throws Exception |
| | | { |
| | | var source = new UnpooledDataSource("org.h2.Driver", "jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL", "sa", ""); |
| | | var configuration = new Configuration(new Environment("test", new JdbcTransactionFactory(), source)); |
| | | var pagination = new PageInterceptor(); |
| | | var properties = new java.util.Properties(); |
| | | properties.setProperty("helperDialect", "mysql"); |
| | | pagination.setProperties(properties); |
| | | configuration.addInterceptor(pagination); |
| | | configuration.getTypeAliasRegistry().registerAliases("com.battery.business.domain"); |
| | | for (String name : List.of("DeviceRelatedTestMapper", "TDetectionCabinetMapper", "TCollectorMapper")) |
| | | { |
| | | String resource = "mapper/battery/" + name + ".xml"; |
| | | try (var input = getClass().getClassLoader().getResourceAsStream(resource)) |
| | | { |
| | | new XMLMapperBuilder(input, configuration, resource, configuration.getSqlFragments()).parse(); |
| | | } |
| | | } |
| | | session = new SqlSessionFactoryBuilder().build(configuration).openSession(); |
| | | try (var sql = session.getConnection().createStatement()) |
| | | { |
| | | sql.execute("create table t_test(test_id bigint primary key, test_name varchar(100), test_status varchar(30), del_flag int)"); |
| | | sql.execute("insert into t_test values (1,'Waiting','WAITING',0),(2,'Running','RUNNING',0),(3,'Paused','PAUSED',0),(4,'Completed','COMPLETED',0),(5,'Deleted','RUNNING',1),(6,'Other device','WAITING',0)"); |
| | | sql.execute("create table t_detection_channel(channel_id bigint primary key, cabinet_id bigint, subdevid int, chlid int, del_flag int)"); |
| | | sql.execute("insert into t_detection_channel values (11,1,1,1,0),(12,1,1,2,0),(13,1,2,1,0),(21,2,1,1,0)"); |
| | | sql.execute("create table t_test_channel_binding(test_id bigint, channel_id bigint)"); |
| | | sql.execute("insert into t_test_channel_binding values (1,11),(1,12),(1,13),(2,11),(3,12),(4,11),(5,11),(6,21),(1,21)"); |
| | | sql.execute("create table t_test_collector_channel(test_id bigint, collector_id bigint, channel_code varchar(100))"); |
| | | sql.execute("insert into t_test_collector_channel values (1,1,'S-01'),(1,1,'S-02'),(2,1,'S-01'),(3,1,'S-02'),(4,1,'S-01'),(5,1,'S-01'),(6,2,'S-03'),(1,2,'S-03')"); |
| | | String common = "adapter_id bigint, ip_address varchar(45), mac_address varchar(20), manufacturer varchar(100), model varchar(100), channel_count int, online_status varchar(10), status varchar(1), create_by varchar(64), create_time timestamp, update_by varchar(64), update_time timestamp, remark varchar(200), del_flag int default 0"; |
| | | sql.execute("create table t_detection_cabinet(cabinet_id bigint primary key, adapter_code varchar(64), cabinet_code varchar(64), cabinet_name varchar(100), capacity decimal, registration_status varchar(20) default 'REGISTERED', " + common + ")"); |
| | | sql.execute("insert into t_detection_cabinet(cabinet_id,cabinet_name,online_status) values (1,'Cabinet','OFFLINE'),(3,'Unused','ONLINE')"); |
| | | sql.execute("create table t_collector(collector_id bigint primary key, collector_code varchar(64), collector_name varchar(100), last_seen_at_utc timestamp, " + common + ")"); |
| | | sql.execute("insert into t_collector(collector_id,collector_name,online_status) values (1,'Collector','ONLINE'),(3,'Unused','OFFLINE')"); |
| | | } |
| | | } |
| | | |
| | | @AfterEach |
| | | void tearDown() |
| | | { |
| | | PageHelper.clearPage(); |
| | | if (session != null) session.close(); |
| | | } |
| | | |
| | | @Test |
| | | void cabinetIncludesAllTestStatesOnceAndOnlyItsOwnChannels() |
| | | { |
| | | var tests = session.getMapper(DeviceRelatedTestMapper.class).selectCabinetRelatedTests(1L); |
| | | assertStates(tests); |
| | | assertEquals(List.of("1-1", "1-2", "2-1"), tests.get(3).getChannels()); |
| | | assertEquals("Waiting", tests.get(3).getTestName()); |
| | | assertTrue(session.getMapper(DeviceRelatedTestMapper.class).selectCabinetRelatedTests(3L).isEmpty()); |
| | | } |
| | | |
| | | @Test |
| | | void collectorIncludesAllTestStatesOnceAndOnlyItsOwnChannels() |
| | | { |
| | | var tests = session.getMapper(DeviceRelatedTestMapper.class).selectCollectorRelatedTests(1L); |
| | | assertStates(tests); |
| | | assertEquals(List.of("S-01", "S-02"), tests.get(3).getChannels()); |
| | | assertTrue(session.getMapper(DeviceRelatedTestMapper.class).selectCollectorRelatedTests(3L).isEmpty()); |
| | | } |
| | | |
| | | @Test |
| | | void deviceListAndDetailAttachTheSameRelationsWithoutMultiplyingDeviceRows() |
| | | { |
| | | var cabinets = session.getMapper(TDetectionCabinetMapper.class); |
| | | assertEquals(2, cabinets.selectDetectionCabinetList(new TDetectionCabinet()).size()); |
| | | assertStates(cabinets.selectDetectionCabinetById(1L).getRelatedTests()); |
| | | assertTrue(cabinets.selectDetectionCabinetById(3L).getRelatedTests().isEmpty()); |
| | | var collectors = session.getMapper(TCollectorMapper.class); |
| | | assertEquals(2, collectors.selectCollectorList(new TCollector()).size()); |
| | | assertStates(collectors.selectCollectorById(1L).getRelatedTests()); |
| | | assertTrue(collectors.selectCollectorById(3L).getRelatedTests().isEmpty()); |
| | | } |
| | | |
| | | @Test |
| | | void devicePaginationKeepsTotalsAndCompleteRelatedTestCollections() |
| | | { |
| | | PageHelper.startPage(2, 1); |
| | | var cabinets = session.getMapper(TDetectionCabinetMapper.class).selectDetectionCabinetList(new TDetectionCabinet()); |
| | | assertEquals(2, new PageInfo<>(cabinets).getTotal()); |
| | | assertEquals(1, cabinets.size()); |
| | | assertEquals(1L, cabinets.get(0).getCabinetId()); |
| | | assertStates(cabinets.get(0).getRelatedTests()); |
| | | assertEquals(List.of("1-1", "1-2", "2-1"), cabinets.get(0).getRelatedTests().get(3).getChannels()); |
| | | |
| | | PageHelper.startPage(2, 1); |
| | | var collectors = session.getMapper(TCollectorMapper.class).selectCollectorList(new TCollector()); |
| | | assertEquals(2, new PageInfo<>(collectors).getTotal()); |
| | | assertEquals(1, collectors.size()); |
| | | assertEquals(1L, collectors.get(0).getCollectorId()); |
| | | assertStates(collectors.get(0).getRelatedTests()); |
| | | assertEquals(List.of("S-01", "S-02"), collectors.get(0).getRelatedTests().get(3).getChannels()); |
| | | } |
| | | |
| | | @Test |
| | | void erasedTestDisappearsFromBothDevices() throws Exception |
| | | { |
| | | try (var sql = session.getConnection().createStatement()) |
| | | { |
| | | sql.execute("delete from t_test where test_id = 1"); |
| | | } |
| | | var mapper = session.getMapper(DeviceRelatedTestMapper.class); |
| | | assertEquals(List.of(4L, 3L, 2L), mapper.selectCabinetRelatedTests(1L).stream().map(DeviceRelatedTestVo::getTestId).toList()); |
| | | assertEquals(List.of(4L, 3L, 2L), mapper.selectCollectorRelatedTests(1L).stream().map(DeviceRelatedTestVo::getTestId).toList()); |
| | | } |
| | | |
| | | private void assertStates(List<DeviceRelatedTestVo> tests) |
| | | { |
| | | assertEquals(List.of(4L, 3L, 2L, 1L), tests.stream().map(DeviceRelatedTestVo::getTestId).toList()); |
| | | assertEquals(List.of("COMPLETED", "PAUSED", "RUNNING", "WAITING"), tests.stream().map(DeviceRelatedTestVo::getTestStatus).toList()); |
| | | } |
| | | } |
| | |
| | | assertEquals(new BigDecimal("120.50"), savedCabinet.getCapacity()); |
| | | assertEquals("OFFLINE", savedCabinet.getOnlineStatus()); |
| | | assertEquals("0", savedCabinet.getStatus()); |
| | | assertNull(savedCabinet.getCurrentTest()); |
| | | assertTrue(savedCabinet.getRelatedTests().isEmpty()); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * 验证检测柜主列表从通道事实派生旧页面展示字段,不读取数据库不存在的列。 |
| | | * 验证检测柜主列表保留操作校验所需派生状态,不读取数据库不存在的列。 |
| | | */ |
| | | @Test |
| | | void detectionCabinetListSqlShouldDeriveLegacyPresentationFields() throws IOException |
| | | void detectionCabinetListSqlShouldDeriveOperationStateWithoutCurrentTest() throws IOException |
| | | { |
| | | try (InputStream input = getClass().getResourceAsStream( |
| | | "/mapper/battery/TDetectionCabinetMapper.xml")) |
| | |
| | | assertFalse(selectSql.contains("online_status, test_status")); |
| | | assertFalse(selectSql.contains("current_test, status")); |
| | | assertTrue(selectSql.contains("as test_status")); |
| | | assertTrue(selectSql.contains("as current_test")); |
| | | assertFalse(selectSql.contains("current_test")); |
| | | String activeTestSql = sqlFragment(mapperXml, "activeCabinetTestExists"); |
| | | assertTrue(activeTestSql.contains("t_test_channel_binding")); |
| | | assertTrue(activeTestSql.contains("t_detection_channel")); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 验证设备选择列表读取 Redis 候选,并保持原前端字段和状态文本。 |
| | | * 验证设备选择列表读取候选的设备事实,不推断系统测试关系。 |
| | | */ |
| | | @Test |
| | | void selectDiscoveredCabinetListShouldMapPersistedCabinetFacts() |
| | |
| | | assertEquals("192.168.1.10", devices.get(0).getIp()); |
| | | assertEquals("AA:BB:CC:DD:EE:FF", devices.get(0).getMac()); |
| | | assertEquals("在线", devices.get(0).getOnlineStatus()); |
| | | assertEquals("测试中", devices.get(0).getTestStatus()); |
| | | assertEquals("待确认", devices.get(0).getCurrentTest()); |
| | | var fields = new com.fasterxml.jackson.databind.ObjectMapper().valueToTree(devices.get(0)); |
| | | assertFalse(fields.has("testStatus")); |
| | | assertFalse(fields.has("currentTest")); |
| | | assertEquals("一号模拟柜", devices.get(0).getName()); |
| | | assertEquals("开发模拟器", devices.get(0).getManufacturer()); |
| | | assertEquals("BTS Virtual Cabinet", devices.get(0).getModel()); |