package com.zy.ai.service.impl; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.zy.ai.domain.autotune.AutoTuneRuleSnapshotItem; import com.zy.asrs.entity.BasDevp; import com.zy.asrs.entity.BasStation; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.BasDevpService; import com.zy.asrs.service.BasStationService; import com.zy.asrs.service.WrkMastService; import com.zy.core.model.StationObjModel; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.springframework.test.util.ReflectionTestUtils; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class AutoTuneSnapshotServiceImplTest { private AutoTuneSnapshotServiceImpl service; @BeforeEach void setUp() { service = new AutoTuneSnapshotServiceImpl(); } @Test void buildStationOutTaskLimitMapPreservesNullZeroAndNegativeLimits() { Map result = service.buildStationOutTaskLimitMap(Arrays.asList( station(101, null), station(102, 0), station(103, -1), station(104, 5) )); assertNull(result.get("101")); assertEquals(0, result.get("102")); assertEquals(-1, result.get("103")); assertEquals(5, result.get("104")); } @Test void buildStationOutBufferCapacityMapPreservesConfiguredCapacity() { Map result = service.buildStationOutBufferCapacityMap(Arrays.asList( station(101, 1, null), station(102, 1, 0), station(103, 1, 3) )); assertNull(result.get("101")); assertEquals(0, result.get("102")); assertEquals(3, result.get("103")); } @Test void buildRuleSnapshotExposesStepRangeCooldownAndDynamicMaxSource() { List result = service.buildRuleSnapshot(); AutoTuneRuleSnapshotItem stationOutTaskRule = findRule(result, "station", "outTaskLimit"); assertEquals(0, stationOutTaskRule.getMinValue()); assertNull(stationOutTaskRule.getMaxValue()); assertEquals(3, stationOutTaskRule.getMaxStep()); assertEquals(10, stationOutTaskRule.getCooldownMinutes()); assertEquals(Boolean.TRUE, stationOutTaskRule.getDynamicMaxValue()); assertEquals("currentParameterSnapshot.stationOutBufferCapacities[targetId]", stationOutTaskRule.getDynamicMaxSource()); assertEquals("单次调整幅度不能超过 maxStep;增大时不得超过对应站点 outBufferCapacity。", stationOutTaskRule.getNote()); AutoTuneRuleSnapshotItem crnMaxOutRule = findRule(result, "crn", "maxOutTask"); assertEquals(3, crnMaxOutRule.getMaxStep()); assertNull(crnMaxOutRule.getDynamicMaxSource()); assertEquals("单次调整幅度不能超过 maxStep。", crnMaxOutRule.getNote()); AutoTuneRuleSnapshotItem crnMaxInRule = findRule(result, "crn", "maxInTask"); assertEquals(3, crnMaxInRule.getMaxStep()); assertRuleMaxStep(result, "sys_config", "crnOutBatchRunningLimit", 3); assertRuleMaxStep(result, "dual_crn", "maxOutTask", 3); assertRuleMaxStep(result, "dual_crn", "maxInTask", 3); } @Test void loadActiveTasksIncludesNullWrkStatusInGroupedCondition() { WrkMastService wrkMastService = mock(WrkMastService.class); when(wrkMastService.list(any(Wrapper.class))).thenReturn(Collections.emptyList()); ReflectionTestUtils.setField(service, "wrkMastService", wrkMastService); ReflectionTestUtils.invokeMethod(service, "loadActiveTasks"); ArgumentCaptor> wrapperCaptor = ArgumentCaptor.forClass(Wrapper.class); verify(wrkMastService).list(wrapperCaptor.capture()); String sqlSegment = wrapperCaptor.getValue().getSqlSegment(); String normalizedSqlSegment = sqlSegment.replaceAll("\\s+", " "); assertTrue(normalizedSqlSegment.contains("(wrk_sts NOT IN")); assertTrue(normalizedSqlSegment.contains("OR wrk_sts IS NULL")); } @Test void loadOutStationListOnlyQueriesBasDevpOutStations() { BasStationService basStationService = mock(BasStationService.class); BasDevpService basDevpService = mock(BasDevpService.class); ReflectionTestUtils.setField(service, "basStationService", basStationService); ReflectionTestUtils.setField(service, "basDevpService", basDevpService); when(basDevpService.list(any(Wrapper.class))).thenReturn(Arrays.asList( basDevp(1, 101, 102), basDevp(2, 102) )); when(basStationService.list(any(Wrapper.class))).thenReturn(Arrays.asList( station(101, 2), station(102, 3) )); java.util.List result = ReflectionTestUtils.invokeMethod(service, "loadOutStationList"); assertEquals(2, result.size()); assertEquals(101, result.get(0).getStationId()); assertEquals(102, result.get(1).getStationId()); ArgumentCaptor> basDevpWrapperCaptor = ArgumentCaptor.forClass(Wrapper.class); verify(basDevpService).list(basDevpWrapperCaptor.capture()); assertTrue(basDevpWrapperCaptor.getValue().getSqlSegment().contains("status =")); ArgumentCaptor> stationWrapperCaptor = ArgumentCaptor.forClass(Wrapper.class); verify(basStationService).list(stationWrapperCaptor.capture()); assertTrue(stationWrapperCaptor.getValue().getSqlSegment().contains("station_id IN")); } @Test void loadOutStationListDoesNotQueryStationsWhenBasDevpOutStationsAreEmpty() { BasStationService basStationService = mock(BasStationService.class); BasDevpService basDevpService = mock(BasDevpService.class); ReflectionTestUtils.setField(service, "basStationService", basStationService); ReflectionTestUtils.setField(service, "basDevpService", basDevpService); when(basDevpService.list(any(Wrapper.class))).thenReturn(Collections.singletonList(basDevp(1))); java.util.List result = ReflectionTestUtils.invokeMethod(service, "loadOutStationList"); assertTrue(result.isEmpty()); verify(basStationService, never()).list(any(Wrapper.class)); } private BasStation station(Integer stationId, Integer outTaskLimit) { return station(stationId, outTaskLimit, null); } private BasStation station(Integer stationId, Integer outTaskLimit, Integer outBufferCapacity) { BasStation station = new BasStation(); station.setStationId(stationId); station.setOutTaskLimit(outTaskLimit); station.setOutBufferCapacity(outBufferCapacity); return station; } private BasDevp basDevp(Integer devpNo, Integer... stationIds) { BasDevp basDevp = new BasDevp(); basDevp.setDevpNo(devpNo); basDevp.setStatus(1); if (stationIds == null || stationIds.length == 0) { return basDevp; } basDevp.setOutStationList(JSON.toJSONString(Arrays.stream(stationIds) .map(this::stationObjModel) .toList())); return basDevp; } private StationObjModel stationObjModel(Integer stationId) { StationObjModel stationObjModel = new StationObjModel(); stationObjModel.setStationId(stationId); return stationObjModel; } private AutoTuneRuleSnapshotItem findRule(List rules, String targetType, String targetKey) { for (AutoTuneRuleSnapshotItem rule : rules) { if (targetType.equals(rule.getTargetType()) && targetKey.equals(rule.getTargetKey())) { return rule; } } throw new AssertionError("rule not found: " + targetType + "/" + targetKey); } private void assertRuleMaxStep(List rules, String targetType, String targetKey, int expectedMaxStep) { AutoTuneRuleSnapshotItem rule = findRule(rules, targetType, targetKey); assertEquals(expectedMaxStep, rule.getMaxStep()); } }