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>
76 changes: 76 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,76 @@
/*
* 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.*;

import com.google.genai.Client;
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.mockito.Mockito;

public class BuilderApiClientTest {

@Test
@Tag("valid")
@DisplayName("apiClient_setsExplicitClient")
public void testApiClient_setsExplicitClient() {
Gemini.Builder builder = Gemini.builder();
Client mockClient = Mockito.mock(Client.class);
Gemini.Builder resultBuilder = builder.apiClient(mockClient);
assertSame(builder, resultBuilder);
// Continue chaining to ensure fluent API contract
Gemini.Builder chained = resultBuilder.modelName("test-model");
Gemini gemini = chained.build();
assertNotNull(gemini);
}

@Test
@Tag("valid")
@DisplayName("apiClient_acceptsNullAndReturnsThisForChaining")
public void testApiClient_acceptsNullAndReturnsThisForChaining() {
Gemini.Builder builder = Gemini.builder();
Gemini.Builder result = builder.apiClient(null);
assertSame(builder, result);
}

}
85 changes: 85 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,85 @@
/*
* 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.*;

import java.lang.reflect.Field;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

public class BuilderApiKeyTest {

@Test
@Tag("valid")
public void settingApiKeyStoresValue() throws Exception {
// Arrange
Gemini.Builder builder = Gemini.builder();
String testApiKey = java.util.UUID.randomUUID().toString();
// Act
Gemini.Builder returned = builder.apiKey(testApiKey); // TODO: Replace with a
// known key if using
// integration tests
// Assert fluent chaining
assertSame(builder, returned, "apiKey should return the same builder instance for fluent chaining.");
// Assert that the value is stored in the builder (private field access via
// reflection)
Field field = Gemini.Builder.class.getDeclaredField("apiKey");
field.setAccessible(true);
String value = (String) field.get(builder);
assertEquals(testApiKey, value, "The apiKey value stored in the builder should match the input value.");
}

@Test
@Tag("valid")
public void settingApiKeyWithNullValue() throws Exception {
// Arrange
Gemini.Builder builder = Gemini.builder();
// Act
Gemini.Builder returned = builder.apiKey(null);
// Assert fluent chaining
assertSame(builder, returned, "apiKey(null) should return the same builder instance for fluent chaining.");
// Assert that the value stored is null
Field field = Gemini.Builder.class.getDeclaredField("apiKey");
field.setAccessible(true);
String value = (String) field.get(builder);
assertNull(value, "The apiKey value should be null when null is passed.");
}

}
125 changes: 125 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,125 @@
/*
* 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.Test;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.*;
import static com.google.common.base.StandardSystemProperty.JAVA_VERSION;
import com.google.adk.Version;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.genai.ResponseStream;
import com.google.genai.types.Candidate;
import com.google.genai.types.Content;
import com.google.genai.types.FinishReason;
import com.google.genai.types.GenerateContentConfig;
import com.google.genai.types.GenerateContentResponse;
import com.google.genai.types.HttpOptions;
import com.google.genai.types.LiveConnectConfig;
import com.google.genai.types.Part;
import io.reactivex.rxjava3.core.Flowable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BuilderBuildTest {

@Test
@Tag("valid")
public void buildWithApiClient() throws Exception {
Client apiClientMock = mock(Client.class);
Gemini gemini = Gemini.builder().modelName("gemini-2.0").apiClient(apiClientMock).build();
assertEquals("gemini-2.0", gemini.model());
Field f = Gemini.class.getDeclaredField("apiClient");
f.setAccessible(true);
Object value = f.get(gemini);
assertSame(apiClientMock, value);
}

@Test
@Tag("valid")
public void buildWithApiKey() throws Exception {
String apiKey = "test-key";
Gemini gemini = Gemini.builder().modelName("gemini-2.0").apiKey(apiKey).build();
assertEquals("gemini-2.0", gemini.model());
Field f = Gemini.class.getDeclaredField("apiKey");
f.setAccessible(true);
Object value = f.get(gemini);
assertEquals(apiKey, (String) value);
}

@Test
@Tag("valid")
public void buildWithVertexCredentials() throws Exception {
VertexCredentials vc = VertexCredentials.builder().build();
Gemini gemini = Gemini.builder().modelName("gemini-2.0").vertexCredentials(vc).build();
assertEquals("gemini-2.0", gemini.model());
Field f = Gemini.class.getDeclaredField("vertexCredentials");
f.setAccessible(true);
Object value = f.get(gemini);
assertSame(vc, value);
}

@Test
@Tag("integration")
public void buildWithDefaultClient() throws Exception {
Gemini gemini = Gemini.builder().modelName("gemini-2.0").build();
assertEquals("gemini-2.0", gemini.model());
Field f = Gemini.class.getDeclaredField("apiClient");
f.setAccessible(true);
Object value = f.get(gemini);
assertNotNull(value);
assertTrue(value instanceof Client);
}

@Test
@Tag("invalid")
public void buildWithNullModelNameThrows() {
assertThrows(NullPointerException.class, () -> Gemini.builder().modelName(null).build());
}

}
Loading