diff --git a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/MimeTypeDetectorTests.java b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/MimeTypeDetectorTests.java index 9ce4aeb5d57..6608a281214 100644 --- a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/MimeTypeDetectorTests.java +++ b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/MimeTypeDetectorTests.java @@ -26,11 +26,13 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.springframework.ai.google.genai.MimeTypeDetector; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.core.io.PathResource; import org.springframework.util.MimeType; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.springframework.ai.google.genai.MimeTypeDetector.GEMINI_MIME_TYPES; /** @@ -90,4 +92,49 @@ void getMimeTypeByString(String extension, MimeType expectedMimeType) { assertThat(mimeType).isEqualTo(expectedMimeType); } + @ParameterizedTest + @ValueSource(strings = { " ", "\t", "\n" }) + void getMimeTypeByStringWithInvalidInputShouldThrowException(String invalidPath) { + assertThatThrownBy(() -> MimeTypeDetector.getMimeType(invalidPath)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unable to detect the MIME type"); + } + + @ParameterizedTest + @ValueSource(strings = { "JPG", "PNG", "GIF" }) + void getMimeTypeByStringWithUppercaseExtensionsShouldWork(String uppercaseExt) { + String upperFileName = "test." + uppercaseExt; + String lowerFileName = "test." + uppercaseExt.toLowerCase(); + + // Should throw for uppercase (not in map) but work for lowercase + assertThatThrownBy(() -> MimeTypeDetector.getMimeType(upperFileName)) + .isInstanceOf(IllegalArgumentException.class); + + // Lowercase should work if it's a supported extension + if (GEMINI_MIME_TYPES.containsKey(uppercaseExt.toLowerCase())) { + assertThatCode(() -> MimeTypeDetector.getMimeType(lowerFileName)).doesNotThrowAnyException(); + } + } + + @ParameterizedTest + @ValueSource(strings = { "test.jpg", "test.png", "test.gif" }) + void getMimeTypeSupportedFileAcrossDifferentMethodsShouldBeConsistent(String fileName) { + MimeType stringResult = MimeTypeDetector.getMimeType(fileName); + MimeType fileResult = MimeTypeDetector.getMimeType(new File(fileName)); + MimeType pathResult = MimeTypeDetector.getMimeType(Path.of(fileName)); + + // All methods should return the same result for supported extensions + assertThat(stringResult).isEqualTo(fileResult); + assertThat(stringResult).isEqualTo(pathResult); + } + + @ParameterizedTest + @ValueSource(strings = { "https://example.com/documents/file.pdf", "https://example.com/data/file.json", + "https://example.com/files/document.txt" }) + void getMimeTypeByURIWithUnsupportedExtensionsShouldThrowException(String url) { + URI uri = URI.create(url); + + assertThatThrownBy(() -> MimeTypeDetector.getMimeType(uri)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unable to detect the MIME type"); + } + } diff --git a/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceFilterExpressionConverterTests.java b/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceFilterExpressionConverterTests.java index b1487f3e2ec..bd0ec23bfd9 100644 --- a/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceFilterExpressionConverterTests.java +++ b/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceFilterExpressionConverterTests.java @@ -90,4 +90,61 @@ private ValueExtractor extractor(String property) { return new ChainedExtractor(new UniversalExtractor<>("metadata"), new UniversalExtractor<>(property)); } + @Test + void testBooleanValues() { + final Expression e1 = new FilterExpressionTextParser().parse("active == true"); + final Expression e2 = new FilterExpressionTextParser().parse("deleted == false"); + + assertThat(CONVERTER.convert(e1)).isEqualTo(Filters.equal(extractor("active"), true)); + assertThat(CONVERTER.convert(e2)).isEqualTo(Filters.equal(extractor("deleted"), false)); + } + + @Test + void testNumericValues() { + final Expression intExpr = new FilterExpressionTextParser().parse("count == 42"); + final Expression doubleExpr = new FilterExpressionTextParser().parse("rating == 4.5"); + final Expression negativeExpr = new FilterExpressionTextParser().parse("temperature == -10"); + + assertThat(CONVERTER.convert(intExpr)).isEqualTo(Filters.equal(extractor("count"), 42)); + assertThat(CONVERTER.convert(doubleExpr)).isEqualTo(Filters.equal(extractor("rating"), 4.5)); + assertThat(CONVERTER.convert(negativeExpr)).isEqualTo(Filters.equal(extractor("temperature"), -10)); + } + + @Test + void testStringWithSpecialCharacters() { + final Expression e = new FilterExpressionTextParser().parse("description == 'This has \"quotes\" and spaces'"); + assertThat(CONVERTER.convert(e)) + .isEqualTo(Filters.equal(extractor("description"), "This has \"quotes\" and spaces")); + } + + @Test + void testEmptyStringValue() { + final Expression e = new FilterExpressionTextParser().parse("comment == ''"); + assertThat(CONVERTER.convert(e)).isEqualTo(Filters.equal(extractor("comment"), "")); + } + + @Test + void testINWithMixedTypes() { + final Expression e = new FilterExpressionTextParser().parse("status in [1, 'active', true]"); + assertThat(CONVERTER.convert(e)).isEqualTo(Filters.in(extractor("status"), 1, "active", true)); + } + + @Test + void testINWithSingleValue() { + final Expression e = new FilterExpressionTextParser().parse("category in ['category1']"); + assertThat(CONVERTER.convert(e)).isEqualTo(Filters.in(extractor("category"), "category1")); + } + + @Test + void testNINWithSingleValue() { + final Expression e = new FilterExpressionTextParser().parse("category nin ['inactive']"); + assertThat(CONVERTER.convert(e)).isEqualTo(Filters.not(Filters.in(extractor("category"), "inactive"))); + } + + @Test + void testCategoryWithNumericComparison() { + final Expression e = new FilterExpressionTextParser().parse("categoryId >= 5"); + assertThat(CONVERTER.convert(e)).isEqualTo(Filters.greaterEqual(extractor("categoryId"), 5)); + } + }