test: Add comprehensive test coverage for Vertex AI ContentsMapper (#3831)
## Summary This PR enhances test coverage for the `ContentsMapper` class in the Vertex AI Gemini integration, adding tests for various edge cases and message type combinations. ## Changes - Added test for empty message list handling - Added test for single system message processing - Added test for single user message processing - Added test for multiple system messages handling - Added test for consecutive user messages - Added test for consecutive AI messages - Added test for tool execution without preceding AI message - Added test for single tool execution request - Added test for tools with empty arguments - Added test for tools with null arguments ## Test Coverage Details The new tests cover: - **Empty input handling**: Verifying proper behavior with empty message lists - **Single message types**: Testing isolation of system-only and user-only messages - **Multiple system messages**: Ensuring proper handling when multiple system messages are present - **Consecutive messages**: Testing same-type messages appearing in sequence - **Tool execution edge cases**: Testing tool requests and responses with various argument configurations - **Null/empty arguments**: Verifying handling of tools with null or empty argument objects ## Key Scenarios Tested - Message list boundary conditions (empty, single message) - Message type combinations and ordering - Tool execution flow with and without AI messages - Argument handling in tool requests (null, empty, populated) ## Impact - No production code changes - Improves confidence in ContentsMapper message handling - Documents expected behavior through comprehensive test cases - Helps prevent regressions in Vertex AI message conversion logic Signed-off-by: Oleksandr Klymenko <alexanderklmn@gmail.com>
This commit is contained in:
parent
35f337a821
commit
cdcae55470
|
|
@ -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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue