From 25c7e5bc3498e1d51069513394c255c799ab627d Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 14 Jul 2026 09:09:28 +0200 Subject: [PATCH 1/9] disable Slack notification --- .github/workflows/e2e-test.yaml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index 230fdbc31..a7db81d5e 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -99,19 +99,19 @@ jobs: # print response body with headers to stdout. q:body only O:print -:stdout S:headers run: wget -qO- -S localhost:8080 - - name: "Slack Notification" - if: failure() - uses: slackapi/slack-github-action@v3.0.3 - with: - webhook: ${{ secrets.SLACK_WEBHOOK }} - webhook-type: incoming-webhook - payload: | - blocks: - - type: "section" - text: - type: "mrkdwn" - text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " - - type: "section" - text: - type: "plain_text" - text: "${{ steps.run_tests.outputs.error_message }} " +# - name: "Slack Notification" +# if: failure() +# uses: slackapi/slack-github-action@v3.0.3 +# with: +# webhook: ${{ secrets.SLACK_WEBHOOK }} +# webhook-type: incoming-webhook +# payload: | +# blocks: +# - type: "section" +# text: +# type: "mrkdwn" +# text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " +# - type: "section" +# text: +# type: "plain_text" +# text: "${{ steps.run_tests.outputs.error_message }} " From 0844da172a3026e9305abd9c97b0576e9a531f34 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 14 Jul 2026 09:09:46 +0200 Subject: [PATCH 2/9] enable multiline error messages --- .github/workflows/e2e-test.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index a7db81d5e..420e9103a 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -55,7 +55,9 @@ jobs: awk '/Results:/, /----/' mvn_output.log > test_error.log || true # true ensures the step doesn't fail if no match is found. ERROR_MSG=$(cat test_error.log | tail +4 | head -n -4 | awk 'BEGIN{RS=""} {gsub(/"/, "\\\""); gsub(/Expecting KeySet:.*but could not find the following element\(s\):/, "Missing element: "); printf "%s\n", $0}') echo "$ERROR_MSG" - echo "error_message=$ERROR_MSG" >> $GITHUB_OUTPUT + echo "error_message<> $GITHUB_OUTPUT + echo "$ERROR_MSG" >> $GITHUB_OUTPUT + echo "GITHUB_OUTPUT_EOF" >> $GITHUB_OUTPUT if grep -q "BUILD FAILURE" mvn_output.log; then echo "Maven build failed." From 7a9c57e4abdc70d47b1cbf39df58d1b7cc314fd5 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 14 Jul 2026 09:51:41 +0200 Subject: [PATCH 3/9] enable Slack notification again --- .github/workflows/e2e-test.yaml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index 420e9103a..308e49e2f 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -101,19 +101,19 @@ jobs: # print response body with headers to stdout. q:body only O:print -:stdout S:headers run: wget -qO- -S localhost:8080 -# - name: "Slack Notification" -# if: failure() -# uses: slackapi/slack-github-action@v3.0.3 -# with: -# webhook: ${{ secrets.SLACK_WEBHOOK }} -# webhook-type: incoming-webhook -# payload: | -# blocks: -# - type: "section" -# text: -# type: "mrkdwn" -# text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " -# - type: "section" -# text: -# type: "plain_text" -# text: "${{ steps.run_tests.outputs.error_message }} " + - name: "Slack Notification" + if: failure() + uses: slackapi/slack-github-action@v3.0.3 + with: + webhook: ${{ secrets.SLACK_WEBHOOK }} + webhook-type: incoming-webhook + payload: | + blocks: + - type: "section" + text: + type: "mrkdwn" + text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " + - type: "section" + text: + type: "plain_text" + text: "${{ steps.run_tests.outputs.error_message }} " From d765a8ca7141444287dcf333253e6b6fe2abac73 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 14 Jul 2026 13:48:56 +0200 Subject: [PATCH 4/9] disable new tests --- .../sdk/app/controllers/AiCoreOpenAiTest.java | 468 +++++++++--------- 1 file changed, 234 insertions(+), 234 deletions(-) diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java index 4a644d7f3..1145917d2 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java @@ -21,239 +21,239 @@ @Slf4j class AiCoreOpenAiTest { - AiCoreOpenAiService service; +// AiCoreOpenAiService service; - @BeforeEach - void setUp() { - service = new AiCoreOpenAiService(); - } - - @Test - void testCreateResponse() { - final var response = service.createResponse("What is the capital of France?"); - assertThat(response).isNotNull(); - assertThat(response.output()).isNotNull(); - - final var reasoningOutput = response.output().get(0); - assertThat(reasoningOutput.isReasoning()).isTrue(); - final var messageOutput = response.output().get(1); - assertThat(messageOutput.isMessage()).isTrue(); - assertThat(messageOutput.asMessage().content()).isNotEmpty(); - final var content = messageOutput.asMessage().content().get(0); - assertThat(content.isOutputText()).isTrue(); - assertThat(content.asOutputText().text()).containsIgnoringCase("Paris"); - } - - @Test - void testCreateStreamingResponse() { - try (var stream = service.createStreamingResponse("What is the capital of France?")) { - stream.stream() - .forEach( - event -> { - assertThat(event.isValid()).isTrue(); - - if (event.isCompleted()) { - final var response = event.asCompleted().response(); - assertThat(response.output()).isNotEmpty(); - final var message = - response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - final var content = message.get().asMessage().content(); - assertThat(content).isNotEmpty(); - assertThat(content.get(0).isOutputText()).isTrue(); - assertThat(content.get(0).asOutputText().text()).containsIgnoringCase("Paris"); - } - }); - } - } - - @Test - void testRetrieveResponse() { - final var created = service.createPersistentResponse("Say hi.", false); - assertThat(created.id()).isNotBlank(); - - final var retrieved = service.retrieveResponse(created.id()); - assertThat(retrieved).isNotNull(); - assertThat(retrieved.id()).isEqualTo(created.id()); - - // Cleanup - service.deleteResponse(created.id()); - } - - @Test - void testCancelResponse() { - final var created = - service.createPersistentResponse( - "Write an extremely detailed 10-page essay covering the full history of distributed" - + " systems from the 1960s to today. Include subsections, citations, and concrete" - + " examples for every decade.", - true); - assertThat(created.id()).isNotBlank(); - - final var cancelled = service.cancelResponse(created.id()); - assertThat(cancelled).isNotNull(); - assertThat(cancelled.id()).isEqualTo(created.id()); - assertThat(cancelled.status()).contains(ResponseStatus.CANCELLED); - - // Cleanup - service.deleteResponse(created.id()); - } - - @Test - void testDeleteResponse() { - final var created = service.createPersistentResponse("Say hi.", false); - assertThat(created.id()).isNotBlank(); - - assertThatNoException().isThrownBy(() -> service.deleteResponse(created.id())); - } - - @Test - void testBackgroundMode() throws InterruptedException { - final var response = - service.createBackgroundResponseAndPoll("Write a short poem about the sea."); - assertThat(response).isNotNull(); - assertThat(response.status()) - .satisfiesAnyOf( - s -> assertThat(s).contains(ResponseStatus.COMPLETED), - s -> assertThat(s).contains(ResponseStatus.FAILED)); - assertThat(response.output()).isNotEmpty(); - final var message = - response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - assertThat(message.get().asMessage().content().get(0).asOutputText().text()).isNotBlank(); - } - - @Test - void testMultiTurnResponse() { - final var first = service.createPersistentResponse("Count to 3 in Spanish.", false); - assertThat(first.id()).isNotBlank(); - - final var followUp = - service.createMultiTurnResponse("What did I just ask you to count to?", first.id()); - assertThat(followUp).isNotNull(); - assertThat(followUp.previousResponseId()).contains(first.id()); - final var message = - followUp.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - assertThat( - message - .get() - .asMessage() - .content() - .get(0) - .asOutputText() - .text() - .toLowerCase(Locale.ROOT)) - .containsAnyOf("three", "3"); - } - - @Test - void testToolCalling() { - final var response = service.createResponseWithTools("What is the weather in Berlin today?"); - assertThat(response).isNotNull(); - assertThat(response.output()).isNotEmpty(); - final var functionCall = - response.output().stream().filter(ResponseOutputItem::isFunctionCall).findFirst(); - assertThat(functionCall).isPresent(); - assertThat(functionCall.get().asFunctionCall().name()).isEqualTo("get_weather"); - assertThat(functionCall.get().asFunctionCall().arguments()).contains("Berlin"); - } - - @Test - void testReasoningEffort() { - final var response = - service.createResponseWithReasoning( - "If a train travels 120 km in 1.5 hours, what is its average speed?", - ReasoningEffort.HIGH); - assertThat(response).isNotNull(); - assertThat(response.reasoning().isPresent()).isTrue(); - assertThat(response.reasoning().get().effort()).contains(ReasoningEffort.HIGH); - final var reasoning = - response.output().stream().filter(ResponseOutputItem::isReasoning).findFirst(); - assertThat(reasoning).isPresent(); - assertThat(reasoning.get().asReasoning().summary()).isNotEmpty(); - final var message = - response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - assertThat(message.get().asMessage().content().get(0).asOutputText().text()).contains("80"); - } - - @Test - void testStructuredOutput() throws JsonProcessingException { - final var response = - service.createStructuredResponse("Extract the name and age from: John is 30 years old."); - assertThat(response).isNotNull(); - final var message = - response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - final var text = message.get().asMessage().content().get(0).asOutputText().text(); - final var parsed = new ObjectMapper().readValue(text, Map.class); - assertThat(parsed.get("name")).isEqualTo("John"); - assertThat(parsed.get("age")).isEqualTo(30); - } - - @Test - void testStatelessMultiTurn() { - final var messages = - List.of( - ResponseInputItem.ofEasyInputMessage( - EasyInputMessage.builder() - .role(EasyInputMessage.Role.USER) - .content("Count to 3 in Spanish.") - .build()), - ResponseInputItem.ofEasyInputMessage( - EasyInputMessage.builder() - .role(EasyInputMessage.Role.ASSISTANT) - .content("Uno, dos, tres.") - .build()), - ResponseInputItem.ofEasyInputMessage( - EasyInputMessage.builder() - .role(EasyInputMessage.Role.USER) - .content("Now count to 5.") - .build())); - final var response = service.createStatelessMultiTurnResponse(messages); - assertThat(response).isNotNull(); - final var message = - response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - final var text = message.get().asMessage().content().get(0).asOutputText().text(); - assertThat(text).containsIgnoringCase("cinco"); - } - - @Test - void testTruncation() { - final var first = - service.createPersistentResponse("Write a short poem about the ocean.", false); - assertThat(first.id()).isNotBlank(); - - final var response = - service.createResponseWithTruncation("Summarize what I asked.", first.id()); - assertThat(response).isNotNull(); - assertThat(response.previousResponseId()).contains(first.id()); - assertThat(response.truncation()).contains(Truncation.AUTO); - final var message = - response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - assertThat(message).isPresent(); - assertThat(message.get().asMessage().content()).isNotEmpty(); - } - - @Test - void testPromptCaching() { - final var cacheKey = "ai-sdk-java-test-cache-key"; - final var prompt = "What is the capital of France?"; - - // First call populates the cache - final var first = service.createCachedResponse(prompt, cacheKey); - assertThat(first).isNotNull(); - assertThat(first.promptCacheKey()).contains(cacheKey); - assertThat(first.usage().isPresent()).isTrue(); - - // Second call with the same key — cache hit is server-side and not guaranteed in tests, so we - // only assert the key is echoed back and usage is accessible - final var second = service.createCachedResponse(prompt, cacheKey); - assertThat(second).isNotNull(); - assertThat(second.promptCacheKey()).contains(cacheKey); - assertThat(second.usage().isPresent()).isTrue(); - assertThat(second.usage().get().inputTokensDetails().cachedTokens()).isGreaterThanOrEqualTo(0); - } +// @BeforeEach +// void setUp() { +// service = new AiCoreOpenAiService(); +// } +// +// @Test +// void testCreateResponse() { +// final var response = service.createResponse("What is the capital of France?"); +// assertThat(response).isNotNull(); +// assertThat(response.output()).isNotNull(); +// +// final var reasoningOutput = response.output().get(0); +// assertThat(reasoningOutput.isReasoning()).isTrue(); +// final var messageOutput = response.output().get(1); +// assertThat(messageOutput.isMessage()).isTrue(); +// assertThat(messageOutput.asMessage().content()).isNotEmpty(); +// final var content = messageOutput.asMessage().content().get(0); +// assertThat(content.isOutputText()).isTrue(); +// assertThat(content.asOutputText().text()).containsIgnoringCase("Paris"); +// } +// +// @Test +// void testCreateStreamingResponse() { +// try (var stream = service.createStreamingResponse("What is the capital of France?")) { +// stream.stream() +// .forEach( +// event -> { +// assertThat(event.isValid()).isTrue(); +// +// if (event.isCompleted()) { +// final var response = event.asCompleted().response(); +// assertThat(response.output()).isNotEmpty(); +// final var message = +// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// final var content = message.get().asMessage().content(); +// assertThat(content).isNotEmpty(); +// assertThat(content.get(0).isOutputText()).isTrue(); +// assertThat(content.get(0).asOutputText().text()).containsIgnoringCase("Paris"); +// } +// }); +// } +// } +// +// @Test +// void testRetrieveResponse() { +// final var created = service.createPersistentResponse("Say hi.", false); +// assertThat(created.id()).isNotBlank(); +// +// final var retrieved = service.retrieveResponse(created.id()); +// assertThat(retrieved).isNotNull(); +// assertThat(retrieved.id()).isEqualTo(created.id()); +// +// // Cleanup +// service.deleteResponse(created.id()); +// } +// +// @Test +// void testCancelResponse() { +// final var created = +// service.createPersistentResponse( +// "Write an extremely detailed 10-page essay covering the full history of distributed" +// + " systems from the 1960s to today. Include subsections, citations, and concrete" +// + " examples for every decade.", +// true); +// assertThat(created.id()).isNotBlank(); +// +// final var cancelled = service.cancelResponse(created.id()); +// assertThat(cancelled).isNotNull(); +// assertThat(cancelled.id()).isEqualTo(created.id()); +// assertThat(cancelled.status()).contains(ResponseStatus.CANCELLED); +// +// // Cleanup +// service.deleteResponse(created.id()); +// } +// +// @Test +// void testDeleteResponse() { +// final var created = service.createPersistentResponse("Say hi.", false); +// assertThat(created.id()).isNotBlank(); +// +// assertThatNoException().isThrownBy(() -> service.deleteResponse(created.id())); +// } +// +// @Test +// void testBackgroundMode() throws InterruptedException { +// final var response = +// service.createBackgroundResponseAndPoll("Write a short poem about the sea."); +// assertThat(response).isNotNull(); +// assertThat(response.status()) +// .satisfiesAnyOf( +// s -> assertThat(s).contains(ResponseStatus.COMPLETED), +// s -> assertThat(s).contains(ResponseStatus.FAILED)); +// assertThat(response.output()).isNotEmpty(); +// final var message = +// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// assertThat(message.get().asMessage().content().get(0).asOutputText().text()).isNotBlank(); +// } +// +// @Test +// void testMultiTurnResponse() { +// final var first = service.createPersistentResponse("Count to 3 in Spanish.", false); +// assertThat(first.id()).isNotBlank(); +// +// final var followUp = +// service.createMultiTurnResponse("What did I just ask you to count to?", first.id()); +// assertThat(followUp).isNotNull(); +// assertThat(followUp.previousResponseId()).contains(first.id()); +// final var message = +// followUp.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// assertThat( +// message +// .get() +// .asMessage() +// .content() +// .get(0) +// .asOutputText() +// .text() +// .toLowerCase(Locale.ROOT)) +// .containsAnyOf("three", "3"); +// } +// +// @Test +// void testToolCalling() { +// final var response = service.createResponseWithTools("What is the weather in Berlin today?"); +// assertThat(response).isNotNull(); +// assertThat(response.output()).isNotEmpty(); +// final var functionCall = +// response.output().stream().filter(ResponseOutputItem::isFunctionCall).findFirst(); +// assertThat(functionCall).isPresent(); +// assertThat(functionCall.get().asFunctionCall().name()).isEqualTo("get_weather"); +// assertThat(functionCall.get().asFunctionCall().arguments()).contains("Berlin"); +// } +// +// @Test +// void testReasoningEffort() { +// final var response = +// service.createResponseWithReasoning( +// "If a train travels 120 km in 1.5 hours, what is its average speed?", +// ReasoningEffort.HIGH); +// assertThat(response).isNotNull(); +// assertThat(response.reasoning().isPresent()).isTrue(); +// assertThat(response.reasoning().get().effort()).contains(ReasoningEffort.HIGH); +// final var reasoning = +// response.output().stream().filter(ResponseOutputItem::isReasoning).findFirst(); +// assertThat(reasoning).isPresent(); +// assertThat(reasoning.get().asReasoning().summary()).isNotEmpty(); +// final var message = +// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// assertThat(message.get().asMessage().content().get(0).asOutputText().text()).contains("80"); +// } +// +// @Test +// void testStructuredOutput() throws JsonProcessingException { +// final var response = +// service.createStructuredResponse("Extract the name and age from: John is 30 years old."); +// assertThat(response).isNotNull(); +// final var message = +// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// final var text = message.get().asMessage().content().get(0).asOutputText().text(); +// final var parsed = new ObjectMapper().readValue(text, Map.class); +// assertThat(parsed.get("name")).isEqualTo("John"); +// assertThat(parsed.get("age")).isEqualTo(30); +// } +// +// @Test +// void testStatelessMultiTurn() { +// final var messages = +// List.of( +// ResponseInputItem.ofEasyInputMessage( +// EasyInputMessage.builder() +// .role(EasyInputMessage.Role.USER) +// .content("Count to 3 in Spanish.") +// .build()), +// ResponseInputItem.ofEasyInputMessage( +// EasyInputMessage.builder() +// .role(EasyInputMessage.Role.ASSISTANT) +// .content("Uno, dos, tres.") +// .build()), +// ResponseInputItem.ofEasyInputMessage( +// EasyInputMessage.builder() +// .role(EasyInputMessage.Role.USER) +// .content("Now count to 5.") +// .build())); +// final var response = service.createStatelessMultiTurnResponse(messages); +// assertThat(response).isNotNull(); +// final var message = +// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// final var text = message.get().asMessage().content().get(0).asOutputText().text(); +// assertThat(text).containsIgnoringCase("cinco"); +// } +// +// @Test +// void testTruncation() { +// final var first = +// service.createPersistentResponse("Write a short poem about the ocean.", false); +// assertThat(first.id()).isNotBlank(); +// +// final var response = +// service.createResponseWithTruncation("Summarize what I asked.", first.id()); +// assertThat(response).isNotNull(); +// assertThat(response.previousResponseId()).contains(first.id()); +// assertThat(response.truncation()).contains(Truncation.AUTO); +// final var message = +// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); +// assertThat(message).isPresent(); +// assertThat(message.get().asMessage().content()).isNotEmpty(); +// } +// +// @Test +// void testPromptCaching() { +// final var cacheKey = "ai-sdk-java-test-cache-key"; +// final var prompt = "What is the capital of France?"; +// +// // First call populates the cache +// final var first = service.createCachedResponse(prompt, cacheKey); +// assertThat(first).isNotNull(); +// assertThat(first.promptCacheKey()).contains(cacheKey); +// assertThat(first.usage().isPresent()).isTrue(); +// +// // Second call with the same key — cache hit is server-side and not guaranteed in tests, so we +// // only assert the key is echoed back and usage is accessible +// final var second = service.createCachedResponse(prompt, cacheKey); +// assertThat(second).isNotNull(); +// assertThat(second.promptCacheKey()).contains(cacheKey); +// assertThat(second.usage().isPresent()).isTrue(); +// assertThat(second.usage().get().inputTokensDetails().cachedTokens()).isGreaterThanOrEqualTo(0); +// } } From 4e2e5932149967fcf88456c1e74a286c35db1394 Mon Sep 17 00:00:00 2001 From: SAP Cloud SDK Bot Date: Tue, 14 Jul 2026 11:49:45 +0000 Subject: [PATCH 5/9] Formatting --- .../sdk/app/controllers/AiCoreOpenAiTest.java | 492 +++++++++--------- 1 file changed, 241 insertions(+), 251 deletions(-) diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java index 1145917d2..6f4f2cd51 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java @@ -1,259 +1,249 @@ package com.sap.ai.sdk.app.controllers; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatNoException; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.openai.models.ReasoningEffort; -import com.openai.models.responses.EasyInputMessage; -import com.openai.models.responses.Response.Truncation; -import com.openai.models.responses.ResponseInputItem; -import com.openai.models.responses.ResponseOutputItem; -import com.openai.models.responses.ResponseStatus; -import com.sap.ai.sdk.app.services.AiCoreOpenAiService; -import java.util.List; -import java.util.Locale; -import java.util.Map; import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; @Slf4j class AiCoreOpenAiTest { -// AiCoreOpenAiService service; + // AiCoreOpenAiService service; -// @BeforeEach -// void setUp() { -// service = new AiCoreOpenAiService(); -// } -// -// @Test -// void testCreateResponse() { -// final var response = service.createResponse("What is the capital of France?"); -// assertThat(response).isNotNull(); -// assertThat(response.output()).isNotNull(); -// -// final var reasoningOutput = response.output().get(0); -// assertThat(reasoningOutput.isReasoning()).isTrue(); -// final var messageOutput = response.output().get(1); -// assertThat(messageOutput.isMessage()).isTrue(); -// assertThat(messageOutput.asMessage().content()).isNotEmpty(); -// final var content = messageOutput.asMessage().content().get(0); -// assertThat(content.isOutputText()).isTrue(); -// assertThat(content.asOutputText().text()).containsIgnoringCase("Paris"); -// } -// -// @Test -// void testCreateStreamingResponse() { -// try (var stream = service.createStreamingResponse("What is the capital of France?")) { -// stream.stream() -// .forEach( -// event -> { -// assertThat(event.isValid()).isTrue(); -// -// if (event.isCompleted()) { -// final var response = event.asCompleted().response(); -// assertThat(response.output()).isNotEmpty(); -// final var message = -// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// final var content = message.get().asMessage().content(); -// assertThat(content).isNotEmpty(); -// assertThat(content.get(0).isOutputText()).isTrue(); -// assertThat(content.get(0).asOutputText().text()).containsIgnoringCase("Paris"); -// } -// }); -// } -// } -// -// @Test -// void testRetrieveResponse() { -// final var created = service.createPersistentResponse("Say hi.", false); -// assertThat(created.id()).isNotBlank(); -// -// final var retrieved = service.retrieveResponse(created.id()); -// assertThat(retrieved).isNotNull(); -// assertThat(retrieved.id()).isEqualTo(created.id()); -// -// // Cleanup -// service.deleteResponse(created.id()); -// } -// -// @Test -// void testCancelResponse() { -// final var created = -// service.createPersistentResponse( -// "Write an extremely detailed 10-page essay covering the full history of distributed" -// + " systems from the 1960s to today. Include subsections, citations, and concrete" -// + " examples for every decade.", -// true); -// assertThat(created.id()).isNotBlank(); -// -// final var cancelled = service.cancelResponse(created.id()); -// assertThat(cancelled).isNotNull(); -// assertThat(cancelled.id()).isEqualTo(created.id()); -// assertThat(cancelled.status()).contains(ResponseStatus.CANCELLED); -// -// // Cleanup -// service.deleteResponse(created.id()); -// } -// -// @Test -// void testDeleteResponse() { -// final var created = service.createPersistentResponse("Say hi.", false); -// assertThat(created.id()).isNotBlank(); -// -// assertThatNoException().isThrownBy(() -> service.deleteResponse(created.id())); -// } -// -// @Test -// void testBackgroundMode() throws InterruptedException { -// final var response = -// service.createBackgroundResponseAndPoll("Write a short poem about the sea."); -// assertThat(response).isNotNull(); -// assertThat(response.status()) -// .satisfiesAnyOf( -// s -> assertThat(s).contains(ResponseStatus.COMPLETED), -// s -> assertThat(s).contains(ResponseStatus.FAILED)); -// assertThat(response.output()).isNotEmpty(); -// final var message = -// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// assertThat(message.get().asMessage().content().get(0).asOutputText().text()).isNotBlank(); -// } -// -// @Test -// void testMultiTurnResponse() { -// final var first = service.createPersistentResponse("Count to 3 in Spanish.", false); -// assertThat(first.id()).isNotBlank(); -// -// final var followUp = -// service.createMultiTurnResponse("What did I just ask you to count to?", first.id()); -// assertThat(followUp).isNotNull(); -// assertThat(followUp.previousResponseId()).contains(first.id()); -// final var message = -// followUp.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// assertThat( -// message -// .get() -// .asMessage() -// .content() -// .get(0) -// .asOutputText() -// .text() -// .toLowerCase(Locale.ROOT)) -// .containsAnyOf("three", "3"); -// } -// -// @Test -// void testToolCalling() { -// final var response = service.createResponseWithTools("What is the weather in Berlin today?"); -// assertThat(response).isNotNull(); -// assertThat(response.output()).isNotEmpty(); -// final var functionCall = -// response.output().stream().filter(ResponseOutputItem::isFunctionCall).findFirst(); -// assertThat(functionCall).isPresent(); -// assertThat(functionCall.get().asFunctionCall().name()).isEqualTo("get_weather"); -// assertThat(functionCall.get().asFunctionCall().arguments()).contains("Berlin"); -// } -// -// @Test -// void testReasoningEffort() { -// final var response = -// service.createResponseWithReasoning( -// "If a train travels 120 km in 1.5 hours, what is its average speed?", -// ReasoningEffort.HIGH); -// assertThat(response).isNotNull(); -// assertThat(response.reasoning().isPresent()).isTrue(); -// assertThat(response.reasoning().get().effort()).contains(ReasoningEffort.HIGH); -// final var reasoning = -// response.output().stream().filter(ResponseOutputItem::isReasoning).findFirst(); -// assertThat(reasoning).isPresent(); -// assertThat(reasoning.get().asReasoning().summary()).isNotEmpty(); -// final var message = -// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// assertThat(message.get().asMessage().content().get(0).asOutputText().text()).contains("80"); -// } -// -// @Test -// void testStructuredOutput() throws JsonProcessingException { -// final var response = -// service.createStructuredResponse("Extract the name and age from: John is 30 years old."); -// assertThat(response).isNotNull(); -// final var message = -// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// final var text = message.get().asMessage().content().get(0).asOutputText().text(); -// final var parsed = new ObjectMapper().readValue(text, Map.class); -// assertThat(parsed.get("name")).isEqualTo("John"); -// assertThat(parsed.get("age")).isEqualTo(30); -// } -// -// @Test -// void testStatelessMultiTurn() { -// final var messages = -// List.of( -// ResponseInputItem.ofEasyInputMessage( -// EasyInputMessage.builder() -// .role(EasyInputMessage.Role.USER) -// .content("Count to 3 in Spanish.") -// .build()), -// ResponseInputItem.ofEasyInputMessage( -// EasyInputMessage.builder() -// .role(EasyInputMessage.Role.ASSISTANT) -// .content("Uno, dos, tres.") -// .build()), -// ResponseInputItem.ofEasyInputMessage( -// EasyInputMessage.builder() -// .role(EasyInputMessage.Role.USER) -// .content("Now count to 5.") -// .build())); -// final var response = service.createStatelessMultiTurnResponse(messages); -// assertThat(response).isNotNull(); -// final var message = -// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// final var text = message.get().asMessage().content().get(0).asOutputText().text(); -// assertThat(text).containsIgnoringCase("cinco"); -// } -// -// @Test -// void testTruncation() { -// final var first = -// service.createPersistentResponse("Write a short poem about the ocean.", false); -// assertThat(first.id()).isNotBlank(); -// -// final var response = -// service.createResponseWithTruncation("Summarize what I asked.", first.id()); -// assertThat(response).isNotNull(); -// assertThat(response.previousResponseId()).contains(first.id()); -// assertThat(response.truncation()).contains(Truncation.AUTO); -// final var message = -// response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); -// assertThat(message).isPresent(); -// assertThat(message.get().asMessage().content()).isNotEmpty(); -// } -// -// @Test -// void testPromptCaching() { -// final var cacheKey = "ai-sdk-java-test-cache-key"; -// final var prompt = "What is the capital of France?"; -// -// // First call populates the cache -// final var first = service.createCachedResponse(prompt, cacheKey); -// assertThat(first).isNotNull(); -// assertThat(first.promptCacheKey()).contains(cacheKey); -// assertThat(first.usage().isPresent()).isTrue(); -// -// // Second call with the same key — cache hit is server-side and not guaranteed in tests, so we -// // only assert the key is echoed back and usage is accessible -// final var second = service.createCachedResponse(prompt, cacheKey); -// assertThat(second).isNotNull(); -// assertThat(second.promptCacheKey()).contains(cacheKey); -// assertThat(second.usage().isPresent()).isTrue(); -// assertThat(second.usage().get().inputTokensDetails().cachedTokens()).isGreaterThanOrEqualTo(0); -// } + // @BeforeEach + // void setUp() { + // service = new AiCoreOpenAiService(); + // } + // + // @Test + // void testCreateResponse() { + // final var response = service.createResponse("What is the capital of France?"); + // assertThat(response).isNotNull(); + // assertThat(response.output()).isNotNull(); + // + // final var reasoningOutput = response.output().get(0); + // assertThat(reasoningOutput.isReasoning()).isTrue(); + // final var messageOutput = response.output().get(1); + // assertThat(messageOutput.isMessage()).isTrue(); + // assertThat(messageOutput.asMessage().content()).isNotEmpty(); + // final var content = messageOutput.asMessage().content().get(0); + // assertThat(content.isOutputText()).isTrue(); + // assertThat(content.asOutputText().text()).containsIgnoringCase("Paris"); + // } + // + // @Test + // void testCreateStreamingResponse() { + // try (var stream = service.createStreamingResponse("What is the capital of France?")) { + // stream.stream() + // .forEach( + // event -> { + // assertThat(event.isValid()).isTrue(); + // + // if (event.isCompleted()) { + // final var response = event.asCompleted().response(); + // assertThat(response.output()).isNotEmpty(); + // final var message = + // + // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // final var content = message.get().asMessage().content(); + // assertThat(content).isNotEmpty(); + // assertThat(content.get(0).isOutputText()).isTrue(); + // + // assertThat(content.get(0).asOutputText().text()).containsIgnoringCase("Paris"); + // } + // }); + // } + // } + // + // @Test + // void testRetrieveResponse() { + // final var created = service.createPersistentResponse("Say hi.", false); + // assertThat(created.id()).isNotBlank(); + // + // final var retrieved = service.retrieveResponse(created.id()); + // assertThat(retrieved).isNotNull(); + // assertThat(retrieved.id()).isEqualTo(created.id()); + // + // // Cleanup + // service.deleteResponse(created.id()); + // } + // + // @Test + // void testCancelResponse() { + // final var created = + // service.createPersistentResponse( + // "Write an extremely detailed 10-page essay covering the full history of distributed" + // + " systems from the 1960s to today. Include subsections, citations, and + // concrete" + // + " examples for every decade.", + // true); + // assertThat(created.id()).isNotBlank(); + // + // final var cancelled = service.cancelResponse(created.id()); + // assertThat(cancelled).isNotNull(); + // assertThat(cancelled.id()).isEqualTo(created.id()); + // assertThat(cancelled.status()).contains(ResponseStatus.CANCELLED); + // + // // Cleanup + // service.deleteResponse(created.id()); + // } + // + // @Test + // void testDeleteResponse() { + // final var created = service.createPersistentResponse("Say hi.", false); + // assertThat(created.id()).isNotBlank(); + // + // assertThatNoException().isThrownBy(() -> service.deleteResponse(created.id())); + // } + // + // @Test + // void testBackgroundMode() throws InterruptedException { + // final var response = + // service.createBackgroundResponseAndPoll("Write a short poem about the sea."); + // assertThat(response).isNotNull(); + // assertThat(response.status()) + // .satisfiesAnyOf( + // s -> assertThat(s).contains(ResponseStatus.COMPLETED), + // s -> assertThat(s).contains(ResponseStatus.FAILED)); + // assertThat(response.output()).isNotEmpty(); + // final var message = + // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // assertThat(message.get().asMessage().content().get(0).asOutputText().text()).isNotBlank(); + // } + // + // @Test + // void testMultiTurnResponse() { + // final var first = service.createPersistentResponse("Count to 3 in Spanish.", false); + // assertThat(first.id()).isNotBlank(); + // + // final var followUp = + // service.createMultiTurnResponse("What did I just ask you to count to?", first.id()); + // assertThat(followUp).isNotNull(); + // assertThat(followUp.previousResponseId()).contains(first.id()); + // final var message = + // followUp.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // assertThat( + // message + // .get() + // .asMessage() + // .content() + // .get(0) + // .asOutputText() + // .text() + // .toLowerCase(Locale.ROOT)) + // .containsAnyOf("three", "3"); + // } + // + // @Test + // void testToolCalling() { + // final var response = service.createResponseWithTools("What is the weather in Berlin + // today?"); + // assertThat(response).isNotNull(); + // assertThat(response.output()).isNotEmpty(); + // final var functionCall = + // response.output().stream().filter(ResponseOutputItem::isFunctionCall).findFirst(); + // assertThat(functionCall).isPresent(); + // assertThat(functionCall.get().asFunctionCall().name()).isEqualTo("get_weather"); + // assertThat(functionCall.get().asFunctionCall().arguments()).contains("Berlin"); + // } + // + // @Test + // void testReasoningEffort() { + // final var response = + // service.createResponseWithReasoning( + // "If a train travels 120 km in 1.5 hours, what is its average speed?", + // ReasoningEffort.HIGH); + // assertThat(response).isNotNull(); + // assertThat(response.reasoning().isPresent()).isTrue(); + // assertThat(response.reasoning().get().effort()).contains(ReasoningEffort.HIGH); + // final var reasoning = + // response.output().stream().filter(ResponseOutputItem::isReasoning).findFirst(); + // assertThat(reasoning).isPresent(); + // assertThat(reasoning.get().asReasoning().summary()).isNotEmpty(); + // final var message = + // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // assertThat(message.get().asMessage().content().get(0).asOutputText().text()).contains("80"); + // } + // + // @Test + // void testStructuredOutput() throws JsonProcessingException { + // final var response = + // service.createStructuredResponse("Extract the name and age from: John is 30 years + // old."); + // assertThat(response).isNotNull(); + // final var message = + // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // final var text = message.get().asMessage().content().get(0).asOutputText().text(); + // final var parsed = new ObjectMapper().readValue(text, Map.class); + // assertThat(parsed.get("name")).isEqualTo("John"); + // assertThat(parsed.get("age")).isEqualTo(30); + // } + // + // @Test + // void testStatelessMultiTurn() { + // final var messages = + // List.of( + // ResponseInputItem.ofEasyInputMessage( + // EasyInputMessage.builder() + // .role(EasyInputMessage.Role.USER) + // .content("Count to 3 in Spanish.") + // .build()), + // ResponseInputItem.ofEasyInputMessage( + // EasyInputMessage.builder() + // .role(EasyInputMessage.Role.ASSISTANT) + // .content("Uno, dos, tres.") + // .build()), + // ResponseInputItem.ofEasyInputMessage( + // EasyInputMessage.builder() + // .role(EasyInputMessage.Role.USER) + // .content("Now count to 5.") + // .build())); + // final var response = service.createStatelessMultiTurnResponse(messages); + // assertThat(response).isNotNull(); + // final var message = + // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // final var text = message.get().asMessage().content().get(0).asOutputText().text(); + // assertThat(text).containsIgnoringCase("cinco"); + // } + // + // @Test + // void testTruncation() { + // final var first = + // service.createPersistentResponse("Write a short poem about the ocean.", false); + // assertThat(first.id()).isNotBlank(); + // + // final var response = + // service.createResponseWithTruncation("Summarize what I asked.", first.id()); + // assertThat(response).isNotNull(); + // assertThat(response.previousResponseId()).contains(first.id()); + // assertThat(response.truncation()).contains(Truncation.AUTO); + // final var message = + // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + // assertThat(message).isPresent(); + // assertThat(message.get().asMessage().content()).isNotEmpty(); + // } + // + // @Test + // void testPromptCaching() { + // final var cacheKey = "ai-sdk-java-test-cache-key"; + // final var prompt = "What is the capital of France?"; + // + // // First call populates the cache + // final var first = service.createCachedResponse(prompt, cacheKey); + // assertThat(first).isNotNull(); + // assertThat(first.promptCacheKey()).contains(cacheKey); + // assertThat(first.usage().isPresent()).isTrue(); + // + // // Second call with the same key — cache hit is server-side and not guaranteed in tests, so + // we + // // only assert the key is echoed back and usage is accessible + // final var second = service.createCachedResponse(prompt, cacheKey); + // assertThat(second).isNotNull(); + // assertThat(second.promptCacheKey()).contains(cacheKey); + // assertThat(second.usage().isPresent()).isTrue(); + // + // assertThat(second.usage().get().inputTokensDetails().cachedTokens()).isGreaterThanOrEqualTo(0); + // } } From 6596b8509891d090bde3dc3ca70a8cff402a4e99 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 14 Jul 2026 13:49:54 +0200 Subject: [PATCH 6/9] silence --- .github/workflows/e2e-test.yaml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index 308e49e2f..420e9103a 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -101,19 +101,19 @@ jobs: # print response body with headers to stdout. q:body only O:print -:stdout S:headers run: wget -qO- -S localhost:8080 - - name: "Slack Notification" - if: failure() - uses: slackapi/slack-github-action@v3.0.3 - with: - webhook: ${{ secrets.SLACK_WEBHOOK }} - webhook-type: incoming-webhook - payload: | - blocks: - - type: "section" - text: - type: "mrkdwn" - text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " - - type: "section" - text: - type: "plain_text" - text: "${{ steps.run_tests.outputs.error_message }} " +# - name: "Slack Notification" +# if: failure() +# uses: slackapi/slack-github-action@v3.0.3 +# with: +# webhook: ${{ secrets.SLACK_WEBHOOK }} +# webhook-type: incoming-webhook +# payload: | +# blocks: +# - type: "section" +# text: +# type: "mrkdwn" +# text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " +# - type: "section" +# text: +# type: "plain_text" +# text: "${{ steps.run_tests.outputs.error_message }} " From 50faf2b5df2bf4814ebe8454730e23614e55d378 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 14 Jul 2026 14:10:47 +0200 Subject: [PATCH 7/9] remove potential fix to test --- .github/workflows/e2e-test.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index 420e9103a..a7db81d5e 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -55,9 +55,7 @@ jobs: awk '/Results:/, /----/' mvn_output.log > test_error.log || true # true ensures the step doesn't fail if no match is found. ERROR_MSG=$(cat test_error.log | tail +4 | head -n -4 | awk 'BEGIN{RS=""} {gsub(/"/, "\\\""); gsub(/Expecting KeySet:.*but could not find the following element\(s\):/, "Missing element: "); printf "%s\n", $0}') echo "$ERROR_MSG" - echo "error_message<> $GITHUB_OUTPUT - echo "$ERROR_MSG" >> $GITHUB_OUTPUT - echo "GITHUB_OUTPUT_EOF" >> $GITHUB_OUTPUT + echo "error_message=$ERROR_MSG" >> $GITHUB_OUTPUT if grep -q "BUILD FAILURE" mvn_output.log; then echo "Maven build failed." From 37b04f51a236babe95567253e0d61abefba5aa5a Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 15 Jul 2026 13:23:29 +0200 Subject: [PATCH 8/9] clean up a lot of logs --- .../controllers/OrchestrationController.java | 32 +- .../SpringAiOrchestrationController.java | 7 +- .../sdk/app/controllers/AiCoreOpenAiTest.java | 495 +++++++++--------- .../app/controllers/OpenAiDeprecatedTest.java | 3 - .../ai/sdk/app/controllers/OpenAiTest.java | 3 - .../app/controllers/OrchestrationTest.java | 5 - .../app/controllers/SpringAiOpenAiTest.java | 4 - .../SpringAiOrchestrationTest.java | 5 +- 8 files changed, 274 insertions(+), 280 deletions(-) diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java index bff2c8e1d..18a033bd1 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java @@ -63,11 +63,7 @@ ResponseEntity streamChatCompletion() { final Runnable consumeStream = () -> { try (stream) { - stream.forEach( - deltaMessage -> { - log.info("Service: {}", deltaMessage); - send(emitter, deltaMessage); - }); + stream.forEach(deltaMessage -> send(emitter, deltaMessage)); } finally { emitter.complete(); } @@ -191,7 +187,7 @@ Object inputFiltering( try { response = service.inputFiltering(policy); } catch (OrchestrationFilterException.Input e) { - final var msg = + final var errorMessage = new StringBuilder( "[Http %d] Failed to obtain a response as the content was flagged by input filter. " .formatted(e.getStatusCode())); @@ -199,10 +195,11 @@ Object inputFiltering( Optional.ofNullable(e.getAzureContentSafetyInput()) .map(AzureContentSafetyInput::getViolence) .filter(rating -> rating.compareTo(policy.getAzureThreshold()) > 0) - .ifPresent(rating -> msg.append("Violence score %d".formatted(rating.getValue()))); + .ifPresent( + rating -> errorMessage.append("Violence score %d".formatted(rating.getValue()))); - log.debug(msg.toString(), e); - return ResponseEntity.internalServerError().body(msg.toString()); + log.error(errorMessage.toString(), e); + return ResponseEntity.internalServerError().body(errorMessage.toString()); } if ("json".equals(format)) { @@ -224,17 +221,18 @@ Object outputFiltering( try { content = response.getContent(); } catch (OrchestrationFilterException.Output e) { - final var msg = + final var errorMessage = new StringBuilder( "Failed to obtain a response as the content was flagged by output filter. "); Optional.ofNullable(e.getAzureContentSafetyOutput()) .map(AzureContentSafetyOutput::getViolence) .filter(rating -> rating.compareTo(policy.getAzureThreshold()) > 0) - .ifPresent(rating -> msg.append("Violence score %d ".formatted(rating.getValue()))); + .ifPresent( + rating -> errorMessage.append("Violence score %d ".formatted(rating.getValue()))); - log.debug(msg.toString(), e); - return ResponseEntity.internalServerError().body(msg.toString()); + log.error(errorMessage.toString(), e); + return ResponseEntity.internalServerError().body(errorMessage.toString()); } if ("json".equals(format)) { @@ -253,14 +251,14 @@ Object llamaGuardInputFiltering( try { response = service.llamaGuardInputFilter(enabled); } catch (OrchestrationFilterException.Input e) { - var msg = + var errorMessage = "[Http %d] Failed to obtain a response as the content was flagged by input filter. " .formatted(e.getStatusCode()); if (e.getLlamaGuard38b() != null) { - msg += " Violent crimes are %s".formatted(e.getLlamaGuard38b().isViolentCrimes()); + errorMessage += " Violent crimes are %s".formatted(e.getLlamaGuard38b().isViolentCrimes()); } - log.debug(msg, e); - return ResponseEntity.internalServerError().body(msg); + log.error(errorMessage, e); + return ResponseEntity.internalServerError().body(errorMessage); } if ("json".equals(format)) { diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java index a775f00d6..e4226674c 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java @@ -70,9 +70,10 @@ Object inputFiltering( try { response = service.inputFiltering(policy); } catch (OrchestrationClientException e) { - final var msg = "Failed to obtain a response as the content was flagged by input filter."; - log.debug(msg, e); - return ResponseEntity.internalServerError().body(msg); + final var errorMessage = + "Failed to obtain a response as the content was flagged by input filter."; + log.error(errorMessage, e); + return ResponseEntity.internalServerError().body(errorMessage); } if ("json".equals(format)) { diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java index 6f4f2cd51..6b9c86bf2 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/AiCoreOpenAiTest.java @@ -1,249 +1,260 @@ package com.sap.ai.sdk.app.controllers; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.openai.models.ReasoningEffort; +import com.openai.models.responses.EasyInputMessage; +import com.openai.models.responses.Response.Truncation; +import com.openai.models.responses.ResponseInputItem; +import com.openai.models.responses.ResponseOutputItem; +import com.openai.models.responses.ResponseStatus; +import com.sap.ai.sdk.app.services.AiCoreOpenAiService; +import java.util.List; +import java.util.Locale; +import java.util.Map; import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; @Slf4j class AiCoreOpenAiTest { - // AiCoreOpenAiService service; - - // @BeforeEach - // void setUp() { - // service = new AiCoreOpenAiService(); - // } - // - // @Test - // void testCreateResponse() { - // final var response = service.createResponse("What is the capital of France?"); - // assertThat(response).isNotNull(); - // assertThat(response.output()).isNotNull(); - // - // final var reasoningOutput = response.output().get(0); - // assertThat(reasoningOutput.isReasoning()).isTrue(); - // final var messageOutput = response.output().get(1); - // assertThat(messageOutput.isMessage()).isTrue(); - // assertThat(messageOutput.asMessage().content()).isNotEmpty(); - // final var content = messageOutput.asMessage().content().get(0); - // assertThat(content.isOutputText()).isTrue(); - // assertThat(content.asOutputText().text()).containsIgnoringCase("Paris"); - // } - // - // @Test - // void testCreateStreamingResponse() { - // try (var stream = service.createStreamingResponse("What is the capital of France?")) { - // stream.stream() - // .forEach( - // event -> { - // assertThat(event.isValid()).isTrue(); - // - // if (event.isCompleted()) { - // final var response = event.asCompleted().response(); - // assertThat(response.output()).isNotEmpty(); - // final var message = - // - // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // final var content = message.get().asMessage().content(); - // assertThat(content).isNotEmpty(); - // assertThat(content.get(0).isOutputText()).isTrue(); - // - // assertThat(content.get(0).asOutputText().text()).containsIgnoringCase("Paris"); - // } - // }); - // } - // } - // - // @Test - // void testRetrieveResponse() { - // final var created = service.createPersistentResponse("Say hi.", false); - // assertThat(created.id()).isNotBlank(); - // - // final var retrieved = service.retrieveResponse(created.id()); - // assertThat(retrieved).isNotNull(); - // assertThat(retrieved.id()).isEqualTo(created.id()); - // - // // Cleanup - // service.deleteResponse(created.id()); - // } - // - // @Test - // void testCancelResponse() { - // final var created = - // service.createPersistentResponse( - // "Write an extremely detailed 10-page essay covering the full history of distributed" - // + " systems from the 1960s to today. Include subsections, citations, and - // concrete" - // + " examples for every decade.", - // true); - // assertThat(created.id()).isNotBlank(); - // - // final var cancelled = service.cancelResponse(created.id()); - // assertThat(cancelled).isNotNull(); - // assertThat(cancelled.id()).isEqualTo(created.id()); - // assertThat(cancelled.status()).contains(ResponseStatus.CANCELLED); - // - // // Cleanup - // service.deleteResponse(created.id()); - // } - // - // @Test - // void testDeleteResponse() { - // final var created = service.createPersistentResponse("Say hi.", false); - // assertThat(created.id()).isNotBlank(); - // - // assertThatNoException().isThrownBy(() -> service.deleteResponse(created.id())); - // } - // - // @Test - // void testBackgroundMode() throws InterruptedException { - // final var response = - // service.createBackgroundResponseAndPoll("Write a short poem about the sea."); - // assertThat(response).isNotNull(); - // assertThat(response.status()) - // .satisfiesAnyOf( - // s -> assertThat(s).contains(ResponseStatus.COMPLETED), - // s -> assertThat(s).contains(ResponseStatus.FAILED)); - // assertThat(response.output()).isNotEmpty(); - // final var message = - // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // assertThat(message.get().asMessage().content().get(0).asOutputText().text()).isNotBlank(); - // } - // - // @Test - // void testMultiTurnResponse() { - // final var first = service.createPersistentResponse("Count to 3 in Spanish.", false); - // assertThat(first.id()).isNotBlank(); - // - // final var followUp = - // service.createMultiTurnResponse("What did I just ask you to count to?", first.id()); - // assertThat(followUp).isNotNull(); - // assertThat(followUp.previousResponseId()).contains(first.id()); - // final var message = - // followUp.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // assertThat( - // message - // .get() - // .asMessage() - // .content() - // .get(0) - // .asOutputText() - // .text() - // .toLowerCase(Locale.ROOT)) - // .containsAnyOf("three", "3"); - // } - // - // @Test - // void testToolCalling() { - // final var response = service.createResponseWithTools("What is the weather in Berlin - // today?"); - // assertThat(response).isNotNull(); - // assertThat(response.output()).isNotEmpty(); - // final var functionCall = - // response.output().stream().filter(ResponseOutputItem::isFunctionCall).findFirst(); - // assertThat(functionCall).isPresent(); - // assertThat(functionCall.get().asFunctionCall().name()).isEqualTo("get_weather"); - // assertThat(functionCall.get().asFunctionCall().arguments()).contains("Berlin"); - // } - // - // @Test - // void testReasoningEffort() { - // final var response = - // service.createResponseWithReasoning( - // "If a train travels 120 km in 1.5 hours, what is its average speed?", - // ReasoningEffort.HIGH); - // assertThat(response).isNotNull(); - // assertThat(response.reasoning().isPresent()).isTrue(); - // assertThat(response.reasoning().get().effort()).contains(ReasoningEffort.HIGH); - // final var reasoning = - // response.output().stream().filter(ResponseOutputItem::isReasoning).findFirst(); - // assertThat(reasoning).isPresent(); - // assertThat(reasoning.get().asReasoning().summary()).isNotEmpty(); - // final var message = - // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // assertThat(message.get().asMessage().content().get(0).asOutputText().text()).contains("80"); - // } - // - // @Test - // void testStructuredOutput() throws JsonProcessingException { - // final var response = - // service.createStructuredResponse("Extract the name and age from: John is 30 years - // old."); - // assertThat(response).isNotNull(); - // final var message = - // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // final var text = message.get().asMessage().content().get(0).asOutputText().text(); - // final var parsed = new ObjectMapper().readValue(text, Map.class); - // assertThat(parsed.get("name")).isEqualTo("John"); - // assertThat(parsed.get("age")).isEqualTo(30); - // } - // - // @Test - // void testStatelessMultiTurn() { - // final var messages = - // List.of( - // ResponseInputItem.ofEasyInputMessage( - // EasyInputMessage.builder() - // .role(EasyInputMessage.Role.USER) - // .content("Count to 3 in Spanish.") - // .build()), - // ResponseInputItem.ofEasyInputMessage( - // EasyInputMessage.builder() - // .role(EasyInputMessage.Role.ASSISTANT) - // .content("Uno, dos, tres.") - // .build()), - // ResponseInputItem.ofEasyInputMessage( - // EasyInputMessage.builder() - // .role(EasyInputMessage.Role.USER) - // .content("Now count to 5.") - // .build())); - // final var response = service.createStatelessMultiTurnResponse(messages); - // assertThat(response).isNotNull(); - // final var message = - // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // final var text = message.get().asMessage().content().get(0).asOutputText().text(); - // assertThat(text).containsIgnoringCase("cinco"); - // } - // - // @Test - // void testTruncation() { - // final var first = - // service.createPersistentResponse("Write a short poem about the ocean.", false); - // assertThat(first.id()).isNotBlank(); - // - // final var response = - // service.createResponseWithTruncation("Summarize what I asked.", first.id()); - // assertThat(response).isNotNull(); - // assertThat(response.previousResponseId()).contains(first.id()); - // assertThat(response.truncation()).contains(Truncation.AUTO); - // final var message = - // response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); - // assertThat(message).isPresent(); - // assertThat(message.get().asMessage().content()).isNotEmpty(); - // } - // - // @Test - // void testPromptCaching() { - // final var cacheKey = "ai-sdk-java-test-cache-key"; - // final var prompt = "What is the capital of France?"; - // - // // First call populates the cache - // final var first = service.createCachedResponse(prompt, cacheKey); - // assertThat(first).isNotNull(); - // assertThat(first.promptCacheKey()).contains(cacheKey); - // assertThat(first.usage().isPresent()).isTrue(); - // - // // Second call with the same key — cache hit is server-side and not guaranteed in tests, so - // we - // // only assert the key is echoed back and usage is accessible - // final var second = service.createCachedResponse(prompt, cacheKey); - // assertThat(second).isNotNull(); - // assertThat(second.promptCacheKey()).contains(cacheKey); - // assertThat(second.usage().isPresent()).isTrue(); - // - // assertThat(second.usage().get().inputTokensDetails().cachedTokens()).isGreaterThanOrEqualTo(0); - // } + AiCoreOpenAiService service; + + @BeforeEach + void setUp() { + service = new AiCoreOpenAiService(); + } + + @Test + void testCreateResponse() { + final var response = service.createResponse("What is the capital of France?"); + assertThat(response).isNotNull(); + assertThat(response.output()).isNotNull(); + + final var reasoningOutput = response.output().get(0); + assertThat(reasoningOutput.isReasoning()).isTrue(); + final var messageOutput = response.output().get(1); + assertThat(messageOutput.isMessage()).isTrue(); + assertThat(messageOutput.asMessage().content()).isNotEmpty(); + final var content = messageOutput.asMessage().content().get(0); + assertThat(content.isOutputText()).isTrue(); + assertThat(content.asOutputText().text()).containsIgnoringCase("Paris"); + } + + @Test + void testCreateStreamingResponse() { + try (var stream = service.createStreamingResponse("What is the capital of France?")) { + stream.stream() + .forEach( + event -> { + assertThat(event.isValid()).isTrue(); + + if (event.isCompleted()) { + final var response = event.asCompleted().response(); + assertThat(response.output()).isNotEmpty(); + final var message = + response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + final var content = message.get().asMessage().content(); + assertThat(content).isNotEmpty(); + assertThat(content.get(0).isOutputText()).isTrue(); + assertThat(content.get(0).asOutputText().text()).containsIgnoringCase("Paris"); + } + }); + } + } + + @Test + void testRetrieveResponse() { + final var created = service.createPersistentResponse("Say hi.", false); + assertThat(created.id()).isNotBlank(); + + final var retrieved = service.retrieveResponse(created.id()); + assertThat(retrieved).isNotNull(); + assertThat(retrieved.id()).isEqualTo(created.id()); + + // Cleanup + service.deleteResponse(created.id()); + } + + @Test + void testCancelResponse() { + final var created = + service.createPersistentResponse( + "Write an extremely detailed 10-page essay covering the full history of distributed" + + " systems from the 1960s to today. Include subsections, citations, and concrete" + + " examples for every decade.", + true); + assertThat(created.id()).isNotBlank(); + + final var cancelled = service.cancelResponse(created.id()); + assertThat(cancelled).isNotNull(); + assertThat(cancelled.id()).isEqualTo(created.id()); + assertThat(cancelled.status()).contains(ResponseStatus.CANCELLED); + + // Cleanup + service.deleteResponse(created.id()); + } + + @Test + void testDeleteResponse() { + final var created = service.createPersistentResponse("Say hi.", false); + assertThat(created.id()).isNotBlank(); + + assertThatNoException().isThrownBy(() -> service.deleteResponse(created.id())); + } + + @Test + void testBackgroundMode() throws InterruptedException { + final var response = + service.createBackgroundResponseAndPoll("Write a short poem about the sea."); + assertThat(response).isNotNull(); + assertThat(response.status()) + .satisfiesAnyOf( + s -> assertThat(s).contains(ResponseStatus.COMPLETED), + s -> assertThat(s).contains(ResponseStatus.FAILED)); + assertThat(response.output()).isNotEmpty(); + final var message = + response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + assertThat(message.get().asMessage().content().get(0).asOutputText().text()).isNotBlank(); + } + + @Test + void testMultiTurnResponse() { + final var first = service.createPersistentResponse("Count to 3 in Spanish.", false); + assertThat(first.id()).isNotBlank(); + + final var followUp = + service.createMultiTurnResponse("What did I just ask you to count to?", first.id()); + assertThat(followUp).isNotNull(); + assertThat(followUp.previousResponseId()).contains(first.id()); + final var message = + followUp.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + assertThat( + message + .get() + .asMessage() + .content() + .get(0) + .asOutputText() + .text() + .toLowerCase(Locale.ROOT)) + .containsAnyOf("three", "3"); + } + + @Test + void testToolCalling() { + final var response = service.createResponseWithTools("What is the weather in Berlin today?"); + assertThat(response).isNotNull(); + assertThat(response.output()).isNotEmpty(); + final var functionCall = + response.output().stream().filter(ResponseOutputItem::isFunctionCall).findFirst(); + assertThat(functionCall).isPresent(); + assertThat(functionCall.get().asFunctionCall().name()).isEqualTo("get_weather"); + assertThat(functionCall.get().asFunctionCall().arguments()).contains("Berlin"); + } + + @Test + void testReasoningEffort() { + final var response = + service.createResponseWithReasoning( + "If a train travels 120 km in 1.5 hours, what is its average speed?", + ReasoningEffort.HIGH); + assertThat(response).isNotNull(); + assertThat(response.reasoning().isPresent()).isTrue(); + assertThat(response.reasoning().get().effort()).contains(ReasoningEffort.HIGH); + final var reasoning = + response.output().stream().filter(ResponseOutputItem::isReasoning).findFirst(); + assertThat(reasoning).isPresent(); + assertThat(reasoning.get().asReasoning().summary()).isNotEmpty(); + final var message = + response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + assertThat(message.get().asMessage().content().get(0).asOutputText().text()).contains("80"); + } + + @Test + void testStructuredOutput() throws JsonProcessingException { + final var response = + service.createStructuredResponse("Extract the name and age from: John is 30 years old."); + assertThat(response).isNotNull(); + final var message = + response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + final var text = message.get().asMessage().content().get(0).asOutputText().text(); + final var parsed = new ObjectMapper().readValue(text, Map.class); + assertThat(parsed.get("name")).isEqualTo("John"); + assertThat(parsed.get("age")).isEqualTo(30); + } + + @Test + void testStatelessMultiTurn() { + final var messages = + List.of( + ResponseInputItem.ofEasyInputMessage( + EasyInputMessage.builder() + .role(EasyInputMessage.Role.USER) + .content("Count to 3 in Spanish.") + .build()), + ResponseInputItem.ofEasyInputMessage( + EasyInputMessage.builder() + .role(EasyInputMessage.Role.ASSISTANT) + .content("Uno, dos, tres.") + .build()), + ResponseInputItem.ofEasyInputMessage( + EasyInputMessage.builder() + .role(EasyInputMessage.Role.USER) + .content("Now count to 5.") + .build())); + final var response = service.createStatelessMultiTurnResponse(messages); + assertThat(response).isNotNull(); + final var message = + response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + final var text = message.get().asMessage().content().get(0).asOutputText().text(); + assertThat(text).containsIgnoringCase("cinco"); + } + + @Test + void testTruncation() { + final var first = + service.createPersistentResponse("Write a short poem about the ocean.", false); + assertThat(first.id()).isNotBlank(); + + final var response = + service.createResponseWithTruncation("Summarize what I asked.", first.id()); + assertThat(response).isNotNull(); + assertThat(response.previousResponseId()).contains(first.id()); + assertThat(response.truncation()).contains(Truncation.AUTO); + final var message = + response.output().stream().filter(ResponseOutputItem::isMessage).findFirst(); + assertThat(message).isPresent(); + assertThat(message.get().asMessage().content()).isNotEmpty(); + } + + @Test + void testPromptCaching() { + final var cacheKey = "ai-sdk-java-test-cache-key"; + final var prompt = "What is the capital of France?"; + + // First call populates the cache + final var first = service.createCachedResponse(prompt, cacheKey); + assertThat(first).isNotNull(); + assertThat(first.promptCacheKey()).contains(cacheKey); + assertThat(first.usage().isPresent()).isTrue(); + + // Second call with the same key — cache hit is server-side and not guaranteed in tests, so we + // only assert the key is echoed back and usage is accessible + final var second = service.createCachedResponse(prompt, cacheKey); + assertThat(second).isNotNull(); + assertThat(second.promptCacheKey()).contains(cacheKey); + assertThat(second.usage().isPresent()).isTrue(); + + assertThat(second.usage().get().inputTokensDetails().cachedTokens()).isGreaterThanOrEqualTo(0); + } } diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiDeprecatedTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiDeprecatedTest.java index 3d6aac716..413a1f235 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiDeprecatedTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiDeprecatedTest.java @@ -9,11 +9,9 @@ import com.sap.ai.sdk.foundationmodels.openai.model.OpenAiChatCompletionParameters; import com.sap.ai.sdk.foundationmodels.openai.model.OpenAiChatMessage.OpenAiChatUserMessage; import java.util.concurrent.atomic.AtomicInteger; -import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -@Slf4j class OpenAiDeprecatedTest { OpenAiServiceDeprecated service; @@ -57,7 +55,6 @@ void streamChatCompletion() { .forEach( delta -> { final String deltaContent = delta.getDeltaContent(); - log.info("delta: {}", delta); if (!deltaContent.isEmpty()) { filledDeltaCount.incrementAndGet(); } diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiTest.java index 5548ce2cb..37f43ad11 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OpenAiTest.java @@ -12,11 +12,9 @@ import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -@Slf4j class OpenAiTest { OpenAiService service; @@ -63,7 +61,6 @@ void streamChatCompletion() { delta -> { usageRef.compareAndExchange(null, delta.getCompletionUsage()); final String deltaContent = delta.getDeltaContent(); - log.info("delta: {}", delta); if (!deltaContent.isEmpty()) { filledDeltaCount.incrementAndGet(); } diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java index 92d27ee15..b9e931fcd 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java @@ -73,7 +73,6 @@ void testStreamChatCompletion() { // foreach consumes all elements, closing the stream at the end .forEach( delta -> { - log.info("delta: {}", delta); if (!delta.isEmpty()) { filledDeltaCount.incrementAndGet(); } @@ -626,7 +625,6 @@ void testCompletionWithFallbackStreaming() { val filledDeltaCount = new AtomicInteger(0); stream.forEach( delta -> { - log.info("delta: {}", delta); if (!delta.isEmpty()) { filledDeltaCount.incrementAndGet(); } @@ -640,7 +638,6 @@ void testStreamDeltasWithInlineConfig() { val filledDeltaCount = new AtomicInteger(0); stream.forEach( delta -> { - log.info("delta: {}", delta); if (!delta.getDeltaContent().isEmpty()) { filledDeltaCount.incrementAndGet(); } @@ -654,7 +651,6 @@ void testStreamDeltasWithReferenceById() { val filledDeltaCount = new AtomicInteger(0); stream.forEach( delta -> { - log.info("delta: {}", delta); if (!delta.getDeltaContent().isEmpty()) { filledDeltaCount.incrementAndGet(); } @@ -668,7 +664,6 @@ void testStreamDeltasWithReferenceByScenario() { val filledDeltaCount = new AtomicInteger(0); stream.forEach( delta -> { - log.info("delta: {}", delta); if (!delta.getDeltaContent().isEmpty()) { filledDeltaCount.incrementAndGet(); } diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOpenAiTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOpenAiTest.java index 46c6f199b..e1fd24147 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOpenAiTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOpenAiTest.java @@ -13,8 +13,6 @@ class SpringAiOpenAiTest { private final SpringAiOpenAiService service = new SpringAiOpenAiService(); - private static final org.slf4j.Logger log = - org.slf4j.LoggerFactory.getLogger(SpringAiOrchestrationTest.class); @Test void testEmbedStrings() { @@ -46,7 +44,6 @@ void testStreamChatCompletion() { // foreach consumes all elements, closing the stream at the end .forEach( delta -> { - log.info("delta: {}", delta); String text = delta.getResult().getOutput().getText(); if (text != null && !text.isEmpty()) { filledDeltaCount.incrementAndGet(); @@ -86,7 +83,6 @@ void testChatMemory() { ChatResponse response = service.chatMemory(); assertThat(response).isNotNull(); String text = response.getResult().getOutput().getText(); - log.info(text); assertThat(text) .containsAnyOf( "French", "onion", "pastries", "cheese", "baguette", "coq au vin", "foie gras"); diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationTest.java index 4727d0ad4..635a9d5ee 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationTest.java @@ -35,8 +35,8 @@ void testStreamChatCompletion() { // foreach consumes all elements, closing the stream at the end .forEach( delta -> { - log.info("delta: {}", delta); - if (!delta.getResult().getOutput().getText().isEmpty()) { + final var text = delta.getResult().getOutput().getText(); + if (text != null && !text.isEmpty()) { filledDeltaCount.incrementAndGet(); } }); @@ -155,7 +155,6 @@ void testChatMemory() { ChatResponse response = service.chatMemory(); assertThat(response).isNotNull(); String text = response.getResult().getOutput().getText(); - log.info(text); assertThat(text) .containsAnyOf( "French", "onion", "pastries", "cheese", "baguette", "coq au vin", "foie gras"); From f633e5442c8e7add2ebffb09fceeaab9715558a4 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 15 Jul 2026 14:32:45 +0200 Subject: [PATCH 9/9] test --- .github/workflows/e2e-test.yaml | 36 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index a7db81d5e..308e49e2f 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -55,7 +55,9 @@ jobs: awk '/Results:/, /----/' mvn_output.log > test_error.log || true # true ensures the step doesn't fail if no match is found. ERROR_MSG=$(cat test_error.log | tail +4 | head -n -4 | awk 'BEGIN{RS=""} {gsub(/"/, "\\\""); gsub(/Expecting KeySet:.*but could not find the following element\(s\):/, "Missing element: "); printf "%s\n", $0}') echo "$ERROR_MSG" - echo "error_message=$ERROR_MSG" >> $GITHUB_OUTPUT + echo "error_message<> $GITHUB_OUTPUT + echo "$ERROR_MSG" >> $GITHUB_OUTPUT + echo "GITHUB_OUTPUT_EOF" >> $GITHUB_OUTPUT if grep -q "BUILD FAILURE" mvn_output.log; then echo "Maven build failed." @@ -99,19 +101,19 @@ jobs: # print response body with headers to stdout. q:body only O:print -:stdout S:headers run: wget -qO- -S localhost:8080 -# - name: "Slack Notification" -# if: failure() -# uses: slackapi/slack-github-action@v3.0.3 -# with: -# webhook: ${{ secrets.SLACK_WEBHOOK }} -# webhook-type: incoming-webhook -# payload: | -# blocks: -# - type: "section" -# text: -# type: "mrkdwn" -# text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " -# - type: "section" -# text: -# type: "plain_text" -# text: "${{ steps.run_tests.outputs.error_message }} " + - name: "Slack Notification" + if: failure() + uses: slackapi/slack-github-action@v3.0.3 + with: + webhook: ${{ secrets.SLACK_WEBHOOK }} + webhook-type: incoming-webhook + payload: | + blocks: + - type: "section" + text: + type: "mrkdwn" + text: "⚠️ End-to-end tests failed! 😬 Please inspect & fix by clicking " + - type: "section" + text: + type: "plain_text" + text: "${{ steps.run_tests.outputs.error_message }} "