From 6677465bd0e1534427d5e1192c78cd2de633ef44 Mon Sep 17 00:00:00 2001 From: Mark Pollack Date: Thu, 8 May 2025 12:46:06 -0400 Subject: [PATCH] Improve support for running tests on windows Signed-off-by: szarpul@users.noreply.github.com Signed-off-by: Mark Pollack --- .../ai/document/ContentFormatterTests.java | 15 ++- .../ai/document/TextBlockAssertion.java | 53 ++++++++ .../ai/converter/BeanOutputConverterTest.java | 122 +++++++++--------- .../ai/util/TextBlockAssertion.java | 53 ++++++++ 4 files changed, 177 insertions(+), 66 deletions(-) create mode 100644 spring-ai-commons/src/test/java/org/springframework/ai/document/TextBlockAssertion.java create mode 100644 spring-ai-model/src/test/java/org/springframework/ai/util/TextBlockAssertion.java diff --git a/spring-ai-commons/src/test/java/org/springframework/ai/document/ContentFormatterTests.java b/spring-ai-commons/src/test/java/org/springframework/ai/document/ContentFormatterTests.java index e71daba9a43..d1d52c2913a 100644 --- a/spring-ai-commons/src/test/java/org/springframework/ai/document/ContentFormatterTests.java +++ b/spring-ai-commons/src/test/java/org/springframework/ai/document/ContentFormatterTests.java @@ -32,7 +32,7 @@ public class ContentFormatterTests { @Test public void noExplicitlySetFormatter() { - assertThat(this.document.getText()).isEqualTo(""" + TextBlockAssertion.assertThat(this.document.getText()).isEqualTo(""" The World is Big and Salvation Lurks Around the Corner"""); assertThat(this.document.getFormattedContent()).isEqualTo(this.document.getFormattedContent(MetadataMode.ALL)); @@ -46,13 +46,14 @@ public void defaultConfigTextFormatter() { DefaultContentFormatter defaultConfigFormatter = DefaultContentFormatter.defaultConfig(); - assertThat(this.document.getFormattedContent(defaultConfigFormatter, MetadataMode.ALL)).isEqualTo(""" - llmKey2: value4 - embedKey1: value1 - embedKey2: value2 - embedKey3: value3 + TextBlockAssertion.assertThat(this.document.getFormattedContent(defaultConfigFormatter, MetadataMode.ALL)) + .isEqualTo(""" + llmKey2: value4 + embedKey1: value1 + embedKey2: value2 + embedKey3: value3 - The World is Big and Salvation Lurks Around the Corner"""); + The World is Big and Salvation Lurks Around the Corner"""); assertThat(this.document.getFormattedContent(defaultConfigFormatter, MetadataMode.ALL)) .isEqualTo(this.document.getFormattedContent()); diff --git a/spring-ai-commons/src/test/java/org/springframework/ai/document/TextBlockAssertion.java b/spring-ai-commons/src/test/java/org/springframework/ai/document/TextBlockAssertion.java new file mode 100644 index 00000000000..06ea5fb357d --- /dev/null +++ b/spring-ai-commons/src/test/java/org/springframework/ai/document/TextBlockAssertion.java @@ -0,0 +1,53 @@ +/* + * Copyright 2024 - 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ai.document; + +import java.util.Arrays; + +import org.assertj.core.api.AbstractCharSequenceAssert; +import org.assertj.core.api.Assertions; + +public class TextBlockAssertion extends AbstractCharSequenceAssert { + + protected TextBlockAssertion(String string) { + super(string, TextBlockAssertion.class); + } + + public static TextBlockAssertion assertThat(String actual) { + return new TextBlockAssertion(actual); + } + + @Override + public TextBlockAssertion isEqualTo(Object expected) { + Assertions.assertThat(normalizedEOL(actual)).isEqualTo(normalizedEOL((String) expected)); + return this; + } + + @Override + public TextBlockAssertion contains(CharSequence... values) { + Assertions.assertThat(normalizedEOL(actual)).contains(normalizedEOL(values)); + return this; + } + + private String normalizedEOL(CharSequence... values) { + return Arrays.stream(values).map(CharSequence::toString).map(this::normalizedEOL).reduce("", (a, b) -> a + b); + } + + private String normalizedEOL(String line) { + return line.replaceAll("\r\n|\r|\n", System.lineSeparator()); + } + +} diff --git a/spring-ai-model/src/test/java/org/springframework/ai/converter/BeanOutputConverterTest.java b/spring-ai-model/src/test/java/org/springframework/ai/converter/BeanOutputConverterTest.java index b136ded49f8..498d0782045 100644 --- a/spring-ai-model/src/test/java/org/springframework/ai/converter/BeanOutputConverterTest.java +++ b/spring-ai-model/src/test/java/org/springframework/ai/converter/BeanOutputConverterTest.java @@ -38,6 +38,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.LoggerFactory; +import org.springframework.ai.util.TextBlockAssertion; import org.springframework.core.ParameterizedTypeReference; import static org.assertj.core.api.Assertions.assertThat; @@ -246,24 +247,25 @@ class FormatTest { @Test void formatClassType() { var converter = new BeanOutputConverter<>(TestClass.class); - assertThat(converter.getFormat()).isEqualTo( - """ - Your response should be in JSON format. - Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. - Do not include markdown code blocks in your response. - Remove the ```json markdown from the output. - Here is the JSON Schema instance your output must adhere to: - ```{ - "$schema" : "https://json-schema.org/draft/2020-12/schema", - "type" : "object", - "properties" : { - "someString" : { - "type" : "string" - } - }, - "additionalProperties" : false - }``` - """); + TextBlockAssertion.assertThat(converter.getFormat()) + .isEqualTo( + """ + Your response should be in JSON format. + Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. + Do not include markdown code blocks in your response. + Remove the ```json markdown from the output. + Here is the JSON Schema instance your output must adhere to: + ```{ + "$schema" : "https://json-schema.org/draft/2020-12/schema", + "type" : "object", + "properties" : { + "someString" : { + "type" : "string" + } + }, + "additionalProperties" : false + }``` + """); } @Test @@ -271,24 +273,25 @@ void formatTypeReference() { var converter = new BeanOutputConverter<>(new ParameterizedTypeReference() { }); - assertThat(converter.getFormat()).isEqualTo( - """ - Your response should be in JSON format. - Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. - Do not include markdown code blocks in your response. - Remove the ```json markdown from the output. - Here is the JSON Schema instance your output must adhere to: - ```{ - "$schema" : "https://json-schema.org/draft/2020-12/schema", - "type" : "object", - "properties" : { - "someString" : { - "type" : "string" - } - }, - "additionalProperties" : false - }``` - """); + TextBlockAssertion.assertThat(converter.getFormat()) + .isEqualTo( + """ + Your response should be in JSON format. + Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. + Do not include markdown code blocks in your response. + Remove the ```json markdown from the output. + Here is the JSON Schema instance your output must adhere to: + ```{ + "$schema" : "https://json-schema.org/draft/2020-12/schema", + "type" : "object", + "properties" : { + "someString" : { + "type" : "string" + } + }, + "additionalProperties" : false + }``` + """); } @Test @@ -296,33 +299,34 @@ void formatTypeReferenceArray() { var converter = new BeanOutputConverter<>(new ParameterizedTypeReference>() { }); - assertThat(converter.getFormat()).isEqualTo( - """ - Your response should be in JSON format. - Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. - Do not include markdown code blocks in your response. - Remove the ```json markdown from the output. - Here is the JSON Schema instance your output must adhere to: - ```{ - "$schema" : "https://json-schema.org/draft/2020-12/schema", - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "someString" : { - "type" : "string" - } - }, - "additionalProperties" : false - } - }``` - """); + TextBlockAssertion.assertThat(converter.getFormat()) + .isEqualTo( + """ + Your response should be in JSON format. + Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. + Do not include markdown code blocks in your response. + Remove the ```json markdown from the output. + Here is the JSON Schema instance your output must adhere to: + ```{ + "$schema" : "https://json-schema.org/draft/2020-12/schema", + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "someString" : { + "type" : "string" + } + }, + "additionalProperties" : false + } + }``` + """); } @Test void formatClassTypeWithAnnotations() { var converter = new BeanOutputConverter<>(TestClassWithJsonAnnotations.class); - assertThat(converter.getFormat()).contains(""" + TextBlockAssertion.assertThat(converter.getFormat()).contains(""" ```{ "$schema" : "https://json-schema.org/draft/2020-12/schema", "type" : "object", @@ -342,7 +346,7 @@ void formatTypeReferenceWithAnnotations() { var converter = new BeanOutputConverter<>(new ParameterizedTypeReference() { }); - assertThat(converter.getFormat()).contains(""" + TextBlockAssertion.assertThat(converter.getFormat()).contains(""" ```{ "$schema" : "https://json-schema.org/draft/2020-12/schema", "type" : "object", diff --git a/spring-ai-model/src/test/java/org/springframework/ai/util/TextBlockAssertion.java b/spring-ai-model/src/test/java/org/springframework/ai/util/TextBlockAssertion.java new file mode 100644 index 00000000000..5dc17587fa7 --- /dev/null +++ b/spring-ai-model/src/test/java/org/springframework/ai/util/TextBlockAssertion.java @@ -0,0 +1,53 @@ +/* + * Copyright 2024 - 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ai.util; + +import java.util.Arrays; + +import org.assertj.core.api.AbstractCharSequenceAssert; +import org.assertj.core.api.Assertions; + +public class TextBlockAssertion extends AbstractCharSequenceAssert { + + protected TextBlockAssertion(String string) { + super(string, TextBlockAssertion.class); + } + + public static TextBlockAssertion assertThat(String actual) { + return new TextBlockAssertion(actual); + } + + @Override + public TextBlockAssertion isEqualTo(Object expected) { + Assertions.assertThat(normalizedEOL(actual)).isEqualTo(normalizedEOL((String) expected)); + return this; + } + + @Override + public TextBlockAssertion contains(CharSequence... values) { + Assertions.assertThat(normalizedEOL(actual)).contains(normalizedEOL(values)); + return this; + } + + private String normalizedEOL(CharSequence... values) { + return Arrays.stream(values).map(CharSequence::toString).map(this::normalizedEOL).reduce("", (a, b) -> a + b); + } + + private String normalizedEOL(String line) { + return line.replaceAll("\r\n|\r|\n", System.lineSeparator()); + } + +}