Skip to content

Commit 655e1d3

Browse files
authored
chore: Backport ResultAggregator tests (#298)
1 parent 26ec196 commit 655e1d3

1 file changed

Lines changed: 186 additions & 0 deletions

File tree

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package io.a2a.server.tasks;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNotNull;
5+
import static org.mockito.Mockito.reset;
6+
import static org.mockito.Mockito.times;
7+
import static org.mockito.Mockito.verify;
8+
import static org.mockito.Mockito.verifyNoInteractions;
9+
import static org.mockito.Mockito.when;
10+
11+
import java.util.Collections;
12+
13+
import io.a2a.spec.EventKind;
14+
import io.a2a.spec.Message;
15+
import io.a2a.spec.Task;
16+
import io.a2a.spec.TaskState;
17+
import io.a2a.spec.TaskStatus;
18+
import io.a2a.spec.TextPart;
19+
import org.junit.jupiter.api.BeforeEach;
20+
import org.junit.jupiter.api.Test;
21+
import org.mockito.Mock;
22+
import org.mockito.MockitoAnnotations;
23+
24+
/**
25+
* Comprehensive tests for ResultAggregator based on Python test patterns.
26+
* This is not a strict backport of the Python test, but it implements the same testing patterns
27+
* adapted for Java's reactive streams and concurrency model.
28+
*
29+
* Note: This simplified version focuses on the core functionality without complex reactive stream testing
30+
* that was causing issues with the original implementation.
31+
*/
32+
public class ResultAggregatorTest {
33+
34+
@Mock
35+
private TaskManager mockTaskManager;
36+
37+
private ResultAggregator aggregator;
38+
39+
@BeforeEach
40+
void setUp() {
41+
MockitoAnnotations.openMocks(this);
42+
aggregator = new ResultAggregator(mockTaskManager, null);
43+
}
44+
45+
// Helper methods for creating sample data
46+
private Message createSampleMessage(String content, String msgId, Message.Role role) {
47+
return new Message.Builder()
48+
.messageId(msgId)
49+
.role(role)
50+
.parts(Collections.singletonList(new TextPart(content)))
51+
.build();
52+
}
53+
54+
private Task createSampleTask(String taskId, TaskState statusState, String contextId) {
55+
return new Task.Builder()
56+
.id(taskId)
57+
.contextId(contextId)
58+
.status(new TaskStatus(statusState))
59+
.build();
60+
}
61+
62+
63+
// Basic functionality tests
64+
65+
@Test
66+
void testConstructorWithMessage() {
67+
Message initialMessage = createSampleMessage("initial", "msg1", Message.Role.USER);
68+
ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, initialMessage);
69+
70+
// Test that the message is properly stored by checking getCurrentResult
71+
assertEquals(initialMessage, aggregatorWithMessage.getCurrentResult());
72+
// TaskManager should not be called when message is set
73+
verifyNoInteractions(mockTaskManager);
74+
}
75+
76+
@Test
77+
void testGetCurrentResultWithMessageSet() {
78+
Message sampleMessage = createSampleMessage("hola", "msg1", Message.Role.USER);
79+
ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, sampleMessage);
80+
81+
EventKind result = aggregatorWithMessage.getCurrentResult();
82+
83+
assertEquals(sampleMessage, result);
84+
// TaskManager.getTask() should not be called when message is set
85+
verifyNoInteractions(mockTaskManager);
86+
}
87+
88+
@Test
89+
void testGetCurrentResultWithMessageNull() {
90+
Task expectedTask = createSampleTask("task_from_tm", TaskState.SUBMITTED, "ctx1");
91+
when(mockTaskManager.getTask()).thenReturn(expectedTask);
92+
93+
EventKind result = aggregator.getCurrentResult();
94+
95+
assertEquals(expectedTask, result);
96+
verify(mockTaskManager).getTask();
97+
}
98+
99+
@Test
100+
void testConstructorStoresTaskManagerCorrectly() {
101+
// Test that constructor properly initializes the aggregator
102+
// We can't access the private field directly, but we can test behavior
103+
Task expectedTask = createSampleTask("test_task", TaskState.SUBMITTED, "ctx1");
104+
when(mockTaskManager.getTask()).thenReturn(expectedTask);
105+
106+
EventKind result = aggregator.getCurrentResult();
107+
108+
assertEquals(expectedTask, result);
109+
verify(mockTaskManager).getTask();
110+
}
111+
112+
@Test
113+
void testConstructorWithNullMessage() {
114+
ResultAggregator aggregatorWithNullMessage = new ResultAggregator(mockTaskManager, null);
115+
Task expectedTask = createSampleTask("null_msg_task", TaskState.WORKING, "ctx1");
116+
when(mockTaskManager.getTask()).thenReturn(expectedTask);
117+
118+
EventKind result = aggregatorWithNullMessage.getCurrentResult();
119+
120+
assertEquals(expectedTask, result);
121+
verify(mockTaskManager).getTask();
122+
}
123+
124+
@Test
125+
void testGetCurrentResultReturnsTaskWhenNoMessage() {
126+
Task expectedTask = createSampleTask("no_message_task", TaskState.COMPLETED, "ctx1");
127+
when(mockTaskManager.getTask()).thenReturn(expectedTask);
128+
129+
EventKind result = aggregator.getCurrentResult();
130+
131+
assertNotNull(result);
132+
assertEquals(expectedTask, result);
133+
verify(mockTaskManager).getTask();
134+
}
135+
136+
@Test
137+
void testGetCurrentResultWithDifferentTaskStates() {
138+
// Test with WORKING and COMPLETED states using chained returns
139+
Task workingTask = createSampleTask("working_task", TaskState.WORKING, "ctx1");
140+
Task completedTask = createSampleTask("completed_task", TaskState.COMPLETED, "ctx1");
141+
when(mockTaskManager.getTask()).thenReturn(workingTask, completedTask);
142+
143+
// First call returns WORKING task
144+
EventKind result1 = aggregator.getCurrentResult();
145+
assertEquals(workingTask, result1);
146+
147+
// Second call returns COMPLETED task
148+
EventKind result2 = aggregator.getCurrentResult();
149+
assertEquals(completedTask, result2);
150+
}
151+
152+
@Test
153+
void testMultipleGetCurrentResultCalls() {
154+
// Test that multiple calls to getCurrentResult behave consistently
155+
Task expectedTask = createSampleTask("multi_call_task", TaskState.SUBMITTED, "ctx1");
156+
when(mockTaskManager.getTask()).thenReturn(expectedTask);
157+
158+
EventKind result1 = aggregator.getCurrentResult();
159+
EventKind result2 = aggregator.getCurrentResult();
160+
EventKind result3 = aggregator.getCurrentResult();
161+
162+
assertEquals(expectedTask, result1);
163+
assertEquals(expectedTask, result2);
164+
assertEquals(expectedTask, result3);
165+
166+
// Verify getTask was called multiple times
167+
verify(mockTaskManager, times(3)).getTask();
168+
}
169+
170+
@Test
171+
void testGetCurrentResultWithMessageTakesPrecedence() {
172+
// Test that when both message and task are available, message takes precedence
173+
Message message = createSampleMessage("priority message", "pri1", Message.Role.USER);
174+
ResultAggregator messageAggregator = new ResultAggregator(mockTaskManager, message);
175+
176+
// Even if we set up the task manager to return something, message should take precedence
177+
Task task = createSampleTask("should_not_be_returned", TaskState.WORKING, "ctx1");
178+
when(mockTaskManager.getTask()).thenReturn(task);
179+
180+
EventKind result = messageAggregator.getCurrentResult();
181+
182+
assertEquals(message, result);
183+
// Task manager should not be called when message is present
184+
verifyNoInteractions(mockTaskManager);
185+
}
186+
}

0 commit comments

Comments
 (0)