Skip to content

Commit

Permalink
add ability to mock start child workflow failed case (cadence-workflo…
Browse files Browse the repository at this point in the history
  • Loading branch information
yiminc authored Apr 24, 2018
1 parent 6f0bab8 commit 2ddd0bc
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 11 deletions.
2 changes: 1 addition & 1 deletion internal/internal_event_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ func (weh *workflowExecutionEventHandlerImpl) handleStartChildWorkflowExecutionF
return nil
}

err := fmt.Errorf("ChildWorkflowFailed: %v", attributes.GetCause())
err := fmt.Errorf("start child workflow failed: %v", attributes.GetCause())
childWorkflow.startedCallback(WorkflowExecution{}, err)
childWorkflow.handle(nil, err)

Expand Down
26 changes: 18 additions & 8 deletions internal/internal_workflow_testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,6 @@ func (env *testWorkflowEnvironmentImpl) executeWorkflowInternal(workflowType str
// In case of child workflow, this executeWorkflowInternal() is run in separate goroutinue, so use postCallback
// to make sure workflowDef.Execute() is run in main loop.
env.postCallback(func() {
if env.isChildWorkflow() {
// notify parent that child workflow is started
env.parentEnv.postCallback(func() {
env.startedHandler(env.workflowInfo.WorkflowExecution, nil)
}, true)
}

env.workflowDef.Execute(env, input)
}, false)
env.startMainLoop()
Expand Down Expand Up @@ -968,8 +961,25 @@ func (w *workflowExecutorWrapper) Execute(ctx Context, input []byte) (result []b
// ExecuteUntilAllBlocked() returns).
env.runningCount--

childWE := env.workflowInfo.WorkflowExecution
var startedErr error
if mockRet != nil {
return m.executeMock(ctx, input, mockRet)
// workflow was mocked.
result, err = m.executeMock(ctx, input, mockRet)
if env.isChildWorkflow() && err == ErrMockStartChildWorkflowFailed {
childWE, startedErr = WorkflowExecution{}, err
}
}

if env.isChildWorkflow() {
// notify parent that child workflow is started
env.parentEnv.postCallback(func() {
env.startedHandler(childWE, startedErr)
}, true)
}

if mockRet != nil {
return result, err
}

// no mock, so call the actual workflow
Expand Down
22 changes: 22 additions & 0 deletions internal/internal_workflow_testsuite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,28 @@ func (s *WorkflowTestSuiteUnitTest) Test_ChildWorkflow_Mock() {
s.Equal("mock_msg mock_msg mock_heartbeat", actualResult)
}

func (s *WorkflowTestSuiteUnitTest) Test_ChildWorkflow_StartFailed() {
workflowFn := func(ctx Context) (string, error) {
cwo := ChildWorkflowOptions{ExecutionStartToCloseTimeout: time.Minute}
ctx = WithChildWorkflowOptions(ctx, cwo)
err := ExecuteChildWorkflow(ctx, testWorkflowHello).GetChildWorkflowExecution().Get(ctx, nil)
if err != nil {
return "", errors.New("fail to start child")
}

return "should-not-go-here", nil
}

RegisterWorkflow(workflowFn)
env := s.NewTestWorkflowEnvironment()
env.OnWorkflow(testWorkflowHello, mock.Anything).Return("", ErrMockStartChildWorkflowFailed)
env.ExecuteWorkflow(workflowFn)

s.True(env.IsWorkflowCompleted())
s.Error(env.GetWorkflowError())
s.Equal("fail to start child", env.GetWorkflowError().Error())
}

func (s *WorkflowTestSuiteUnitTest) Test_ChildWorkflow_Listener() {
workflowFn := func(ctx Context) (string, error) {
ctx = WithActivityOptions(ctx, s.activityOptions)
Expand Down
11 changes: 9 additions & 2 deletions internal/workflow_testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ package internal

import (
"context"
"fmt"
"reflect"
"time"

"go.uber.org/cadence/encoded"

"github.com/stretchr/testify/mock"
"github.com/uber-go/tally"
"go.uber.org/cadence/.gen/go/shared"
"go.uber.org/cadence/encoded"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -168,6 +169,10 @@ func (t *TestWorkflowEnvironment) OnActivity(activity interface{}, args ...inter
return t.wrapCall(call)
}

// ErrMockStartChildWorkflowFailed is special error used to indicate the mocked child workflow should fail to start.
// This error is also exposed as public as testsuite.ErrMockStartChildWorkflowFailed
var ErrMockStartChildWorkflowFailed = fmt.Errorf("start child workflow failed: %v", shared.ChildWorkflowExecutionFailedCauseWorkflowAlreadyRunning)

// OnWorkflow setup a mock call for workflow. Parameter workflow must be workflow function (func) or workflow name (string).
// You must call Return() with appropriate parameters on the returned *MockCallWrapper instance. The supplied parameters to
// the Return() call should either be a function that has exact same signature as the mocked workflow, or it should be
Expand All @@ -181,6 +186,8 @@ func (t *TestWorkflowEnvironment) OnActivity(activity interface{}, args ...inter
// })
// OR return mock values with same types as workflow function's return types:
// t.OnWorkflow(MyChildWorkflow, mock.Anything, mock.Anything).Return("mock_result", nil)
// You could also setup mock to simulate start child workflow failure case by returning ErrMockStartChildWorkflowFailed
// as error.
func (t *TestWorkflowEnvironment) OnWorkflow(workflow interface{}, args ...interface{}) *MockCallWrapper {
fType := reflect.TypeOf(workflow)
var call *mock.Call
Expand Down
3 changes: 3 additions & 0 deletions testsuite/testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ type (
// MockCallWrapper is a wrapper to mock.Call. It offers the ability to wait on workflow's clock instead of wall clock.
MockCallWrapper = internal.MockCallWrapper
)

// ErrMockStartChildWorkflowFailed is special error used to indicate the mocked child workflow should fail to start.
var ErrMockStartChildWorkflowFailed = internal.ErrMockStartChildWorkflowFailed

0 comments on commit 2ddd0bc

Please sign in to comment.