Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0"?>
<!--
Copyright 2025 Google LLC

Expand All @@ -16,19 +16,15 @@
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>0.4.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>0.4.1-SNAPSHOT</version>
<!-- {x-version-update:google-adk:current} -->
</parent>

<artifactId>google-adk</artifactId>
<name>Agent Development Kit</name>
<description>Agent Development Kit: an open-source, code-first toolkit designed to simplify building, evaluating, and deploying advanced AI agents anywhere.</description>



<dependencies>
<dependency>
<groupId>com.anthropic</groupId>
Expand Down Expand Up @@ -201,6 +197,15 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.40</version>
<!--Plugin added by RoostGPT-->
</plugin>
</plugins>
<pluginManagement>
<plugins/>
</pluginManagement>
</build>
</project>
</project>
84 changes: 84 additions & 0 deletions core/src/test/java/com/google/adk/models/BuilderApiClientTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* 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 unit-java-adk using AI Type Open AI and AI Model gpt-5-nano

ROOST_METHOD_HASH=apiClient_c66ebe1d58
ROOST_METHOD_SIG_HASH=apiClient_d59e3a5ed5

Scenario 1: apiClient_setsExplicitClient

Details:
TestName: apiClient_setsExplicitClient
Description: Verify that calling apiClient with a non-null Client assigns the provided client to the builder and returns the same builder instance to support chaining.

Execution:
Arrange: Create a Gemini.Builder via Gemini.builder(); prepare a mock/stub Client instance named mockClient.
Act: Builder resultBuilder = builder.apiClient(mockClient);
Assert: Assert that resultBuilder is the same object instance as the original builder (reference equality); optionally verify that the builder can continue chaining by calling another method and ensuring no exception is thrown.
Validation: Ensures that the explicit client is stored in the builder and that the fluent API contract (returning this) is preserved, enabling method chaining.


*/

// ********RoostGPT********

package com.google.adk.models;

import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.mock;

import com.google.genai.Client;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

/** Test suite for Gemini.Builder.apiClient(Client apiClient) */
public class BuilderApiClientTest {

@Test
@Tag("valid")
public void testApiClientSetsExplicitClient() {
Gemini.Builder builder = Gemini.builder();
Client mockClient = mock(Client.class);
Gemini.Builder resultBuilder = builder.apiClient(mockClient);
// Ensure fluent API returns the same builder instance (enables chaining)
assertSame(builder, resultBuilder);
// Ensure chaining remains functional by calling another method on the same
// builder
Gemini.Builder chained = resultBuilder.modelName("test-model"); // TODO: adjust
// modelName as
// needed
assertSame(builder, chained);
}

@Test
@Tag("boundary")
public void testApiClientAcceptsNullClient() {
Gemini.Builder builder = Gemini.builder();
Gemini.Builder resultBuilder = builder.apiClient(null);
// Even with null input, the fluent API should return the same builder instance
assertSame(builder, resultBuilder);
// Chaining should continue to work with a null client
Gemini.Builder chained = resultBuilder.modelName("test-model-null"); // TODO:
// adjust
// modelName
// as
// needed
assertSame(builder, chained);
}
}
78 changes: 78 additions & 0 deletions core/src/test/java/com/google/adk/models/BuilderApiKeyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 unit-java-adk using AI Type Open AI and AI Model gpt-5-nano

ROOST_METHOD_HASH=apiKey_6f7fe65f1f
ROOST_METHOD_SIG_HASH=apiKey_f645a7d0cc

Scenario 1: Setting non-null apiKey stores the value and enables fluent chaining on the Builder
Details:
TestName: settingApiKeyStoresValue
Description: Verify that calling apiKey with a non-null string assigns that value to the builder's apiKey field and returns the same Builder instance to support method chaining.
Execution:
Arrange: Instantiate a new Gemini.Builder via Gemini.builder().
Act: Call builder.apiKey("my-api-key") and capture the returned reference.
Assert: The returned reference is the same instance as the original builder (identity check) to confirm fluent chaining is preserved.
Validation:
The assertion confirms fluent API usage for the Builder.apiKey method, ensuring subsequent builder methods can be chained without losing the current state.

*/

// ********RoostGPT********

package com.google.adk.models;

import static org.junit.jupiter.api.Assertions.assertSame;

import com.google.adk.models.Gemini.Builder;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

/** Tests for the nested Builder.apiKey(...) method on Gemini. */
public class BuilderApiKeyTest {

@Test
@Tag("valid")
public void testSettingApiKeyStoresValue() {
// Arrange
Builder builder = Gemini.builder();
// Act
Builder returned = builder.apiKey("TEST_API_KEY"); // TODO: replace with a real
// key if needed
// Assert
assertSame(
builder,
returned,
"apiKey(...) should return the same Builder instance to support fluent chaining.");
}

@Test
@Tag("boundary")
public void testSettingApiKeyWithNullKeepsChaining() {
// Arrange
Builder builder = Gemini.builder();
// Act
Builder returned = builder.apiKey(null);
// Assert
assertSame(
builder,
returned,
"apiKey(null) should return the same Builder instance to support fluent chaining even for null input.");
}
}
157 changes: 157 additions & 0 deletions core/src/test/java/com/google/adk/models/BuilderBuildTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* 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 unit-java-adk using AI Type Open AI and AI Model gpt-5-nano

ROOST_METHOD_HASH=build_a5a48bce54
ROOST_METHOD_SIG_HASH=build_6248639c03

Scenario 1: Build with explicit apiClient returns Gemini using that client
Details:
TestName: buildWithApiClient
Description: When apiClient is provided to the Builder along with a non-null modelName, the build() method should instantiate Gemini using that exact apiClient, ignoring apiKey and vertexCredentials.
Execution:
Arrange: Create a Builder, set modelName to "gemini-2.0", create a mock Client instance named apiClientMock, and call builder.apiClient(apiClientMock).
Act: Call builder.build().
Assert: The returned object is an instance of Gemini, and via reflection verify that the internal apiClient reference equals apiClientMock; verify the modelName used is "gemini-2.0".
Validation:
Clarify that the test confirms explicit apiClient takes precedence over other credential options and that the Gemini is wired to use the provided client.

*/

// ********RoostGPT********

package com.google.adk.models;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import com.google.genai.Client;
import java.lang.reflect.Field;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class BuilderBuildTest {

@Test
@Tag("valid")
@DisplayName("buildWithApiClient: Build with explicit apiClient returns Gemini using that client")
public void testBuildWithApiClient() throws Exception {
// Arrange
Gemini.Builder builder = Gemini.builder();
String modelName = "gemini-2.0"; // TODO: adjust if needed for different test
// environments
Client apiClientMock = mock(Client.class);
// Act
Gemini gemini = builder.modelName(modelName).apiClient(apiClientMock).build();
// Assert
assertNotNull(gemini, "Gemini instance should not be null");
// Use reflection to verify internal fields
Field modelField = Gemini.class.getDeclaredField("modelName");
modelField.setAccessible(true);
Object actualModelName = modelField.get(gemini);
assertEquals(modelName, actualModelName, "modelName should be set to the provided value");
Field apiClientField = Gemini.class.getDeclaredField("apiClient");
apiClientField.setAccessible(true);
Object actualApiClient = apiClientField.get(gemini);
assertEquals(apiClientMock, actualApiClient, "apiClient should be the same as provided");
}

@Test
@Tag("valid")
@DisplayName("buildWithApiKey: Build with explicit apiKey")
public void testBuildWithApiKey() throws Exception {
// Arrange
Gemini.Builder builder = Gemini.builder();
String modelName = "gemini-2.0"; // TODO: adjust if needed
String apiKey = "test-api-key";
// Act
Gemini gemini = builder.modelName(modelName).apiKey(apiKey).build();
// Assert
Field modelField = Gemini.class.getDeclaredField("modelName");
modelField.setAccessible(true);
Object actualModelName = modelField.get(gemini);
assertEquals(modelName, actualModelName, "modelName should be set to the provided value");
Field apiKeyField = Gemini.class.getDeclaredField("apiKey");
apiKeyField.setAccessible(true);
Object actualApiKey = apiKeyField.get(gemini);
assertEquals(apiKey, actualApiKey, "apiKey should be the same as provided");
}

@Test
@Tag("valid")
@DisplayName("buildWithVertexCredentials: Build with vertexCredentials")
public void testBuildWithVertexCredentials() throws Exception {
// Arrange
Gemini.Builder builder = Gemini.builder();
String modelName = "gemini-2.0"; // TODO: adjust if needed
VertexCredentials vertexCredentials = VertexCredentials.builder().build();
// Act
Gemini gemini = builder.modelName(modelName).vertexCredentials(vertexCredentials).build();
// Assert
Field modelField = Gemini.class.getDeclaredField("modelName");
modelField.setAccessible(true);
Object actualModelName = modelField.get(gemini);
assertEquals(modelName, actualModelName, "modelName should be set to the provided value");
Field vcField = Gemini.class.getDeclaredField("vertexCredentials");
vcField.setAccessible(true);
Object actualVertexCreds = vcField.get(gemini);
assertEquals(
vertexCredentials, actualVertexCreds, "vertexCredentials should be the same as provided");
}

@Test
@Tag("boundary")
@DisplayName("buildWithNoCredentials: Build with no credentials uses default Client")
public void testBuildWithNoCredentials() throws Exception {
// Arrange
Gemini.Builder builder = Gemini.builder();
String modelName = "gemini-2.0"; // TODO: adjust if needed
// Act
Gemini gemini = builder.modelName(modelName).build();
// Assert
Field modelField = Gemini.class.getDeclaredField("modelName");
modelField.setAccessible(true);
Object actualModelName = modelField.get(gemini);
assertEquals(modelName, actualModelName, "modelName should be set to the provided value");
Field apiClientField = Gemini.class.getDeclaredField("apiClient");
apiClientField.setAccessible(true);
Object actualApiClient = apiClientField.get(gemini);
assertNotNull(
actualApiClient,
"apiClient should be initialized by default when no credentials are provided");
assertTrue(actualApiClient instanceof Client, "apiClient should be an instance of Client");
}

@Test
@Tag("invalid")
@DisplayName("buildWithNullModelNameThrows: Null modelName should throw NullPointerException")
public void testBuildWithNullModelNameThrows() {
// Arrange
Gemini.Builder builder = Gemini.builder();
// Act & Assert
assertThrows(
NullPointerException.class,
() -> builder.build(),
"Expected NPE when modelName is not set");
}
}
Loading