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/memory/AutoValueMemoryEntryContentTest.java b/core/src/test/java/com/google/adk/memory/AutoValueMemoryEntryContentTest.java
new file mode 100644
index 000000000..7933b405f
--- /dev/null
+++ b/core/src/test/java/com/google/adk/memory/AutoValueMemoryEntryContentTest.java
@@ -0,0 +1,125 @@
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test unit-java-adk using AI Type Azure Open AI and AI Model gpt-5
+
+ROOST_METHOD_HASH=content_f95ec3ddc9
+ROOST_METHOD_SIG_HASH=content_accc65ce1a
+
+
+Scenario 1: Returns the same Content instance that was supplied at construction
+
+Details:
+ TestName: returnsSameContentInstance
+ Description: Verify that the content() method returns the exact Content object that was used to build the AutoValue_MemoryEntry instance (reference identity, not a copy).
+
+Execution:
+ Arrange: Create a valid Content instance (e.g., a concrete instance or a simple test double) and build a MemoryEntry via the Builder with that Content.
+ Act: Call content() on the built MemoryEntry.
+ Assert: Use JUnit assertions to confirm that the returned Content is the same object instance as the one provided during construction (reference equality).
+
+Validation:
+ This assertion verifies that content() is a simple accessor returning the internal field without copying or transforming it. It ensures the method exposes the exact Content reference stored in the entry, which is important for consumers relying on object identity or avoiding unnecessary allocations.
+
+*/
+
+// ********RoostGPT********
+
+package com.google.adk.memory;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.google.genai.types.Content;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import javax.annotation.Nullable;
+import javax.annotation.processing.Generated;
+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.mockito.Mockito;
+
+@Generated("AutoValueMemoryEntryContentTest")
+public abstract class AutoValueMemoryEntryContentTest extends MemoryEntry {
+
+ // Intentionally left abstract as per requirement.
+
+}
+
+class AutoValueMemoryEntryContentTestCases {
+
+ private Content defaultContent;
+
+ @BeforeEach
+ public void setUp() {
+ defaultContent = Mockito.mock(Content.class);
+ }
+
+ @Test
+ @Tag("valid")
+ public void testReturnsSameContentInstance() {
+ MemoryEntry entry = (MemoryEntry) createEntry(defaultContent, null, null);
+ Content actual = (Content) entry.content();
+ assertSame(
+ (Content) defaultContent,
+ (Content) actual,
+ "content() should return the same Content instance provided to constructor");
+ }
+
+ @Test
+ @Tag("valid")
+ public void testContentNotNullWhenConstructedWithNonNullContent() {
+ MemoryEntry entry = (MemoryEntry) createEntry(defaultContent, null, null);
+ Content actual = (Content) entry.content();
+ assertNotNull(
+ (Object) actual, "content() should not return null when constructed with non-null Content");
+ }
+
+ @Test
+ @Tag("invalid")
+ public void testConstructorWithNullContent_throwsNullPointerException() {
+ assertThrows(
+ NullPointerException.class,
+ () -> {
+ createEntry(null, null, null);
+ });
+ }
+
+ @Test
+ @Tag("boundary")
+ public void testReturnsSameContentInstance_withTimestampAndAuthorVariants() {
+ Content content = Mockito.mock(Content.class);
+ // TODO: Change author if needed for specific scenario
+ @Nullable String author = null;
+ // Using a static ISO-8601 timestamp example
+ String timestamp = "2020-01-01T00:00:00Z";
+ MemoryEntry entry = (MemoryEntry) createEntry(content, author, timestamp);
+ Content actual = (Content) entry.content();
+ assertSame(
+ (Content) content,
+ (Content) actual,
+ "content() should return the same instance irrespective of author/timestamp values");
+ }
+
+ private AutoValue_MemoryEntry createEntry(
+ @Nullable Content content, @Nullable String author, @Nullable String timestamp) {
+ try {
+ Constructor ctor =
+ AutoValue_MemoryEntry.class.getDeclaredConstructor(
+ Content.class, String.class, String.class);
+ ctor.setAccessible(true);
+ return ctor.newInstance(content, author, timestamp);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ }
+ if (cause instanceof Error) {
+ throw (Error) cause;
+ }
+ throw new RuntimeException(cause);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/core/src/test/java/com/google/adk/memory/InMemoryMemoryServiceAddSessionToMemoryTest.java.invalid b/core/src/test/java/com/google/adk/memory/InMemoryMemoryServiceAddSessionToMemoryTest.java.invalid
new file mode 100644
index 000000000..eb7602934
--- /dev/null
+++ b/core/src/test/java/com/google/adk/memory/InMemoryMemoryServiceAddSessionToMemoryTest.java.invalid
@@ -0,0 +1,169 @@
+//This test file is marked invalid as it contains compilation errors. Change the extension to of this file to .java, to manually edit its contents
+/*
+ * 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 Azure Open AI and AI Model gpt-5
+
+ROOST_METHOD_HASH=addSessionToMemory_8a630adf5c
+ROOST_METHOD_SIG_HASH=addSessionToMemory_3e3003d0a0
+
+Scenario 1: Successfully stores a session with events that have non-empty parts
+
+Details:
+ TestName: storesSessionWithEventsHavingNonEmptyParts
+ Description: Verifies that addSessionToMemory stores a session whose events include content with present, non-empty parts. Confirms that the returned Completable completes without errors and that the stored events are discoverable via searchMemory.
+
+Execution:
+ Arrange: Create a Session with appName "appA", userId "user1", session id "s1", and events where at least one event has content().isPresent() and parts().isPresent() with a non-empty list containing a Part with non-empty text like "hello world".
+ Act: Invoke addSessionToMemory(session) and await the Completable to complete. Then call searchMemory("appA", "user1", "hello") to retrieve memories.
+ Assert: Assert the Completable completes successfully. Assert that searchMemory returns at least one MemoryEntry with content containing the word "hello".
+
+Validation:
+ Confirms that events meeting the filter (content present, parts present and non-empty) are retained and can be retrieved through searchMemory. Ensures the Completable signals completion, indicating the write to memory occurred.
+
+*/
+
+// ********RoostGPT********
+
+package com.google.adk.memory;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.google.adk.events.Event;
+import com.google.genai.types.Content;
+import com.google.adk.sessions.Session;
+import com.google.genai.types.Part;
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.observers.TestObserver;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.junit.jupiter.api.*;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import io.reactivex.rxjava3.core.Single;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class InMemoryMemoryServiceAddSessionToMemoryTest {
+ private InMemoryMemoryService memoryService;
+ @BeforeEach
+ public void setUp() {
+ memoryService = new InMemoryMemoryService();
+ }
+ @Test
+ @Tag("integration")
+ public void testStoresSessionWithEventsHavingNonEmptyParts() {
+ // Arrange
+ String appName = "appA";
+ String userId = "user1";
+ String sessionId = "s1";
+ Session session = Mockito.mock(Session.class);
+ Mockito.when(session.appName()).thenReturn(appName);
+ Mockito.when(session.userId()).thenReturn(userId);
+ Mockito.when(session.id()).thenReturn(sessionId);
+ // Event with non-empty parts
+ Event eventWithText = Mockito.mock(Event.class);
+ Content contentWithText = Mockito.mock(Content.class);
+ Part partWithText = Mockito.mock(Part.class);
+ Mockito.when(partWithText.text()).thenReturn((Optional) Optional.of("hello world"));
+ Mockito.when(contentWithText.parts()).thenReturn((Optional>) Optional.of((List) List.of(partWithText)));
+ Mockito.when(eventWithText.content()).thenReturn((Optional) Optional.of(contentWithText));
+ Mockito.when(eventWithText.author()).thenReturn("user");
+ Mockito.when(eventWithText.timestamp()).thenReturn(1_710_000_000L);
+ // Event with empty parts should be filtered out
+ Event eventWithEmptyParts = Mockito.mock(Event.class);
+ Content emptyContent = Mockito.mock(Content.class);
+ Mockito.when(emptyContent.parts()).thenReturn((Optional>) Optional.of((List) Collections.emptyList()));
+ Mockito.when(eventWithEmptyParts.content()).thenReturn((Optional) Optional.of(emptyContent));
+ Mockito.when(session.events()).thenReturn((List) List.of(eventWithText, eventWithEmptyParts));
+ // Act
+ Completable addCompletable = memoryService.addSessionToMemory(session);
+ TestObserver addObserver = addCompletable.test();
+ // Assert add completion
+ addObserver.assertComplete();
+ addObserver.assertNoErrors();
+ // Act - search memory
+ SearchMemoryResponse response = (SearchMemoryResponse) memoryService.searchMemory(appName, userId, "hello").blockingGet();
+ // Assert - memories should include the event with "hello"
+ List memories = (List) response.memories();
+ assertFalse(((List) memories).isEmpty());
+ MemoryEntry first = ((List) memories).get(0);
+ Content content = (Content) first.content();
+ Optional> partsOpt = (Optional>) content.parts();
+ assertTrue(((Optional>) partsOpt).isPresent());
+ List parts = ((Optional>) partsOpt).get();
+ assertFalse(((List) parts).isEmpty());
+ Optional txt = ((Part) parts.get(0)).text();
+ assertTrue(((Optional) txt).isPresent());
+ assertTrue(((String) txt.get()).toLowerCase(Locale.ROOT).contains("hello"));
+ }
+ @Test
+ @Tag("boundary")
+ public void testDoesNotStoreEventsWithEmptyParts() {
+ // Arrange
+ String appName = "appB";
+ String userId = "user2";
+ String sessionId = "s2";
+ Session session = Mockito.mock(Session.class);
+ Mockito.when(session.appName()).thenReturn(appName);
+ Mockito.when(session.userId()).thenReturn(userId);
+ Mockito.when(session.id()).thenReturn(sessionId);
+ // Event with empty parts
+ Event eventWithEmptyParts = Mockito.mock(Event.class);
+ Content emptyContent = Mockito.mock(Content.class);
+ Mockito.when(emptyContent.parts()).thenReturn((Optional>) Optional.of((List) Collections.emptyList()));
+ Mockito.when(eventWithEmptyParts.content()).thenReturn((Optional) Optional.of(emptyContent));
+ Mockito.when(session.events()).thenReturn((List) List.of(eventWithEmptyParts));
+ // Act
+ Completable addCompletable = memoryService.addSessionToMemory(session);
+ TestObserver addObserver = addCompletable.test();
+ // Assert add completion
+ addObserver.assertComplete();
+ addObserver.assertNoErrors();
+ // Search for any term should yield no memories as event parts were empty
+ SearchMemoryResponse response = (SearchMemoryResponse) memoryService.searchMemory(appName, userId, "anything").blockingGet();
+ // Assert
+ List memories = (List) response.memories();
+ assertTrue(((List) memories).isEmpty());
+ }
+ @Test
+ @Tag("invalid")
+ public void testAddSessionToMemory_withNullSession_emitsError() {
+ // Arrange
+ Session nullSession = null; // TODO: If test requires different invalid input, adjust accordingly.
+ // Act
+ Completable addCompletable = memoryService.addSessionToMemory(nullSession);
+ // Assert
+ addCompletable
+ .test()
+ .assertError(throwable -> throwable instanceof NullPointerException);
+ }
+}
\ No newline at end of file
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