package com.bruce.rag; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.bruce.common.typehandler.PgJsonbStringTypeHandler; import com.bruce.common.domain.model.RequestResult; import com.bruce.rag.constant.RagSystemConstants; import com.bruce.rag.controller.RagDocumentController; import com.bruce.rag.controller.RagStoreController; import com.bruce.rag.dto.request.RagDocumentQueryRequest; import com.bruce.rag.dto.request.RagDocumentParseRequest; import com.bruce.rag.dto.request.RagStoreQueryRequest; import com.bruce.rag.dto.request.RagStoreSaveRequest; import com.bruce.rag.dto.response.RagDocumentParseResponse; import com.bruce.rag.dto.response.RagStoreDocumentOverviewResponse; import com.bruce.rag.dto.response.RagStoreOverviewResponse; import com.bruce.rag.dto.response.RagDocumentResponse; import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.entity.RagChunk; import com.bruce.rag.entity.RagChunkEmbedding; import com.bruce.rag.entity.RagDocument; import com.bruce.rag.entity.RagDocumentParseResult; import com.bruce.rag.entity.RagStore; import com.bruce.rag.mapper.RagChunkEmbeddingMapper; import com.bruce.rag.mapper.RagChunkMapper; import com.bruce.rag.mapper.RagDocumentMapper; import com.bruce.rag.mapper.RagDocumentParseResultMapper; import com.bruce.rag.mapper.RagStoreMapper; import com.bruce.rag.service.IRagChunkEmbeddingService; import com.bruce.rag.service.IRagChunkService; import com.bruce.rag.service.IRagDocumentParseService; import com.bruce.rag.service.IRagDocumentParseResultService; import com.bruce.rag.service.IRagDocumentService; import com.bruce.rag.service.IRagStoreService; import com.bruce.rag.service.impl.RagChunkEmbeddingServiceImpl; import com.bruce.rag.service.impl.RagChunkServiceImpl; import com.bruce.rag.service.impl.RagDocumentParseResultServiceImpl; import com.bruce.rag.service.impl.RagDocumentServiceImpl; import com.bruce.rag.service.impl.RagStoreServiceImpl; import org.junit.jupiter.api.Test; import org.springframework.web.bind.annotation.PostMapping; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; class RagComponentStructureTests { @Test void ragComponentsShouldReuseMybatisPlusBaseTypes() { assertTrue(BaseMapper.class.isAssignableFrom(RagStoreMapper.class)); assertTrue(BaseMapper.class.isAssignableFrom(RagDocumentMapper.class)); assertTrue(BaseMapper.class.isAssignableFrom(RagDocumentParseResultMapper.class)); assertTrue(BaseMapper.class.isAssignableFrom(RagChunkMapper.class)); assertTrue(BaseMapper.class.isAssignableFrom(RagChunkEmbeddingMapper.class)); assertTrue(IService.class.isAssignableFrom(IRagStoreService.class)); assertTrue(IService.class.isAssignableFrom(IRagDocumentService.class)); assertTrue(IService.class.isAssignableFrom(IRagDocumentParseResultService.class)); assertTrue(IService.class.isAssignableFrom(IRagChunkService.class)); assertTrue(IService.class.isAssignableFrom(IRagChunkEmbeddingService.class)); assertTrue(ServiceImpl.class.isAssignableFrom(RagStoreServiceImpl.class)); assertTrue(ServiceImpl.class.isAssignableFrom(RagDocumentServiceImpl.class)); assertTrue(ServiceImpl.class.isAssignableFrom(RagDocumentParseResultServiceImpl.class)); assertTrue(ServiceImpl.class.isAssignableFrom(RagChunkServiceImpl.class)); assertTrue(ServiceImpl.class.isAssignableFrom(RagChunkEmbeddingServiceImpl.class)); } @Test void ragControllersShouldExposeRequestResultAndQueryDtoMethods() throws NoSuchMethodException { Method storeListMethod = RagStoreController.class.getMethod("list"); Method storeQueryMethod = RagStoreController.class.getMethod("query", RagStoreQueryRequest.class); Method storeDetailMethod = RagStoreController.class.getMethod("getById", Long.class); Method storeOverviewMethod = RagStoreController.class.getMethod("overview"); Method storeDocumentOverviewMethod = RagStoreController.class.getMethod("documentOverview", Long.class); Method storeSaveMethod = RagStoreController.class.getMethod("saveOrUpdate", RagStoreSaveRequest.class); Method storeDeleteMethod = RagStoreController.class.getMethod("deleteById", Long.class); Method storeResponseListMethod = IRagStoreService.class.getMethod("listResponses"); Method storeServiceQueryMethod = IRagStoreService.class.getMethod("query", RagStoreQueryRequest.class); Method storeServiceDetailMethod = IRagStoreService.class.getMethod("getResponseById", Long.class); Method storeServiceOverviewMethod = IRagStoreService.class.getMethod("getOverview"); Method storeServiceDocumentOverviewMethod = IRagStoreService.class.getMethod("getDocumentOverview", Long.class); Method storeServiceSaveMethod = IRagStoreService.class.getMethod("saveOrUpdate", RagStoreSaveRequest.class); Method documentListMethod = RagDocumentController.class.getMethod("list"); Method documentQueryMethod = RagDocumentController.class.getMethod("query", RagDocumentQueryRequest.class); Method documentParseMethod = RagDocumentController.class.getMethod("parse", RagDocumentParseRequest.class); Method documentResponseListMethod = IRagDocumentService.class.getMethod("listResponses"); Method documentServiceQueryMethod = IRagDocumentService.class.getMethod("query", RagDocumentQueryRequest.class); Method documentParseServiceMethod = IRagDocumentParseService.class.getMethod("parse", RagDocumentParseRequest.class); assertEquals(RequestResult.class, storeListMethod.getReturnType()); assertEquals(RequestResult.class, storeQueryMethod.getReturnType()); assertEquals(RequestResult.class, storeDetailMethod.getReturnType()); assertEquals(RequestResult.class, storeOverviewMethod.getReturnType()); assertEquals(RequestResult.class, storeDocumentOverviewMethod.getReturnType()); assertEquals(RequestResult.class, storeSaveMethod.getReturnType()); assertEquals(RequestResult.class, storeDeleteMethod.getReturnType()); assertEquals(List.class, storeServiceQueryMethod.getReturnType()); assertEquals(RagStoreResponse.class, storeServiceDetailMethod.getReturnType()); assertEquals(RagStoreOverviewResponse.class, storeServiceOverviewMethod.getReturnType()); assertEquals(RagStoreDocumentOverviewResponse.class, storeServiceDocumentOverviewMethod.getReturnType()); assertEquals(boolean.class, storeServiceSaveMethod.getReturnType()); assertTrue(storeResponseListMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); assertTrue(storeServiceQueryMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); assertTrue(storeListMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); assertTrue(storeQueryMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); assertTrue(storeDetailMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); assertTrue(storeOverviewMethod.getGenericReturnType().getTypeName().contains("RagStoreOverviewResponse")); assertTrue(storeDocumentOverviewMethod.getGenericReturnType().getTypeName().contains("RagStoreDocumentOverviewResponse")); assertEquals(RagStoreResponse.class, RagStoreResponse.class.getMethod("fromEntity", RagStore.class).getReturnType()); assertEquals(RequestResult.class, documentListMethod.getReturnType()); assertEquals(RequestResult.class, documentQueryMethod.getReturnType()); assertEquals(RequestResult.class, documentParseMethod.getReturnType()); assertEquals(List.class, documentServiceQueryMethod.getReturnType()); assertEquals(List.class, documentParseServiceMethod.getReturnType()); assertTrue(documentResponseListMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); assertTrue(documentServiceQueryMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); assertTrue(documentListMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); assertTrue(documentQueryMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); assertTrue(documentParseMethod.getGenericReturnType().getTypeName().contains("RagDocumentParseResponse")); assertEquals(RagDocumentResponse.class, RagDocumentResponse.class.getMethod("fromEntity", RagDocument.class).getReturnType()); } @Test void ragDocumentListUrlShouldUseExplicitListAction() throws NoSuchMethodException { Method documentListMethod = RagDocumentController.class.getMethod("list"); PostMapping postMapping = documentListMethod.getAnnotation(PostMapping.class); assertNotNull(postMapping); assertEquals("/list", postMapping.value()[0]); } @Test void ragSourceTypesAndDocumentRelationShouldExist() throws NoSuchFieldException { Field storeIdField = RagDocument.class.getDeclaredField("storeId"); Field attachmentIdField = RagDocument.class.getDeclaredField("attachmentId"); assertEquals("RAG_STORE", RagSystemConstants.RAG_STORE); assertEquals("RAG_DOCUMENT", RagSystemConstants.RAG_DOCUMENT); assertEquals("RAG", RagSystemConstants.SOURCE_TYPE_RAG); assertEquals(Long.class, storeIdField.getType()); assertEquals(Long.class, attachmentIdField.getType()); assertTrue(RagStore.class.getSimpleName().contains("RagStore")); assertTrue(RagStoreController.class.getSimpleName().contains("RagStoreController")); assertTrue(RagDocumentController.class.getSimpleName().contains("RagDocumentController")); } @Test void ragChunkStructureShouldSupportChunkMetadata() throws NoSuchFieldException { assertEquals(Long.class, RagChunk.class.getDeclaredField("storeId").getType()); assertEquals(Long.class, RagChunk.class.getDeclaredField("documentId").getType()); assertEquals(Integer.class, RagChunk.class.getDeclaredField("chunkIndex").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("chunkContent").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("chunkSummary").getType()); assertEquals(Integer.class, RagChunk.class.getDeclaredField("tokenCount").getType()); assertEquals(Integer.class, RagChunk.class.getDeclaredField("pageNumber").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("sectionTitle").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("headingPath").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("vectorId").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("metadataJson").getType()); assertEquals(Boolean.class, RagChunk.class.getDeclaredField("enabled").getType()); assertEquals(String.class, RagChunk.class.getDeclaredField("remark").getType()); } @Test void ragChunkEmbeddingStructureShouldSupportPgvectorMetadata() throws NoSuchFieldException { assertEquals(Long.class, RagChunkEmbedding.class.getDeclaredField("storeId").getType()); assertEquals(Long.class, RagChunkEmbedding.class.getDeclaredField("documentId").getType()); assertEquals(Long.class, RagChunkEmbedding.class.getDeclaredField("chunkId").getType()); assertEquals(String.class, RagChunkEmbedding.class.getDeclaredField("embeddingModel").getType()); assertEquals(Integer.class, RagChunkEmbedding.class.getDeclaredField("embeddingDimension").getType()); assertEquals(String.class, RagChunkEmbedding.class.getDeclaredField("embedding").getType()); assertEquals(String.class, RagChunkEmbedding.class.getDeclaredField("contentHash").getType()); assertEquals(Boolean.class, RagChunkEmbedding.class.getDeclaredField("enabled").getType()); assertEquals(String.class, RagChunkEmbedding.class.getDeclaredField("remark").getType()); } @Test void ragParseResultStructureShouldSupportSnapshotMetadata() throws NoSuchFieldException { assertEquals(Long.class, RagDocumentParseResult.class.getDeclaredField("storeId").getType()); assertEquals(Long.class, RagDocumentParseResult.class.getDeclaredField("documentId").getType()); assertEquals(String.class, RagDocumentParseResult.class.getDeclaredField("parsedText").getType()); assertEquals(Integer.class, RagDocumentParseResult.class.getDeclaredField("textLength").getType()); assertEquals(Integer.class, RagDocumentParseResult.class.getDeclaredField("pageCount").getType()); assertEquals(Integer.class, RagDocumentParseResult.class.getDeclaredField("sheetCount").getType()); assertEquals(String.class, RagDocumentParseResult.class.getDeclaredField("metadataJson").getType()); assertEquals(String.class, RagDocumentParseResult.class.getDeclaredField("contentHash").getType()); assertEquals(Integer.class, RagDocumentParseResult.class.getDeclaredField("parseVersion").getType()); assertEquals(Boolean.class, RagDocumentParseResult.class.getDeclaredField("enabled").getType()); } @Test void ragMetadataJsonFieldsShouldUseJsonbTypeHandler() throws NoSuchFieldException { TableName chunkTable = RagChunk.class.getAnnotation(TableName.class); TableName parseResultTable = RagDocumentParseResult.class.getAnnotation(TableName.class); TableField chunkMetadataField = RagChunk.class.getDeclaredField("metadataJson").getAnnotation(TableField.class); TableField parseResultMetadataField = RagDocumentParseResult.class.getDeclaredField("metadataJson").getAnnotation(TableField.class); assertNotNull(chunkTable); assertNotNull(parseResultTable); assertTrue(chunkTable.autoResultMap()); assertTrue(parseResultTable.autoResultMap()); assertNotNull(chunkMetadataField); assertNotNull(parseResultMetadataField); assertEquals(PgJsonbStringTypeHandler.class, chunkMetadataField.typeHandler()); assertEquals(PgJsonbStringTypeHandler.class, parseResultMetadataField.typeHandler()); } }