package com.zy.core.utils.station; import com.zy.asrs.domain.enums.NotifyMsgType; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.WrkAnalysisService; import com.zy.asrs.service.WrkMastService; import com.zy.asrs.utils.NotifyUtils; import com.zy.common.utils.RedisUtil; import com.zy.core.cache.SlaveConnection; import com.zy.core.dispatch.StationCommandDispatchResult; import com.zy.core.dispatch.StationCommandDispatcher; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.enums.WrkStsType; import com.zy.core.model.StationObjModel; import com.zy.core.model.command.StationCommand; import com.zy.core.model.protocol.StationProtocol; import com.zy.core.move.StationMoveCoordinator; import com.zy.core.thread.StationThread; import com.zy.core.utils.station.model.DispatchLimitConfig; import com.zy.core.utils.station.model.LoadGuardState; import com.zy.core.utils.station.model.LoopHitResult; import com.zy.core.utils.station.model.OutOrderDispatchDecision; import org.junit.jupiter.api.Test; import org.springframework.test.util.ReflectionTestUtils; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.same; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class StationOutboundDispatchProcessorTest { @Test void crnStationOutExecute_recordsDispatchSessionAndClearsStationCacheAfterIssuingMoveCommand() { StationOutboundDispatchProcessor processor = new StationOutboundDispatchProcessor(); WrkMastService wrkMastService = mock(WrkMastService.class); WrkAnalysisService wrkAnalysisService = mock(WrkAnalysisService.class); RedisUtil redisUtil = mock(RedisUtil.class); StationMoveCoordinator coordinator = mock(StationMoveCoordinator.class); StationCommandDispatcher dispatcher = mock(StationCommandDispatcher.class); StationDispatchLoadSupport loadSupport = mock(StationDispatchLoadSupport.class); StationOutboundDecisionSupport decisionSupport = mock(StationOutboundDecisionSupport.class); StationThread stationThread = mock(StationThread.class); ReflectionTestUtils.setField(processor, "wrkMastService", wrkMastService); ReflectionTestUtils.setField(processor, "wrkAnalysisService", wrkAnalysisService); ReflectionTestUtils.setField(processor, "redisUtil", redisUtil); ReflectionTestUtils.setField(processor, "stationMoveCoordinator", coordinator); ReflectionTestUtils.setField(processor, "stationCommandDispatcher", dispatcher); ReflectionTestUtils.setField(processor, "stationDispatchLoadSupport", loadSupport); ReflectionTestUtils.setField(processor, "stationOutboundDecisionSupport", decisionSupport); WrkMast wrkMast = buildWrkMast(10001, 145); wrkMast.setWrkSts(WrkStsType.OUTBOUND_RUN_COMPLETE.sts); wrkMast.setCrnNo(4); when(wrkMastService.list(any(com.baomidou.mybatisplus.core.conditions.Wrapper.class))) .thenReturn(Collections.singletonList(wrkMast)); when(wrkMastService.updateById(wrkMast)).thenReturn(true); StationObjModel stationObjModel = new StationObjModel(); stationObjModel.setDeviceNo(1); stationObjModel.setStationId(101); when(redisUtil.get(RedisKeyType.CRN_OUT_TASK_COMPLETE_STATION_INFO.key + 10001)) .thenReturn(com.alibaba.fastjson.JSON.toJSONString(stationObjModel)); when(redisUtil.get(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + 101)).thenReturn(null); StationProtocol stationProtocol = buildStationProtocol(101, 0, 101); stationProtocol.setAutoing(true); stationProtocol.setLoading(true); when(stationThread.getStatusMap()).thenReturn(Map.of(101, stationProtocol)); DispatchLimitConfig limitConfig = new DispatchLimitConfig(); LoadGuardState loadGuardState = new LoadGuardState(); LoopHitResult noHit = LoopHitResult.noHit(); OutOrderDispatchDecision decision = OutOrderDispatchDecision.direct(145); StationCommand command = buildCommand(10001, 101, 145); when(loadSupport.getDispatchLimitConfig(null, null)).thenReturn(limitConfig); when(loadSupport.countCurrentStationTask()).thenReturn(0); when(loadSupport.buildLoadGuardState(limitConfig)).thenReturn(loadGuardState); when(decisionSupport.getAllOutOrderList()).thenReturn(List.of(101, 121, 145)); when(decisionSupport.resolveOutboundPathLenFactor(wrkMast)).thenReturn(0.25d); when(decisionSupport.resolveOutboundDispatchDecision(101, wrkMast, List.of(101, 121, 145), 0.25d)).thenReturn(decision); when(loadSupport.getDispatchLimitConfig(101, 145)).thenReturn(limitConfig); when(loadSupport.findPathLoopHit(limitConfig, 101, 145, loadGuardState, wrkMast, 0.25d)).thenReturn(noHit); when(loadSupport.isDispatchBlocked(limitConfig, 0, loadGuardState, false)).thenReturn(false); when(decisionSupport.buildOutboundMoveCommand(stationThread, wrkMast, 101, 145, 0.25d)).thenReturn(command); when(dispatcher.dispatch(1, command, "station-operate-process", "crnStationOutExecute")) .thenReturn(StationCommandDispatchResult.accepted("accepted", 1, "station-operate-process", "crnStationOutExecute")); SlaveConnection.put(SlaveType.Devp, 1, stationThread); try { processor.crnStationOutExecute(); verify(wrkAnalysisService, times(1)).markOutboundStationStart(eq(wrkMast), any(Date.class)); verify(coordinator, times(1)).recordDispatch(eq(10001), eq(101), eq("crnStationOutExecute"), same(command), eq(false)); verify(redisUtil, times(1)).set(eq(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + 101), eq("lock"), eq(5L)); verify(redisUtil, times(1)).del(RedisKeyType.CRN_OUT_TASK_COMPLETE_STATION_INFO.key + 10001); verify(loadSupport, times(1)).saveLoopLoadReserve(10001, noHit); assertEquals(WrkStsType.STATION_RUN.sts, wrkMast.getWrkSts()); } finally { SlaveConnection.remove(SlaveType.Devp, 1); } } @Test void dualCrnStationOutExecute_recordsDispatchSessionAndClearsDualCacheAfterIssuingMoveCommand() { StationOutboundDispatchProcessor processor = new StationOutboundDispatchProcessor(); WrkMastService wrkMastService = mock(WrkMastService.class); RedisUtil redisUtil = mock(RedisUtil.class); StationMoveCoordinator coordinator = mock(StationMoveCoordinator.class); StationCommandDispatcher dispatcher = mock(StationCommandDispatcher.class); NotifyUtils notifyUtils = mock(NotifyUtils.class); StationOutboundDecisionSupport decisionSupport = mock(StationOutboundDecisionSupport.class); StationThread stationThread = mock(StationThread.class); ReflectionTestUtils.setField(processor, "wrkMastService", wrkMastService); ReflectionTestUtils.setField(processor, "redisUtil", redisUtil); ReflectionTestUtils.setField(processor, "stationMoveCoordinator", coordinator); ReflectionTestUtils.setField(processor, "stationCommandDispatcher", dispatcher); ReflectionTestUtils.setField(processor, "notifyUtils", notifyUtils); ReflectionTestUtils.setField(processor, "stationOutboundDecisionSupport", decisionSupport); WrkMast wrkMast = buildWrkMast(10002, 188); wrkMast.setWrkSts(WrkStsType.OUTBOUND_RUN_COMPLETE.sts); wrkMast.setDualCrnNo(2); when(wrkMastService.list(any(com.baomidou.mybatisplus.core.conditions.Wrapper.class))) .thenReturn(Collections.singletonList(wrkMast)); when(wrkMastService.updateById(wrkMast)).thenReturn(true); StationObjModel stationObjModel = new StationObjModel(); stationObjModel.setDeviceNo(1); stationObjModel.setStationId(121); when(redisUtil.get(RedisKeyType.DUAL_CRN_OUT_TASK_STATION_INFO.key + 10002)) .thenReturn(com.alibaba.fastjson.JSON.toJSONString(stationObjModel)); when(redisUtil.get(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + 121)).thenReturn(null); StationProtocol stationProtocol = buildStationProtocol(121, 0, 121); stationProtocol.setAutoing(true); stationProtocol.setLoading(true); when(stationThread.getStatusMap()).thenReturn(Map.of(121, stationProtocol)); StationCommand command = buildCommand(10002, 121, 188); when(decisionSupport.resolveOutboundPathLenFactor(wrkMast)).thenReturn(0.5d); when(decisionSupport.buildOutboundMoveCommand(stationThread, wrkMast, 121, 188, 0.5d)).thenReturn(command); when(dispatcher.dispatch(1, command, "station-operate-process", "dualCrnStationOutExecute")) .thenReturn(StationCommandDispatchResult.accepted("accepted", 1, "station-operate-process", "dualCrnStationOutExecute")); SlaveConnection.put(SlaveType.Devp, 1, stationThread); try { processor.dualCrnStationOutExecute(); verify(coordinator, times(1)).recordDispatch(eq(10002), eq(121), eq("dualCrnStationOutExecute"), same(command), eq(false)); verify(notifyUtils, times(1)).notify(String.valueOf(SlaveType.Devp), 1, "10002", wrkMast.getWmsWrkNo(), NotifyMsgType.STATION_OUT_TASK_RUN, null); verify(redisUtil, times(1)).set(eq(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + 121), eq("lock"), eq(5L)); verify(redisUtil, times(1)).del(RedisKeyType.DUAL_CRN_OUT_TASK_STATION_INFO.key + 10002); assertEquals(WrkStsType.STATION_RUN.sts, wrkMast.getWrkSts()); } finally { SlaveConnection.remove(SlaveType.Devp, 1); } } private static WrkMast buildWrkMast(int wrkNo, int targetStationId) { WrkMast wrkMast = new WrkMast(); wrkMast.setWrkNo(wrkNo); wrkMast.setStaNo(targetStationId); wrkMast.setWmsWrkNo("WMS-" + wrkNo); wrkMast.setIoTime(new Date()); return wrkMast; } private static StationProtocol buildStationProtocol(int stationId, int taskNo, int targetStationId) { StationProtocol stationProtocol = new StationProtocol(); stationProtocol.setStationId(stationId); stationProtocol.setTaskNo(taskNo); stationProtocol.setTargetStaNo(targetStationId); return stationProtocol; } private static StationCommand buildCommand(int wrkNo, int stationId, int targetStationId) { StationCommand command = new StationCommand(); command.setTaskNo(wrkNo); command.setStationId(stationId); command.setTargetStaNo(targetStationId); return command; } }