From 2da5fe476c2b8760bcb0a1a43c580af67bc10467 Mon Sep 17 00:00:00 2001 From: Jakob Haahr Taankvist Date: Thu, 28 Nov 2024 20:48:11 +0100 Subject: [PATCH] Test for TestWorkflowMutableStateImpl (#979) --- .../TestWorkflowMutableStateAttrUtil.java | 96 ++++++++++++++ .../TestWorkflowMutableStateImpl.java | 73 +---------- ...eritUnsetPropertiesFromParentWorkflow.java | 98 ++++++++++++++ ...Util_validateScheduleActivityTaskTest.java | 124 ++++++++++++++++++ ...validateStartChildExecutionAttributes.java | 101 ++++++++++++++ 5 files changed, 422 insertions(+), 70 deletions(-) create mode 100644 src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil.java create mode 100644 src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_inheritUnsetPropertiesFromParentWorkflow.java create mode 100644 src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateScheduleActivityTaskTest.java create mode 100644 src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateStartChildExecutionAttributes.java diff --git a/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil.java b/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil.java new file mode 100644 index 000000000..bffb9ba70 --- /dev/null +++ b/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil.java @@ -0,0 +1,96 @@ +/* + * + * * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * * + * * Modifications copyright (C) 2017 Uber Technologies, Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"). You may not + * * use this file except in compliance with the License. A copy of the License is + * * located at + * * + * * http://aws.amazon.com/apache2.0 + * * + * * or in the "license" file accompanying this file. This file 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. + * + */ + +package com.uber.cadence.internal.testservice; + +import com.uber.cadence.*; + +public class TestWorkflowMutableStateAttrUtil { + + static void validateScheduleActivityTask(ScheduleActivityTaskDecisionAttributes a) + throws BadRequestError { + if (a == null) { + throw new BadRequestError("ScheduleActivityTaskDecisionAttributes is not set on decision."); + } + + if (a.getTaskList() == null || a.getTaskList().getName().isEmpty()) { + throw new BadRequestError("TaskList is not set on decision."); + } + if (a.getActivityId() == null || a.getActivityId().isEmpty()) { + throw new BadRequestError("ActivityId is not set on decision."); + } + if (a.getActivityType() == null + || a.getActivityType().getName() == null + || a.getActivityType().getName().isEmpty()) { + throw new BadRequestError("ActivityType is not set on decision."); + } + if (a.getStartToCloseTimeoutSeconds() <= 0) { + throw new BadRequestError("A valid StartToCloseTimeoutSeconds is not set on decision."); + } + if (a.getScheduleToStartTimeoutSeconds() <= 0) { + throw new BadRequestError("A valid ScheduleToStartTimeoutSeconds is not set on decision."); + } + if (a.getScheduleToCloseTimeoutSeconds() <= 0) { + throw new BadRequestError("A valid ScheduleToCloseTimeoutSeconds is not set on decision."); + } + if (a.getHeartbeatTimeoutSeconds() < 0) { + throw new BadRequestError("Ac valid HeartbeatTimeoutSeconds is not set on decision."); + } + } + + static void validateStartChildExecutionAttributes(StartChildWorkflowExecutionDecisionAttributes a) + throws BadRequestError { + if (a == null) { + throw new BadRequestError( + "StartChildWorkflowExecutionDecisionAttributes is not set on decision."); + } + + if (a.getWorkflowId().isEmpty()) { + throw new BadRequestError("Required field WorkflowID is not set on decision."); + } + + if (a.getWorkflowType() == null || a.getWorkflowType().getName().isEmpty()) { + throw new BadRequestError("Required field WorkflowType is not set on decision."); + } + + RetryPolicy retryPolicy = a.getRetryPolicy(); + if (retryPolicy != null) { + RetryState.validateRetryPolicy(retryPolicy); + } + } + + public static void inheritUnsetPropertiesFromParentWorkflow( + StartWorkflowExecutionRequest startRequest, StartChildWorkflowExecutionDecisionAttributes a) { + // Inherit tasklist from parent workflow execution if not provided on decision + if (a.getTaskList() == null || a.getTaskList().getName().isEmpty()) { + a.setTaskList(startRequest.getTaskList()); + } + + // Inherit workflow timeout from parent workflow execution if not provided on decision + if (a.getExecutionStartToCloseTimeoutSeconds() <= 0) { + a.setExecutionStartToCloseTimeoutSeconds( + startRequest.getExecutionStartToCloseTimeoutSeconds()); + } + + // Inherit decision task timeout from parent workflow execution if not provided on decision + if (a.getTaskStartToCloseTimeoutSeconds() <= 0) { + a.setTaskStartToCloseTimeoutSeconds(startRequest.getTaskStartToCloseTimeoutSeconds()); + } + } +} diff --git a/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateImpl.java b/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateImpl.java index e2a80afbb..79ac3dd26 100644 --- a/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateImpl.java +++ b/src/main/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateImpl.java @@ -17,6 +17,8 @@ package com.uber.cadence.internal.testservice; +import static com.uber.cadence.internal.testservice.TestWorkflowMutableStateAttrUtil.*; + import com.cronutils.model.Cron; import com.cronutils.model.CronType; import com.cronutils.model.definition.CronDefinition; @@ -72,7 +74,6 @@ import com.uber.cadence.RespondDecisionTaskCompletedRequest; import com.uber.cadence.RespondDecisionTaskFailedRequest; import com.uber.cadence.RespondQueryTaskCompletedRequest; -import com.uber.cadence.RetryPolicy; import com.uber.cadence.ScheduleActivityTaskDecisionAttributes; import com.uber.cadence.SignalExternalWorkflowExecutionDecisionAttributes; import com.uber.cadence.SignalExternalWorkflowExecutionFailedCause; @@ -592,87 +593,19 @@ private void processScheduleActivityTask( ctx.lockTimer(); } - private void validateScheduleActivityTask(ScheduleActivityTaskDecisionAttributes a) - throws BadRequestError { - if (a == null) { - throw new BadRequestError("ScheduleActivityTaskDecisionAttributes is not set on decision."); - } - - if (a.getTaskList() == null || a.getTaskList().getName().isEmpty()) { - throw new BadRequestError("TaskList is not set on decision."); - } - if (a.getActivityId() == null || a.getActivityId().isEmpty()) { - throw new BadRequestError("ActivityId is not set on decision."); - } - if (a.getActivityType() == null - || a.getActivityType().getName() == null - || a.getActivityType().getName().isEmpty()) { - throw new BadRequestError("ActivityType is not set on decision."); - } - if (a.getStartToCloseTimeoutSeconds() <= 0) { - throw new BadRequestError("A valid StartToCloseTimeoutSeconds is not set on decision."); - } - if (a.getScheduleToStartTimeoutSeconds() <= 0) { - throw new BadRequestError("A valid ScheduleToStartTimeoutSeconds is not set on decision."); - } - if (a.getScheduleToCloseTimeoutSeconds() <= 0) { - throw new BadRequestError("A valid ScheduleToCloseTimeoutSeconds is not set on decision."); - } - if (a.getHeartbeatTimeoutSeconds() < 0) { - throw new BadRequestError("Ac valid HeartbeatTimeoutSeconds is not set on decision."); - } - } - private void processStartChildWorkflow( RequestContext ctx, StartChildWorkflowExecutionDecisionAttributes a, long decisionTaskCompletedId) throws BadRequestError, InternalServiceError { validateStartChildExecutionAttributes(a); + inheritUnsetPropertiesFromParentWorkflow(startRequest, a); StateMachine child = StateMachines.newChildWorkflowStateMachine(service); childWorkflows.put(ctx.getNextEventId(), child); child.action(StateMachines.Action.INITIATE, ctx, a, decisionTaskCompletedId); ctx.lockTimer(); } - /** Clone of the validateStartChildExecutionAttributes from historyEngine.go */ - private void validateStartChildExecutionAttributes( - StartChildWorkflowExecutionDecisionAttributes a) throws BadRequestError { - if (a == null) { - throw new BadRequestError( - "StartChildWorkflowExecutionDecisionAttributes is not set on decision."); - } - - if (a.getWorkflowId().isEmpty()) { - throw new BadRequestError("Required field WorkflowID is not set on decision."); - } - - if (a.getWorkflowType() == null || a.getWorkflowType().getName().isEmpty()) { - throw new BadRequestError("Required field WorkflowType is not set on decision."); - } - - // Inherit tasklist from parent workflow execution if not provided on decision - if (a.getTaskList() == null || a.getTaskList().getName().isEmpty()) { - a.setTaskList(startRequest.getTaskList()); - } - - // Inherit workflow timeout from parent workflow execution if not provided on decision - if (a.getExecutionStartToCloseTimeoutSeconds() <= 0) { - a.setExecutionStartToCloseTimeoutSeconds( - startRequest.getExecutionStartToCloseTimeoutSeconds()); - } - - // Inherit decision task timeout from parent workflow execution if not provided on decision - if (a.getTaskStartToCloseTimeoutSeconds() <= 0) { - a.setTaskStartToCloseTimeoutSeconds(startRequest.getTaskStartToCloseTimeoutSeconds()); - } - - RetryPolicy retryPolicy = a.getRetryPolicy(); - if (retryPolicy != null) { - RetryState.validateRetryPolicy(retryPolicy); - } - } - private void processSignalExternalWorkflowExecution( RequestContext ctx, SignalExternalWorkflowExecutionDecisionAttributes a, diff --git a/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_inheritUnsetPropertiesFromParentWorkflow.java b/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_inheritUnsetPropertiesFromParentWorkflow.java new file mode 100644 index 000000000..44fef7c31 --- /dev/null +++ b/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_inheritUnsetPropertiesFromParentWorkflow.java @@ -0,0 +1,98 @@ +/* + * + * * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * * + * * Modifications copyright (C) 2017 Uber Technologies, Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"). You may not + * * use this file except in compliance with the License. A copy of the License is + * * located at + * * + * * http://aws.amazon.com/apache2.0 + * * + * * or in the "license" file accompanying this file. This file 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. + * + */ + +package com.uber.cadence.internal.testservice; + +import static com.uber.cadence.internal.testservice.TestWorkflowMutableStateAttrUtil.validateStartChildExecutionAttributes; + +import com.uber.cadence.RetryPolicy; +import com.uber.cadence.StartChildWorkflowExecutionDecisionAttributes; +import com.uber.cadence.WorkflowType; +import java.util.Arrays; +import java.util.Collection; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class TestWorkflowMutableStateAttrUtil_inheritUnsetPropertiesFromParentWorkflow + extends TestCase { + + private final StartChildWorkflowExecutionDecisionAttributes attributes; + private final String errorMessage; + + public TestWorkflowMutableStateAttrUtil_inheritUnsetPropertiesFromParentWorkflow( + String testName, + StartChildWorkflowExecutionDecisionAttributes attributes, + String errorMessage) { + this.attributes = attributes; + this.errorMessage = errorMessage; + } + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {"valid", createAtt(), null}, + {"null", null, "StartChildWorkflowExecutionDecisionAttributes is not set on decision."}, + { + "WorkflowId empty", + createAtt().setWorkflowId(""), + "Required field WorkflowID is not set on decision." + }, + { + "WorkflowType null", + createAtt().setWorkflowType(null), + "Required field WorkflowType is not set on decision." + }, + { + "WorkflowType name empty", + createAtt().setWorkflowType(new WorkflowType().setName("")), + "Required field WorkflowType is not set on decision." + }, + {"RetryPolicy null", createAtt().setRetryPolicy(null), null}, + }); + } + + @Test + public void testValidateScheduleActivityTask() { + try { + validateStartChildExecutionAttributes(attributes); + if (errorMessage != null) { + fail("Expected exception"); + } + } catch (Exception e) { + assertEquals(errorMessage, e.getMessage()); + } + } + + private static StartChildWorkflowExecutionDecisionAttributes createAtt() { + return new StartChildWorkflowExecutionDecisionAttributes() + .setWorkflowId("testWorkflowId") + .setWorkflowType(new WorkflowType().setName("testWorkflowType")) + .setRetryPolicy( + new RetryPolicy() + .setInitialIntervalInSeconds(12) + .setBackoffCoefficient(3.4) + .setMaximumIntervalInSeconds(56) + .setMaximumAttempts(78) + .setExpirationIntervalInSeconds(99)); + } +} diff --git a/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateScheduleActivityTaskTest.java b/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateScheduleActivityTaskTest.java new file mode 100644 index 000000000..2156979fc --- /dev/null +++ b/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateScheduleActivityTaskTest.java @@ -0,0 +1,124 @@ +/* + * + * * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * * + * * Modifications copyright (C) 2017 Uber Technologies, Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"). You may not + * * use this file except in compliance with the License. A copy of the License is + * * located at + * * + * * http://aws.amazon.com/apache2.0 + * * + * * or in the "license" file accompanying this file. This file 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. + * + */ + +package com.uber.cadence.internal.testservice; + +import com.uber.cadence.ActivityType; +import com.uber.cadence.ScheduleActivityTaskDecisionAttributes; +import com.uber.cadence.TaskList; +import java.util.Arrays; +import java.util.Collection; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class TestWorkflowMutableStateAttrUtil_validateScheduleActivityTaskTest extends TestCase { + + private final ScheduleActivityTaskDecisionAttributes attributes; + private final String errorMessage; + + public TestWorkflowMutableStateAttrUtil_validateScheduleActivityTaskTest( + String testName, ScheduleActivityTaskDecisionAttributes attributes, String errorMessage) { + this.attributes = attributes; + this.errorMessage = errorMessage; + } + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {"valid", createAtt(), null}, + {"null", null, "ScheduleActivityTaskDecisionAttributes is not set on decision."}, + {"task list null", createAtt().setTaskList(null), "TaskList is not set on decision."}, + { + "task list no name", + createAtt().setTaskList(new TaskList().setName("")), + "TaskList is not set on decision." + }, + { + "activity id null", + createAtt().setActivityId(null), + "ActivityId is not set on decision." + }, + { + "activity id empty", createAtt().setActivityId(""), "ActivityId is not set on decision." + }, + { + "activity type null", + createAtt().setActivityType(null), + "ActivityType is not set on decision." + }, + { + "activity type name null", + createAtt().setActivityType(new ActivityType().setName(null)), + "ActivityType is not set on decision." + }, + { + "activity type name empty", + createAtt().setActivityType(new ActivityType().setName("")), + "ActivityType is not set on decision." + }, + { + "start to close <= 0", + createAtt().setStartToCloseTimeoutSeconds(0), + "A valid StartToCloseTimeoutSeconds is not set on decision." + }, + { + "schedule to start <= 0", + createAtt().setScheduleToStartTimeoutSeconds(0), + "A valid ScheduleToStartTimeoutSeconds is not set on decision." + }, + { + "schedule to close <= 0", + createAtt().setScheduleToCloseTimeoutSeconds(0), + "A valid ScheduleToCloseTimeoutSeconds is not set on decision." + }, + { + "heartbeat < 0", + createAtt().setHeartbeatTimeoutSeconds(-1), + "Ac valid HeartbeatTimeoutSeconds is not set on decision." + }, + }); + } + + @Test + public void testValidateScheduleActivityTask() { + try { + TestWorkflowMutableStateAttrUtil.validateScheduleActivityTask(attributes); + if (errorMessage != null) { + fail("Expected exception"); + } + } catch (Exception e) { + assertEquals(errorMessage, e.getMessage()); + } + } + + private static ScheduleActivityTaskDecisionAttributes createAtt() { + return new ScheduleActivityTaskDecisionAttributes() + .setTaskList(new TaskList().setName("testTaskList")) + .setActivityId("testActivityId") + .setActivityType(new ActivityType().setName("testActivityType")) + .setStartToCloseTimeoutSeconds(12) + .setScheduleToStartTimeoutSeconds(34) + .setScheduleToCloseTimeoutSeconds(45) + .setHeartbeatTimeoutSeconds(78); + } +} diff --git a/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateStartChildExecutionAttributes.java b/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateStartChildExecutionAttributes.java new file mode 100644 index 000000000..43776b1be --- /dev/null +++ b/src/test/java/com/uber/cadence/internal/testservice/TestWorkflowMutableStateAttrUtil_validateStartChildExecutionAttributes.java @@ -0,0 +1,101 @@ +/* + * + * * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * * + * * Modifications copyright (C) 2017 Uber Technologies, Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"). You may not + * * use this file except in compliance with the License. A copy of the License is + * * located at + * * + * * http://aws.amazon.com/apache2.0 + * * + * * or in the "license" file accompanying this file. This file 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. + * + */ + +package com.uber.cadence.internal.testservice; + +import static com.uber.cadence.internal.testservice.TestWorkflowMutableStateAttrUtil.inheritUnsetPropertiesFromParentWorkflow; + +import com.uber.cadence.*; +import java.util.Arrays; +import java.util.Collection; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class TestWorkflowMutableStateAttrUtil_validateStartChildExecutionAttributes + extends TestCase { + + private final StartChildWorkflowExecutionDecisionAttributes attributes; + private final StartChildWorkflowExecutionDecisionAttributes expectedAttributes; + + public TestWorkflowMutableStateAttrUtil_validateStartChildExecutionAttributes( + String testName, + StartChildWorkflowExecutionDecisionAttributes attributes, + StartChildWorkflowExecutionDecisionAttributes expectedAttributes) { + this.attributes = attributes; + this.expectedAttributes = expectedAttributes; + } + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {"all set", createAtt(), createAtt()}, + { + "empty", + new StartChildWorkflowExecutionDecisionAttributes(), + createAtt() + .setTaskList(new TaskList().setName("testTaskListFromParent")) + .setExecutionStartToCloseTimeoutSeconds(21) + .setTaskStartToCloseTimeoutSeconds(22) + }, + { + "taskList null", + createAtt().setTaskList(null), + createAtt().setTaskList(new TaskList().setName("testTaskListFromParent")) + }, + { + "taskList name empty", + createAtt().setTaskList(new TaskList().setName("")), + createAtt().setTaskList(new TaskList().setName("testTaskListFromParent")) + }, + { + "executionStartToCloseTimeoutSeconds", + createAtt().setExecutionStartToCloseTimeoutSeconds(0), + createAtt().setExecutionStartToCloseTimeoutSeconds(21) + }, + { + "taskStartToCloseTimeoutSeconds", + createAtt().setTaskStartToCloseTimeoutSeconds(0), + createAtt().setTaskStartToCloseTimeoutSeconds(22) + }, + }); + } + + @Test + public void testValidateScheduleActivityTask() { + StartWorkflowExecutionRequest startRequest = + new StartWorkflowExecutionRequest() + .setTaskList(new TaskList().setName("testTaskListFromParent")) + .setExecutionStartToCloseTimeoutSeconds(21) + .setTaskStartToCloseTimeoutSeconds(22); + + inheritUnsetPropertiesFromParentWorkflow(startRequest, attributes); + assertEquals(expectedAttributes, attributes); + } + + private static StartChildWorkflowExecutionDecisionAttributes createAtt() { + return new StartChildWorkflowExecutionDecisionAttributes() + .setTaskList(new TaskList().setName("testTaskList")) + .setExecutionStartToCloseTimeoutSeconds(11) + .setTaskStartToCloseTimeoutSeconds(12); + } +}