package com.zy.core.utils.station; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.zy.asrs.entity.BasStationOpt; import com.zy.asrs.service.BasStationOptService; import com.zy.common.utils.RedisUtil; import com.zy.core.enums.RedisKeyType; import com.zy.core.model.command.StationCommand; import org.junit.jupiter.api.Test; import org.springframework.test.util.ReflectionTestUtils; import java.util.Collections; import java.util.Date; import java.util.concurrent.atomic.AtomicReference; 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; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class StationDispatchRuntimeStateSupportTest { @Test void idleTrack_isTimeoutUsesFirstSeenTime() { StationTaskIdleTrack track = new StationTaskIdleTrack(100, 145, System.currentTimeMillis() - 11_000L); assertTrue(track.isTimeout(10)); } @Test void touchIdleTrack_replacesTrackWhenStationChanges() { StationDispatchRuntimeStateSupport support = new StationDispatchRuntimeStateSupport(); RedisUtil redisUtil = mock(RedisUtil.class); ReflectionTestUtils.setField(support, "redisUtil", redisUtil); when(redisUtil.get(RedisKeyType.STATION_TASK_IDLE_TRACK_.key + 100)) .thenReturn(JSON.toJSONString(new StationTaskIdleTrack(100, 145, System.currentTimeMillis() - 3_000L))); StationTaskIdleTrack track = support.touchIdleTrack(100, 146); assertEquals(146, track.getStationId()); verify(redisUtil).set(eq(RedisKeyType.STATION_TASK_IDLE_TRACK_.key + 100), org.mockito.ArgumentMatchers.any(String.class), eq(3600L)); } @Test void hasRecentIssuedMoveCommand_returnsTrueForRecentMoveLog() { StationDispatchRuntimeStateSupport support = new StationDispatchRuntimeStateSupport(); BasStationOptService basStationOptService = mock(BasStationOptService.class); ReflectionTestUtils.setField(support, "basStationOptService", basStationOptService); when(basStationOptService.list(org.mockito.ArgumentMatchers.>any())) .thenReturn(Collections.singletonList(new BasStationOpt())); boolean result = support.hasRecentIssuedMoveCommand(100, 145, 10_000L); assertTrue(result); } @Test void clearIssuedMoveCommandsDuringIdleStay_marksSendZeroAndAppendsMemo() { StationDispatchRuntimeStateSupport support = new StationDispatchRuntimeStateSupport(); BasStationOptService basStationOptService = mock(BasStationOptService.class); ReflectionTestUtils.setField(support, "basStationOptService", basStationOptService); BasStationOpt opt = new BasStationOpt(); opt.setId(1L); opt.setSend(1); opt.setMemo("existing"); opt.setSendTime(new Date()); when(basStationOptService.list(org.mockito.ArgumentMatchers.>any())) .thenReturn(Collections.singletonList(opt)); int clearedCount = support.clearIssuedMoveCommandsDuringIdleStay( new StationTaskIdleTrack(100, 145, System.currentTimeMillis() - 10_000L), 100, 145 ); assertEquals(1, clearedCount); assertEquals(0, opt.getSend()); assertTrue(opt.getMemo().contains("existing")); assertTrue(opt.getMemo().contains("idleRecoverRerouteCleared(stationId=145)")); assertFalse(opt.getUpdateTime() == null); verify(basStationOptService).updateBatchById(Collections.singletonList(opt)); } @Test void tryAcquireOutOrderDispatchLock_returnsFalseWhenKeyAlreadyExists() { StationDispatchRuntimeStateSupport support = new StationDispatchRuntimeStateSupport(); RedisUtil redisUtil = mock(RedisUtil.class); ReflectionTestUtils.setField(support, "redisUtil", redisUtil); when(redisUtil.get(RedisKeyType.STATION_OUT_ORDER_DISPATCH_LIMIT_.key + "100_145")).thenReturn("lock"); boolean acquired = support.tryAcquireOutOrderDispatchLock(100, 145, 2); assertFalse(acquired); } @Test void signalSegmentReset_setsAndClearsResetKey() { StationDispatchRuntimeStateSupport support = new StationDispatchRuntimeStateSupport(); RedisUtil redisUtil = mock(RedisUtil.class); ReflectionTestUtils.setField(support, "redisUtil", redisUtil); support.signalSegmentReset(100, 0L); verify(redisUtil).set(RedisKeyType.DEVICE_STATION_MOVE_RESET.key + 100, "cancel", 3); verify(redisUtil).del(RedisKeyType.DEVICE_STATION_MOVE_RESET.key + 100); } @Test void watchCircleCommand_roundTripsThroughRedis() { StationDispatchRuntimeStateSupport support = new StationDispatchRuntimeStateSupport(); RedisUtil redisUtil = mock(RedisUtil.class); ReflectionTestUtils.setField(support, "redisUtil", redisUtil); AtomicReference storedValue = new AtomicReference<>(); when(redisUtil.get(RedisKeyType.WATCH_CIRCLE_STATION_.key + 100)) .thenAnswer(invocation -> storedValue.get()); when(redisUtil.set(eq(RedisKeyType.WATCH_CIRCLE_STATION_.key + 100), org.mockito.ArgumentMatchers.any(String.class), eq(60L * 60 * 24))) .thenAnswer(invocation -> { storedValue.set(invocation.getArgument(1)); return true; }); StationCommand command = new StationCommand(); command.setTaskNo(100); command.setTargetStaNo(145); support.saveWatchCircleCommand(100, command); StationCommand loaded = support.loadWatchCircleCommand(100); assertNotNull(loaded); assertEquals(145, loaded.getTargetStaNo()); support.clearWatchCircleCommand(100); verify(redisUtil).del(RedisKeyType.WATCH_CIRCLE_STATION_.key + 100); } }