package com.superbiz.agent.config; import com.superbiz.agent.harness.core.DiagnosisHarnessCore; import com.superbiz.agent.harness.application.persistence.ChatRunStore; import com.superbiz.agent.harness.tool.contract.MysqlToolRequest; import com.superbiz.agent.harness.tool.mysql.MysqlSqlValidator; import com.superbiz.agent.harness.tool.mysql.MysqlSecurityException; import com.superbiz.agent.tool.LookupKnowledgeTool; import com.superbiz.agent.tool.RetrievedDocTracker; import com.superbiz.agent.service.KnowledgeContextPacker; import com.superbiz.agent.service.KnowledgeDocumentRetriever; import com.superbiz.agent.service.KnowledgeEvidencePostProcessor; import com.superbiz.agent.service.KnowledgeQueryTransformer; import com.superbiz.agent.service.LookupResultAssembler; import com.superbiz.agent.service.ToolInvocationRecorder; import com.superbiz.agent.repository.AgentStepRepository; import org.springframework.ai.chat.model.ChatModel; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.data.redis.core.RedisTemplate; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import java.util.Map; import java.util.concurrent.ThreadPoolExecutor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; class HarnessChatConfigurationTest { @Test void defaultsArePositiveAndExecutorsAreBounded() { ChatHarnessProperties properties = new ChatHarnessProperties(); properties.validate(); HarnessChatConfiguration configuration = new HarnessChatConfiguration(); ThreadPoolExecutor worker = configuration.chatWorkerExecutor(properties); ThreadPoolExecutor model = configuration.harnessModelExecutor(properties); try { assertTrue(worker.getQueue().remainingCapacity() > 0); assertTrue(model.getQueue().remainingCapacity() > 0); assertEquals(properties.getWorkerMaxPoolSize(), worker.getMaximumPoolSize()); assertEquals(properties.getModelMaxPoolSize(), model.getMaximumPoolSize()); } finally { worker.shutdownNow(); model.shutdownNow(); } } @Test void emptyMysqlConfigurationFailsClosedWithoutApplicationDatasource() { MysqlToolProperties properties = new MysqlToolProperties(); HarnessChatConfiguration configuration = new HarnessChatConfiguration(); assertTrue(configuration.harnessMysqlDataSources(properties).isEmpty()); Map definitions = configuration.harnessMysqlDefinitions(properties); MysqlSqlValidator validator = configuration.mysqlSqlValidator(definitions); assertThrows(MysqlSecurityException.class, () -> validator.validate( new MysqlToolRequest("application", "SELECT id FROM users", java.util.List.of()))); } @Test void harnessConfigurationBuildsOneApplicationGraphWithControlledDependencies() { new ApplicationContextRunner() .withUserConfiguration(HarnessChatConfiguration.class) .withBean(ObjectMapper.class, ObjectMapper::new) .withBean(ChatModel.class, () -> mock(ChatModel.class)) .withBean(RedisTemplate.class, () -> mock(RedisTemplate.class)) .withBean(LookupKnowledgeTool.class, () -> mock(LookupKnowledgeTool.class)) .withBean(KnowledgeQueryTransformer.class, () -> mock(KnowledgeQueryTransformer.class)) .withBean(KnowledgeDocumentRetriever.class, () -> mock(KnowledgeDocumentRetriever.class)) .withBean(KnowledgeEvidencePostProcessor.class, () -> mock(KnowledgeEvidencePostProcessor.class)) .withBean(KnowledgeContextPacker.class, () -> mock(KnowledgeContextPacker.class)) .withBean(LookupResultAssembler.class, () -> mock(LookupResultAssembler.class)) .withBean(ToolInvocationRecorder.class, () -> mock(ToolInvocationRecorder.class)) .withBean(RetrievedDocTracker.class, () -> mock(RetrievedDocTracker.class)) .withBean(AgentStepRepository.class, () -> mock(AgentStepRepository.class)) .withBean(ChatRunStore.class, () -> mock(ChatRunStore.class)) .withBean(MysqlToolProperties.class, MysqlToolProperties::new) .run(context -> { assertTrue(context.isRunning()); assertEquals(1, context.getBeansOfType( com.superbiz.agent.harness.application.ChatApplicationUseCase.class).size()); assertTrue(context.containsBean("harnessModelExecutor")); assertTrue(context.containsBean("chatWorkerExecutor")); }); } }