Skip to content

Commit f55ce55

Browse files
authored
Add unit tests for WorkflowExecutionUtils (#959)
1 parent 535f844 commit f55ce55

File tree

1 file changed

+365
-0
lines changed

1 file changed

+365
-0
lines changed
Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
/**
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* <p>Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* <p>Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file
7+
* except in compliance with the License. A copy of the License is located at
8+
*
9+
* <p>http://aws.amazon.com/apache2.0
10+
*
11+
* <p>or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
13+
* specific language governing permissions and limitations under the License.
14+
*/
15+
package com.uber.cadence.internal.common;
16+
17+
import static org.junit.Assert.*;
18+
import static org.mockito.Mockito.*;
19+
20+
import com.uber.cadence.EventType;
21+
import com.uber.cadence.GetWorkflowExecutionHistoryResponse;
22+
import com.uber.cadence.History;
23+
import com.uber.cadence.HistoryEvent;
24+
import com.uber.cadence.StartChildWorkflowExecutionFailedEventAttributes;
25+
import com.uber.cadence.WorkflowExecution;
26+
import com.uber.cadence.WorkflowExecutionCloseStatus;
27+
import com.uber.cadence.client.WorkflowTerminatedException;
28+
import com.uber.cadence.client.WorkflowTimedOutException;
29+
import com.uber.cadence.serviceclient.IWorkflowService;
30+
import java.util.Arrays;
31+
import java.util.Collections;
32+
import java.util.Iterator;
33+
import java.util.Optional;
34+
import java.util.concurrent.CancellationException;
35+
import java.util.concurrent.TimeUnit;
36+
import java.util.concurrent.TimeoutException;
37+
import org.junit.Before;
38+
import org.junit.Test;
39+
40+
public class WorkflowExecutionUtilsTest {
41+
42+
private IWorkflowService mockService;
43+
private WorkflowExecution workflowExecution;
44+
45+
@Before
46+
public void setUp() {
47+
mockService = mock(IWorkflowService.class);
48+
workflowExecution =
49+
new WorkflowExecution().setWorkflowId("testWorkflowId").setRunId("testRunId");
50+
}
51+
52+
// Helper method to create a response with a single event
53+
private GetWorkflowExecutionHistoryResponse createResponseWithEvent(HistoryEvent event) {
54+
GetWorkflowExecutionHistoryResponse response = new GetWorkflowExecutionHistoryResponse();
55+
response.setHistory(new History().setEvents(Collections.singletonList(event)));
56+
return response;
57+
}
58+
59+
// ===========================
60+
// Test for successful completion case
61+
// ===========================
62+
@Test
63+
public void testGetWorkflowExecutionResult_SuccessfulCompletion() throws Exception {
64+
// Mock a completed event with a result
65+
HistoryEvent completedEvent = new HistoryEvent();
66+
completedEvent.setEventType(EventType.WorkflowExecutionCompleted);
67+
byte[] expectedResult = "result".getBytes();
68+
completedEvent.setWorkflowExecutionCompletedEventAttributes(
69+
new com.uber.cadence.WorkflowExecutionCompletedEventAttributes().setResult(expectedResult));
70+
71+
// Mock the response from GetWorkflowExecutionHistoryWithTimeout
72+
GetWorkflowExecutionHistoryResponse response = createResponseWithEvent(completedEvent);
73+
when(mockService.GetWorkflowExecutionHistoryWithTimeout(any(), anyLong())).thenReturn(response);
74+
75+
byte[] result =
76+
WorkflowExecutionUtils.getWorkflowExecutionResult(
77+
mockService, "testDomain", workflowExecution, Optional.empty(), 5, TimeUnit.SECONDS);
78+
79+
assertArrayEquals(expectedResult, result);
80+
}
81+
82+
// ===========================
83+
// Test for canceled workflow case
84+
// ===========================
85+
@Test(expected = CancellationException.class)
86+
public void testGetWorkflowExecutionResult_CancelledWorkflow() throws Exception {
87+
// Mock a canceled event
88+
HistoryEvent canceledEvent = new HistoryEvent();
89+
canceledEvent.setEventType(EventType.WorkflowExecutionCanceled);
90+
canceledEvent.setWorkflowExecutionCanceledEventAttributes(
91+
new com.uber.cadence.WorkflowExecutionCanceledEventAttributes());
92+
93+
GetWorkflowExecutionHistoryResponse response = createResponseWithEvent(canceledEvent);
94+
when(mockService.GetWorkflowExecutionHistoryWithTimeout(any(), anyLong())).thenReturn(response);
95+
96+
WorkflowExecutionUtils.getWorkflowExecutionResult(
97+
mockService, "testDomain", workflowExecution, Optional.empty(), 5, TimeUnit.SECONDS);
98+
}
99+
100+
// ===========================
101+
// Test for terminated workflow case
102+
// ===========================
103+
@Test(expected = WorkflowTerminatedException.class)
104+
public void testGetWorkflowExecutionResult_TerminatedWorkflow() throws Exception {
105+
// Mock a terminated event
106+
HistoryEvent terminatedEvent = new HistoryEvent();
107+
terminatedEvent.setEventType(EventType.WorkflowExecutionTerminated);
108+
terminatedEvent.setWorkflowExecutionTerminatedEventAttributes(
109+
new com.uber.cadence.WorkflowExecutionTerminatedEventAttributes());
110+
111+
GetWorkflowExecutionHistoryResponse response = createResponseWithEvent(terminatedEvent);
112+
when(mockService.GetWorkflowExecutionHistoryWithTimeout(any(), anyLong())).thenReturn(response);
113+
114+
WorkflowExecutionUtils.getWorkflowExecutionResult(
115+
mockService, "testDomain", workflowExecution, Optional.empty(), 5, TimeUnit.SECONDS);
116+
}
117+
118+
// ===========================
119+
// Test for timed-out workflow case
120+
// ===========================
121+
@Test(expected = WorkflowTimedOutException.class)
122+
public void testGetWorkflowExecutionResult_TimedOutWorkflow() throws Exception {
123+
// Mock a timed-out event
124+
HistoryEvent timedOutEvent = new HistoryEvent();
125+
timedOutEvent.setEventType(EventType.WorkflowExecutionTimedOut);
126+
timedOutEvent.setWorkflowExecutionTimedOutEventAttributes(
127+
new com.uber.cadence.WorkflowExecutionTimedOutEventAttributes());
128+
129+
GetWorkflowExecutionHistoryResponse response = createResponseWithEvent(timedOutEvent);
130+
when(mockService.GetWorkflowExecutionHistoryWithTimeout(any(), anyLong())).thenReturn(response);
131+
132+
WorkflowExecutionUtils.getWorkflowExecutionResult(
133+
mockService, "testDomain", workflowExecution, Optional.empty(), 5, TimeUnit.SECONDS);
134+
}
135+
136+
// ===========================
137+
// Test for an unsupported close event type
138+
// ===========================
139+
@Test(expected = RuntimeException.class)
140+
public void testGetWorkflowExecutionResult_UnsupportedCloseEvent() throws Exception {
141+
// Mock an event type that doesn't represent a closed workflow
142+
HistoryEvent unsupportedEvent = new HistoryEvent();
143+
unsupportedEvent.setEventType(EventType.ActivityTaskScheduled); // Not a close event
144+
145+
GetWorkflowExecutionHistoryResponse response = createResponseWithEvent(unsupportedEvent);
146+
when(mockService.GetWorkflowExecutionHistoryWithTimeout(any(), anyLong())).thenReturn(response);
147+
148+
WorkflowExecutionUtils.getWorkflowExecutionResult(
149+
mockService, "testDomain", workflowExecution, Optional.empty(), 5, TimeUnit.SECONDS);
150+
}
151+
152+
// ===========================
153+
// Test for timeout exceeded while waiting
154+
// ===========================
155+
@Test(expected = TimeoutException.class)
156+
public void testGetWorkflowExecutionResult_TimeoutExceeded() throws Exception {
157+
// Simulate a delay by mocking the service call to throw a TimeoutException
158+
WorkflowExecutionUtils.getWorkflowExecutionResult(
159+
mockService, "testDomain", workflowExecution, Optional.empty(), -1, TimeUnit.MILLISECONDS);
160+
}
161+
162+
// ===========================
163+
// Test getId with StartChildWorkflowExecutionFailedEvent
164+
// ===========================
165+
@Test
166+
public void testGetId_WithStartChildWorkflowExecutionFailedEvent() {
167+
// Create a StartChildWorkflowExecutionFailed event with a workflow ID
168+
HistoryEvent event = new HistoryEvent();
169+
event.setEventType(EventType.StartChildWorkflowExecutionFailed);
170+
StartChildWorkflowExecutionFailedEventAttributes attributes =
171+
new StartChildWorkflowExecutionFailedEventAttributes();
172+
attributes.setWorkflowId("testWorkflowId");
173+
event.setStartChildWorkflowExecutionFailedEventAttributes(attributes);
174+
175+
// Call getId and verify it returns the workflow ID
176+
String result = WorkflowExecutionUtils.getId(event);
177+
assertEquals("testWorkflowId", result);
178+
}
179+
180+
// ===========================
181+
// Test getId with other event types (should return null)
182+
// ===========================
183+
@Test
184+
public void testGetId_WithNonChildWorkflowEvent() {
185+
// Create a HistoryEvent of a different type (e.g., WorkflowExecutionStarted)
186+
HistoryEvent event = new HistoryEvent();
187+
event.setEventType(EventType.WorkflowExecutionStarted);
188+
189+
// Call getId and verify it returns null
190+
String result = WorkflowExecutionUtils.getId(event);
191+
assertNull(result);
192+
}
193+
194+
@Test
195+
public void testGetId_WithNullEvent() {
196+
// Call getId with a null event and verify it returns null
197+
String result = WorkflowExecutionUtils.getId(null);
198+
assertNull(result);
199+
}
200+
201+
// ===========================
202+
// Test getCloseStatus for each close event type
203+
// ===========================
204+
205+
@Test
206+
public void testGetCloseStatus_Completed() {
207+
HistoryEvent event = new HistoryEvent();
208+
event.setEventType(EventType.WorkflowExecutionCompleted);
209+
210+
WorkflowExecutionCloseStatus result = WorkflowExecutionUtils.getCloseStatus(event);
211+
assertEquals(WorkflowExecutionCloseStatus.COMPLETED, result);
212+
}
213+
214+
@Test
215+
public void testGetCloseStatus_Canceled() {
216+
HistoryEvent event = new HistoryEvent();
217+
event.setEventType(EventType.WorkflowExecutionCanceled);
218+
219+
WorkflowExecutionCloseStatus result = WorkflowExecutionUtils.getCloseStatus(event);
220+
assertEquals(WorkflowExecutionCloseStatus.CANCELED, result);
221+
}
222+
223+
@Test
224+
public void testGetCloseStatus_Failed() {
225+
HistoryEvent event = new HistoryEvent();
226+
event.setEventType(EventType.WorkflowExecutionFailed);
227+
228+
WorkflowExecutionCloseStatus result = WorkflowExecutionUtils.getCloseStatus(event);
229+
assertEquals(WorkflowExecutionCloseStatus.FAILED, result);
230+
}
231+
232+
@Test
233+
public void testGetCloseStatus_TimedOut() {
234+
HistoryEvent event = new HistoryEvent();
235+
event.setEventType(EventType.WorkflowExecutionTimedOut);
236+
237+
WorkflowExecutionCloseStatus result = WorkflowExecutionUtils.getCloseStatus(event);
238+
assertEquals(WorkflowExecutionCloseStatus.TIMED_OUT, result);
239+
}
240+
241+
@Test
242+
public void testGetCloseStatus_ContinuedAsNew() {
243+
HistoryEvent event = new HistoryEvent();
244+
event.setEventType(EventType.WorkflowExecutionContinuedAsNew);
245+
246+
WorkflowExecutionCloseStatus result = WorkflowExecutionUtils.getCloseStatus(event);
247+
assertEquals(WorkflowExecutionCloseStatus.CONTINUED_AS_NEW, result);
248+
}
249+
250+
@Test
251+
public void testGetCloseStatus_Terminated() {
252+
HistoryEvent event = new HistoryEvent();
253+
event.setEventType(EventType.WorkflowExecutionTerminated);
254+
255+
WorkflowExecutionCloseStatus result = WorkflowExecutionUtils.getCloseStatus(event);
256+
assertEquals(WorkflowExecutionCloseStatus.TERMINATED, result);
257+
}
258+
259+
// ===========================
260+
// Test getCloseStatus with an unsupported event type
261+
// ===========================
262+
@Test
263+
public void testGetCloseStatus_InvalidEvent() {
264+
HistoryEvent event = new HistoryEvent();
265+
event.setEventType(EventType.ActivityTaskScheduled); // Unsupported close event type
266+
267+
IllegalArgumentException exception =
268+
assertThrows(
269+
IllegalArgumentException.class,
270+
() -> {
271+
WorkflowExecutionUtils.getCloseStatus(event);
272+
});
273+
274+
assertTrue(exception.getMessage().contains("Not close event"));
275+
}
276+
277+
// Helper method to create a response with events and a next page token
278+
private GetWorkflowExecutionHistoryResponse createResponseWithEvents(
279+
HistoryEvent[] events, byte[] nextPageToken) {
280+
GetWorkflowExecutionHistoryResponse response = new GetWorkflowExecutionHistoryResponse();
281+
response.setHistory(new History().setEvents(Arrays.asList(events)));
282+
response.setNextPageToken(nextPageToken);
283+
return response;
284+
}
285+
// ===========================
286+
// Test for single-page history
287+
// ===========================
288+
@Test
289+
public void testGetHistory_SinglePage() throws Exception {
290+
// Create a single-page history with two events
291+
HistoryEvent event1 =
292+
new HistoryEvent().setEventType(EventType.WorkflowExecutionStarted).setEventId(1);
293+
HistoryEvent event2 =
294+
new HistoryEvent().setEventType(EventType.WorkflowExecutionCompleted).setEventId(2);
295+
296+
GetWorkflowExecutionHistoryResponse response =
297+
createResponseWithEvents(new HistoryEvent[] {event1, event2}, null);
298+
when(mockService.GetWorkflowExecutionHistory(any())).thenReturn(response);
299+
300+
Iterator<HistoryEvent> iterator =
301+
WorkflowExecutionUtils.getHistory(mockService, "testDomain", workflowExecution);
302+
303+
assertTrue(iterator.hasNext());
304+
assertEquals(event1, iterator.next());
305+
assertTrue(iterator.hasNext());
306+
assertEquals(event2, iterator.next());
307+
assertFalse(iterator.hasNext()); // End of history
308+
}
309+
310+
// ===========================
311+
// Test for multi-page history
312+
// ===========================
313+
@Test
314+
public void testGetHistory_MultiPage() throws Exception {
315+
// Create a multi-page history with three events over two pages
316+
HistoryEvent event1 =
317+
new HistoryEvent().setEventType(EventType.WorkflowExecutionStarted).setEventId(1);
318+
HistoryEvent event2 =
319+
new HistoryEvent().setEventType(EventType.ActivityTaskScheduled).setEventId(2);
320+
HistoryEvent event3 =
321+
new HistoryEvent().setEventType(EventType.WorkflowExecutionCompleted).setEventId(3);
322+
323+
// Page 1 with a nextPageToken
324+
byte[] nextPageToken = new byte[] {1};
325+
GetWorkflowExecutionHistoryResponse responsePage1 =
326+
createResponseWithEvents(new HistoryEvent[] {event1, event2}, nextPageToken);
327+
328+
// Page 2 with no nextPageToken, indicating the end of history
329+
GetWorkflowExecutionHistoryResponse responsePage2 =
330+
createResponseWithEvents(new HistoryEvent[] {event3}, null);
331+
332+
when(mockService.GetWorkflowExecutionHistory(any()))
333+
.thenReturn(responsePage1) // First call returns page 1
334+
.thenReturn(responsePage2); // Second call returns page 2
335+
336+
Iterator<HistoryEvent> iterator =
337+
WorkflowExecutionUtils.getHistory(mockService, "testDomain", workflowExecution);
338+
339+
// Verify the iterator iterates over both pages
340+
assertTrue(iterator.hasNext());
341+
assertEquals(event1, iterator.next());
342+
assertTrue(iterator.hasNext());
343+
assertEquals(event2, iterator.next());
344+
assertTrue(iterator.hasNext());
345+
assertEquals(event3, iterator.next());
346+
assertFalse(iterator.hasNext()); // End of history
347+
}
348+
349+
// ===========================
350+
// Test for empty history
351+
// ===========================
352+
@Test
353+
public void testGetHistory_EmptyHistory() throws Exception {
354+
// Create an empty history response
355+
GetWorkflowExecutionHistoryResponse response =
356+
createResponseWithEvents(new HistoryEvent[] {}, null);
357+
when(mockService.GetWorkflowExecutionHistory(any())).thenReturn(response);
358+
359+
Iterator<HistoryEvent> iterator =
360+
WorkflowExecutionUtils.getHistory(mockService, "testDomain", workflowExecution);
361+
362+
// Verify that hasNext() is false immediately
363+
assertFalse(iterator.hasNext());
364+
}
365+
}

0 commit comments

Comments
 (0)