From 9d99ecf807405ae97ae80c186d8d8300246fc463 Mon Sep 17 00:00:00 2001 From: Shijie Sheng Date: Mon, 21 Oct 2024 12:15:16 -0700 Subject: [PATCH] redo unit test --- tools/cli/app_test.go | 57 ++++--- tools/cli/utils_test.go | 25 +++ tools/cli/workflow_commands.go | 2 +- tools/cli/workflow_commands_test.go | 251 ++++++++++++++++++++++++++++ 4 files changed, 310 insertions(+), 25 deletions(-) diff --git a/tools/cli/app_test.go b/tools/cli/app_test.go index eacd17852e1..fbd23fada96 100644 --- a/tools/cli/app_test.go +++ b/tools/cli/app_test.go @@ -29,6 +29,7 @@ import ( "github.com/olekukonko/tablewriter" "github.com/olivere/elastic" "github.com/pborman/uuid" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "github.com/urfave/cli/v2" @@ -39,13 +40,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) @@ -105,6 +115,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) @@ -417,15 +443,6 @@ func (s *cliAppSuite) TestSignalWorkflow_Failed() { s.Error(s.app.Run([]string{"", "--do", domainName, "workflow", "signal", "-w", "wid", "-n", "signal-name"})) } -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) -} - func (s *cliAppSuite) TestQueryWorkflowUsingStackTrace() { resp := &types.QueryWorkflowResponse{ QueryResult: []byte("query-result"), @@ -435,14 +452,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 diff --git a/tools/cli/utils_test.go b/tools/cli/utils_test.go index 7680b864b5d..effcfa7709a 100644 --- a/tools/cli/utils_test.go +++ b/tools/cli/utils_test.go @@ -30,6 +30,31 @@ import ( "github.com/uber/cadence/common/types" ) +func Test_JSONHistorySerializer(t *testing.T) { + serializer := JSONHistorySerializer{} + h := &types.History{ + Events: []*types.HistoryEvent{ + { + ID: 1, + Version: 1, + EventType: types.EventTypeWorkflowExecutionStarted.Ptr(), + }, + { + ID: 2, + Version: 1, + EventType: types.EventTypeDecisionTaskScheduled.Ptr(), + }, + }, + } + data, err := serializer.Serialize(h) + assert.NoError(t, err) + assert.NotNil(t, data) + + h2, err := serializer.Deserialize(data) + assert.NoError(t, err) + assert.Equal(t, h, h2) +} + func Test_ParseIntMultiRange(t *testing.T) { tests := []struct { name string diff --git a/tools/cli/workflow_commands.go b/tools/cli/workflow_commands.go index e4546af4f28..83cc74f0a13 100644 --- a/tools/cli/workflow_commands.go +++ b/tools/cli/workflow_commands.go @@ -1080,7 +1080,7 @@ func describeWorkflowHelper(c *cli.Context, wid, rid string) error { } else { o, err = convertDescribeWorkflowExecutionResponse(resp, frontendClient, c) if err != nil { - return commoncli.Problem("WF helper describe failed: ", err) + return commoncli.Problem("convert describe workflow response failed: ", err) } } diff --git a/tools/cli/workflow_commands_test.go b/tools/cli/workflow_commands_test.go index 5122c60fa84..08f54d0c27d 100644 --- a/tools/cli/workflow_commands_test.go +++ b/tools/cli/workflow_commands_test.go @@ -26,17 +26,20 @@ import ( "context" "errors" "flag" + "fmt" "testing" "time" "github.com/golang/mock/gomock" "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/mocktracer" + "github.com/pborman/uuid" "github.com/stretchr/testify/assert" "github.com/urfave/cli/v2" "github.com/uber/cadence/client/admin" "github.com/uber/cadence/client/frontend" + "github.com/uber/cadence/common" "github.com/uber/cadence/common/types" ) @@ -674,3 +677,251 @@ func Test_ResetWorkflow_Missing_RunID(t *testing.T) { err := ResetWorkflow(c) assert.Error(t, err) } + +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) 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) 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) 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) TestQueryWorkflow() { + 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) 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) 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) TestSignalWithStartWorkflowExecution() { + s.testcaseHelper([]testcase{ + { + name: "happy", + 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(&types.StartWorkflowExecutionResponse{}, nil) + }, + }, + { + 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", + }, + }) +}