Skip to content

Commit

Permalink
[CLI] add unit test to workflow_commands
Browse files Browse the repository at this point in the history
  • Loading branch information
shijiesheng committed Oct 21, 2024
1 parent e1bb082 commit 0cbbfa1
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 42 deletions.
2 changes: 1 addition & 1 deletion idls
Submodule idls updated 1 files
+0 −7 thrift/sqlblobs.thrift
309 changes: 269 additions & 40 deletions tools/cli/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package cli

import (
"fmt"
"strings"
"testing"
"time"
Expand All @@ -40,13 +41,22 @@ import (
"github.com/uber/cadence/common/types"
)

type cliAppSuite struct {
suite.Suite
app *cli.App
mockCtrl *gomock.Controller
serverFrontendClient *frontend.MockClient
serverAdminClient *admin.MockClient
}
type (
cliAppSuite struct {
suite.Suite
app *cli.App
mockCtrl *gomock.Controller
serverFrontendClient *frontend.MockClient
serverAdminClient *admin.MockClient
}

testcase struct {
name string
command string
err string
mock func()
}
)

var _ ClientFactory = (*clientFactoryMock)(nil)

Expand Down Expand Up @@ -106,6 +116,22 @@ func (s *cliAppSuite) TearDownTest() {
s.mockCtrl.Finish() // assert mock’s expectations
}

func (s *cliAppSuite) testcaseHelper(testcases []testcase) {
for _, tt := range testcases {
s.T().Run(tt.name, func(t *testing.T) {
if tt.mock != nil {
tt.mock()
}
err := s.app.Run(strings.Split(tt.command, " "))
if tt.err != "" {
assert.ErrorContains(t, err, tt.err)
} else {
assert.NoError(t, err)
}
})
}
}

func (s *cliAppSuite) TestAppCommands() {
for _, test := range commands {
cmd := s.app.Command(test)
Expand Down Expand Up @@ -418,13 +444,160 @@ func (s *cliAppSuite) TestSignalWorkflow_Failed() {
s.Error(s.app.Run([]string{"", "--do", domainName, "workflow", "signal", "-w", "wid", "-n", "signal-name"}))
}

func (s *cliAppSuite) TestDescribeWorkflow() {
s.testcaseHelper([]testcase{
{
"happy",
"cadence --do test-domain wf describe -w wid",
"",
func() {
resp := &types.DescribeWorkflowExecutionResponse{
WorkflowExecutionInfo: &types.WorkflowExecutionInfo{
Execution: &types.WorkflowExecution{
WorkflowID: "wid",
},
Type: &types.WorkflowType{
Name: "workflow-type",
},
StartTime: common.Int64Ptr(time.Now().UnixNano()),
CloseTime: common.Int64Ptr(time.Now().UnixNano()),
},
PendingActivities: []*types.PendingActivityInfo{
{},
},
PendingDecision: &types.PendingDecisionInfo{},
}
s.serverFrontendClient.EXPECT().DescribeWorkflowExecution(gomock.Any(), gomock.Any()).Return(resp, nil)
},
},
})
}

func (s *cliAppSuite) TestQueryWorkflow() {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().QueryWorkflow(gomock.Any(), gomock.Any()).Return(resp, nil)
err := s.app.Run([]string{"", "--do", domainName, "workflow", "query", "-w", "wid", "-qt", "query-type-test"})
s.Nil(err)
s.testcaseHelper([]testcase{
{
name: "happy",
command: `cadence --do test-domain wf query -w wid -qt query-type-test`,
err: "",
mock: func () {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().QueryWorkflow(gomock.Any(), gomock.Any()).Return(resp, nil)
},
},
{
name: "query with reject not_open",
command: `cadence --do test-domain wf query -w wid -qt query-type-test --query_reject_condition not_open`,
err: "",
mock: func () {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().
QueryWorkflow(gomock.Any(), &types.QueryWorkflowRequest{
Domain: "test-domain",
Execution: &types.WorkflowExecution{
WorkflowID: "wid",
},
Query: &types.WorkflowQuery{
QueryType: "query-type-test",
},
QueryRejectCondition: types.QueryRejectConditionNotOpen.Ptr(),
}).
Return(resp, nil)
},
},
{
name: "query with reject not_completed_cleanly",
command: `cadence --do test-domain wf query -w wid -qt query-type-test --query_reject_condition not_completed_cleanly`,
err: "",
mock: func () {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().
QueryWorkflow(gomock.Any(), &types.QueryWorkflowRequest{
Domain: "test-domain",
Execution: &types.WorkflowExecution{
WorkflowID: "wid",
},
Query: &types.WorkflowQuery{
QueryType: "query-type-test",
},
QueryRejectCondition: types.QueryRejectConditionNotCompletedCleanly.Ptr(),
}).
Return(resp, nil)
},
},
{
name: "query with unknown reject",
command: `cadence --do test-domain wf query -w wid -qt query-type-test --query_reject_condition unknown`,
err: "invalid reject condition",
},
{
name: "query with eventual consistency",
command: `cadence --do test-domain wf query -w wid -qt query-type-test --query_consistency_level eventual`,
err: "",
mock: func () {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().
QueryWorkflow(gomock.Any(), &types.QueryWorkflowRequest{
Domain: "test-domain",
Execution: &types.WorkflowExecution{
WorkflowID: "wid",
},
Query: &types.WorkflowQuery{
QueryType: "query-type-test",
},
QueryConsistencyLevel: types.QueryConsistencyLevelEventual.Ptr(),
}).
Return(resp, nil)
},
},
{
name: "query with strong consistency",
command: `cadence --do test-domain wf query -w wid -qt query-type-test --query_consistency_level strong`,
err: "",
mock: func () {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().
QueryWorkflow(gomock.Any(), &types.QueryWorkflowRequest{
Domain: "test-domain",
Execution: &types.WorkflowExecution{
WorkflowID: "wid",
},
Query: &types.WorkflowQuery{
QueryType: "query-type-test",
},
QueryConsistencyLevel: types.QueryConsistencyLevelStrong.Ptr(),
}).
Return(resp, nil)
},
},
{
name: "query with invalid consistency",
command: `cadence --do test-domain wf query -w wid -qt query-type-test --query_consistency_level invalid`,
err: "invalid query consistency level",
},
{
name: "failed",
command: `cadence --do test-domain wf query -w wid -qt query-type-test`,
err: "some error",
mock: func () {
s.serverFrontendClient.EXPECT().QueryWorkflow(gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("some error"))
},
},
{
name: "missing flags",
command: "cadence wf query",
err: "Required flag not found",
},
})
}

func (s *cliAppSuite) TestQueryWorkflowUsingStackTrace() {
Expand All @@ -436,14 +609,6 @@ func (s *cliAppSuite) TestQueryWorkflowUsingStackTrace() {
s.Nil(err)
}

func (s *cliAppSuite) TestQueryWorkflow_Failed() {
resp := &types.QueryWorkflowResponse{
QueryResult: []byte("query-result"),
}
s.serverFrontendClient.EXPECT().QueryWorkflow(gomock.Any(), gomock.Any()).Return(resp, &types.BadRequestError{"faked error"})
s.Error(s.app.Run([]string{"", "--do", domainName, "workflow", "query", "-w", "wid", "-qt", "query-type-test"}))
}

var (
closeStatus = types.WorkflowExecutionCloseStatusCompleted

Expand Down Expand Up @@ -483,6 +648,46 @@ var (
}
)

func (s *cliAppSuite) TestListAllWorkflow() {
s.testcaseHelper([]testcase{
{
name: "happy",
command: `cadence --do test-domain wf listall`,
mock: func () {
countWorkflowResp := &types.CountWorkflowExecutionsResponse{}
s.serverFrontendClient.EXPECT().CountWorkflowExecutions(gomock.Any(), gomock.Any()).Return(countWorkflowResp, nil)
s.serverFrontendClient.EXPECT().ListClosedWorkflowExecutions(gomock.Any(), gomock.Any()).Return(listClosedWorkflowExecutionsResponse, nil)
},
},
})
}

func (s *cliAppSuite) TestScanAllWorkflow() {
s.testcaseHelper([]testcase{
{
name: "happy",
command: `cadence --do test-domain wf scanall`,
mock: func () {
s.serverFrontendClient.EXPECT().ScanWorkflowExecutions(gomock.Any(), gomock.Any()).Return(&types.ListWorkflowExecutionsResponse{}, nil)
},
},
})
}

func (s *cliAppSuite) TestResetWorkflow() {
s.testcaseHelper([]testcase{
{
name: "happy",
command: `cadence --do test-domain wf reset -w wid -r rid -reason test-reason --event_id 1`,
err: "",
mock: func () {
resp := &types.ResetWorkflowExecutionResponse{RunID: uuid.New()}
s.serverFrontendClient.EXPECT().ResetWorkflowExecution(gomock.Any(), gomock.Any()).Return(resp, nil)
},
},
})
}

func (s *cliAppSuite) TestListWorkflow() {
resp := listClosedWorkflowExecutionsResponse
countWorkflowResp := &types.CountWorkflowExecutionsResponse{}
Expand Down Expand Up @@ -854,31 +1059,55 @@ func (s *cliAppSuite) TestParseBool() {
}

func (s *cliAppSuite) TestSignalWithStartWorkflowExecution() {
for _, tt := range []struct {
name string
command string
err string
mock func()
}{
s.testcaseHelper([]testcase{
{
name: "happy",
command: "cadence --do test-domain wf signalwithstart -w wid -n signal-name -i input",
command: `cadence --do test-domain wf signalwithstart --et 100 --workflow_type sometype --tasklist tasklist -w wid -n signal-name --signal_input []`,
err: "",
mock: func () {
s.serverFrontendClient.EXPECT().SignalWithStartWorkflowExecution(gomock.Any(), gomock.Any()).Return(nil)
s.serverFrontendClient.EXPECT().SignalWithStartWorkflowExecution(gomock.Any(), gomock.Any()).Return(&types.StartWorkflowExecutionResponse{}, nil)
},
},
} {
s.T().Run(tt.name, func(t *testing.T) {
tt.mock()
err := s.app.Run(strings.Split(tt.command, " "))
if tt.err != "" {
assert.ErrorContains(t, err, tt.err)
} else {
assert.NoError(t, err)
}
})
}
{
name: "failed",
command: `cadence --do test-domain wf signalwithstart --et 100 --workflow_type sometype --tasklist tasklist -w wid -n signal-name --signal_input []`,
err: "some error",
mock: func () {
s.serverFrontendClient.EXPECT().SignalWithStartWorkflowExecution(gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("some error"))
},
},
{
name: "missing flags",
command: "cadence wf signalwithstart",
err: "Required flag not found",
},
})
}

func (s *cliAppSuite) TestCompleteActivity() {
s.testcaseHelper([]testcase{
{
name: "happy",
command: `cadence --do test-domain wf activity complete -w wid -r rid -aid 3 -result result --identity tester`,
err: "",
mock: func () {
s.serverFrontendClient.EXPECT().RespondActivityTaskCompletedByID(gomock.Any(), gomock.Any()).Return(nil)
},
},
})
}

func (s *cliAppSuite) TestFailActivity() {
s.testcaseHelper([]testcase{
{
name: "happy",
command: `cadence --do test-domain wf activity fail -w wid -r rid -aid 3 --reason somereason --detail somedetail --identity tester`,
err: "",
mock: func () {
s.serverFrontendClient.EXPECT().RespondActivityTaskFailedByID(gomock.Any(), gomock.Any()).Return(nil)
},
},
})
}

func (s *cliAppSuite) TestConvertStringToRealType() {
Expand Down
4 changes: 3 additions & 1 deletion tools/cli/workflow_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,9 @@ func describeWorkflowHelper(c *cli.Context, wid, rid string) error {
o = resp
} else {
o, err = convertDescribeWorkflowExecutionResponse(resp, frontendClient, c)
return commoncli.Problem("WF helper describe failed: ", err)
if err != nil {
return commoncli.Problem("convert describe workflow response failed: ", err)
}
}

prettyPrintJSONObject(o)
Expand Down

0 comments on commit 0cbbfa1

Please sign in to comment.