| | |
| | | import com.zy.ai.domain.autotune.AutoTuneApplyResult; |
| | | import com.zy.ai.domain.autotune.AutoTuneChangeCommand; |
| | | import com.zy.ai.domain.autotune.AutoTuneSnapshot; |
| | | import com.zy.ai.domain.autotune.AutoTuneTriggerType; |
| | | import com.zy.ai.entity.AiAutoTuneChange; |
| | | import com.zy.ai.entity.AiAutoTuneJob; |
| | | import com.zy.ai.entity.AiPromptTemplate; |
| | |
| | | import com.zy.ai.mcp.service.SpringAiMcpToolManager; |
| | | import com.zy.ai.mcp.tool.AutoTuneMcpTools; |
| | | import com.zy.ai.service.impl.AutoTuneAgentServiceImpl; |
| | | import com.zy.ai.service.impl.AutoTuneCoordinatorServiceImpl; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.enums.RedisKeyType; |
| | | import com.zy.system.service.ConfigService; |
| | | import com.zy.system.service.OperateLogService; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.junit.jupiter.api.extension.ExtendWith; |
| | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | import static org.mockito.ArgumentMatchers.any; |
| | | import static org.mockito.ArgumentMatchers.anyDouble; |
| | | import static org.mockito.ArgumentMatchers.anyInt; |
| | | import static org.mockito.ArgumentMatchers.anyLong; |
| | | import static org.mockito.ArgumentMatchers.anyString; |
| | | import static org.mockito.Mockito.never; |
| | | import static org.mockito.Mockito.times; |
| | | import static org.mockito.Mockito.verify; |
| | |
| | | private SpringAiMcpToolManager mcpToolManager; |
| | | @Mock |
| | | private AiPromptTemplateService aiPromptTemplateService; |
| | | @Mock |
| | | private ConfigService configService; |
| | | @Mock |
| | | private WrkMastService wrkMastService; |
| | | @Mock |
| | | private AutoTuneAgentService autoTuneAgentService; |
| | | @Mock |
| | | private RedisUtil redisUtil; |
| | | @Mock |
| | | private OperateLogService operateLogService; |
| | | |
| | | @BeforeEach |
| | | void setUp() { |
| | |
| | | } |
| | | |
| | | @Test |
| | | void coordinatorSkipsWhenDisabled() { |
| | | when(configService.getConfigValue("aiAutoTuneEnabled", "N")).thenReturn("N"); |
| | | |
| | | AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runAutoTuneIfEligible(); |
| | | |
| | | assertTrue(result.getSkipped()); |
| | | assertEquals("disabled", result.getReason()); |
| | | verify(wrkMastService, never()).count(any(Wrapper.class)); |
| | | verify(autoTuneAgentService, never()).runAutoTune(anyString()); |
| | | } |
| | | |
| | | @Test |
| | | void coordinatorSkipsWhenNoActiveTasks() { |
| | | when(configService.getConfigValue("aiAutoTuneEnabled", "N")).thenReturn("Y"); |
| | | when(configService.getConfigValue("aiAutoTuneIntervalMinutes", "10")).thenReturn("10"); |
| | | when(wrkMastService.count(any(Wrapper.class))).thenReturn(0L); |
| | | |
| | | AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runAutoTuneIfEligible(); |
| | | |
| | | assertTrue(result.getSkipped()); |
| | | assertEquals("no_active_tasks", result.getReason()); |
| | | verify(autoTuneAgentService, never()).runAutoTune(anyString()); |
| | | } |
| | | |
| | | @Test |
| | | void coordinatorSkipsWhenIntervalNotReached() { |
| | | AiAutoTuneJob recentJob = new AiAutoTuneJob(); |
| | | recentJob.setId(11L); |
| | | recentJob.setFinishTime(new Date()); |
| | | when(configService.getConfigValue("aiAutoTuneEnabled", "N")).thenReturn("true"); |
| | | when(configService.getConfigValue("aiAutoTuneIntervalMinutes", "10")).thenReturn("10"); |
| | | when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L); |
| | | when(redisUtil.get(RedisKeyType.AI_AUTO_TUNE_LAST_TRIGGER_GUARD.key)).thenReturn(null); |
| | | when(aiAutoTuneJobService.list(any(Wrapper.class))).thenReturn(Collections.singletonList(recentJob)); |
| | | |
| | | AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runAutoTuneIfEligible(); |
| | | |
| | | assertTrue(result.getSkipped()); |
| | | assertEquals("interval_not_reached", result.getReason()); |
| | | verify(autoTuneAgentService, never()).runAutoTune(anyString()); |
| | | } |
| | | |
| | | @Test |
| | | void coordinatorTriggersAgentWhenEligible() { |
| | | AutoTuneAgentService.AutoTuneAgentResult agentResult = successfulAgentResult(); |
| | | when(configService.getConfigValue("aiAutoTuneEnabled", "N")).thenReturn("1"); |
| | | when(configService.getConfigValue("aiAutoTuneIntervalMinutes", "10")).thenReturn("10"); |
| | | when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L); |
| | | when(redisUtil.get(RedisKeyType.AI_AUTO_TUNE_LAST_TRIGGER_GUARD.key)).thenReturn(null); |
| | | when(aiAutoTuneJobService.list(any(Wrapper.class))).thenReturn(Collections.emptyList(), Collections.emptyList()); |
| | | when(redisUtil.trySetStringIfAbsent(anyString(), anyString(), anyLong())).thenReturn(true); |
| | | when(autoTuneAgentService.runAutoTune(AutoTuneTriggerType.AUTO.getCode())).thenReturn(agentResult); |
| | | |
| | | AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runAutoTuneIfEligible(); |
| | | |
| | | assertFalse(result.getSkipped()); |
| | | assertTrue(result.getTriggered()); |
| | | assertSame(agentResult, result.getAgentResult()); |
| | | verify(autoTuneAgentService).runAutoTune(AutoTuneTriggerType.AUTO.getCode()); |
| | | verify(operateLogService).save(any()); |
| | | verify(redisUtil).set(anyString(), any(), anyLong()); |
| | | verify(redisUtil).compareAndDelete(anyString(), anyString()); |
| | | } |
| | | |
| | | @Test |
| | | void coordinatorSkipsWhenRunningLockIsNotAcquired() { |
| | | when(configService.getConfigValue("aiAutoTuneEnabled", "N")).thenReturn("Y"); |
| | | when(configService.getConfigValue("aiAutoTuneIntervalMinutes", "10")).thenReturn("10"); |
| | | when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L); |
| | | when(redisUtil.get(RedisKeyType.AI_AUTO_TUNE_LAST_TRIGGER_GUARD.key)).thenReturn(null); |
| | | when(aiAutoTuneJobService.list(any(Wrapper.class))).thenReturn(Collections.emptyList()); |
| | | when(redisUtil.trySetStringIfAbsent(anyString(), anyString(), anyLong())).thenReturn(false); |
| | | |
| | | AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runAutoTuneIfEligible(); |
| | | |
| | | assertTrue(result.getSkipped()); |
| | | assertEquals("running_lock_not_acquired", result.getReason()); |
| | | verify(autoTuneAgentService, never()).runAutoTune(anyString()); |
| | | verify(redisUtil, never()).compareAndDelete(anyString(), anyString()); |
| | | } |
| | | |
| | | @Test |
| | | void agentExecutesSnapshotDryRunAndRealApplyToolSequence() { |
| | | AutoTuneAgentServiceImpl service = new AutoTuneAgentServiceImpl( |
| | | llmChatService, |
| | |
| | | return new AutoTuneAgentServiceImpl(llmChatService, mcpToolManager, aiPromptTemplateService); |
| | | } |
| | | |
| | | private AutoTuneCoordinatorServiceImpl coordinatorService() { |
| | | return new AutoTuneCoordinatorServiceImpl( |
| | | configService, |
| | | wrkMastService, |
| | | aiAutoTuneJobService, |
| | | autoTuneAgentService, |
| | | redisUtil, |
| | | operateLogService); |
| | | } |
| | | |
| | | private AutoTuneAgentService.AutoTuneAgentResult successfulAgentResult() { |
| | | AutoTuneAgentService.AutoTuneAgentResult result = new AutoTuneAgentService.AutoTuneAgentResult(); |
| | | result.setSuccess(true); |
| | | result.setTriggerType(AutoTuneTriggerType.AUTO.getCode()); |
| | | result.setSummary("no changes needed"); |
| | | result.setToolCallCount(1); |
| | | result.setLlmCallCount(1); |
| | | result.setPromptTokens(10L); |
| | | result.setCompletionTokens(5L); |
| | | result.setTotalTokens(15L); |
| | | result.setMaxRoundsReached(false); |
| | | return result; |
| | | } |
| | | |
| | | private AutoTuneChangeCommand change(String targetType, String targetId, String targetKey, String newValue) { |
| | | AutoTuneChangeCommand command = new AutoTuneChangeCommand(); |
| | | command.setTargetType(targetType); |