| | |
| | | import com.zy.ai.entity.AiAutoTuneChange; |
| | | import com.zy.ai.entity.AiAutoTuneJob; |
| | | import com.zy.ai.service.impl.AutoTuneApplyServiceImpl; |
| | | import com.zy.ai.service.impl.AutoTuneControlModeServiceImpl; |
| | | import com.zy.asrs.entity.BasCrnp; |
| | | import com.zy.asrs.entity.BasDualCrnp; |
| | | import com.zy.asrs.entity.BasStation; |
| | |
| | | ReflectionTestUtils.setField(service, "aiAutoTuneJobService", aiAutoTuneJobService); |
| | | ReflectionTestUtils.setField(service, "aiAutoTuneChangeService", aiAutoTuneChangeService); |
| | | ReflectionTestUtils.setField(service, "configService", configService); |
| | | ReflectionTestUtils.setField(service, "autoTuneControlModeService", |
| | | new AutoTuneControlModeServiceImpl(configService)); |
| | | ReflectionTestUtils.setField(service, "basStationService", basStationService); |
| | | ReflectionTestUtils.setField(service, "basCrnpService", basCrnpService); |
| | | ReflectionTestUtils.setField(service, "basDualCrnpService", basDualCrnpService); |
| | |
| | | when(aiAutoTuneChangeService.list(any(Wrapper.class))).thenReturn(Collections.emptyList()); |
| | | when(wrkMastService.count(any(Wrapper.class))).thenReturn(0L); |
| | | when(configService.getConfigValue(eq("aiAutoTuneIntervalMinutes"), any())).thenReturn("10"); |
| | | when(configService.getConfigValue("aiAutoTuneAnalysisOnly", "Y")).thenReturn("N"); |
| | | when(configService.saveConfigValue(any(), any())).thenReturn(true); |
| | | when(basStationService.update(any(Wrapper.class))).thenReturn(true); |
| | | when(basCrnpService.update(any(Wrapper.class))).thenReturn(true); |
| | |
| | | } |
| | | |
| | | @Test |
| | | void rejectCrnOutBatchRunningLimitRangeAndStepCases() { |
| | | void crnOutBatchRunningLimitAllowsStepThreeAndRejectsRangeAndStepCases() { |
| | | when(configService.getOne(any(Wrapper.class))).thenReturn(config("crnOutBatchRunningLimit", "10")); |
| | | |
| | | service.apply(request(true, |
| | | command("sys_config", null, "crnOutBatchRunningLimit", "13"), |
| | | command("sys_config", null, "crnOutBatchRunningLimit", "14"), |
| | | command("sys_config", null, "crnOutBatchRunningLimit", "21") |
| | | )); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | | assertEquals("rejected", changes.get(0).getResultStatus()); |
| | | assertTrue(changes.get(0).getRejectReason().contains("步长不能超过 2")); |
| | | assertEquals("dry_run", changes.get(0).getResultStatus()); |
| | | assertEquals("13", changes.get(0).getRequestedValue()); |
| | | assertEquals("rejected", changes.get(1).getResultStatus()); |
| | | assertTrue(changes.get(1).getRejectReason().contains("1~20")); |
| | | assertTrue(changes.get(1).getRejectReason().contains("步长不能超过 3")); |
| | | assertEquals("rejected", changes.get(2).getResultStatus()); |
| | | assertTrue(changes.get(2).getRejectReason().contains("1~20")); |
| | | } |
| | | |
| | | @Test |
| | | void rejectMaxInTaskRangeAndStepCases() { |
| | | void maxInTaskAllowsStepThreeAndRejectsRangeAndStepCases() { |
| | | when(basCrnpService.getById(1)).thenReturn(crn(1, 1, 5)); |
| | | |
| | | service.apply(request(true, |
| | | command("crn", "1", "maxInTask", "7"), |
| | | command("crn", "1", "maxInTask", "8"), |
| | | command("crn", "1", "maxInTask", "9"), |
| | | command("crn", "1", "maxInTask", "11") |
| | | )); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | | assertEquals("rejected", changes.get(0).getResultStatus()); |
| | | assertTrue(changes.get(0).getRejectReason().contains("步长不能超过 1")); |
| | | assertEquals("dry_run", changes.get(0).getResultStatus()); |
| | | assertEquals("8", changes.get(0).getRequestedValue()); |
| | | assertEquals("rejected", changes.get(1).getResultStatus()); |
| | | assertTrue(changes.get(1).getRejectReason().contains("0~10")); |
| | | assertTrue(changes.get(1).getRejectReason().contains("步长不能超过 3")); |
| | | assertEquals("rejected", changes.get(2).getResultStatus()); |
| | | assertTrue(changes.get(2).getRejectReason().contains("0~10")); |
| | | } |
| | | |
| | | @Test |
| | |
| | | } |
| | | |
| | | @Test |
| | | void rejectStationOutTaskLimitAboveDirectionalBufferCapacity() { |
| | | when(basStationService.getById(101)).thenReturn(station(101, 1, 2)); |
| | | void stationOutTaskLimitAllowsAboveBufferCapacityButRejectsOverStep() { |
| | | when(basStationService.getById(101)).thenReturn(station(101, 5, 3)); |
| | | |
| | | service.apply(request(true, command("station", "101", "outTaskLimit", "3"))); |
| | | service.apply(request(true, |
| | | command("station", "101", "outTaskLimit", "6"), |
| | | command("station", "101", "outTaskLimit", "9") |
| | | )); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | | assertEquals("rejected", changes.get(0).getResultStatus()); |
| | | assertTrue(changes.get(0).getRejectReason().contains("0~2")); |
| | | assertEquals("dry_run", changes.get(0).getResultStatus()); |
| | | assertEquals("5", changes.get(0).getOldValue()); |
| | | assertEquals("6", changes.get(0).getRequestedValue()); |
| | | assertEquals("rejected", changes.get(1).getResultStatus()); |
| | | assertTrue(changes.get(1).getRejectReason().contains("步长不能超过 3")); |
| | | } |
| | | |
| | | @Test |
| | |
| | | } |
| | | |
| | | @Test |
| | | void rejectStationOutTaskLimitWithoutOutBufferCapacity() { |
| | | void allowStationOutTaskLimitWithoutOutBufferCapacity() { |
| | | when(basStationService.getById(101)).thenReturn(station(101, 0)); |
| | | |
| | | service.apply(request(true, command("station", "101", "outTaskLimit", "1"))); |
| | | AutoTuneApplyResult result = service.apply(request(true, command("station", "101", "outTaskLimit", "1"))); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | | assertEquals("rejected", changes.get(0).getResultStatus()); |
| | | assertTrue(changes.get(0).getRejectReason().contains("缺少 outBufferCapacity")); |
| | | assertTrue(result.getSuccess()); |
| | | assertEquals("dry_run", changes.get(0).getResultStatus()); |
| | | assertEquals("1", changes.get(0).getRequestedValue()); |
| | | } |
| | | |
| | | @Test |
| | |
| | | |
| | | AutoTuneApplyResult result = service.apply(request(false, |
| | | command("sys_config", null, "conveyorStationTaskLimit", "15"), |
| | | command("station", "101", "outTaskLimit", "3") |
| | | command("station", "101", "outTaskLimit", "5") |
| | | )); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | |
| | | assertTrue(changes.stream().allMatch(change -> "rejected".equals(change.getResultStatus()))); |
| | | verify(configService, never()).saveConfigValue(any(), any()); |
| | | verify(basStationService, never()).update(any(Wrapper.class)); |
| | | } |
| | | |
| | | @Test |
| | | void analysisOnlyRealApplyWritesRejectedAuditAndDoesNotAcquireApplyLock() { |
| | | when(configService.getConfigValue("aiAutoTuneAnalysisOnly", "Y")).thenReturn("Y"); |
| | | |
| | | AutoTuneApplyResult result = service.apply(request(false, |
| | | command("sys_config", null, "conveyorStationTaskLimit", "15"))); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | | AiAutoTuneJob job = updatedJob(); |
| | | assertFalse(result.getSuccess()); |
| | | assertTrue(result.getAnalysisOnly()); |
| | | assertTrue(result.getNoApply()); |
| | | assertEquals("rejected", job.getStatus()); |
| | | assertEquals("rejected", changes.get(0).getResultStatus()); |
| | | assertTrue(changes.get(0).getRejectReason().contains("仅分析模式禁止实际应用/回滚")); |
| | | verify(redisUtil, never()).trySetStringIfAbsent(anyString(), anyString(), anyLong()); |
| | | verify(configService, never()).saveConfigValue(any(), any()); |
| | | } |
| | | |
| | | @Test |
| | | void realApplyResultUsesEntryControlModeSnapshotWhenConfigFlips() { |
| | | when(configService.getConfigValue("aiAutoTuneAnalysisOnly", "Y")).thenReturn("N", "Y"); |
| | | when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10")); |
| | | |
| | | AutoTuneApplyResult result = service.apply(request(false, |
| | | command("sys_config", null, "conveyorStationTaskLimit", "15"))); |
| | | |
| | | assertTrue(result.getSuccess()); |
| | | assertFalse(result.getAnalysisOnly()); |
| | | verify(configService, times(1)).getConfigValue("aiAutoTuneAnalysisOnly", "Y"); |
| | | } |
| | | |
| | | @Test |
| | |
| | | } |
| | | |
| | | @Test |
| | | void analysisOnlyRollbackWritesRejectedAuditAndDoesNotAcquireApplyLock() { |
| | | when(configService.getConfigValue("aiAutoTuneAnalysisOnly", "Y")).thenReturn("Y"); |
| | | |
| | | AutoTuneApplyResult result = service.rollbackLastSuccessfulJob("manual rollback"); |
| | | |
| | | List<AiAutoTuneChange> changes = savedChanges(); |
| | | AiAutoTuneJob job = updatedJob(); |
| | | assertFalse(result.getSuccess()); |
| | | assertTrue(result.getAnalysisOnly()); |
| | | assertTrue(result.getNoApply()); |
| | | assertEquals("rejected", job.getStatus()); |
| | | assertEquals("rejected", changes.get(0).getResultStatus()); |
| | | assertEquals("rollback", changes.get(0).getTargetKey()); |
| | | verify(redisUtil, never()).trySetStringIfAbsent(anyString(), anyString(), anyLong()); |
| | | } |
| | | |
| | | @Test |
| | | void rollbackResultUsesEntryControlModeSnapshotWhenConfigFlips() { |
| | | when(configService.getConfigValue("aiAutoTuneAnalysisOnly", "Y")).thenReturn("N", "Y"); |
| | | AiAutoTuneJob latestRealJob = job(10L, "manual", "success"); |
| | | AiAutoTuneChange configChange = successChange(10L, "sys_config", "", "conveyorStationTaskLimit", "10", "15"); |
| | | when(aiAutoTuneChangeService.list(any(Wrapper.class))) |
| | | .thenReturn(List.of(configChange)) |
| | | .thenReturn(List.of(configChange)); |
| | | when(aiAutoTuneJobService.getById(10L)).thenReturn(latestRealJob); |
| | | when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "15")); |
| | | |
| | | AutoTuneApplyResult result = service.rollbackLastSuccessfulJob("manual rollback"); |
| | | |
| | | assertTrue(result.getSuccess()); |
| | | assertFalse(result.getAnalysisOnly()); |
| | | verify(configService, times(1)).getConfigValue("aiAutoTuneAnalysisOnly", "Y"); |
| | | } |
| | | |
| | | @Test |
| | | void applyJobRecordsActiveTasksWhenCountIsPositive() { |
| | | when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10")); |
| | | when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L); |