diff --git a/langchain4j-vertex-ai-gemini/src/test/java/dev/langchain4j/model/vertexai/gemini/ContentsMapperTest.java b/langchain4j-vertex-ai-gemini/src/test/java/dev/langchain4j/model/vertexai/gemini/ContentsMapperTest.java index 85c76259eb..62bd3f12df 100644 --- a/langchain4j-vertex-ai-gemini/src/test/java/dev/langchain4j/model/vertexai/gemini/ContentsMapperTest.java +++ b/langchain4j-vertex-ai-gemini/src/test/java/dev/langchain4j/model/vertexai/gemini/ContentsMapperTest.java @@ -115,4 +115,201 @@ class ContentsMapperTest { assertThat(contents.get(3).getPartsCount()).isEqualTo(1); assertThat(contents.get(3).getParts(0).getText()).isEqualTo("3+4 is smaller than 5+6"); } + + @Test + void should_handle_empty_message_list() { + // given + List msgs = new ArrayList<>(); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.systemInstruction).isNull(); + assertThat(instructionAndContent.contents).isEmpty(); + } + + @Test + void should_handle_only_system_message() { + // given + List msgs = new ArrayList<>(); + msgs.add(SystemMessage.from("Process data efficiently")); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.systemInstruction).isNotNull(); + assertThat(instructionAndContent.systemInstruction.getParts(0).getText()) + .isEqualTo("Process data efficiently"); + assertThat(instructionAndContent.contents).isEmpty(); + } + + @Test + void should_handle_only_user_message() { + // given + List msgs = new ArrayList<>(); + msgs.add(UserMessage.from("Process this request")); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.systemInstruction).isNull(); + assertThat(instructionAndContent.contents).hasSize(1); + assertThat(instructionAndContent.contents.get(0).getParts(0).getText()).isEqualTo("Process this request"); + } + + @Test + void should_handle_multiple_system_messages() { + // given + List msgs = new ArrayList<>(); + msgs.add(SystemMessage.from("First configuration")); + msgs.add(SystemMessage.from("Second configuration")); + msgs.add(UserMessage.from("Input data")); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.systemInstruction).isNotNull(); + assertThat(instructionAndContent.contents).hasSize(1); + assertThat(instructionAndContent.contents.get(0).getParts(0).getText()).isEqualTo("Input data"); + } + + @Test + void should_handle_consecutive_user_messages() { + // given + List msgs = new ArrayList<>(); + msgs.add(UserMessage.from("First input")); + msgs.add(UserMessage.from("Second input")); + msgs.add(UserMessage.from("Third input")); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.systemInstruction).isNull(); + assertThat(instructionAndContent.contents).hasSize(3); + assertThat(instructionAndContent.contents.get(0).getParts(0).getText()).isEqualTo("First input"); + assertThat(instructionAndContent.contents.get(1).getParts(0).getText()).isEqualTo("Second input"); + assertThat(instructionAndContent.contents.get(2).getParts(0).getText()).isEqualTo("Third input"); + } + + @Test + void should_handle_consecutive_ai_messages() { + // given + List msgs = new ArrayList<>(); + msgs.add(UserMessage.from("Request")); + msgs.add(AiMessage.from("Initial output")); + msgs.add(AiMessage.from("Additional output")); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.contents).hasSize(3); + assertThat(instructionAndContent.contents.get(0).getParts(0).getText()).isEqualTo("Request"); + assertThat(instructionAndContent.contents.get(1).getParts(0).getText()).isEqualTo("Initial output"); + assertThat(instructionAndContent.contents.get(2).getParts(0).getText()).isEqualTo("Additional output"); + } + + @Test + void should_handle_tool_execution_without_ai_message() { + // given + List msgs = new ArrayList<>(); + msgs.add(UserMessage.from("Execute task")); + msgs.add(ToolExecutionResultMessage.from(null, "process", "{\"status\": \"complete\"}")); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.contents).hasSize(2); + assertThat(instructionAndContent.contents.get(0).getParts(0).getText()).isEqualTo("Execute task"); + assertThat(instructionAndContent + .contents + .get(1) + .getParts(0) + .getFunctionResponse() + .getName()) + .isEqualTo("process"); + } + + @Test + void should_handle_single_tool_execution_request() { + // given + List msgs = new ArrayList<>(); + msgs.add(UserMessage.from("Request")); + ToolExecutionRequest request = ToolExecutionRequest.builder() + .name("Request") + .arguments("{\"type\": \"standard\"}") + .build(); + msgs.add(AiMessage.from(request)); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.contents).hasSize(2); + assertThat(instructionAndContent + .contents + .get(1) + .getParts(0) + .getFunctionCall() + .getName()) + .isEqualTo("Request"); + } + + @Test + void should_handle_tool_with_empty_arguments() { + // given + List msgs = new ArrayList<>(); + ToolExecutionRequest request = + ToolExecutionRequest.builder().name("getStatus").arguments("{}").build(); + msgs.add(AiMessage.from(request)); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.contents).hasSize(1); + assertThat(instructionAndContent + .contents + .get(0) + .getParts(0) + .getFunctionCall() + .getName()) + .isEqualTo("getStatus"); + assertThat(instructionAndContent + .contents + .get(0) + .getParts(0) + .getFunctionCall() + .getArgs() + .getFieldsCount()) + .isEqualTo(0); + } + + @Test + void should_handle_tool_with_null_arguments() { + // given + List msgs = new ArrayList<>(); + ToolExecutionRequest request = + ToolExecutionRequest.builder().name("fetchData").arguments(null).build(); + msgs.add(AiMessage.from(request)); + + // when + ContentsMapper.InstructionAndContent instructionAndContent = splitInstructionAndContent(msgs); + + // then + assertThat(instructionAndContent.contents).hasSize(1); + assertThat(instructionAndContent + .contents + .get(0) + .getParts(0) + .getFunctionCall() + .getName()) + .isEqualTo("fetchData"); + } }