From 06cbb11993f68f9430c0cc2e08909bd38ce39e1b Mon Sep 17 00:00:00 2001 From: roost-io <8110509+mgdevstack@users.noreply.github.com> Date: Wed, 24 Jun 2026 12:41:49 +0530 Subject: [PATCH] Unit test generated by RoostGPT Using AI Model global.anthropic.claude-sonnet-4-6 --- core/pom.xml | 21 +- ...cationContextActiveStreamingToolsTest.java | 440 +++++ .../agents/InvocationContextAgentTest.java | 681 +++++++ .../agents/InvocationContextAppNameTest.java | 347 ++++ .../InvocationContextArtifactServiceTest.java | 560 ++++++ .../InvocationContextBranch837Test.java | 434 ++++ .../agents/InvocationContextBranchTest.java | 395 ++++ .../agents/InvocationContextBuilderTest.java | 1760 +++++++++++++++++ .../agents/InvocationContextCopyOfTest.java | 497 +++++ .../InvocationContextCreate573Test.java | 384 ++++ .../agents/InvocationContextCreateTest.java | 464 +++++ .../InvocationContextEndInvocationTest.java | 593 ++++++ .../agents/InvocationContextEqualsTest.java | 515 +++++ .../agents/InvocationContextHashCodeTest.java | 482 +++++ ...tionContextIncrementLlmCallsCountTest.java | 543 +++++ .../InvocationContextInvocationIdTest.java | 702 +++++++ .../InvocationContextIsResumableTest.java | 439 ++++ ...InvocationContextLiveRequestQueueTest.java | 477 +++++ .../InvocationContextMemoryServiceTest.java | 557 ++++++ ...tionContextNewInvocationContextIdTest.java | 269 +++ .../InvocationContextPluginManagerTest.java | 738 +++++++ .../InvocationContextRunConfigTest.java | 435 ++++ .../InvocationContextSessionServiceTest.java | 720 +++++++ .../agents/InvocationContextSessionTest.java | 1005 ++++++++++ ...ationContextShouldPauseInvocationTest.java | 604 ++++++ .../InvocationContextUserContentTest.java | 635 ++++++ .../agents/InvocationContextUserIdTest.java | 371 ++++ pom.xml | 79 +- 28 files changed, 15123 insertions(+), 24 deletions(-) create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextActiveStreamingToolsTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextAgentTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextAppNameTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextArtifactServiceTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextBranch837Test.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextBranchTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextBuilderTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextCopyOfTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextCreate573Test.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextCreateTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextEndInvocationTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextEqualsTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextHashCodeTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextIncrementLlmCallsCountTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextInvocationIdTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextIsResumableTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextLiveRequestQueueTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextMemoryServiceTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextNewInvocationContextIdTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextPluginManagerTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextRunConfigTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextSessionServiceTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextSessionTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextShouldPauseInvocationTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextUserContentTest.java create mode 100644 core/src/test/java/com/google/adk/agents/InvocationContextUserIdTest.java diff --git a/core/pom.xml b/core/pom.xml index fe65715f3..7d2032c7e 100644 --- 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/InvocationContextActiveStreamingToolsTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextActiveStreamingToolsTest.java new file mode 100644 index 000000000..efdcff440 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextActiveStreamingToolsTest.java @@ -0,0 +1,440 @@ +/* + * 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=activeStreamingTools_c4cc5030aa +ROOST_METHOD_SIG_HASH=activeStreamingTools_398f84db97 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +"Scenario 1: Verify activeStreamingTools Returns an Empty Map on Freshly Built InvocationContext + +Details: + TestName: activeStreamingToolsReturnsEmptyMapOnFreshContext + Description: Verifies that when a new InvocationContext is built using the builder with no streaming tools added, + the activeStreamingTools() method returns an empty (but non-null) map. This confirms the field is + properly initialized as an empty ConcurrentHashMap. + +Execution: + Arrange: Build an InvocationContext using InvocationContext.builder() with the required fields + (sessionService, artifactService, memoryService, pluginManager, invocationId, agent, session, + userContent, runConfig, endInvocation) without adding any active streaming tools. + Act: Call activeStreamingTools() on the newly built InvocationContext instance. + Assert: Assert that the returned map is not null. + Assert that the returned map is empty (size == 0). + +Validation: + The assertion verifies that the ConcurrentHashMap backing activeStreamingTools is initialized to an empty state + by default. This is important to ensure that no stale or unexpected tool entries exist at the start of a new + invocation, preventing incorrect behavior in streaming tool management. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Map; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextActiveStreamingToolsTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private BaseAgent mockAgent; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ActiveStreamingTool mockActiveTool1; + + @Mock + private ActiveStreamingTool mockActiveTool2; + + private InvocationContext invocationContext; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .endInvocation(false) + .build(); + } + + @Test + @Tag("valid") + void activeStreamingToolsReturnsEmptyMapOnFreshContext() { + // Act + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result, "activeStreamingTools map should not be null"); + assertTrue(result.isEmpty(), "activeStreamingTools map should be empty on a freshly built context"); + assertEquals(0, result.size(), "activeStreamingTools map size should be 0 on a freshly built context"); + } + + @Test + @Tag("valid") + void activeStreamingToolsReturnsSameMapInstance() { + // Act + Map result1 = invocationContext.activeStreamingTools(); + Map result2 = invocationContext.activeStreamingTools(); + // Assert + assertSame(result1, result2, "activeStreamingTools should return the same map instance on repeated calls"); + } + + @Test + @Tag("valid") + void activeStreamingToolsReturnsMapWithAddedTool() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + // Act + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertEquals(1, result.size()); + assertTrue(result.containsKey("tool1")); + assertEquals(mockActiveTool1, result.get("tool1")); + } + + @Test + @Tag("valid") + void activeStreamingToolsReturnsMapWithMultipleTools() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + tools.put("tool2", mockActiveTool2); + // Act + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertEquals(2, result.size()); + assertTrue(result.containsKey("tool1")); + assertTrue(result.containsKey("tool2")); + assertEquals(mockActiveTool1, result.get("tool1")); + assertEquals(mockActiveTool2, result.get("tool2")); + } + + @Test + @Tag("valid") + void activeStreamingToolsMapIsMutableAndReflectsRemovals() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + tools.put("tool2", mockActiveTool2); + // Act + tools.remove("tool1"); + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertEquals(1, result.size()); + assertFalse(result.containsKey("tool1")); + assertTrue(result.containsKey("tool2")); + } + + @Test + @Tag("valid") + void activeStreamingToolsIsNotNullWhenBuiltWithMinimalFields() { + // Arrange + InvocationContext minimalContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .agent(mockAgent) + .runConfig(mockRunConfig) + .build(); + // Act + Map result = minimalContext.activeStreamingTools(); + // Assert + assertNotNull(result, "activeStreamingTools should not be null even with minimal builder setup"); + assertTrue(result.isEmpty(), "activeStreamingTools should be empty on minimal context"); + } + + @Test + @Tag("valid") + void activeStreamingToolsCopiedCorrectlyViaCopyOf() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(invocationContext); + Map copiedTools = copiedContext.activeStreamingTools(); + // Assert + assertNotNull(copiedTools); + assertEquals(1, copiedTools.size()); + assertTrue(copiedTools.containsKey("tool1")); + assertEquals(mockActiveTool1, copiedTools.get("tool1")); + } + + @Test + @Tag("valid") + void activeStreamingToolsCopyIsIndependentFromOriginal() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + InvocationContext copiedContext = InvocationContext.copyOf(invocationContext); + // Act - modify the copy + copiedContext.activeStreamingTools().put("tool2", mockActiveTool2); + // Assert - original should still have only tool1 + assertEquals(1, invocationContext.activeStreamingTools().size()); + assertEquals(2, copiedContext.activeStreamingTools().size()); + } + + @Test + @Tag("valid") + void activeStreamingToolsEmptyOnCopyOfFreshContext() { + // Arrange + InvocationContext freshContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .agent(mockAgent) + .runConfig(mockRunConfig) + .build(); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(freshContext); + Map result = copiedContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + @Tag("valid") + void activeStreamingToolsMapKeySet() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("toolAlpha", mockActiveTool1); + tools.put("toolBeta", mockActiveTool2); + // Act + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertTrue(result.keySet().contains("toolAlpha")); + assertTrue(result.keySet().contains("toolBeta")); + assertEquals(2, result.keySet().size()); + } + + @Test + @Tag("valid") + void activeStreamingToolsMapValuesContainExpectedTools() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + tools.put("tool2", mockActiveTool2); + // Act + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertTrue(result.values().contains(mockActiveTool1)); + assertTrue(result.values().contains(mockActiveTool2)); + } + + @Test + @Tag("boundary") + void activeStreamingToolsMapReturnsNullForMissingKey() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + // Act + ActiveStreamingTool result = invocationContext.activeStreamingTools().get("nonExistentTool"); + // Assert + assertNull(result, "Getting a non-existent key should return null"); + } + + @Test + @Tag("boundary") + void activeStreamingToolsMapHandlesClearOperation() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + tools.put("tool2", mockActiveTool2); + // Act + tools.clear(); + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertTrue(result.isEmpty()); + assertEquals(0, result.size()); + } + + @Test + @Tag("boundary") + void activeStreamingToolsMapOverwritesExistingKey() { + // Arrange + Map tools = invocationContext.activeStreamingTools(); + tools.put("tool1", mockActiveTool1); + // Act + tools.put("tool1", mockActiveTool2); + Map result = invocationContext.activeStreamingTools(); + // Assert + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(mockActiveTool2, result.get("tool1"), "Value should be updated when same key is inserted"); + } + + @Test + @Tag("integration") + void activeStreamingToolsIntegratesWithCreateFactory() { + // Arrange + Content userContent = mock(Content.class); + InvocationContext contextFromFactory = InvocationContext.create(mockSessionService, mockArtifactService, + "integration-invocation-id", mockAgent, mockSession, userContent, mockRunConfig); + // Act + Map result = contextFromFactory.activeStreamingTools(); + // Assert + assertNotNull(result, "activeStreamingTools should not be null from create factory"); + assertTrue(result.isEmpty(), "activeStreamingTools should be empty from create factory"); + } + + @Test + @Tag("integration") + void activeStreamingToolsIntegratesWithLiveCreateFactory() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext contextFromFactory = InvocationContext.create(mockSessionService, mockArtifactService, + mockAgent, mockSession, liveRequestQueue, mockRunConfig); + // Act + Map result = contextFromFactory.activeStreamingTools(); + // Assert + assertNotNull(result, "activeStreamingTools should not be null from live create factory"); + assertTrue(result.isEmpty(), "activeStreamingTools should be empty from live create factory"); + } + + @Test + @Tag("integration") + void activeStreamingToolsUsedInEqualsComparison() { + // Arrange + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .agent(mockAgent) + .runConfig(mockRunConfig) + .invocationId("same-id") + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .agent(mockAgent) + .runConfig(mockRunConfig) + .invocationId("same-id") + .build(); + // Both have empty activeStreamingTools + // Act + Map tools1 = context1.activeStreamingTools(); + Map tools2 = context2.activeStreamingTools(); + // Assert + assertEquals(tools1, tools2, "Two fresh contexts should have equal (empty) activeStreamingTools maps"); + assertTrue(context1.equals(context2), "Two contexts with same fields should be equal"); + } + + @Test + @Tag("integration") + void activeStreamingToolsMutationAffectsEqualityCheck() { + // Arrange + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .agent(mockAgent) + .runConfig(mockRunConfig) + .invocationId("same-id") + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .agent(mockAgent) + .runConfig(mockRunConfig) + .invocationId("same-id") + .build(); + // Act - modify one context's streaming tools + context1.activeStreamingTools().put("tool1", mockActiveTool1); + // Assert + assertNotEquals(context1.activeStreamingTools(), context2.activeStreamingTools(), + "After mutation, activeStreamingTools maps should differ"); + assertFalse(context1.equals(context2), "Contexts with different activeStreamingTools should not be equal"); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextAgentTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextAgentTest.java new file mode 100644 index 000000000..5a52f3b9b --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextAgentTest.java @@ -0,0 +1,681 @@ +/* + * 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=agent_9b91251448 +ROOST_METHOD_SIG_HASH=agent_877597f15f + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +" + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/SequentialAgentTest.java +Tests: + "@Test +public void runAsync_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runAsync(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +" + "@Test +public void runLive_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent_live"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgentLive").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runLive(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +"Scenario 1: Verify agent() Returns the Initially Set Agent + +Details: + TestName: agentReturnsInitiallySetAgent + Description: Verifies that the agent() method returns the exact BaseAgent instance that was set during the construction of the InvocationContext via the builder. + +Execution: + Arrange: + - Create a mock of BaseAgent (mockAgent). + - Build an InvocationContext using the builder, setting mockAgent as the agent along with other required fields (sessionService, artifactService, memoryService, session). + Act: + - Call context.agent() on the constructed InvocationContext. + Assert: + - Assert that the returned value from context.agent() is equal to mockAgent. + +Validation: + The assertion confirms that the agent() getter faithfully returns the BaseAgent reference stored during construction. This is critical because the invocation context's agent field determines which agent handles the current invocation, and an incorrect return value would cause delegation failures. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class InvocationContextAgentTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private BaseAgent mockAgent; + + @Mock + private BaseAgent mockAgent2; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + private InvocationContext invocationContext; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + @Test + @Tag("valid") + void agentReturnsInitiallySetAgent() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertEquals(mockAgent, result); + } + + @Test + @Tag("valid") + void agentReturnsCorrectAgentAfterBuilderConstruction() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-001") + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent returnedAgent = invocationContext.agent(); + // Assert + assertSame(mockAgent, returnedAgent, + "agent() should return the same instance that was set during construction"); + } + + @Test + @Tag("valid") + void agentReturnsSameReferenceNotACopy() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-ref-test") + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent firstCall = invocationContext.agent(); + BaseAgent secondCall = invocationContext.agent(); + // Assert + assertSame(firstCall, secondCall, "Multiple calls to agent() should return the same reference"); + } + + @Test + @Tag("valid") + void agentReturnsUpdatedAgentAfterSetterCall() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-update-test") + .runConfig(mockRunConfig) + .build(); + // Act + invocationContext.agent(mockAgent2); + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertEquals(mockAgent2, result); + assertNotEquals(mockAgent, result); + } + + @Test + @Tag("valid") + void agentReturnsPreviousAgentBeforeUpdate() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-before-update") + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent beforeUpdate = invocationContext.agent(); + invocationContext.agent(mockAgent2); + BaseAgent afterUpdate = invocationContext.agent(); + // Assert + assertSame(mockAgent, beforeUpdate); + assertSame(mockAgent2, afterUpdate); + assertNotSame(beforeUpdate, afterUpdate); + } + + @Test + @Tag("valid") + void agentReturnsCorrectAgentWhenCreatedWithStaticCreateMethod() { + // Arrange + Content userContent = mock(Content.class); + invocationContext = InvocationContext.create(mockSessionService, mockArtifactService, "inv-static-create", + mockAgent, mockSession, userContent, mockRunConfig); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertEquals(mockAgent, result); + } + + @Test + @Tag("valid") + void agentReturnsCorrectAgentWhenCreatedWithLiveRequestQueueStaticCreateMethod() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + invocationContext = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, mockSession, + liveRequestQueue, mockRunConfig); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertEquals(mockAgent, result); + } + + @Test + @Tag("valid") + void agentReturnsSameAgentFromCopiedContext() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-copy-test") + .runConfig(mockRunConfig) + .build(); + InvocationContext copied = InvocationContext.copyOf(original); + // Act + BaseAgent originalAgent = original.agent(); + BaseAgent copiedAgent = copied.agent(); + // Assert + assertNotNull(copiedAgent); + assertSame(originalAgent, copiedAgent, "Copied context should have the same agent reference"); + } + + @Test + @Tag("valid") + void agentChangeInCopiedContextDoesNotAffectOriginal() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-independence-test") + .runConfig(mockRunConfig) + .build(); + InvocationContext copied = InvocationContext.copyOf(original); + // Act + copied.agent(mockAgent2); + // Assert + assertSame(mockAgent, original.agent(), "Changing agent in copied context should not affect original"); + assertSame(mockAgent2, copied.agent(), "Copied context should have the updated agent"); + } + + @Test + @Tag("valid") + void agentReturnsMockAgentWithCorrectName() { + // Arrange + when(mockAgent.name()).thenReturn("testAgentName"); + invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-name-check") + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertEquals("testAgentName", result.name()); + } + + @Test + @Tag("boundary") + void agentReturnsNullWhenSetToNull() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .session(mockSession) + .invocationId("inv-null-agent") + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNull(result, "agent() should return null when no agent was set during construction"); + } + + @Test + @Tag("boundary") + void agentReturnsNullAfterExplicitlySetToNull() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-set-null-agent") + .runConfig(mockRunConfig) + .build(); + // Act + invocationContext.agent(null); + BaseAgent result = invocationContext.agent(); + // Assert + assertNull(result, "agent() should return null after explicitly setting agent to null"); + } + + @Test + @Tag("integration") + void agentIsCorrectlySetAndRetrievedInFullContextWithAllFields() { + // Arrange + when(mockAgent.name()).thenReturn("fullContextAgent"); + when(mockAgent.description()).thenReturn("Full context agent description"); + invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-full-context") + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .branch(Optional.of("test-branch")) + .endInvocation(false) + .build(); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertSame(mockAgent, result); + assertEquals("fullContextAgent", result.name()); + assertEquals("Full context agent description", result.description()); + } + + @Test + @Tag("integration") + void agentIsConsistentWithOtherContextFieldsAfterConstruction() { + // Arrange + String invocationId = "inv-consistency-test"; + when(mockAgent.name()).thenReturn("consistencyAgent"); + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId(invocationId) + .runConfig(mockRunConfig) + .build(); + // Act + BaseAgent result = invocationContext.agent(); + // Assert + assertNotNull(result); + assertSame(mockAgent, result); + assertEquals(invocationId, invocationContext.invocationId()); + assertSame(mockSession, invocationContext.session()); + assertSame(mockSessionService, invocationContext.sessionService()); + } + + @Test + @Tag("integration") + void agentFieldParticipatesInEquality() { + // Arrange + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-equality-test") + .runConfig(mockRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-equality-test") + .runConfig(mockRunConfig) + .build(); + InvocationContext context3 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent2) + .session(mockSession) + .invocationId("inv-equality-test") + .runConfig(mockRunConfig) + .build(); + // Act & Assert + assertSame(mockAgent, context1.agent()); + assertSame(mockAgent, context2.agent()); + assertSame(mockAgent2, context3.agent()); + assertEquals(context1, context2, "Contexts with same fields including agent should be equal"); + assertNotEquals(context1, context3, "Contexts with different agents should not be equal"); + } + + @Test + @Tag("valid") + void agentSetViaSetterOverridesBuilderValue() { + // Arrange + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-override-test") + .runConfig(mockRunConfig) + .build(); + // Verify initial state + assertSame(mockAgent, invocationContext.agent()); + // Act + invocationContext.agent(mockAgent2); + // Assert + assertSame(mockAgent2, invocationContext.agent()); + assertNotSame(mockAgent, invocationContext.agent()); + } + + @Test + @Tag("valid") + void agentCanBeUpdatedMultipleTimes() { + // Arrange + BaseAgent mockAgent3 = mock(BaseAgent.class); + invocationContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("inv-multiple-updates") + .runConfig(mockRunConfig) + .build(); + // Act & Assert - Multiple updates + assertSame(mockAgent, invocationContext.agent()); + invocationContext.agent(mockAgent2); + assertSame(mockAgent2, invocationContext.agent()); + invocationContext.agent(mockAgent3); + assertSame(mockAgent3, invocationContext.agent()); + invocationContext.agent(mockAgent); + assertSame(mockAgent, invocationContext.agent()); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextAppNameTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextAppNameTest.java new file mode 100644 index 000000000..77a8e906d --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextAppNameTest.java @@ -0,0 +1,347 @@ +/* + * 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=appName_a8fa25d446 +ROOST_METHOD_SIG_HASH=appName_e2ea244c93 + +Scenario 1: Return Application Name from a Valid Session + +Details: + TestName: appNameReturnsSessionAppName + Description: Verifies that the `appName()` method correctly delegates to the underlying + `Session` object and returns the application name stored in the session. + This is the primary happy-path scenario. +Execution: + Arrange: - Create a mock `Session` object. + - Configure the mock `Session` to return a specific, non-null string (e.g., "MyTestApp") + when `appName()` is called on it. + - Build an `InvocationContext` using `InvocationContext.builder()`, setting the + mocked `Session` via `.session(mockSession)`, and providing any other required + builder parameters (e.g., `sessionService`, `artifactService`, `agent`). + Act: - Call `invocationContext.appName()` on the constructed `InvocationContext` instance. + Assert: - Use `assertEquals("MyTestApp", invocationContext.appName())` to verify the + return value matches the expected application name. +Validation: + This assertion confirms that `appName()` correctly propagates the return value from + `session.appName()` without any modification or transformation. It validates the + delegation behavior that is fundamental to how `InvocationContext` exposes session data. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextAppNameTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private BaseAgent mockAgent; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + private RunConfig defaultRunConfig; + + @BeforeEach + void setUp() { + defaultRunConfig = RunConfig.builder().build(); + } + + private InvocationContext buildContext(Session session) { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(session) + .runConfig(defaultRunConfig) + .invocationId("test-invocation-id") + .build(); + } + + @Test + @Tag("valid") + void appNameReturnsSessionAppName() { + when(mockSession.appName()).thenReturn("MyTestApp"); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals("MyTestApp", result); + verify(mockSession, times(1)).appName(); + } + + @Test + @Tag("valid") + void appNameReturnsCorrectValueWhenSessionHasTypicalAppName() { + when(mockSession.appName()).thenReturn("ProductionApp"); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals("ProductionApp", result); + assertNotNull(result); + } + + @Test + @Tag("valid") + void appNameDelegatesCallToUnderlyingSession() { + when(mockSession.appName()).thenReturn("DelegationTestApp"); + InvocationContext invocationContext = buildContext(mockSession); + invocationContext.appName(); + verify(mockSession).appName(); + } + + @Test + @Tag("valid") + void appNameReturnsSameValueOnMultipleCalls() { + when(mockSession.appName()).thenReturn("StableApp"); + InvocationContext invocationContext = buildContext(mockSession); + String firstCall = invocationContext.appName(); + String secondCall = invocationContext.appName(); + String thirdCall = invocationContext.appName(); + assertEquals("StableApp", firstCall); + assertEquals("StableApp", secondCall); + assertEquals("StableApp", thirdCall); + assertEquals(firstCall, secondCall); + assertEquals(secondCall, thirdCall); + verify(mockSession, times(3)).appName(); + } + + @Test + @Tag("valid") + void appNameReturnsAppNameFromCreateStaticMethod() { + when(mockSession.appName()).thenReturn("StaticCreateApp"); + InvocationContext invocationContext = + InvocationContext.create( + mockSessionService, + mockArtifactService, + "static-invocation-id", + mockAgent, + mockSession, + null, + defaultRunConfig); + String result = invocationContext.appName(); + assertEquals("StaticCreateApp", result); + } + + @Test + @Tag("valid") + void appNameReturnedFromCopiedContext() { + when(mockSession.appName()).thenReturn("CopiedContextApp"); + InvocationContext originalContext = buildContext(mockSession); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + String result = copiedContext.appName(); + assertEquals("CopiedContextApp", result); + } + + @Test + @Tag("boundary") + void appNameReturnsEmptyStringWhenSessionAppNameIsEmpty() { + when(mockSession.appName()).thenReturn(""); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertNotNull(result); + assertEquals("", result); + } + + @Test + @Tag("boundary") + void appNameReturnsSingleCharacterAppName() { + when(mockSession.appName()).thenReturn("A"); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals("A", result); + assertNotNull(result); + } + + @Test + @Tag("boundary") + void appNameReturnsVeryLongAppName() { + String longAppName = "A".repeat(1000); + when(mockSession.appName()).thenReturn(longAppName); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals(longAppName, result); + assertNotNull(result); + assertEquals(1000, result.length()); + } + + @Test + @Tag("boundary") + void appNameReturnsAppNameWithSpecialCharacters() { + String specialAppName = "App-Name_With.Special@Characters#123"; + when(mockSession.appName()).thenReturn(specialAppName); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals(specialAppName, result); + assertNotNull(result); + } + + @Test + @Tag("boundary") + void appNameReturnsAppNameWithWhitespace() { + when(mockSession.appName()).thenReturn(" App With Spaces "); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals(" App With Spaces ", result); + assertNotNull(result); + } + + @Test + @Tag("boundary") + void appNameReturnsNullWhenSessionAppNameIsNull() { + when(mockSession.appName()).thenReturn(null); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertNull(result); + } + + @Test + @Tag("integration") + void appNameWorksWithFullyConfiguredContext() { + when(mockSession.appName()).thenReturn("FullyConfiguredApp"); + InvocationContext invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .invocationId("full-invocation-id") + .branch("main-branch") + .userContent(Optional.empty()) + .build(); + String result = invocationContext.appName(); + assertEquals("FullyConfiguredApp", result); + assertNotNull(result); + } + + @Test + @Tag("integration") + void appNameConsistentBetweenOriginalAndCopiedContext() { + when(mockSession.appName()).thenReturn("ConsistencyApp"); + InvocationContext originalContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .invocationId("original-id") + .build(); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertEquals(originalContext.appName(), copiedContext.appName()); + assertEquals("ConsistencyApp", originalContext.appName()); + assertEquals("ConsistencyApp", copiedContext.appName()); + } + + @Test + @Tag("integration") + void appNameAndUserIdBothDelegateToSession() { + when(mockSession.appName()).thenReturn("IntegrationApp"); + when(mockSession.userId()).thenReturn("user-123"); + InvocationContext invocationContext = buildContext(mockSession); + String appName = invocationContext.appName(); + String userId = invocationContext.userId(); + assertEquals("IntegrationApp", appName); + assertEquals("user-123", userId); + verify(mockSession, times(1)).appName(); + verify(mockSession, times(1)).userId(); + } + + @Test + @Tag("valid") + void appNameWithNumericOnlyName() { + when(mockSession.appName()).thenReturn("123456"); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals("123456", result); + assertNotNull(result); + } + + @Test + @Tag("valid") + void appNameWithUnicodeCharacters() { + when(mockSession.appName()).thenReturn("应用程序"); + InvocationContext invocationContext = buildContext(mockSession); + String result = invocationContext.appName(); + assertEquals("应用程序", result); + assertNotNull(result); + } + + @Test + @Tag("integration") + void appNameNotAffectedByAgentChange() { + when(mockSession.appName()).thenReturn("AgentChangeApp"); + BaseAgent anotherMockAgent = mock(BaseAgent.class); + InvocationContext invocationContext = buildContext(mockSession); + String appNameBefore = invocationContext.appName(); + invocationContext.agent(anotherMockAgent); + String appNameAfter = invocationContext.appName(); + assertEquals(appNameBefore, appNameAfter); + assertEquals("AgentChangeApp", appNameBefore); + assertEquals("AgentChangeApp", appNameAfter); + } + + @Test + @Tag("integration") + void appNameNotAffectedByEndInvocationChange() { + when(mockSession.appName()).thenReturn("EndInvocationApp"); + InvocationContext invocationContext = buildContext(mockSession); + String appNameBefore = invocationContext.appName(); + invocationContext.setEndInvocation(true); + String appNameAfter = invocationContext.appName(); + assertEquals(appNameBefore, appNameAfter); + assertEquals("EndInvocationApp", appNameBefore); + assertEquals("EndInvocationApp", appNameAfter); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextArtifactServiceTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextArtifactServiceTest.java new file mode 100644 index 000000000..2ca7dba17 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextArtifactServiceTest.java @@ -0,0 +1,560 @@ +/* + * 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=artifactService_d673c8a05b +ROOST_METHOD_SIG_HASH=artifactService_769a3f8842 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +" + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +"Scenario 1: Verify artifactService Returns the Correctly Assigned BaseArtifactService Instance + +Details: + TestName: artifactServiceReturnsAssignedInstance + Description: Verifies that the artifactService() method returns the exact BaseArtifactService instance that was provided during the construction of InvocationContext via the builder. This is the primary happy-path scenario for the getter method. + +Execution: + Arrange: + - Create a mock instance of BaseArtifactService (mockArtifactService). + - Create a mock instance of BaseSessionService (mockSessionService). + - Create a mock instance of BaseMemoryService (mockMemoryService). + - Create a mock instance of BaseAgent (mockAgent). + - Create a mock instance of Session (session). + - Build an InvocationContext using InvocationContext.builder() and provide the mockArtifactService via .artifactService(mockArtifactService), along with the other required fields (sessionService, memoryService, agent, session). + Act: + - Call context.artifactService() on the built InvocationContext instance. + Assert: + - Assert that the returned value is the same instance as mockArtifactService using assertThat(context.artifactService()).isEqualTo(mockArtifactService). + +Validation: + This assertion confirms that the artifactService() getter faithfully returns the field value set during construction. It ensures the builder correctly assigns the artifactService field and the getter does not introduce any transformation or substitution. This is fundamental to the correct functioning of any component that depends on the artifact service being available through the invocation context. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextArtifactServiceTest { + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + @Test + @Tag("valid") + void artifactServiceReturnsAssignedInstance() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + BaseArtifactService result = context.artifactService(); + assertThat(result).isEqualTo(mockArtifactService); + } + + @Test + @Tag("valid") + void artifactServiceReturnsSameReferenceAsProvided() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + assertThat(context.artifactService()).isSameInstanceAs(mockArtifactService); + } + + @Test + @Tag("invalid") + void artifactServiceReturnsNullWhenNotSet() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + assertThat(context.artifactService()).isNull(); + } + + @Test + @Tag("valid") + void artifactServiceReturnedAfterCopyOfPreservesInstance() { + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + InvocationContext copy = InvocationContext.copyOf(original); + assertThat(copy.artifactService()).isEqualTo(mockArtifactService); + assertThat(copy.artifactService()).isSameInstanceAs(mockArtifactService); + } + + @Test + @Tag("valid") + void artifactServiceIsConsistentAcrossMultipleCalls() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + BaseArtifactService firstCall = context.artifactService(); + BaseArtifactService secondCall = context.artifactService(); + BaseArtifactService thirdCall = context.artifactService(); + assertThat(firstCall).isSameInstanceAs(secondCall); + assertThat(secondCall).isSameInstanceAs(thirdCall); + } + + @Test + @Tag("valid") + void artifactServiceReturnedViaCreateFactoryMethod() { + Content userContent = Content.newBuilder().build(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "test-invocation-id", mockAgent, mockSession, userContent, mockRunConfig); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.artifactService()).isSameInstanceAs(mockArtifactService); + } + + @Test + @Tag("valid") + void artifactServiceReturnedViaLiveCreateFactoryMethod() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, mockRunConfig); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.artifactService()).isSameInstanceAs(mockArtifactService); + } + + @Test + @Tag("integration") + void artifactServiceIsIndependentBetweenTwoContextInstances() { + BaseArtifactService anotherMockArtifactService = mock(BaseArtifactService.class); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("invocation-id-1") + .runConfig(mockRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(anotherMockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("invocation-id-2") + .runConfig(mockRunConfig) + .build(); + assertThat(context1.artifactService()).isSameInstanceAs(mockArtifactService); + assertThat(context2.artifactService()).isSameInstanceAs(anotherMockArtifactService); + assertThat(context1.artifactService()).isNotSameInstanceAs(context2.artifactService()); + } + + @Test + @Tag("valid") + void artifactServiceReturnedIsNotNullWhenSet() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + assertThat(context.artifactService()).isNotNull(); + } + + @Test + @Tag("integration") + void artifactServiceRemainsUnchangedAfterMutatingOtherFields() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + context.setEndInvocation(true); + context.branch("new-branch"); + context.agent(mock(BaseAgent.class)); + assertThat(context.artifactService()).isSameInstanceAs(mockArtifactService); + } + + @Test + @Tag("valid") + void artifactServiceEqualsAcrossEqualContextInstances() { + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("same-invocation-id") + .runConfig(mockRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("same-invocation-id") + .runConfig(mockRunConfig) + .build(); + assertThat(context1.artifactService()).isEqualTo(context2.artifactService()); + } + + @Test + @Tag("boundary") + void artifactServiceNullDoesNotThrowWhenAccessed() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(null) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + assertDoesNotThrow(() -> context.artifactService()); + assertThat(context.artifactService()).isNull(); + } + + @Test + @Tag("integration") + void artifactServicePreservedAfterCopyOfWithActiveStreamingTools() { + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .invocationId("original-invocation-id") + .runConfig(mockRunConfig) + .build(); + InvocationContext copied = InvocationContext.copyOf(original); + assertThat(copied.artifactService()).isSameInstanceAs(mockArtifactService); + assertThat(copied.artifactService()).isSameInstanceAs(original.artifactService()); + } + + @Test + @Tag("valid") + void artifactServiceBuilderWithAllFields() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .invocationId("full-invocation-id") + .branch("test-branch") + .runConfig(mockRunConfig) + .endInvocation(false) + .build(); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.artifactService()).isNotNull(); + } + + @Test + @Tag("valid") + void artifactServiceReturnedMatchesTypeBaseArtifactService() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(mockRunConfig) + .build(); + BaseArtifactService result = context.artifactService(); + assertThat(result).isInstanceOf(BaseArtifactService.class); + } + + @Test + @Tag("boundary") + void artifactServiceCanBeReplacedInNewBuilderFromExistingConfig() { + BaseArtifactService secondArtifactService = mock(BaseArtifactService.class); + InvocationContext originalContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("original-invocation-id") + .runConfig(mockRunConfig) + .build(); + InvocationContext updatedContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(secondArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("updated-invocation-id") + .runConfig(mockRunConfig) + .build(); + assertThat(originalContext.artifactService()).isSameInstanceAs(mockArtifactService); + assertThat(updatedContext.artifactService()).isSameInstanceAs(secondArtifactService); + assertThat(originalContext.artifactService()).isNotSameInstanceAs(updatedContext.artifactService()); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextBranch837Test.java b/core/src/test/java/com/google/adk/agents/InvocationContextBranch837Test.java new file mode 100644 index 000000000..b0d88d4b0 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextBranch837Test.java @@ -0,0 +1,434 @@ +/* + * 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=branch_5cdb3cf131 +ROOST_METHOD_SIG_HASH=branch_38b042f6d4 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/ParallelAgentTest.java +Tests: + "@Test +public void runAsync_subAgentsExecuteInParallel_eventsOrderedByCompletion() { + String agent1Name = "test_agent_1_delayed"; + String agent2Name = "test_agent_2_fast"; + String parallelAgentName = "test_parallel_agent"; + TestingAgent agent1 = new TestingAgent(agent1Name, "Delayed Agent", 500); + TestingAgent agent2 = new TestingAgent(agent2Name, "Fast Agent", 0); + ParallelAgent parallelAgent = ParallelAgent.builder().name(parallelAgentName).subAgents(agent1, agent2).build(); + InvocationContext invocationContext = createInvocationContext(parallelAgent); + List events = parallelAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(2); + + Event firstEvent = events.get(0); + assertThat(firstEvent.author()).isEqualTo(agent2Name); + assertThat(firstEvent.content().get().parts().get().get(0).text()).hasValue("Hello, async " + agent2Name + "!"); + assertThat(firstEvent.branch().get()).endsWith(agent2Name); + + Event secondEvent = events.get(1); + assertThat(secondEvent.author()).isEqualTo(agent1Name); + assertThat(secondEvent.content().get().parts().get().get(0).text()).hasValue("Hello, async " + agent1Name + "!"); + assertThat(secondEvent.branch().get()).endsWith(agent1Name); +} +"Scenario 1: Branch Returns Empty Optional When Not Set During Build + +Details: + TestName: branchReturnsEmptyOptionalWhenNotSetDuringBuild + Description: Verifies that the branch() method returns an empty Optional when no branch value + is provided during the construction of InvocationContext via the builder. The + default value in the Builder is Optional.empty(), so the returned Optional should + have no value present. + +Execution: + Arrange: Build an InvocationContext instance using InvocationContext.builder() without calling + the branch(String) or branch(Optional) builder methods, supplying only the + minimal required fields (e.g., sessionService, artifactService, agent, session). + Act: Call invocationContext.branch() on the constructed instance. + Assert: Assert that the returned Optional is not null. + Assert that the returned Optional is empty (i.e., Optional.isPresent() is false). + +Validation: + The assertion confirms that the default state of the branch field is Optional.empty(), as + initialized in the Builder. This validates correct default behavior when no branch is explicitly + configured, which is important for invocations that do not involve forked conversation histories. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class InvocationContextBranch837Test { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + private RunConfig defaultRunConfig; + + @BeforeEach + void setUp() { + defaultRunConfig = RunConfig.builder().build(); + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext buildMinimalContext() { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .build(); + } + + @Test + @Tag("valid") + void branchReturnsEmptyOptionalWhenNotSetDuringBuild() { + InvocationContext context = buildMinimalContext(); + Optional result = context.branch(); + assertNotNull(result); + assertFalse(result.isPresent()); + } + + @Test + @Tag("valid") + void branchReturnsOptionalWithValueWhenSetViaBuilderString() { + String branchValue = "my-branch"; + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals(branchValue, result.get()); + } + + @Test + @Tag("valid") + void branchReturnsOptionalWithValueWhenSetViaBuilderOptional() { + Optional branchOptional = Optional.of("optional-branch"); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchOptional) + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals("optional-branch", result.get()); + } + + @Test + @Tag("valid") + void branchReturnsEmptyOptionalWhenSetWithEmptyOptional() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(Optional.empty()) + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertFalse(result.isPresent()); + } + + @Test + @Tag("valid") + void branchCanBeUpdatedAfterCreation() { + InvocationContext context = buildMinimalContext(); + assertFalse(context.branch().isPresent()); + context.branch("new-branch"); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals("new-branch", result.get()); + } + + @Test + @Tag("valid") + void branchCanBeSetToNullAfterBeingSet() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch("some-branch") + .build(); + assertTrue(context.branch().isPresent()); + context.branch((String) null); + Optional result = context.branch(); + assertNotNull(result); + assertFalse(result.isPresent()); + } + + @Test + @Tag("boundary") + void branchReturnsOptionalWithEmptyStringValue() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch("") + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals("", result.get()); + } + + @Test + @Tag("boundary") + void branchReturnsOptionalWithLongBranchName() { + String longBranch = "a".repeat(1000); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(longBranch) + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals(longBranch, result.get()); + } + + @Test + @Tag("valid") + void branchIsPreservedInCopyOf() { + String branchValue = "preserved-branch"; + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + InvocationContext copy = InvocationContext.copyOf(original); + Optional result = copy.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals(branchValue, result.get()); + } + + @Test + @Tag("valid") + void branchEmptyIsPreservedInCopyOf() { + InvocationContext original = buildMinimalContext(); + InvocationContext copy = InvocationContext.copyOf(original); + Optional result = copy.branch(); + assertNotNull(result); + assertFalse(result.isPresent()); + } + + @Test + @Tag("integration") + void branchChangesDoNotAffectCopiedContext() { + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch("original-branch") + .build(); + InvocationContext copy = InvocationContext.copyOf(original); + original.branch("modified-branch"); + assertEquals("original-branch", copy.branch().get()); + assertEquals("modified-branch", original.branch().get()); + } + + @Test + @Tag("valid") + void branchReturnsConsistentValueOnMultipleCalls() { + String branchValue = "consistent-branch"; + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + Optional firstCall = context.branch(); + Optional secondCall = context.branch(); + Optional thirdCall = context.branch(); + assertEquals(firstCall, secondCall); + assertEquals(secondCall, thirdCall); + assertTrue(firstCall.isPresent()); + assertEquals(branchValue, firstCall.get()); + } + + @Test + @Tag("valid") + void branchReturnsSameInstanceOnMultipleCallsWhenEmpty() { + InvocationContext context = buildMinimalContext(); + Optional firstCall = context.branch(); + Optional secondCall = context.branch(); + assertFalse(firstCall.isPresent()); + assertFalse(secondCall.isPresent()); + } + + @Test + @Tag("valid") + void branchReturnsOptionalWithSpecialCharacters() { + String branchValue = "branch/with-special_chars.and:symbols"; + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals(branchValue, result.get()); + } + + @Test + @Tag("valid") + void branchReturnsOptionalWithHierarchicalBranchName() { + String hierarchicalBranch = "parent.child.grandchild"; + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(hierarchicalBranch) + .build(); + Optional result = context.branch(); + assertNotNull(result); + assertTrue(result.isPresent()); + assertEquals(hierarchicalBranch, result.get()); + } + + @Test + @Tag("integration") + void branchUsedCorrectlyInCreateMethod() { + Content userContent = Content.newBuilder().build(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "test-invocation-id", mockAgent, mockSession, userContent, defaultRunConfig); + Optional result = context.branch(); + assertNotNull(result); + assertFalse(result.isPresent()); + } + + @Test + @Tag("valid") + void branchUpdatedMultipleTimesReturnsLatestValue() { + InvocationContext context = buildMinimalContext(); + context.branch("first-branch"); + assertEquals("first-branch", context.branch().get()); + context.branch("second-branch"); + assertEquals("second-branch", context.branch().get()); + context.branch("third-branch"); + assertEquals("third-branch", context.branch().get()); + } + + @Test + @Tag("valid") + void branchEqualityBetweenTwoContextsWithSameBranch() { + String branchValue = "same-branch"; + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + assertEquals(context1.branch(), context2.branch()); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextBranchTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextBranchTest.java new file mode 100644 index 000000000..0b17dcc4d --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextBranchTest.java @@ -0,0 +1,395 @@ +/* + * 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=branch_25309d7017 +ROOST_METHOD_SIG_HASH=branch_5237016f3f + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/ParallelAgentTest.java +Tests: + "@Test +public void runAsync_subAgentsExecuteInParallel_eventsOrderedByCompletion() { + String agent1Name = "test_agent_1_delayed"; + String agent2Name = "test_agent_2_fast"; + String parallelAgentName = "test_parallel_agent"; + TestingAgent agent1 = new TestingAgent(agent1Name, "Delayed Agent", 500); + TestingAgent agent2 = new TestingAgent(agent2Name, "Fast Agent", 0); + ParallelAgent parallelAgent = ParallelAgent.builder().name(parallelAgentName).subAgents(agent1, agent2).build(); + InvocationContext invocationContext = createInvocationContext(parallelAgent); + List events = parallelAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(2); + + Event firstEvent = events.get(0); + assertThat(firstEvent.author()).isEqualTo(agent2Name); + assertThat(firstEvent.content().get().parts().get().get(0).text()).hasValue("Hello, async " + agent2Name + "!"); + assertThat(firstEvent.branch().get()).endsWith(agent2Name); + + Event secondEvent = events.get(1); + assertThat(secondEvent.author()).isEqualTo(agent1Name); + assertThat(secondEvent.content().get().parts().get().get(0).text()).hasValue("Hello, async " + agent1Name + "!"); + assertThat(secondEvent.branch().get()).endsWith(agent1Name); +} +"Scenario 1: Setting a Valid Non-Null Branch String + +Details: + TestName: branchSetsValidNonNullStringAsOptionalPresent + Description: Verifies that calling branch() with a valid, non-null string value correctly + wraps it in an Optional and stores it in the branch field of InvocationContext. +Execution: + Arrange: Create an InvocationContext instance using InvocationContext.builder() with all + required fields (sessionService, artifactService, agent, session, runConfig). + Define a non-null branch string value such as "main-branch". + Act: Invoke context.branch("main-branch") on the created InvocationContext instance. + Assert: Call context.branch() and assert that the returned Optional is present and + contains the value "main-branch". +Validation: + The assertion confirms that a valid non-null string is correctly wrapped in + Optional.of(...) and stored. This is important because the branch field tracks + which conversation fork the invocation belongs to, and a correctly stored branch + value enables accurate routing and history tracking in multi-agent flows. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextBranchTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + private RunConfig runConfig; + + @BeforeEach + public void setUp() { + runConfig = RunConfig.builder().build(); + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext buildDefaultContext() { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(runConfig) + .build(); + } + + // Scenario 1: Setting a Valid Non-Null Branch String + @Test + @Tag("valid") + public void branchSetsValidNonNullStringAsOptionalPresent() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = "main-branch"; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("main-branch", context.branch().get()); + } + + @Test + @Tag("invalid") + public void branchSetsNullAsOptionalEmpty() { + // Arrange + InvocationContext context = buildDefaultContext(); + // Act + context.branch(null); + // Assert + assertFalse(context.branch().isPresent()); + assertEquals(Optional.empty(), context.branch()); + } + + @Test + @Tag("valid") + public void branchSetsEmptyStringAsOptionalPresentWithEmptyString() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = ""; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("", context.branch().get()); + } + + @Test + @Tag("valid") + public void branchSetsComplexHierarchicalBranchString() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = "parent-agent.child-agent.sub-agent"; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("parent-agent.child-agent.sub-agent", context.branch().get()); + } + + @Test + @Tag("valid") + public void branchUpdatesExistingBranchValue() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(runConfig) + .branch("initial-branch") + .build(); + // Act + context.branch("updated-branch"); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("updated-branch", context.branch().get()); + } + + @Test + @Tag("valid") + public void branchOverwritesExistingBranchWithNull() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(runConfig) + .branch("some-branch") + .build(); + // Act + context.branch(null); + // Assert + assertFalse(context.branch().isPresent()); + assertEquals(Optional.empty(), context.branch()); + } + + @Test + @Tag("boundary") + public void branchHandlesVeryLongBranchString() { + // Arrange + InvocationContext context = buildDefaultContext(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 1000; i++) { + sb.append("a"); + } + String longBranchValue = sb.toString(); + // Act + context.branch(longBranchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals(longBranchValue, context.branch().get()); + assertEquals(1000, context.branch().get().length()); + } + + @Test + @Tag("boundary") + public void branchHandlesSingleCharacterBranchString() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = "a"; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("a", context.branch().get()); + } + + @Test + @Tag("valid") + public void branchHandlesSpecialCharactersInBranchString() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = "branch-123_test.v2@special"; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("branch-123_test.v2@special", context.branch().get()); + } + + @Test + @Tag("valid") + public void branchReturnValueIsWrappedInOptional() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = "optional-branch"; + // Act + context.branch(branchValue); + Optional result = context.branch(); + // Assert + assertNotNull(result); + assertInstanceOf(Optional.class, result); + assertEquals(Optional.of("optional-branch"), result); + } + + @Test + @Tag("integration") + public void branchCanBeSetAndRetrievedMultipleTimes() { + // Arrange + InvocationContext context = buildDefaultContext(); + // Act & Assert - first set + context.branch("first-branch"); + assertTrue(context.branch().isPresent()); + assertEquals("first-branch", context.branch().get()); + // Act & Assert - second set + context.branch("second-branch"); + assertTrue(context.branch().isPresent()); + assertEquals("second-branch", context.branch().get()); + // Act & Assert - set to null + context.branch(null); + assertFalse(context.branch().isPresent()); + // Act & Assert - set again + context.branch("third-branch"); + assertTrue(context.branch().isPresent()); + assertEquals("third-branch", context.branch().get()); + } + + @Test + @Tag("integration") + public void branchIsPreservedInCopyOf() { + // Arrange + InvocationContext original = buildDefaultContext(); + original.branch("original-branch"); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertTrue(copy.branch().isPresent()); + assertEquals("original-branch", copy.branch().get()); + } + + @Test + @Tag("integration") + public void branchChangesInCopyDoNotAffectOriginal() { + // Arrange + InvocationContext original = buildDefaultContext(); + original.branch("original-branch"); + InvocationContext copy = InvocationContext.copyOf(original); + // Act + copy.branch("modified-branch"); + // Assert + assertTrue(original.branch().isPresent()); + assertEquals("original-branch", original.branch().get()); + assertTrue(copy.branch().isPresent()); + assertEquals("modified-branch", copy.branch().get()); + } + + @Test + @Tag("valid") + public void branchDefaultValueIsEmptyOptionalWhenNotSetInBuilder() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(runConfig) + .build(); + // Assert default (no branch set) + assertNotNull(context.branch()); + } + + @Test + @Tag("valid") + public void branchSetViaBuilderIsReturnedCorrectly() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(runConfig) + .branch("builder-branch") + .build(); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("builder-branch", context.branch().get()); + } + + @Test + @Tag("valid") + public void branchSetsWhitespaceStringAsOptionalPresent() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = " "; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals(" ", context.branch().get()); + } + + @Test + @Tag("boundary") + public void branchHandlesBranchWithDotSeparatedSegments() { + // Arrange + InvocationContext context = buildDefaultContext(); + String branchValue = "root.child.grandchild"; + // Act + context.branch(branchValue); + // Assert + assertTrue(context.branch().isPresent()); + assertEquals("root.child.grandchild", context.branch().get()); + assertTrue(context.branch().get().contains(".")); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextBuilderTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextBuilderTest.java new file mode 100644 index 000000000..e88965310 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextBuilderTest.java @@ -0,0 +1,1760 @@ +/* + * 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_2187989d2f +ROOST_METHOD_SIG_HASH=builder_80041265ae + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void setUp() { + MockitoAnnotations.openMocks(this); + liveRequestQueue = new LiveRequestQueue(); + session = Session.builder("test-session-id").build(); + userContent = Content.builder().build(); + runConfig = RunConfig.builder().build(); + testInvocationId = "test-invocation-id"; + activeStreamingTools = new HashMap<>(); + activeStreamingTools.put("test-tool", new ActiveStreamingTool(new LiveRequestQueue())); +} +" + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +" + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/CallbacksTest.java +Tests: + "@Test +public void testRun_withBeforeModelCallback_returnsResponseFromCallback() { + Content realContent = Content.fromParts(Part.fromText("Real LLM response")); + Content callbackContent = Content.fromParts(Part.fromText("Callback response")); + TestLlm testLlm = createTestLlm(createLlmResponse(realContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeModelCallback((context, request) -> Maybe.just(LlmResponse.builder().content(callbackContent).build())).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(testLlm.getRequests()).isEmpty(); + assertThat(events).hasSize(1); + assertThat(getOnlyElement(events).content()).hasValue(callbackContent); +} +" + "@Test +public void testRun_withBeforeModelCallback_usesModifiedRequestFromCallback() { + TestLlm testLlm = createTestLlm(createLlmResponse(Content.builder().build())); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeModelCallback((context, requestBuilder) -> { + requestBuilder.contents(ImmutableList.of(Content.fromParts(Part.fromText("Modified request")))); + return Maybe.empty(); + }).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List unused = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(testLlm.getRequests()).hasSize(1); + assertThat(testLlm.getRequests().get(0).contents()).containsExactly(Content.fromParts(Part.fromText("Modified request"))); +} +" + "@Test +public void testRun_withAfterModelCallback_returnsResponseFromCallback() { + Part textPartFromModel = Part.fromText("Real LLM response"); + Part textPartFromCallback = Part.fromText("Callback response"); + TestLlm testLlm = createTestLlm(createLlmResponse(Content.fromParts(textPartFromModel))); + LlmAgent agent = createTestAgentBuilder(testLlm).afterModelCallback((context, response) -> Maybe.just(addPartToResponse(response, textPartFromCallback))).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(1); + assertThat(getOnlyElement(events).content()).hasValue(Content.builder().parts(ImmutableList.of(textPartFromModel, textPartFromCallback)).build()); +} +" + "@Test +public void testRun_withChainedModelCallbacks_mixOfSyncAndAsync_returnsBeforeCallbackResponse() { + Content originalLlmResponseContent = Content.fromParts(Part.fromText("Original LLM response")); + Content contentFromSecondBeforeCallback = Content.fromParts(Part.fromText("Response from second beforeModelCallback")); + Content contentFromSecondAfterCallback = Content.fromParts(Part.fromText("Response from second afterModelCallback")); + TestLlm testLlm = createTestLlm(createLlmResponse(originalLlmResponseContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeModelCallback(ImmutableList.of((Callbacks.BeforeModelCallbackSync) (context, request) -> Optional.empty(), (Callbacks.BeforeModelCallback) (context, request) -> Maybe.just(LlmResponse.builder().content(contentFromSecondBeforeCallback).build()))).afterModelCallback(ImmutableList.of((Callbacks.AfterModelCallbackSync) (context, response) -> Optional.empty(), (Callbacks.AfterModelCallback) (context, response) -> Maybe.just(LlmResponse.builder().content(contentFromSecondAfterCallback).build()))).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(testLlm.getRequests()).isEmpty(); + assertThat(events).hasSize(1); + assertThat(getOnlyElement(events).content()).hasValue(contentFromSecondBeforeCallback); +} +" + "@Test +public void testRun_withChainedModelCallbacks_mixOfSyncAndAsync_returnsAfterCallbackResponse() { + Content originalLlmResponseContent = Content.fromParts(Part.fromText("Original LLM response")); + Content contentFromSecondAfterCallback = Content.fromParts(Part.fromText("Response from second afterModelCallback")); + TestLlm testLlm = createTestLlm(createLlmResponse(originalLlmResponseContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeModelCallback(ImmutableList.of((Callbacks.BeforeModelCallbackSync) (context, request) -> Optional.empty(), (Callbacks.BeforeModelCallback) (context, request) -> Maybe.empty())).afterModelCallback(ImmutableList.of((Callbacks.AfterModelCallbackSync) (context, response) -> Optional.empty(), (Callbacks.AfterModelCallback) (context, response) -> Maybe.just(LlmResponse.builder().content(contentFromSecondAfterCallback).build()))).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(testLlm.getRequests()).isNotEmpty(); + assertThat(events).hasSize(1); + assertThat(getOnlyElement(events).content()).hasValue(contentFromSecondAfterCallback); +} +" + "@Test +private static LlmResponse addPartToResponse(LlmResponse response, Part part) { + return LlmResponse.builder().content(Content.builder().parts(ImmutableList.builder().addAll(response.content().flatMap(Content::parts).orElse(ImmutableList.of())).add(part).build()).build()).build(); +} +" + "@Test +public void handleFunctionCalls_withBeforeToolCallback_returnsBeforeToolCallbackResult() { + ImmutableMap beforeToolCallbackResult = ImmutableMap.of("before_tool_callback_result", "value"); + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallback((invocationContext1, tool, args, toolContext) -> Maybe.just(beforeToolCallbackResult)).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.FailingEchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(beforeToolCallbackResult).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withBeforeToolCallbackThatReturnsNull_returnsToolResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallback((invocationContext1, tool, args, toolContext) -> Maybe.empty()).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.EchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("result", ImmutableMap.of("key", "value"))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withBeforeToolCallbackSync_returnsBeforeToolCallbackResult() { + ImmutableMap beforeToolCallbackResult = ImmutableMap.of("before_tool_callback_result", "value"); + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallbackSync((invocationContext1, tool, args, toolContext) -> Optional.of(beforeToolCallbackResult)).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.FailingEchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(beforeToolCallbackResult).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withBeforeToolCallbackSyncThatReturnsNull_returnsToolResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallbackSync((invocationContext1, tool, args, toolContext) -> Optional.empty()).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.EchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("result", ImmutableMap.of("key", "value"))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withAfterToolCallback_returnsAfterToolCallbackResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).afterToolCallback((invocationContext1, tool, args, toolContext, response) -> Maybe.just(ImmutableMap.of("after_tool_callback_result", response))).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.EchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("after_tool_callback_result", ImmutableMap.of("result", ImmutableMap.of("key", "value")))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withAfterToolCallbackThatReturnsNull_returnsToolResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).afterToolCallback((invocationContext1, tool, args, toolContext, response) -> Maybe.empty()).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.EchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("result", ImmutableMap.of("key", "value"))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withAfterToolCallbackSync_returnsAfterToolCallbackResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).afterToolCallbackSync((invocationContext1, tool, args, toolContext, response) -> Optional.of(ImmutableMap.of("after_tool_callback_result", response))).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.EchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("after_tool_callback_result", ImmutableMap.of("result", ImmutableMap.of("key", "value")))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withAfterToolCallbackSyncThatReturnsNull_returnsToolResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).afterToolCallbackSync((invocationContext1, tool, args, toolContext, response) -> Optional.empty()).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.EchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("result", ImmutableMap.of("key", "value"))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withBeforeAndAfterToolCallback_returnsAfterToolCallbackResultAppliedToBeforeToolCallbackResult() { + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallback((invocationContext1, tool, args, toolContext) -> Maybe.just(ImmutableMap.of("before_tool_callback_result", "value"))).afterToolCallback((invocationContext1, tool, args, toolContext, response) -> Maybe.just(ImmutableMap.of("after_tool_callback_result", response))).build()); + Event event = createEvent("event").toBuilder().content(Content.fromParts(Part.fromText("..."), Part.builder().functionCall(FunctionCall.builder().id("function_call_id").name("echo_tool").args(ImmutableMap.of("key", "value")).build()).build())).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, event, ImmutableMap.of("echo_tool", new TestUtils.FailingEchoTool())).blockingGet(); + assertThat(functionResponseEvent).isNotNull(); + assertThat(functionResponseEvent.content().get().parts().get()).containsExactly(Part.builder().functionResponse(FunctionResponse.builder().id("function_call_id").name("echo_tool").response(ImmutableMap.of("after_tool_callback_result", ImmutableMap.of("before_tool_callback_result", "value"))).build()).build()); +} +" + "@Test +public void handleFunctionCalls_withChainedToolCallbacks_overridesResultAndPassesContext() { + ImmutableMap originalToolInputArgs = ImmutableMap.of("input_key", "input_value"); + ImmutableMap stateAddedByBc2 = ImmutableMap.of("bc2_state_key", "bc2_state_value"); + ImmutableMap responseFromAc2 = ImmutableMap.of("ac2_response_key", "ac2_response_value"); + Callbacks.BeforeToolCallbackSync bc1 = (invCtx, toolName, args, currentToolCtx) -> Optional.empty(); + Callbacks.BeforeToolCallbackSync bc2 = (invCtx, toolName, args, currentToolCtx) -> { + currentToolCtx.state().putAll(stateAddedByBc2); + return Optional.empty(); + }; + TestUtils.EchoTool echoTool = new TestUtils.EchoTool(); + Callbacks.AfterToolCallbackSync ac1 = (invCtx, toolName, args, currentToolCtx, responseFromTool) -> Optional.empty(); + Callbacks.AfterToolCallbackSync ac2 = (invCtx, toolName, args, currentToolCtx, responseFromTool) -> Optional.of(responseFromAc2); + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallback(ImmutableList.of(bc1, bc2)).afterToolCallback(ImmutableList.of(ac1, ac2)).build()); + Event eventWithFunctionCall = createEvent("event").toBuilder().content(createFunctionCallContent("fc_id_minimal", "echo_tool", originalToolInputArgs)).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, eventWithFunctionCall, ImmutableMap.of("echo_tool", echoTool)).blockingGet(); + assertThat(getFunctionResponse(functionResponseEvent)).isEqualTo(responseFromAc2); + assertThat(invocationContext.session().state()).containsExactlyEntriesIn(stateAddedByBc2); +} +" + "@Test +public void agentRunAsync_withToolCallbacks_inspectsArgsAndReturnsResponse() { + TestUtils.EchoTool echoTool = new TestUtils.EchoTool(); + String toolName = echoTool.declaration().get().name().get(); + ImmutableMap functionArgs = ImmutableMap.of("message", "hello"); + Content llmFunctionCallContent = Content.builder().role("model").parts(ImmutableList.of(Part.fromFunctionCall(toolName, functionArgs))).build(); + Content llmTextContent = Content.builder().role("model").parts(ImmutableList.of(Part.fromText("hi there"))).build(); + TestLlm testLlm = createTestLlm(createLlmResponse(llmFunctionCallContent), createLlmResponse(llmTextContent)); + ImmutableMap responseFromAfterToolCallback = ImmutableMap.of("final_wrapper", "wrapped_value_from_after_callback"); + Callbacks.BeforeToolCallback beforeToolCb = (invCtx, tName, args, toolCtx) -> { + assertThat(args).isEqualTo(functionArgs); + return Maybe.empty(); + }; + Callbacks.AfterToolCallback afterToolCb = (invCtx, tName, args, toolCtx, toolResponse) -> { + assertThat(args).isEqualTo(functionArgs); + assertThat(toolResponse).isEqualTo(ImmutableMap.of("result", functionArgs)); + return Maybe.just(responseFromAfterToolCallback); + }; + LlmAgent agent = createTestAgentBuilder(testLlm).tools(ImmutableList.of(echoTool)).beforeToolCallback(beforeToolCb).afterToolCallback(afterToolCb).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(testLlm.getRequests()).hasSize(2); + assertThat(events).hasSize(3); + var functionCall = getFunctionCall(events.get(0)); + assertThat(functionCall.args().get()).isEqualTo(functionArgs); + assertThat(functionCall.name()).hasValue(toolName); + var functionResponse = getFunctionResponse(events.get(1)); + assertThat(functionResponse).isEqualTo(responseFromAfterToolCallback); + assertThat(events.get(2).content()).hasValue(llmTextContent); +} +" + "@Test +private static Content createFunctionCallContent(String functionCallId, String toolName, Map args) { + return Content.builder().role("model").parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name(toolName).id(functionCallId).args(args).build()).build())).build(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/RunConfigTest.java +Tests: + "@Test +public void testBuilderWithVariousValues() { + SpeechConfig speechConfig = SpeechConfig.builder().build(); + AudioTranscriptionConfig audioTranscriptionConfig = AudioTranscriptionConfig.builder().build(); + RunConfig runConfig = RunConfig.builder().setSpeechConfig(speechConfig).setResponseModalities(ImmutableList.of(new Modality(Modality.Known.TEXT))).setSaveInputBlobsAsArtifacts(true).setStreamingMode(RunConfig.StreamingMode.SSE).setOutputAudioTranscription(audioTranscriptionConfig).setInputAudioTranscription(audioTranscriptionConfig).setMaxLlmCalls(10).build(); + assertThat(runConfig.speechConfig()).isEqualTo(speechConfig); + assertThat(runConfig.responseModalities()).containsExactly(new Modality(Modality.Known.TEXT)); + assertThat(runConfig.saveInputBlobsAsArtifacts()).isTrue(); + assertThat(runConfig.streamingMode()).isEqualTo(RunConfig.StreamingMode.SSE); + assertThat(runConfig.outputAudioTranscription()).isEqualTo(audioTranscriptionConfig); + assertThat(runConfig.inputAudioTranscription()).isEqualTo(audioTranscriptionConfig); + assertThat(runConfig.maxLlmCalls()).isEqualTo(10); +} +" + "@Test +public void testBuilderDefaults() { + RunConfig runConfig = RunConfig.builder().build(); + assertThat(runConfig.speechConfig()).isNull(); + assertThat(runConfig.responseModalities()).isEmpty(); + assertThat(runConfig.saveInputBlobsAsArtifacts()).isFalse(); + assertThat(runConfig.streamingMode()).isEqualTo(RunConfig.StreamingMode.NONE); + assertThat(runConfig.outputAudioTranscription()).isNull(); + assertThat(runConfig.inputAudioTranscription()).isNull(); + assertThat(runConfig.maxLlmCalls()).isEqualTo(500); +} +" + "@Test +public void testMaxLlmCalls_negativeValueAllowedInSetterButLoggedAndBuilt() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(-1).build(); + assertThat(runConfig.maxLlmCalls()).isEqualTo(-1); +} +" + "@Test +public void testBuilderWithDifferentValues() { + SpeechConfig speechConfig = SpeechConfig.builder().build(); + AudioTranscriptionConfig audioTranscriptionConfig = AudioTranscriptionConfig.builder().build(); + RunConfig runConfig = RunConfig.builder().setSpeechConfig(speechConfig).setResponseModalities(ImmutableList.of(new Modality(Modality.Known.AUDIO))).setSaveInputBlobsAsArtifacts(true).setStreamingMode(RunConfig.StreamingMode.BIDI).setOutputAudioTranscription(audioTranscriptionConfig).setInputAudioTranscription(audioTranscriptionConfig).setMaxLlmCalls(20).build(); + assertThat(runConfig.speechConfig()).isEqualTo(speechConfig); + assertThat(runConfig.responseModalities()).containsExactly(new Modality(Modality.Known.AUDIO)); + assertThat(runConfig.saveInputBlobsAsArtifacts()).isTrue(); + assertThat(runConfig.streamingMode()).isEqualTo(RunConfig.StreamingMode.BIDI); + assertThat(runConfig.outputAudioTranscription()).isEqualTo(audioTranscriptionConfig); + assertThat(runConfig.inputAudioTranscription()).isEqualTo(audioTranscriptionConfig); + assertThat(runConfig.maxLlmCalls()).isEqualTo(20); +} +" + "@Test +public void testInputAudioTranscriptionOnly() { + AudioTranscriptionConfig inputTranscriptionConfig = AudioTranscriptionConfig.builder().build(); + RunConfig runConfig = RunConfig.builder().setStreamingMode(RunConfig.StreamingMode.BIDI).setResponseModalities(ImmutableList.of(new Modality(Modality.Known.AUDIO))).setInputAudioTranscription(inputTranscriptionConfig).build(); + assertThat(runConfig.inputAudioTranscription()).isEqualTo(inputTranscriptionConfig); + assertThat(runConfig.outputAudioTranscription()).isNull(); + assertThat(runConfig.streamingMode()).isEqualTo(RunConfig.StreamingMode.BIDI); + assertThat(runConfig.responseModalities()).containsExactly(new Modality(Modality.Known.AUDIO)); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/LlmAgentTest.java +Tests: + "@Test +public void build_withOutputSchemaAndTools_throwsIllegalArgumentException() { + BaseTool tool = new BaseTool("test_tool", "test_description") { + + @Override + public Optional declaration() { + return Optional.empty(); + } + }; + Schema outputSchema = Schema.builder().type("OBJECT").properties(ImmutableMap.of("status", Schema.builder().type("STRING").build())).required(ImmutableList.of("status")).build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> + LlmAgent.builder().name("agent with invalid tool config").outputSchema( + outputSchema).tools( + ImmutableList.of(tool)). + build()); + assertThat(exception).hasMessageThat().contains("Invalid config for agent agent with invalid tool config: if outputSchema is set, tools" + " must be empty"); +} +" + "@Test +public void build_withOutputSchemaAndSubAgents_throwsIllegalArgumentException() { + ImmutableList subAgents = ImmutableList.of(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).name("test_sub_agent").description("test_sub_agent_description").build()); + Schema outputSchema = Schema.builder().type("OBJECT").properties(ImmutableMap.of("status", Schema.builder().type("STRING").build())).required(ImmutableList.of("status")).build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> + LlmAgent.builder().name("agent with invalid tool config").outputSchema( + outputSchema).subAgents( + subAgents). + build()); + assertThat(exception).hasMessageThat().contains("Invalid config for agent agent with invalid tool config: if outputSchema is set," + " subAgents must be empty to disable agent transfer."); +} +" + "@Test +public void testBuild_withNullInstruction_setsInstructionToEmptyString() { + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction((String) null).build(); + assertThat(agent.instruction()).isEqualTo(new Instruction.Static("")); +} +" + "@Test +public void testCanonicalInstruction_acceptsPlainString() { + String instruction = "Test static instruction"; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction(instruction).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction); +} +" + "@Test +public void testCanonicalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + "@Test +public void testBuild_withNullGlobalInstruction_setsGlobalInstructionToEmptyString() { + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction((String) null).build(); + assertThat(agent.globalInstruction()).isEqualTo(new Instruction.Static("")); +} +" + "@Test +public void testCanonicalGlobalInstruction_acceptsPlainString() { + String instruction = "Test static global instruction"; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction(instruction).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalGlobalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction); +} +" + "@Test +public void testCanonicalGlobalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider global instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalGlobalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + "@Test +public void resolveModel_withModelName_resolvesFromRegistry() { + String modelName = "test-model"; + TestLlm testLlm = createTestLlm(LlmResponse.builder().build()); + LlmRegistry.registerLlm(modelName, (name) -> testLlm); + LlmAgent agent = createTestAgentBuilder(testLlm).model(modelName).build(); + Model resolvedModel = agent.resolvedModel(); + assertThat(resolvedModel.modelName()).hasValue(modelName); + assertThat(resolvedModel.model()).hasValue(testLlm); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/LoopAgentTest.java +Tests: + "@Test +public void runAsync_withNoAgents_returnsEmptyEvents() { + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of()).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).isEmpty(); +} +" + "@Test +public void runAsync_withSingleAgent_singleIteration_returnsEvents() { + Event event1 = createEvent("event1"); + Event event2 = createEvent("event2"); + TestBaseAgent subAgent = createSubAgent("subAgent", Flowable.just(event1, event2)); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(subAgent)).maxIterations(1).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1, event2).inOrder(); +} +" + "@Test +public void runAsync_withSingleAgent_multipleIterations_returnsEvents() { + Event event1 = createEvent("event1"); + Event event2 = createEvent("event2"); + Event event3 = createEvent("event3"); + Event event4 = createEvent("event4"); + TestBaseAgent subAgent = createSubAgent("subAgent", Flowable.just(event1, event2), Flowable.just(event3, event4)); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(subAgent)).maxIterations(2).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1, event2, event3, event4).inOrder(); +} +" + "@Test +public void runAsync_withMultipleAgents_loopsAndReturnsEvents() { + Event event1 = createEvent("event1"); + Event event2 = createEvent("event2"); + Event event3 = createEvent("event3"); + Event event4 = createEvent("event4"); + TestBaseAgent subAgent1 = createSubAgent("subAgent1", Flowable.just(event1), Flowable.just(event3)); + TestBaseAgent subAgent2 = createSubAgent("subAgent2", Flowable.just(event2), Flowable.just(event4)); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(subAgent1, subAgent2)).maxIterations(2).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1, event2, event3, event4).inOrder(); +} +" + "@Test +public void runAsync_withEscalateAction_returnsEventsUpToEscalateAndStops() { + Event event1 = createEvent("event1"); + Event escalateEvent2 = createEscalateEvent("escalate2"); + Event event3 = createEvent("event3"); + Event event4 = createEvent("event4"); + Flowable subAgent1Events = Flowable.just(event1, escalateEvent2, event3); + Flowable subAgent2Events = Flowable.just(event4); + TestBaseAgent subAgent1 = createSubAgent("subAgent1", subAgent1Events); + TestBaseAgent subAgent2 = createSubAgent("subAgent2", subAgent2Events); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(subAgent1, subAgent2)).maxIterations(1).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1, escalateEvent2).inOrder(); +} +" + "@Test +public void runAsync_withEscalateAction_loopsAndReturnsEventsUpToEscalateAndStops() { + Event event1 = createEvent("event1"); + Event event2 = createEvent("event2"); + Event event3 = createEvent("event3"); + Event event4 = createEvent("event4"); + Event escalateEvent5 = createEscalateEvent("escalate5"); + Event escalateEvent6 = createEscalateEvent("escalate6"); + TestBaseAgent subAgent1 = createSubAgent("subAgent1", Flowable.just(event1, event2), Flowable.just(event4)); + TestBaseAgent subAgent2 = createSubAgent("subAgent2", Flowable.just(event3), Flowable.just(escalateEvent5, escalateEvent6)); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(subAgent1, subAgent2)).maxIterations(3).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1, event2, event3, event4, escalateEvent5).inOrder(); +} +" + "@Test +public void runAsync_withNoMaxIterations_keepsLooping() { + Event event1 = createEvent("event1"); + Event event2 = createEvent("event2"); + TestBaseAgent subAgent = createSubAgent("subAgent", () -> Flowable.just(event1, event2)); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(subAgent)).maxIterations(Optional.empty()).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + Iterable result = loopAgent.runAsync(invocationContext).blockingIterable(); + Iterable first10Events = Iterables.limit(result, 10); + assertThat(first10Events).containsExactly(event1, event2, event1, event2, event1, event2, event1, event2, event1, event2).inOrder(); +} +" + "@Test +public void runAsync_withEndInvocationInSubAgentCallback_stopsSubAgentButLoopContinues() { + AtomicInteger normalAgentRunCount = new AtomicInteger(0); + TestBaseAgent normalAgent = createSubAgent("NormalAgent", () -> { + int count = normalAgentRunCount.incrementAndGet(); + return Flowable.just(createEvent("Normal Agent Run " + count)); + }); + AtomicInteger subAgent2CallbackCount = new AtomicInteger(0); + AtomicInteger subAgent2RunCount = new AtomicInteger(0); + BeforeAgentCallback subAgent2BeforeCallback = (callbackContext) -> { + int callbackCount = subAgent2CallbackCount.incrementAndGet(); + if (callbackCount > 1) { + return Maybe.just(Content.fromParts(Part.fromText("Exit Callback Triggered After " + callbackCount + " Runs"))); + } + return Maybe.empty(); + }; + TestBaseAgent earlyExitAgent = new TestBaseAgent("EarlyExitAgent", "An agent that exits early after its callback is called once", () -> { + int count = subAgent2RunCount.incrementAndGet(); + return Flowable.just(createEvent("Early Exit Agent Run " + count)); + }, + ImmutableList.of(), + ImmutableList.of(subAgent2BeforeCallback), + ImmutableList.of()); + LoopAgent loopAgent = LoopAgent.builder().name("loopAgent").subAgents(ImmutableList.of(normalAgent, earlyExitAgent)).maxIterations(3).build(); + InvocationContext invocationContext = createInvocationContext(loopAgent); + List events = loopAgent.runAsync(invocationContext).toList().blockingGet(); + ImmutableList eventTexts = events.stream().filter(e -> e.content().isPresent()).map(e -> e.content().get().text()).collect(toImmutableList()); + assertThat(eventTexts).containsExactly("content for event Normal Agent Run 1", "content for event Early Exit Agent Run 1", "content for event Normal Agent Run 2", "Exit Callback Triggered After 2 Runs", "content for event Normal Agent Run 3", "Exit Callback Triggered After 3 Runs").inOrder(); + assertThat(normalAgentRunCount.get()).isEqualTo(3); + assertThat(subAgent2RunCount.get()).isEqualTo(1); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/ConfigAgentUtilsTest.java +Tests: + "@Test +public void fromConfig_withExamplesList_appendsExamplesInFlow() throws IOException, ConfigurationException { + + ComponentRegistry originalRegistry = ComponentRegistry.getInstance(); + class TestRegistry extends ComponentRegistry { + + TestRegistry() { + super(); + } + } + ComponentRegistry testRegistry = new TestRegistry(); + Example example = Example.builder().input(Content.fromParts(Part.fromText("qin"))).output(ImmutableList.of(Content.fromParts(Part.fromText("qout")))).build(); + testRegistry.register("multi_agent_llm_config.example_tool", ExampleTool.builder().addExample(example).build()); + ComponentRegistry.setInstance(testRegistry); + File configFile = tempFolder.newFile("with_examples.yaml"); + Files.writeString(configFile.toPath(), """ + name: examples_agent + description: Agent with examples configured via tool + instruction: You are a test agent + agent_class: LlmAgent + model: gemini-2.0-flash + tools: + - name: multi_agent_llm_config.example_tool + """); + String configPath = configFile.getAbsolutePath(); + BaseAgent agent; + try { + agent = ConfigAgentUtils.fromConfig(configPath); + } finally { + ComponentRegistry.setInstance(originalRegistry); + } + assertThat(agent).isInstanceOf(LlmAgent.class); + LlmAgent llmAgent = (LlmAgent) agent; + + LlmRequest.Builder requestBuilder = LlmRequest.builder().model("gemini-2.0-flash"); + InvocationContext context = TestUtils.createInvocationContext(agent); + llmAgent.canonicalTools(new ReadonlyContext(context)).concatMapCompletable(tool -> tool.processLlmRequest(requestBuilder, ToolContext.builder(context).build())).blockingAwait(); + LlmRequest updated = requestBuilder.build(); + + assertThat(updated.getSystemInstructions()).isNotEmpty(); +} +" + "@Test +public void resolveSubAgents_withCode_resolvesSuccessfully() throws IOException, ConfigurationException { + + LlmAgent testAgent = LlmAgent.builder().name("test_agent").description("Test agent for code resolution").instruction("Test instruction").build(); + + ComponentRegistry.getInstance().register("sub_agents_config.test_agent.agent", testAgent); + File mainAgentFile = tempFolder.newFile("main_agent.yaml"); + Files.writeString(mainAgentFile.toPath(), """ + agent_class: LlmAgent + name: main_agent + description: Main agent with code subagent + instruction: You are a main agent + sub_agents: + - code: sub_agents_config.test_agent.agent + """); + BaseAgent mainAgent = ConfigAgentUtils.fromConfig(mainAgentFile.getAbsolutePath()); + assertThat(mainAgent).isNotNull(); + assertThat(mainAgent.subAgents()).hasSize(1); + BaseAgent subAgent = mainAgent.subAgents().get(0); + assertThat(subAgent).isInstanceOf(LlmAgent.class); + assertThat(subAgent.name()).isEqualTo("test_agent"); + assertThat(subAgent.description()).isEqualTo("Test agent for code resolution"); +} +" + "@Test +public void resolveSubAgents_withLifeAgentUsingCode_resolvesSuccessfully() throws IOException, ConfigurationException { + + LlmAgent lifeAgent = LlmAgent.builder().name("life_agent").description("Life agent").instruction("You are a life agent. You are responsible for answering questions about life.").build(); + + ComponentRegistry.getInstance().register("sub_agents_config.life_agent.agent", lifeAgent); + File mainAgentFile = tempFolder.newFile("root_agent.yaml"); + Files.writeString(mainAgentFile.toPath(), """ + name: root_agent + model: gemini-2.0-flash + description: Root agent + instruction: | + If the user query is about life, you should route it to the life sub-agent. + If the user query is about work, you should route it to the work sub-agent. + If the user query is about anything else, you should answer it yourself. + sub_agents: + - code: sub_agents_config.life_agent.agent + """); + BaseAgent rootAgent = ConfigAgentUtils.fromConfig(mainAgentFile.getAbsolutePath()); + assertThat(rootAgent).isNotNull(); + assertThat(rootAgent.name()).isEqualTo("root_agent"); + assertThat(rootAgent.description()).isEqualTo("Root agent"); + assertThat(rootAgent).isInstanceOf(LlmAgent.class); + + assertThat(rootAgent.subAgents()).hasSize(1); + BaseAgent subAgent = rootAgent.subAgents().get(0); + assertThat(subAgent).isInstanceOf(LlmAgent.class); + assertThat(subAgent.name()).isEqualTo("life_agent"); + assertThat(subAgent.description()).isEqualTo("Life agent"); + LlmAgent llmSubAgent = (LlmAgent) subAgent; + assertThat(llmSubAgent.instruction().toString()).contains("You are a life agent. You are responsible for answering questions about life."); +} +" + "@Test +public void testLlmAgentConfigAccessors() { + LlmAgentConfig config = new LlmAgentConfig(); + assertThat(config.agentClass()).isEqualTo("LlmAgent"); + config.setModel("test-model"); + assertThat(config.model()).isEqualTo("test-model"); + config.setInstruction("test instruction"); + assertThat(config.instruction()).isEqualTo("test instruction"); + config.setDisallowTransferToParent(true); + assertThat(config.disallowTransferToParent()).isTrue(); + config.setDisallowTransferToPeers(false); + assertThat(config.disallowTransferToPeers()).isFalse(); + config.setOutputKey("test-output-key"); + assertThat(config.outputKey()).isEqualTo("test-output-key"); + config.setIncludeContents(LlmAgent.IncludeContents.NONE); + assertThat(config.includeContents()).isEqualTo(LlmAgent.IncludeContents.NONE); + GenerateContentConfig contentConfig = GenerateContentConfig.builder().temperature(0.8f).build(); + config.setGenerateContentConfig(contentConfig); + assertThat(config.generateContentConfig()).isEqualTo(contentConfig); + List beforeAgentCallbacks = new ArrayList<>(); + beforeAgentCallbacks.add(new LlmAgentConfig.CallbackRef("callback1")); + config.setBeforeAgentCallbacks(beforeAgentCallbacks); + assertThat(config.beforeAgentCallbacks()).hasSize(1); + assertThat(config.beforeAgentCallbacks().get(0).name()).isEqualTo("callback1"); + List afterAgentCallbacks = new ArrayList<>(); + afterAgentCallbacks.add(new LlmAgentConfig.CallbackRef("callback2")); + config.setAfterAgentCallbacks(afterAgentCallbacks); + assertThat(config.afterAgentCallbacks()).hasSize(1); + assertThat(config.afterAgentCallbacks().get(0).name()).isEqualTo("callback2"); + List beforeModelCallbacks = new ArrayList<>(); + beforeModelCallbacks.add(new LlmAgentConfig.CallbackRef("callback3")); + config.setBeforeModelCallbacks(beforeModelCallbacks); + assertThat(config.beforeModelCallbacks()).hasSize(1); + assertThat(config.beforeModelCallbacks().get(0).name()).isEqualTo("callback3"); + List afterModelCallbacks = new ArrayList<>(); + afterModelCallbacks.add(new LlmAgentConfig.CallbackRef("callback4")); + config.setAfterModelCallbacks(afterModelCallbacks); + assertThat(config.afterModelCallbacks()).hasSize(1); + assertThat(config.afterModelCallbacks().get(0).name()).isEqualTo("callback4"); + List beforeToolCallbacks = new ArrayList<>(); + beforeToolCallbacks.add(new LlmAgentConfig.CallbackRef("callback5")); + config.setBeforeToolCallbacks(beforeToolCallbacks); + assertThat(config.beforeToolCallbacks()).hasSize(1); + assertThat(config.beforeToolCallbacks().get(0).name()).isEqualTo("callback5"); + List afterToolCallbacks = new ArrayList<>(); + afterToolCallbacks.add(new LlmAgentConfig.CallbackRef("callback6")); + config.setAfterToolCallbacks(afterToolCallbacks); + assertThat(config.afterToolCallbacks()).hasSize(1); + assertThat(config.afterToolCallbacks().get(0).name()).isEqualTo("callback6"); + List tools = new ArrayList<>(); + BaseTool.ToolConfig toolConfig = new BaseTool.ToolConfig(); + toolConfig.setName("test-tool"); + tools.add(toolConfig); + config.setTools(tools); + assertThat(config.tools()).hasSize(1); + assertThat(config.tools().get(0).name()).isEqualTo("test-tool"); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/AgentWithMemoryTest.java +Tests: + "@Test +public void agentRemembersUserNameWithMemoryTool() throws Exception { + String userId = "test-user"; + String agentName = "test-agent"; + Part functionCall = Part.builder().functionCall(FunctionCall.builder().name("loadMemory").args(ImmutableMap.of("query", "what is my name?")).build()).build(); + TestLlm testLlm = new TestLlm(ImmutableList.of(LlmResponse.builder().content(Content.builder().parts(Part.fromText("OK, I'll remember that.")).role("model").build()).build(), LlmResponse.builder().content(Content.builder().role("model").parts(ImmutableList.of(functionCall)).build()).build(), LlmResponse.builder().content(Content.builder(). + + parts(Part.fromText("Your name is James.")).role("model").build()).build())); + LlmAgent agent = LlmAgent.builder().name(agentName).model(testLlm).tools(ImmutableList.of(new LoadMemoryTool())).build(); + InMemoryRunner runner = new InMemoryRunner(agent); + String sessionId = runner.sessionService().createSession(agentName, userId).blockingGet().id(); + Content firstMessage = Content.fromParts(Part.fromText("My name is James")); + var unused = runner.runAsync(userId, sessionId, firstMessage, RunConfig.builder().build()).toList().blockingGet(); + + Session updatedSession = runner.sessionService().getSession("test-agent", userId, sessionId, Optional.empty()).blockingGet(); + + runner.memoryService().addSessionToMemory(updatedSession).blockingAwait(); + Content secondMessage = Content.fromParts(Part.fromText("what is my name?")); + unused = runner.runAsync(userId, updatedSession.id(), secondMessage, RunConfig.builder().build()).toList().blockingGet(); + + LlmRequest lastRequest = testLlm.getLastRequest(); + Content functionResponseContent = Iterables.getLast(lastRequest.contents()); + Optional functionResponsePart = functionResponseContent.parts().get().stream().filter(p -> p.functionResponse().isPresent()).findFirst(); + assertThat(functionResponsePart).isPresent(); + FunctionResponse functionResponse = functionResponsePart.get().functionResponse().get(); + assertThat(functionResponse.name()).hasValue("loadMemory"); + assertThat(functionResponse.response().get().toString()).contains("My name is James"); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InstructionTest.java +Tests: + "@Test +public void testCanonicalInstruction_staticInstruction() { + String instruction = "Test static instruction"; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction(instruction).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction); +} +" + "@Test +public void testCanonicalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + "@Test +public void testCanonicalGlobalInstruction_staticInstruction() { + String instruction = "Test static global instruction"; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction(instruction).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalGlobalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction); +} +" + "@Test +public void testCanonicalGlobalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider global instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalGlobalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/SequentialAgentTest.java +Tests: + "@Test +public void runAsync_withNoSubAgents_returnsEmptyEvents() { + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of()).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).isEmpty(); +} +" + "@Test +public void runAsync_withSingleSubAgent_returnsEventsFromSubAgent() { + Event event1 = createEvent("event1").toBuilder().author("subAgent").build(); + TestBaseAgent subAgent = createSubAgent("subAgent", event1); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1); + assertThat(events.get(0).author()).isEqualTo("subAgent"); +} +" + "@Test +public void runAsync_withSingleLlmSubAgent_returnsEventsFromSubAgent() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + LlmAgent subAgent = createTestAgent(testLlm); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(1); + assertThat(getOnlyElement(events).content()).hasValue(modelContent); +} +" + "@Test +public void runAsync_withMultipleSubAgents_returnsConcatenatedEventsInOrder() { + Event event1 = createEvent("event1"); + Event event2 = createEvent("event2"); + Event event3 = createEvent("event3"); + TestBaseAgent subAgent1 = createSubAgent("subAgent", event1.toBuilder().author("subAgent").build(), event2.toBuilder().author("subAgent").build()); + TestBaseAgent subAgent2 = createSubAgent("subAgent2", event3.toBuilder().author("subAgent2").build()); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent1, subAgent2)).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(3); + assertThat(events.get(0).id()).isEqualTo("event1"); + assertThat(events.get(0).author()).isEqualTo("subAgent"); + assertThat(events.get(1).id()).isEqualTo("event2"); + assertThat(events.get(1).author()).isEqualTo("subAgent"); + assertThat(events.get(2).id()).isEqualTo("event3"); + assertThat(events.get(2).author()).isEqualTo("subAgent2"); +} +" + "@Test +public void runAsync_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runAsync(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +" + "@Test +public void runLive_withNoSubAgents_returnsEmptyEvents() { + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of()).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runLive(invocationContext).toList().blockingGet(); + assertThat(events).isEmpty(); +} +" + "@Test +public void runLive_withSingleSubAgent_returnsEventsFromSubAgent() { + Event event1 = createEvent("event1_live").toBuilder().author("subAgent_live").build(); + TestBaseAgent subAgent = createSubAgent("subAgent_live", event1); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgentLive").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runLive(invocationContext).toList().blockingGet(); + assertThat(events).containsExactly(event1); + assertThat(events.get(0).author()).isEqualTo("subAgent_live"); +} +" + "@Test +public void runLive_withMultipleSubAgents_returnsConcatenatedEventsInOrder() { + Event event1 = createEvent("event1_live"); + Event event2 = createEvent("event2_live"); + Event event3 = createEvent("event3_live"); + TestBaseAgent subAgent1 = createSubAgent("subAgent_live", event1.toBuilder().author("subAgent_live").build(), event2.toBuilder().author("subAgent_live").build()); + TestBaseAgent subAgent2 = createSubAgent("subAgent2_live", event3.toBuilder().author("subAgent2_live").build()); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgentLive").subAgents(ImmutableList.of(subAgent1, subAgent2)).build(); + InvocationContext invocationContext = createInvocationContext(sequentialAgent); + List events = sequentialAgent.runLive(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(3); + assertThat(events.get(0).id()).isEqualTo("event1_live"); + assertThat(events.get(0).author()).isEqualTo("subAgent_live"); + assertThat(events.get(1).id()).isEqualTo("event2_live"); + assertThat(events.get(1).author()).isEqualTo("subAgent_live"); + assertThat(events.get(2).id()).isEqualTo("event3_live"); + assertThat(events.get(2).author()).isEqualTo("subAgent2_live"); +} +" + "@Test +public void runLive_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent_live"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgentLive").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runLive(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/ParallelAgentTest.java +Tests: + "@Test +public void runAsync_subAgentsExecuteInParallel_eventsOrderedByCompletion() { + String agent1Name = "test_agent_1_delayed"; + String agent2Name = "test_agent_2_fast"; + String parallelAgentName = "test_parallel_agent"; + TestingAgent agent1 = new TestingAgent(agent1Name, "Delayed Agent", 500); + TestingAgent agent2 = new TestingAgent(agent2Name, "Fast Agent", 0); + ParallelAgent parallelAgent = ParallelAgent.builder().name(parallelAgentName).subAgents(agent1, agent2).build(); + InvocationContext invocationContext = createInvocationContext(parallelAgent); + List events = parallelAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(2); + + Event firstEvent = events.get(0); + assertThat(firstEvent.author()).isEqualTo(agent2Name); + assertThat(firstEvent.content().get().parts().get().get(0).text()).hasValue("Hello, async " + agent2Name + "!"); + assertThat(firstEvent.branch().get()).endsWith(agent2Name); + + Event secondEvent = events.get(1); + assertThat(secondEvent.author()).isEqualTo(agent1Name); + assertThat(secondEvent.content().get().parts().get().get(0).text()).hasValue("Hello, async " + agent1Name + "!"); + assertThat(secondEvent.branch().get()).endsWith(agent1Name); +} +" + "@Test +public void runAsync_noSubAgents_returnsEmptyFlowable() { + String parallelAgentName = "empty_parallel_agent"; + ParallelAgent parallelAgent = ParallelAgent.builder().name(parallelAgentName).subAgents(ImmutableList.of()).build(); + InvocationContext invocationContext = createInvocationContext(parallelAgent); + List events = parallelAgent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).isEmpty(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/BaseAgentTest.java +Tests: + "@Test +public void runAsync_beforeAgentCallbackReturnsContent_endsInvocationAndSkipsRunAsyncImplAndAfterCallback() { + AtomicBoolean runAsyncImplCalled = new AtomicBoolean(false); + AtomicBoolean afterAgentCallbackCalled = new AtomicBoolean(false); + Content callbackContent = Content.fromParts(Part.fromText("before_callback_output")); + Callbacks.BeforeAgentCallback beforeCallback = (callbackContext) -> Maybe.just(callbackContent); + Callbacks.AfterAgentCallback afterCallback = (callbackContext) -> { + afterAgentCallbackCalled.set(true); + return Maybe.empty(); + }; + TestBaseAgent agent = new TestBaseAgent(TEST_AGENT_NAME, TEST_AGENT_DESCRIPTION, ImmutableList.of(beforeCallback), ImmutableList.of(afterCallback), () -> Flowable.defer(() -> { + runAsyncImplCalled.set(true); + return Flowable.just(Event.builder().content(Content.fromParts(Part.fromText("main_output"))).build()); + })); + InvocationContext invocationContext = TestUtils.createInvocationContext(agent); + List results = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(results).hasSize(1); + assertThat(results.get(0).content()).hasValue(callbackContent); + assertThat(runAsyncImplCalled.get()).isFalse(); + assertThat(afterAgentCallbackCalled.get()).isFalse(); +} +"Scenario 1: Verify that builder() returns a non-null Builder instance + +Details: + TestName: builderReturnsNonNullInstance + Description: Verifies that calling InvocationContext.builder() returns a new, non-null Builder object. This is the most fundamental check to ensure the factory method works correctly. +Execution: + Arrange: No setup required; the method is static. + Act: Call InvocationContext.builder() and capture the returned value. + Assert: Assert that the returned Builder instance is not null. +Validation: + Confirms that the static factory method produces a valid Builder object. A null return value would prevent any further configuration or construction of an InvocationContext. + +--- + +Scenario 2: Verify that each call to builder() returns a distinct Builder instance + +Details: + TestName: builderReturnsNewInstanceOnEachCall + Description: Verifies that successive calls to InvocationContext.builder() produce separate, independent Builder objects and not the same singleton instance. +Execution: + Arrange: No setup required. + Act: Call InvocationContext.builder() twice, storing each result in a separate variable. + Assert: Assert that the two Builder instances are not the same object reference (i.e., assertThat(builder1).isNotSameInstanceAs(builder2)). +Validation: + Ensures there is no shared state between Builder instances obtained from separate calls. Sharing a Builder instance would cause unintended data leakage between independent InvocationContext construction operations. + +--- + +Scenario 3: Verify that the Builder returned by builder() has liveRequestQueue defaulting to empty Optional + +Details: + TestName: builderDefaultsLiveRequestQueueToEmpty + Description: Verifies that the Builder produced by builder() initializes the liveRequestQueue field to Optional.empty() by default, so that a built InvocationContext without explicitly setting a live request queue will reflect an absent queue. +Execution: + Arrange: Prepare the minimum required dependencies: a mock BaseSessionService, a mock BaseArtifactService, a mock BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), supply only the required fields (sessionService, artifactService, agent, session), and call build(). + Assert: Assert that context.liveRequestQueue() returns an empty Optional. +Validation: + Confirms the Builder correctly defaults the liveRequestQueue to empty, ensuring that contexts not using live streaming behave correctly without requiring the caller to explicitly opt out. + +--- + +Scenario 4: Verify that the Builder returned by builder() has endInvocation defaulting to false + +Details: + TestName: builderDefaultsEndInvocationToFalse + Description: Verifies that the Builder produced by builder() initializes the endInvocation flag to false by default, so that a newly created InvocationContext does not immediately signal the end of an invocation. +Execution: + Arrange: Prepare mocks for BaseSessionService, BaseArtifactService, BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), set only the required fields, and call build(). + Assert: Assert that context.endInvocation() returns false. +Validation: + Ensures the default state of a newly built InvocationContext is that the invocation is ongoing (not ended), which is the expected and safe starting condition for any agent execution. + +--- + +Scenario 5: Verify that the Builder returned by builder() has userContent defaulting to empty Optional + +Details: + TestName: builderDefaultsUserContentToEmpty + Description: Verifies that the Builder produced by builder() initializes the userContent field to Optional.empty() by default, allowing contexts to be created without any initial user content. +Execution: + Arrange: Prepare mocks for BaseSessionService, BaseArtifactService, BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), set only the required fields, and call build(). + Assert: Assert that context.userContent() returns an empty Optional. +Validation: + Confirms that the Builder correctly handles the absence of user content by default. This is important for scenarios such as live streaming invocations where no initial user message may be present. + +--- + +Scenario 6: Verify that the Builder returned by builder() generates a non-null invocationId by default + +Details: + TestName: builderGeneratesDefaultInvocationId + Description: Verifies that the Builder produced by builder() auto-generates a non-null, non-empty invocationId following the "e-" prefix convention defined by newInvocationContextId(). +Execution: + Arrange: Prepare mocks for BaseSessionService, BaseArtifactService, BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), set only the required fields, and call build(). + Assert: Assert that context.invocationId() is not null, is not empty, and starts with "e-". +Validation: + Ensures that every InvocationContext built without an explicit invocationId still has a unique, properly formatted identifier. This is critical for tracking and correlating events within a single agent invocation. + +--- + +Scenario 7: Verify that the Builder returned by builder() has a non-null PluginManager by default + +Details: + TestName: builderDefaultsPluginManagerToNonNull + Description: Verifies that the Builder produced by builder() initializes the pluginManager field to a new, non-null PluginManager instance, so that a built context can always reference a plugin manager without null checks. +Execution: + Arrange: Prepare mocks for BaseSessionService, BaseArtifactService, BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), set only the required fields, and call build(). + Assert: Assert that context.pluginManager() is not null. +Validation: + Confirms the Builder provides a sensible non-null default for the pluginManager. Downstream code that calls pluginManager() can do so safely without null-pointer concerns when the caller has not explicitly configured a plugin manager. + +--- + +Scenario 8: Verify that the Builder returned by builder() has a non-null RunConfig by default + +Details: + TestName: builderDefaultsRunConfigToNonNull + Description: Verifies that the Builder produced by builder() initializes the runConfig field to a default RunConfig instance, so that a built context always has configuration available without the caller needing to supply it explicitly. +Execution: + Arrange: Prepare mocks for BaseSessionService, BaseArtifactService, BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), set only the required fields, and call build(). + Assert: Assert that context.runConfig() is not null. +Validation: + Ensures there is always a valid RunConfig present on any InvocationContext, preventing NullPointerExceptions in code paths that access run configuration settings during agent execution. + +--- + +Scenario 9: Verify that a Builder obtained from builder() can successfully build a complete InvocationContext + +Details: + TestName: builderCanBuildCompleteInvocationContext + Description: Verifies that the Builder returned by builder() supports the full fluent chain of setter calls and produces a correctly populated InvocationContext when build() is called with all fields supplied. +Execution: + Arrange: Create mock instances for BaseSessionService, BaseArtifactService, BaseMemoryService, BaseAgent; create a Session using Session.builder("test-session-id").build(); create a Content using Content.builder().build(); create a RunConfig using RunConfig.builder().build(); define an invocationId string. + Act: Call InvocationContext.builder().sessionService(...).artifactService(...).memoryService(...).invocationId(...).agent(...).session(...).userContent(Optional.of(content)).runConfig(...).endInvocation(false).build() and capture the result. + Assert: Assert that the context is not null; assert that context.sessionService() equals the mock session service; assert that context.artifactService() equals the mock artifact service; assert that context.memoryService() equals the mock memory service; assert that context.invocationId() equals the defined invocationId; assert that context.agent() equals the mock agent; assert that context.session() equals the session; assert that context.userContent() contains the content; assert that context.runConfig() equals the runConfig; assert that context.endInvocation() is false. +Validation: + Confirms end-to-end that the Builder returned by builder() correctly transfers all configured values to the resulting InvocationContext. This validates the completeness and correctness of the builder pattern implementation. + +--- + +Scenario 10: Verify that the Builder returned by builder() correctly propagates a set invocationId + +Details: + TestName: builderPropagatesExplicitInvocationId + Description: Verifies that when an explicit invocationId is set on the Builder via invocationId(String), the resulting InvocationContext reflects exactly that value rather than the auto-generated default. +Execution: + Arrange: Prepare the required mocks and objects. Define a specific invocationId string, e.g., "my-custom-id". + Act: Call InvocationContext.builder() with all required fields plus .invocationId("my-custom-id") and call build(). + Assert: Assert that context.invocationId() equals "my-custom-id". +Validation: + Ensures the Builder correctly overrides the auto-generated default invocationId when an explicit one is provided by the caller, which is critical for use cases that require deterministic or externally assigned invocation identifiers. + +--- + +Scenario 11: Verify that the Builder returned by builder() correctly propagates a set liveRequestQueue + +Details: + TestName: builderPropagatesLiveRequestQueue + Description: Verifies that when a LiveRequestQueue is set on the Builder, the resulting InvocationContext contains that queue wrapped in a present Optional. +Execution: + Arrange: Create a LiveRequestQueue instance. Prepare the required mocks (BaseSessionService, BaseArtifactService, BaseAgent) and a Session. + Act: Call InvocationContext.builder() with required fields plus .liveRequestQueue(liveRequestQueue) and call build(). + Assert: Assert that context.liveRequestQueue() is present and contains the provided LiveRequestQueue. +Validation: + Confirms the Builder correctly propagates live request queue configuration. This is important for live streaming use cases where the queue is the primary mechanism for delivering real-time input to the agent. + +--- + +Scenario 12: Verify that the Builder returned by builder() has branch defaulting to empty Optional + +Details: + TestName: builderDefaultsBranchToEmpty + Description: Verifies that the Builder produced by builder() initializes the branch field to Optional.empty() by default, so that a built InvocationContext without a branch configured returns an empty Optional from branch(). +Execution: + Arrange: Prepare mocks for BaseSessionService, BaseArtifactService, BaseAgent, and a Session object. + Act: Call InvocationContext.builder(), set only the required fields, and call build(). + Assert: Assert that context.branch() returns an empty Optional. +Validation: + Confirms that newly created contexts have no branch by default, which is the expected state for top-level (non-forked) invocations. A non-empty default branch value would incorrectly imply a fork in the conversation history. + +--- + +Scenario 13: Verify that the Builder returned by builder() correctly propagates an explicit branch value + +Details: + TestName: builderPropagatesExplicitBranch + Description: Verifies that when a branch string is set on the Builder via branch(String), the resulting InvocationContext contains that branch value wrapped in a present Optional. +Execution: + Arrange: Prepare the required mocks and objects. Define a branch string, e.g., "my-branch". + Act: Call InvocationContext.builder() with required fields plus .branch("my-branch") and call build(). + Assert: Assert that context.branch() is present and its value equals "my-branch". +Validation: + Confirms the Builder correctly propagates explicit branch values to the InvocationContext, ensuring that sub-agent or forked invocations can maintain proper conversation history tracking. + +*/ + +// ********RoostGPT******** + +```java +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.events.Event; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.*; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.InlineMe; +import com.google.genai.types.FunctionCall; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextBuilderTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private BaseAgent mockAgent; + + private Session mockSession; + + private RunConfig defaultRunConfig; + + @BeforeEach + public void setUp() { + mockSession = mock(Session.class); + when(mockSession.appName()).thenReturn("test-app"); + when(mockSession.userId()).thenReturn("test-user"); + defaultRunConfig = RunConfig.builder().build(); + } + + @Test + @Tag("valid") + public void builderReturnsNonNullInstance() { + // Act + InvocationContext.Builder builder = InvocationContext.builder(); + // Assert + assertThat(builder).isNotNull(); + } + + @Test + @Tag("valid") + public void builderReturnsNewInstanceOnEachCall() { + // Act + InvocationContext.Builder builder1 = InvocationContext.builder(); + InvocationContext.Builder builder2 = InvocationContext.builder(); + // Assert + assertThat(builder1).isNotSameInstanceAs(builder2); + } + + @Test + @Tag("valid") + public void builderDefaultsLiveRequestQueueToEmpty() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("valid") + public void builderDefaultsEndInvocationToFalse() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.endInvocation()).isFalse(); + } + + @Test + @Tag("valid") + public void builderDefaultsUserContentToEmpty() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.userContent()).isEmpty(); + } + + @Test + @Tag("valid") + public void builderGeneratesDefaultInvocationId() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.invocationId()).isNotNull(); + assertThat(context.invocationId()).isNotEmpty(); + assertThat(context.invocationId()).startsWith("e-"); + } + + @Test + @Tag("valid") + public void builderDefaultsPluginManagerToNonNull() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.pluginManager()).isNotNull(); + } + + @Test + @Tag("valid") + public void builderDefaultsRunConfigToNonNull() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.runConfig()).isNotNull(); + } + + @Test + @Tag("integration") + public void builderCanBuildCompleteInvocationContext() { + // Arrange + String invocationId = "e-test-invocation-id"; + Content userContent = Content.builder().build(); + RunConfig runConfig = RunConfig.builder().build(); + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(invocationId) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .endInvocation(false) + .build(); + // Assert + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.invocationId()).isEqualTo(invocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(mockSession); + assertThat(context.userContent()).isPresent(); + assertThat(context.userContent().get()).isEqualTo(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); + } + + @Test + @Tag("valid") + public void builderPropagatesExplicitInvocationId() { + // Arrange + String customInvocationId = "my-custom-id"; + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .invocationId(customInvocationId) + .build(); + // Assert + assertThat(context.invocationId()).isEqualTo(customInvocationId); + } + + @Test + @Tag("valid") + public void builderPropagatesLiveRequestQueue() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .liveRequestQueue(liveRequestQueue) + .build(); + // Assert + assertThat(context.liveRequestQueue()).isPresent(); + assertThat(context.liveRequestQueue().get()).isEqualTo(liveRequestQueue); + } + + @Test + @Tag("valid") + public void builderDefaultsBranchToEmpty() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.branch()).isEmpty(); + } + + @Test + @Tag("valid") + public void builderPropagatesExplicitBranch() { + // Arrange + String branchValue = "my-branch"; + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .branch(branchValue) + .build(); + // Assert + assertThat(context.branch()).isPresent(); + assertThat(context.branch().get()).isEqualTo(branchValue); + } + + @Test + @Tag("valid") + public void builderPropagatesOptionalLiveRequestQueue() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .build(); + // Assert + assertThat(context.liveRequestQueue()).isPresent(); + assertThat(context.liveRequestQueue().get()).isEqualTo(liveRequestQueue); + } + + @Test + @Tag("valid") + public void builderPropagatesOptionalEmptyLiveRequestQueue() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .liveRequestQueue(Optional.empty()) + .build(); + // Assert + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("valid") + public void builderPropagatesOptionalBranch() { + // Arrange + String branchValue = "optional-branch"; + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .branch(Optional.of(branchValue)) + .build(); + // Assert + assertThat(context.branch()).isPresent(); + assertThat(context.branch().get()).isEqualTo(branchValue); + } + + @Test + @Tag("valid") + public void builderPropagatesUserContentViaContent() { + // Arrange + Content userContent = Content.builder().build(); + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .userContent(userContent) + .build(); + // Assert + assertThat(context.userContent()).isPresent(); + assertThat(context.userContent().get()).isEqualTo(userContent); + } + + @Test + @Tag("valid") + public void builderPropagatesEndInvocationTrue() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .endInvocation(true) + .build(); + // Assert + assertThat(context.endInvocation()).isTrue(); + } + + @Test + @Tag("valid") + public void builderPropagatesPluginManager() { + // Arrange + PluginManager pluginManager = mock(PluginManager.class); + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .pluginManager(pluginManager) + .build(); + // Assert + assertThat(context.pluginManager()).isEqualTo(pluginManager); + } + + @Test + @Tag("valid") + public void builderPropagatesMemoryService() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + } + + @Test + @Tag("valid") + public void builderPropagatesSession() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.session()).isEqualTo(mockSession); + } + + @Test + @Tag("valid") + public void builderPropagatesSessionService() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.sessionService()).isEqualTo(mockSessionService); + } + + @Test + @Tag("valid") + public void builderPropagatesArtifactService() { + // Act + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + // Assert + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + } + +@Test + @Tag("boundary") + public void builderGeneratesUniqueInvocationIdsOnMultipleBuilds() { + // Act + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) \ No newline at end of file diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextCopyOfTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextCopyOfTest.java new file mode 100644 index 000000000..bc34cfcbf --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextCopyOfTest.java @@ -0,0 +1,497 @@ +/* + * 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=copyOf_49f0784c6e +ROOST_METHOD_SIG_HASH=copyOf_2c012f0957 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +"Scenario 1: Copy of Context with Minimal Required Fields Only + +Details: + TestName: copyOfWithMinimalRequiredFields + Description: Verifies that copyOf correctly creates a new InvocationContext when only the + minimal required fields (sessionService, artifactService, invocationId, agent, + session) are set, while optional fields retain their defaults. +Execution: + Arrange: Build an InvocationContext using the builder with only sessionService, + artifactService, invocationId, agent, and session set. Leave memoryService, + pluginManager, liveRequestQueue, userContent, runConfig, branch, endInvocation, + and resumabilityConfig at their defaults. + Act: Call InvocationContext.copyOf(originalContext). + Assert: Assert that the returned context is not null, is not the same instance as the + original, and that sessionService(), artifactService(), invocationId(), agent(), + and session() all match the original. Assert that userContent() equals + Optional.empty(), liveRequestQueue() equals Optional.empty(), and + endInvocation() is false. +Validation: + Verifies that copyOf handles the minimal-field scenario without errors, and that default + values for optional fields are correctly propagated into the new context. This is important + to ensure robustness when not all optional fields are explicitly set during context creation. + +*/ + +// ********RoostGPT******** + +```java +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.events.Event; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import io.reactivex.rxjava3.core.Flowable; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.*; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.InlineMe; +import com.google.genai.types.FunctionCall; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +@ExtendWith(MockitoExtension.class) +class InvocationContextCopyOfTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + private BaseAgent mockAgent; + + private RunConfig defaultRunConfig; + + @BeforeEach + void setUp() { + mockAgent = new BaseAgent("testAgent", "A test agent", null, null, null) { + @Override + protected Flowable runAsyncImpl(InvocationContext invocationContext) { + return Flowable.empty(); + } + + @Override + protected Flowable runLiveImpl(InvocationContext invocationContext) { + return Flowable.empty(); + } + }; + defaultRunConfig = RunConfig.builder().build(); + } + + // ------------------------------------------------------------------------- + // Scenario 1: Copy of Context with Minimal Required Fields Only + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfWithMinimalRequiredFields() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertNotSame(original, copy); + assertSame(mockSessionService, copy.sessionService()); + assertSame(mockArtifactService, copy.artifactService()); + assertEquals("inv-001", copy.invocationId()); + assertSame(mockAgent, copy.agent()); + assertSame(mockSession, copy.session()); + assertEquals(Optional.empty(), copy.userContent()); + assertEquals(Optional.empty(), copy.liveRequestQueue()); + assertFalse(copy.endInvocation()); + assertNull(copy.memoryService()); + assertNull(copy.pluginManager()); + assertNull(copy.runConfig()); + assertEquals(Optional.empty(), copy.branch()); + } + + // ------------------------------------------------------------------------- + // Scenario 2: Copy of Context with All Fields Set + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfWithAllFieldsSet() { + // Arrange + Content userContent = Content.newBuilder().build(); + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + ResumabilityConfig resumabilityConfig = mock(ResumabilityConfig.class); + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("inv-full-001") + .agent(mockAgent) + .session(mockSession) + .userContent(userContent) + .runConfig(defaultRunConfig) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .branch("main-branch") + .endInvocation(true) + .resumabilityConfig(resumabilityConfig) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertNotSame(original, copy); + assertSame(mockSessionService, copy.sessionService()); + assertSame(mockArtifactService, copy.artifactService()); + assertSame(mockMemoryService, copy.memoryService()); + assertSame(mockPluginManager, copy.pluginManager()); + assertEquals("inv-full-001", copy.invocationId()); + assertSame(mockAgent, copy.agent()); + assertSame(mockSession, copy.session()); + assertTrue(copy.userContent().isPresent()); + assertSame(userContent, copy.userContent().get()); + assertSame(defaultRunConfig, copy.runConfig()); + assertTrue(copy.liveRequestQueue().isPresent()); + assertSame(liveRequestQueue, copy.liveRequestQueue().get()); + assertTrue(copy.branch().isPresent()); + assertEquals("main-branch", copy.branch().get()); + assertTrue(copy.endInvocation()); + assertSame(resumabilityConfig, copy.resumabilityConfig()); + } + + // ------------------------------------------------------------------------- + // Scenario 3: Copy preserves activeStreamingTools + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfPreservesActiveStreamingTools() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-streaming-001") + .agent(mockAgent) + .session(mockSession) + .build(); + ActiveStreamingTool mockTool1 = mock(ActiveStreamingTool.class); + ActiveStreamingTool mockTool2 = mock(ActiveStreamingTool.class); + original.activeStreamingTools().put("tool1", mockTool1); + original.activeStreamingTools().put("tool2", mockTool2); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertNotSame(original, copy); + assertEquals(2, copy.activeStreamingTools().size()); + assertSame(mockTool1, copy.activeStreamingTools().get("tool1")); + assertSame(mockTool2, copy.activeStreamingTools().get("tool2")); + } + + // ------------------------------------------------------------------------- + // Scenario 4: Copy returns a distinct instance (not same reference) + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfReturnsDistinctInstance() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-distinct-001") + .agent(mockAgent) + .session(mockSession) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertNotSame(original, copy); + } + + // ------------------------------------------------------------------------- + // Scenario 5: Copy of context with endInvocation = false propagates correctly + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfWithEndInvocationFalse() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-end-false-001") + .agent(mockAgent) + .session(mockSession) + .endInvocation(false) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertFalse(copy.endInvocation()); + } + + // ------------------------------------------------------------------------- + // Scenario 6: Copy of context with endInvocation = true propagates correctly + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfWithEndInvocationTrue() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-end-true-001") + .agent(mockAgent) + .session(mockSession) + .endInvocation(true) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertTrue(copy.endInvocation()); + } + + // ------------------------------------------------------------------------- + // Scenario 7: Mutations to copy do not affect original + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfMutationDoesNotAffectOriginal() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-mutation-001") + .agent(mockAgent) + .session(mockSession) + .endInvocation(false) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + copy.setEndInvocation(true); + copy.branch("new-branch"); + // Assert + assertFalse(original.endInvocation()); + assertEquals(Optional.empty(), original.branch()); + assertTrue(copy.endInvocation()); + assertEquals(Optional.of("new-branch"), copy.branch()); + } + + // ------------------------------------------------------------------------- + // Scenario 8: Mutations to activeStreamingTools in copy do not affect original + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfActiveStreamingToolsMutationDoesNotAffectOriginal() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-tool-mutation-001") + .agent(mockAgent) + .session(mockSession) + .build(); + ActiveStreamingTool mockTool = mock(ActiveStreamingTool.class); + original.activeStreamingTools().put("tool1", mockTool); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + ActiveStreamingTool mockTool2 = mock(ActiveStreamingTool.class); + copy.activeStreamingTools().put("tool2", mockTool2); + // Assert + assertEquals(1, original.activeStreamingTools().size()); + assertTrue(original.activeStreamingTools().containsKey("tool1")); + assertFalse(original.activeStreamingTools().containsKey("tool2")); + assertEquals(2, copy.activeStreamingTools().size()); + assertTrue(copy.activeStreamingTools().containsKey("tool1")); + assertTrue(copy.activeStreamingTools().containsKey("tool2")); + } + + // ------------------------------------------------------------------------- + // Scenario 9: Copy of context with empty activeStreamingTools + // ------------------------------------------------------------------------- + @Test + @Tag("boundary") + void copyOfWithEmptyActiveStreamingTools() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-empty-tools-001") + .agent(mockAgent) + .session(mockSession) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertNotNull(copy.activeStreamingTools()); + assertTrue(copy.activeStreamingTools().isEmpty()); + } + + // ------------------------------------------------------------------------- + // Scenario 10: Copy of context preserves branch value + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfPreservesBranchValue() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-branch-001") + .agent(mockAgent) + .session(mockSession) + .branch("parent.child.grandchild") + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertTrue(copy.branch().isPresent()); + assertEquals("parent.child.grandchild", copy.branch().get()); + } + + // ------------------------------------------------------------------------- + // Scenario 11: Copy of context with Optional.empty branch + // ------------------------------------------------------------------------- + @Test + @Tag("boundary") + void copyOfWithEmptyBranch() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-no-branch-001") + .agent(mockAgent) + .session(mockSession) + .branch(Optional.empty()) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertFalse(copy.branch().isPresent()); + } + + // ------------------------------------------------------------------------- + // Scenario 12: Copy of context preserves invocationId exactly + // ------------------------------------------------------------------------- + @Test + @Tag("valid") + void copyOfPreservesInvocationId() { + // Arrange + String specificId = "e-" + "12345678-1234-1234-1234-123456789012"; + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(specificId) + .agent(mockAgent) + .session(mockSession) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertEquals(specificId, copy.invocationId()); + } + + // ------------------------------------------------------------------------- + // Scenario 13: Copy of context with null optional fields (userContent = empty) + // ------------------------------------------------------------------------- + @Test + @Tag("boundary") + void copyOfWithNullUserContent() { + // Arrange + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-null-content-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .build(); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertNotNull(copy); + assertFalse(copy.userContent().isPresent()); + } + +// ------------------------------------------------------------------------- +// Scenario 14: Copy of context preserves runConfig +// ------------------------------------------------------------------------- +@Test + @Tag("valid") + void copyOfPreservesRunConfig() { + // Arrange + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(10).build(); + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockA \ No newline at end of file diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextCreate573Test.java b/core/src/test/java/com/google/adk/agents/InvocationContextCreate573Test.java new file mode 100644 index 000000000..af3e57cd5 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextCreate573Test.java @@ -0,0 +1,384 @@ +/* + * 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=create_6e6963ca78 +ROOST_METHOD_SIG_HASH=create_ac1179ff57 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/ToolResolverTest.java +Tests: + "@Test +public void testResolveToolInstance_fromRegistry() throws Exception { + FunctionTool testTool = FunctionTool.create(TestToolWithMethods.class, "method1"); + testRegistry.register("test.tool.instance", testTool); + BaseTool resolved = ToolResolver.resolveToolInstance("test.tool.instance"); + assertThat(resolved).isEqualTo(testTool); +} +" + "@Test +public void testResolveTools_mixedTypes() throws Exception { + + FunctionTool registeredTool = FunctionTool.create(TestToolWithMethods.class, "method1"); + testRegistry.register("registered.tool", registeredTool); + ImmutableList toolConfigs = ImmutableList.of( + createToolConfig("registered.tool", null), + createToolConfig(TestToolWithDefaultConstructor.class.getName(), null), createToolConfig(TestToolWithStaticField.class.getName() + ".INSTANCE", + null)); + ImmutableList resolved = ToolResolver.resolveTools(toolConfigs, "/test/path"); + assertThat(resolved).hasSize(3); + assertThat(resolved.get(0)).isEqualTo(registeredTool); + assertThat(resolved.get(1)).isInstanceOf(TestToolWithDefaultConstructor.class); + assertThat(resolved.get(2)).isInstanceOf(TestToolWithStaticField.class); +} +"Scenario 1: Create InvocationContext with All Valid Non-Null Parameters + +Details: + TestName: createWithAllValidNonNullParameters + Description: Verifies that calling the create method with all valid, non-null parameters produces a fully populated InvocationContext instance where each field is correctly assigned. + +Execution: + Arrange: + - Create a mock or stub instance of BaseSessionService. + - Create a mock or stub instance of BaseArtifactService. + - Create a mock or stub instance of BaseAgent. + - Create a mock or stub instance of Session. + - Create a mock or stub instance of LiveRequestQueue. + - Create a RunConfig instance using RunConfig.builder().build(). + Act: + - Call InvocationContext.create(sessionService, artifactService, agent, session, liveRequestQueue, runConfig). + Assert: + - Assert that the returned InvocationContext is not null. + - Assert that context.sessionService() equals the provided sessionService. + - Assert that context.artifactService() equals the provided artifactService. + - Assert that context.agent() equals the provided agent. + - Assert that context.session() equals the provided session. + - Assert that context.liveRequestQueue() is equal to Optional.of(liveRequestQueue). + - Assert that context.runConfig() equals the provided runConfig. + +Validation: + This test ensures that when all parameters are provided and non-null, the factory method correctly delegates to the builder and produces an InvocationContext with every field set to the expected value. It validates the fundamental happy-path behavior of the create method. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextCreate573Test { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + private LiveRequestQueue liveRequestQueue; + + private RunConfig runConfig; + + @BeforeEach + void setUp() { + liveRequestQueue = new LiveRequestQueue(); + runConfig = RunConfig.builder().build(); + } + + @Test + @Tag("valid") + void createWithAllValidNonNullParameters() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertEquals(Optional.of(liveRequestQueue), context.liveRequestQueue()); + assertEquals(runConfig, context.runConfig()); + } + + @Test + @Tag("valid") + void createWithNullLiveRequestQueue() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, null, runConfig); + assertNotNull(context); + assertEquals(Optional.empty(), context.liveRequestQueue()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertEquals(runConfig, context.runConfig()); + } + + @Test + @Tag("valid") + void createWithNullSessionService() { + InvocationContext context = InvocationContext.create(null, mockArtifactService, mockAgent, mockSession, + liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertEquals(Optional.of(liveRequestQueue), context.liveRequestQueue()); + } + + @Test + @Tag("valid") + void createWithNullArtifactService() { + InvocationContext context = InvocationContext.create(mockSessionService, null, mockAgent, mockSession, + liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.artifactService()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertEquals(Optional.of(liveRequestQueue), context.liveRequestQueue()); + } + + @Test + @Tag("valid") + void createWithNullAgent() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, null, mockSession, + liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.agent()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockSession, context.session()); + assertEquals(Optional.of(liveRequestQueue), context.liveRequestQueue()); + } + + @Test + @Tag("valid") + void createWithNullSession() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, null, + liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.session()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockAgent, context.agent()); + assertEquals(Optional.of(liveRequestQueue), context.liveRequestQueue()); + } + + @Test + @Tag("valid") + void createWithNullRunConfig() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, null); + assertNotNull(context); + assertNull(context.runConfig()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertEquals(Optional.of(liveRequestQueue), context.liveRequestQueue()); + } + + @Test + @Tag("boundary") + void createWithAllNullParameters() { + InvocationContext context = InvocationContext.create(null, null, null, null, null, null); + assertNotNull(context); + assertNull(context.sessionService()); + assertNull(context.artifactService()); + assertNull(context.agent()); + assertNull(context.session()); + assertEquals(Optional.empty(), context.liveRequestQueue()); + assertNull(context.runConfig()); + } + + @Test + @Tag("valid") + void createReturnsContextWithEmptyInvocationId() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.invocationId()); + } + + @Test + @Tag("valid") + void createReturnsContextWithEmptyUserContent() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertNotNull(context.userContent()); + assertFalse(context.userContent().isPresent()); + } + + @Test + @Tag("valid") + void createReturnsContextWithEndInvocationFalse() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertFalse(context.endInvocation()); + } + + @Test + @Tag("valid") + void createReturnsContextWithEmptyBranch() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertNotNull(context.branch()); + assertFalse(context.branch().isPresent()); + } + + @Test + @Tag("valid") + void createReturnsContextWithEmptyActiveStreamingTools() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertNotNull(context.activeStreamingTools()); + assertTrue(context.activeStreamingTools().isEmpty()); + } + + @Test + @Tag("valid") + void createWithLiveRequestQueuePresent() { + LiveRequestQueue queue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, queue, runConfig); + assertNotNull(context); + assertTrue(context.liveRequestQueue().isPresent()); + assertEquals(queue, context.liveRequestQueue().get()); + } + + @Test + @Tag("integration") + void createWithRunConfigMaxLlmCallsCustomValue() { + RunConfig customRunConfig = RunConfig.builder().setMaxLlmCalls(100).build(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, customRunConfig); + assertNotNull(context); + assertEquals(100, context.runConfig().maxLlmCalls()); + } + + @Test + @Tag("integration") + void createReturnsDistinctInstancesOnMultipleCalls() { + InvocationContext context1 = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + InvocationContext context2 = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context1); + assertNotNull(context2); + assertNotSame(context1, context2); + } + + @Test + @Tag("integration") + void createContextCanBeUsedWithCopyOf() { + InvocationContext original = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + InvocationContext copy = InvocationContext.copyOf(original); + assertNotNull(copy); + assertEquals(original.sessionService(), copy.sessionService()); + assertEquals(original.artifactService(), copy.artifactService()); + assertEquals(original.agent(), copy.agent()); + assertEquals(original.session(), copy.session()); + assertEquals(original.liveRequestQueue(), copy.liveRequestQueue()); + assertEquals(original.runConfig(), copy.runConfig()); + assertEquals(original.endInvocation(), copy.endInvocation()); + } + + @Test + @Tag("valid") + void createWithDifferentSessionServicesReturnsDifferentContexts() { + BaseSessionService anotherSessionService = mock(BaseSessionService.class); + InvocationContext context1 = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + InvocationContext context2 = InvocationContext.create(anotherSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context1); + assertNotNull(context2); + assertNotEquals(context1.sessionService(), context2.sessionService()); + } + + @Test + @Tag("valid") + void createContextMemoryServiceIsNull() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.memoryService()); + } + + @Test + @Tag("valid") + void createContextPluginManagerIsNull() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context); + assertNull(context.pluginManager()); + } + + @Test + @Tag("integration") + void createContextEqualsAnotherContextWithSameParameters() { + InvocationContext context1 = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + InvocationContext context2 = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + assertNotNull(context1); + assertNotNull(context2); + assertEquals(context1, context2); + } + + @Test + @Tag("boundary") + void createWithNewLiveRequestQueueHasCorrectOptionalWrapping() { + LiveRequestQueue queue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, queue, runConfig); + assertNotNull(context); + Optional liveQueueOpt = context.liveRequestQueue(); + assertNotNull(liveQueueOpt); + assertTrue(liveQueueOpt.isPresent()); + assertSame(queue, liveQueueOpt.get()); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextCreateTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextCreateTest.java new file mode 100644 index 000000000..693faab4a --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextCreateTest.java @@ -0,0 +1,464 @@ +/* + * 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=create_a8299eaa31 +ROOST_METHOD_SIG_HASH=create_95f62994c3 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/ToolResolverTest.java +Tests: + "@Test +public void testResolveToolInstance_fromRegistry() throws Exception { + FunctionTool testTool = FunctionTool.create(TestToolWithMethods.class, "method1"); + testRegistry.register("test.tool.instance", testTool); + BaseTool resolved = ToolResolver.resolveToolInstance("test.tool.instance"); + assertThat(resolved).isEqualTo(testTool); +} +" + "@Test +public void testResolveTools_mixedTypes() throws Exception { + + FunctionTool registeredTool = FunctionTool.create(TestToolWithMethods.class, "method1"); + testRegistry.register("registered.tool", registeredTool); + ImmutableList toolConfigs = ImmutableList.of( + createToolConfig("registered.tool", null), + createToolConfig(TestToolWithDefaultConstructor.class.getName(), null), createToolConfig(TestToolWithStaticField.class.getName() + ".INSTANCE", + null)); + ImmutableList resolved = ToolResolver.resolveTools(toolConfigs, "/test/path"); + assertThat(resolved).hasSize(3); + assertThat(resolved.get(0)).isEqualTo(registeredTool); + assertThat(resolved.get(1)).isInstanceOf(TestToolWithDefaultConstructor.class); + assertThat(resolved.get(2)).isInstanceOf(TestToolWithStaticField.class); +} +"Scenario 1: Create InvocationContext With All Valid Non-Null Parameters + +Details: + TestName: createWithAllValidNonNullParameters + Description: Verifies that the `create` method successfully constructs an `InvocationContext` when all parameters, + including a non-null `userContent`, are provided with valid values. This confirms that each field + is correctly assigned through the builder chain. +Execution: + Arrange: + - Create a mock of `BaseSessionService`. + - Create a mock of `BaseArtifactService`. + - Create a mock of `BaseAgent`. + - Create a mock of `Session`. + - Create a mock of `Content` (non-null userContent). + - Create a mock of `RunConfig`. + - Define a non-empty `invocationId` string (e.g., "test-invocation-id-001"). + Act: + - Call `InvocationContext.create(sessionService, artifactService, invocationId, agent, session, userContent, runConfig)`. + Assert: + - Assert that the returned `InvocationContext` object is not null. + - Assert that `context.sessionService()` equals the provided `sessionService` mock. + - Assert that `context.artifactService()` equals the provided `artifactService` mock. + - Assert that `context.invocationId()` equals "test-invocation-id-001". + - Assert that `context.agent()` equals the provided `agent` mock. + - Assert that `context.session()` equals the provided `session` mock. + - Assert that `context.userContent()` is present and equals the provided `userContent` mock. + - Assert that `context.runConfig()` equals the provided `runConfig` mock. +Validation: + This test validates the primary happy-path scenario, ensuring that the factory method correctly + delegates all provided parameters to the underlying builder and that the resulting context + accurately reflects all supplied values. This is fundamental to the correct initialization of + an invocation lifecycle. + +*/ + +// ********RoostGPT******** + +```java +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.*; +import com.google.adk.events.Event; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.InlineMe; +import com.google.genai.types.FunctionCall; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextCreateTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @Mock + private Content mockUserContent; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + private static final String VALID_INVOCATION_ID = "test-invocation-id-001"; + + @BeforeEach + void setUp() { + // Common setup if needed + } + + // ===== Scenario 1: Create InvocationContext With All Valid Non-Null Parameters ===== + @Test + @Tag("valid") + void createWithAllValidNonNullParameters() { + // Arrange + String invocationId = VALID_INVOCATION_ID; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, invocationId, + mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(invocationId, context.invocationId()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertTrue(context.userContent().isPresent()); + assertEquals(mockUserContent, context.userContent().get()); + assertEquals(mockRunConfig, context.runConfig()); + } + + // ===== Scenario 2: Create InvocationContext With Null UserContent ===== + @Test + @Tag("valid") + void createWithNullUserContentResultsInEmptyOptional() { + // Arrange + String invocationId = "test-invocation-null-content"; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, invocationId, + mockAgent, mockSession, null, mockRunConfig); + // Assert + assertNotNull(context); + assertFalse(context.userContent().isPresent()); + assertEquals(invocationId, context.invocationId()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(mockAgent, context.agent()); + assertEquals(mockSession, context.session()); + assertEquals(mockRunConfig, context.runConfig()); + } + + // ===== Scenario 3: Create InvocationContext With Null SessionService ===== + @Test + @Tag("valid") + void createWithNullSessionService() { + // Arrange + String invocationId = "test-invocation-null-session-service"; + // Act + InvocationContext context = InvocationContext.create(null, mockArtifactService, invocationId, mockAgent, + mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertNull(context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + assertEquals(invocationId, context.invocationId()); + } + + // ===== Scenario 4: Create InvocationContext With Null ArtifactService ===== + @Test + @Tag("valid") + void createWithNullArtifactService() { + // Arrange + String invocationId = "test-invocation-null-artifact-service"; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, null, invocationId, mockAgent, + mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertEquals(mockSessionService, context.sessionService()); + assertNull(context.artifactService()); + assertEquals(invocationId, context.invocationId()); + } + + // ===== Scenario 5: Create InvocationContext With Empty InvocationId ===== + @Test + @Tag("boundary") + void createWithEmptyInvocationId() { + // Arrange + String emptyInvocationId = ""; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, emptyInvocationId, + mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertEquals("", context.invocationId()); + assertEquals(mockSessionService, context.sessionService()); + assertEquals(mockArtifactService, context.artifactService()); + } + + // ===== Scenario 6: Create InvocationContext With Null InvocationId ===== + @Test + @Tag("boundary") + void createWithNullInvocationId() { + // Arrange - null invocationId + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, null, mockAgent, + mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertNull(context.invocationId()); + } + + // ===== Scenario 7: Create InvocationContext With Null Agent ===== + @Test + @Tag("valid") + void createWithNullAgent() { + // Arrange + String invocationId = "test-invocation-null-agent"; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, invocationId, + null, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertNull(context.agent()); + assertEquals(invocationId, context.invocationId()); + } + + // ===== Scenario 8: Create InvocationContext With Null Session ===== + @Test + @Tag("valid") + void createWithNullSession() { + // Arrange + String invocationId = "test-invocation-null-session"; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, invocationId, + mockAgent, null, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertNull(context.session()); + assertEquals(invocationId, context.invocationId()); + } + + // ===== Scenario 9: Create InvocationContext With Null RunConfig ===== + @Test + @Tag("valid") + void createWithNullRunConfig() { + // Arrange + String invocationId = "test-invocation-null-runconfig"; + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, invocationId, + mockAgent, mockSession, mockUserContent, null); + // Assert + assertNotNull(context); + assertNull(context.runConfig()); + assertEquals(invocationId, context.invocationId()); + } + + // ===== Scenario 10: Create InvocationContext With All Null Parameters ===== + @Test + @Tag("boundary") + void createWithAllNullParameters() { + // Act + InvocationContext context = InvocationContext.create(null, null, null, null, null, null, null); + // Assert + assertNotNull(context); + assertNull(context.sessionService()); + assertNull(context.artifactService()); + assertNull(context.invocationId()); + assertNull(context.agent()); + assertNull(context.session()); + assertFalse(context.userContent().isPresent()); + assertNull(context.runConfig()); + } + + // ===== Scenario 11: Create InvocationContext Returns Non-Null Object ===== + @Test + @Tag("valid") + void createReturnsNonNullObject() { + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + VALID_INVOCATION_ID, mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context, "The create method must not return null"); + } + + // ===== Scenario 12: Create InvocationContext Verifies UserContent Is Wrapped In + // Optional ===== + @Test + @Tag("valid") + void createUserContentIsWrappedInOptional() { + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + VALID_INVOCATION_ID, mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context.userContent()); + assertTrue(context.userContent() instanceof Optional); + assertTrue(context.userContent().isPresent()); + assertSame(mockUserContent, context.userContent().get()); + } + + // ===== Scenario 13: Create Two InvocationContexts Are Independent ===== + @Test + @Tag("valid") + void createTwoContextsAreIndependent() { + // Arrange + BaseSessionService anotherSessionService = mock(BaseSessionService.class); + String invocationId1 = "invocation-001"; + String invocationId2 = "invocation-002"; + // Act + InvocationContext context1 = InvocationContext.create(mockSessionService, mockArtifactService, invocationId1, + mockAgent, mockSession, mockUserContent, mockRunConfig); + InvocationContext context2 = InvocationContext.create(anotherSessionService, mockArtifactService, invocationId2, + mockAgent, mockSession, null, mockRunConfig); + // Assert + assertNotEquals(context1.invocationId(), context2.invocationId()); + assertNotEquals(context1.sessionService(), context2.sessionService()); + assertTrue(context1.userContent().isPresent()); + assertFalse(context2.userContent().isPresent()); + } + + // ===== Scenario 14: Create InvocationContext Has Default endInvocation False ===== + @Test + @Tag("valid") + void createDefaultEndInvocationIsFalse() { + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + VALID_INVOCATION_ID, mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertFalse(context.endInvocation(), "Default endInvocation should be false"); + } + + // ===== Scenario 15: Create InvocationContext Has Empty Branch By Default ===== + @Test + @Tag("valid") + void createDefaultBranchIsEmpty() { + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + VALID_INVOCATION_ID, mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context.branch()); + assertFalse(context.branch().isPresent(), "Default branch should be empty"); + } + + // ===== Scenario 16: Create InvocationContext Has Empty LiveRequestQueue By Default + // ===== + @Test + @Tag("valid") + void createDefaultLiveRequestQueueIsEmpty() { + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + VALID_INVOCATION_ID, mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context.liveRequestQueue()); + assertFalse(context.liveRequestQueue().isPresent(), "Default liveRequestQueue should be empty"); + } + + // ===== Scenario 17: Create InvocationContext Has Empty ActiveStreamingTools By + // Default ===== + @Test + @Tag("valid") + void createDefaultActiveStreamingToolsIsEmpty() { + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + VALID_INVOCATION_ID, mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context.activeStreamingTools()); + assertTrue(context.activeStreamingTools().isEmpty(), "Default activeStreamingTools should be empty"); + } + + // ===== Scenario 18: Create InvocationContext With Long InvocationId ===== + @Test + @Tag("boundary") + void createWithVeryLongInvocationId() { + // Arrange + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 1000; i++) { + sb.append("x"); + } + String longInvocationId = sb.toString(); + // Act + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, longInvocationId, + mockAgent, mockSession, mockUserContent, mockRunConfig); + // Assert + assertNotNull(context); + assertEquals(longInvocationId, context.invocationId()); + assertEquals(1000, context.invocationId().length()); + } + + // ===== Scenario 19: Create InvocationContext Invocation Id With Special Characters + // ===== + @Test + @Tag("boundary") + void createWithSpecialCharactersInInvocationId() { + // Arrange + String specialInvocationId = "e-" + java.util.UUID.randomUUID().toString(); + // Act + InvocationContext context = InvocationContext.create( + mockSessionService, + mockArtifactService, + specialInvocationId, + mockAgent, + mockSession, + mockUserContent, + mockRunConfig + ); + // Assert + assertNotNull(context); + assertEquals(specialInvocationId, context.invocationId()); + assertTrue(context.invocationId().startsWith("e-")); + } + +// ===== Scenario 20: Create Two Separate Calls Return Different Instances ===== +@Test + @Tag("valid") + void createReturnsDifferentInstancesOnMultipleCalls() { + // Act + InvocationContext context1 = InvocationContext.create( + mockSessionService, + mockArtifactService, + VALID_INVOCATION_ID, + mockAgent, + mockSession, \ No newline at end of file diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextEndInvocationTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextEndInvocationTest.java new file mode 100644 index 000000000..cb027e6d8 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextEndInvocationTest.java @@ -0,0 +1,593 @@ +/* + * 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=endInvocation_306878eff5 +ROOST_METHOD_SIG_HASH=endInvocation_b038f3ac95 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +"Scenario 1: Verify endInvocation Returns False When Built with endInvocation Set to False + +Details: + TestName: endInvocationReturnsFalseWhenSetToFalse + Description: Verifies that the endInvocation() method returns false when the InvocationContext + is constructed using the builder with endInvocation explicitly set to false. +Execution: + Arrange: Build an InvocationContext using the builder, providing all required fields + (sessionService, artifactService, memoryService, pluginManager, invocationId, + agent, session, userContent, runConfig) and setting endInvocation(false). + Act: Call endInvocation() on the constructed InvocationContext instance. + Assert: Assert that the return value of endInvocation() is false. +Validation: + The assertion confirms that when the builder explicitly sets endInvocation to false, + the getter correctly reflects that value. This is critical for ensuring the invocation + lifecycle is not prematurely terminated under normal operating conditions. + +*/ + +// ********RoostGPT******** + +```java +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.events.Event; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.*; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.InlineMe; +import com.google.genai.types.FunctionCall; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextEndInvocationTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private BaseAgent mockAgent; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext buildBaseContext(boolean endInvocation) { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .endInvocation(endInvocation) + .build(); + } + + @Test + @Tag("valid") + void endInvocationReturnsFalseWhenSetToFalse() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .endInvocation(false) + .build(); + // Act + boolean result = context.endInvocation(); + // Assert + assertFalse(result, "endInvocation() should return false when set to false in builder"); + } + + @Test + @Tag("valid") + void endInvocationReturnsTrueWhenSetToTrue() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .endInvocation(true) + .build(); + // Act + boolean result = context.endInvocation(); + // Assert + assertTrue(result, "endInvocation() should return true when set to true in builder"); + } + + @Test + @Tag("valid") + void endInvocationDefaultsToFalseWhenNotExplicitlySet() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .build(); + // Act + boolean result = context.endInvocation(); + // Assert + assertFalse(result, "endInvocation() should default to false when not explicitly set"); + } + + @Test + @Tag("valid") + void endInvocationReturnsFalseAfterSetEndInvocationCalledWithFalse() { + // Arrange + InvocationContext context = buildBaseContext(false); + // Act + context.setEndInvocation(false); + boolean result = context.endInvocation(); + // Assert + assertFalse(result, "endInvocation() should return false after setEndInvocation(false) is called"); + } + + @Test + @Tag("valid") + void endInvocationReturnsTrueAfterSetEndInvocationCalledWithTrue() { + // Arrange + InvocationContext context = buildBaseContext(false); + // Act + context.setEndInvocation(true); + boolean result = context.endInvocation(); + // Assert + assertTrue(result, "endInvocation() should return true after setEndInvocation(true) is called"); + } + + @Test + @Tag("valid") + void endInvocationReflectsUpdatedValueAfterMultipleSetCalls() { + // Arrange + InvocationContext context = buildBaseContext(false); + // Act & Assert - toggle between true and false + context.setEndInvocation(true); + assertTrue(context.endInvocation(), "endInvocation() should return true after first setEndInvocation(true)"); + context.setEndInvocation(false); + assertFalse(context.endInvocation(), "endInvocation() should return false after setEndInvocation(false)"); + context.setEndInvocation(true); + assertTrue(context.endInvocation(), "endInvocation() should return true after second setEndInvocation(true)"); + } + + @Test + @Tag("valid") + void endInvocationIsCopiedCorrectlyWhenContextIsCopied() { + // Arrange + InvocationContext original = buildBaseContext(true); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertTrue(copy.endInvocation(), "Copied context should preserve endInvocation=true from original"); + } + + @Test + @Tag("valid") + void endInvocationFalseIsCopiedCorrectlyWhenContextIsCopied() { + // Arrange + InvocationContext original = buildBaseContext(false); + // Act + InvocationContext copy = InvocationContext.copyOf(original); + // Assert + assertFalse(copy.endInvocation(), "Copied context should preserve endInvocation=false from original"); + } + + @Test + @Tag("valid") + void endInvocationOfCopyIsIndependentOfOriginal() { + // Arrange + InvocationContext original = buildBaseContext(false); + InvocationContext copy = InvocationContext.copyOf(original); + // Act - modify the copy's endInvocation + copy.setEndInvocation(true); + // Assert + assertFalse(original.endInvocation(), + "Original context's endInvocation should remain unaffected when copy is modified"); + assertTrue(copy.endInvocation(), "Copied context should reflect updated endInvocation=true"); + } + + @Test + @Tag("valid") + void endInvocationOfOriginalIsIndependentOfCopy() { + // Arrange + InvocationContext original = buildBaseContext(false); + InvocationContext copy = InvocationContext.copyOf(original); + // Act - modify the original's endInvocation + original.setEndInvocation(true); + // Assert + assertTrue(original.endInvocation(), "Original context's endInvocation should return true after being set"); + assertFalse(copy.endInvocation(), "Copied context's endInvocation should remain false"); + } + + @Test + @Tag("boundary") + void endInvocationInitiallyFalseBeforeAnyMutation() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("boundary-test-id") + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .build(); + // Act + boolean result = context.endInvocation(); + // Assert + assertFalse(result, "endInvocation() should be false initially before any mutation"); + } + + @Test + @Tag("boundary") + void endInvocationRemainsConsistentAfterRepeatedReads() { + // Arrange + InvocationContext context = buildBaseContext(true); + // Act & Assert - read multiple times to ensure consistency + for (int i = 0; i < 5; i++) { + assertTrue(context.endInvocation(), + "endInvocation() should consistently return true on repeated reads, iteration: " + i); + } + } + + @Test + @Tag("boundary") + void endInvocationFalseRemainsConsistentAfterRepeatedReads() { + // Arrange + InvocationContext context = buildBaseContext(false); + // Act & Assert - read multiple times to ensure consistency + for (int i = 0; i < 5; i++) { + assertFalse(context.endInvocation(), + "endInvocation() should consistently return false on repeated reads, iteration: " + i); + } + } + + @Test + @Tag("valid") + void endInvocationUsedInCreateFactoryMethodDefaultsToFalse() { + // Arrange + Content userContent = mock(Content.class); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "factory-invocation-id", mockAgent, mockSession, userContent, mockRunConfig); + // Act + boolean result = context.endInvocation(); + // Assert + assertFalse(result, "endInvocation() should default to false when created via create() factory method"); + } + + @Test + @Tag("valid") + void endInvocationFalseIncludedInEqualsComparison() { + // Arrange + InvocationContext context1 = buildBaseContext(false); + InvocationContext context2 = buildBaseContext(false); + // Act & Assert + assertEquals(context1, context2, + "Two InvocationContexts with same parameters and endInvocation=false should be equal"); + } + + @Test + @Tag("valid") + void endInvocationTrueIncludedInEqualsComparison() { + // Arrange + InvocationContext context1 = buildBaseContext(true); + InvocationContext context2 = buildBaseContext(true); + // Act & Assert + assertEquals(context1, context2, + "Two InvocationContexts with same parameters and endInvocation=true should be equal"); + } + + @Test + @Tag("valid") + void endInvocationDifferenceBreaksEquality() { + // Arrange + InvocationContext contextFalse = buildBaseContext(false); + InvocationContext contextTrue = buildBaseContext(true); + // Act & Assert + assertNotEquals(contextFalse, contextTrue, + "Two InvocationContexts differing only in endInvocation value should not be equal"); + } + + @Test + @Tag("valid") + void endInvocationDifferenceAffectsHashCode() { + // Arrange + InvocationContext contextFalse = buildBaseContext(false); + InvocationContext contextTrue = buildBaseContext(true); + // Act & Assert + assertNotEquals(contextFalse.hashCode(), contextTrue.hashCode(), + "Two InvocationContexts differing in endInvocation should (typically) have different hash codes"); + } + + @Test + @Tag("integration") + void endInvocationWorksCorrectlyWithAllFieldsProvided() { + // Arrange + Content userContent = mock(Content.class); + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .branch("test-branch") + .invocationId("full-context-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.of(userContent)) + .runConfig(mockRunConfig) + .endInvocation(false) + .build(); + // Act + boolean result = context.endInvocation(); + // Assert + assertFalse(result, "endInvocation() should return false even when all optional fields are provided"); + } + + @Test + @Tag("integration") + void endInvocationTrueWorksCorrectlyWithAllFieldsProvided() { + // Arrange + Content userContent = mock(Content.class); + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .branch("test-branch") + .invocationId("full-context-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.of(userContent)) + .runConfig(mockRunConfig) + .endInvocation(true) + .build(); + // Act + boolean result = context.endInvocation(); + // Assert + assertTrue(result, + "endInvocation() should return true when set to true even with all optional fields provided"); + } + + @ParameterizedTest + @Tag("valid") + @ValueSource(booleans = {true, false}) + void endInvocationReturnsSameValueAsSetInBuilder(boolean endInvocationValue) { + // Arrange + InvocationContext context = buildBaseContext(endInvocationValue); + // Act + boolean result = context.endInvocation(); + // Assert + assertEquals(endInvocationValue, result, + "endInvocation() should return the same value as was set in the builder"); + } + +@Test + @Tag("integration") + void endInvocationTransitionsFromFalseToTrueAndBackToFalse() { + // Arrange + InvocationContext context = buildBaseContext(false); + // Assert initial state + assertFalse(context.endInvocation(), "Initial endInvocation should be false"); + // Act - transition to true + context.setEndInvocation(true); + // Assert transitioned state + assertTrue(context.endInvocation(), "endInvocation should be true after setEndInvocation(true)"); + // Act - transition back to false + context.setEndInvocation(false); + // Assert final state + assertFalse(context.endInv \ No newline at end of file diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextEqualsTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextEqualsTest.java new file mode 100644 index 000000000..adbb5abce --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextEqualsTest.java @@ -0,0 +1,515 @@ +/* + * 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=equals_271e2b6b9b +ROOST_METHOD_SIG_HASH=equals_f2d574000d + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +"Scenario 1: Comparing Two Objects with Different endInvocation Flag Values + +Details: + TestName: equalsDifferentEndInvocationFlag + Description: Verifies that two InvocationContext instances with identical field values except for the + endInvocation boolean flag are not considered equal. This tests the primitive boolean + comparison within the equals method. +Execution: + Arrange: Create two InvocationContext instances with all identical fields, but set endInvocation=false + for the first and endInvocation=true for the second, using the same sessionService, + artifactService, memoryService, pluginManager, invocationId, agent, session, userContent, + and runConfig. + Act: Call context1.equals(context2) and context2.equals(context1). + Assert: Assert that both comparisons return false. +Validation: + This test confirms that the endInvocation boolean field is evaluated in the equality check. + Since it is the first field compared after the type check, a mismatch here should immediately + cause the method to return false. This is significant because the invocation termination state + is a critical part of the invocation lifecycle. + +*/ + +// ********RoostGPT******** + +```java +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.*; +import com.google.adk.events.Event; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.InlineMe; +import com.google.genai.types.FunctionCall; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextEqualsTest { + + @Mock + private BaseSessionService sessionService; + + @Mock + private BaseArtifactService artifactService; + + @Mock + private BaseMemoryService memoryService; + + @Mock + private PluginManager pluginManager; + + @Mock + private BaseAgent agent; + + @Mock + private Session session; + + @Mock + private Content userContent; + + @Mock + private RunConfig runConfig; + + @Mock + private ResumabilityConfig resumabilityConfig; + + private InvocationContext.Builder baseBuilder; + + @BeforeEach + void setUp() { + baseBuilder = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false); + } + + @Test + @Tag("valid") + void equalsReturnsTrueForSameInstance() { + InvocationContext context = baseBuilder.build(); + assertTrue(context.equals(context)); + } + + @Test + @Tag("valid") + void equalsReturnsTrueForTwoIdenticalInstances() { + InvocationContext context1 = baseBuilder.build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertTrue(context1.equals(context2)); + assertTrue(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForNull() { + InvocationContext context = baseBuilder.build(); + assertFalse(context.equals(null)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentObjectType() { + InvocationContext context = baseBuilder.build(); + assertFalse(context.equals("some string")); + assertFalse(context.equals(42)); + assertFalse(context.equals(new Object())); + } + + @Test + @Tag("invalid") + void equalsDifferentEndInvocationFlag() { + InvocationContext context1 = baseBuilder.endInvocation(false).build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(true) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentSessionService() { + InvocationContext context1 = baseBuilder.build(); + BaseSessionService differentSessionService = mock(BaseSessionService.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(differentSessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentArtifactService() { + InvocationContext context1 = baseBuilder.build(); + BaseArtifactService differentArtifactService = mock(BaseArtifactService.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(differentArtifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentMemoryService() { + InvocationContext context1 = baseBuilder.build(); + BaseMemoryService differentMemoryService = mock(BaseMemoryService.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(differentMemoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentPluginManager() { + InvocationContext context1 = baseBuilder.build(); + PluginManager differentPluginManager = mock(PluginManager.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(differentPluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentInvocationId() { + InvocationContext context1 = baseBuilder.invocationId("id-one").build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("id-two") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentAgent() { + InvocationContext context1 = baseBuilder.build(); + BaseAgent differentAgent = mock(BaseAgent.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(differentAgent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentSession() { + InvocationContext context1 = baseBuilder.build(); + Session differentSession = mock(Session.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(differentSession) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentUserContent() { + InvocationContext context1 = baseBuilder.build(); + Content differentUserContent = mock(Content.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(differentUserContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentRunConfig() { + InvocationContext context1 = baseBuilder.build(); + RunConfig differentRunConfig = mock(RunConfig.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(differentRunConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("invalid") + void equalsReturnsFalseForDifferentResumabilityConfig() { + InvocationContext context1 = baseBuilder.build(); + ResumabilityConfig differentResumabilityConfig = mock(ResumabilityConfig.class); + InvocationContext context2 = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(differentResumabilityConfig) + .endInvocation(false) + .build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + + @Test + @Tag("valid") + void equalsReturnsTrueWhenAllNullableFieldsAreNull() { + InvocationContext context1 = InvocationContext.builder() + .sessionService(null) + .artifactService(null) + .memoryService(null) + .pluginManager(null) + .invocationId(null) + .agent(null) + .session(null) + .userContent(Optional.empty()) + .runConfig(null) + .resumabilityConfig(null) + .endInvocation(false) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(null) + .artifactService(null) + .memoryService(null) + .pluginManager(null) + .invocationId(null) + .agent(null) + .session(null) + .userContent(Optional.empty()) + .runConfig(null) + .resumabilityConfig(null) + .endInvocation(false) + .build(); + assertTrue(context1.equals(context2)); + assertTrue(context2.equals(context1)); + } + + @Test + @Tag("boundary") + void equalsReturnsFalseWhenOneSessionServiceIsNullAndOtherIsNot() { + InvocationContext context1 = InvocationContext.builder() + .sessionService(null) + .artifactService(artifactService) + .memoryService(memoryService) + .pluginManager(pluginManager) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .userContent(Optional.of(userContent)) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + InvocationContext context2 = baseBuilder.build(); + assertFalse(context1.equals(context2)); + assertFalse(context2.equals(context1)); + } + +@Test + @Tag("boundary") + void equalsReturnsFalseWhenUserContentPresentVsEmpty() { + InvocationContext context1 = baseBuilder.userContent(Optional.of( \ No newline at end of file diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextHashCodeTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextHashCodeTest.java new file mode 100644 index 000000000..cca6657b2 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextHashCodeTest.java @@ -0,0 +1,482 @@ +/* + * 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=hashCode_c3a2d500cd +ROOST_METHOD_SIG_HASH=hashCode_5a2657087a + +Scenario 1: Hash Code Consistency for the Same Object + +Details: + TestName: hashCodeIsConsistentForSameObject + Description: Verifies that calling hashCode() multiple times on the same InvocationContext instance + returns the same value on every invocation, confirming the contract of consistent hashing. + +Execution: + Arrange: + - Create mock instances of BaseSessionService, BaseArtifactService, BaseMemoryService, PluginManager, + Session, RunConfig, and ResumabilityConfig using Mockito. + - Build an InvocationContext using InvocationContext.builder() with all mocked dependencies, + a specific invocationId (e.g., "inv-001"), a branch value, userContent as Optional.empty(), + and endInvocation set to false. + Act: + - Call context.hashCode() three separate times and store each result. + Assert: + - Assert that all three returned hash code values are equal to each other. + +Validation: + This confirms the immutability contract of hashCode(): for a given object whose state does not change, + the hash code must remain the same across multiple calls within the same execution. This is critical + for correct behavior when InvocationContext instances are stored in hash-based collections like + HashMap or HashSet. + +*/ + +// ********RoostGPT******** + +```java +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.*; +import com.google.adk.events.Event; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.InlineMe; +import com.google.genai.types.FunctionCall; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextHashCodeTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Content mockContent; + + private InvocationContext baseContext; + + @BeforeEach + void setUp() { + baseContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .branch("main-branch") + .endInvocation(false) + .resumabilityConfig(mockResumabilityConfig) + .build(); + } + + @Test + @Tag("valid") + void hashCodeIsConsistentForSameObject() { + int hashCode1 = baseContext.hashCode(); + int hashCode2 = baseContext.hashCode(); + int hashCode3 = baseContext.hashCode(); + assertEquals(hashCode1, hashCode2); + assertEquals(hashCode2, hashCode3); + assertEquals(hashCode1, hashCode3); + } + + @Test + @Tag("valid") + void hashCodeIsEqualForEqualObjects() { + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("inv-equal") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .branch("branch-equal") + .endInvocation(false) + .resumabilityConfig(mockResumabilityConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("inv-equal") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .branch("branch-equal") + .endInvocation(false) + .resumabilityConfig(mockResumabilityConfig) + .build(); + assertEquals(context1.hashCode(), context2.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenInvocationIdDiffers() { + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-AAA") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-BBB") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenSessionServiceDiffers() { + BaseSessionService anotherSessionService = mock(BaseSessionService.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(anotherSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenArtifactServiceDiffers() { + BaseArtifactService anotherArtifactService = mock(BaseArtifactService.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(anotherArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenMemoryServiceDiffers() { + BaseMemoryService anotherMemoryService = mock(BaseMemoryService.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(anotherMemoryService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenPluginManagerDiffers() { + PluginManager anotherPluginManager = mock(PluginManager.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .pluginManager(mockPluginManager) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .pluginManager(anotherPluginManager) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenAgentDiffers() { + BaseAgent anotherAgent = mock(BaseAgent.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(anotherAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenSessionDiffers() { + Session anotherSession = mock(Session.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(anotherSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenUserContentDiffers() { + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.of(mockContent)) + .runConfig(mockRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenRunConfigDiffers() { + RunConfig anotherRunConfig = mock(RunConfig.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(anotherRunConfig) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenEndInvocationDiffers() { + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .endInvocation(false) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .endInvocation(true) + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + + @Test + @Tag("valid") + void hashCodeDiffersWhenBranchDiffers() { + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .branch("branch-A") + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .branch("branch-B") + .build(); + assertNotEquals(contextA.hashCode(), contextB.hashCode()); + } + +@Test + @Tag("valid") + void hashCodeDiffersWhenResumabilityConfigDiffers() { + ResumabilityConfig anotherResumabilityConfig = mock(ResumabilityConfig.class); + InvocationContext contextA = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .resumabilityConfig(mockResumabilityConfig) + .build(); + InvocationContext contextB = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("inv-001") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .resumabilityConfig(anotherResumabilityConfig) + .build(); + assertNot \ No newline at end of file diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextIncrementLlmCallsCountTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextIncrementLlmCallsCountTest.java new file mode 100644 index 000000000..309535f97 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextIncrementLlmCallsCountTest.java @@ -0,0 +1,543 @@ +/* + * 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=incrementLlmCallsCount_728a2657e3 +ROOST_METHOD_SIG_HASH=incrementLlmCallsCount_ccbe51a785 + +Scenario 1: Successful LLM Call Increment When RunConfig Is Null + +Details: + TestName: incrementLlmCallsCountSucceedsWhenRunConfigIsNull + Description: Verifies that calling incrementLlmCallsCount() does not throw any exception + when the RunConfig is null, meaning no limit enforcement is applied. + +Execution: + Arrange: Build an InvocationContext using InvocationContext.builder() with all required + fields (sessionService, artifactService, session, agent) but pass null as the + runConfig (or rely on the fact that a null runConfig skips the limit check). + Specifically set runConfig to null via builder.runConfig(null). + Act: Call invocationContext.incrementLlmCallsCount(). + Assert: Assert that no LlmCallsLimitExceededException is thrown. + +Validation: + Confirms that when runConfig is null, the internal check + "if (runConfig != null && ...)" evaluates to false, and the method completes normally. + This is important to ensure backward compatibility when no RunConfig is provided. + + +--- + +Scenario 2: Successful LLM Call Increment When maxLlmCalls Is Zero (No Limit Set) + +Details: + TestName: incrementLlmCallsCountSucceedsWhenMaxLlmCallsIsZero + Description: Verifies that calling incrementLlmCallsCount() does not throw an exception + when RunConfig has maxLlmCalls set to 0, which means "unlimited" calls. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 0 (the default or explicitly set). + Build an InvocationContext using InvocationContext.builder() with the + constructed RunConfig. + Act: Call invocationContext.incrementLlmCallsCount() once. + Assert: Assert that no LlmCallsLimitExceededException is thrown. + +Validation: + Confirms that the condition "runConfig.maxLlmCalls() > 0" is false when maxLlmCalls is 0, + so the limit is never enforced. This represents the "unlimited" scenario in the application. + + +--- + +Scenario 3: Successful LLM Call Increment When Count Is Within the Defined Limit + +Details: + TestName: incrementLlmCallsCountSucceedsWhenWithinLimit + Description: Verifies that calling incrementLlmCallsCount() does not throw an exception + when the number of LLM calls made so far has not yet exceeded the configured + maximum. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 5. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Act: Call invocationContext.incrementLlmCallsCount() exactly 5 times. + Assert: Assert that no LlmCallsLimitExceededException is thrown during any of the 5 calls. + +Validation: + Confirms the boundary condition where numberOfLlmCalls equals maxLlmCalls. + The condition "numberOfLlmCalls > runConfig.maxLlmCalls()" is false when they are equal, + so the last allowed call must complete without an exception. + + +--- + +Scenario 4: LlmCallsLimitExceededException Thrown When Count Exceeds the Defined Limit + +Details: + TestName: incrementLlmCallsCountThrowsExceptionWhenLimitExceeded + Description: Verifies that calling incrementLlmCallsCount() throws + LlmCallsLimitExceededException when the number of LLM calls made exceeds + the configured maximum in RunConfig. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 3. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Call invocationContext.incrementLlmCallsCount() 3 times without exception. + Act: Call invocationContext.incrementLlmCallsCount() a 4th time (exceeding the limit). + Assert: Assert that LlmCallsLimitExceededException is thrown on the 4th call. + +Validation: + Confirms the core enforcement behavior: when numberOfLlmCalls (4) > maxLlmCalls (3), + the method must throw LlmCallsLimitExceededException. This is critical to prevent + runaway LLM usage that could incur unexpected costs. + + +--- + +Scenario 5: LlmCallsLimitExceededException Message Contains Correct Limit Value + +Details: + TestName: incrementLlmCallsCountExceptionMessageContainsMaxLlmCalls + Description: Verifies that the exception message thrown when the LLM call limit is exceeded + contains the configured maxLlmCalls value, so callers can identify the limit + that was breached. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 2. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Call invocationContext.incrementLlmCallsCount() twice (reaching the limit). + Act: Call invocationContext.incrementLlmCallsCount() a 3rd time and capture the + thrown LlmCallsLimitExceededException. + Assert: Assert that the exception message contains "2" (the maxLlmCalls value). + +Validation: + Confirms that the error message "Max number of llm calls limit of 2 exceeded" is produced + correctly. A descriptive error message aids in diagnosing issues in production and provides + meaningful feedback to the caller. + + +--- + +Scenario 6: Single LLM Call Succeeds When maxLlmCalls Is Exactly One + +Details: + TestName: incrementLlmCallsCountSucceedsWithExactlyOneCallWhenLimitIsOne + Description: Verifies that the first and only allowed LLM call does not throw an exception + when maxLlmCalls is set to 1. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 1. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Act: Call invocationContext.incrementLlmCallsCount() once. + Assert: Assert that no LlmCallsLimitExceededException is thrown. + +Validation: + Confirms the boundary condition at the lowest meaningful positive limit. + When numberOfLlmCalls (1) equals maxLlmCalls (1), the condition + "numberOfLlmCalls > maxLlmCalls" is false, so the call is allowed. + + +--- + +Scenario 7: Second LLM Call Throws Exception When maxLlmCalls Is One + +Details: + TestName: incrementLlmCallsCountThrowsExceptionOnSecondCallWhenLimitIsOne + Description: Verifies that the second LLM call throws LlmCallsLimitExceededException + when maxLlmCalls is configured to 1, since only one call is permitted. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 1. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Call invocationContext.incrementLlmCallsCount() once (allowed call). + Act: Call invocationContext.incrementLlmCallsCount() a second time. + Assert: Assert that LlmCallsLimitExceededException is thrown on the second call. + +Validation: + Validates the strict enforcement when maxLlmCalls = 1. This tests the smallest + non-trivial limit and ensures the counter increments correctly before the check. + + +--- + +Scenario 8: Successful LLM Calls When maxLlmCalls Is Negative (No Limit Enforced) + +Details: + TestName: incrementLlmCallsCountSucceedsWhenMaxLlmCallsIsNegative + Description: Verifies that calling incrementLlmCallsCount() multiple times does not throw + an exception when maxLlmCalls is configured to a negative value, since the + condition "maxLlmCalls() > 0" would be false. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls set to a negative value (e.g., -1). + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Act: Call invocationContext.incrementLlmCallsCount() multiple times (e.g., 10 times). + Assert: Assert that no LlmCallsLimitExceededException is thrown during any call. + +Validation: + Confirms that negative values for maxLlmCalls are treated as "no limit" due to the + guard condition "runConfig.maxLlmCalls() > 0". This prevents accidental enforcement + from misconfigured negative values. + + +--- + +Scenario 9: LLM Call Count Is Cumulative Across Multiple Increments Until Limit + +Details: + TestName: incrementLlmCallsCountIsCumulativeAcrossMultipleIncrements + Description: Verifies that the LLM call counter accumulates correctly across multiple + successive calls to incrementLlmCallsCount(), and that the exception is thrown + only when the cumulative count exceeds the configured limit. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 4. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Act: Call invocationContext.incrementLlmCallsCount() four times without exception, + then call it a fifth time. + Assert: Assert that no exception is thrown during the first 4 calls and + LlmCallsLimitExceededException is thrown on the 5th call. + +Validation: + Confirms that the internal numberOfLlmCalls counter is persistent across calls within + the same InvocationContext instance and enforces the limit correctly at the right boundary. + This validates the stateful nature of the InvocationCostManager. + + +--- + +Scenario 10: Consecutive Exception Thrown After Limit Is Exceeded + +Details: + TestName: incrementLlmCallsCountContinuesToThrowAfterLimitIsExceeded + Description: Verifies that once the LLM call limit is exceeded and an exception is thrown, + subsequent calls to incrementLlmCallsCount() also throw + LlmCallsLimitExceededException, ensuring the limit remains enforced. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 2. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Call invocationContext.incrementLlmCallsCount() twice (reaching the limit). + Act: Call invocationContext.incrementLlmCallsCount() a 3rd time (limit exceeded). + Call invocationContext.incrementLlmCallsCount() a 4th time. + Assert: Assert that LlmCallsLimitExceededException is thrown on both the 3rd and 4th calls. + +Validation: + Confirms that once the limit is exceeded, the enforcement is persistent and the counter + continues to increment past the limit. The condition remains true for all subsequent calls + since numberOfLlmCalls keeps growing beyond maxLlmCalls. + + +--- + +Scenario 11: InvocationContext Built With Default RunConfig Does Not Enforce LLM Limit + +Details: + TestName: incrementLlmCallsCountWithDefaultRunConfigDoesNotThrow + Description: Verifies that an InvocationContext built using only the builder's defaults + (which sets a default RunConfig with maxLlmCalls = 0) does not throw + LlmCallsLimitExceededException when incrementLlmCallsCount() is called + many times. + +Execution: + Arrange: Build an InvocationContext using InvocationContext.builder() without explicitly + setting a RunConfig (relying on the builder default of RunConfig.builder().build()). + Act: Call invocationContext.incrementLlmCallsCount() many times (e.g., 100 times). + Assert: Assert that no LlmCallsLimitExceededException is thrown at any point. + +Validation: + Confirms that the default configuration of an InvocationContext imposes no LLM call + limit. This is important for ensuring that agents work unrestricted unless a limit is + explicitly configured by the caller. + + +--- + +Scenario 12: InvocationContext With Large maxLlmCalls Limit Enforces at Correct Boundary + +Details: + TestName: incrementLlmCallsCountEnforcesLimitAtCorrectBoundaryForLargeLimit + Description: Verifies that when maxLlmCalls is set to a large value, the exception is thrown + only after the exact number of allowed calls has been exceeded. + +Execution: + Arrange: Build a RunConfig with maxLlmCalls = 1000. + Build an InvocationContext using InvocationContext.builder() with this RunConfig. + Act: Call invocationContext.incrementLlmCallsCount() exactly 1000 times (should succeed), + then call it one more time (the 1001st call). + Assert: Assert that no exception is thrown during the first 1000 calls and + LlmCallsLimitExceededException is thrown on the 1001st call. + +Validation: + Validates the precision of the counter and limit enforcement for larger configured limits. + Ensures the boundary condition (numberOfLlmCalls > maxLlmCalls) is correctly evaluated + at scale, avoiding off-by-one errors in the implementation. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +class InvocationContextIncrementLlmCallsCountTest { + + private BaseSessionService mockSessionService; + + private BaseArtifactService mockArtifactService; + + private BaseAgent mockAgent; + + private Session mockSession; + + @BeforeEach + void setUp() { + mockSessionService = mock(BaseSessionService.class); + mockArtifactService = mock(BaseArtifactService.class); + mockAgent = mock(BaseAgent.class); + mockSession = mock(Session.class); + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext buildContext(RunConfig runConfig) { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(runConfig) + .build(); + } + + @Test + @Tag("valid") + void incrementLlmCallsCountSucceedsWhenRunConfigIsNull() { + InvocationContext context = buildContext(null); + assertDoesNotThrow(() -> context.incrementLlmCallsCount(), "Should not throw when RunConfig is null"); + } + + @Test + @Tag("valid") + void incrementLlmCallsCountSucceedsWhenMaxLlmCallsIsZero() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(0).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> context.incrementLlmCallsCount(), + "Should not throw when maxLlmCalls is 0 (unlimited)"); + } + + @Test + @Tag("boundary") + void incrementLlmCallsCountSucceedsWhenWithinLimit() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(5).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> { + for (int i = 0; i < 5; i++) { + context.incrementLlmCallsCount(); + } + }, "Should not throw when calls are within the configured limit of 5"); + } + + @Test + @Tag("invalid") + void incrementLlmCallsCountThrowsExceptionWhenLimitExceeded() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(3).build(); + InvocationContext context = buildContext(runConfig); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the 4th call when limit is 3"); + } + + @Test + @Tag("invalid") + void incrementLlmCallsCountExceptionMessageContainsMaxLlmCalls() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(2).build(); + InvocationContext context = buildContext(runConfig); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + LlmCallsLimitExceededException exception = assertThrows(LlmCallsLimitExceededException.class, + () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the 3rd call when limit is 2"); + assertTrue(exception.getMessage().contains("2"), + "Exception message should contain the maxLlmCalls value '2'. Actual message: " + + exception.getMessage()); + } + + @Test + @Tag("boundary") + void incrementLlmCallsCountSucceedsWithExactlyOneCallWhenLimitIsOne() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(1).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> context.incrementLlmCallsCount(), + "Should not throw on the first call when maxLlmCalls is 1"); + } + + @Test + @Tag("boundary") + void incrementLlmCallsCountThrowsExceptionOnSecondCallWhenLimitIsOne() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(1).build(); + InvocationContext context = buildContext(runConfig); + context.incrementLlmCallsCount(); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the second call when maxLlmCalls is 1"); + } + + @Test + @Tag("valid") + void incrementLlmCallsCountSucceedsWhenMaxLlmCallsIsNegative() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(-1).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> { + for (int i = 0; i < 10; i++) { + context.incrementLlmCallsCount(); + } + }, "Should not throw when maxLlmCalls is negative (treated as no limit)"); + } + + @Test + @Tag("boundary") + void incrementLlmCallsCountIsCumulativeAcrossMultipleIncrements() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(4).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> { + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + }, "Should not throw for the first 4 calls when maxLlmCalls is 4"); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the 5th call when limit is 4"); + } + + @Test + @Tag("invalid") + void incrementLlmCallsCountContinuesToThrowAfterLimitIsExceeded() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(2).build(); + InvocationContext context = buildContext(runConfig); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the 3rd call when limit is 2"); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the 4th call as well"); + } + + @Test + @Tag("valid") + void incrementLlmCallsCountWithDefaultRunConfigDoesNotThrow() { + RunConfig defaultRunConfig = RunConfig.builder().build(); + InvocationContext context = buildContext(defaultRunConfig); + assertDoesNotThrow(() -> { + for (int i = 0; i < 100; i++) { + context.incrementLlmCallsCount(); + } + }, "Should not throw when using default RunConfig (maxLlmCalls defaults to 500 or 0, no limit enforced in test range)"); + } + + @Test + @Tag("boundary") + void incrementLlmCallsCountEnforcesLimitAtCorrectBoundaryForLargeLimit() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(1000).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> { + for (int i = 0; i < 1000; i++) { + context.incrementLlmCallsCount(); + } + }, "Should not throw for the first 1000 calls when maxLlmCalls is 1000"); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException on the 1001st call when limit is 1000"); + } + + @Test + @Tag("integration") + void incrementLlmCallsCountWithFullContextBuilderSucceedsAndThenThrows() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(3).build(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mock(BaseMemoryService.class)) + .pluginManager(mock(PluginManager.class)) + .invocationId(InvocationContext.newInvocationContextId()) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(runConfig) + .endInvocation(false) + .build(); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + assertThrows(LlmCallsLimitExceededException.class, () -> context.incrementLlmCallsCount(), + "Should throw LlmCallsLimitExceededException when limit is exceeded in fully built context"); + } + + @Test + @Tag("integration") + void incrementLlmCallsCountOnCopiedContextIsIndependentFromOriginal() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(3).build(); + InvocationContext original = buildContext(runConfig); + original.incrementLlmCallsCount(); + original.incrementLlmCallsCount(); + InvocationContext copied = InvocationContext.copyOf(original); + assertDoesNotThrow(() -> copied.incrementLlmCallsCount(), + "Copied context should have its own independent InvocationCostManager, so 1st call on copy should succeed"); + } + + @Test + @Tag("valid") + void incrementLlmCallsCountSingleCallSucceedsWithValidRunConfig() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(10).build(); + InvocationContext context = buildContext(runConfig); + assertDoesNotThrow(() -> context.incrementLlmCallsCount(), + "A single call should not throw when maxLlmCalls is 10"); + } + + @Test + @Tag("invalid") + void incrementLlmCallsCountThrowsCorrectExceptionType() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(1).build(); + InvocationContext context = buildContext(runConfig); + context.incrementLlmCallsCount(); + LlmCallsLimitExceededException exception = assertThrows(LlmCallsLimitExceededException.class, + () -> context.incrementLlmCallsCount(), "Should throw exactly LlmCallsLimitExceededException"); + assertTrue(exception instanceof LlmCallsLimitExceededException, + "Exception should be of type LlmCallsLimitExceededException"); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextInvocationIdTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextInvocationIdTest.java new file mode 100644 index 000000000..27a7deff6 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextInvocationIdTest.java @@ -0,0 +1,702 @@ +/* + * 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=invocationId_b0959abc16 +ROOST_METHOD_SIG_HASH=invocationId_6cd6fb05e4 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/CallbacksTest.java +Tests: + "@Test +public void testRun_withModelCallbacks_receivesCorrectContext() { + Content realContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(realContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeModelCallback((callbackContext, request) -> { + assertThat(callbackContext.invocationId()).isNotEmpty(); + assertThat(callbackContext.agentName()).isEqualTo("test agent"); + return Maybe.empty(); + }).afterModelCallback((callbackContext, response) -> { + assertThat(callbackContext.invocationId()).isNotEmpty(); + assertThat(callbackContext.agentName()).isEqualTo("test agent"); + assertThat(response.content()).hasValue(realContent); + return Maybe.empty(); + }).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + assertThat(events).hasSize(1); + assertThat(getOnlyElement(events).content()).hasValue(realContent); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/LlmAgentTest.java +Tests: + "@Test +public void testCanonicalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + "@Test +public void testCanonicalGlobalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider global instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalGlobalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InstructionTest.java +Tests: + "@Test +public void testCanonicalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).instruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + "@Test +public void testCanonicalGlobalInstruction_providerInstructionInjectsContext() { + String instruction = "Test provider global instruction for invocation: "; + LlmAgent agent = createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).globalInstruction(new Instruction.Provider(context -> Single.just(instruction + context.invocationId()))).build(); + ReadonlyContext invocationContext = new ReadonlyContext(createInvocationContext(agent)); + String canonicalInstruction = agent.canonicalGlobalInstruction(invocationContext).blockingGet().getKey(); + assertThat(canonicalInstruction).isEqualTo(instruction + invocationContext.invocationId()); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/SequentialAgentTest.java +Tests: + "@Test +public void runAsync_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runAsync(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +" + "@Test +public void runLive_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent_live"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgentLive").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runLive(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +"Scenario 1: Verify invocationId Returns the Exact Value Set via Builder + +Details: + TestName: invocationIdReturnsExactValueSetViaBuilder + Description: Verifies that the invocationId() method returns the exact string value that was explicitly set through the builder's invocationId() method. This confirms that the field is properly stored and retrieved without any transformation. + +Execution: + Arrange: Build an InvocationContext using the builder, providing a specific known invocationId string (e.g., "test-invocation-123") along with all other required fields (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on the constructed InvocationContext instance. + Assert: Assert that the returned value is equal to the exact string "test-invocation-123" that was passed to the builder. + +Validation: + The assertion confirms that the invocationId field is faithfully stored and returned by the getter without modification. This is critical because invocationId is used to correlate events, callbacks, and sub-agent executions back to a single invocation lifecycle. + + +Scenario 2: Verify invocationId Returns Auto-Generated Value When Not Explicitly Set + +Details: + TestName: invocationIdReturnsAutoGeneratedValueWhenNotExplicitlySet + Description: Verifies that when no invocationId is explicitly provided to the builder, the invocationId() method returns a non-null, non-empty auto-generated value that follows the expected "e-" prefix format produced by newInvocationContextId(). + +Execution: + Arrange: Build an InvocationContext using the builder without calling invocationId() on the builder — relying on the default value. Provide all other required fields (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on the constructed InvocationContext instance. + Assert: Assert that the returned value is not null, not empty, and starts with the prefix "e-". + +Validation: + The assertion confirms that the default invocationId generation mechanism (newInvocationContextId()) works correctly and produces a valid identifier. This is important to guarantee that every invocation has a unique identity even when the caller does not supply one. + + +Scenario 3: Verify invocationId Returns a Non-Null Value + +Details: + TestName: invocationIdReturnsNonNullValue + Description: Verifies that the invocationId() method never returns null when an invocationId has been explicitly set through the builder. + +Execution: + Arrange: Build an InvocationContext using the builder with a non-null invocationId string (e.g., "non-null-id-456"). Provide all other required fields (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on the constructed InvocationContext instance. + Assert: Assert that the returned value is not null. + +Validation: + The assertion ensures the getter does not introduce unexpected null returns. Since other parts of the system (such as callbacks and sub-agent propagation) rely on invocationId() to be a valid non-null string, this check is essential for downstream correctness. + + +Scenario 4: Verify invocationId Is Consistent Across Multiple Calls + +Details: + TestName: invocationIdIsConsistentAcrossMultipleCalls + Description: Verifies that calling invocationId() multiple times on the same InvocationContext instance always returns the same immutable value, confirming the field is final and does not change between calls. + +Execution: + Arrange: Build an InvocationContext using the builder with a specific invocationId string (e.g., "stable-invocation-id"). Provide all other required fields (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on the constructed InvocationContext instance three times and store each result. + Assert: Assert that all three returned values are equal to each other and equal to "stable-invocation-id". + +Validation: + The assertion confirms the immutability of the invocationId field. Because invocationId is declared as a private final String, it must be stable throughout the lifetime of the object. This stability is required so that the invocation ID remains consistent when used across multiple components, callbacks, and sub-agents. + + +Scenario 5: Verify invocationId Is Preserved by copyOf + +Details: + TestName: invocationIdIsPreservedByCopyOf + Description: Verifies that when InvocationContext.copyOf() is used to create a shallow copy of an existing context, the invocationId() of the copied context is equal to the original context's invocationId(). + +Execution: + Arrange: Build an InvocationContext using the builder with a specific invocationId string (e.g., "original-invocation-id"). Provide all other required fields. Then call InvocationContext.copyOf() with the original context. + Act: Call invocationId() on the copied InvocationContext instance. + Assert: Assert that the invocationId() of the copied context equals the invocationId() of the original context ("original-invocation-id"). + +Validation: + The assertion confirms that the copyOf operation correctly propagates the invocationId to the new context. This is significant because sub-agents and delegated executions that use copied contexts must share the same invocationId to maintain traceability within a single invocation lifecycle. + + +Scenario 6: Verify invocationId Returns a Non-Empty String + +Details: + TestName: invocationIdReturnsNonEmptyString + Description: Verifies that the invocationId() method returns a non-empty string when a valid non-empty invocationId is provided through the builder. + +Execution: + Arrange: Build an InvocationContext using the builder with a non-empty invocationId string (e.g., "valid-id-789"). Provide all other required fields (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on the constructed InvocationContext instance. + Assert: Assert that the returned string is not empty. + +Validation: + The assertion ensures that the stored invocationId is not inadvertently cleared or emptied during construction. An empty invocationId would break correlation logic in callbacks and agent propagation, making this a critical validation. + + +Scenario 7: Verify Two Distinct InvocationContext Instances Have Different Auto-Generated invocationIds + +Details: + TestName: twoDistinctContextsHaveDifferentAutoGeneratedInvocationIds + Description: Verifies that two InvocationContext instances built without an explicit invocationId each receive a different auto-generated invocationId, confirming the uniqueness guarantee of the default ID generation. + +Execution: + Arrange: Build two separate InvocationContext instances using the builder, neither of which has an explicitly set invocationId. Provide all other required fields to both builders (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on both instances and store the results. + Assert: Assert that the two invocationId values are not equal to each other. + +Validation: + The assertion confirms that the UUID-based generation in newInvocationContextId() produces unique values for different instances. Uniqueness is a foundational requirement for tracking and differentiating concurrent or sequential invocations in a multi-agent system. + + +Scenario 8: Verify invocationId Matches the Value Used in Auto-Generated Format + +Details: + TestName: invocationIdMatchesAutoGeneratedFormat + Description: Verifies that an auto-generated invocationId (when not explicitly set) matches the expected format produced by newInvocationContextId(), i.e., it starts with "e-" followed by a UUID string. + +Execution: + Arrange: Build an InvocationContext using the builder without calling invocationId() explicitly. Provide all other required fields (sessionService, artifactService, memoryService, pluginManager, agent, session, userContent, runConfig). + Act: Call invocationId() on the constructed InvocationContext instance. + Assert: Assert that the returned value starts with "e-" and has a total length consistent with the "e-" prefix plus a standard UUID string (e.g., length greater than 2). + +Validation: + The assertion confirms adherence to the naming convention enforced by newInvocationContextId(). This format is important because other parts of the system (such as sub-agent context propagation tests) expect invocationIds to conform to this pattern for identification and debugging purposes. + + +Scenario 9: Verify invocationId Is Independent of Other Field Mutations + +Details: + TestName: invocationIdRemainsUnchangedAfterAgentMutation + Description: Verifies that calling the mutable setter agent() on an InvocationContext does not affect the value returned by invocationId(), confirming that the final invocationId field is fully isolated from mutable state changes. + +Execution: + Arrange: Build an InvocationContext using the builder with a specific invocationId (e.g., "immutable-id-001") and a mock agent. Provide all other required fields. Create a second mock agent object. + Act: Call agent() on the context to replace the agent with the second mock agent. Then call invocationId() on the same context. + Assert: Assert that the value returned by invocationId() is still equal to "immutable-id-001". + +Validation: + The assertion confirms that mutating mutable fields (like agent) does not corrupt or change the invocationId field. Since invocationId is declared final, this test serves as a safeguard against accidental misuse or future refactoring that might inadvertently break field isolation. + + +Scenario 10: Verify invocationId With an Explicit UUID-Format String + +Details: + TestName: invocationIdWithExplicitUuidFormatString + Description: Verifies that the invocationId() method correctly stores and returns an explicitly provided UUID-format string (e.g., a value resembling "e-" followed by a UUID), just as it would be stored by the builder. + +Execution: + Arrange: Generate a UUID-format invocationId string using InvocationContext.newInvocationContextId() or by constructing a string in the format "e-" + UUID.randomUUID().toString(). Build an InvocationContext using the builder, passing this generated string as the invocationId. Provide all other required fields. + Act: Call invocationId() on the constructed InvocationContext instance. + Assert: Assert that the returned value equals the UUID-format string that was set. + +Validation: + The assertion ensures that the builder correctly stores and the getter correctly retrieves a UUID-format invocationId. This scenario mirrors real-world usage patterns where the caller may pre-generate an invocationId using the provided utility method before constructing the context. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import java.util.UUID; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextInvocationIdTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private BaseAgent mockAgent2; + + @Mock + private Session mockSession; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + @Mock + private Content mockContent; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext.Builder baseBuilder() { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockContent)) + .runConfig(mockRunConfig) + .resumabilityConfig(mockResumabilityConfig); + } + + @Test + @Tag("valid") + void invocationIdReturnsExactValueSetViaBuilder() { + String expectedId = "test-invocation-123"; + InvocationContext context = baseBuilder().invocationId(expectedId).build(); + String actualId = context.invocationId(); + assertEquals(expectedId, actualId); + } + + @Test + @Tag("valid") + void invocationIdReturnsAutoGeneratedValueWhenNotExplicitlySet() { + InvocationContext context = baseBuilder().build(); + String actualId = context.invocationId(); + assertNotNull(actualId); + assertFalse(actualId.isEmpty()); + assertTrue(actualId.startsWith("e-"), + "Auto-generated invocationId should start with 'e-' but was: " + actualId); + } + + @Test + @Tag("valid") + void invocationIdReturnsNonNullValue() { + String inputId = "non-null-id-456"; + InvocationContext context = baseBuilder().invocationId(inputId).build(); + String actualId = context.invocationId(); + assertNotNull(actualId); + } + + @Test + @Tag("valid") + void invocationIdIsConsistentAcrossMultipleCalls() { + String expectedId = "stable-invocation-id"; + InvocationContext context = baseBuilder().invocationId(expectedId).build(); + String firstCall = context.invocationId(); + String secondCall = context.invocationId(); + String thirdCall = context.invocationId(); + assertEquals(expectedId, firstCall); + assertEquals(expectedId, secondCall); + assertEquals(expectedId, thirdCall); + assertEquals(firstCall, secondCall); + assertEquals(secondCall, thirdCall); + } + + @Test + @Tag("integration") + void invocationIdIsPreservedByCopyOf() { + String expectedId = "original-invocation-id"; + InvocationContext originalContext = baseBuilder().invocationId(expectedId).build(); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertEquals(expectedId, copiedContext.invocationId()); + assertEquals(originalContext.invocationId(), copiedContext.invocationId()); + } + + @Test + @Tag("valid") + void invocationIdReturnsNonEmptyString() { + String inputId = "valid-id-789"; + InvocationContext context = baseBuilder().invocationId(inputId).build(); + String actualId = context.invocationId(); + assertNotNull(actualId); + assertFalse(actualId.isEmpty()); + } + + @Test + @Tag("valid") + void twoDistinctContextsHaveDifferentAutoGeneratedInvocationIds() { + InvocationContext context1 = baseBuilder().build(); + InvocationContext context2 = baseBuilder().build(); + String id1 = context1.invocationId(); + String id2 = context2.invocationId(); + assertNotNull(id1); + assertNotNull(id2); + assertNotEquals(id1, id2, + "Two independently created InvocationContext instances should have different invocationIds"); + } + + @Test + @Tag("valid") + void invocationIdMatchesAutoGeneratedFormat() { + InvocationContext context = baseBuilder().build(); + String actualId = context.invocationId(); + assertNotNull(actualId); + assertTrue(actualId.startsWith("e-"), + "Auto-generated invocationId should start with 'e-' but was: " + actualId); + assertTrue(actualId.length() > 2, + "Auto-generated invocationId should have content after 'e-' prefix, but was: " + actualId); + // "e-" prefix (2 chars) + UUID standard length (36 chars) = 38 chars total + assertEquals(38, actualId.length(), + "Auto-generated invocationId should be 38 characters (2 for 'e-' + 36 for UUID) but was: " + actualId); + } + + @Test + @Tag("valid") + void invocationIdRemainsUnchangedAfterAgentMutation() { + String expectedId = "immutable-id-001"; + InvocationContext context = baseBuilder().invocationId(expectedId).agent(mockAgent).build(); + context.agent(mockAgent2); + String actualId = context.invocationId(); + assertEquals(expectedId, actualId, "invocationId should remain unchanged after mutating the agent field"); + } + + @Test + @Tag("valid") + void invocationIdWithExplicitUuidFormatString() { + String generatedId = InvocationContext.newInvocationContextId(); + InvocationContext context = baseBuilder().invocationId(generatedId).build(); + String actualId = context.invocationId(); + assertEquals(generatedId, actualId); + assertNotNull(actualId); + assertTrue(actualId.startsWith("e-")); + } + + @Test + @Tag("valid") + void invocationIdWithCustomUuidFormatString() { + String customId = "e-" + UUID.randomUUID().toString(); + InvocationContext context = baseBuilder().invocationId(customId).build(); + String actualId = context.invocationId(); + assertEquals(customId, actualId); + assertTrue(actualId.startsWith("e-")); + assertEquals(38, actualId.length()); + } + + @Test + @Tag("boundary") + void invocationIdWithVeryLongString() { + String longId = "e-" + "a".repeat(1000); + InvocationContext context = baseBuilder().invocationId(longId).build(); + String actualId = context.invocationId(); + assertEquals(longId, actualId); + assertNotNull(actualId); + assertFalse(actualId.isEmpty()); + } + + @Test + @Tag("boundary") + void invocationIdWithSingleCharacterString() { + String singleCharId = "x"; + InvocationContext context = baseBuilder().invocationId(singleCharId).build(); + String actualId = context.invocationId(); + assertEquals(singleCharId, actualId); + assertNotNull(actualId); + assertFalse(actualId.isEmpty()); + } + + @Test + @Tag("boundary") + void invocationIdWithSpecialCharacters() { + String specialId = "e-special!@#$%^&*()-id_001"; + InvocationContext context = baseBuilder().invocationId(specialId).build(); + String actualId = context.invocationId(); + assertEquals(specialId, actualId); + assertNotNull(actualId); + } + + @Test + @Tag("integration") + void invocationIdRemainsUnchangedAfterBranchMutation() { + String expectedId = "branch-immutable-id"; + InvocationContext context = baseBuilder().invocationId(expectedId).build(); + context.branch("new-branch"); + String actualId = context.invocationId(); + assertEquals(expectedId, actualId, "invocationId should remain unchanged after mutating the branch field"); + } + + @Test + @Tag("integration") + void invocationIdRemainsUnchangedAfterEndInvocationMutation() { + String expectedId = "end-invocation-immutable-id"; + InvocationContext context = baseBuilder().invocationId(expectedId).build(); + context.setEndInvocation(true); + String actualId = context.invocationId(); + assertEquals(expectedId, actualId, "invocationId should remain unchanged after setting endInvocation to true"); + } + + @Test + @Tag("valid") + void newInvocationContextIdGeneratesUniqueIds() { + String id1 = InvocationContext.newInvocationContextId(); + String id2 = InvocationContext.newInvocationContextId(); + String id3 = InvocationContext.newInvocationContextId(); + assertNotNull(id1); + assertNotNull(id2); + assertNotNull(id3); + assertNotEquals(id1, id2); + assertNotEquals(id2, id3); + assertNotEquals(id1, id3); + assertTrue(id1.startsWith("e-")); + assertTrue(id2.startsWith("e-")); + assertTrue(id3.startsWith("e-")); + } + + @Test + @Tag("integration") + void invocationIdIsConsistentBetweenOriginalAndCopiedContext() { + String expectedId = "copy-consistency-id"; + InvocationContext original = baseBuilder().invocationId(expectedId).build(); + InvocationContext copy = InvocationContext.copyOf(original); + String originalId = original.invocationId(); + String copiedId = copy.invocationId(); + assertEquals(originalId, copiedId); + assertEquals(expectedId, originalId); + assertEquals(expectedId, copiedId); + } + + @Test + @Tag("valid") + void invocationIdFromCreateFactoryMethodWithExplicitId() { + String expectedId = "factory-create-id"; + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, expectedId, + mockAgent, mockSession, mockContent, mockRunConfig); + String actualId = context.invocationId(); + assertEquals(expectedId, actualId); + assertNotNull(actualId); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextIsResumableTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextIsResumableTest.java new file mode 100644 index 000000000..aba395b8f --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextIsResumableTest.java @@ -0,0 +1,439 @@ +/* + * 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=isResumable_2397941e46 +ROOST_METHOD_SIG_HASH=isResumable_6fb85ad5c9 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +"Scenario 1: Verify isResumable Returns True When ResumabilityConfig Is Explicitly Set to True + +Details: + TestName: isResumable_whenResumabilityConfigExplicitlySetToTrue_returnsTrue + Description: Verifies that the isResumable() method returns true when the InvocationContext is built + with a ResumabilityConfig explicitly initialized with true. This ensures that the delegation + from InvocationContext.isResumable() to ResumabilityConfig.isResumable() works correctly + for the positive resumable case. +Execution: + Arrange: Create an InvocationContext using the builder, supplying all required fields (sessionService, + artifactService, memoryService, agent, session) and setting resumabilityConfig to + new ResumabilityConfig(true). + Act: Call context.isResumable() on the constructed InvocationContext instance. + Assert: Assert that the returned boolean value is true. +Validation: + This assertion confirms that when ResumabilityConfig is set to resumable, the InvocationContext + correctly propagates this state through its isResumable() method. This is critical for the flow + engine to determine whether an invocation can be paused and later resumed (e.g., during long-running + tool executions). + +--- + +Scenario 2: Verify isResumable Returns False When ResumabilityConfig Is Explicitly Set to False + +Details: + TestName: isResumable_whenResumabilityConfigExplicitlySetToFalse_returnsFalse + Description: Verifies that the isResumable() method returns false when the InvocationContext is built + with a ResumabilityConfig explicitly initialized with false. This confirms correct + delegation for the non-resumable case. +Execution: + Arrange: Create an InvocationContext using the builder, supplying all required fields and setting + resumabilityConfig to new ResumabilityConfig(false). + Act: Call context.isResumable() on the constructed InvocationContext instance. + Assert: Assert that the returned boolean value is false. +Validation: + This assertion verifies that the InvocationContext faithfully reflects a non-resumable configuration. + When resumability is disabled, the flow engine should not attempt to pause and resume the invocation, + making this a critical correctness check for the shouldPauseInvocation logic which depends on isResumable(). + +--- + +Scenario 3: Verify isResumable Returns the Default Value When No ResumabilityConfig Is Provided + +Details: + TestName: isResumable_whenResumabilityConfigIsDefault_returnsDefaultResumabilityValue + Description: Verifies that the isResumable() method returns the default value determined by the + default ResumabilityConfig when the builder is used without explicitly setting a + resumabilityConfig. The builder defaults resumabilityConfig to new ResumabilityConfig(), + so the test checks that isResumable() matches what a default ResumabilityConfig provides. +Execution: + Arrange: Create an InvocationContext using the builder, supplying all required fields (sessionService, + artifactService, memoryService, agent, session) but NOT calling .resumabilityConfig(...), + allowing the builder's default (new ResumabilityConfig()) to be used. Also create a + standalone ResumabilityConfig defaultConfig = new ResumabilityConfig() to determine the + expected value via defaultConfig.isResumable(). + Act: Call context.isResumable() on the constructed InvocationContext instance. + Assert: Assert that context.isResumable() equals defaultConfig.isResumable(). +Validation: + This test ensures that when no explicit resumability configuration is provided, the InvocationContext + behaves consistently with the default ResumabilityConfig. This guards against regressions if the + default value of ResumabilityConfig changes, as the InvocationContext should always reflect whatever + the default configuration dictates. + +--- + +Scenario 4: Verify isResumable Consistency After Copying InvocationContext with Resumable Config + +Details: + TestName: isResumable_whenInvocationContextCopiedWithResumableConfig_returnsTrueOnCopy + Description: Verifies that when an InvocationContext with a resumable ResumabilityConfig is copied + using InvocationContext.copyOf(), the resulting copy also returns true for isResumable(). + This tests that the copyOf() method correctly preserves the resumabilityConfig field. +Execution: + Arrange: Create an original InvocationContext using the builder with resumabilityConfig set to + new ResumabilityConfig(true) along with all required fields. Then create a copy using + InvocationContext.copyOf(original). + Act: Call copiedContext.isResumable() on the copied InvocationContext instance. + Assert: Assert that the returned boolean value is true. +Validation: + This assertion verifies that InvocationContext.copyOf() faithfully copies the resumabilityConfig, + ensuring that copied contexts used in sub-agent delegations or flow branching maintain the same + resumability state as the original context. Inconsistency here could cause unexpected behavior + in multi-agent orchestration scenarios. + +--- + +Scenario 5: Verify isResumable Consistency After Copying InvocationContext with Non-Resumable Config + +Details: + TestName: isResumable_whenInvocationContextCopiedWithNonResumableConfig_returnsFalseOnCopy + Description: Verifies that when an InvocationContext with a non-resumable ResumabilityConfig is + copied using InvocationContext.copyOf(), the resulting copy also returns false for + isResumable(). This tests that copyOf() does not inadvertently change the resumability + state. +Execution: + Arrange: Create an original InvocationContext using the builder with resumabilityConfig set to + new ResumabilityConfig(false) along with all required fields. Then create a copy using + InvocationContext.copyOf(original). + Act: Call copiedContext.isResumable() on the copied InvocationContext instance. + Assert: Assert that the returned boolean value is false. +Validation: + This assertion confirms that copying a non-resumable InvocationContext does not accidentally enable + resumability on the copy. This is important for preserving consistent behavior across all copies of + the context, particularly when the agent delegates to sub-agents while maintaining a non-resumable + configuration. + +--- + +Scenario 6: Verify isResumable Is Independent of Other InvocationContext Fields + +Details: + TestName: isResumable_whenOtherFieldsVaryButResumabilityConfigIsTrue_alwaysReturnsTrue + Description: Verifies that the return value of isResumable() depends solely on the ResumabilityConfig + and is not affected by other fields of InvocationContext such as endInvocation, branch, + or userContent. +Execution: + Arrange: Create two InvocationContext instances using the builder, both with resumabilityConfig set + to new ResumabilityConfig(true), but differing in other fields: the first with + endInvocation(false) and no branch set, the second with endInvocation(true) and a + branch("some-branch") set. Both use the same required services, agent, and session. + Act: Call isResumable() on both instances. + Assert: Assert that both instances return true for isResumable(). +Validation: + This test confirms that isResumable() is a pure function of the ResumabilityConfig field and is + not influenced by the state of other fields. This verifies the separation of concerns in the + InvocationContext design and ensures predictable behavior of the resumability feature regardless + of the overall invocation state. + +--- + +Scenario 7: Verify isResumable Returns False When Other Context Fields Are Set and ResumabilityConfig Is False + +Details: + TestName: isResumable_whenEndInvocationTrueAndResumabilityConfigFalse_returnsFalse + Description: Verifies that even when endInvocation is set to true and other fields are populated, + isResumable() still returns false when ResumabilityConfig is set to false. This ensures + the method's return value is not coupled to the endInvocation flag. +Execution: + Arrange: Create an InvocationContext using the builder with all required fields, setting + endInvocation(true), branch("test-branch"), and resumabilityConfig to + new ResumabilityConfig(false). + Act: Call context.isResumable() on the constructed InvocationContext instance. + Assert: Assert that the returned boolean value is false. +Validation: + This test validates that the isResumable() method exclusively delegates to ResumabilityConfig + and is not inadvertently affected by the endInvocation state or branch fields. This is important + because endInvocation and resumability are orthogonal concepts — an invocation that has ended + is distinct from one that is non-resumable. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class InvocationContextIsResumableTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext.Builder baseBuilder() { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .userContent(Optional.empty()) + .runConfig(RunConfig.builder().build()); + } + + @Test + @Tag("valid") + void isResumable_whenResumabilityConfigExplicitlySetToTrue_returnsTrue() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(true); + InvocationContext context = baseBuilder().resumabilityConfig(resumabilityConfig).build(); + // Act + boolean result = context.isResumable(); + // Assert + assertTrue(result, "isResumable() should return true when ResumabilityConfig is set to true"); + } + + @Test + @Tag("valid") + void isResumable_whenResumabilityConfigExplicitlySetToFalse_returnsFalse() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(false); + InvocationContext context = baseBuilder().resumabilityConfig(resumabilityConfig).build(); + // Act + boolean result = context.isResumable(); + // Assert + assertFalse(result, "isResumable() should return false when ResumabilityConfig is set to false"); + } + + @Test + @Tag("boundary") + void isResumable_whenResumabilityConfigIsDefault_returnsDefaultResumabilityValue() { + // Arrange + ResumabilityConfig defaultConfig = new ResumabilityConfig(); + InvocationContext context = baseBuilder().resumabilityConfig(defaultConfig).build(); + // Act + boolean result = context.isResumable(); + // Assert + assertEquals(defaultConfig.isResumable(), result, + "isResumable() should match the default ResumabilityConfig's isResumable() value"); + } + + @Test + @Tag("integration") + void isResumable_whenInvocationContextCopiedWithResumableConfig_returnsTrueOnCopy() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(true); + InvocationContext original = baseBuilder().resumabilityConfig(resumabilityConfig).build(); + InvocationContext copiedContext = InvocationContext.copyOf(original); + // Act + boolean result = copiedContext.isResumable(); + // Assert + assertTrue(result, + "isResumable() should return true on copied InvocationContext when original had ResumabilityConfig(true)"); + } + + @Test + @Tag("integration") + void isResumable_whenInvocationContextCopiedWithNonResumableConfig_returnsFalseOnCopy() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(false); + InvocationContext original = baseBuilder().resumabilityConfig(resumabilityConfig).build(); + InvocationContext copiedContext = InvocationContext.copyOf(original); + // Act + boolean result = copiedContext.isResumable(); + // Assert + assertFalse(result, + "isResumable() should return false on copied InvocationContext when original had ResumabilityConfig(false)"); + } + + @Test + @Tag("valid") + void isResumable_whenOtherFieldsVaryButResumabilityConfigIsTrue_alwaysReturnsTrue() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(true); + InvocationContext contextWithDefaultFields = baseBuilder().resumabilityConfig(resumabilityConfig) + .endInvocation(false) + .build(); + InvocationContext contextWithVariedFields = baseBuilder().resumabilityConfig(resumabilityConfig) + .endInvocation(true) + .branch("some-branch") + .build(); + // Act + boolean resultDefault = contextWithDefaultFields.isResumable(); + boolean resultVaried = contextWithVariedFields.isResumable(); + // Assert + assertTrue(resultDefault, "isResumable() should return true regardless of endInvocation=false and no branch"); + assertTrue(resultVaried, "isResumable() should return true regardless of endInvocation=true and branch set"); + } + + @Test + @Tag("invalid") + void isResumable_whenEndInvocationTrueAndResumabilityConfigFalse_returnsFalse() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(false); + InvocationContext context = baseBuilder().resumabilityConfig(resumabilityConfig) + .endInvocation(true) + .branch("test-branch") + .build(); + // Act + boolean result = context.isResumable(); + // Assert + assertFalse(result, + "isResumable() should return false even when endInvocation=true and branch is set, if ResumabilityConfig is false"); + } + + @Test + @Tag("valid") + void isResumable_whenResumabilityConfigTrueAndCopyPreservesResumability_bothOriginalAndCopyReturnTrue() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(true); + InvocationContext original = baseBuilder().resumabilityConfig(resumabilityConfig).build(); + InvocationContext copy = InvocationContext.copyOf(original); + // Act + boolean originalResult = original.isResumable(); + boolean copyResult = copy.isResumable(); + // Assert + assertTrue(originalResult, "Original context isResumable() should return true"); + assertTrue(copyResult, "Copied context isResumable() should also return true"); + assertEquals(originalResult, copyResult, + "Original and copied context should have the same isResumable() value"); + } + + @Test + @Tag("valid") + void isResumable_whenResumabilityConfigFalseAndCopyPreservesNonResumability_bothOriginalAndCopyReturnFalse() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(false); + InvocationContext original = baseBuilder().resumabilityConfig(resumabilityConfig).build(); + InvocationContext copy = InvocationContext.copyOf(original); + // Act + boolean originalResult = original.isResumable(); + boolean copyResult = copy.isResumable(); + // Assert + assertFalse(originalResult, "Original context isResumable() should return false"); + assertFalse(copyResult, "Copied context isResumable() should also return false"); + assertEquals(originalResult, copyResult, + "Original and copied context should have the same isResumable() value"); + } + + @Test + @Tag("boundary") + void isResumable_whenMultipleContextsWithDifferentResumabilityConfigs_returnCorrectValues() { + // Arrange + ResumabilityConfig trueConfig = new ResumabilityConfig(true); + ResumabilityConfig falseConfig = new ResumabilityConfig(false); + InvocationContext resumableContext = baseBuilder().resumabilityConfig(trueConfig).build(); + InvocationContext nonResumableContext = baseBuilder().resumabilityConfig(falseConfig).build(); + // Act + boolean resumableResult = resumableContext.isResumable(); + boolean nonResumableResult = nonResumableContext.isResumable(); + // Assert + assertTrue(resumableResult, "Context with ResumabilityConfig(true) should return true"); + assertFalse(nonResumableResult, "Context with ResumabilityConfig(false) should return false"); + } + + @Test + @Tag("valid") + void isResumable_whenResumabilityConfigTrueWithMemoryServiceAndPluginManager_returnsTrue() { + // Arrange + ResumabilityConfig resumabilityConfig = new ResumabilityConfig(true); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-with-memory") + .userContent(Optional.empty()) + .runConfig(RunConfig.builder().build()) + .resumabilityConfig(resumabilityConfig) + .build(); + // Act + boolean result = context.isResumable(); + // Assert + assertTrue(result, "isResumable() should return true with all services set and ResumabilityConfig(true)"); + } + + @Test + @Tag("boundary") + void isResumable_whenDefaultResumabilityConfigMatchesExpectedDefault() { + // Arrange + ResumabilityConfig defaultConfig1 = new ResumabilityConfig(); + ResumabilityConfig defaultConfig2 = new ResumabilityConfig(); + InvocationContext context1 = baseBuilder().resumabilityConfig(defaultConfig1).build(); + InvocationContext context2 = baseBuilder().resumabilityConfig(defaultConfig2).build(); + // Act + boolean result1 = context1.isResumable(); + boolean result2 = context2.isResumable(); + // Assert + assertEquals(result1, result2, + "Two contexts with default ResumabilityConfig should return the same isResumable() value"); + assertEquals(defaultConfig1.isResumable(), result1, + "Context isResumable() should match standalone default ResumabilityConfig.isResumable()"); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextLiveRequestQueueTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextLiveRequestQueueTest.java new file mode 100644 index 000000000..f2dfac131 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextLiveRequestQueueTest.java @@ -0,0 +1,477 @@ +/* + * 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=liveRequestQueue_752dd14d55 +ROOST_METHOD_SIG_HASH=liveRequestQueue_66d4c7a2b5 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +"Scenario 1: Verify liveRequestQueue Returns Empty Optional When Not Set During Build + +Details: + TestName: liveRequestQueueReturnsEmptyOptionalWhenNotProvided + Description: Verifies that when an InvocationContext is built without explicitly setting + a liveRequestQueue, the liveRequestQueue() method returns an empty Optional. + This tests the default behavior of the builder where liveRequestQueue defaults + to Optional.empty(). +Execution: + Arrange: Build an InvocationContext using the builder without calling liveRequestQueue(), + providing all other required fields (sessionService, artifactService, memoryService, + pluginManager, invocationId, agent, session, userContent, runConfig, endInvocation). + Act: Call liveRequestQueue() on the constructed InvocationContext instance. + Assert: assertThat(context.liveRequestQueue()).isEmpty(); +Validation: + Confirms that the default value for liveRequestQueue in the builder is Optional.empty(), + and the getter faithfully returns the internally stored Optional without modification. + This is critical for ensuring that non-live invocations do not incorrectly carry a + live request queue reference. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextLiveRequestQueueTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @Mock + private Content mockContent; + + @Mock + private RunConfig mockRunConfig; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + private static final String TEST_INVOCATION_ID = "e-test-invocation-id-123"; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + @Test + @Tag("valid") + void liveRequestQueueReturnsEmptyOptionalWhenNotProvided() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockContent)) + .runConfig(mockRunConfig) + .endInvocation(false) + .build(); + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("valid") + void liveRequestQueueReturnsQueueWhenSetViaOptional() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .runConfig(mockRunConfig) + .build(); + assertThat(context.liveRequestQueue()).isPresent(); + assertThat(context.liveRequestQueue().get()).isEqualTo(liveRequestQueue); + } + + @Test + @Tag("valid") + void liveRequestQueueReturnsQueueWhenSetDirectly() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(liveRequestQueue) + .runConfig(mockRunConfig) + .build(); + assertThat(context.liveRequestQueue()).isPresent(); + assertThat(context.liveRequestQueue().get()).isEqualTo(liveRequestQueue); + } + + @Test + @Tag("valid") + void liveRequestQueueReturnsEmptyOptionalWhenSetToEmptyOptional() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("valid") + void liveRequestQueuePreservedInCopyOf() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .runConfig(mockRunConfig) + .build(); + InvocationContext copy = InvocationContext.copyOf(original); + assertThat(copy.liveRequestQueue()).isPresent(); + assertThat(copy.liveRequestQueue().get()).isEqualTo(liveRequestQueue); + } + + @Test + @Tag("valid") + void liveRequestQueueEmptyPreservedInCopyOf() { + InvocationContext original = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .build(); + InvocationContext copy = InvocationContext.copyOf(original); + assertThat(copy.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("valid") + void liveRequestQueueReturnedByCreateWithLiveRequestQueueFactory() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, mockRunConfig); + assertThat(context.liveRequestQueue()).isPresent(); + assertThat(context.liveRequestQueue().get()).isEqualTo(liveRequestQueue); + } + + @Test + @Tag("valid") + void liveRequestQueueEmptyWhenCreatedWithUserContentFactory() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + TEST_INVOCATION_ID, mockAgent, mockSession, mockContent, mockRunConfig); + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("boundary") + void liveRequestQueueReturnedIsNotNull() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .build(); + assertNotNull(context.liveRequestQueue()); + } + + @Test + @Tag("boundary") + void liveRequestQueueWithNullPassedToOptionalOfNullable() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.ofNullable(null)) + .runConfig(mockRunConfig) + .build(); + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("valid") + void liveRequestQueueIsSameInstanceAsProvided() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(liveRequestQueue) + .runConfig(mockRunConfig) + .build(); + assertThat(context.liveRequestQueue().isPresent()).isTrue(); + assertSame(liveRequestQueue, context.liveRequestQueue().get()); + } + + @Test + @Tag("valid") + void liveRequestQueueCalledMultipleTimesReturnsSameResult() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(liveRequestQueue) + .runConfig(mockRunConfig) + .build(); + Optional firstCall = context.liveRequestQueue(); + Optional secondCall = context.liveRequestQueue(); + assertThat(firstCall).isEqualTo(secondCall); + assertThat(firstCall.get()).isEqualTo(secondCall.get()); + } + + @Test + @Tag("integration") + void liveRequestQueueCanReceiveContentAfterRetrieval() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(liveRequestQueue) + .runConfig(mockRunConfig) + .build(); + Optional retrievedQueue = context.liveRequestQueue(); + assertThat(retrievedQueue).isPresent(); + LiveRequestQueue queue = retrievedQueue.get(); + assertNotNull(queue); + assertNotNull(queue.get()); + } + + @Test + @Tag("integration") + void liveRequestQueueInContextUsedInCreateFactoryMethod() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, mockRunConfig); + assertThat(context.liveRequestQueue()).isPresent(); + assertNotNull(context.liveRequestQueue().get()); + assertSame(liveRequestQueue, context.liveRequestQueue().get()); + } + + @Test + @Tag("valid") + void liveRequestQueueNotPresentInContextCreatedWithUserContentAndNullContent() { + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + TEST_INVOCATION_ID, mockAgent, mockSession, null, mockRunConfig); + assertThat(context.liveRequestQueue()).isEmpty(); + } + + @Test + @Tag("boundary") + void liveRequestQueueEqualsCheckBetweenContextsWithSameQueue() { + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .runConfig(mockRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .runConfig(mockRunConfig) + .build(); + assertThat(context1.liveRequestQueue()).isEqualTo(context2.liveRequestQueue()); + } + + @Test + @Tag("boundary") + void liveRequestQueueNotEqualBetweenContextsWithDifferentQueues() { + LiveRequestQueue liveRequestQueue1 = new LiveRequestQueue(); + LiveRequestQueue liveRequestQueue2 = new LiveRequestQueue(); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue1)) + .runConfig(mockRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue2)) + .runConfig(mockRunConfig) + .build(); + assertThat(context1.liveRequestQueue()).isNotEqualTo(context2.liveRequestQueue()); + } + + @Test + @Tag("valid") + void liveRequestQueueEmptyForContextCreatedWithOnlyMinimalFields() { + InvocationContext context = InvocationContext.builder().agent(mockAgent).session(mockSession).build(); + assertThat(context.liveRequestQueue()).isEmpty(); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextMemoryServiceTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextMemoryServiceTest.java new file mode 100644 index 000000000..1c26c520c --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextMemoryServiceTest.java @@ -0,0 +1,557 @@ +/* + * 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=memoryService_1115878a43 +ROOST_METHOD_SIG_HASH=memoryService_b8500b83f5 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +" + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/AgentWithMemoryTest.java +Tests: + "@Test +public void agentRemembersUserNameWithMemoryTool() throws Exception { + String userId = "test-user"; + String agentName = "test-agent"; + Part functionCall = Part.builder().functionCall(FunctionCall.builder().name("loadMemory").args(ImmutableMap.of("query", "what is my name?")).build()).build(); + TestLlm testLlm = new TestLlm(ImmutableList.of(LlmResponse.builder().content(Content.builder().parts(Part.fromText("OK, I'll remember that.")).role("model").build()).build(), LlmResponse.builder().content(Content.builder().role("model").parts(ImmutableList.of(functionCall)).build()).build(), LlmResponse.builder().content(Content.builder(). + + parts(Part.fromText("Your name is James.")).role("model").build()).build())); + LlmAgent agent = LlmAgent.builder().name(agentName).model(testLlm).tools(ImmutableList.of(new LoadMemoryTool())).build(); + InMemoryRunner runner = new InMemoryRunner(agent); + String sessionId = runner.sessionService().createSession(agentName, userId).blockingGet().id(); + Content firstMessage = Content.fromParts(Part.fromText("My name is James")); + var unused = runner.runAsync(userId, sessionId, firstMessage, RunConfig.builder().build()).toList().blockingGet(); + + Session updatedSession = runner.sessionService().getSession("test-agent", userId, sessionId, Optional.empty()).blockingGet(); + + runner.memoryService().addSessionToMemory(updatedSession).blockingAwait(); + Content secondMessage = Content.fromParts(Part.fromText("what is my name?")); + unused = runner.runAsync(userId, updatedSession.id(), secondMessage, RunConfig.builder().build()).toList().blockingGet(); + + LlmRequest lastRequest = testLlm.getLastRequest(); + Content functionResponseContent = Iterables.getLast(lastRequest.contents()); + Optional functionResponsePart = functionResponseContent.parts().get().stream().filter(p -> p.functionResponse().isPresent()).findFirst(); + assertThat(functionResponsePart).isPresent(); + FunctionResponse functionResponse = functionResponsePart.get().functionResponse().get(); + assertThat(functionResponse.name()).hasValue("loadMemory"); + assertThat(functionResponse.response().get().toString()).contains("My name is James"); +} +"Scenario 1: Verify That memoryService() Returns the Correct Memory Service Instance Set via Builder + +Details: + TestName: memoryServiceReturnsCorrectInstanceSetViaBuilder + Description: Verifies that the memoryService() method returns the exact same BaseMemoryService instance + that was provided to the builder during construction of InvocationContext. +Execution: + Arrange: Create a mock of BaseMemoryService. Build an InvocationContext using the builder, + providing the mocked BaseMemoryService via the .memoryService(...) builder method, + along with the other required fields (sessionService, artifactService, agent, session). + Act: Call context.memoryService() on the constructed InvocationContext instance. + Assert: Assert that the returned value is the same instance as the mocked BaseMemoryService + (assertThat(context.memoryService()).isEqualTo(mockMemoryService)). +Validation: + This assertion confirms that the memoryService field is correctly stored during construction + and accurately retrieved by the accessor method. It is critical for ensuring that the + InvocationContext correctly wires the memory layer, which is required for agents to access + past memory during invocations. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextMemoryServiceTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + private RunConfig defaultRunConfig; + + @BeforeEach + void setUp() { + defaultRunConfig = RunConfig.builder().build(); + } + + @Test + @Tag("valid") + void memoryServiceReturnsCorrectInstanceSetViaBuilder() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id") + .runConfig(defaultRunConfig) + .build(); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + } + + @Test + @Tag("valid") + void memoryServiceReturnsSameReferenceAsProvided() { + BaseMemoryService specificMemoryService = mock(BaseMemoryService.class); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(specificMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id-2") + .runConfig(defaultRunConfig) + .build(); + assertThat(context.memoryService()).isSameInstanceAs(specificMemoryService); + } + + @Test + @Tag("valid") + void memoryServiceReturnsNullWhenNotSetViaBuilder() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id-3") + .runConfig(defaultRunConfig) + .build(); + assertThat(context.memoryService()).isNull(); + } + + @Test + @Tag("valid") + void memoryServiceReturnedAfterCopyOf() { + InvocationContext originalContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id-4") + .runConfig(defaultRunConfig) + .build(); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext.memoryService()).isEqualTo(mockMemoryService); + assertThat(copiedContext.memoryService()).isSameInstanceAs(originalContext.memoryService()); + } + + @Test + @Tag("valid") + void memoryServiceIsIndependentBetweenTwoBuilderInstances() { + BaseMemoryService memoryService1 = mock(BaseMemoryService.class); + BaseMemoryService memoryService2 = mock(BaseMemoryService.class); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(memoryService1) + .agent(mockAgent) + .session(mockSession) + .invocationId("invocation-id-1") + .runConfig(defaultRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(memoryService2) + .agent(mockAgent) + .session(mockSession) + .invocationId("invocation-id-2") + .runConfig(defaultRunConfig) + .build(); + assertThat(context1.memoryService()).isEqualTo(memoryService1); + assertThat(context2.memoryService()).isEqualTo(memoryService2); + assertThat(context1.memoryService()).isNotSameInstanceAs(context2.memoryService()); + } + + @Test + @Tag("valid") + void memoryServiceNotNullWhenSet() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id-5") + .runConfig(defaultRunConfig) + .build(); + assertThat(context.memoryService()).isNotNull(); + } + + @Test + @Tag("valid") + void memoryServiceReturnedFromDeprecatedConstructor() { + InvocationContext context = new InvocationContext(mockSessionService, mockArtifactService, mockMemoryService, + mockPluginManager, Optional.empty(), Optional.empty(), "deprecated-invocation-id", mockAgent, + mockSession, Optional.empty(), defaultRunConfig, false); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + } + + @Test + @Tag("valid") + void memoryServiceReturnedFromDeprecatedConstructorWithoutPluginManager() { + InvocationContext context = new InvocationContext(mockSessionService, mockArtifactService, mockMemoryService, + Optional.empty(), Optional.empty(), "deprecated-invocation-id-2", mockAgent, mockSession, + Optional.empty(), defaultRunConfig, false); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + } + + @Test + @Tag("valid") + void memoryServiceConsistentAcrossMultipleCalls() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("test-invocation-id-6") + .runConfig(defaultRunConfig) + .build(); + BaseMemoryService firstCall = context.memoryService(); + BaseMemoryService secondCall = context.memoryService(); + BaseMemoryService thirdCall = context.memoryService(); + assertThat(firstCall).isSameInstanceAs(secondCall); + assertThat(secondCall).isSameInstanceAs(thirdCall); + } + + @Test + @Tag("integration") + void memoryServicePreservedAlongsideOtherFields() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .invocationId("integration-invocation-id") + .runConfig(defaultRunConfig) + .build(); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.pluginManager()).isEqualTo(mockPluginManager); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(mockSession); + assertThat(context.invocationId()).isEqualTo("integration-invocation-id"); + } + + @Test + @Tag("boundary") + void memoryServiceNullWhenExplicitlySetToNull() { + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(null) + .agent(mockAgent) + .session(mockSession) + .invocationId("null-memory-service-id") + .runConfig(defaultRunConfig) + .build(); + assertThat(context.memoryService()).isNull(); + } + + @Test + @Tag("boundary") + void memoryServiceNullPreservedInCopyOf() { + InvocationContext originalContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .invocationId("null-memory-copy-id") + .runConfig(defaultRunConfig) + .build(); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext.memoryService()).isNull(); + assertThat(originalContext.memoryService()).isNull(); + } + + @Test + @Tag("valid") + void memoryServiceEqualsReturnsTrueForSameMemoryService() { + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("equals-test-id") + .runConfig(defaultRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId("equals-test-id") + .runConfig(defaultRunConfig) + .build(); + assertThat(context1.memoryService()).isEqualTo(context2.memoryService()); + } + + @Test + @Tag("valid") + void memoryServiceNotEqualForDifferentInstances() { + BaseMemoryService memoryServiceA = mock(BaseMemoryService.class); + BaseMemoryService memoryServiceB = mock(BaseMemoryService.class); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(memoryServiceA) + .agent(mockAgent) + .session(mockSession) + .invocationId("not-equal-id-1") + .runConfig(defaultRunConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(memoryServiceB) + .agent(mockAgent) + .session(mockSession) + .invocationId("not-equal-id-2") + .runConfig(defaultRunConfig) + .build(); + assertThat(context1.memoryService()).isNotEqualTo(context2.memoryService()); + assertThat(context1.memoryService()).isNotSameInstanceAs(context2.memoryService()); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextNewInvocationContextIdTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextNewInvocationContextIdTest.java new file mode 100644 index 000000000..963098970 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextNewInvocationContextIdTest.java @@ -0,0 +1,269 @@ +/* + * 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=newInvocationContextId_87a927076b +ROOST_METHOD_SIG_HASH=newInvocationContextId_db44e2dbb1 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testNewInvocationContextId() { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).isNotNull(); + assertThat(id).isNotEmpty(); + assertThat(id).startsWith("e-"); + + assertThat(id.substring(2)).matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"); +} +"Scenario 1: Verify That Two Consecutive Invocation IDs Are Unique + +Details: + TestName: newInvocationContextIdGeneratesUniqueIdsOnConsecutiveCalls + Description: Verifies that calling newInvocationContextId() multiple times in sequence + produces different ID values each time, ensuring the UUID-based generation + provides proper uniqueness for each invocation context. +Execution: + Arrange: No special setup is required since newInvocationContextId() is a static method + with no dependencies or parameters. + Act: Call InvocationContext.newInvocationContextId() twice in succession, storing + each result in separate String variables (firstId and secondId). + Assert: Use assertThat(firstId).isNotEqualTo(secondId) to confirm the two IDs differ. +Validation: + This assertion confirms that the UUID.randomUUID() component ensures each call yields + a distinct identifier. In the context of the InvocationContext lifecycle, the invocationId + field must be unique per context instance, so repeated calls must never produce collisions + under normal operating conditions. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +class InvocationContextNewInvocationContextIdTest { + + private static final Pattern UUID_PATTERN = Pattern + .compile("^e-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); + + @Test + @Tag("valid") + void newInvocationContextIdGeneratesUniqueIdsOnConsecutiveCalls() { + String firstId = InvocationContext.newInvocationContextId(); + String secondId = InvocationContext.newInvocationContextId(); + assertThat(firstId).isNotEqualTo(secondId); + } + + @Test + @Tag("valid") + void newInvocationContextIdReturnsNonNullValue() { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).isNotNull(); + } + + @Test + @Tag("valid") + void newInvocationContextIdStartsWithExpectedPrefix() { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).startsWith("e-"); + } + + @Test + @Tag("valid") + void newInvocationContextIdMatchesExpectedFormat() { + String id = InvocationContext.newInvocationContextId(); + assertThat(UUID_PATTERN.matcher(id).matches()).isTrue(); + } + + @Test + @Tag("valid") + void newInvocationContextIdHasCorrectLength() { + String id = InvocationContext.newInvocationContextId(); + // "e-" (2 chars) + UUID (36 chars) = 38 chars + assertThat(id).hasLength(38); + } + + @Test + @Tag("valid") + void newInvocationContextIdContainsUuidAfterPrefix() { + String id = InvocationContext.newInvocationContextId(); + String uuidPart = id.substring(2); + assertThat(uuidPart).isNotEmpty(); + Pattern uuidOnlyPattern = Pattern + .compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); + assertThat(uuidOnlyPattern.matcher(uuidPart).matches()).isTrue(); + } + + @Test + @Tag("valid") + void newInvocationContextIdGeneratesUniqueIdsInLargeBatch() { + int batchSize = 1000; + Set ids = new HashSet<>(); + for (int i = 0; i < batchSize; i++) { + ids.add(InvocationContext.newInvocationContextId()); + } + assertThat(ids).hasSize(batchSize); + } + + @Test + @Tag("valid") + void newInvocationContextIdReturnsDifferentIdsOnThreeConsecutiveCalls() { + String firstId = InvocationContext.newInvocationContextId(); + String secondId = InvocationContext.newInvocationContextId(); + String thirdId = InvocationContext.newInvocationContextId(); + assertThat(firstId).isNotEqualTo(secondId); + assertThat(secondId).isNotEqualTo(thirdId); + assertThat(firstId).isNotEqualTo(thirdId); + } + + @Test + @Tag("valid") + void newInvocationContextIdPrefixIsExactlyEDash() { + String id = InvocationContext.newInvocationContextId(); + assertThat(id.substring(0, 2)).isEqualTo("e-"); + } + + @Test + @Tag("valid") + void newInvocationContextIdDoesNotReturnEmptyString() { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).isNotEmpty(); + } + + @Test + @Tag("valid") + void newInvocationContextIdUuidPartContainsFourHyphens() { + String id = InvocationContext.newInvocationContextId(); + String uuidPart = id.substring(2); + long hyphenCount = uuidPart.chars().filter(c -> c == '-').count(); + assertThat(hyphenCount).isEqualTo(4); + } + + @Test + @Tag("boundary") + void newInvocationContextIdNeverReturnsNullAcrossMultipleCalls() { + for (int i = 0; i < 100; i++) { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).isNotNull(); + } + } + + @Test + @Tag("boundary") + void newInvocationContextIdAlwaysStartsWithPrefixAcrossMultipleCalls() { + for (int i = 0; i < 100; i++) { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).startsWith("e-"); + } + } + + @Test + @Tag("boundary") + void newInvocationContextIdAlwaysHasCorrectLengthAcrossMultipleCalls() { + for (int i = 0; i < 100; i++) { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).hasLength(38); + } + } + + @Test + @Tag("boundary") + void newInvocationContextIdGeneratesUniqueIdsInSmallBatch() { + int batchSize = 10; + Set ids = new HashSet<>(); + for (int i = 0; i < batchSize; i++) { + ids.add(InvocationContext.newInvocationContextId()); + } + assertThat(ids).hasSize(batchSize); + } + + @Test + @Tag("integration") + void newInvocationContextIdCanBeUsedAsInvocationIdInBuilder() { + String generatedId = InvocationContext.newInvocationContextId(); + assertThat(generatedId).isNotNull(); + assertThat(UUID_PATTERN.matcher(generatedId).matches()).isTrue(); + assertThat(generatedId).startsWith("e-"); + } + + @Test + @Tag("integration") + void newInvocationContextIdIsThreadSafeAndProducesUniqueValuesFromMultipleThreads() throws InterruptedException { + int threadCount = 10; + int idsPerThread = 50; + Set allIds = java.util.Collections.synchronizedSet(new HashSet<>()); + Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = new Thread(() -> { + for (int j = 0; j < idsPerThread; j++) { + allIds.add(InvocationContext.newInvocationContextId()); + } + }); + } + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + thread.join(); + } + assertThat(allIds).hasSize(threadCount * idsPerThread); + } + + @Test + @Tag("valid") + void newInvocationContextIdUuidPartHasCorrectSegmentLengths() { + String id = InvocationContext.newInvocationContextId(); + String uuidPart = id.substring(2); + String[] segments = uuidPart.split("-"); + assertThat(segments).hasLength(5); + assertThat(segments[0]).hasLength(8); + assertThat(segments[1]).hasLength(4); + assertThat(segments[2]).hasLength(4); + assertThat(segments[3]).hasLength(4); + assertThat(segments[4]).hasLength(12); + } + + @Test + @Tag("valid") + void newInvocationContextIdUuidPartContainsOnlyHexCharactersAndHyphens() { + String id = InvocationContext.newInvocationContextId(); + String uuidPart = id.substring(2); + assertThat(uuidPart).matches("[0-9a-fA-F\\-]+"); + } + + @Test + @Tag("valid") + void newInvocationContextIdReturnValueIsImmutableString() { + String id = InvocationContext.newInvocationContextId(); + assertThat(id).isInstanceOf(String.class); + assertThat(id).isNotNull(); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextPluginManagerTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextPluginManagerTest.java new file mode 100644 index 000000000..f242e9feb --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextPluginManagerTest.java @@ -0,0 +1,738 @@ +/* + * 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=pluginManager_009a0b1a05 +ROOST_METHOD_SIG_HASH=pluginManager_3452d016c7 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +"Scenario 1: Verify pluginManager() Returns the Explicitly Set PluginManager Instance + +Details: + TestName: pluginManagerReturnsExplicitlySetInstance + Description: Verifies that the pluginManager() method returns the exact PluginManager instance + that was explicitly provided to the builder during construction of InvocationContext. +Execution: + Arrange: Create a specific PluginManager instance. Build an InvocationContext using the builder, + supplying the custom PluginManager via .pluginManager(pluginManager), along with other + required fields such as sessionService, artifactService, memoryService, invocationId, + agent, session, userContent, and runConfig. + Act: Invoke context.pluginManager() on the constructed InvocationContext. + Assert: Assert that the returned value is the same instance (using isSameInstanceAs or isEqualTo) + as the PluginManager provided during construction. +Validation: + This assertion verifies that the pluginManager() getter faithfully returns the field value + assigned during construction. It is fundamental to ensure that dependency injection through + the builder works correctly for the PluginManager, which is responsible for accessing tools + and plugins throughout the invocation lifecycle. + + +Scenario 2: Verify pluginManager() Returns the Default PluginManager When None Is Explicitly Set + +Details: + TestName: pluginManagerReturnsDefaultWhenNotExplicitlyProvided + Description: Verifies that when no PluginManager is explicitly set via the builder, the + pluginManager() method returns the default PluginManager instance initialized + inside the Builder (i.e., new PluginManager()). +Execution: + Arrange: Build an InvocationContext using the builder without calling .pluginManager(...), + supplying only the other required fields (sessionService, artifactService, + memoryService, invocationId, agent, session, userContent, runConfig). + Act: Invoke context.pluginManager() on the constructed InvocationContext. + Assert: Assert that the returned PluginManager is not null. +Validation: + This test confirms that the Builder provides a safe non-null default value for the + pluginManager field, preventing NullPointerExceptions during invocation processing even + when the caller does not explicitly configure a PluginManager. + + +Scenario 3: Verify pluginManager() Does Not Return Null When PluginManager Is Explicitly Set + +Details: + TestName: pluginManagerIsNotNullWhenExplicitlySet + Description: Verifies that the pluginManager() method never returns null when a valid, + non-null PluginManager is explicitly provided to the builder. +Execution: + Arrange: Instantiate a PluginManager object. Construct an InvocationContext via the builder, + passing the PluginManager instance explicitly through .pluginManager(pluginManager), + along with the remaining required fields. + Act: Invoke context.pluginManager() on the resulting InvocationContext. + Assert: Assert that the result of pluginManager() is not null (using isNotNull()). +Validation: + Ensures the getter does not inadvertently return null when a PluginManager has been correctly + configured, which is critical for any downstream component relying on the PluginManager + to register or invoke plugins and tools. + + +Scenario 4: Verify pluginManager() Returns the Same PluginManager After copyOf() + +Details: + TestName: pluginManagerReturnsSameInstanceAfterCopyOf + Description: Verifies that when an InvocationContext is copied using InvocationContext.copyOf(), + the pluginManager() method of the copied context returns the same PluginManager + instance as the original context (shallow copy behavior). +Execution: + Arrange: Create a PluginManager instance. Build an original InvocationContext using the builder + with the PluginManager and all required fields. Then create a copied context using + InvocationContext.copyOf(originalContext). + Act: Invoke pluginManager() on both the original and the copied InvocationContext. + Assert: Assert that copiedContext.pluginManager() is equal to (or the same instance as) + originalContext.pluginManager(). +Validation: + Since copyOf() performs a shallow copy, the pluginManager field reference should be shared + between the original and copied contexts. This test confirms that the copy operation preserves + the PluginManager reference correctly, which is important for scenarios where a sub-agent or + delegated invocation needs access to the same plugin infrastructure. + + +Scenario 5: Verify pluginManager() Returns Correct Instance When Multiple InvocationContexts Are Built With Different PluginManagers + +Details: + TestName: pluginManagerReturnsCorrectInstanceForEachContext + Description: Verifies that two separate InvocationContext instances, each built with a different + PluginManager, correctly return their respective PluginManager instances from + pluginManager(), without cross-contamination between instances. +Execution: + Arrange: Create two distinct PluginManager instances (pluginManager1 and pluginManager2). + Build two InvocationContext objects using the builder, assigning pluginManager1 to + the first context and pluginManager2 to the second context. Supply identical values + for all other required fields. + Act: Invoke pluginManager() on both context1 and context2. + Assert: Assert that context1.pluginManager() equals pluginManager1 and that + context2.pluginManager() equals pluginManager2. Also assert that + context1.pluginManager() is not equal to context2.pluginManager(). +Validation: + This test confirms the isolation between independent InvocationContext instances, ensuring + that the pluginManager field is instance-specific and not inadvertently shared as a static + or class-level resource. This is critical when multiple concurrent invocations use different + plugin configurations. + + +Scenario 6: Verify pluginManager() Returns the Updated PluginManager When Builder Is Reconfigured + +Details: + TestName: pluginManagerReturnsLastSetValueWhenBuilderIsReused + Description: Verifies that if the builder's .pluginManager() method is called multiple times + before .build(), the last value set is the one returned by pluginManager() on + the resulting InvocationContext. +Execution: + Arrange: Create two PluginManager instances: pluginManagerFirst and pluginManagerLast. + Using a single Builder, call .pluginManager(pluginManagerFirst) and then + .pluginManager(pluginManagerLast), followed by setting all other required fields, + and then call .build(). + Act: Invoke context.pluginManager() on the built InvocationContext. + Assert: Assert that the returned PluginManager equals pluginManagerLast and does not equal + pluginManagerFirst. +Validation: + This scenario validates that the builder correctly overwrites previous values when + .pluginManager() is called more than once, which reflects standard builder pattern behavior + and prevents configuration errors caused by stale or intermediate values being retained. + + +Scenario 7: Verify pluginManager() Consistency Between Initial Build and After endInvocation State Change + +Details: + TestName: pluginManagerRemainsUnchangedAfterEndInvocationStateChange + Description: Verifies that the PluginManager returned by pluginManager() remains the same + after the endInvocation state is modified via setEndInvocation(), confirming + that mutable state changes do not affect the immutable pluginManager field. +Execution: + Arrange: Build an InvocationContext with a specific PluginManager instance and endInvocation + set to false. Capture the initial result of pluginManager(). + Act: Call context.setEndInvocation(true) to mutate the endInvocation state, then invoke + context.pluginManager() again. + Assert: Assert that the PluginManager returned before and after the state change are the + same instance (equal). +Validation: + This test validates the immutability of the pluginManager field in the face of allowed + mutable state changes (endInvocation, agent, branch). It ensures that plugin management + infrastructure remains stable throughout the full lifecycle of an invocation, including + after terminal state changes are applied. + + +Scenario 8: Verify pluginManager() Is Reflected Correctly in equals() Comparison + +Details: + TestName: pluginManagerDifferenceIsReflectedInEqualsComparison + Description: Verifies that two InvocationContext instances built with all identical fields + except for different PluginManager instances are considered unequal, confirming + that the pluginManager field is included in the equals() contract. +Execution: + Arrange: Build two InvocationContext instances with all the same field values (sessionService, + artifactService, memoryService, invocationId, agent, session, userContent, runConfig, + endInvocation), but assign two different PluginManager instances to each context + respectively using .pluginManager(). + Act: Call context1.equals(context2). + Assert: Assert that context1.equals(context2) returns false. +Validation: + The equals() method in InvocationContext includes pluginManager in its comparison logic. + This test ensures that the pluginManager field participates meaningfully in object identity + and equality checks, which is important for caching, deduplication, or comparison scenarios + involving InvocationContext objects. + + +Scenario 9: Verify pluginManager() Is Reflected Correctly in hashCode() Computation + +Details: + TestName: pluginManagerDifferenceIsReflectedInHashCode + Description: Verifies that two InvocationContext instances that differ only in their + PluginManager produce different hash codes, confirming that pluginManager + is included in the hashCode() computation. +Execution: + Arrange: Build two InvocationContext instances with identical field values except for two + distinct PluginManager instances. Capture the hash code of each context using + hashCode(). + Act: Compare the hash codes of context1 and context2. + Assert: Assert that the hash codes are not equal (noting that while hash collisions are + theoretically possible, distinct object references for PluginManager should in + practice yield different hash codes). +Validation: + The hashCode() method includes pluginManager in its computation. This scenario verifies + that the PluginManager contributes to the hash, supporting correct behavior when + InvocationContext instances are used in hash-based collections such as HashMap or HashSet. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextPluginManagerTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @Mock + private Content mockUserContent; + + @Mock + private RunConfig mockRunConfig; + + private static final String TEST_INVOCATION_ID = "e-test-invocation-id-123"; + + @BeforeEach + void setUp() { + lenient().when(mockSession.appName()).thenReturn("testApp"); + lenient().when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext buildBaseContext(PluginManager pluginManager) { + InvocationContext.Builder builder = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig); + if (pluginManager != null) { + builder.pluginManager(pluginManager); + } + return builder.build(); + } + + @Test + @Tag("valid") + void pluginManagerReturnsExplicitlySetInstance() { + // Arrange + PluginManager explicitPluginManager = new PluginManager(); + InvocationContext context = buildBaseContext(explicitPluginManager); + // Act + PluginManager result = context.pluginManager(); + // Assert + assertNotNull(result); + assertSame(explicitPluginManager, result); + } + + @Test + @Tag("valid") + void pluginManagerReturnsDefaultWhenNotExplicitlyProvided() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .build(); + // Act + PluginManager result = context.pluginManager(); + // Assert + assertNotNull(result); + } + + @Test + @Tag("valid") + void pluginManagerIsNotNullWhenExplicitlySet() { + // Arrange + PluginManager explicitPluginManager = new PluginManager(); + InvocationContext context = buildBaseContext(explicitPluginManager); + // Act + PluginManager result = context.pluginManager(); + // Assert + assertNotNull(result); + } + + @Test + @Tag("integration") + void pluginManagerReturnsSameInstanceAfterCopyOf() { + // Arrange + PluginManager originalPluginManager = new PluginManager(); + InvocationContext originalContext = buildBaseContext(originalPluginManager); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + PluginManager originalResult = originalContext.pluginManager(); + PluginManager copiedResult = copiedContext.pluginManager(); + // Assert + assertNotNull(originalResult); + assertNotNull(copiedResult); + assertSame(originalResult, copiedResult); + } + + @Test + @Tag("valid") + void pluginManagerReturnsCorrectInstanceForEachContext() { + // Arrange + PluginManager pluginManager1 = new PluginManager(); + PluginManager pluginManager2 = new PluginManager(); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager1) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager2) + .build(); + // Act + PluginManager result1 = context1.pluginManager(); + PluginManager result2 = context2.pluginManager(); + // Assert + assertSame(pluginManager1, result1); + assertSame(pluginManager2, result2); + assertNotSame(result1, result2); + } + + @Test + @Tag("valid") + void pluginManagerReturnsLastSetValueWhenBuilderIsReused() { + // Arrange + PluginManager pluginManagerFirst = new PluginManager(); + PluginManager pluginManagerLast = new PluginManager(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManagerFirst) + .pluginManager(pluginManagerLast) + .build(); + // Act + PluginManager result = context.pluginManager(); + // Assert + assertSame(pluginManagerLast, result); + assertNotSame(pluginManagerFirst, result); + } + + @Test + @Tag("valid") + void pluginManagerRemainsUnchangedAfterEndInvocationStateChange() { + // Arrange + PluginManager pluginManager = new PluginManager(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager) + .endInvocation(false) + .build(); + // Act + PluginManager beforeChange = context.pluginManager(); + context.setEndInvocation(true); + PluginManager afterChange = context.pluginManager(); + // Assert + assertNotNull(beforeChange); + assertNotNull(afterChange); + assertSame(beforeChange, afterChange); + assertSame(pluginManager, afterChange); + } + + @Test + @Tag("valid") + void pluginManagerDifferenceIsReflectedInEqualsComparison() { + // Arrange + PluginManager pluginManager1 = new PluginManager(); + PluginManager pluginManager2 = new PluginManager(); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager1) + .endInvocation(false) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager2) + .endInvocation(false) + .build(); + // Act & Assert + assertFalse(context1.equals(context2)); + } + + @Test + @Tag("valid") + void pluginManagerDifferenceIsReflectedInHashCode() { + // Arrange + PluginManager pluginManager1 = new PluginManager(); + PluginManager pluginManager2 = new PluginManager(); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager1) + .endInvocation(false) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.ofNullable(mockUserContent)) + .runConfig(mockRunConfig) + .pluginManager(pluginManager2) + .endInvocation(false) + .build(); + // Act + int hashCode1 = context1.hashCode(); + int hashCode2 = context2.hashCode(); + // Assert + assertNotEquals(hashCode1, hashCode2, "Hash codes of contexts with different PluginManagers should differ"); + } + + @Test + @Tag("valid") + void pluginManagerReturnsSameReferenceOnMultipleCalls() { + // Arrange + PluginManager pluginManager = new PluginManager(); + InvocationContext context = buildBaseContext(pluginManager); + // Act + PluginManager firstCall = context.pluginManager(); + PluginManager secondCall = context.pluginManager(); + // Assert + assertSame(firstCall, secondCall); + assertSame(pluginManager, firstCall); + } + + @Test + @Tag("valid") + void pluginManagerReturnsSameInstanceAfterAgentChange() { + // Arrange + PluginManager pluginManager = new PluginManager(); + InvocationContext context = buildBaseContext(pluginManager); + BaseAgent anotherAgent = mock(BaseAgent.class); + // Act + PluginManager before = context.pluginManager(); + context.agent(anotherAgent); + PluginManager after = context.pluginManager(); + // Assert + assertSame(pluginManager, before); + assertSame(pluginManager, after); + assertSame(before, after); + } + + @Test + @Tag("valid") + void pluginManagerReturnsSameInstanceAfterBranchChange() { + // Arrange + PluginManager pluginManager = new PluginManager(); + InvocationContext context = buildBaseContext(pluginManager); + // Act + PluginManager before = context.pluginManager(); + context.branch("newBranch"); + PluginManager after = context.pluginManager(); + // Assert + assertSame(pluginManager, before); + assertSame(pluginManager, after); + assertSame(before, after); + } + + @Test + @Tag("boundary") + void pluginManagerWithNullBuildsThenDefaultIsUsed() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId(TEST_INVOCATION_ID) + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(mockRunConfig) + .build(); + // Act + PluginManager result = context.pluginManager(); + // Assert + assertNotNull(result, "PluginManager should not be null even when not explicitly set"); + } + + @Test + @Tag("integration") + void pluginManagerPreservedAcrossMultipleCopyOfOperations() { + // Arrange + PluginManager originalPluginManager = new PluginManager(); + InvocationContext originalContext = buildBaseContext(originalPluginManager); + // Act + InvocationContext copy1 = InvocationContext.copyOf(originalContext); + InvocationContext copy2 = InvocationContext.copyOf(copy1); + // Assert + assertSame(originalPluginManager, originalContext.pluginManager()); + assertSame(originalPluginManager, copy1.pluginManager()); + assertSame(originalPluginManager, copy2.pluginManager()); + } + + @Test + @Tag("valid") + void pluginManagerEqualsWhenSameInstance() { + // Arrange + PluginManager pluginManager = new PluginManager(); + InvocationContext context1 = buildBaseContext(pluginManager); + InvocationContext context2 = buildBaseContext(pluginManager); + // Act + PluginManager result1 = context1.pluginManager(); + PluginManager result2 = context2.pluginManager(); + // Assert + assertSame(result1, result2); + assertEquals(result1, result2); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextRunConfigTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextRunConfigTest.java new file mode 100644 index 000000000..4a9f36d45 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextRunConfigTest.java @@ -0,0 +1,435 @@ +/* + * 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=runConfig_09ff6f346f +ROOST_METHOD_SIG_HASH=runConfig_dbfa69ec19 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +"Scenario 1: Verify that runConfig() returns the exact RunConfig instance set during construction via builder + +Details: + TestName: runConfigReturnsConfigSetViaBuilder + Description: Verifies that the runConfig() method returns the exact same RunConfig instance that was provided to the builder during InvocationContext construction. This ensures that the field is correctly assigned and retrieved without modification. + +Execution: + Arrange: + - Create a RunConfig instance using RunConfig.builder().build() and assign it to a variable (e.g., expectedRunConfig). + - Build an InvocationContext using InvocationContext.builder() with all required fields (sessionService, artifactService, memoryService, pluginManager, invocationId, agent, session, userContent) and supply the expectedRunConfig to the .runConfig() builder method. + Act: + - Call context.runConfig() on the constructed InvocationContext. + Assert: + - Assert that the returned value is equal to expectedRunConfig using assertThat(context.runConfig()).isEqualTo(expectedRunConfig). + +Validation: + This assertion confirms that the runConfig() getter faithfully returns the RunConfig instance stored during construction. It is essential that the run configuration is accessible for controlling agent run behavior, such as enforcing LLM call limits and other runtime settings. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.models.LlmCallsLimitExceededException; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class InvocationContextRunConfigTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @BeforeEach + void setUp() { + when(mockSession.appName()).thenReturn("testApp"); + when(mockSession.userId()).thenReturn("testUser"); + } + + private InvocationContext buildContext(RunConfig runConfig) { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(runConfig) + .build(); + } + + @Test + @Tag("valid") + void runConfigReturnsConfigSetViaBuilder() { + RunConfig expectedRunConfig = RunConfig.builder().build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isEqualTo(expectedRunConfig); + } + + @Test + @Tag("valid") + void runConfigReturnsSameInstanceSetViaBuilder() { + RunConfig expectedRunConfig = RunConfig.builder().build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isSameInstanceAs(expectedRunConfig); + } + + @Test + @Tag("valid") + void runConfigReturnsConfigWithCustomMaxLlmCalls() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(100).build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isEqualTo(expectedRunConfig); + assertThat(context.runConfig().maxLlmCalls()).isEqualTo(100); + } + + @Test + @Tag("valid") + void runConfigReturnsConfigWithDefaultMaxLlmCalls() { + RunConfig expectedRunConfig = RunConfig.builder().build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isNotNull(); + assertThat(context.runConfig().maxLlmCalls()).isEqualTo(500); + } + + @Test + @Tag("valid") + void runConfigReturnsSameValueAfterMultipleCalls() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(200).build(); + InvocationContext context = buildContext(expectedRunConfig); + RunConfig firstCall = context.runConfig(); + RunConfig secondCall = context.runConfig(); + assertThat(firstCall).isSameInstanceAs(secondCall); + } + + @Test + @Tag("valid") + void runConfigIsPreservedAfterCopyOf() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(300).build(); + InvocationContext original = buildContext(expectedRunConfig); + InvocationContext copied = InvocationContext.copyOf(original); + assertThat(copied.runConfig()).isEqualTo(expectedRunConfig); + assertThat(copied.runConfig()).isSameInstanceAs(original.runConfig()); + } + + @Test + @Tag("valid") + void runConfigReturnedFromCreateMethod() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(150).build(); + Content userContent = mock(Content.class); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "test-invocation-id", mockAgent, mockSession, userContent, expectedRunConfig); + assertThat(context.runConfig()).isEqualTo(expectedRunConfig); + } + + @Test + @Tag("valid") + void runConfigReturnedFromCreateWithLiveQueueMethod() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(75).build(); + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, expectedRunConfig); + assertThat(context.runConfig()).isEqualTo(expectedRunConfig); + } + + @Test + @Tag("boundary") + void runConfigWithZeroMaxLlmCalls() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(0).build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isNotNull(); + assertThat(context.runConfig().maxLlmCalls()).isEqualTo(0); + } + + @Test + @Tag("boundary") + void runConfigWithMaxIntMaxLlmCalls() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(Integer.MAX_VALUE).build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isNotNull(); + assertThat(context.runConfig().maxLlmCalls()).isEqualTo(Integer.MAX_VALUE); + } + + @Test + @Tag("boundary") + void runConfigWithMinimumMaxLlmCallsOfOne() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(1).build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isNotNull(); + assertThat(context.runConfig().maxLlmCalls()).isEqualTo(1); + } + + @Test + @Tag("valid") + void runConfigDoesNotChangeWhenOtherFieldsAreModified() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(50).build(); + InvocationContext context = buildContext(expectedRunConfig); + context.setEndInvocation(true); + context.agent(mock(BaseAgent.class)); + context.branch("newBranch"); + assertThat(context.runConfig()).isEqualTo(expectedRunConfig); + assertThat(context.runConfig()).isSameInstanceAs(expectedRunConfig); + } + + @Test + @Tag("integration") + void runConfigIsUsedByIncrementLlmCallsCount() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(2).build(); + InvocationContext context = buildContext(runConfig); + assertThat(context.runConfig().maxLlmCalls()).isEqualTo(2); + context.incrementLlmCallsCount(); + context.incrementLlmCallsCount(); + org.junit.jupiter.api.Assertions.assertThrows(LlmCallsLimitExceededException.class, + () -> context.incrementLlmCallsCount()); + } + + @Test + @Tag("integration") + void runConfigIsConsistentAcrossContextEquality() { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(100).build(); + InvocationContext context1 = buildContext(runConfig); + InvocationContext context2 = buildContext(runConfig); + assertThat(context1.runConfig()).isEqualTo(context2.runConfig()); + } + + @Test + @Tag("valid") + void runConfigNotNullAfterConstruction() { + RunConfig expectedRunConfig = RunConfig.builder().build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isNotNull(); + } + + @Test + @Tag("valid") + void runConfigWithSaveInputBlobsAsArtifactsTrue() { + RunConfig expectedRunConfig = RunConfig.builder().setSaveInputBlobsAsArtifacts(true).build(); + InvocationContext context = buildContext(expectedRunConfig); + assertThat(context.runConfig()).isNotNull(); + assertThat(context.runConfig().saveInputBlobsAsArtifacts()).isTrue(); + } + + @Test + @Tag("valid") + void runConfigPreservedWithResumabilityConfigInContext() { + RunConfig expectedRunConfig = RunConfig.builder().setMaxLlmCalls(10).build(); + ResumabilityConfig resumabilityConfig = mock(ResumabilityConfig.class); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.empty()) + .runConfig(expectedRunConfig) + .resumabilityConfig(resumabilityConfig) + .build(); + assertThat(context.runConfig()).isEqualTo(expectedRunConfig); + assertThat(context.runConfig()).isSameInstanceAs(expectedRunConfig); + } + + @Test + @Tag("integration") + void runConfigCopiedContextHasSameRunConfigBehavior() throws LlmCallsLimitExceededException { + RunConfig runConfig = RunConfig.builder().setMaxLlmCalls(3).build(); + InvocationContext original = buildContext(runConfig); + InvocationContext copied = InvocationContext.copyOf(original); + assertThat(copied.runConfig()).isEqualTo(original.runConfig()); + assertThat(copied.runConfig().maxLlmCalls()).isEqualTo(3); + copied.incrementLlmCallsCount(); + copied.incrementLlmCallsCount(); + copied.incrementLlmCallsCount(); + org.junit.jupiter.api.Assertions.assertThrows(LlmCallsLimitExceededException.class, + () -> copied.incrementLlmCallsCount()); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextSessionServiceTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextSessionServiceTest.java new file mode 100644 index 000000000..b213c239b --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextSessionServiceTest.java @@ -0,0 +1,720 @@ +/* + * 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=sessionService_c04b1de6f8 +ROOST_METHOD_SIG_HASH=sessionService_1fa67a6550 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +" + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/AgentWithMemoryTest.java +Tests: + "@Test +public void agentRemembersUserNameWithMemoryTool() throws Exception { + String userId = "test-user"; + String agentName = "test-agent"; + Part functionCall = Part.builder().functionCall(FunctionCall.builder().name("loadMemory").args(ImmutableMap.of("query", "what is my name?")).build()).build(); + TestLlm testLlm = new TestLlm(ImmutableList.of(LlmResponse.builder().content(Content.builder().parts(Part.fromText("OK, I'll remember that.")).role("model").build()).build(), LlmResponse.builder().content(Content.builder().role("model").parts(ImmutableList.of(functionCall)).build()).build(), LlmResponse.builder().content(Content.builder(). + + parts(Part.fromText("Your name is James.")).role("model").build()).build())); + LlmAgent agent = LlmAgent.builder().name(agentName).model(testLlm).tools(ImmutableList.of(new LoadMemoryTool())).build(); + InMemoryRunner runner = new InMemoryRunner(agent); + String sessionId = runner.sessionService().createSession(agentName, userId).blockingGet().id(); + Content firstMessage = Content.fromParts(Part.fromText("My name is James")); + var unused = runner.runAsync(userId, sessionId, firstMessage, RunConfig.builder().build()).toList().blockingGet(); + + Session updatedSession = runner.sessionService().getSession("test-agent", userId, sessionId, Optional.empty()).blockingGet(); + + runner.memoryService().addSessionToMemory(updatedSession).blockingAwait(); + Content secondMessage = Content.fromParts(Part.fromText("what is my name?")); + unused = runner.runAsync(userId, updatedSession.id(), secondMessage, RunConfig.builder().build()).toList().blockingGet(); + + LlmRequest lastRequest = testLlm.getLastRequest(); + Content functionResponseContent = Iterables.getLast(lastRequest.contents()); + Optional functionResponsePart = functionResponseContent.parts().get().stream().filter(p -> p.functionResponse().isPresent()).findFirst(); + assertThat(functionResponsePart).isPresent(); + FunctionResponse functionResponse = functionResponsePart.get().functionResponse().get(); + assertThat(functionResponse.name()).hasValue("loadMemory"); + assertThat(functionResponse.response().get().toString()).contains("My name is James"); +} +"Scenario 1: Verify that sessionService() returns the exact BaseSessionService instance set during construction via the builder + +Details: + TestName: sessionServiceReturnsInstanceSetViaBuilder + Description: Verifies that the sessionService() method returns the exact same BaseSessionService instance + that was provided to the InvocationContext builder. This confirms that the field is correctly + assigned during construction and accurately exposed through the accessor method. +Execution: + Arrange: Create a mock of BaseSessionService (mockSessionService). Build an InvocationContext using + InvocationContext.builder(), supplying mockSessionService as the session service, along with + the required fields (artifactService, memoryService, agent, session). + Act: Call context.sessionService() on the constructed InvocationContext instance. + Assert: assertThat(context.sessionService()).isEqualTo(mockSessionService) + assertThat(context.sessionService()).isSameInstanceAs(mockSessionService) +Validation: + Confirms that sessionService() returns the precise mock instance injected via the builder, + not a copy or a null. This is fundamental for ensuring that session state management uses + the correct service throughout the invocation lifecycle. + +--- + +Scenario 2: Verify that sessionService() does not return null when a valid BaseSessionService is provided + +Details: + TestName: sessionServiceIsNotNullWhenProvided + Description: Confirms that the sessionService() accessor method returns a non-null value when a + valid BaseSessionService instance is supplied during the construction of InvocationContext. +Execution: + Arrange: Create a mock of BaseSessionService. Build an InvocationContext using the builder, + passing the mock as the session service along with other required fields + (artifactService, memoryService, agent, session). + Act: Call context.sessionService() on the resulting InvocationContext. + Assert: assertThat(context.sessionService()).isNotNull() +Validation: + Verifies that the returned sessionService is not null, ensuring that a properly configured + InvocationContext always provides access to its session service. A null return would indicate + a construction or assignment failure, which could cause NullPointerExceptions downstream. + +--- + +Scenario 3: Verify that sessionService() returns the same instance as stored in the context, confirming no defensive copy is made + +Details: + TestName: sessionServiceReturnsSameReferenceNotCopy + Description: Checks that sessionService() returns the same object reference as the one supplied + during construction, confirming the field is stored and returned by reference, not copied. +Execution: + Arrange: Create a mock of BaseSessionService. Build an InvocationContext via the builder with + the mock as sessionService and other required fields (artifactService, memoryService, + agent, session). + Act: Invoke context.sessionService() and capture the returned value. + Assert: assertThat(context.sessionService()).isSameInstanceAs(mockSessionService) +Validation: + Ensures no wrapping, proxying, or copying occurs on the sessionService field. Correct reference + identity is essential so that callers modifying or interacting with the returned service are + working on the same instance as the rest of the application. + +--- + +Scenario 4: Verify that sessionService() returns consistent values across multiple calls (idempotency) + +Details: + TestName: sessionServiceReturnsSameValueOnMultipleCalls + Description: Validates that repeated invocations of sessionService() on the same InvocationContext + instance always return the same BaseSessionService reference, confirming the field is + immutable (final) and the accessor is idempotent. +Execution: + Arrange: Create a mock of BaseSessionService. Build an InvocationContext via the builder + with the mock as sessionService and other required fields (artifactService, + memoryService, agent, session). + Act: Call context.sessionService() multiple times (e.g., first call, second call, third call). + Assert: assertThat(context.sessionService()).isEqualTo(mockSessionService) + assertThat(context.sessionService()).isSameInstanceAs(context.sessionService()) +Validation: + Since sessionService is declared as a private final field, it must never change after + construction. Multiple calls should always return the same value, guaranteeing thread-safe + read access and consistent behavior across the invocation lifecycle. + +--- + +Scenario 5: Verify that sessionService() on a copied InvocationContext returns the same BaseSessionService as the original + +Details: + TestName: sessionServiceOnCopiedContextEqualsOriginal + Description: Confirms that after creating a shallow copy of an InvocationContext using + InvocationContext.copyOf(), the sessionService() method on the copy returns the + same BaseSessionService instance as the original context. +Execution: + Arrange: Create a mock of BaseSessionService. Build an original InvocationContext with the mock + as the sessionService and other required fields (artifactService, memoryService, + agent, session, userContent, runConfig). Create a copy using InvocationContext.copyOf(originalContext). + Act: Call copiedContext.sessionService() on the copied context. + Assert: assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()) + assertThat(copiedContext.sessionService()).isSameInstanceAs(mockSessionService) +Validation: + InvocationContext.copyOf() is a shallow copy operation. The sessionService reference must + be shared between the original and the copy. This ensures that both contexts interact with + the same underlying session management logic, which is critical for maintaining session + state consistency when delegating to sub-agents. + +--- + +Scenario 6: Verify that sessionService() returns the correct instance when two distinct InvocationContext objects are built with different BaseSessionService instances + +Details: + TestName: sessionServiceReturnsDistinctInstancesForDifferentContexts + Description: Ensures that two separate InvocationContext instances built with different + BaseSessionService mocks each return their own corresponding service instance from + sessionService(), confirming proper isolation between contexts. +Execution: + Arrange: Create two separate mocks: mockSessionService1 and mockSessionService2. Build + context1 with mockSessionService1 and context2 with mockSessionService2, each using + their own required fields (artifactService, memoryService, agent, session). + Act: Call context1.sessionService() and context2.sessionService() respectively. + Assert: assertThat(context1.sessionService()).isEqualTo(mockSessionService1) + assertThat(context2.sessionService()).isEqualTo(mockSessionService2) + assertThat(context1.sessionService()).isNotEqualTo(context2.sessionService()) +Validation: + Each InvocationContext must be fully independent. This test confirms that there is no + shared static state or cross-contamination between context instances regarding the + sessionService field, which is vital in multi-agent or parallel invocation scenarios. + +--- + +Scenario 7: Verify that sessionService() returns the correct BaseSessionService when context is built using all optional and required fields together + +Details: + TestName: sessionServiceReturnedCorrectlyInFullyPopulatedContext + Description: Validates that sessionService() returns the expected BaseSessionService mock even + when the InvocationContext is built with all available fields populated — including + optional fields such as liveRequestQueue, userContent, branch, invocationId, + runConfig, endInvocation, and resumabilityConfig — ensuring no field interaction + interferes with the sessionService assignment. +Execution: + Arrange: Create a mock BaseSessionService, BaseArtifactService, BaseMemoryService, PluginManager, + BaseAgent, Session, and LiveRequestQueue. Build an InvocationContext using + the builder with all fields set, including the mockSessionService, liveRequestQueue, + userContent (Optional.of(...)), branch, invocationId, agent, session, runConfig, + endInvocation, and resumabilityConfig. + Act: Call context.sessionService() on the fully constructed InvocationContext. + Assert: assertThat(context.sessionService()).isEqualTo(mockSessionService) + assertThat(context.sessionService()).isSameInstanceAs(mockSessionService) +Validation: + This scenario guards against any possible interference from other builder fields that might + affect how sessionService is stored or returned. It ensures the accessor is robust across + all valid construction configurations of InvocationContext. + +--- + +Scenario 8: Verify that sessionService() on the deprecated constructor-based InvocationContext returns the correct BaseSessionService + +Details: + TestName: sessionServiceReturnedCorrectlyFromDeprecatedConstructor + Description: Confirms that an InvocationContext created via the deprecated constructor (accepting + all fields explicitly) correctly stores and returns the provided BaseSessionService + instance through the sessionService() accessor method. +Execution: + Arrange: Create a mock BaseSessionService, BaseArtifactService, BaseMemoryService, PluginManager, + BaseAgent, and Session. Instantiate InvocationContext using the deprecated constructor: + new InvocationContext(mockSessionService, mockArtifactService, mockMemoryService, + mockPluginManager, Optional.empty(), Optional.empty(), testInvocationId, mockAgent, + session, Optional.empty(), runConfig, false). + Act: Call context.sessionService() on the constructed instance. + Assert: assertThat(context.sessionService()).isEqualTo(mockSessionService) +Validation: + Although the constructor is deprecated, it must still correctly wire the sessionService field. + This ensures backward compatibility for existing callers using the deprecated API while + guaranteeing the sessionService() accessor works uniformly regardless of how the context + was created. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextSessionServiceTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + @Mock + private Session mockSession; + + @Mock + private ResumabilityConfig mockResumabilityConfig; + + private RunConfig runConfig; + + private String testInvocationId; + + @BeforeEach + void setUp() { + runConfig = RunConfig.builder().build(); + testInvocationId = InvocationContext.newInvocationContextId(); + } + + private InvocationContext buildBasicContext(BaseSessionService sessionService) { + return InvocationContext.builder() + .sessionService(sessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId(testInvocationId) + .runConfig(runConfig) + .build(); + } + + @Test + @Tag("valid") + void sessionServiceReturnsInstanceSetViaBuilder() { + // Arrange + InvocationContext context = buildBasicContext(mockSessionService); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isEqualTo(mockSessionService); + assertThat(returnedService).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("valid") + void sessionServiceIsNotNullWhenProvided() { + // Arrange + InvocationContext context = buildBasicContext(mockSessionService); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isNotNull(); + } + + @Test + @Tag("valid") + void sessionServiceReturnsSameReferenceNotCopy() { + // Arrange + InvocationContext context = buildBasicContext(mockSessionService); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("valid") + void sessionServiceReturnsSameValueOnMultipleCalls() { + // Arrange + InvocationContext context = buildBasicContext(mockSessionService); + // Act + BaseSessionService firstCall = context.sessionService(); + BaseSessionService secondCall = context.sessionService(); + BaseSessionService thirdCall = context.sessionService(); + // Assert + assertThat(firstCall).isEqualTo(mockSessionService); + assertThat(firstCall).isSameInstanceAs(secondCall); + assertThat(secondCall).isSameInstanceAs(thirdCall); + assertThat(context.sessionService()).isSameInstanceAs(context.sessionService()); + } + + @Test + @Tag("integration") + void sessionServiceOnCopiedContextEqualsOriginal() { + // Arrange + InvocationContext originalContext = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId(testInvocationId) + .userContent(Optional.empty()) + .runConfig(runConfig) + .build(); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + // Assert + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.sessionService()).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("valid") + void sessionServiceReturnsDistinctInstancesForDifferentContexts() { + // Arrange + BaseSessionService mockSessionService1 = mock(BaseSessionService.class); + BaseSessionService mockSessionService2 = mock(BaseSessionService.class); + InvocationContext context1 = InvocationContext.builder() + .sessionService(mockSessionService1) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId(InvocationContext.newInvocationContextId()) + .runConfig(runConfig) + .build(); + InvocationContext context2 = InvocationContext.builder() + .sessionService(mockSessionService2) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId(InvocationContext.newInvocationContextId()) + .runConfig(runConfig) + .build(); + // Act + BaseSessionService returnedService1 = context1.sessionService(); + BaseSessionService returnedService2 = context2.sessionService(); + // Assert + assertThat(returnedService1).isEqualTo(mockSessionService1); + assertThat(returnedService2).isEqualTo(mockSessionService2); + assertThat(returnedService1).isNotEqualTo(returnedService2); + } + + @Test + @Tag("integration") + void sessionServiceReturnedCorrectlyInFullyPopulatedContext() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + Content userContent = Content.builder().role("user").build(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .userContent(Optional.of(userContent)) + .branch("testBranch") + .invocationId(testInvocationId) + .agent(mockAgent) + .session(mockSession) + .runConfig(runConfig) + .endInvocation(false) + .resumabilityConfig(mockResumabilityConfig) + .build(); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isEqualTo(mockSessionService); + assertThat(returnedService).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("valid") + @SuppressWarnings("deprecation") + void sessionServiceReturnedCorrectlyFromDeprecatedConstructor() { + // Arrange + InvocationContext context = new InvocationContext(mockSessionService, mockArtifactService, mockMemoryService, + mockPluginManager, Optional.empty(), Optional.empty(), testInvocationId, mockAgent, mockSession, + Optional.empty(), runConfig, false); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isEqualTo(mockSessionService); + } + + @Test + @Tag("boundary") + void sessionServiceReturnsNullWhenNotSet() { + // Arrange + InvocationContext context = InvocationContext.builder() + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .invocationId(testInvocationId) + .runConfig(runConfig) + .build(); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isNull(); + } + + @Test + @Tag("valid") + void sessionServiceReturnedCorrectlyFromStaticCreateMethod() { + // Arrange + Content userContent = Content.builder().role("user").build(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, testInvocationId, + mockAgent, mockSession, userContent, runConfig); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isNotNull(); + assertThat(returnedService).isEqualTo(mockSessionService); + assertThat(returnedService).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("valid") + void sessionServiceReturnedCorrectlyFromStaticCreateMethodWithLiveRequestQueue() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, runConfig); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isNotNull(); + assertThat(returnedService).isEqualTo(mockSessionService); + assertThat(returnedService).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("integration") + void sessionServiceRemainsUnchangedAfterMutatingOtherFields() { + // Arrange + InvocationContext context = buildBasicContext(mockSessionService); + BaseAgent newMockAgent = mock(BaseAgent.class); + // Act - mutate other fields + context.agent(newMockAgent); + context.branch("newBranch"); + context.setEndInvocation(true); + // Assert - sessionService should remain unchanged + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.sessionService()).isSameInstanceAs(mockSessionService); + } + + @Test + @Tag("boundary") + void sessionServiceOnCopiedContextIsSameInstanceAfterMutation() { + // Arrange + InvocationContext originalContext = buildBasicContext(mockSessionService); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + // Act - mutate the copied context + copiedContext.setEndInvocation(true); + copiedContext.branch("anotherBranch"); + // Assert - sessionService should still reference the same instance + assertThat(copiedContext.sessionService()).isSameInstanceAs(mockSessionService); + assertThat(copiedContext.sessionService()).isSameInstanceAs(originalContext.sessionService()); + } + + @Test + @Tag("valid") + @SuppressWarnings("deprecation") + void sessionServiceReturnedCorrectlyFromDeprecatedConstructorWithoutPluginManager() { + // Arrange + InvocationContext context = new InvocationContext(mockSessionService, mockArtifactService, mockMemoryService, + Optional.empty(), Optional.empty(), testInvocationId, mockAgent, mockSession, Optional.empty(), + runConfig, false); + // Act + BaseSessionService returnedService = context.sessionService(); + // Assert + assertThat(returnedService).isNotNull(); + assertThat(returnedService).isEqualTo(mockSessionService); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextSessionTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextSessionTest.java new file mode 100644 index 000000000..e6af96ffd --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextSessionTest.java @@ -0,0 +1,1005 @@ +/* + * 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=session_a0f90dafba +ROOST_METHOD_SIG_HASH=session_a2fc7a867d + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + assertThat(context.isResumable()).isFalse(); +} +" + "@Test +public void isResumable_whenResumabilityConfigIsResumable_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + assertThat(context.isResumable()).isTrue(); +} +" + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/CallbacksTest.java +Tests: + "@Test +public void testRun_withBeforeAgentCallback_returnsNothing() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeAgentCallback(callbackContext -> Maybe.empty()).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + + assertThat(events).hasSize(1); + assertThat(events.get(0).content()).hasValue(modelContent); + assertThat(events.get(0).actions().stateDelta()).isEmpty(); + assertThat(finalState).isEmpty(); +} +" + "@Test +public void testRun_withBeforeAgentCallback_returnsContent() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + Content beforeAgentContent = Content.fromParts(Part.fromText("before agent content")); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeAgentCallback(callbackContext -> { + Object unused = callbackContext.state().put("before_key", "before_value"); + return Maybe.just(beforeAgentContent); + }).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + + assertThat(events).hasSize(1); + assertThat(events.get(0).content()).hasValue(beforeAgentContent); + assertThat(events.get(0).actions().stateDelta()).containsExactly("before_key", "before_value"); + assertThat(finalState).containsEntry("before_key", "before_value"); +} +" + "@Test +public void testRun_withBeforeAgentCallback_modifiesStateOnly() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeAgentCallback(callbackContext -> { + Object unused = callbackContext.state().put("before_key", "before_value"); + + return Maybe.empty(); + }).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + + assertThat(events).hasSize(2); + + + assertThat(events.get(0).content().flatMap(Content::parts)).isEmpty(); + assertThat(events.get(0).actions().stateDelta()).containsExactly("before_key", "before_value"); + + assertThat(events.get(1).content()).hasValue(modelContent); + assertThat(events.get(1).actions().stateDelta()).isEmpty(); + assertThat(finalState).containsEntry("before_key", "before_value"); +} +" + "@Test +public void testRun_agentCallback_modifyStateAndOverrideResponse() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + LlmAgent agent = createTestAgentBuilder(testLlm).beforeAgentCallback(callbackContext -> { + Object unused = callbackContext.state().put("before_key", "before_value"); + return Maybe.empty(); + }).afterAgentCallback(callbackContext -> { + Object unused = callbackContext.state().put("after_key", "after_value"); + return Maybe.just(Content.fromParts(Part.fromText("after agent content"))); + }).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + assertThat(events).hasSize(3); + assertThat(events.get(0).content().flatMap(Content::parts)).isEmpty(); + assertThat(events.get(0).actions().stateDelta()).containsExactly("before_key", "before_value"); + assertThat(events.get(1).content()).hasValue(modelContent); + assertThat(events.get(1).actions().stateDelta()).isEmpty(); + assertThat(events.get(2).content().get().parts().get().get(0).text()).hasValue("after agent content"); + assertThat(events.get(2).actions().stateDelta()).containsExactly("after_key", "after_value"); + assertThat(finalState).containsEntry("before_key", "before_value"); + assertThat(finalState).containsEntry("after_key", "after_value"); +} +" + "@Test +public void testRun_withMultipleBeforeAgentCallbacks_firstReturnsContent() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + Content beforeAgentContent1 = Content.fromParts(Part.fromText("before agent content 1")); + Content beforeAgentContent2 = Content.fromParts(Part.fromText("before agent content 2")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + Callbacks.BeforeAgentCallbackSync cb1 = callbackContext -> { + var unused = callbackContext.state().put("key1", "value1"); + return Optional.of(beforeAgentContent1); + }; + Callbacks.BeforeAgentCallback cb2 = callbackContext -> { + var unused = callbackContext.state().put("key2", "value2"); + return Maybe.just(beforeAgentContent2); + }; + LlmAgent agent = createTestAgentBuilder(testLlm).beforeAgentCallback(ImmutableList.of(cb1, cb2)).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + assertThat(events).hasSize(1); + Event event1 = events.get(0); + assertThat(event1.content()).hasValue(beforeAgentContent1); + assertThat(event1.actions().stateDelta()).containsExactly("key1", "value1"); + assertThat(finalState).containsExactly("key1", "value1"); + assertThat(testLlm.getRequests()).isEmpty(); +} +" + "@Test +public void testRun_withMultipleBeforeAgentCallbacks_allModifyState_noneReturnContent() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + Callbacks.BeforeAgentCallbackSync cb1 = callbackContext -> { + var unused = callbackContext.state().put("key1", "value1"); + return Optional.empty(); + }; + Callbacks.BeforeAgentCallback cb2 = callbackContext -> { + var unused = callbackContext.state().put("key2", "value2"); + return Maybe.empty(); + }; + LlmAgent agent = createTestAgentBuilder(testLlm).beforeAgentCallback(ImmutableList.of(cb1, cb2)).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + assertThat(events).hasSize(2); + Event event1 = events.get(0); + assertThat(event1.content().flatMap(Content::parts)).isEmpty(); + assertThat(event1.actions().stateDelta()).containsExactly("key1", "value1", "key2", "value2"); + Event event2 = events.get(1); + assertThat(event2.content()).hasValue(modelContent); + assertThat(event2.actions().stateDelta()).isEmpty(); + assertThat(finalState).containsExactly("key1", "value1", "key2", "value2"); + assertThat(testLlm.getRequests()).hasSize(1); +} +" + "@Test +public void testRun_withMultipleAfterAgentCallbacks_firstReturnsContent() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + Content afterAgentContent1 = Content.fromParts(Part.fromText("after agent content 1")); + Content afterAgentContent2 = Content.fromParts(Part.fromText("after agent content 2")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + Callbacks.AfterAgentCallbackSync cb1 = callbackContext -> { + var unused = callbackContext.state().put("key1", "value1"); + return Optional.of(afterAgentContent1); + }; + Callbacks.AfterAgentCallback cb2 = callbackContext -> { + var unused = callbackContext.state().put("key2", "value2"); + return Maybe.just(afterAgentContent2); + }; + LlmAgent agent = createTestAgentBuilder(testLlm).afterAgentCallback(ImmutableList.of(cb1, cb2)).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + assertThat(events).hasSize(2); + Event event1 = events.get(0); + assertThat(event1.content()).hasValue(modelContent); + assertThat(event1.actions().stateDelta()).isEmpty(); + Event event2 = events.get(1); + assertThat(event2.content()).hasValue(afterAgentContent1); + assertThat(event2.actions().stateDelta()).containsExactly("key1", "value1"); + assertThat(finalState).containsExactly("key1", "value1"); + assertThat(testLlm.getRequests()).hasSize(1); +} +" + "@Test +public void testRun_withMultipleAfterAgentCallbacks_allModifyState_noneReturnContent() { + Content modelContent = Content.fromParts(Part.fromText("Real LLM response")); + TestLlm testLlm = createTestLlm(createLlmResponse(modelContent)); + Callbacks.AfterAgentCallbackSync cb1 = callbackContext -> { + var unused = callbackContext.state().put("key1", "value1"); + return Optional.empty(); + }; + Callbacks.AfterAgentCallback cb2 = callbackContext -> { + var unused = callbackContext.state().put("key2", "value2"); + return Maybe.empty(); + }; + LlmAgent agent = createTestAgentBuilder(testLlm).afterAgentCallback(ImmutableList.of(cb1, cb2)).build(); + InvocationContext invocationContext = createInvocationContext(agent); + List events = agent.runAsync(invocationContext).toList().blockingGet(); + Map finalState = invocationContext.session().state(); + assertThat(events).hasSize(2); + Event event1 = events.get(0); + assertThat(event1.content()).hasValue(modelContent); + assertThat(event1.actions().stateDelta()).isEmpty(); + Event event2 = events.get(1); + assertThat(event2.content().flatMap(Content::parts)).isEmpty(); + assertThat(event2.actions().stateDelta()).containsExactly("key1", "value1", "key2", "value2"); + assertThat(finalState).containsExactly("key1", "value1", "key2", "value2"); + assertThat(testLlm.getRequests()).hasSize(1); +} +" + "@Test +public void handleFunctionCalls_withChainedToolCallbacks_overridesResultAndPassesContext() { + ImmutableMap originalToolInputArgs = ImmutableMap.of("input_key", "input_value"); + ImmutableMap stateAddedByBc2 = ImmutableMap.of("bc2_state_key", "bc2_state_value"); + ImmutableMap responseFromAc2 = ImmutableMap.of("ac2_response_key", "ac2_response_value"); + Callbacks.BeforeToolCallbackSync bc1 = (invCtx, toolName, args, currentToolCtx) -> Optional.empty(); + Callbacks.BeforeToolCallbackSync bc2 = (invCtx, toolName, args, currentToolCtx) -> { + currentToolCtx.state().putAll(stateAddedByBc2); + return Optional.empty(); + }; + TestUtils.EchoTool echoTool = new TestUtils.EchoTool(); + Callbacks.AfterToolCallbackSync ac1 = (invCtx, toolName, args, currentToolCtx, responseFromTool) -> Optional.empty(); + Callbacks.AfterToolCallbackSync ac2 = (invCtx, toolName, args, currentToolCtx, responseFromTool) -> Optional.of(responseFromAc2); + InvocationContext invocationContext = createInvocationContext(createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())).beforeToolCallback(ImmutableList.of(bc1, bc2)).afterToolCallback(ImmutableList.of(ac1, ac2)).build()); + Event eventWithFunctionCall = createEvent("event").toBuilder().content(createFunctionCallContent("fc_id_minimal", "echo_tool", originalToolInputArgs)).build(); + Event functionResponseEvent = Functions.handleFunctionCalls(invocationContext, eventWithFunctionCall, ImmutableMap.of("echo_tool", echoTool)).blockingGet(); + assertThat(getFunctionResponse(functionResponseEvent)).isEqualTo(responseFromAc2); + assertThat(invocationContext.session().state()).containsExactlyEntriesIn(stateAddedByBc2); +} +" + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/SequentialAgentTest.java +Tests: + "@Test +public void runAsync_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgent").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runAsync(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +" + "@Test +public void runLive_propagatesInvocationContextToSubAgents() { + TestBaseAgent subAgent = createSubAgent("subAgent_live"); + SequentialAgent sequentialAgent = SequentialAgent.builder().name("seqAgentLive").subAgents(ImmutableList.of(subAgent)).build(); + InvocationContext parentContext = createInvocationContext(sequentialAgent); + List unused = sequentialAgent.runLive(parentContext).toList().blockingGet(); + InvocationContext capturedContext = subAgent.getLastInvocationContext(); + assertThat(capturedContext).isNotNull(); + assertThat(capturedContext.invocationId()).isEqualTo(parentContext.invocationId()); + assertThat(capturedContext.session()).isEqualTo(parentContext.session()); + assertThat(capturedContext.agent()).isEqualTo(subAgent); + assertThat(subAgent.getInvocationCount()).isEqualTo(1); +} +"Scenario 1: Verify That session() Returns the Session Object Set During Construction + +Details: + TestName: sessionReturnsSessionSetDuringConstruction + Description: Verifies that the session() method returns the exact Session instance that was provided to the builder when constructing the InvocationContext. This is the primary happy-path scenario for the session() accessor. +Execution: + Arrange: + - Create a mock Session object (e.g., mockSession). + - Create a mock BaseSessionService, BaseArtifactService, and BaseMemoryService. + - Build an InvocationContext using InvocationContext.builder() with the mocked session assigned via .session(mockSession). + Act: + - Invoke context.session() on the built InvocationContext. + Assert: + - assertThat(context.session()).isEqualTo(mockSession); +Validation: + This assertion confirms that the session() accessor faithfully returns the Session instance stored in the private final field during object construction. Since the field is final and set only once via the builder, the returned object must be identical to the one supplied. This is foundational to the correct operation of any downstream logic that relies on session state, user ID, or app name. + + +Scenario 2: Verify That session() Does Not Return Null When a Valid Session Is Provided + +Details: + TestName: sessionDoesNotReturnNullWhenSessionIsProvided + Description: Verifies that the session() method never returns null when a non-null Session object has been supplied through the builder. This guards against accidental null returns that could cause NullPointerExceptions in callers. +Execution: + Arrange: + - Create a mock Session object. + - Build an InvocationContext via InvocationContext.builder() providing the mock session. + Act: + - Call context.session(). + Assert: + - assertThat(context.session()).isNotNull(); +Validation: + The session field is final and assigned from the builder value. Asserting non-null ensures the accessor does not accidentally transform or discard the value. This test protects against regressions where a null-returning code path might be inadvertently introduced. + + +Scenario 3: Verify That session() Returns the Same Instance Across Multiple Calls (Idempotency) + +Details: + TestName: sessionReturnsSameInstanceOnRepeatedCalls + Description: Verifies that multiple successive calls to session() on the same InvocationContext instance always return the same Session object, confirming the accessor is idempotent and consistent. +Execution: + Arrange: + - Create a mock Session object. + - Build an InvocationContext via InvocationContext.builder() providing the mock session. + Act: + - Call context.session() twice, storing the results as firstCall and secondCall. + Assert: + - assertThat(firstCall).isSameInstanceAs(secondCall); +Validation: + Since session is a private final field with no mutation path, every call to session() must return the identical object reference. This test confirms referential equality (same instance), not just value equality. Idempotency here is critical because many parts of the agent framework retrieve the session repeatedly and must observe a stable reference. + + +Scenario 4: Verify That session() Returns the Correct Session Object When a CopyOf Context Is Created + +Details: + TestName: sessionReturnsSameSessionAfterCopyOf + Description: Verifies that after creating a copy of an InvocationContext using InvocationContext.copyOf(), the session() method on the copied context returns the same Session instance as the original, confirming that copyOf performs a shallow copy of the session field. +Execution: + Arrange: + - Create a mock Session object. + - Build an original InvocationContext via InvocationContext.builder() with the mock session. + - Create a copied context via InvocationContext.copyOf(originalContext). + Act: + - Call copiedContext.session(). + Assert: + - assertThat(copiedContext.session()).isSameInstanceAs(originalContext.session()); +Validation: + The copyOf() method is documented to produce a shallow copy. Therefore, both the original and copied contexts must share the exact same Session reference. This is important because sub-agents and forked invocation paths should operate on the same session state unless explicitly provided with a different one. + + +Scenario 5: Verify That session() Returns the Correct Session When Multiple InvocationContexts Are Built With Different Sessions + +Details: + TestName: sessionReturnsDifferentSessionsForDifferentContexts + Description: Verifies that two separately built InvocationContext instances each return their own respective Session objects from session(), with no cross-contamination between instances. +Execution: + Arrange: + - Create two distinct mock Session objects: mockSession1 and mockSession2. + - Build context1 using InvocationContext.builder() with mockSession1. + - Build context2 using InvocationContext.builder() with mockSession2. + Act: + - Call context1.session() and context2.session(). + Assert: + - assertThat(context1.session()).isEqualTo(mockSession1); + - assertThat(context2.session()).isEqualTo(mockSession2); + - assertThat(context1.session()).isNotSameInstanceAs(context2.session()); +Validation: + This test confirms that InvocationContext instances are fully independent with respect to their session field. Each builder call produces an isolated object, so session data from one invocation cannot bleed into another. This is critical for multi-tenant or multi-session execution environments. + + +Scenario 6: Verify That session() Is Consistent With the Session Returned by appName() and userId() Accessors + +Details: + TestName: sessionIsConsistentWithAppNameAndUserId + Description: Verifies that the Session object returned by session() is the same instance whose appName() and userId() are exposed by the InvocationContext's own appName() and userId() delegate methods, confirming internal consistency. +Execution: + Arrange: + - Create a mock Session configured to return a known appName (e.g., "testApp") and userId (e.g., "testUser"). + - Build an InvocationContext with this mock session. + Act: + - Call context.session(), context.appName(), and context.userId(). + Assert: + - assertThat(context.appName()).isEqualTo(context.session().appName()); + - assertThat(context.userId()).isEqualTo(context.session().userId()); +Validation: + The InvocationContext delegates appName() and userId() directly to the session field. This test verifies that the object returned by session() is the authoritative source of those values, and that there is no discrepancy between reading from the session directly versus reading via the context's convenience accessors. + + +Scenario 7: Verify That session() Returns the Session Object When the Context Is Built Without Optional Fields + +Details: + TestName: sessionReturnedWhenContextBuiltWithMinimalRequiredFields + Description: Verifies that session() correctly returns the supplied Session even when the InvocationContext is constructed with only the minimal required fields (sessionService, artifactService, memoryService, agent, session) and all optional fields are left at their defaults. +Execution: + Arrange: + - Create mocks for BaseSessionService, BaseArtifactService, BaseMemoryService, BaseAgent, and Session. + - Build an InvocationContext using only the minimal required builder fields. + Act: + - Call context.session(). + Assert: + - assertThat(context.session()).isNotNull(); + - assertThat(context.session()).isEqualTo(mockSession); +Validation: + Confirms that the session() accessor works correctly irrespective of whether optional fields like liveRequestQueue, userContent, branch, or runConfig are set. This tests the robustness of the accessor in minimal-configuration scenarios, which are common in unit tests for agent flows. + + +Scenario 8: Verify That session() Returns the Correct Session After Agent Is Reassigned on the Context + +Details: + TestName: sessionRemainsUnchangedAfterAgentReassignment + Description: Verifies that calling context.agent(newAgent) to reassign the agent on an InvocationContext does not affect the value returned by session(). The session field is final and must remain stable even when other mutable fields are updated. +Execution: + Arrange: + - Create a mock Session, mock BaseAgent (mockAgent), and a new mock BaseAgent (newMockAgent). + - Build an InvocationContext with mockAgent and the mock session. + - Call context.agent(newMockAgent) to mutate the agent field. + Act: + - Call context.session() after the agent reassignment. + Assert: + - assertThat(context.session()).isEqualTo(mockSession); +Validation: + Since session is a private final field, it cannot be changed after construction. Mutating the agent field must not affect the session. This test ensures that the immutability contract of the session field is upheld even as other mutable parts of InvocationContext are modified during an invocation lifecycle. + + +Scenario 9: Verify That session() Returns the Correct Session After endInvocation State Is Changed + +Details: + TestName: sessionRemainsUnchangedAfterEndInvocationIsSet + Description: Verifies that calling context.setEndInvocation(true) to signal the end of the invocation does not affect the Session object returned by session(). The session field must remain stable throughout the lifecycle of the context. +Execution: + Arrange: + - Create a mock Session and build an InvocationContext with endInvocation set to false. + - Call context.setEndInvocation(true) to simulate ending the invocation. + Act: + - Call context.session(). + Assert: + - assertThat(context.session()).isEqualTo(mockSession); + - assertThat(context.endInvocation()).isTrue(); +Validation: + This scenario confirms that the session field is unaffected by lifecycle mutations such as ending the invocation. It validates the independence of the final session field from mutable state fields, ensuring that even in terminal states, session data remains accessible and accurate. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextSessionTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private BaseAgent mockAgent; + + @Mock + private RunConfig mockRunConfig; + + @BeforeEach + void setUp() { + when(mockRunConfig.maxLlmCalls()).thenReturn(500); + } + + private InvocationContext buildMinimalContext(Session session) { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(session) + .runConfig(mockRunConfig) + .invocationId("test-invocation-id") + .build(); + } + + @Test + @Tag("valid") + void sessionReturnsSessionSetDuringConstruction() { + // Arrange + InvocationContext context = buildMinimalContext(mockSession); + // Act + Session result = context.session(); + // Assert + assertThat(result).isEqualTo(mockSession); + } + + @Test + @Tag("valid") + void sessionDoesNotReturnNullWhenSessionIsProvided() { + // Arrange + InvocationContext context = buildMinimalContext(mockSession); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + } + + @Test + @Tag("valid") + void sessionReturnsSameInstanceOnRepeatedCalls() { + // Arrange + InvocationContext context = buildMinimalContext(mockSession); + // Act + Session firstCall = context.session(); + Session secondCall = context.session(); + // Assert + assertThat(firstCall).isSameInstanceAs(secondCall); + } + + @Test + @Tag("valid") + void sessionReturnsSameSessionAfterCopyOf() { + // Arrange + InvocationContext originalContext = buildMinimalContext(mockSession); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + // Assert + assertThat(copiedContext.session()).isSameInstanceAs(originalContext.session()); + } + + @Test + @Tag("valid") + void sessionReturnsDifferentSessionsForDifferentContexts() { + // Arrange + Session mockSession1 = mock(Session.class); + Session mockSession2 = mock(Session.class); + InvocationContext context1 = buildMinimalContext(mockSession1); + InvocationContext context2 = buildMinimalContext(mockSession2); + // Act + Session result1 = context1.session(); + Session result2 = context2.session(); + // Assert + assertThat(result1).isEqualTo(mockSession1); + assertThat(result2).isEqualTo(mockSession2); + assertThat(result1).isNotSameInstanceAs(result2); + } + + @Test + @Tag("integration") + void sessionIsConsistentWithAppNameAndUserId() { + // Arrange + String expectedAppName = "testApp"; + String expectedUserId = "testUser"; + when(mockSession.appName()).thenReturn(expectedAppName); + when(mockSession.userId()).thenReturn(expectedUserId); + InvocationContext context = buildMinimalContext(mockSession); + // Act + String appName = context.appName(); + String userId = context.userId(); + Session session = context.session(); + // Assert + assertThat(appName).isEqualTo(session.appName()); + assertThat(userId).isEqualTo(session.userId()); + assertThat(appName).isEqualTo(expectedAppName); + assertThat(userId).isEqualTo(expectedUserId); + } + + @Test + @Tag("valid") + void sessionReturnedWhenContextBuiltWithMinimalRequiredFields() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .build(); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + } + + @Test + @Tag("valid") + void sessionRemainsUnchangedAfterAgentReassignment() { + // Arrange + BaseAgent newMockAgent = mock(BaseAgent.class); + InvocationContext context = buildMinimalContext(mockSession); + // Act + context.agent(newMockAgent); + Session result = context.session(); + // Assert + assertThat(result).isEqualTo(mockSession); + assertThat(context.agent()).isSameInstanceAs(newMockAgent); + } + + @Test + @Tag("valid") + void sessionRemainsUnchangedAfterEndInvocationIsSet() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .invocationId("test-invocation-id") + .endInvocation(false) + .build(); + // Act + context.setEndInvocation(true); + Session result = context.session(); + // Assert + assertThat(result).isEqualTo(mockSession); + assertThat(context.endInvocation()).isTrue(); + } + + @Test + @Tag("valid") + void sessionReturnedFromStaticCreateMethodWithUserContent() { + // Arrange + Content mockContent = mock(Content.class); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "test-invocation-id", mockAgent, mockSession, mockContent, mockRunConfig); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + } + + @Test + @Tag("valid") + void sessionReturnedFromStaticCreateMethodWithLiveRequestQueue() { + // Arrange + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, mockAgent, + mockSession, liveRequestQueue, mockRunConfig); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + } + + @Test + @Tag("valid") + void sessionReturnedWithBranchSet() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .invocationId("test-invocation-id") + .branch("main.sub-branch") + .build(); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + assertThat(context.branch()).isEqualTo(Optional.of("main.sub-branch")); + } + + @Test + @Tag("integration") + void sessionReturnedWithResumabilityConfigSet() { + // Arrange + ResumabilityConfig resumabilityConfig = mock(ResumabilityConfig.class); + when(resumabilityConfig.isResumable()).thenReturn(true); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .invocationId("test-invocation-id") + .resumabilityConfig(resumabilityConfig) + .build(); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + assertThat(context.isResumable()).isTrue(); + } + + @Test + @Tag("valid") + void sessionReturnedWhenUserContentIsAbsent() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .invocationId("test-invocation-id") + .userContent(Optional.empty()) + .build(); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + assertThat(context.userContent()).isEmpty(); + } + + @Test + @Tag("integration") + void sessionConsistentAcrossMultipleCopyOfOperations() { + // Arrange + InvocationContext originalContext = buildMinimalContext(mockSession); + InvocationContext copiedOnce = InvocationContext.copyOf(originalContext); + InvocationContext copiedTwice = InvocationContext.copyOf(copiedOnce); + // Act & Assert + assertThat(originalContext.session()).isSameInstanceAs(copiedOnce.session()); + assertThat(copiedOnce.session()).isSameInstanceAs(copiedTwice.session()); + assertThat(originalContext.session()).isSameInstanceAs(copiedTwice.session()); + } + + @Test + @Tag("valid") + void sessionReturnedFromContextBuiltWithAllOptionalFields() { + // Arrange + Content mockContent = mock(Content.class); + PluginManager mockPluginManager = mock(PluginManager.class); + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .invocationId("full-invocation-id") + .userContent(mockContent) + .branch("main") + .liveRequestQueue(liveRequestQueue) + .endInvocation(false) + .build(); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + } + + @Test + @Tag("boundary") + void sessionReturnedWhenInvocationIdIsEmpty() { + // Arrange + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .agent(mockAgent) + .session(mockSession) + .runConfig(mockRunConfig) + .invocationId("") + .build(); + // Act + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + } + + @Test + @Tag("valid") + void sessionReturnedFromContextWithBranchMutation() { + // Arrange + InvocationContext context = buildMinimalContext(mockSession); + // Act + context.branch("new-branch"); + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + assertThat(context.branch()).isEqualTo(Optional.of("new-branch")); + } + + @Test + @Tag("valid") + void sessionNotAffectedByActiveStreamingToolsAddition() { + // Arrange + InvocationContext context = buildMinimalContext(mockSession); + ActiveStreamingTool mockStreamingTool = mock(ActiveStreamingTool.class); + // Act + context.activeStreamingTools().put("tool-1", mockStreamingTool); + Session result = context.session(); + // Assert + assertThat(result).isNotNull(); + assertThat(result).isEqualTo(mockSession); + assertThat(context.activeStreamingTools()).containsKey("tool-1"); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextShouldPauseInvocationTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextShouldPauseInvocationTest.java new file mode 100644 index 000000000..5eb95dbf5 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextShouldPauseInvocationTest.java @@ -0,0 +1,604 @@ +/* + * 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=shouldPauseInvocation_16da4698a8 +ROOST_METHOD_SIG_HASH=shouldPauseInvocation_4abf425c41 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void shouldPauseInvocation_whenNotResumable_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(false)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoLongRunningToolIds_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoFunctionCalls_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndNoMatchingFunctionCallId_isFalse() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc2"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isFalse(); +} +" + "@Test +public void shouldPauseInvocation_whenResumableAndMatchingFunctionCallId_isTrue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).agent(mockAgent).session(session).resumabilityConfig(new ResumabilityConfig(true)).build(); + Event event = Event.builder().longRunningToolIds(Optional.of(ImmutableSet.of("fc1"))).content(Content.builder().parts(ImmutableList.of(Part.builder().functionCall(FunctionCall.builder().name("tool1").id("fc1").build()).build())).build()).build(); + assertThat(context.shouldPauseInvocation(event)).isTrue(); +} +"Scenario 1: Resumable context with multiple function calls where only one matches a long-running tool ID + +Details: + TestName: shouldPauseInvocation_whenResumableAndOneOfMultipleFunctionCallsMatchesLongRunningToolId_isTrue + Description: Verifies that when the context is resumable, there are multiple function calls in the event, + and at least one function call ID matches a long-running tool ID, the method returns true. + This validates the anyMatch logic: even with multiple function calls, a single match is sufficient + to pause the invocation. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing only "fc2". + - Build the Event content with two function calls: one with id "fc1" (name "tool1") and one with id "fc2" (name "tool2"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is true. +Validation: + The assertion confirms that the anyMatch logic correctly identifies a match when at least one of multiple + function call IDs is present in the longRunningToolIds set. This is important for scenarios where an + agent makes multiple tool calls simultaneously and only some are long-running. + +--- + +Scenario 2: Resumable context with multiple function calls where all match long-running tool IDs + +Details: + TestName: shouldPauseInvocation_whenResumableAndAllFunctionCallsMatchLongRunningToolIds_isTrue + Description: Verifies that when the context is resumable and all function call IDs in the event match + entries in the longRunningToolIds set, the method returns true. This checks the positive + case for complete overlap between function calls and long-running tools. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc1" and "fc2". + - Build the Event content with two function calls: one with id "fc1" (name "tool1") and one with id "fc2" (name "tool2"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is true. +Validation: + Confirms that when every function call is long-running, the method still returns true (not just for partial + matches). This ensures robustness when an agent invokes multiple long-running tools at the same time. + +--- + +Scenario 3: Resumable context with an empty longRunningToolIds set (explicitly provided as empty) + +Details: + TestName: shouldPauseInvocation_whenResumableAndLongRunningToolIdsExplicitlyEmpty_isFalse + Description: Verifies that when the context is resumable and the event's longRunningToolIds is present + but explicitly set to an empty ImmutableSet, the method returns false. This tests the branch + where longRunningToolIds is present but empty. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds set to Optional.of(ImmutableSet.of()) (empty set). + - Build the Event content with a function call with id "fc1" (name "tool1"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Confirms that an explicitly empty longRunningToolIds set causes an early return of false, even if function + calls exist. This is consistent with the isEmpty() guard in the method implementation, preventing + unnecessary stream operations. + +--- + +Scenario 4: Resumable context with function calls that have no IDs (empty Optional IDs) + +Details: + TestName: shouldPauseInvocation_whenResumableAndFunctionCallsHaveNoIds_isFalse + Description: Verifies that when the context is resumable, longRunningToolIds is non-empty, but all + function calls in the event have no IDs (empty Optional), the method returns false. + This tests the flatMap(Optional::stream) logic that filters out absent IDs. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc1". + - Build the Event content with a function call that has no id set (id is absent/empty Optional). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Confirms that function calls without IDs are correctly filtered out by the flatMap(Optional::stream) + step, and do not accidentally match any long-running tool IDs. This is critical for handling + incomplete or malformed event data gracefully. + +--- + +Scenario 5: Resumable context with a mix of function calls with and without IDs, none matching + +Details: + TestName: shouldPauseInvocation_whenResumableAndMixedFunctionCallIdPresenceWithNoMatch_isFalse + Description: Verifies that when some function calls have IDs and some do not, and none of the present + IDs match the longRunningToolIds, the method returns false. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc99". + - Build the Event content with two function calls: one with id "fc1" and one with no id. + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Ensures correct behavior when the event contains heterogeneous function calls (some with IDs, some without), + and none of the IDs match. Validates both the Optional filtering and the non-matching scenario together. + +--- + +Scenario 6: Resumable context with a mix of function calls with and without IDs, one matching + +Details: + TestName: shouldPauseInvocation_whenResumableAndMixedFunctionCallIdPresenceWithOneMatch_isTrue + Description: Verifies that when some function calls have IDs and some do not, and at least one of the + present IDs matches a longRunningToolId, the method returns true. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc1". + - Build the Event content with two function calls: one with id "fc1" (name "tool1") and one with no id. + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is true. +Validation: + Confirms that the presence of function calls with absent IDs does not interfere with the correct + identification of a matching function call ID. This validates the robustness of the stream pipeline + in mixed-data scenarios. + +--- + +Scenario 7: Resumable context with a single matching function call and multiple long-running tool IDs + +Details: + TestName: shouldPauseInvocation_whenResumableAndSingleFunctionCallMatchesOneOfMultipleLongRunningToolIds_isTrue + Description: Verifies that when there is only one function call and its ID matches one of several entries + in the longRunningToolIds set, the method returns true. This checks the contains() logic + against a multi-entry set. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc1", "fc2", and "fc3". + - Build the Event content with a single function call with id "fc2" (name "tool2"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is true. +Validation: + Confirms that a single function call can pause the invocation when it matches any one of multiple + long-running tool IDs. This verifies the contains() check against an ImmutableSet with multiple entries. + +--- + +Scenario 8: Not resumable context, event has both long-running tool IDs and matching function calls + +Details: + TestName: shouldPauseInvocation_whenNotResumableEvenWithLongRunningToolIdsAndMatchingFunctionCalls_isFalse + Description: Verifies that even when the event has long-running tool IDs and matching function calls, + if the context is not resumable (ResumabilityConfig set to false), the method immediately + returns false without evaluating tool IDs or function calls. This tests the short-circuit + behavior of the isResumable() guard. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(false). + - Build an Event with longRunningToolIds containing "fc1" and "fc2". + - Build the Event content with function calls for both "fc1" and "fc2". + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Confirms that the isResumable() guard is the first and most decisive check in the method. Regardless + of the event's content, a non-resumable context will never trigger a pause. This is important for + ensuring non-resumable workflows are not inadvertently interrupted. + +--- + +Scenario 9: Resumable context with default ResumabilityConfig (no explicit setting) + +Details: + TestName: shouldPauseInvocation_whenDefaultResumabilityConfigAndMatchingFunctionCall_behavesAccordingToDefault + Description: Verifies the behavior of shouldPauseInvocation when the InvocationContext is built with + a default ResumabilityConfig (no explicit resumabilityConfig set in the builder). The + result should reflect the default value of isResumable() as defined by ResumabilityConfig's + default constructor. +Execution: + Arrange: + - Create an InvocationContext using the builder without explicitly setting resumabilityConfig + (relying on the default new ResumabilityConfig() set in the Builder class). + - Build an Event with longRunningToolIds containing "fc1". + - Build the Event content with a function call with id "fc1" (name "tool1"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result matches the expected default behavior of ResumabilityConfig (e.g., false + if the default is non-resumable, or true if the default is resumable). +Validation: + Tests the default path for ResumabilityConfig to ensure the builder's default initialization does not + cause unexpected behavior. This is relevant for clients who do not explicitly configure resumability. + +--- + +Scenario 10: Resumable context with longRunningToolIds absent (Optional.empty()) in the event + +Details: + TestName: shouldPauseInvocation_whenResumableAndLongRunningToolIdsAbsent_isFalse + Description: Verifies that when the context is resumable but the event's longRunningToolIds is + Optional.empty() (not present at all, using the orElse(ImmutableSet.of()) fallback), + the method returns false. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event without setting longRunningToolIds (so it defaults to Optional.empty()). + - Build the Event content with a function call with id "fc1" (name "tool1"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Confirms that the orElse(ImmutableSet.of()) fallback for an absent longRunningToolIds correctly + results in an empty set, triggering the isEmpty() guard and returning false. This is the expected + behavior for events that do not involve any long-running tools. + +--- + +Scenario 11: Resumable context, event has function calls but longRunningToolIds contains unrelated IDs + +Details: + TestName: shouldPauseInvocation_whenResumableAndLongRunningToolIdsContainOnlyUnrelatedIds_isFalse + Description: Verifies that when the context is resumable, the event has function calls with valid IDs, + but the longRunningToolIds set contains completely different IDs that do not match any + function call, the method returns false. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc10", "fc20", "fc30". + - Build the Event content with function calls having ids "fc1", "fc2", "fc3". + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Confirms that the anyMatch predicate correctly returns false when there is no overlap between the + function call IDs and the long-running tool IDs. This validates the correctness of the contains() + check in the anyMatch predicate for a completely disjoint set scenario. + +--- + +Scenario 12: Resumable context, event has a single function call with exact case-sensitive match + +Details: + TestName: shouldPauseInvocation_whenResumableAndFunctionCallIdIsCaseSensitiveMatch_isTrue + Description: Verifies that the matching between function call IDs and longRunningToolIds is performed + using exact string equality (case-sensitive). A function call with id "FC1" should not + match a longRunningToolId of "fc1". +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing "fc1" (lowercase). + - Build the Event content with a function call with id "FC1" (uppercase). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is false. +Validation: + Validates that the ID matching is case-sensitive, as ImmutableSet.contains() uses equals() for + comparison. This is important to ensure that tool IDs are treated as exact identifiers, preventing + accidental matches due to case differences. + +--- + +Scenario 13: Resumable context with a single function call ID that exactly matches the only long-running tool ID (boundary condition) + +Details: + TestName: shouldPauseInvocation_whenResumableAndSingleFunctionCallIdExactlyMatchesSingleLongRunningToolId_isTrue + Description: Tests the most basic positive case: exactly one function call, exactly one long-running + tool ID, and they match. This is the minimal boundary condition for a true result. +Execution: + Arrange: + - Create an InvocationContext with resumabilityConfig set to new ResumabilityConfig(true). + - Build an Event with longRunningToolIds containing exactly one ID: "tool-abc-123". + - Build the Event content with exactly one function call with id "tool-abc-123" (name "toolAbc"). + Act: + - Call context.shouldPauseInvocation(event). + Assert: + - Assert that the result is true. +Validation: + Confirms the most direct and minimal true scenario. This test is significant because it validates the + core matching logic with no ambiguity from multiple entries, ensuring the fundamental positive path works. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.events.Event; +import com.google.adk.flows.llmflows.ResumabilityConfig; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.common.collect.ImmutableSet; +import com.google.genai.types.FunctionCall; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextShouldPauseInvocationTest { + + @Mock + private BaseSessionService sessionService; + + @Mock + private BaseArtifactService artifactService; + + @Mock + private BaseMemoryService memoryService; + + @Mock + private BaseAgent agent; + + @Mock + private Session session; + + @Mock + private RunConfig runConfig; + + @BeforeEach + void setUp() { + when(session.appName()).thenReturn("testApp"); + when(session.userId()).thenReturn("testUser"); + } + + private InvocationContext buildContext(ResumabilityConfig resumabilityConfig) { + return InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .runConfig(runConfig) + .resumabilityConfig(resumabilityConfig) + .build(); + } + + private FunctionCall buildFunctionCall(String name, String id) { + return FunctionCall.builder().setName(name).setId(id).build(); + } + + private FunctionCall buildFunctionCallWithoutId(String name) { + return FunctionCall.builder().setName(name).build(); + } + + private Event buildEventWithLongRunningToolIds(ImmutableSet longRunningToolIds, + List functionCalls) { + Event mockEvent = mock(Event.class); + when(mockEvent.longRunningToolIds()).thenReturn(Optional.of(longRunningToolIds)); + when(mockEvent.functionCalls()).thenReturn(functionCalls); + return mockEvent; + } + + private Event buildEventWithAbsentLongRunningToolIds(List functionCalls) { + Event mockEvent = mock(Event.class); + when(mockEvent.longRunningToolIds()).thenReturn(Optional.empty()); + when(mockEvent.functionCalls()).thenReturn(functionCalls); + return mockEvent; + } + + @Test + @Tag("valid") + void shouldPauseInvocation_whenResumableAndOneOfMultipleFunctionCallsMatchesLongRunningToolId_isTrue() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + FunctionCall fc2 = buildFunctionCall("tool2", "fc2"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc2"), Arrays.asList(fc1, fc2)); + boolean result = context.shouldPauseInvocation(event); + assertTrue(result); + } + + @Test + @Tag("valid") + void shouldPauseInvocation_whenResumableAndAllFunctionCallsMatchLongRunningToolIds_isTrue() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + FunctionCall fc2 = buildFunctionCall("tool2", "fc2"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1", "fc2"), Arrays.asList(fc1, fc2)); + boolean result = context.shouldPauseInvocation(event); + assertTrue(result); + } + + @Test + @Tag("boundary") + void shouldPauseInvocation_whenResumableAndLongRunningToolIdsExplicitlyEmpty_isFalse() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of(), Collections.singletonList(fc1)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("invalid") + void shouldPauseInvocation_whenResumableAndFunctionCallsHaveNoIds_isFalse() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fcNoId = buildFunctionCallWithoutId("tool1"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1"), Collections.singletonList(fcNoId)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("invalid") + void shouldPauseInvocation_whenResumableAndMixedFunctionCallIdPresenceWithNoMatch_isFalse() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fcWithId = buildFunctionCall("tool1", "fc1"); + FunctionCall fcWithoutId = buildFunctionCallWithoutId("tool2"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc99"), Arrays.asList(fcWithId, fcWithoutId)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("valid") + void shouldPauseInvocation_whenResumableAndMixedFunctionCallIdPresenceWithOneMatch_isTrue() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fcWithId = buildFunctionCall("tool1", "fc1"); + FunctionCall fcWithoutId = buildFunctionCallWithoutId("tool2"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1"), Arrays.asList(fcWithId, fcWithoutId)); + boolean result = context.shouldPauseInvocation(event); + assertTrue(result); + } + + @Test + @Tag("valid") + void shouldPauseInvocation_whenResumableAndSingleFunctionCallMatchesOneOfMultipleLongRunningToolIds_isTrue() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fc2 = buildFunctionCall("tool2", "fc2"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1", "fc2", "fc3"), + Collections.singletonList(fc2)); + boolean result = context.shouldPauseInvocation(event); + assertTrue(result); + } + + @Test + @Tag("invalid") + void shouldPauseInvocation_whenNotResumableEvenWithLongRunningToolIdsAndMatchingFunctionCalls_isFalse() { + InvocationContext context = buildContext(new ResumabilityConfig(false)); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + FunctionCall fc2 = buildFunctionCall("tool2", "fc2"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1", "fc2"), Arrays.asList(fc1, fc2)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("boundary") + void shouldPauseInvocation_whenDefaultResumabilityConfigAndMatchingFunctionCall_behavesAccordingToDefault() { + InvocationContext context = InvocationContext.builder() + .sessionService(sessionService) + .artifactService(artifactService) + .memoryService(memoryService) + .invocationId("test-invocation-id") + .agent(agent) + .session(session) + .runConfig(runConfig) + .build(); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1"), Collections.singletonList(fc1)); + boolean result = context.shouldPauseInvocation(event); + ResumabilityConfig defaultConfig = new ResumabilityConfig(); + boolean expectedDefault = defaultConfig.isResumable(); + if (expectedDefault) { + assertTrue(result); + } + else { + assertFalse(result); + } + } + + @Test + @Tag("boundary") + void shouldPauseInvocation_whenResumableAndLongRunningToolIdsAbsent_isFalse() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + Event event = buildEventWithAbsentLongRunningToolIds(Collections.singletonList(fc1)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("invalid") + void shouldPauseInvocation_whenResumableAndLongRunningToolIdsContainOnlyUnrelatedIds_isFalse() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fc1 = buildFunctionCall("tool1", "fc1"); + FunctionCall fc2 = buildFunctionCall("tool2", "fc2"); + FunctionCall fc3 = buildFunctionCall("tool3", "fc3"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc10", "fc20", "fc30"), + Arrays.asList(fc1, fc2, fc3)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("boundary") + void shouldPauseInvocation_whenResumableAndFunctionCallIdIsCaseSensitiveMatch_isTrue() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fcUpperCase = buildFunctionCall("tool1", "FC1"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("fc1"), Collections.singletonList(fcUpperCase)); + boolean result = context.shouldPauseInvocation(event); + assertFalse(result); + } + + @Test + @Tag("valid") + void shouldPauseInvocation_whenResumableAndSingleFunctionCallIdExactlyMatchesSingleLongRunningToolId_isTrue() { + InvocationContext context = buildContext(new ResumabilityConfig(true)); + FunctionCall fcAbc = buildFunctionCall("toolAbc", "tool-abc-123"); + Event event = buildEventWithLongRunningToolIds(ImmutableSet.of("tool-abc-123"), + Collections.singletonList(fcAbc)); + boolean result = context.shouldPauseInvocation(event); + assertTrue(result); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextUserContentTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextUserContentTest.java new file mode 100644 index 000000000..d84e19089 --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextUserContentTest.java @@ -0,0 +1,635 @@ +/* + * 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=userContent_84fbf4a756 +ROOST_METHOD_SIG_HASH=userContent_7428a149e0 + +Here are your existing test cases which we found out and are not considered for test generation: + +File Path: /var/tmp/Roost/RoostGPT/june-java-unit/1782282457/source/adk-java/core/src/test/java/com/google/adk/agents/InvocationContextTest.java +Tests: + "@Test +public void testCreateWithUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCreateWithNullUserContent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.userContent()).isEmpty(); +} +" + "@Test +public void testCreateWithLiveRequestQueue() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotNull(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).hasValue(liveRequestQueue); + + assertThat(context.invocationId()).startsWith("e-"); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).isEmpty(); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testCopyOf() { + InvocationContext originalContext = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + originalContext.activeStreamingTools().putAll(activeStreamingTools); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertThat(copiedContext).isNotNull(); + assertThat(copiedContext).isNotSameInstanceAs(originalContext); + assertThat(copiedContext.sessionService()).isEqualTo(originalContext.sessionService()); + assertThat(copiedContext.artifactService()).isEqualTo(originalContext.artifactService()); + assertThat(copiedContext.memoryService()).isEqualTo(originalContext.memoryService()); + assertThat(copiedContext.liveRequestQueue()).isEqualTo(originalContext.liveRequestQueue()); + assertThat(copiedContext.invocationId()).isEqualTo(originalContext.invocationId()); + assertThat(copiedContext.agent()).isEqualTo(originalContext.agent()); + assertThat(copiedContext.session()).isEqualTo(originalContext.session()); + assertThat(copiedContext.userContent()).isEqualTo(originalContext.userContent()); + assertThat(copiedContext.runConfig()).isEqualTo(originalContext.runConfig()); + assertThat(copiedContext.endInvocation()).isEqualTo(originalContext.endInvocation()); + assertThat(copiedContext.activeStreamingTools()).isEqualTo(originalContext.activeStreamingTools()); +} +" + "@Test +public void testGetters() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.sessionService()).isEqualTo(mockSessionService); + assertThat(context.artifactService()).isEqualTo(mockArtifactService); + assertThat(context.memoryService()).isEqualTo(mockMemoryService); + assertThat(context.liveRequestQueue()).isEmpty(); + assertThat(context.invocationId()).isEqualTo(testInvocationId); + assertThat(context.agent()).isEqualTo(mockAgent); + assertThat(context.session()).isEqualTo(session); + assertThat(context.userContent()).hasValue(userContent); + assertThat(context.runConfig()).isEqualTo(runConfig); + assertThat(context.endInvocation()).isFalse(); +} +" + "@Test +public void testSetAgent() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + BaseAgent newMockAgent = mock(BaseAgent.class); + context.agent(newMockAgent); + assertThat(context.agent()).isEqualTo(newMockAgent); +} +" + "@Test +public void testEquals_sameObject() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(context)).isTrue(); +} +" + "@Test +public void testEquals_null() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(null)).isFalse(); +} +" + "@Test +public void testEquals_sameValues() { + InvocationContext context1 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext context2 = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context1.equals(context2)).isTrue(); + + assertThat(context2.equals(context1)).isTrue(); +} +" + "@Test +public void testEquals_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffAgent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent( + mock(BaseAgent.class)).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithUserContentEmpty = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithLiveQueuePresent = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).liveRequestQueue(liveRequestQueue).agent(mockAgent).session(session).userContent(Optional.empty()).runConfig(runConfig).endInvocation(false).build(); + assertThat(context.equals(contextWithDiffSessionService)).isFalse(); + assertThat(context.equals(contextWithDiffInvocationId)).isFalse(); + assertThat(context.equals(contextWithDiffAgent)).isFalse(); + assertThat(context.equals(contextWithUserContentEmpty)).isFalse(); + assertThat(context.equals(contextWithLiveQueuePresent)).isFalse(); +} +" + "@Test +public void testHashCode_differentValues() { + InvocationContext context = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + + InvocationContext contextWithDiffSessionService = InvocationContext.builder().sessionService( + mock(BaseSessionService.class)).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId(testInvocationId).agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + InvocationContext contextWithDiffInvocationId = InvocationContext.builder().sessionService(mockSessionService).artifactService(mockArtifactService).memoryService(mockMemoryService).pluginManager(pluginManager).invocationId( + "another-id").agent(mockAgent).session(session).userContent(Optional.of(userContent)).runConfig(runConfig).endInvocation(false).build(); + assertThat(context).isNotEqualTo(contextWithDiffSessionService); + assertThat(context).isNotEqualTo(contextWithDiffInvocationId); +} +"Scenario 1: Verify that userContent() Returns a Present Optional When Content Is Set + +Details: + TestName: userContentReturnsPresentOptionalWhenContentIsSet + Description: Verifies that the userContent() method returns an Optional containing the Content object + when the InvocationContext is built with a non-null Content value supplied via + Optional.of(userContent). +Execution: + Arrange: Create a Content object (userContent). Build an InvocationContext using the builder, + supplying sessionService, artifactService, memoryService, pluginManager, invocationId, + agent, session, runConfig, endInvocation(false), and userContent(Optional.of(userContent)). + Act: Call context.userContent() on the built InvocationContext. + Assert: Assert that the returned Optional is not empty and that its value equals the original + Content object used during construction. +Validation: + This assertion confirms that when a valid Content object is provided during construction, + the userContent() accessor faithfully wraps and returns it inside a present Optional. + This is critical for downstream components that rely on the presence of user-supplied content + to drive agent behavior. + + +Scenario 2: Verify that userContent() Returns an Empty Optional When No Content Is Provided + +Details: + TestName: userContentReturnsEmptyOptionalWhenNotSet + Description: Verifies that the userContent() method returns Optional.empty() when the + InvocationContext is constructed with Optional.empty() as the user content. +Execution: + Arrange: Build an InvocationContext using the builder with all required fields and + userContent(Optional.empty()). + Act: Call context.userContent() on the built InvocationContext. + Assert: Assert that the returned Optional isEmpty(). +Validation: + Confirms that when no user content is provided, the accessor correctly returns an empty + Optional rather than null or a present Optional. This prevents NullPointerExceptions in + callers that use Optional.isPresent() or Optional.ifPresent() patterns. + + +Scenario 3: Verify that userContent() Does Not Return Null + +Details: + TestName: userContentNeverReturnsNull + Description: Verifies that the userContent() method never returns a null reference, + regardless of whether content was set or not, ensuring safe Optional usage. +Execution: + Arrange: Build an InvocationContext using the builder with userContent(Optional.empty()). + Act: Call context.userContent() on the built InvocationContext. + Assert: Assert that the result of context.userContent() is not null. +Validation: + Ensures the method contract — returning Optional rather than a raw nullable reference — is + respected. Callers should always receive a non-null Optional, which is the fundamental promise + of this return type. + + +Scenario 4: Verify that userContent() Returns the Same Content Instance That Was Provided + +Details: + TestName: userContentReturnsSameContentInstance + Description: Verifies that the Content instance returned inside the Optional from userContent() + is the same object reference that was supplied to the builder. +Execution: + Arrange: Create a specific Content object. Build an InvocationContext with + userContent(Optional.of(thatContentObject)). + Act: Call context.userContent() and extract the value via .get(). + Assert: Assert that the extracted Content instance is the same reference (using isSameInstanceAs + or assertEquals) as the original Content object provided at construction time. +Validation: + Confirms no defensive copying or transformation occurs during storage or retrieval of the + userContent field. The method should return the exact same object, ensuring identity integrity + for downstream processing pipelines. + + +Scenario 5: Verify that userContent() Is Consistent Across Multiple Calls (Idempotency) + +Details: + TestName: userContentIsIdempotentAcrossMultipleCalls + Description: Verifies that calling userContent() multiple times on the same InvocationContext + instance always returns the same Optional value, demonstrating that the field + is immutable and the accessor is side-effect free. +Execution: + Arrange: Build an InvocationContext with a non-null Content object supplied as userContent. + Act: Call context.userContent() three times and store each result. + Assert: Assert that all three returned Optionals are equal to each other, and each contains + a value equal to the original Content object. +Validation: + Since userContent is declared as private final, repeated calls must return the same result. + This test guards against any accidental mutation or lazy-initialization logic that could cause + inconsistent behavior across multiple reads. + + +Scenario 6: Verify that userContent() Returns Present Optional When Built Using Content Directly (Non-Optional Builder Method) + +Details: + TestName: userContentReturnsPresentOptionalWhenBuiltWithContentDirectly + Description: Verifies that the userContent() method returns a present Optional when the + InvocationContext is built using the builder's userContent(Content) overload + (which wraps the content in Optional.of internally) instead of the + userContent(Optional) overload. +Execution: + Arrange: Create a Content object. Build an InvocationContext using + builder().userContent(contentObject) (the non-Optional overload). + Act: Call context.userContent() on the built context. + Assert: Assert that the returned Optional hasValue(contentObject) and is not empty. +Validation: + Confirms that both builder overloads — userContent(Content) and userContent(Optional) — + produce an equivalent and consistent state accessible via userContent(). This ensures API + usability and prevents silent differences between the two construction paths. + + +Scenario 7: Verify that userContent() Reflects the Default Empty State When Builder Sets No User Content + +Details: + TestName: userContentDefaultsToEmptyOptionalWhenNotSetOnBuilder + Description: Verifies that when the builder does not explicitly call userContent(...), the + resulting InvocationContext has an empty Optional returned by userContent(), + confirming the builder's default value is Optional.empty(). +Execution: + Arrange: Build an InvocationContext using the builder but intentionally omit any call to + userContent(...), supplying only the other required fields (sessionService, + artifactService, agent, session, etc.). + Act: Call context.userContent() on the built InvocationContext. + Assert: Assert that the returned Optional isEmpty(). +Validation: + Validates the default initialization contract of the Builder class, where userContent defaults + to Optional.empty(). This protects against regressions where the default might accidentally + be changed, which could cause NullPointerExceptions or incorrect behavior in agents that check + for the absence of user content. + + +Scenario 8: Verify that userContent() from a Copied Context Returns the Same Value as the Original + +Details: + TestName: userContentInCopiedContextMatchesOriginal + Description: Verifies that after using InvocationContext.copyOf(), the copied context's + userContent() method returns a value equal to that of the original context. +Execution: + Arrange: Build an original InvocationContext with a specific Content object as userContent. + Create a copy using InvocationContext.copyOf(originalContext). + Act: Call userContent() on both the original and the copied context. + Assert: Assert that copiedContext.userContent() equals originalContext.userContent(), and + that the Optional in the copy contains the same Content value. +Validation: + Ensures that the shallow copy operation preserves the userContent field correctly. This is + important for sub-agent delegation scenarios, where a copied context must carry the original + user's input without alteration. + + +Scenario 9: Verify that userContent() Is Independent Between Two Separately Built Contexts + +Details: + TestName: userContentIsIndependentBetweenTwoContextInstances + Description: Verifies that two InvocationContext instances built with different userContent + values each independently return their own respective user content without + interference. +Execution: + Arrange: Create two distinct Content objects (contentA and contentB). Build contextA with + userContent(Optional.of(contentA)) and contextB with userContent(Optional.of(contentB)). + Act: Call userContent() on contextA and contextB separately. + Assert: Assert that contextA.userContent() contains contentA and contextB.userContent() + contains contentB. Assert they are not equal to each other. +Validation: + Confirms that InvocationContext instances are independent and do not share state for the + userContent field. This is essential in concurrent or multi-agent scenarios where different + invocations must not bleed user content into one another. + + +Scenario 10: Verify that userContent() Returns Present Optional When One Context Has Content and Another Does Not + +Details: + TestName: userContentPresentInOneContextAndEmptyInAnother + Description: Verifies that two contexts built differently — one with user content and one + without — each return the correct Optional state from userContent(), confirming + no shared mutable state exists between instances. +Execution: + Arrange: Build contextWithContent using userContent(Optional.of(someContent)). + Build contextWithoutContent using userContent(Optional.empty()). + Act: Call userContent() on both contexts. + Assert: Assert that contextWithContent.userContent() isPresent() and + contextWithoutContent.userContent() isEmpty(). +Validation: + This scenario reinforces isolation between InvocationContext instances and validates that the + presence or absence of user content is a property strictly tied to how each individual context + was initialized, with no cross-contamination between instances. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import com.google.genai.types.Part; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextUserContentTest { + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private Session mockSession; + + @Mock + private BaseAgent mockAgent; + + private RunConfig runConfig; + + private Content sampleContent; + + @BeforeEach + void setUp() { + runConfig = RunConfig.builder().build(); + sampleContent = Content.builder().role("user").parts(List.of(Part.fromText("Hello, world!"))).build(); + } + + private InvocationContext.Builder baseBuilder() { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .runConfig(runConfig) + .endInvocation(false); + } + + @Test + @Tag("valid") + void userContentReturnsPresentOptionalWhenContentIsSet() { + // Arrange + InvocationContext context = baseBuilder().userContent(Optional.of(sampleContent)).build(); + // Act + Optional result = context.userContent(); + // Assert + assertTrue(result.isPresent(), "Expected userContent Optional to be present"); + assertEquals(sampleContent, result.get(), "Expected userContent to equal the provided Content object"); + } + + @Test + @Tag("valid") + void userContentReturnsEmptyOptionalWhenNotSet() { + // Arrange + InvocationContext context = baseBuilder().userContent(Optional.empty()).build(); + // Act + Optional result = context.userContent(); + // Assert + assertTrue(result.isEmpty(), "Expected userContent Optional to be empty when no content is provided"); + } + + @Test + @Tag("boundary") + void userContentNeverReturnsNull() { + // Arrange + InvocationContext context = baseBuilder().userContent(Optional.empty()).build(); + // Act + Optional result = context.userContent(); + // Assert + assertNotNull(result, "userContent() must never return null; it should return Optional.empty() instead"); + } + + @Test + @Tag("valid") + void userContentReturnsSameContentInstance() { + // Arrange + Content specificContent = Content.builder() + .role("user") + .parts(List.of(Part.fromText("Specific content for identity check"))) + .build(); + InvocationContext context = baseBuilder().userContent(Optional.of(specificContent)).build(); + // Act + Content retrievedContent = context.userContent().get(); + // Assert + assertSame(specificContent, retrievedContent, + "userContent() should return the exact same Content instance that was provided at construction"); + } + + @Test + @Tag("valid") + void userContentIsIdempotentAcrossMultipleCalls() { + // Arrange + InvocationContext context = baseBuilder().userContent(Optional.of(sampleContent)).build(); + // Act + Optional result1 = context.userContent(); + Optional result2 = context.userContent(); + Optional result3 = context.userContent(); + // Assert + assertEquals(result1, result2, "First and second calls to userContent() should return equal Optionals"); + assertEquals(result2, result3, "Second and third calls to userContent() should return equal Optionals"); + assertTrue(result1.isPresent(), "All calls should return a present Optional"); + assertEquals(sampleContent, result1.get(), "All calls should contain the original Content object"); + assertEquals(sampleContent, result2.get(), "All calls should contain the original Content object"); + assertEquals(sampleContent, result3.get(), "All calls should contain the original Content object"); + } + + @Test + @Tag("valid") + void userContentReturnsPresentOptionalWhenBuiltWithContentDirectly() { + // Arrange + Content contentObject = Content.builder().role("user").parts(List.of(Part.fromText("Direct content"))).build(); + InvocationContext context = baseBuilder().userContent(contentObject).build(); + // Act + Optional result = context.userContent(); + // Assert + assertTrue(result.isPresent(), + "Expected userContent to be present when built using the Content (non-Optional) builder overload"); + assertEquals(contentObject, result.get(), + "Expected retrieved content to equal the content object passed directly to builder"); + } + + @Test + @Tag("boundary") + void userContentDefaultsToEmptyOptionalWhenNotSetOnBuilder() { + // Arrange - intentionally omit userContent call on builder + InvocationContext context = InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-no-content") + .agent(mockAgent) + .session(mockSession) + .runConfig(runConfig) + .endInvocation(false) + .build(); + // Act + Optional result = context.userContent(); + // Assert + assertTrue(result.isEmpty(), + "When no userContent is set on builder, userContent() should return Optional.empty()"); + } + + @Test + @Tag("integration") + void userContentInCopiedContextMatchesOriginal() { + // Arrange + Content originalContent = Content.builder() + .role("user") + .parts(List.of(Part.fromText("Original user content"))) + .build(); + InvocationContext originalContext = baseBuilder().userContent(Optional.of(originalContent)).build(); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + // Assert + assertEquals(originalContext.userContent(), copiedContext.userContent(), + "Copied context's userContent should equal the original context's userContent"); + assertTrue(copiedContext.userContent().isPresent(), "Copied context's userContent should be present"); + assertEquals(originalContent, copiedContext.userContent().get(), + "Copied context's userContent value should equal the original Content object"); + } + + @Test + @Tag("valid") + void userContentIsIndependentBetweenTwoContextInstances() { + // Arrange + Content contentA = Content.builder().role("user").parts(List.of(Part.fromText("Content A"))).build(); + Content contentB = Content.builder().role("model").parts(List.of(Part.fromText("Content B"))).build(); + InvocationContext contextA = baseBuilder().invocationId("invocation-a") + .userContent(Optional.of(contentA)) + .build(); + InvocationContext contextB = baseBuilder().invocationId("invocation-b") + .userContent(Optional.of(contentB)) + .build(); + // Act + Optional resultA = contextA.userContent(); + Optional resultB = contextB.userContent(); + // Assert + assertTrue(resultA.isPresent(), "contextA's userContent should be present"); + assertTrue(resultB.isPresent(), "contextB's userContent should be present"); + assertEquals(contentA, resultA.get(), "contextA should contain contentA"); + assertEquals(contentB, resultB.get(), "contextB should contain contentB"); + assertNotEquals(resultA, resultB, + "The two contexts should return different userContent values, confirming independence"); + } + + @Test + @Tag("valid") + void userContentPresentInOneContextAndEmptyInAnother() { + // Arrange + Content someContent = Content.builder() + .role("user") + .parts(List.of(Part.fromText("Some content for context with content"))) + .build(); + InvocationContext contextWithContent = baseBuilder().invocationId("context-with-content") + .userContent(Optional.of(someContent)) + .build(); + InvocationContext contextWithoutContent = baseBuilder().invocationId("context-without-content") + .userContent(Optional.empty()) + .build(); + // Act + Optional resultWithContent = contextWithContent.userContent(); + Optional resultWithoutContent = contextWithoutContent.userContent(); + // Assert + assertTrue(resultWithContent.isPresent(), "contextWithContent should have a present userContent Optional"); + assertTrue(resultWithoutContent.isEmpty(), "contextWithoutContent should have an empty userContent Optional"); + assertEquals(someContent, resultWithContent.get(), + "contextWithContent should contain the provided someContent"); + } + + @Test + @Tag("valid") + void userContentReturnedFromStaticCreateMethod() { + // Arrange + Content contentForCreate = Content.builder() + .role("user") + .parts(List.of(Part.fromText("Content via static create"))) + .build(); + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "static-create-invocation-id", mockAgent, mockSession, contentForCreate, runConfig); + // Act + Optional result = context.userContent(); + // Assert + assertTrue(result.isPresent(), + "userContent should be present when created via static create method with non-null content"); + assertEquals(contentForCreate, result.get(), + "userContent should equal the Content provided to the static create method"); + } + + @Test + @Tag("boundary") + void userContentReturnsEmptyOptionalWhenNullPassedToStaticCreateMethod() { + // Arrange + InvocationContext context = InvocationContext.create(mockSessionService, mockArtifactService, + "invocation-null-content", mockAgent, mockSession, null, runConfig); + // Act + Optional result = context.userContent(); + // Assert + assertNotNull(result, "userContent() must not return null even when null was passed to create()"); + assertTrue(result.isEmpty(), "userContent should be empty when null content is passed to static create method"); + } + + @Test + @Tag("integration") + void userContentPreservedAfterCopyOfWithEmptyContent() { + // Arrange + InvocationContext originalContext = baseBuilder().userContent(Optional.empty()).build(); + // Act + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + // Assert + assertNotNull(copiedContext.userContent(), "Copied context's userContent() must not return null"); + assertTrue(copiedContext.userContent().isEmpty(), + "Copied context should also have empty userContent when original had empty userContent"); + assertEquals(originalContext.userContent(), copiedContext.userContent(), + "Copied context's userContent should equal the original's empty Optional"); + } + +} diff --git a/core/src/test/java/com/google/adk/agents/InvocationContextUserIdTest.java b/core/src/test/java/com/google/adk/agents/InvocationContextUserIdTest.java new file mode 100644 index 000000000..9f9c9e0cc --- /dev/null +++ b/core/src/test/java/com/google/adk/agents/InvocationContextUserIdTest.java @@ -0,0 +1,371 @@ +/* + * 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=userId_f2e833fd39 +ROOST_METHOD_SIG_HASH=userId_5053f72666 + +Scenario 1: Retrieve a Standard Alphanumeric User ID from the Session + +Details: + TestName: userIdReturnsValueFromSession + Description: Verifies that the `userId()` method correctly delegates to and returns + the user ID from the underlying `Session` object when a standard + alphanumeric user ID is set. + +Execution: + Arrange: - Create a mock of the `Session` class. + - Stub `session.userId()` to return a standard alphanumeric string, e.g., "user123". + - Build an `InvocationContext` instance using `InvocationContext.builder()` + and supply the mocked session via `.session(mockSession)`. + Act: - Call `invocationContext.userId()` on the built context. + Assert: - Use `assertEquals("user123", invocationContext.userId())` to verify the + returned value matches the stubbed session user ID. + +Validation: + The assertion confirms that `userId()` acts as a pure delegation to `session.userId()`, + returning whatever the session provides without any modification. This is critical + to ensure the `InvocationContext` correctly exposes session-level identity data + to any component that depends on it for authorization or personalization purposes. + +*/ + +// ********RoostGPT******** + +package com.google.adk.agents; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.google.adk.artifacts.BaseArtifactService; +import com.google.adk.memory.BaseMemoryService; +import com.google.adk.plugins.PluginManager; +import com.google.adk.sessions.BaseSessionService; +import com.google.adk.sessions.Session; +import com.google.genai.types.Content; +import java.util.Optional; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvocationContextUserIdTest { + + @Mock + private Session mockSession; + + @Mock + private BaseSessionService mockSessionService; + + @Mock + private BaseArtifactService mockArtifactService; + + @Mock + private BaseMemoryService mockMemoryService; + + @Mock + private PluginManager mockPluginManager; + + @Mock + private BaseAgent mockAgent; + + private RunConfig defaultRunConfig; + + @BeforeEach + void setUp() { + defaultRunConfig = RunConfig.builder().build(); + } + + private InvocationContext buildContext(Session session) { + return InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(session) + .runConfig(defaultRunConfig) + .build(); + } + + @Test + @Tag("valid") + void userIdReturnsValueFromSession() { + when(mockSession.userId()).thenReturn("user123"); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals("user123", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsAlphanumericUserId() { + when(mockSession.userId()).thenReturn("abc123XYZ"); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals("abc123XYZ", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsNumericOnlyUserId() { + when(mockSession.userId()).thenReturn("9876543210"); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals("9876543210", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsUuidFormattedUserId() { + String uuidUserId = "550e8400-e29b-41d4-a716-446655440000"; + when(mockSession.userId()).thenReturn(uuidUserId); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals(uuidUserId, invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsDelegatesExactlyToSession() { + String expectedUserId = "delegated_user_id"; + when(mockSession.userId()).thenReturn(expectedUserId); + InvocationContext invocationContext = buildContext(mockSession); + String actualUserId = invocationContext.userId(); + verify(mockSession, times(1)).userId(); + assertEquals(expectedUserId, actualUserId); + } + + @Test + @Tag("valid") + void userIdReturnsEmailFormattedUserId() { + String emailUserId = "user@example.com"; + when(mockSession.userId()).thenReturn(emailUserId); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals(emailUserId, invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsUserIdWithSpecialCharacters() { + String specialCharUserId = "user-name_123.test"; + when(mockSession.userId()).thenReturn(specialCharUserId); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals(specialCharUserId, invocationContext.userId()); + } + + @Test + @Tag("boundary") + void userIdReturnsSingleCharacterUserId() { + when(mockSession.userId()).thenReturn("u"); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals("u", invocationContext.userId()); + } + + @Test + @Tag("boundary") + void userIdReturnsVeryLongUserId() { + String longUserId = "u".repeat(1000); + when(mockSession.userId()).thenReturn(longUserId); + InvocationContext invocationContext = buildContext(mockSession); + assertNotNull(invocationContext.userId()); + assertEquals(1000, invocationContext.userId().length()); + assertEquals(longUserId, invocationContext.userId()); + } + + @Test + @Tag("boundary") + void userIdReturnsEmptyStringUserId() { + when(mockSession.userId()).thenReturn(""); + InvocationContext invocationContext = buildContext(mockSession); + assertNotNull(invocationContext.userId()); + assertEquals("", invocationContext.userId()); + } + + @Test + @Tag("invalid") + void userIdReturnsNullWhenSessionReturnsNull() { + when(mockSession.userId()).thenReturn(null); + InvocationContext invocationContext = buildContext(mockSession); + assertNull(invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdIsConsistentAcrossMultipleCalls() { + when(mockSession.userId()).thenReturn("consistentUser"); + InvocationContext invocationContext = buildContext(mockSession); + String firstCall = invocationContext.userId(); + String secondCall = invocationContext.userId(); + String thirdCall = invocationContext.userId(); + assertEquals(firstCall, secondCall); + assertEquals(secondCall, thirdCall); + assertEquals("consistentUser", firstCall); + } + + @Test + @Tag("integration") + void userIdIsAccessibleAfterCopyOf() { + when(mockSession.userId()).thenReturn("copiedUser"); + when(mockSession.appName()).thenReturn("testApp"); + InvocationContext originalContext = buildContext(mockSession); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertEquals("copiedUser", copiedContext.userId()); + } + + @Test + @Tag("integration") + void userIdReturnsCorrectValueAfterAgentChange() { + when(mockSession.userId()).thenReturn("user_with_agent_change"); + InvocationContext invocationContext = buildContext(mockSession); + invocationContext.agent(mockAgent); + assertEquals("user_with_agent_change", invocationContext.userId()); + } + + @Test + @Tag("integration") + void userIdReturnsCorrectValueAfterBranchSet() { + when(mockSession.userId()).thenReturn("user_with_branch"); + InvocationContext invocationContext = buildContext(mockSession); + invocationContext.branch("some-branch"); + assertEquals("user_with_branch", invocationContext.userId()); + } + + @Test + @Tag("integration") + void userIdReturnsCorrectValueWithMemoryService() { + when(mockSession.userId()).thenReturn("userWithMemory"); + InvocationContext invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .memoryService(mockMemoryService) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + assertEquals("userWithMemory", invocationContext.userId()); + } + + @Test + @Tag("integration") + void userIdReturnsCorrectValueWithPluginManager() { + when(mockSession.userId()).thenReturn("userWithPlugin"); + InvocationContext invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .pluginManager(mockPluginManager) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .runConfig(defaultRunConfig) + .build(); + assertEquals("userWithPlugin", invocationContext.userId()); + } + + @Test + @Tag("integration") + void userIdReturnsCorrectValueWithLiveRequestQueue() { + when(mockSession.userId()).thenReturn("liveUser"); + LiveRequestQueue liveRequestQueue = new LiveRequestQueue(); + InvocationContext invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .agent(mockAgent) + .session(mockSession) + .liveRequestQueue(Optional.of(liveRequestQueue)) + .runConfig(defaultRunConfig) + .build(); + assertEquals("liveUser", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsCorrectValueWithUserContent() { + when(mockSession.userId()).thenReturn("userWithContent"); + Content userContent = Content.builder().build(); + InvocationContext invocationContext = + InvocationContext.builder() + .sessionService(mockSessionService) + .artifactService(mockArtifactService) + .invocationId("test-invocation-id") + .agent(mockAgent) + .session(mockSession) + .userContent(Optional.of(userContent)) + .runConfig(defaultRunConfig) + .build(); + assertEquals("userWithContent", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdOnlyCallsSessionUserIdMethod() { + when(mockSession.userId()).thenReturn("verifyDelegation"); + InvocationContext invocationContext = buildContext(mockSession); + invocationContext.userId(); + verify(mockSession).userId(); + verifyNoMoreInteractions(mockSession); + } + + @Test + @Tag("boundary") + void userIdReturnsWhitespaceOnlyUserId() { + when(mockSession.userId()).thenReturn(" "); + InvocationContext invocationContext = buildContext(mockSession); + assertNotNull(invocationContext.userId()); + assertEquals(" ", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdMatchesSessionUserIdDirectly() { + String expectedUserId = "directUser42"; + when(mockSession.userId()).thenReturn(expectedUserId); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals(mockSession.userId(), invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsUserIdWithUnderscores() { + when(mockSession.userId()).thenReturn("user_name_123"); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals("user_name_123", invocationContext.userId()); + } + + @Test + @Tag("valid") + void userIdReturnsUpperCaseUserId() { + when(mockSession.userId()).thenReturn("UPPERCASE_USER"); + InvocationContext invocationContext = buildContext(mockSession); + assertEquals("UPPERCASE_USER", invocationContext.userId()); + } + + @Test + @Tag("integration") + void userIdReturnsSameValueForCopiedContextAndOriginal() { + when(mockSession.userId()).thenReturn("sharedUser"); + when(mockSession.appName()).thenReturn("testApp"); + InvocationContext originalContext = buildContext(mockSession); + InvocationContext copiedContext = InvocationContext.copyOf(originalContext); + assertEquals(originalContext.userId(), copiedContext.userId()); + } + +} diff --git a/pom.xml b/pom.xml index 6009c7316..24fd6ece6 100644 --- 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