Skip to content

Commit 535f844

Browse files
authored
Add test for LocallyDispatchedActivityPollTask/WorkflowPollTask/ActivityPollTask (#961)
* Add test * add test for workflowPollTask
1 parent 5164d16 commit 535f844

File tree

3 files changed

+475
-0
lines changed

3 files changed

+475
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
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.worker;
16+
17+
import static com.uber.cadence.internal.metrics.MetricsTagValue.INTERNAL_SERVICE_ERROR;
18+
import static com.uber.cadence.internal.metrics.MetricsTagValue.SERVICE_BUSY;
19+
import static org.junit.Assert.*;
20+
import static org.mockito.Mockito.*;
21+
22+
import com.google.common.collect.ImmutableMap;
23+
import com.uber.cadence.InternalServiceError;
24+
import com.uber.cadence.PollForActivityTaskRequest;
25+
import com.uber.cadence.PollForActivityTaskResponse;
26+
import com.uber.cadence.ServiceBusyError;
27+
import com.uber.cadence.internal.metrics.MetricsTag;
28+
import com.uber.cadence.internal.metrics.MetricsType;
29+
import com.uber.cadence.serviceclient.IWorkflowService;
30+
import com.uber.m3.tally.Counter;
31+
import com.uber.m3.tally.Scope;
32+
import com.uber.m3.tally.Stopwatch;
33+
import com.uber.m3.tally.Timer;
34+
import org.apache.thrift.TException;
35+
import org.junit.Before;
36+
import org.junit.Test;
37+
38+
public class ActivityPollTaskTest {
39+
40+
private IWorkflowService mockService;
41+
private SingleWorkerOptions options;
42+
private ActivityPollTask pollTask;
43+
44+
@Before
45+
public void setup() {
46+
mockService = mock(IWorkflowService.class);
47+
Scope metricsScope = mock(Scope.class); // Mock Scope to avoid NoopScope
48+
49+
// Mock the Timer and Stopwatch
50+
Timer timer = mock(Timer.class);
51+
Stopwatch stopwatch = mock(Stopwatch.class);
52+
when(metricsScope.timer(MetricsType.ACTIVITY_POLL_LATENCY)).thenReturn(timer);
53+
when(timer.start()).thenReturn(stopwatch);
54+
55+
// Mock the Counter and its inc() method
56+
Counter counter = mock(Counter.class);
57+
when(metricsScope.counter(MetricsType.ACTIVITY_POLL_COUNTER)).thenReturn(counter);
58+
when(metricsScope.counter(MetricsType.ACTIVITY_POLL_NO_TASK_COUNTER)).thenReturn(counter);
59+
when(metricsScope.counter(MetricsType.ACTIVITY_POLL_FAILED_COUNTER)).thenReturn(counter);
60+
when(metricsScope.counter(MetricsType.ACTIVITY_POLL_TRANSIENT_FAILED_COUNTER))
61+
.thenReturn(counter);
62+
63+
// Use doNothing() to stub the inc() method of Counter, as it returns void
64+
doNothing().when(counter).inc(anyInt());
65+
66+
// Set up SingleWorkerOptions to return the mocked metricsScope
67+
options = mock(SingleWorkerOptions.class);
68+
when(options.getMetricsScope())
69+
.thenReturn(metricsScope); // Set options to return the mock Scope
70+
when(options.getIdentity()).thenReturn("test-identity");
71+
when(options.getTaskListActivitiesPerSecond()).thenReturn(1.0);
72+
73+
// Initialize pollTask with mocked options
74+
pollTask = new ActivityPollTask(mockService, "test-domain", "test-taskList", options);
75+
}
76+
77+
@Test
78+
public void testPollTaskSuccess() throws TException {
79+
PollForActivityTaskResponse response =
80+
new PollForActivityTaskResponse().setTaskToken("testToken".getBytes());
81+
when(mockService.PollForActivityTask(any(PollForActivityTaskRequest.class)))
82+
.thenReturn(response);
83+
84+
// Mock the timer and stopwatch behavior
85+
Scope metricsScope = options.getMetricsScope();
86+
Timer timer = mock(Timer.class);
87+
when(metricsScope.timer(MetricsType.ACTIVITY_POLL_LATENCY)).thenReturn(timer);
88+
Stopwatch sw = mock(Stopwatch.class);
89+
when(timer.start()).thenReturn(sw);
90+
91+
PollForActivityTaskResponse result = pollTask.pollTask();
92+
93+
assertNotNull(result);
94+
assertArrayEquals("testToken".getBytes(), result.getTaskToken());
95+
96+
// Verify the counters and the timer behavior
97+
verify(metricsScope.counter(MetricsType.ACTIVITY_POLL_COUNTER), times(1)).inc(1);
98+
verify(timer, times(1)).start();
99+
verify(sw, times(1)).stop();
100+
}
101+
102+
@Test(expected = InternalServiceError.class)
103+
public void testPollTaskInternalServiceError() throws TException {
104+
// Set up mockService to throw an InternalServiceError exception
105+
when(mockService.PollForActivityTask(any(PollForActivityTaskRequest.class)))
106+
.thenThrow(new InternalServiceError());
107+
108+
// Mock taggedScope and taggedCounter to ensure the behavior
109+
Scope metricsScope = options.getMetricsScope();
110+
Scope taggedScope = mock(Scope.class);
111+
Counter taggedCounter = mock(Counter.class);
112+
113+
// Set up taggedScope to return taggedCounter for specific counter calls
114+
when(metricsScope.tagged(ImmutableMap.of(MetricsTag.CAUSE, INTERNAL_SERVICE_ERROR)))
115+
.thenReturn(taggedScope);
116+
when(taggedScope.counter(MetricsType.ACTIVITY_POLL_TRANSIENT_FAILED_COUNTER))
117+
.thenReturn(taggedCounter);
118+
119+
try {
120+
// Call pollTask.pollTask(), expecting an InternalServiceError to be thrown
121+
pollTask.pollTask();
122+
} finally {
123+
// Verify that taggedCounter.inc(1) is called once
124+
verify(taggedCounter, times(1)).inc(1);
125+
}
126+
}
127+
128+
@Test(expected = ServiceBusyError.class)
129+
public void testPollTaskServiceBusyError() throws TException {
130+
// Set up mockService to throw a ServiceBusyError exception
131+
when(mockService.PollForActivityTask(any(PollForActivityTaskRequest.class)))
132+
.thenThrow(new ServiceBusyError());
133+
134+
// Mock taggedScope and taggedCounter to ensure the behavior
135+
Scope metricsScope = options.getMetricsScope();
136+
Scope taggedScope = mock(Scope.class);
137+
Counter taggedCounter = mock(Counter.class);
138+
139+
// Set up taggedScope to return taggedCounter for specific counter calls
140+
when(metricsScope.tagged(ImmutableMap.of(MetricsTag.CAUSE, SERVICE_BUSY)))
141+
.thenReturn(taggedScope);
142+
when(taggedScope.counter(MetricsType.ACTIVITY_POLL_TRANSIENT_FAILED_COUNTER))
143+
.thenReturn(taggedCounter);
144+
145+
try {
146+
// Call pollTask.pollTask(), expecting a ServiceBusyError to be thrown
147+
pollTask.pollTask();
148+
} finally {
149+
// Verify that taggedCounter.inc(1) is called once
150+
verify(taggedCounter, times(1)).inc(1);
151+
}
152+
}
153+
154+
@Test(expected = TException.class)
155+
public void testPollTaskGeneralTException() throws TException {
156+
// Set up mockService to throw a TException
157+
when(mockService.PollForActivityTask(any(PollForActivityTaskRequest.class)))
158+
.thenThrow(new TException());
159+
160+
// Mock the metricsScope and counter to ensure proper behavior
161+
Scope metricsScope = options.getMetricsScope();
162+
Counter failedCounter = mock(Counter.class);
163+
when(metricsScope.counter(MetricsType.ACTIVITY_POLL_FAILED_COUNTER)).thenReturn(failedCounter);
164+
165+
try {
166+
// Call pollTask.pollTask(), expecting a TException to be thrown
167+
pollTask.pollTask();
168+
} finally {
169+
// Verify that failedCounter.inc(1) is called once
170+
verify(failedCounter, times(1)).inc(1);
171+
}
172+
}
173+
174+
@Test
175+
public void testPollTaskNoTask() throws TException {
176+
// Set up mockService to return an empty PollForActivityTaskResponse
177+
when(mockService.PollForActivityTask(any(PollForActivityTaskRequest.class)))
178+
.thenReturn(new PollForActivityTaskResponse());
179+
180+
// Mock the metricsScope and noTaskCounter to ensure proper behavior
181+
Scope metricsScope = options.getMetricsScope();
182+
Counter noTaskCounter = mock(Counter.class);
183+
when(metricsScope.counter(MetricsType.ACTIVITY_POLL_NO_TASK_COUNTER)).thenReturn(noTaskCounter);
184+
185+
// Call pollTask.pollTask() and check the response
186+
PollForActivityTaskResponse result = pollTask.pollTask();
187+
188+
// Verify that the result is null when there is no task
189+
assertNull(result);
190+
191+
// Verify that noTaskCounter.inc(1) is called once
192+
verify(noTaskCounter, times(1)).inc(1);
193+
}
194+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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.worker;
16+
17+
import static org.junit.Assert.*;
18+
import static org.mockito.Mockito.*;
19+
20+
import com.uber.cadence.client.WorkflowClient;
21+
import com.uber.cadence.client.WorkflowClientOptions;
22+
import com.uber.cadence.serviceclient.ClientOptions;
23+
import com.uber.cadence.serviceclient.IWorkflowService;
24+
import com.uber.m3.tally.NoopScope;
25+
import org.apache.thrift.TException;
26+
import org.junit.Before;
27+
import org.junit.Test;
28+
29+
public class LocallyDispatchedActivityPollTaskTest {
30+
31+
private WorkflowClient mockClient;
32+
private IWorkflowService mockService;
33+
private LocallyDispatchedActivityPollTask pollTask;
34+
private LocallyDispatchedActivityWorker.Task mockTask;
35+
private SingleWorkerOptions options;
36+
37+
@Before
38+
public void setup() throws Exception {
39+
mockClient = mock(WorkflowClient.class);
40+
mockService = mock(IWorkflowService.class);
41+
42+
WorkflowClientOptions clientOptions =
43+
WorkflowClientOptions.newBuilder().setMetricsScope(new NoopScope()).build();
44+
when(mockClient.getOptions()).thenReturn(clientOptions);
45+
when(mockClient.getService()).thenReturn(mockService);
46+
when(mockService.getOptions()).thenReturn(ClientOptions.defaultInstance());
47+
48+
options =
49+
SingleWorkerOptions.newBuilder().setMetricsScope(clientOptions.getMetricsScope()).build();
50+
pollTask = new LocallyDispatchedActivityPollTask(options);
51+
mockTask = mock(LocallyDispatchedActivityWorker.Task.class);
52+
}
53+
54+
@Test
55+
public void testPollTaskInterruptedException() throws Exception {
56+
Thread.currentThread().interrupt();
57+
pollTask.apply(mockTask);
58+
try {
59+
pollTask.pollTask();
60+
fail("Expected RuntimeException due to interruption");
61+
} catch (RuntimeException e) {
62+
assertTrue(e.getMessage().contains("locally dispatch activity poll task interrupted"));
63+
} catch (TException e) {
64+
fail("Unexpected TException");
65+
} finally {
66+
Thread.interrupted();
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)