#
Junjie
10 天以前 dc3f9cc91759823ce59486f19b138be4b296a0f1
src/test/java/com/zy/ai/service/AutoTuneCoordinatorServiceImplTest.java
@@ -6,12 +6,14 @@
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.AutoTuneJobStatus;
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.entity.ChatCompletionRequest;
import com.zy.ai.entity.ChatCompletionResponse;
import com.zy.ai.enums.AiPromptScene;
import com.zy.ai.mcp.service.SpringAiMcpToolManager;
import com.zy.ai.mcp.tool.AutoTuneMcpTools;
import com.zy.ai.service.impl.AutoTuneAgentServiceImpl;
@@ -19,6 +21,7 @@
import com.zy.asrs.service.WrkMastService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.system.entity.OperateLog;
import com.zy.system.service.ConfigService;
import com.zy.system.service.OperateLogService;
import org.junit.jupiter.api.BeforeEach;
@@ -346,6 +349,29 @@
    }
    @Test
    void coordinatorRunsAgentAndReleasesLockWhenGuardWriteFails() {
        AutoTuneAgentService.AutoTuneAgentResult agentResult = successfulAgentResult();
        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(true);
        doThrow(new RuntimeException("guard failed"))
                .when(redisUtil)
                .set(eq(RedisKeyType.AI_AUTO_TUNE_LAST_TRIGGER_GUARD.key), any(), eq(600L));
        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(redisUtil).compareAndDelete(anyString(), anyString());
    }
    @Test
    void coordinatorSetsGuardWhenAgentReturnsFailure() {
        AutoTuneAgentService.AutoTuneAgentResult agentResult = failedAgentResult();
        when(configService.getConfigValue("aiAutoTuneEnabled", "N")).thenReturn("Y");
@@ -399,6 +425,60 @@
    }
    @Test
    void manualTriggerRunsAgentWithRunningLockAndDoesNotWriteSchedulerGuard() {
        AutoTuneAgentService.AutoTuneAgentResult agentResult = successfulAgentResult();
        agentResult.setTriggerType(AutoTuneTriggerType.MANUAL.getCode());
        when(configService.getConfigValue("aiAutoTuneIntervalMinutes", "10")).thenReturn("10");
        when(wrkMastService.count(any(Wrapper.class))).thenReturn(1L);
        when(redisUtil.trySetStringIfAbsent(anyString(), anyString(), anyLong())).thenReturn(true);
        when(autoTuneAgentService.runAutoTune(AutoTuneTriggerType.MANUAL.getCode())).thenReturn(agentResult);
        AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runManualAutoTune();
        assertFalse(result.getSkipped());
        assertTrue(result.getTriggered());
        assertSame(agentResult, result.getAgentResult());
        verify(autoTuneAgentService).runAutoTune(AutoTuneTriggerType.MANUAL.getCode());
        verify(redisUtil, never()).set(eq(RedisKeyType.AI_AUTO_TUNE_LAST_TRIGGER_GUARD.key), any(), anyLong());
        verify(redisUtil).compareAndDelete(anyString(), anyString());
        ArgumentCaptor<OperateLog> operateLogCaptor = ArgumentCaptor.forClass(OperateLog.class);
        verify(operateLogService).save(operateLogCaptor.capture());
        assertEquals("ai_auto_tune_manual_trigger", operateLogCaptor.getValue().getAction());
        ArgumentCaptor<AiAutoTuneJob> jobCaptor = ArgumentCaptor.forClass(AiAutoTuneJob.class);
        verify(aiAutoTuneJobService).save(jobCaptor.capture());
        AiAutoTuneJob auditJob = jobCaptor.getValue();
        assertEquals(AutoTuneTriggerType.MANUAL.getCode(), auditJob.getTriggerType());
        assertEquals(AutoTuneJobStatus.SUCCESS.getCode(), auditJob.getStatus());
        assertNotNull(auditJob.getStartTime());
        assertNotNull(auditJob.getFinishTime());
        assertEquals(1, auditJob.getHasActiveTasks());
        assertEquals(AiPromptScene.AUTO_TUNE_DISPATCH.getCode(), auditJob.getPromptSceneCode());
        assertEquals("no changes needed", auditJob.getSummary());
        assertEquals(10, auditJob.getIntervalBefore());
        assertEquals(10, auditJob.getIntervalAfter());
        assertEquals(0, auditJob.getSuccessCount());
        assertEquals(0, auditJob.getRejectCount());
        assertEquals(1, auditJob.getLlmCallCount());
        assertEquals(10, auditJob.getPromptTokens());
        assertEquals(5, auditJob.getCompletionTokens());
        assertEquals(15, auditJob.getTotalTokens());
    }
    @Test
    void manualTriggerSkipsWhenRunningLockIsNotAcquired() {
        when(redisUtil.trySetStringIfAbsent(anyString(), anyString(), anyLong())).thenReturn(false);
        AutoTuneCoordinatorService.AutoTuneCoordinatorResult result = coordinatorService().runManualAutoTune();
        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,