package com.superbiz.agent.service; import com.fasterxml.jackson.databind.ObjectMapper; import com.superbiz.agent.config.RagSidecarProperties; import com.superbiz.agent.dto.ComparableRetrievalResult; import com.superbiz.agent.dto.RetrievalComparisonCase; import com.superbiz.agent.dto.RetrievalComparisonReport; import com.superbiz.agent.dto.SidecarRetrievalResponse; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class RagRetrievalSidecarComparisonServiceTest { @TempDir Path tempDir; @Test void compareWritesSeparateSidecarReports() throws Exception { VectorSearchService vectorSearchService = mock(VectorSearchService.class); SpringAiVectorStoreSidecarService sidecarService = mock(SpringAiVectorStoreSidecarService.class); RagSidecarProperties properties = new RagSidecarProperties(); RetrievalResultNormalizer normalizer = new RetrievalResultNormalizer(new ObjectMapper()); RagRetrievalSidecarComparisonService comparisonService = new RagRetrievalSidecarComparisonService( vectorSearchService, sidecarService, normalizer, properties, new ObjectMapper() ); VectorSearchService.SearchResult current = new VectorSearchService.SearchResult(); current.setId("current-1"); current.setMetadata("{\"_source\":\"current.md\",\"breadcrumb\":\"A\",\"category\":\"api\"}"); current.setContent("current content"); current.setScore(0.1f); when(vectorSearchService.searchSimilarDocuments("timeout", 3, "api")) .thenReturn(List.of(current)); when(sidecarService.search("timeout", 3, "api")) .thenReturn(SidecarRetrievalResponse.builder() .enabled(true) .available(true) .status("available") .results(List.of(ComparableRetrievalResult.builder() .path("sidecar") .rank(1) .source("sidecar.md") .breadcrumb("B") .scoreLabel("similarity") .scoreValue(0.9) .build())) .build()); RetrievalComparisonReport report = comparisonService.compare(List.of( RetrievalComparisonCase.builder() .caseId("case-1") .scenario("aiops") .query("timeout") .category("api") .build() ), 3); assertEquals(1, report.getCaseCount()); assertEquals("available", report.getSidecarStatus()); assertTrue(report.getResults().get(0).getDifferences().contains("top_source_differs")); Path json = tempDir.resolve("sidecar.json"); Path markdown = tempDir.resolve("sidecar.md"); comparisonService.writeReports(report, json, markdown); assertTrue(Files.readString(json).contains("\"sidecarStatus\"")); assertTrue(Files.readString(markdown).contains("RAG Sidecar Retrieval Comparison")); } @Test void compareGoldenCasesLoadsExistingCaseShape() throws Exception { VectorSearchService vectorSearchService = mock(VectorSearchService.class); SpringAiVectorStoreSidecarService sidecarService = mock(SpringAiVectorStoreSidecarService.class); RagRetrievalSidecarComparisonService comparisonService = new RagRetrievalSidecarComparisonService( vectorSearchService, sidecarService, new RetrievalResultNormalizer(new ObjectMapper()), new RagSidecarProperties(), new ObjectMapper() ); when(vectorSearchService.searchSimilarDocuments("query", 2, null)).thenReturn(List.of()); when(sidecarService.search("query", 2, null)) .thenReturn(SidecarRetrievalResponse.builder() .enabled(false) .available(false) .status("disabled") .results(List.of()) .build()); Path cases = tempDir.resolve("cases.json"); Files.writeString(cases, """ { "topK": 2, "cases": [ {"caseId": "case-1", "scenario": "chat", "query": "query"} ] } """); RetrievalComparisonReport report = comparisonService.compareGoldenCases(cases); assertEquals(1, report.getCaseCount()); assertEquals(2, report.getTopK()); assertEquals("disabled", report.getSidecarStatus()); } }