diff --git a/spring-ai-model/src/test/java/org/springframework/ai/tool/execution/DefaultToolCallResultConverterTests.java b/spring-ai-model/src/test/java/org/springframework/ai/tool/execution/DefaultToolCallResultConverterTests.java index 5b1e908fe48..a7c5288fdb0 100644 --- a/spring-ai-model/src/test/java/org/springframework/ai/tool/execution/DefaultToolCallResultConverterTests.java +++ b/spring-ai-model/src/test/java/org/springframework/ai/tool/execution/DefaultToolCallResultConverterTests.java @@ -123,6 +123,37 @@ void convertImageShouldReturnBase64Image() throws IOException { assertThat(imgRes.getRGB(0, 0)).isEqualTo(img.getRGB(0, 0)); } + @Test + void convertEmptyCollectionsShouldReturnEmptyJson() { + assertThat(this.converter.convert(List.of(), List.class)).isEqualTo("[]"); + assertThat(this.converter.convert(Map.of(), Map.class)).isEqualTo("{}"); + assertThat(this.converter.convert(new String[0], String[].class)).isEqualTo("[]"); + } + + @Test + void convertRecordReturnTypeShouldReturnJson() { + TestRecord record = new TestRecord("recordName", 1); + String result = this.converter.convert(record, TestRecord.class); + + assertThat(result).containsIgnoringWhitespaces("\"recordName\""); + assertThat(result).containsIgnoringWhitespaces("1"); + } + + @Test + void convertSpecialCharactersInStringsShouldEscapeJson() { + String specialChars = "Test with \"quotes\", newlines\n, tabs\t, and backslashes\\"; + String result = this.converter.convert(specialChars, String.class); + + // Should properly escape JSON special characters + assertThat(result).contains("\\\"quotes\\\""); + assertThat(result).contains("\\n"); + assertThat(result).contains("\\t"); + assertThat(result).contains("\\\\"); + } + + record TestRecord(String name, int value) { + } + record Base64Wrapper(MimeType mimeType, String data) { } diff --git a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisFilterExpressionConverterTests.java b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisFilterExpressionConverterTests.java index 33ae76edf8c..732013161ae 100644 --- a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisFilterExpressionConverterTests.java +++ b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisFilterExpressionConverterTests.java @@ -129,4 +129,46 @@ void testComplexIdentifiers() { assertThat(vectorExpr).isEqualTo("@'country 1 2 3':{BG}"); } + @Test + void testSpecialCharactersInValues() { + // Test values with Redis special characters that need escaping + String vectorExpr = converter(RedisVectorStore.MetadataField.tag("description")) + .convertExpression(new Expression(EQ, new Key("description"), new Value("test@value{with}special|chars"))); + + // Should properly escape special Redis characters + assertThat(vectorExpr).isEqualTo("@description:{test@value{with}special|chars}"); + } + + @Test + void testEmptyStringValues() { + String vectorExpr = converter(RedisVectorStore.MetadataField.tag("status")) + .convertExpression(new Expression(EQ, new Key("status"), new Value(""))); + + assertThat(vectorExpr).isEqualTo("@status:{}"); + } + + @Test + void testSingleItemInList() { + String vectorExpr = converter(RedisVectorStore.MetadataField.tag("status")) + .convertExpression(new Expression(IN, new Key("status"), new Value(List.of("active")))); + + assertThat(vectorExpr).isEqualTo("@status:{active}"); + } + + @Test + void testWhitespaceInFieldNames() { + String vectorExpr = converter(RedisVectorStore.MetadataField.tag("value with spaces")) + .convertExpression(new Expression(EQ, new Key("\"value with spaces\""), new Value("test"))); + + assertThat(vectorExpr).isEqualTo("@\"value with spaces\":{test}"); + } + + @Test + void testNestedQuotedFieldNames() { + String vectorExpr = converter(RedisVectorStore.MetadataField.tag("value \"with\" quotes")) + .convertExpression(new Expression(EQ, new Key("\"value \\\"with\\\" quotes\""), new Value("test"))); + + assertThat(vectorExpr).isEqualTo("@\"value \\\"with\\\" quotes\":{test}"); + } + }