Skip to content

Commit ff541b2

Browse files
committed
add unit test and fix mappers
1 parent 2f9c0f5 commit ff541b2

File tree

9 files changed

+773
-8
lines changed

9 files changed

+773
-8
lines changed

src/main/java/com/uber/cadence/internal/compatibility/proto/mappers/RequestMapper.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,7 @@ public static SignalWithStartWorkflowExecutionRequest signalWithStartWorkflowExe
457457
if (t.getDelayStartSeconds() > 0) {
458458
builder.setDelayStart(secondsToDuration(t.getDelayStartSeconds()));
459459
}
460-
if (t.getJitterStartSeconds() > 0) {
461-
builder.setJitterStart(secondsToDuration(t.getJitterStartSeconds()));
462-
}
460+
builder.setJitterStart(secondsToDuration(t.getJitterStartSeconds()));
463461

464462
if (t.getIdentity() != null) {
465463
builder.setIdentity(t.getIdentity());

src/main/java/com/uber/cadence/internal/compatibility/proto/mappers/TypeMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ static byte[] payload(Payload t) {
305305
if (t == null || t == Payload.getDefaultInstance()) {
306306
return null;
307307
}
308-
if (t.getData() == null || t.getData().size() == 0) {
308+
if (t.getData().isEmpty()) {
309309
// protoPayload will not generate this case
310310
// however, Data field will be dropped by the encoding if it's empty
311311
// and receiver side will see null for the Data field

src/test/java/com/uber/cadence/internal/compatibility/ClientObjects.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,16 @@ public class ClientObjects {
180180
.setHistoryArchivalURI("historyArchivalUri")
181181
.setVisibilityArchivalStatus(ArchivalStatus.DISABLED)
182182
.setVisibilityArchivalURI("visibilityArchivalUri")
183-
.setEmitMetric(true);
183+
.setEmitMetric(true)
184+
.setAsyncWorkflowConfiguration(new AsyncWorkflowConfiguration().setEnabled(true))
185+
.setIsolationGroups(
186+
new IsolationGroupConfiguration()
187+
.setPartitions(
188+
ImmutableList.of(
189+
new IsolationGroupPartition()
190+
.setName("partitionName")
191+
.setPercentage(100))));
192+
184193
public static final StartTimeFilter START_TIME_FILTER =
185194
new StartTimeFilter().setEarliestTime(2).setLatestTime(3);
186195
public static final WorkflowExecutionFilter WORKFLOW_EXECUTION_FILTER =

src/test/java/com/uber/cadence/internal/compatibility/MapperTestUtil.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
package com.uber.cadence.internal.compatibility;
1919

2020
import com.google.common.collect.ImmutableSet;
21-
import java.util.Arrays;
22-
import java.util.Collections;
23-
import java.util.Set;
21+
import java.util.*;
22+
import java.util.regex.Matcher;
23+
import java.util.regex.Pattern;
2424
import java.util.stream.Collectors;
2525
import org.apache.thrift.TBase;
2626
import org.apache.thrift.TFieldIdEnum;
@@ -46,6 +46,35 @@ void assertNoMissingFields(M message, Class<E> fields) {
4646
getUnsetFields(message, fields));
4747
}
4848

49+
public static void assertNoMissingFields(Object message) {
50+
List<String> nullFields = getMissingFields(message.toString());
51+
52+
Assert.assertArrayEquals(
53+
"All fields expected to be set in the text",
54+
new String[0],
55+
nullFields.toArray(new String[0]));
56+
}
57+
58+
public static void assertMissingFields(Object message, Set<String> values) {
59+
List<String> nullFields = getMissingFields(message.toString());
60+
Assert.assertArrayEquals(
61+
"Expected missing fields but get different",
62+
values.toArray(new String[0]),
63+
nullFields.toArray(new String[0]));
64+
}
65+
66+
private static List<String> getMissingFields(String text) {
67+
List<String> nullFields = new ArrayList<>();
68+
// Regex to find fieldName=null
69+
Pattern pattern = Pattern.compile("(\\w+)=null");
70+
Matcher matcher = pattern.matcher(text);
71+
72+
while (matcher.find()) {
73+
nullFields.add(matcher.group(1)); // group(1) captures the field name
74+
}
75+
return nullFields;
76+
}
77+
4978
public static <E extends Enum<E> & TFieldIdEnum, M extends TBase<M, E>> void assertMissingFields(
5079
M message, String... values) {
5180
assertMissingFields(message, findFieldsEnum(message), ImmutableSet.copyOf(values));

src/test/java/com/uber/cadence/internal/compatibility/ProtoObjects.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,8 @@ public final class ProtoObjects {
11761176
.setActiveClusterName("activeCluster")
11771177
.setDeleteBadBinary("deleteBadBinary")
11781178
.setFailoverTimeout(seconds(1))
1179+
.setActiveClusterName("activeCluster")
1180+
.addAllClusters(ImmutableList.of(CLUSTER_REPLICATION_CONFIGURATION))
11791181
.setUpdateMask(
11801182
FieldMask.newBuilder()
11811183
.addPaths("description")
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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.compatibility.proto.mappers;
16+
17+
import static com.uber.cadence.internal.compatibility.MapperTestUtil.assertNoMissingFields;
18+
19+
import com.google.common.collect.ImmutableMap;
20+
import com.google.common.collect.Sets;
21+
import com.uber.cadence.entities.Decision;
22+
import com.uber.cadence.entities.DecisionType;
23+
import com.uber.cadence.internal.compatibility.ClientObjects;
24+
import com.uber.cadence.internal.compatibility.ProtoObjects;
25+
import java.util.Collections;
26+
import java.util.EnumSet;
27+
import java.util.Map;
28+
import java.util.Set;
29+
import java.util.stream.Collectors;
30+
import org.junit.Assert;
31+
import org.junit.Test;
32+
33+
public class DecisionMapperTest {
34+
private static final Map<Decision, com.uber.cadence.api.v1.Decision> DECISIONS =
35+
ImmutableMap.<Decision, com.uber.cadence.api.v1.Decision>builder()
36+
.put(
37+
ClientObjects.DECISION_SCHEDULE_ACTIVITY_TASK,
38+
ProtoObjects.DECISION_SCHEDULE_ACTIVITY_TASK)
39+
.put(
40+
ClientObjects.DECISION_REQUEST_CANCEL_ACTIVITY_TASK,
41+
ProtoObjects.DECISION_REQUEST_CANCEL_ACTIVITY_TASK)
42+
.put(ClientObjects.DECISION_START_TIMER, ProtoObjects.DECISION_START_TIMER)
43+
.put(
44+
ClientObjects.DECISION_COMPLETE_WORKFLOW_EXECUTION,
45+
ProtoObjects.DECISION_COMPLETE_WORKFLOW_EXECUTION)
46+
.put(
47+
ClientObjects.DECISION_FAIL_WORKFLOW_EXECUTION,
48+
ProtoObjects.DECISION_FAIL_WORKFLOW_EXECUTION)
49+
.put(ClientObjects.DECISION_CANCEL_TIMER, ProtoObjects.DECISION_CANCEL_TIMER)
50+
.put(ClientObjects.DECISION_CANCEL_WORKFLOW, ProtoObjects.DECISION_CANCEL_WORKFLOW)
51+
.put(
52+
ClientObjects.DECISION_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION,
53+
ProtoObjects.DECISION_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION)
54+
.put(
55+
ClientObjects.DECISION_CONTINUE_AS_NEW_WORKFLOW_EXECUTION,
56+
ProtoObjects.DECISION_CONTINUE_AS_NEW_WORKFLOW_EXECUTION)
57+
.put(
58+
ClientObjects.DECISION_START_CHILD_WORKFLOW_EXECUTION,
59+
ProtoObjects.DECISION_START_CHILD_WORKFLOW_EXECUTION)
60+
.put(
61+
ClientObjects.DECISION_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION,
62+
ProtoObjects.DECISION_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION)
63+
.put(
64+
ClientObjects.DECISION_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES,
65+
ProtoObjects.DECISION_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES)
66+
.put(ClientObjects.DECISION_RECORD_MARKER, ProtoObjects.DECISION_RECORD_MARKER)
67+
.build();
68+
69+
@Test
70+
public void testMapDecision() {
71+
for (Map.Entry<Decision, com.uber.cadence.api.v1.Decision> entry : DECISIONS.entrySet()) {
72+
Assert.assertEquals(
73+
"Failed to convert decision of type: " + entry.getKey().getDecisionType(),
74+
entry.getValue(),
75+
DecisionMapper.decision(entry.getKey()));
76+
}
77+
}
78+
79+
@Test
80+
public void testAllDecisionTypesCovered() {
81+
// If IDL changes add a new decision type, this should fail
82+
Set<DecisionType> expected = EnumSet.allOf(DecisionType.class);
83+
Set<DecisionType> actual =
84+
DECISIONS.keySet().stream().map(Decision::getDecisionType).collect(Collectors.toSet());
85+
86+
Assert.assertEquals(
87+
"Missing conversion for some DecisionTypes",
88+
Collections.emptySet(),
89+
Sets.difference(expected, actual));
90+
}
91+
92+
@Test
93+
public void testAllAttributesSet() {
94+
// If IDL changes add a new field to decision attributes, this should fail
95+
for (Map.Entry<Decision, com.uber.cadence.api.v1.Decision> entry : DECISIONS.entrySet()) {
96+
Decision decision = entry.getKey();
97+
switch (decision.getDecisionType()) {
98+
case ScheduleActivityTask:
99+
assertNoMissingFields(decision.getScheduleActivityTaskDecisionAttributes());
100+
break;
101+
case RequestCancelActivityTask:
102+
assertNoMissingFields(decision.getRequestCancelActivityTaskDecisionAttributes());
103+
break;
104+
case StartTimer:
105+
assertNoMissingFields(decision.getStartTimerDecisionAttributes());
106+
break;
107+
case CompleteWorkflowExecution:
108+
assertNoMissingFields(decision.getCompleteWorkflowExecutionDecisionAttributes());
109+
break;
110+
case FailWorkflowExecution:
111+
assertNoMissingFields(decision.getFailWorkflowExecutionDecisionAttributes());
112+
break;
113+
case CancelTimer:
114+
assertNoMissingFields(decision.getCancelTimerDecisionAttributes());
115+
break;
116+
case CancelWorkflowExecution:
117+
assertNoMissingFields(decision.getCancelWorkflowExecutionDecisionAttributes());
118+
break;
119+
case RequestCancelExternalWorkflowExecution:
120+
assertNoMissingFields(
121+
decision.getRequestCancelExternalWorkflowExecutionDecisionAttributes());
122+
break;
123+
case RecordMarker:
124+
assertNoMissingFields(decision.getRecordMarkerDecisionAttributes());
125+
break;
126+
case ContinueAsNewWorkflowExecution:
127+
assertNoMissingFields(decision.getContinueAsNewWorkflowExecutionDecisionAttributes());
128+
break;
129+
case StartChildWorkflowExecution:
130+
assertNoMissingFields(decision.getStartChildWorkflowExecutionDecisionAttributes());
131+
break;
132+
case SignalExternalWorkflowExecution:
133+
assertNoMissingFields(decision.getSignalExternalWorkflowExecutionDecisionAttributes());
134+
break;
135+
case UpsertWorkflowSearchAttributes:
136+
assertNoMissingFields(decision.getUpsertWorkflowSearchAttributesDecisionAttributes());
137+
break;
138+
}
139+
}
140+
}
141+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
7+
* use this file except in compliance with the License. A copy of the License is
8+
* located at
9+
*
10+
* http://aws.amazon.com/apache2.0
11+
*
12+
* or in the "license" file accompanying this file. This file is distributed on
13+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
package com.uber.cadence.internal.compatibility.proto.mappers;
19+
20+
import static org.junit.Assert.assertEquals;
21+
22+
import com.google.protobuf.Any;
23+
import com.google.protobuf.Message;
24+
import com.uber.cadence.api.v1.*;
25+
import io.grpc.Status;
26+
import io.grpc.StatusRuntimeException;
27+
import io.grpc.protobuf.StatusProto;
28+
import java.util.Arrays;
29+
import java.util.Collection;
30+
import org.junit.Test;
31+
import org.junit.runner.RunWith;
32+
import org.junit.runners.Parameterized;
33+
34+
@RunWith(Parameterized.class)
35+
public class ErrorMapperTest {
36+
37+
@Parameterized.Parameter(0)
38+
public Status status;
39+
40+
@Parameterized.Parameter(1)
41+
public Message detail;
42+
43+
@Parameterized.Parameter(2)
44+
public Class<Throwable> expectedException;
45+
46+
@Parameterized.Parameters
47+
public static Collection<Object[]> data() {
48+
Object[][] data =
49+
new Object[][] {
50+
{
51+
Status.PERMISSION_DENIED,
52+
null,
53+
com.uber.cadence.serviceclient.exceptions.AccessDeniedError.class
54+
},
55+
{
56+
Status.INTERNAL,
57+
null,
58+
com.uber.cadence.serviceclient.exceptions.InternalServiceError.class
59+
},
60+
{
61+
Status.NOT_FOUND,
62+
null,
63+
com.uber.cadence.serviceclient.exceptions.EntityNotExistsError.class
64+
},
65+
{
66+
Status.ALREADY_EXISTS,
67+
DomainAlreadyExistsError.getDefaultInstance(),
68+
com.uber.cadence.serviceclient.exceptions.DomainAlreadyExistsError.class
69+
},
70+
{
71+
Status.FAILED_PRECONDITION,
72+
FeatureNotEnabledError.getDefaultInstance(),
73+
com.uber.cadence.serviceclient.exceptions.FeatureNotEnabledError.class
74+
},
75+
{
76+
Status.RESOURCE_EXHAUSTED,
77+
LimitExceededError.getDefaultInstance(),
78+
com.uber.cadence.serviceclient.exceptions.LimitExceededError.class
79+
},
80+
{
81+
Status.UNKNOWN, null, com.uber.cadence.serviceclient.exceptions.ServiceClientError.class
82+
},
83+
{
84+
Status.NOT_FOUND,
85+
WorkflowExecutionAlreadyCompletedError.getDefaultInstance(),
86+
com.uber.cadence.serviceclient.exceptions.WorkflowExecutionAlreadyCompletedError.class
87+
},
88+
{
89+
Status.ALREADY_EXISTS,
90+
WorkflowExecutionAlreadyStartedError.getDefaultInstance(),
91+
com.uber.cadence.serviceclient.exceptions.WorkflowExecutionAlreadyStartedError.class
92+
},
93+
{
94+
Status.FAILED_PRECONDITION,
95+
DomainNotActiveError.getDefaultInstance(),
96+
com.uber.cadence.serviceclient.exceptions.DomainNotActiveError.class
97+
},
98+
{
99+
Status.FAILED_PRECONDITION,
100+
ClientVersionNotSupportedError.getDefaultInstance(),
101+
com.uber.cadence.serviceclient.exceptions.ClientVersionNotSupportedError.class
102+
},
103+
{
104+
Status.FAILED_PRECONDITION,
105+
FeatureNotEnabledError.getDefaultInstance(),
106+
com.uber.cadence.serviceclient.exceptions.FeatureNotEnabledError.class
107+
},
108+
{
109+
Status.FAILED_PRECONDITION,
110+
DomainNotActiveError.getDefaultInstance(),
111+
com.uber.cadence.serviceclient.exceptions.DomainNotActiveError.class
112+
},
113+
{
114+
Status.FAILED_PRECONDITION,
115+
ClientVersionNotSupportedError.getDefaultInstance(),
116+
com.uber.cadence.serviceclient.exceptions.ClientVersionNotSupportedError.class
117+
},
118+
{
119+
Status.FAILED_PRECONDITION,
120+
FeatureNotEnabledError.getDefaultInstance(),
121+
com.uber.cadence.serviceclient.exceptions.FeatureNotEnabledError.class
122+
},
123+
{
124+
Status.RESOURCE_EXHAUSTED,
125+
LimitExceededError.getDefaultInstance(),
126+
com.uber.cadence.serviceclient.exceptions.LimitExceededError.class
127+
},
128+
{
129+
Status.DATA_LOSS,
130+
null,
131+
com.uber.cadence.serviceclient.exceptions.InternalDataInconsistencyError.class
132+
},
133+
{
134+
Status.RESOURCE_EXHAUSTED,
135+
ServiceBusyError.getDefaultInstance(),
136+
com.uber.cadence.serviceclient.exceptions.ServiceBusyError.class
137+
},
138+
{
139+
Status.INTERNAL,
140+
null,
141+
com.uber.cadence.serviceclient.exceptions.InternalServiceError.class
142+
}
143+
};
144+
return Arrays.asList(data);
145+
}
146+
147+
@Test
148+
public void testErrorMapper() {
149+
com.google.rpc.Status.Builder builder =
150+
com.google.rpc.Status.newBuilder().setCode(status.getCode().value());
151+
152+
if (detail != null) {
153+
builder.addDetails(Any.pack(detail));
154+
}
155+
156+
StatusRuntimeException ex = StatusProto.toStatusRuntimeException(builder.build());
157+
com.uber.cadence.serviceclient.exceptions.ServiceClientError result = ErrorMapper.Error(ex);
158+
assertEquals(expectedException, result.getClass());
159+
}
160+
}

0 commit comments

Comments
 (0)