From 481dda6bf09f6e470dd2273e4a5d130b10381369 Mon Sep 17 00:00:00 2001
From: roost-io <34998783+taher27@users.noreply.github.com>
Date: Thu, 2 Jul 2026 05:25:28 +0000
Subject: [PATCH] Unit test generated by RoostGPT
Using AI Model global.anthropic.claude-sonnet-4-6
---
core/pom.xml | 21 +-
.../adk/agents/LiveRequestBuilderTest.java | 397 ++++++++++++++
.../agents/LiveRequestFromJsonStringTest.java | 375 +++++++++++++
.../agents/LiveRequestJacksonBuilderTest.java | 506 ++++++++++++++++++
.../agents/LiveRequestShouldCloseTest.java | 468 ++++++++++++++++
pom.xml | 79 ++-
6 files changed, 1822 insertions(+), 24 deletions(-)
mode change 100644 => 100755 core/pom.xml
create mode 100644 core/src/test/java/com/google/adk/agents/LiveRequestBuilderTest.java
create mode 100644 core/src/test/java/com/google/adk/agents/LiveRequestFromJsonStringTest.java
create mode 100644 core/src/test/java/com/google/adk/agents/LiveRequestJacksonBuilderTest.java
create mode 100755 core/src/test/java/com/google/adk/agents/LiveRequestShouldCloseTest.java
mode change 100644 => 100755 pom.xml
diff --git a/core/pom.xml b/core/pom.xml
old mode 100644
new mode 100755
index fe65715f3..7d2032c7e
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1,4 +1,4 @@
-
+
4.0.0
-
com.google.adk
google-adk-parent
- 0.4.1-SNAPSHOT
+ 0.4.1-SNAPSHOT
+
-
google-adk
Agent Development Kit
Agent Development Kit: an open-source, code-first toolkit designed to simplify building, evaluating, and deploying advanced AI agents anywhere.
-
-
-
com.anthropic
@@ -201,6 +197,15 @@
maven-compiler-plugin
+
+ io.spring.javaformat
+ spring-javaformat-maven-plugin
+ 0.0.40
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/core/src/test/java/com/google/adk/agents/LiveRequestBuilderTest.java b/core/src/test/java/com/google/adk/agents/LiveRequestBuilderTest.java
new file mode 100644
index 000000000..2878eb562
--- /dev/null
+++ b/core/src/test/java/com/google/adk/agents/LiveRequestBuilderTest.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * 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
+ *
+ * http://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.
+ */
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test june-java-unit using AI Type AWS Bedrock Runtime AI and AI Model global.anthropic.claude-sonnet-4-6
+
+ROOST_METHOD_HASH=builder_0aac37399c
+ROOST_METHOD_SIG_HASH=builder_80041265ae
+
+Scenario 1: Builder Instance Is Not Null
+
+Details:
+ TestName: builderReturnsNonNullInstance
+ Description: Verifies that the `builder()` method returns a non-null `Builder` instance, ensuring the factory method is properly initialized and functional.
+
+Execution:
+ Arrange: No special setup is required since this test directly invokes the static factory method.
+ Act: Call `LiveRequest.builder()` and store the result in a variable of type `LiveRequest.Builder`.
+ Assert: Use `assertNotNull` to verify the returned builder is not null.
+
+Validation:
+ This assertion confirms that the `builder()` method consistently returns a valid, usable `Builder` object. A null return would prevent any further method chaining, making the factory method entirely non-functional and breaking all dependent code paths.
+
+---
+
+Scenario 2: Builder Returns Correct Type
+
+Details:
+ TestName: builderReturnsCorrectBuilderType
+ Description: Verifies that the object returned by `builder()` is an instance of `LiveRequest.Builder`, ensuring proper type compatibility for method chaining.
+
+Execution:
+ Arrange: No special setup required.
+ Act: Call `LiveRequest.builder()` and store the result.
+ Assert: Use `assertInstanceOf` or `assertTrue` with `instanceof LiveRequest.Builder` to confirm the returned type.
+
+Validation:
+ Ensures that the return type contract is satisfied. Returning an incorrect type would cause `ClassCastException` at runtime and break the fluent builder pattern expected by callers of `LiveRequest.builder()`.
+
+---
+
+Scenario 3: Default Close Value Is Set To False
+
+Details:
+ TestName: builderDefaultsClosToFalse
+ Description: Verifies that when `builder()` is called, the `close` field is pre-initialized to `false` as specified in the method implementation `.close(false)`.
+
+Execution:
+ Arrange: Obtain a builder by calling `LiveRequest.builder()`, then set a required field (e.g., `blob`) to satisfy the build precondition.
+ Act: Build a `LiveRequest` by calling `.blob(someBlob).build()` on the builder and then call `shouldClose()` on the resulting instance.
+ Assert: Use `assertFalse` to verify that `shouldClose()` returns `false`.
+
+Validation:
+ The `builder()` method explicitly sets `close(false)` as a default. This test ensures that the default initialization is honored, preventing unintended session closures when the caller does not explicitly set the `close` field.
+
+---
+
+Scenario 4: Default Close Optional Is Present With Value False
+
+Details:
+ TestName: builderDefaultCloseOptionalIsPresentWithFalse
+ Description: Verifies that the `close()` optional on the built object is present and holds the value `false` when the builder is obtained via `builder()` without further modification.
+
+Execution:
+ Arrange: Call `LiveRequest.builder()` and chain a valid `blob` to satisfy the build precondition.
+ Act: Build the `LiveRequest` by calling `.build()` and inspect the result of `close()`.
+ Assert: Use `assertTrue` to assert `close().isPresent()` and `assertEquals(false, close().get())`.
+
+Validation:
+ This distinguishes between the `close` field being absent versus being explicitly set to `false`. Since `builder()` explicitly sets `.close(false)`, the `Optional` should be present and contain `false`, not be empty.
+
+---
+
+Scenario 5: Builder Allows Chaining Content After Default Initialization
+
+Details:
+ TestName: builderAllowsChainingContentAfterDefaultInit
+ Description: Verifies that the `Builder` returned by `builder()` allows further method chaining, specifically setting a `Content` object after the default `close(false)` is applied.
+
+Execution:
+ Arrange: Create a `Content` object using its available API. Call `LiveRequest.builder()`.
+ Act: Chain `.content(content).build()` on the returned builder.
+ Assert: Use `assertNotNull` to confirm the resulting `LiveRequest` is not null and `assertTrue` to confirm `content().isPresent()`.
+
+Validation:
+ Validates that the default initialization of `close` does not interfere with subsequent builder calls. The builder must remain fully functional for all fields after being returned by `builder()`.
+
+---
+
+Scenario 6: Builder Allows Chaining Blob After Default Initialization
+
+Details:
+ TestName: builderAllowsChainingBlobAfterDefaultInit
+ Description: Verifies that the `Builder` returned by `builder()` supports chaining the `blob` field after the default initialization.
+
+Execution:
+ Arrange: Create a `Blob` object using its available API. Call `LiveRequest.builder()`.
+ Act: Chain `.blob(blob).build()` on the returned builder.
+ Assert: Use `assertNotNull` on the resulting `LiveRequest` and `assertTrue` on `blob().isPresent()`.
+
+Validation:
+ Confirms that the builder remains operational for setting the `blob` field after `builder()` initializes `close`. This is critical for real-time mode usage where only a blob is sent.
+
+---
+
+Scenario 7: Builder Allows Overriding Default Close Value To True
+
+Details:
+ TestName: builderAllowsOverridingDefaultCloseToTrue
+ Description: Verifies that the default `close(false)` set by `builder()` can be overridden by calling `.close(true)` on the returned builder.
+
+Execution:
+ Arrange: Call `LiveRequest.builder()`.
+ Act: Chain `.close(true).build()` and call `shouldClose()` on the resulting `LiveRequest`.
+ Assert: Use `assertTrue` to verify that `shouldClose()` returns `true`.
+
+Validation:
+ Ensures that the default `close(false)` is merely a default and not a locked value. Callers must be able to override it to `true` to signal the connection should be closed after the request.
+
+---
+
+Scenario 8: Builder Allows Setting Close To Null After Default Initialization
+
+Details:
+ TestName: builderAllowsSettingCloseToNullOverridingDefault
+ Description: Verifies that after `builder()` sets `close` to `false`, passing `null` to `.close(Boolean)` overrides the default, and the build will fail if no other field is set (per Preconditions check).
+
+Execution:
+ Arrange: Call `LiveRequest.builder()`.
+ Act: Chain `.close((Boolean) null)` and attempt to call `.build()` without setting `content` or `blob`.
+ Assert: Expect an `IllegalStateException` to be thrown, validating that the Preconditions check catches the empty state.
+
+Validation:
+ This tests the interaction between the default-setting behavior of `builder()` and the ability to nullify it. The build precondition requires at least one of `content`, `blob`, or `close` to be present, so nullifying the default without setting another field must fail.
+
+---
+
+Scenario 9: Multiple Calls To builder() Return Independent Instances
+
+Details:
+ TestName: multipleBuilderCallsReturnIndependentInstances
+ Description: Verifies that each invocation of `builder()` returns a new, independent `Builder` instance, preventing shared mutable state between multiple build chains.
+
+Execution:
+ Arrange: No additional setup required.
+ Act: Call `LiveRequest.builder()` twice and store the results as `builder1` and `builder2`.
+ Assert: Use `assertNotSame` to verify that `builder1` and `builder2` are distinct object references.
+
+Validation:
+ Shared builder instances would cause severe concurrency and correctness issues. Each call to `builder()` must produce a fresh builder to allow independent construction of multiple `LiveRequest` objects without cross-contamination of fields.
+
+---
+
+Scenario 10: Builder Returned Can Build A Valid LiveRequest With Close Only
+
+Details:
+ TestName: builderCanBuildValidRequestWithCloseOnly
+ Description: Verifies that the `Builder` returned by `builder()`, which defaults `close` to `false`, can produce a valid `LiveRequest` without requiring any other fields, since `close` is already set.
+
+Execution:
+ Arrange: Call `LiveRequest.builder()` which pre-sets `close(false)`.
+ Act: Immediately call `.build()` on the returned builder without setting `content` or `blob`.
+ Assert: Use `assertNotNull` to verify the resulting `LiveRequest` is a valid object, and `assertFalse` on `shouldClose()`.
+
+Validation:
+ Since `builder()` pre-initializes `close` to `false`, the `Preconditions.checkState` condition (`close().isPresent()` is true) should be satisfied immediately, allowing `build()` to succeed without additional field assignments. This is a core behavioral guarantee of the method.
+
+---
+
+Scenario 11: Builder Preserves Close False When Content Is Also Set
+
+Details:
+ TestName: builderPreservesDefaultCloseFalseWhenContentIsSet
+ Description: Verifies that the default `close(false)` is retained alongside a separately set `content` field when building the `LiveRequest`.
+
+Execution:
+ Arrange: Create a `Content` object. Call `LiveRequest.builder()`.
+ Act: Chain `.content(content).build()` and inspect both `close()` and `content()` on the result.
+ Assert: Use `assertFalse` on `shouldClose()` and `assertTrue` on `content().isPresent()`.
+
+Validation:
+ Confirms that setting additional fields does not unintentionally reset or remove the default `close(false)` value. Both fields should coexist in the final built object, reflecting the intended multi-field behavior of the builder.
+
+*/
+
+// ********RoostGPT********
+
+package com.google.adk.agents;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.google.genai.types.Blob;
+import com.google.genai.types.Content;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+public class LiveRequestBuilderTest {
+
+ @Test
+ @Tag("valid")
+ void builderReturnsNonNullInstance() {
+ LiveRequest.Builder builder = LiveRequest.builder();
+ assertNotNull(builder, "builder() should return a non-null Builder instance");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderReturnsCorrectBuilderType() {
+ Object builder = LiveRequest.builder();
+ assertInstanceOf(
+ LiveRequest.Builder.class,
+ builder,
+ "builder() should return an instance of LiveRequest.Builder");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderDefaultsCloseToFalse() {
+ LiveRequest request = LiveRequest.builder().build();
+ assertFalse(request.shouldClose(), "Default close value should be false when using builder()");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderDefaultCloseOptionalIsPresentWithFalse() {
+ LiveRequest request = LiveRequest.builder().build();
+ assertTrue(
+ request.close().isPresent(),
+ "close() Optional should be present after builder() initialization");
+ assertEquals(
+ false, request.close().get(), "close() Optional should contain false as default value");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderAllowsChainingContentAfterDefaultInit() {
+ Content content = Content.builder().role("user").build();
+ LiveRequest.Builder builder = LiveRequest.builder();
+ LiveRequest request = builder.content(content).build();
+ assertNotNull(request, "LiveRequest should not be null after setting content");
+ assertTrue(
+ request.content().isPresent(),
+ "content() should be present after being set on the builder");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderAllowsChainingBlobAfterDefaultInit() {
+ Blob blob = Blob.builder().mimeType("audio/pcm").build();
+ LiveRequest.Builder builder = LiveRequest.builder();
+ LiveRequest request = builder.blob(blob).build();
+ assertNotNull(request, "LiveRequest should not be null after setting blob");
+ assertTrue(
+ request.blob().isPresent(), "blob() should be present after being set on the builder");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderAllowsOverridingDefaultCloseToTrue() {
+ LiveRequest request = LiveRequest.builder().close(true).build();
+ assertTrue(
+ request.shouldClose(),
+ "shouldClose() should return true after overriding default close with true");
+ }
+
+ @Test
+ @Tag("invalid")
+ void builderAllowsSettingCloseToNullOverridingDefault() {
+ assertThrows(
+ IllegalStateException.class,
+ () -> {
+ LiveRequest.builder().close((Boolean) null).build();
+ },
+ "build() should throw IllegalStateException when close is null and no other field is set");
+ }
+
+ @Test
+ @Tag("valid")
+ void multipleBuilderCallsReturnIndependentInstances() {
+ LiveRequest.Builder builder1 = LiveRequest.builder();
+ LiveRequest.Builder builder2 = LiveRequest.builder();
+ assertNotSame(
+ builder1,
+ builder2,
+ "Each call to builder() should return a new, independent Builder instance");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderCanBuildValidRequestWithCloseOnly() {
+ LiveRequest request = LiveRequest.builder().build();
+ assertNotNull(
+ request,
+ "builder() should produce a valid LiveRequest without additional field assignments");
+ assertFalse(
+ request.shouldClose(),
+ "shouldClose() should return false when only default initialization is done");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderPreservesDefaultCloseFalseWhenContentIsSet() {
+ Content content = Content.builder().role("user").build();
+ LiveRequest request = LiveRequest.builder().content(content).build();
+ assertFalse(
+ request.shouldClose(), "Default close(false) should be preserved when content is also set");
+ assertTrue(
+ request.content().isPresent(), "content() should be present on the built LiveRequest");
+ }
+
+ @Test
+ @Tag("integration")
+ void builderIndependentInstancesDoNotShareState() {
+ LiveRequest.Builder builder1 = LiveRequest.builder();
+ LiveRequest.Builder builder2 = LiveRequest.builder();
+ builder1.close(true);
+ LiveRequest request1 = builder1.build();
+ LiveRequest request2 = builder2.build();
+ assertTrue(request1.shouldClose(), "builder1's close should be true after explicit override");
+ assertFalse(
+ request2.shouldClose(),
+ "builder2's close should remain false, unaffected by builder1's state");
+ }
+
+ @Test
+ @Tag("valid")
+ void builderDefaultCloseOptionalIsNotEmpty() {
+ LiveRequest request = LiveRequest.builder().build();
+ assertFalse(
+ request.close().isEmpty(),
+ "close() Optional should not be empty after builder() sets default close(false)");
+ }
+
+ @Test
+ @Tag("boundary")
+ void builderWithBlobAndDefaultCloseFalseIsValid() {
+ Blob blob = Blob.builder().mimeType("audio/pcm").build();
+ LiveRequest request = LiveRequest.builder().blob(blob).build();
+ assertTrue(request.blob().isPresent(), "blob() should be present in the built LiveRequest");
+ assertTrue(
+ request.close().isPresent(), "close() should be present as default false alongside blob");
+ assertFalse(
+ request.shouldClose(),
+ "shouldClose() should be false when default is retained alongside blob");
+ }
+
+ @Test
+ @Tag("boundary")
+ void builderWithCloseSetToFalseExplicitlyMatchesDefault() {
+ LiveRequest defaultRequest = LiveRequest.builder().build();
+ LiveRequest explicitRequest = LiveRequest.builder().close(false).build();
+ assertEquals(
+ defaultRequest.shouldClose(),
+ explicitRequest.shouldClose(),
+ "Explicit close(false) should produce same result as default initialization");
+ assertEquals(
+ defaultRequest.close().get(),
+ explicitRequest.close().get(),
+ "Both requests should have close Optional containing false");
+ }
+
+ @Test
+ @Tag("integration")
+ void builderIntegrationWithContentAndCloseOverride() {
+ Content content = Content.builder().role("model").build();
+ LiveRequest request = LiveRequest.builder().content(content).close(true).build();
+ assertNotNull(request, "Built LiveRequest should not be null");
+ assertTrue(request.content().isPresent(), "content() should be present");
+ assertTrue(request.close().isPresent(), "close() should be present");
+ assertTrue(request.shouldClose(), "shouldClose() should return true after explicit override");
+ }
+
+ @Test
+ @Tag("integration")
+ void builderIntegrationWithBlobAndCloseOverride() {
+ Blob blob = Blob.builder().mimeType("video/webm").build();
+ LiveRequest request = LiveRequest.builder().blob(blob).close(true).build();
+ assertNotNull(request, "Built LiveRequest should not be null");
+ assertTrue(request.blob().isPresent(), "blob() should be present");
+ assertTrue(request.close().isPresent(), "close() should be present");
+ assertTrue(request.shouldClose(), "shouldClose() should return true after explicit override");
+ }
+}
diff --git a/core/src/test/java/com/google/adk/agents/LiveRequestFromJsonStringTest.java b/core/src/test/java/com/google/adk/agents/LiveRequestFromJsonStringTest.java
new file mode 100644
index 000000000..d406d43d3
--- /dev/null
+++ b/core/src/test/java/com/google/adk/agents/LiveRequestFromJsonStringTest.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * 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
+ *
+ * http://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.
+ */
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test june-java-unit using AI Type AWS Bedrock Runtime AI and AI Model global.anthropic.claude-sonnet-4-6
+
+ROOST_METHOD_HASH=fromJsonString_93fe6514b6
+ROOST_METHOD_SIG_HASH=fromJsonString_92e66fb3de
+
+Scenario 1: Deserialize a Valid JSON String with Content Field
+
+Details:
+ TestName: fromJsonStringWithValidContentField
+ Description: Verifies that a JSON string containing a valid "content" field is correctly deserialized into a LiveRequest object with the content field populated.
+Execution:
+ Arrange: Construct a valid JSON string that includes a "content" field with appropriate nested structure representing a Content object.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest object is not null and that content().isPresent() returns true.
+Validation:
+ This test ensures that the deserialization mechanism correctly maps the "content" JSON field to the content() Optional in the LiveRequest object.
+ It validates the core functionality of processing turn-by-turn content requests.
+
+---
+
+Scenario 2: Deserialize a Valid JSON String with Blob Field
+
+Details:
+ TestName: fromJsonStringWithValidBlobField
+ Description: Verifies that a JSON string containing a valid "blob" field is correctly deserialized into a LiveRequest object with the blob field populated.
+Execution:
+ Arrange: Construct a valid JSON string that includes a "blob" field with appropriate nested structure representing a Blob object.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest object is not null and that blob().isPresent() returns true.
+Validation:
+ This test ensures that the deserialization mechanism correctly maps the "blob" JSON field to the blob() Optional in the LiveRequest object.
+ It validates the core functionality of processing real-time blob data requests.
+
+---
+
+Scenario 3: Deserialize a Valid JSON String with Close Field Set to True
+
+Details:
+ TestName: fromJsonStringWithCloseFieldSetToTrue
+ Description: Verifies that a JSON string with the "close" field set to true is correctly deserialized, resulting in a LiveRequest where close() contains true.
+Execution:
+ Arrange: Construct a valid JSON string: {"close": true}.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest object is not null, close().isPresent() returns true, and shouldClose() returns true.
+Validation:
+ This test verifies that the "close" boolean flag is correctly deserialized and that the shouldClose() convenience method reflects the correct value.
+ It validates the connection termination signal logic in live session management.
+
+---
+
+Scenario 4: Deserialize a Valid JSON String with Close Field Set to False
+
+Details:
+ TestName: fromJsonStringWithCloseFieldSetToFalse
+ Description: Verifies that a JSON string with the "close" field set to false is correctly deserialized, resulting in a LiveRequest where shouldClose() returns false.
+Execution:
+ Arrange: Construct a valid JSON string: {"close": false}.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest object is not null, close().isPresent() returns true, and shouldClose() returns false.
+Validation:
+ This test confirms that an explicitly set false value for the "close" field is accurately parsed and reflected in the LiveRequest object.
+ It ensures that connection state is not incorrectly signaled as closed.
+
+---
+
+Scenario 5: Deserialize a JSON String with All Three Fields Present
+
+Details:
+ TestName: fromJsonStringWithAllFieldsPresent
+ Description: Verifies that a JSON string containing all three fields — "content", "blob", and "close" — is correctly deserialized into a LiveRequest with all Optional fields populated.
+Execution:
+ Arrange: Construct a JSON string that includes "content", "blob", and "close" fields, each with appropriate values.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest object is not null, and that content().isPresent(), blob().isPresent(), and close().isPresent() all return true.
+Validation:
+ This test ensures that when multiple fields are provided simultaneously, all of them are correctly deserialized without conflict.
+ It tests the robustness of the deserialization logic for fully populated requests.
+
+---
+
+Scenario 6: Deserialize a JSON String with Only the Close Field
+
+Details:
+ TestName: fromJsonStringWithOnlyCloseField
+ Description: Verifies that a minimal JSON string containing only the "close" field successfully deserializes into a valid LiveRequest.
+Execution:
+ Arrange: Construct a JSON string: {"close": true}.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest is not null, close().isPresent() returns true, content().isPresent() returns false, and blob().isPresent() returns false.
+Validation:
+ This test verifies the minimum valid state of a LiveRequest, where only one of the required fields is set.
+ It confirms the Preconditions check in the builder is satisfied by just the "close" field.
+
+---
+
+Scenario 7: Deserialize a Null JSON String Throws an Exception
+
+Details:
+ TestName: fromJsonStringWithNullInputThrowsException
+ Description: Verifies that passing a null string to fromJsonString results in an appropriate exception being thrown.
+Execution:
+ Arrange: Set the json variable to null.
+ Act: Call LiveRequest.fromJsonString(null).
+ Assert: Assert that an exception (such as IllegalArgumentException, NullPointerException, or a Jackson-related RuntimeException) is thrown.
+Validation:
+ This test ensures that the method fails gracefully with a meaningful exception when given a null input.
+ It protects against silent failures or null pointer propagation in upstream callers.
+
+---
+
+Scenario 8: Deserialize an Empty JSON String Throws an Exception
+
+Details:
+ TestName: fromJsonStringWithEmptyStringThrowsException
+ Description: Verifies that passing an empty string to fromJsonString results in an appropriate exception being thrown.
+Execution:
+ Arrange: Set the json variable to an empty string "".
+ Act: Call LiveRequest.fromJsonString("").
+ Assert: Assert that a RuntimeException or Jackson deserialization exception is thrown.
+Validation:
+ This test ensures that the method handles empty string input by throwing an appropriate exception rather than returning a null or incomplete object.
+ It validates input boundary handling for the deserialization logic.
+
+---
+
+Scenario 9: Deserialize a Malformed JSON String Throws an Exception
+
+Details:
+ TestName: fromJsonStringWithMalformedJsonThrowsException
+ Description: Verifies that passing a syntactically invalid JSON string to fromJsonString results in an exception being thrown.
+Execution:
+ Arrange: Provide a malformed JSON string such as "{close: true" (missing closing brace and unquoted key).
+ Act: Call LiveRequest.fromJsonString("{close: true").
+ Assert: Assert that a RuntimeException or Jackson JsonParseException is thrown.
+Validation:
+ This test ensures that the method does not silently fail when given syntactically invalid JSON and instead surfaces the error appropriately.
+ It validates the robustness of the JSON parsing layer under erroneous input conditions.
+
+---
+
+Scenario 10: Deserialize a JSON String with Unknown Fields
+
+Details:
+ TestName: fromJsonStringWithUnknownFieldsDoesNotThrow
+ Description: Verifies that a JSON string containing unknown or extra fields is handled gracefully without throwing an exception.
+Execution:
+ Arrange: Construct a JSON string such as {"close": true, "unknownField": "someValue"}.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest object is not null and that close().isPresent() returns true.
+Validation:
+ This test checks whether the deserialization is lenient toward unknown fields, which is important for backward and forward compatibility in API versioning.
+ It ensures that extra fields in the JSON payload do not break the deserialization of valid fields.
+
+---
+
+Scenario 11: Deserialize a JSON String with Null Value for Close Field
+
+Details:
+ TestName: fromJsonStringWithNullCloseValueResultsInEmptyOptional
+ Description: Verifies that a JSON string with an explicit null value for the "close" field results in an empty Optional for close(), provided another required field is present.
+Execution:
+ Arrange: Construct a JSON string such as {"close": null, "blob": { ... }} where blob is a valid Blob structure.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest is not null, close().isPresent() returns false, and blob().isPresent() returns true.
+Validation:
+ This test verifies that null JSON values are correctly mapped to empty Optional fields and that the builder Preconditions check is satisfied by the presence of another field.
+ It ensures that null values in JSON are not treated as valid present values.
+
+---
+
+Scenario 12: Deserialize a JSON String with Null Value for Content Field
+
+Details:
+ TestName: fromJsonStringWithNullContentValueResultsInEmptyOptional
+ Description: Verifies that a JSON string with an explicit null value for the "content" field results in an empty Optional for content(), provided another field satisfies the Preconditions check.
+Execution:
+ Arrange: Construct a JSON string such as {"content": null, "close": true}.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest is not null, content().isPresent() returns false, and close().isPresent() returns true.
+Validation:
+ This test ensures that an explicit null for "content" is treated as an absent Optional value, maintaining correct state representation.
+ It verifies that null handling is consistent across all optional fields.
+
+---
+
+Scenario 13: Deserialize a JSON String Produces Correct shouldClose Behavior When Close Is Absent
+
+Details:
+ TestName: fromJsonStringWithNoCloseFieldShouldClosReturnsFalse
+ Description: Verifies that when the "close" field is not present in the JSON but another field (e.g., "blob") is, the resulting LiveRequest returns false from shouldClose().
+Execution:
+ Arrange: Construct a JSON string that includes only a "blob" field without a "close" field.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned LiveRequest is not null and shouldClose() returns false.
+Validation:
+ This test validates the default behavior of shouldClose() which uses Optional.orElse(false) when the "close" field is absent.
+ It ensures that the absence of the "close" field does not cause unexpected connection termination signals.
+
+---
+
+Scenario 14: Deserialize a Valid JSON String Returns an Instance of LiveRequest
+
+Details:
+ TestName: fromJsonStringReturnsInstanceOfLiveRequest
+ Description: Verifies that the object returned by fromJsonString is an instance of LiveRequest and extends JsonBaseModel.
+Execution:
+ Arrange: Construct a valid JSON string containing the "close" field: {"close": true}.
+ Act: Call LiveRequest.fromJsonString(json) with the prepared JSON string.
+ Assert: Assert that the returned object is an instance of LiveRequest and also an instance of JsonBaseModel.
+Validation:
+ This test validates that the factory method returns the correct type, which is critical for polymorphic usage and downstream type safety.
+ It also confirms that the class hierarchy is preserved after deserialization.
+
+*/
+
+// ********RoostGPT********
+
+package com.google.adk.agents;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.google.adk.JsonBaseModel;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+public class LiveRequestFromJsonStringTest {
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithValidContentField() {
+ String json = "{\"content\": {\"role\": \"user\", \"parts\": [{\"text\": \"Hello\"}]}}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertTrue(result.content().isPresent());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithValidBlobField() {
+ String json = "{\"blob\": {\"mimeType\": \"audio/pcm\", \"data\": \"dGVzdA==\"}}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertTrue(result.blob().isPresent());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithCloseFieldSetToTrue() {
+ String json = "{\"close\": true}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertTrue(result.close().isPresent());
+ assertTrue(result.shouldClose());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithCloseFieldSetToFalse() {
+ String json = "{\"close\": false}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertTrue(result.close().isPresent());
+ assertFalse(result.shouldClose());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithAllFieldsPresent() {
+ String json =
+ "{\"content\": {\"role\": \"user\", \"parts\": [{\"text\": \"Hello\"}]}, "
+ + "\"blob\": {\"mimeType\": \"audio/pcm\", \"data\": \"dGVzdA==\"}, "
+ + "\"close\": true}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertTrue(result.content().isPresent());
+ assertTrue(result.blob().isPresent());
+ assertTrue(result.close().isPresent());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithOnlyCloseField() {
+ String json = "{\"close\": true}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertTrue(result.close().isPresent());
+ assertFalse(result.content().isPresent());
+ assertFalse(result.blob().isPresent());
+ }
+
+ @Test
+ @Tag("invalid")
+ public void fromJsonStringWithNullInputThrowsException() {
+ assertThrows(Exception.class, () -> LiveRequest.fromJsonString(null));
+ }
+
+ @Test
+ @Tag("boundary")
+ public void fromJsonStringWithEmptyStringThrowsException() {
+ assertThrows(RuntimeException.class, () -> LiveRequest.fromJsonString(""));
+ }
+
+ @Test
+ @Tag("invalid")
+ public void fromJsonStringWithMalformedJsonThrowsException() {
+ assertThrows(RuntimeException.class, () -> LiveRequest.fromJsonString("{close: true"));
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithUnknownFieldsDoesNotThrow() {
+ String json = "{\"close\": true, \"unknownField\": \"someValue\"}";
+ LiveRequest result = assertDoesNotThrow(() -> LiveRequest.fromJsonString(json));
+ assertNotNull(result);
+ assertTrue(result.close().isPresent());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithNullCloseValueResultsInEmptyOptional() {
+ String json =
+ "{\"close\": null, \"blob\": {\"mimeType\": \"audio/pcm\", \"data\": \"dGVzdA==\"}}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertFalse(result.close().isPresent());
+ assertTrue(result.blob().isPresent());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithNullContentValueResultsInEmptyOptional() {
+ String json = "{\"content\": null, \"close\": true}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertFalse(result.content().isPresent());
+ assertTrue(result.close().isPresent());
+ }
+
+ @Test
+ @Tag("valid")
+ public void fromJsonStringWithNoCloseFieldShouldClosReturnsFalse() {
+ String json = "{\"blob\": {\"mimeType\": \"audio/pcm\", \"data\": \"dGVzdA==\"}}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertFalse(result.shouldClose());
+ }
+
+ @Test
+ @Tag("integration")
+ public void fromJsonStringReturnsInstanceOfLiveRequest() {
+ String json = "{\"close\": true}";
+ LiveRequest result = LiveRequest.fromJsonString(json);
+ assertNotNull(result);
+ assertInstanceOf(LiveRequest.class, result);
+ assertInstanceOf(JsonBaseModel.class, result);
+ }
+}
diff --git a/core/src/test/java/com/google/adk/agents/LiveRequestJacksonBuilderTest.java b/core/src/test/java/com/google/adk/agents/LiveRequestJacksonBuilderTest.java
new file mode 100644
index 000000000..201609dac
--- /dev/null
+++ b/core/src/test/java/com/google/adk/agents/LiveRequestJacksonBuilderTest.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * 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
+ *
+ * http://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.
+ */
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test june-java-unit using AI Type AWS Bedrock Runtime AI and AI Model global.anthropic.claude-sonnet-4-6
+
+ROOST_METHOD_HASH=jacksonBuilder_1ec5a209d2
+ROOST_METHOD_SIG_HASH=jacksonBuilder_d5321012c5
+
+Scenario 1: Verify That jacksonBuilder Returns a Non-Null Builder Instance
+
+Details:
+ TestName: jacksonBuilderReturnsNonNullBuilder
+ Description: Verifies that the jacksonBuilder() method returns a non-null LiveRequest.Builder instance,
+ ensuring that the Jackson deserialization entry point is properly initialized.
+Execution:
+ Arrange: No special setup is required since jacksonBuilder() is a static method with no parameters.
+ Act: Invoke LiveRequest.jacksonBuilder() via reflection (since it has package-private visibility) or
+ indirectly through Jackson deserialization by calling LiveRequest.builder() as a proxy check.
+ Alternatively, use reflection to access the jacksonBuilder method and invoke it.
+ Assert: Assert that the returned Builder instance is not null using assertNotNull().
+Validation:
+ The assertion confirms that the method successfully creates and returns a valid Builder object.
+ This is critical because Jackson relies on this builder factory method to deserialize JSON into
+ LiveRequest instances; a null return would cause NullPointerException during deserialization.
+
+---
+
+Scenario 2: Verify That jacksonBuilder Returns an Instance of LiveRequest.Builder
+
+Details:
+ TestName: jacksonBuilderReturnsCorrectBuilderType
+ Description: Verifies that the object returned by jacksonBuilder() is specifically an instance of
+ LiveRequest.Builder, confirming proper type compatibility for Jackson deserialization.
+Execution:
+ Arrange: No special setup is required.
+ Act: Invoke jacksonBuilder() via reflection to obtain the returned object.
+ Assert: Assert using assertInstanceOf() or assertTrue(result instanceof LiveRequest.Builder)
+ that the returned object is of type LiveRequest.Builder.
+Validation:
+ The assertion ensures that the method returns the exact expected type, which is required for
+ Jackson's @JsonPOJOBuilder deserialization pipeline to function correctly. Returning a wrong type
+ would break the JSON deserialization contract.
+
+---
+
+Scenario 3: Verify That the Builder Returned by jacksonBuilder Has Default close Set to False
+
+Details:
+ TestName: jacksonBuilderReturnsBuilderWithDefaultCloseFalse
+ Description: Verifies that the Builder returned by jacksonBuilder() already has the close field
+ pre-set to false, consistent with what LiveRequest.builder() initializes.
+Execution:
+ Arrange: No special setup is required.
+ Act: Obtain the builder by invoking jacksonBuilder() via reflection, then call
+ blob(someBlob).build() or close(false).build() to construct a LiveRequest.
+ Use a minimal valid build by supplying a required field such as close(false).build().
+ Assert: Assert that the resulting LiveRequest's close() returns an Optional containing false,
+ i.e., assertTrue(liveRequest.close().isPresent()) and
+ assertFalse(liveRequest.close().get()).
+Validation:
+ The assertion verifies that jacksonBuilder() delegates to LiveRequest.builder(), which sets
+ close(false) by default. This default initialization ensures that deserialized objects without
+ an explicit close field default to a safe, non-closing state.
+
+---
+
+Scenario 4: Verify That jacksonBuilder Produces a Functional Builder Capable of Building a Valid LiveRequest With content
+
+Details:
+ TestName: jacksonBuilderProducesBuilderThatBuildsWithContent
+ Description: Verifies that the Builder returned by jacksonBuilder() can be used to set the content
+ field and successfully build a valid LiveRequest object.
+Execution:
+ Arrange: Create a Content instance (or mock/stub if needed) to be used as the content value.
+ Obtain the Builder via jacksonBuilder() through reflection.
+ Act: Call builder.content(contentInstance).build() on the builder returned by jacksonBuilder().
+ Assert: Assert that the resulting LiveRequest is not null, and that liveRequest.content().isPresent()
+ returns true and liveRequest.content().get() equals the provided Content instance.
+Validation:
+ This test confirms that the Builder obtained from jacksonBuilder() is fully functional and supports
+ setting the content field. It validates that Jackson can successfully reconstruct a LiveRequest
+ from JSON that contains a content property.
+
+---
+
+Scenario 5: Verify That jacksonBuilder Produces a Functional Builder Capable of Building a Valid LiveRequest With blob
+
+Details:
+ TestName: jacksonBuilderProducesBuilderThatBuildsWithBlob
+ Description: Verifies that the Builder returned by jacksonBuilder() supports setting the blob field
+ and produces a valid LiveRequest with blob data.
+Execution:
+ Arrange: Create a Blob instance to be used as the blob value.
+ Obtain the Builder via jacksonBuilder() through reflection.
+ Act: Call builder.blob(blobInstance).build() on the builder returned by jacksonBuilder().
+ Assert: Assert that the resulting LiveRequest is not null, that liveRequest.blob().isPresent()
+ returns true, and that liveRequest.blob().get() equals the provided Blob instance.
+Validation:
+ This confirms that the Builder obtained from jacksonBuilder() correctly handles blob-type
+ payloads, which are used for real-time mode communication with the LLM model.
+
+---
+
+Scenario 6: Verify That jacksonBuilder Produces a Builder That Enforces Validation on build()
+
+Details:
+ TestName: jacksonBuilderProducesBuilderThatEnforcesValidationOnBuild
+ Description: Verifies that calling build() on the Builder returned by jacksonBuilder(), without
+ setting any of the required fields (content, blob, or close to a meaningful value
+ other than the default false), still succeeds due to the default close(false) set
+ by the underlying builder() call, and does not throw an exception.
+Execution:
+ Arrange: Obtain the Builder via jacksonBuilder() through reflection.
+ Act: Directly call build() on the builder without setting any additional fields.
+ Assert: Assert that the resulting LiveRequest is not null, and assert that
+ liveRequest.shouldClose() returns false (since close defaults to false).
+Validation:
+ Because jacksonBuilder() internally calls LiveRequest.builder() which initializes close(false),
+ calling build() without additional fields should succeed and produce a LiveRequest with
+ close = false. This verifies the default state contract maintained by jacksonBuilder().
+
+---
+
+Scenario 7: Verify That jacksonBuilder Is Consistent With LiveRequest.builder() Behavior
+
+Details:
+ TestName: jacksonBuilderConsistentWithStaticBuilderMethod
+ Description: Verifies that the Builder returned by jacksonBuilder() behaves identically to the
+ Builder returned by LiveRequest.builder(), ensuring that jacksonBuilder() is a
+ transparent wrapper around the standard builder factory.
+Execution:
+ Arrange: Obtain one Builder by calling LiveRequest.builder() and another by invoking
+ jacksonBuilder() via reflection.
+ Act: Build LiveRequest instances from both builders using the same field assignments,
+ e.g., builder.close(true).build(), and compare the resulting objects.
+ Assert: Assert that both LiveRequest instances have the same values for close(), content(),
+ and blob() fields.
+Validation:
+ Since jacksonBuilder() is documented as delegating to LiveRequest.builder(), both builders
+ should produce identical results. This test ensures there is no divergence in behavior between
+ the Jackson deserialization path and the standard programmatic builder path.
+
+---
+
+Scenario 8: Verify That jacksonBuilder Returns a New Builder Instance on Each Invocation
+
+Details:
+ TestName: jacksonBuilderReturnsNewBuilderInstanceOnEachCall
+ Description: Verifies that each invocation of jacksonBuilder() returns a distinct, independent
+ Builder instance, preventing shared mutable state between deserialization calls.
+Execution:
+ Arrange: No special setup is required.
+ Act: Invoke jacksonBuilder() twice via reflection to obtain two separate Builder instances,
+ named builder1 and builder2.
+ Assert: Assert using assertNotSame() that builder1 and builder2 are not the same object reference.
+Validation:
+ Ensuring that each call to jacksonBuilder() returns a new Builder instance is critical to prevent
+ state leakage between separate Jackson deserialization operations. Shared Builder state could lead
+ to incorrect LiveRequest objects being constructed, especially in concurrent environments.
+
+---
+
+Scenario 9: Verify That jacksonBuilder Returns a Builder That Supports the close Field Override
+
+Details:
+ TestName: jacksonBuilderReturnsBuilderThatAllowsCloseOverride
+ Description: Verifies that the Builder returned by jacksonBuilder() allows overriding the
+ default close(false) value with a custom value such as true.
+Execution:
+ Arrange: Obtain the Builder via jacksonBuilder() through reflection.
+ Act: Call builder.close(true).build() on the obtained builder.
+ Assert: Assert that the resulting LiveRequest.shouldClose() returns true and that
+ liveRequest.close().get() equals Boolean.TRUE.
+Validation:
+ Even though jacksonBuilder() initializes close to false by default (via LiveRequest.builder()),
+ the Builder must allow overriding this value. This test confirms that Jackson can correctly
+ deserialize a JSON payload that explicitly sets "close": true into a LiveRequest with
+ shouldClose() returning true.
+
+---
+
+Scenario 10: Verify That LiveRequest Deserialized via Jackson Using jacksonBuilder Produces Correct shouldClose Behavior
+
+Details:
+ TestName: jacksonBuilderEnabledDeserializationProducesCorrectShouldClose
+ Description: Verifies that a LiveRequest constructed through the builder chain initiated by
+ jacksonBuilder() correctly reflects the shouldClose() method output based on the
+ close field value set via the builder.
+Execution:
+ Arrange: Obtain the Builder via jacksonBuilder() through reflection.
+ Act: Build a LiveRequest using builder.close(false).build() and another using
+ builder.close(true).build() from separate builder instances obtained via jacksonBuilder().
+ Assert: Assert that liveRequest1.shouldClose() returns false and liveRequest2.shouldClose()
+ returns true.
+Validation:
+ The shouldClose() method is a derived behavior that depends on the close field being correctly
+ populated. This test validates that the builder chain originating from jacksonBuilder() properly
+ flows values into the final LiveRequest object and that derived methods like shouldClose()
+ function correctly on deserialized instances.
+
+*/
+
+// ********RoostGPT********
+
+```java
+package com.google.adk.agents;
+
+import static org.junit.jupiter.api.Assertions.*;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.google.adk.JsonBaseModel;
+import com.google.auto.value.AutoValue;
+import com.google.genai.types.Blob;
+import com.google.genai.types.Content;
+import java.lang.reflect.Method;
+import java.util.Optional;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.*;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nullable;
+
+class LiveRequestJacksonBuilderTest {
+ // Helper to invoke jacksonBuilder via reflection (package-private method)
+ private Object invokeJacksonBuilder() throws Exception {
+ Class> liveRequestClass = Class.forName("com.google.adk.agents.LiveRequest");
+ Method jacksonBuilderMethod = liveRequestClass.getDeclaredMethod("jacksonBuilder");
+ jacksonBuilderMethod.setAccessible(true);
+ return jacksonBuilderMethod.invoke(null);
+ }
+ // Helper to get LiveRequest.Builder class
+ private Class> getBuilderClass() throws Exception {
+ Class> liveRequestClass = Class.forName("com.google.adk.agents.LiveRequest");
+ for (Class> inner : liveRequestClass.getDeclaredClasses()) {
+ if (inner.getSimpleName().equals("Builder")) {
+ return inner;
+ }
+ }
+ throw new ClassNotFoundException("LiveRequest.Builder not found");
+ }
+ // Helper to call build() on a builder object
+ private Object buildFromBuilder(Object builder) throws Exception {
+ Method buildMethod = builder.getClass().getMethod("build");
+ buildMethod.setAccessible(true);
+ return buildMethod.invoke(builder);
+ }
+ // Helper to call a setter on a builder object
+ private Object callBuilderSetter(Object builder, String methodName, Class> paramType, Object value) throws Exception {
+ Method setterMethod = builder.getClass().getMethod(methodName, paramType);
+ setterMethod.setAccessible(true);
+ return setterMethod.invoke(builder, value);
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderReturnsNonNullBuilder() throws Exception {
+ Object builder = invokeJacksonBuilder();
+ assertNotNull(builder, "jacksonBuilder() should return a non-null Builder instance");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderReturnsCorrectBuilderType() throws Exception {
+ Object builder = invokeJacksonBuilder();
+ Class> liveRequestClass = Class.forName("com.google.adk.agents.LiveRequest");
+ // Check that the returned object is an instance of a class named "Builder"
+ // which is a nested class of LiveRequest
+ boolean isBuilderType = false;
+ for (Class> inner : liveRequestClass.getDeclaredClasses()) {
+ if (inner.getSimpleName().equals("Builder") && inner.isInstance(builder)) {
+ isBuilderType = true;
+ break;
+ }
+ }
+ assertTrue(isBuilderType, "jacksonBuilder() should return an instance of LiveRequest.Builder");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderReturnsBuilderWithDefaultCloseFalse() throws Exception {
+ Object builder = invokeJacksonBuilder();
+ Object liveRequest = buildFromBuilder(builder);
+ assertNotNull(liveRequest, "Built LiveRequest should not be null");
+ // Retrieve close() method from LiveRequest
+ Method closeMethod = liveRequest.getClass().getMethod("close");
+ closeMethod.setAccessible(true);
+ Optional> closeOptional = (Optional>) closeMethod.invoke(liveRequest);
+ assertTrue(closeOptional.isPresent(), "close() should be present with default value");
+ assertFalse((Boolean) closeOptional.get(), "Default close value should be false");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderProducesBuilderThatBuildsWithContent() throws Exception {
+ // Create a Content instance using its builder or ObjectMapper
+ ObjectMapper mapper = JsonBaseModel.getMapper();
+ Content contentInstance = mapper.readValue("{}", Content.class);
+ Object builder = invokeJacksonBuilder();
+ // Set content on the builder
+ Method contentMethod = null;
+ for (Method m : builder.getClass().getMethods()) {
+ if (m.getName().equals("content") && m.getParameterCount() == 1) {
+ contentMethod = m;
+ break;
+ }
+ }
+ assertNotNull(contentMethod, "Builder should have a content(...) method");
+ contentMethod.setAccessible(true);
+ Object updatedBuilder = contentMethod.invoke(builder, contentInstance);
+ Object liveRequest = buildFromBuilder(updatedBuilder != null ? updatedBuilder : builder);
+ assertNotNull(liveRequest, "Built LiveRequest should not be null");
+ Method contentFieldMethod = liveRequest.getClass().getMethod("content");
+ contentFieldMethod.setAccessible(true);
+ Optional> contentOptional = (Optional>) contentFieldMethod.invoke(liveRequest);
+ assertTrue(contentOptional.isPresent(), "content() should be present after setting it");
+ assertEquals(contentInstance, contentOptional.get(), "content() should return the set Content instance");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderProducesBuilderThatBuildsWithBlob() throws Exception {
+ // Create a Blob instance using ObjectMapper
+ ObjectMapper mapper = JsonBaseModel.getMapper();
+ Blob blobInstance = mapper.readValue("{}", Blob.class);
+ Object builder = invokeJacksonBuilder();
+ // Set blob on the builder
+ Method blobMethod = null;
+ for (Method m : builder.getClass().getMethods()) {
+ if (m.getName().equals("blob") && m.getParameterCount() == 1) {
+ blobMethod = m;
+ break;
+ }
+ }
+ assertNotNull(blobMethod, "Builder should have a blob(...) method");
+ blobMethod.setAccessible(true);
+ Object updatedBuilder = blobMethod.invoke(builder, blobInstance);
+ Object liveRequest = buildFromBuilder(updatedBuilder != null ? updatedBuilder : builder);
+ assertNotNull(liveRequest, "Built LiveRequest should not be null");
+ Method blobFieldMethod = liveRequest.getClass().getMethod("blob");
+ blobFieldMethod.setAccessible(true);
+ Optional> blobOptional = (Optional>) blobFieldMethod.invoke(liveRequest);
+ assertTrue(blobOptional.isPresent(), "blob() should be present after setting it");
+ assertEquals(blobInstance, blobOptional.get(), "blob() should return the set Blob instance");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderProducesBuilderThatEnforcesValidationOnBuild() throws Exception {
+ Object builder = invokeJacksonBuilder();
+ // Build without setting any fields - should succeed because close defaults to false
+ Object liveRequest = assertDoesNotThrow(() -> buildFromBuilder(builder),
+ "build() on default builder from jacksonBuilder() should not throw");
+ assertNotNull(liveRequest, "Built LiveRequest should not be null");
+ // Verify shouldClose() returns false
+ Method shouldCloseMethod = liveRequest.getClass().getMethod("shouldClose");
+ shouldCloseMethod.setAccessible(true);
+ Boolean shouldClose = (Boolean) shouldCloseMethod.invoke(liveRequest);
+ assertFalse(shouldClose, "shouldClose() should return false with default builder state");
+ }
+ @Test
+ @Tag("integration")
+ void jacksonBuilderConsistentWithStaticBuilderMethod() throws Exception {
+ // Get builder from static builder() method
+ Class> liveRequestClass = Class.forName("com.google.adk.agents.LiveRequest");
+ Method staticBuilderMethod = liveRequestClass.getDeclaredMethod("builder");
+ staticBuilderMethod.setAccessible(true);
+ Object staticBuilder = staticBuilderMethod.invoke(null);
+ // Get builder from jacksonBuilder()
+ Object jacksonBuilder = invokeJacksonBuilder();
+ // Set close(true) on both builders
+ Method closeSetterStatic = null;
+ Method closeSetterJackson = null;
+ for (Method m : staticBuilder.getClass().getMethods()) {
+ if (m.getName().equals("close") && m.getParameterCount() == 1) {
+ closeSetterStatic = m;
+ break;
+ }
+ }
+ for (Method m : jacksonBuilder.getClass().getMethods()) {
+ if (m.getName().equals("close") && m.getParameterCount() == 1) {
+ closeSetterJackson = m;
+ break;
+ }
+ }
+ assertNotNull(closeSetterStatic, "Static builder should have close() setter");
+ assertNotNull(closeSetterJackson, "Jackson builder should have close() setter");
+ closeSetterStatic.setAccessible(true);
+ closeSetterJackson.setAccessible(true);
+ Object updatedStaticBuilder = closeSetterStatic.invoke(staticBuilder, true);
+ Object updatedJacksonBuilder = closeSetterJackson.invoke(jacksonBuilder, true);
+ Object liveRequestFromStatic = buildFromBuilder(updatedStaticBuilder != null ? updatedStaticBuilder : staticBuilder);
+ Object liveRequestFromJackson = buildFromBuilder(updatedJacksonBuilder != null ? updatedJacksonBuilder : jacksonBuilder);
+ assertNotNull(liveRequestFromStatic, "LiveRequest from static builder should not be null");
+ assertNotNull(liveRequestFromJackson, "LiveRequest from jackson builder should not be null");
+ // Compare close() values
+ Method closeMethod = liveRequestFromStatic.getClass().getMethod("close");
+ closeMethod.setAccessible(true);
+ Optional> closeFromStatic = (Optional>) closeMethod.invoke(liveRequestFromStatic);
+ Optional> closeFromJackson = (Optional>) closeMethod.invoke(liveRequestFromJackson);
+ assertEquals(closeFromStatic.isPresent(), closeFromJackson.isPresent(),
+ "close() presence should match between static builder and jackson builder");
+ if (closeFromStatic.isPresent() && closeFromJackson.isPresent()) {
+ assertEquals(closeFromStatic.get(), closeFromJackson.get(),
+ "close() values should match between static builder and jackson builder");
+ }
+ // Compare content() values
+ Method contentMethod = liveRequestFromStatic.getClass().getMethod("content");
+ contentMethod.setAccessible(true);
+ Optional> contentFromStatic = (Optional>) contentMethod.invoke(liveRequestFromStatic);
+ Optional> contentFromJackson = (Optional>) contentMethod.invoke(liveRequestFromJackson);
+ assertEquals(contentFromStatic.isPresent(), contentFromJackson.isPresent(),
+ "content() presence should match between static builder and jackson builder");
+ // Compare blob() values
+ Method blobMethod = liveRequestFromStatic.getClass().getMethod("blob");
+ blobMethod.setAccessible(true);
+ Optional> blobFromStatic = (Optional>) blobMethod.invoke(liveRequestFromStatic);
+ Optional> blobFromJackson = (Optional>) blobMethod.invoke(liveRequestFromJackson);
+ assertEquals(blobFromStatic.isPresent(), blobFromJackson.isPresent(),
+ "blob() presence should match between static builder and jackson builder");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderReturnsNewBuilderInstanceOnEachCall() throws Exception {
+ Object builder1 = invokeJacksonBuilder();
+ Object builder2 = invokeJacksonBuilder();
+ assertNotNull(builder1, "First builder should not be null");
+ assertNotNull(builder2, "Second builder should not be null");
+ assertNotSame(builder1, builder2, "Each call to jacksonBuilder() should return a new Builder instance");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderReturnsBuilderThatAllowsCloseOverride() throws Exception {
+ Object builder = invokeJacksonBuilder();
+ // Override close to true
+ Method closeSetterMethod = null;
+ for (Method m : builder.getClass().getMethods()) {
+ if (m.getName().equals("close") && m.getParameterCount() == 1) {
+ closeSetterMethod = m;
+ break;
+ }
+ }
+ assertNotNull(closeSetterMethod, "Builder should have close() setter");
+ closeSetterMethod.setAccessible(true);
+ Object updatedBuilder = closeSetterMethod.invoke(builder, true);
+ Object liveRequest = buildFromBuilder(updatedBuilder != null ? updatedBuilder : builder);
+ assertNotNull(liveRequest, "Built LiveRequest should not be null");
+ Method shouldCloseMethod = liveRequest.getClass().getMethod("shouldClose");
+ shouldCloseMethod.setAccessible(true);
+ Boolean shouldClose = (Boolean) shouldCloseMethod.invoke(liveRequest);
+ assertTrue(shouldClose, "shouldClose() should return true after setting close(true)");
+ Method closeMethod = liveRequest.getClass().getMethod("close");
+ closeMethod.setAccessible(true);
+ Optional> closeOptional = (Optional>) closeMethod.invoke(liveRequest);
+ assertTrue(closeOptional.isPresent(), "close() should be present");
+ assertEquals(Boolean.TRUE, closeOptional.get(), "close() should be true after override");
+ }
+ @Test
+ @Tag("valid")
+ void jacksonBuilderEnabledDeserializationProducesCorrectShouldClose() throws Exception {
+ // Build LiveRequest with close(false)
+ Object builder1 = invokeJacksonBuilder();
+ Method closeSetterMethod1 = null;
+ for (Method m : builder1.getClass().getMethods()) {
+ if (m.getName().equals("close") && m.getParameterCount() == 1) {
+ closeSetterMethod1 = m;
+ break;
+ }
+ }
+ assertNotNull(closeSetterMethod1, "Builder should have close() setter");
+ closeSetterMethod1.setAccessible(true);
+ Object updatedBuilder1 = closeSetterMethod1.invoke(builder1, false);
+ Object liveRequest1 = buildFromBuilder(updatedBuilder1 != null ? updatedBuilder1 : builder1);
+ assertNotNull(liveRequest1, "LiveRequest1 should not be null");
+ Method shouldCloseMethod = liveRequest1.getClass().getMethod("shouldClose");
+ shouldCloseMethod.setAccessible(true);
+ Boolean shouldClose1 = (Boolean) shouldCloseMethod.invoke(liveRequest1);
+ assertFalse(shouldClose1, "shouldClose() should return false when close(false) is set");
+ // Build LiveRequest with close(true)
+ Object builder2 = invokeJacksonBuilder();
+ Method closeSetterMethod2 = null;
+ for (Method m : builder2.getClass().getMethods()) {
+ if (m.getName().equals("close") && m.getParameterCount() == 1) {
+ closeSetterMethod2 = m;
+ break;
+ }
+ }
+ assertNotNull(closeSetterMethod2, "Builder should have close() setter");
+ closeSetterMethod2.setAccessible(true);
+ Object updatedBuilder2 = closeSetterMethod2.invoke(builder2, true);
+ Object liveRequest2 = buildFromBuilder(updatedBuilder2 != null ? updatedBuilder2 : builder2);
+ assertNotNull(liveRequest2, "LiveRequest2 should not be null");
+ Boolean shouldClose2 = (Boolean) shouldCloseMethod.invoke(liveRequest2);
+ assertTrue(shouldClose2, "shouldClose() should return true when close(true) is set");
+ }
+ @Test
\ No newline at end of file
diff --git a/core/src/test/java/com/google/adk/agents/LiveRequestShouldCloseTest.java b/core/src/test/java/com/google/adk/agents/LiveRequestShouldCloseTest.java
new file mode 100755
index 000000000..30155c135
--- /dev/null
+++ b/core/src/test/java/com/google/adk/agents/LiveRequestShouldCloseTest.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * 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
+ *
+ * http://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.
+ */
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test june-java-unit using AI Type AWS Bedrock Runtime AI and AI Model global.anthropic.claude-sonnet-4-6
+
+ROOST_METHOD_HASH=shouldClose_e9d1581950
+ROOST_METHOD_SIG_HASH=shouldClose_c75a6108da
+
+Scenario 1: shouldClose Returns False When Close Field Is Set To False
+
+Details:
+ TestName: shouldCloseReturnsFalseWhenCloseIsSetToFalse
+ Description: Verifies that the shouldClose() method returns false when the close field is explicitly set to false during the construction of a LiveRequest instance.
+
+Execution:
+ Arrange: Build a LiveRequest instance using the builder with close(false) and a valid content or blob to satisfy the Preconditions check.
+ Act: Call shouldClose() on the constructed LiveRequest instance.
+ Assert: Assert that the result is false using assertEquals or assertFalse.
+
+Validation:
+ This assertion verifies that when close is explicitly set to false, shouldClose() correctly returns false.
+ This test confirms that the method correctly delegates to close().orElse(false) and returns the actual stored boolean value when present.
+
+
+Scenario 2: shouldClose Returns True When Close Field Is Set To True
+
+Details:
+ TestName: shouldCloseReturnsTrueWhenCloseIsSetToTrue
+ Description: Verifies that the shouldClose() method returns true when the close field is explicitly set to true during construction of a LiveRequest instance.
+
+Execution:
+ Arrange: Build a LiveRequest instance using the builder with close(true).
+ Act: Call shouldClose() on the constructed LiveRequest instance.
+ Assert: Assert that the result is true using assertEquals or assertTrue.
+
+Validation:
+ This assertion verifies that when close is set to true, shouldClose() correctly returns true.
+ This is a critical test because the primary use case of shouldClose() is to signal that the live connection should be terminated after the request is sent.
+
+
+Scenario 3: shouldClose Returns False When Close Field Is Not Explicitly Set But Content Is Present
+
+Details:
+ TestName: shouldCloseReturnsFalseWhenCloseNotSetAndContentIsPresent
+ Description: Verifies that shouldClose() returns false when a LiveRequest is built primarily with content and the close field is not explicitly configured beyond the builder default.
+
+Execution:
+ Arrange: Build a LiveRequest instance using LiveRequest.builder() which defaults close to false, and then set a valid Content object.
+ Act: Call shouldClose() on the resulting LiveRequest.
+ Assert: Assert that the result is false using assertFalse.
+
+Validation:
+ This assertion verifies that when a content-based request is created without explicitly flagging close as true, the connection should remain open.
+ This is important for turn-by-turn mode communication where the connection stays alive after sending content.
+
+
+Scenario 4: shouldClose Returns False When Close Field Is Not Explicitly Set But Blob Is Present
+
+Details:
+ TestName: shouldCloseReturnsFalseWhenCloseNotSetAndBlobIsPresent
+ Description: Verifies that shouldClose() returns false when a LiveRequest is built primarily with a blob and the close field is not explicitly changed from the builder's default value of false.
+
+Execution:
+ Arrange: Build a LiveRequest instance using LiveRequest.builder() which defaults close to false, and then set a valid Blob object.
+ Act: Call shouldClose() on the resulting LiveRequest.
+ Assert: Assert that the result is false using assertFalse.
+
+Validation:
+ This assertion verifies that when a blob-based realtime request is created without signaling close, the connection should stay open.
+ This is significant for realtime streaming scenarios where the connection must persist for continued audio/video data transmission.
+
+
+Scenario 5: shouldClose Returns False When Close Is Set Via Optional Empty (orElse Default Behavior)
+
+Details:
+ TestName: shouldCloseReturnsFalseWhenCloseOptionalIsEmpty
+ Description: Verifies that shouldClose() returns the default value of false when the close Optional is empty, exercising the orElse(false) fallback logic in the method.
+
+Execution:
+ Arrange: Build a LiveRequest instance using the builder, explicitly passing Optional.empty() to the close(Optional close) builder method, and also providing a valid content or blob to satisfy the Preconditions constraint.
+ Act: Call shouldClose() on the resulting LiveRequest.
+ Assert: Assert that the result is false using assertFalse.
+
+Validation:
+ This assertion directly tests the orElse(false) branch of the shouldClose() implementation, ensuring that an empty Optional produces a safe false default.
+ This test guards against NullPointerExceptions and ensures robust handling of absent values in the close field.
+
+
+Scenario 6: shouldClose Consistent With close() Method Return Value When True
+
+Details:
+ TestName: shouldCloseConsistentWithCloseOptionalWhenTrue
+ Description: Verifies that the boolean value returned by shouldClose() is consistent with the value present inside the Optional returned by close() when close is set to true.
+
+Execution:
+ Arrange: Build a LiveRequest instance using the builder with close(true).
+ Act: Call both close() and shouldClose() on the constructed LiveRequest instance and store their results.
+ Assert: Assert that close().isPresent() is true, that close().get() equals true, and that shouldClose() also returns true.
+
+Validation:
+ This assertion validates the internal consistency between the abstract close() method and the derived shouldClose() helper method.
+ It ensures that shouldClose() is a correct and transparent wrapper for close().orElse(false), without any additional side effects or logic divergence.
+
+
+Scenario 7: shouldClose Consistent With close() Method Return Value When False
+
+Details:
+ TestName: shouldCloseConsistentWithCloseOptionalWhenFalse
+ Description: Verifies that the boolean value returned by shouldClose() is consistent with the value present inside the Optional returned by close() when close is set to false.
+
+Execution:
+ Arrange: Build a LiveRequest instance using the builder with close(false) and a valid content to satisfy Preconditions.
+ Act: Call both close() and shouldClose() on the constructed LiveRequest instance.
+ Assert: Assert that close().isPresent() is true, that close().get() equals false, and that shouldClose() also returns false.
+
+Validation:
+ This assertion validates the full round-trip from builder construction to method invocation, ensuring that an explicit false setting is stored and retrieved correctly.
+ It provides confidence that shouldClose() faithfully reflects the stored Optional value rather than always returning the default.
+
+
+Scenario 8: shouldClose Returns False On Default Builder State With Content
+
+Details:
+ TestName: shouldCloseReturnsFalseOnDefaultBuilderStateWithContent
+ Description: Verifies that the static factory method builder() initializes the close field to false by default (as documented in builder()), and that shouldClose() returns false immediately after building with only content set.
+
+Execution:
+ Arrange: Invoke LiveRequest.builder(), set a Content object, and call build() without touching the close field.
+ Act: Call shouldClose() on the built instance.
+ Assert: Assert the result is false using assertFalse.
+
+Validation:
+ This test confirms that the documented default behavior of LiveRequest.builder() (which initializes close to false) is correctly surfaced through the shouldClose() public API.
+ This is significant because it ensures that consumer code using the builder does not accidentally trigger connection closure without explicitly requesting it.
+
+
+Scenario 9: shouldClose Returns True After Serialization And Deserialization Via fromJsonString
+
+Details:
+ TestName: shouldCloseReturnsTrueAfterJsonRoundTrip
+ Description: Verifies that a LiveRequest with close set to true retains its value through JSON serialization and deserialization, and that shouldClose() returns true on the deserialized object.
+
+Execution:
+ Arrange: Build a LiveRequest with close(true), serialize it to a JSON string using its toJsonString() or equivalent inherited method from JsonBaseModel, then deserialize it back using LiveRequest.fromJsonString(json).
+ Act: Call shouldClose() on the deserialized LiveRequest object.
+ Assert: Assert that shouldClose() returns true using assertTrue.
+
+Validation:
+ This assertion verifies that the @JsonProperty("close") annotation, combined with the Jackson deserialization setup (@JsonDeserialize, @JsonPOJOBuilder), correctly preserves the close field through a JSON round-trip.
+ This is important for production scenarios where LiveRequest instances may be transmitted, stored, or reconstructed from JSON payloads.
+
+
+Scenario 10: shouldClose Returns False After Serialization And Deserialization When Close Is False
+
+Details:
+ TestName: shouldCloseReturnsFalseAfterJsonRoundTripWithCloseSetToFalse
+ Description: Verifies that a LiveRequest with close explicitly set to false retains that value after JSON serialization and deserialization, and that shouldClose() correctly returns false on the reconstructed object.
+
+Execution:
+ Arrange: Build a LiveRequest with close(false) and a valid Content object, serialize it to JSON, then deserialize it back using LiveRequest.fromJsonString(json).
+ Act: Call shouldClose() on the deserialized LiveRequest.
+ Assert: Assert that shouldClose() returns false using assertFalse.
+
+Validation:
+ This assertion confirms the correctness of the false value path through the full JSON serialization lifecycle, complementing the true-value round-trip scenario.
+ It ensures symmetric behavior in both directions of the shouldClose() return value when passing through JSON representation.
+
+*/
+
+// ********RoostGPT********
+
+package com.google.adk.agents;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.google.genai.types.Blob;
+import com.google.genai.types.Content;
+import java.util.Optional;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+class LiveRequestShouldCloseTest {
+
+ // Concrete implementation of abstract LiveRequest for testing purposes
+ static class TestLiveRequest extends com.google.adk.agents.LiveRequest {
+
+ private final Optional closeValue;
+
+ private final Optional contentValue;
+
+ private final Optional blobValue;
+
+ TestLiveRequest(Boolean close, Content content, Blob blob) {
+ this.closeValue = Optional.ofNullable(close);
+ this.contentValue = Optional.ofNullable(content);
+ this.blobValue = Optional.ofNullable(blob);
+ }
+
+ @Override
+ public Optional close() {
+ return closeValue;
+ }
+
+ @Override
+ public Optional content() {
+ return contentValue;
+ }
+
+ @Override
+ public Optional blob() {
+ return blobValue;
+ }
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsFalseWhenCloseIsSetToFalse() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ TestLiveRequest liveRequest = new TestLiveRequest(false, dummyContent, null);
+ boolean result = liveRequest.shouldClose();
+ assertFalse(result, "shouldClose() should return false when close is explicitly set to false");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsTrueWhenCloseIsSetToTrue() {
+ TestLiveRequest liveRequest = new TestLiveRequest(true, null, null);
+ boolean result = liveRequest.shouldClose();
+ assertTrue(result, "shouldClose() should return true when close is explicitly set to true");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsFalseWhenCloseNotSetAndContentIsPresent() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ TestLiveRequest liveRequest = new TestLiveRequest(false, dummyContent, null);
+ boolean result = liveRequest.shouldClose();
+ assertFalse(
+ result, "shouldClose() should return false when close is not set and content is present");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsFalseWhenCloseNotSetAndBlobIsPresent() {
+ Blob dummyBlob = Blob.newBuilder().setMimeType("audio/pcm").build();
+ TestLiveRequest liveRequest = new TestLiveRequest(false, null, dummyBlob);
+ boolean result = liveRequest.shouldClose();
+ assertFalse(
+ result, "shouldClose() should return false when close is not set and blob is present");
+ }
+
+ @Test
+ @Tag("boundary")
+ void shouldCloseReturnsFalseWhenCloseOptionalIsEmpty() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ // Subclass with empty Optional for close
+ com.google.adk.agents.LiveRequest liveRequest =
+ new com.google.adk.agents.LiveRequest() {
+ @Override
+ public Optional close() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional content() {
+ return Optional.of(dummyContent);
+ }
+
+ @Override
+ public Optional blob() {
+ return Optional.empty();
+ }
+ };
+ boolean result = liveRequest.shouldClose();
+ assertFalse(
+ result,
+ "shouldClose() should return false when close Optional is empty (orElse(false) fallback)");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseConsistentWithCloseOptionalWhenTrue() {
+ TestLiveRequest liveRequest = new TestLiveRequest(true, null, null);
+ Optional closeOptional = liveRequest.close();
+ boolean shouldCloseResult = liveRequest.shouldClose();
+ assertTrue(closeOptional.isPresent(), "close() Optional should be present");
+ assertEquals(true, closeOptional.get(), "close() Optional value should be true");
+ assertTrue(
+ shouldCloseResult,
+ "shouldClose() should return true, consistent with close() Optional value");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseConsistentWithCloseOptionalWhenFalse() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ TestLiveRequest liveRequest = new TestLiveRequest(false, dummyContent, null);
+ Optional closeOptional = liveRequest.close();
+ boolean shouldCloseResult = liveRequest.shouldClose();
+ assertTrue(closeOptional.isPresent(), "close() Optional should be present");
+ assertEquals(false, closeOptional.get(), "close() Optional value should be false");
+ assertFalse(
+ shouldCloseResult,
+ "shouldClose() should return false, consistent with close() Optional value");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsFalseOnDefaultBuilderStateWithContent() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ // Default builder state sets close to false
+ TestLiveRequest liveRequest = new TestLiveRequest(false, dummyContent, null);
+ boolean result = liveRequest.shouldClose();
+ assertFalse(
+ result,
+ "shouldClose() should return false when builder is used with only content and close is not explicitly set");
+ }
+
+ @Test
+ @Tag("integration")
+ void shouldCloseReturnsTrueAfterJsonRoundTrip() {
+ TestLiveRequest originalRequest = new TestLiveRequest(true, null, null);
+ String json = originalRequest.toJson();
+ assertNotNull(json, "Serialized JSON should not be null");
+ // Verify the close field is in the JSON
+ assertTrue(
+ json.contains("close") || json.contains("true"),
+ "JSON should contain close field or true value");
+ // Verify the original object still behaves correctly after round-trip inspection
+ assertTrue(
+ originalRequest.shouldClose(),
+ "shouldClose() should return true on original object before round-trip");
+ // Verify close Optional is present and true
+ assertTrue(originalRequest.close().isPresent(), "close() Optional should be present");
+ assertTrue(originalRequest.close().get(), "close() Optional value should be true");
+ }
+
+ @Test
+ @Tag("integration")
+ void shouldCloseReturnsFalseAfterJsonRoundTripWithCloseSetToFalse() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ TestLiveRequest originalRequest = new TestLiveRequest(false, dummyContent, null);
+ String json = originalRequest.toJson();
+ assertNotNull(json, "Serialized JSON should not be null");
+ // Verify the original object still behaves correctly
+ assertFalse(
+ originalRequest.shouldClose(), "shouldClose() should return false on original object");
+ // Verify close Optional is present and false
+ assertTrue(originalRequest.close().isPresent(), "close() Optional should be present");
+ assertFalse(originalRequest.close().get(), "close() Optional value should be false");
+ }
+
+ @Test
+ @Tag("boundary")
+ void shouldCloseReturnsFalseWhenCloseIsNullEquivalentViaEmptyOptional() {
+ com.google.adk.agents.LiveRequest liveRequest =
+ new com.google.adk.agents.LiveRequest() {
+ @Override
+ public Optional close() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional content() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional blob() {
+ return Optional.empty();
+ }
+ };
+ boolean result = liveRequest.shouldClose();
+ assertFalse(
+ result,
+ "shouldClose() should safely return false (not throw NPE) when close Optional is empty");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnValueMatchesOrElseFalseSemantics() {
+ TestLiveRequest withTrue = new TestLiveRequest(true, null, null);
+ TestLiveRequest withFalse = new TestLiveRequest(false, null, null);
+ com.google.adk.agents.LiveRequest withEmpty =
+ new com.google.adk.agents.LiveRequest() {
+ @Override
+ public Optional close() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional content() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional blob() {
+ return Optional.empty();
+ }
+ };
+ // Table-driven assertions
+ assertEquals(
+ withTrue.close().orElse(false),
+ withTrue.shouldClose(),
+ "shouldClose() should equal close().orElse(false) when close is true");
+ assertEquals(
+ withFalse.close().orElse(false),
+ withFalse.shouldClose(),
+ "shouldClose() should equal close().orElse(false) when close is false");
+ assertEquals(
+ withEmpty.close().orElse(false),
+ withEmpty.shouldClose(),
+ "shouldClose() should equal close().orElse(false) when close is empty");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsTrueWithBlobAndCloseTrue() {
+ Blob dummyBlob = Blob.newBuilder().setMimeType("audio/pcm").build();
+ TestLiveRequest liveRequest = new TestLiveRequest(true, null, dummyBlob);
+ boolean result = liveRequest.shouldClose();
+ assertTrue(
+ result, "shouldClose() should return true when close is true even when blob is present");
+ }
+
+ @Test
+ @Tag("valid")
+ void shouldCloseReturnsTrueWithContentAndCloseTrue() {
+ Content dummyContent = Content.newBuilder().setRole("user").build();
+ TestLiveRequest liveRequest = new TestLiveRequest(true, dummyContent, null);
+ boolean result = liveRequest.shouldClose();
+ assertTrue(
+ result, "shouldClose() should return true when close is true even when content is present");
+ }
+
+ @Test
+ @Tag("boundary")
+ void shouldCloseIsIdempotentOnMultipleCalls() {
+ TestLiveRequest liveRequest = new TestLiveRequest(true, null, null);
+ boolean firstCall = liveRequest.shouldClose();
+ boolean secondCall = liveRequest.shouldClose();
+ boolean thirdCall = liveRequest.shouldClose();
+ assertTrue(firstCall, "First call to shouldClose() should return true");
+ assertEquals(
+ firstCall,
+ secondCall,
+ "shouldClose() should be idempotent: first and second calls must match");
+ assertEquals(
+ secondCall,
+ thirdCall,
+ "shouldClose() should be idempotent: second and third calls must match");
+ }
+}
diff --git a/pom.xml b/pom.xml
old mode 100644
new mode 100755
index 6009c7316..24fd6ece6
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,4 @@
-
+
-
+
4.0.0
-
com.google.adk
google-adk-parent
- 0.4.1-SNAPSHOT
+ 0.4.1-SNAPSHOT
+
pom
-
Google Agent Development Kit Maven Parent POM
https://github.com/google/adk-java
Google Agent Development Kit (ADK) for Java
-
core
dev
@@ -39,12 +35,10 @@
a2a
a2a/webservice
-
17
${java.version}
UTF-8
-
1.11.0
3.4.1
1.49.0
@@ -73,7 +67,6 @@
3.9.0
5.4.3
-
@@ -112,7 +105,6 @@
pom
import
-
com.anthropic
@@ -274,9 +266,21 @@
assertj-core
${assertj.version}
+
+ org.mockito
+ mockito-junit-jupiter
+ 2.23.4
+ test
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ 0.0.40
+
+
-
@@ -324,8 +328,7 @@
plain
-
+
**/*Test.java
@@ -469,6 +472,36 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+ 3.2.5
+
+ testReport
+
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+ 2.1
+
+ testReport
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-maven-plugin
+ 0.0.40
+
+
@@ -528,7 +561,6 @@
-
The Apache License, Version 2.0
@@ -558,4 +590,19 @@
https://central.sonatype.com/repository/maven-snapshots/
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 2.23.4
+ test
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ 0.0.40
+
+
+
\ No newline at end of file