From 56d6cb476d72e6f7b50d277d7b18b673156ec215 Mon Sep 17 00:00:00 2001 From: Abhishek Jha Date: Fri, 5 Apr 2024 18:18:46 -0700 Subject: [PATCH 1/4] Added transmissionHandler mock to generate cases --- common/domain/handler_test.go | 30 ++++++++ common/domain/transmissionTaskHandler.go | 2 + common/domain/transmissionTaskHandler_mock.go | 72 +++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 common/domain/transmissionTaskHandler_mock.go diff --git a/common/domain/handler_test.go b/common/domain/handler_test.go index be24d2fee08..59a1d3db64f 100644 --- a/common/domain/handler_test.go +++ b/common/domain/handler_test.go @@ -189,6 +189,36 @@ func TestRegisterDomain(t *testing.T) { wantErr: true, expectedErr: &types.BadRequestError{}, }, + { + name: "invalid history archival configuration", + request: &types.RegisterDomainRequest{ + Name: "test-domain-invalid-archival-config", + HistoryArchivalStatus: types.ArchivalStatusEnabled.Ptr(), + HistoryArchivalURI: "invalid-uri", + IsGlobalDomain: true, + }, + isPrimaryCluster: true, + mockSetup: func(mockDomainMgr *persistence.MockDomainManager, request *types.RegisterDomainRequest) { + mockDomainMgr.EXPECT().GetDomain(gomock.Any(), &persistence.GetDomainRequest{Name: request.Name}).Return(nil, &types.EntityNotExistsError{}) + }, + wantErr: true, + expectedErr: errInvalidArchivalConfig, + }, + { + name: "error during domain creation", + request: &types.RegisterDomainRequest{ + Name: "domain-creation-error", + WorkflowExecutionRetentionPeriodInDays: 2, + IsGlobalDomain: false, + }, + isPrimaryCluster: true, + mockSetup: func(mockDomainMgr *persistence.MockDomainManager, request *types.RegisterDomainRequest) { + mockDomainMgr.EXPECT().GetDomain(gomock.Any(), &persistence.GetDomainRequest{Name: request.Name}).Return(nil, &types.EntityNotExistsError{}) + + mockDomainMgr.EXPECT().CreateDomain(gomock.Any(), gomock.Any()).Return(nil, errors.New("creation failed")) + }, + wantErr: true, + }, } for _, tc := range tests { diff --git a/common/domain/transmissionTaskHandler.go b/common/domain/transmissionTaskHandler.go index e0b4825d1e2..e1bdbf532a0 100644 --- a/common/domain/transmissionTaskHandler.go +++ b/common/domain/transmissionTaskHandler.go @@ -18,6 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +//go:generate mockgen -package $GOPACKAGE -source $GOFILE -destination transmissionTaskHandler_mock.go + package domain import ( diff --git a/common/domain/transmissionTaskHandler_mock.go b/common/domain/transmissionTaskHandler_mock.go new file mode 100644 index 00000000000..a456b62fa62 --- /dev/null +++ b/common/domain/transmissionTaskHandler_mock.go @@ -0,0 +1,72 @@ +// Copyright (c) 2020 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// Code generated by MockGen. DO NOT EDIT. +// Source: transmissionTaskHandler.go + +// Package domain is a generated GoMock package. +package domain + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + + persistence "github.com/uber/cadence/common/persistence" + types "github.com/uber/cadence/common/types" +) + +// MockReplicator is a mock of Replicator interface. +type MockReplicator struct { + ctrl *gomock.Controller + recorder *MockReplicatorMockRecorder +} + +// MockReplicatorMockRecorder is the mock recorder for MockReplicator. +type MockReplicatorMockRecorder struct { + mock *MockReplicator +} + +// NewMockReplicator creates a new mock instance. +func NewMockReplicator(ctrl *gomock.Controller) *MockReplicator { + mock := &MockReplicator{ctrl: ctrl} + mock.recorder = &MockReplicatorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockReplicator) EXPECT() *MockReplicatorMockRecorder { + return m.recorder +} + +// HandleTransmissionTask mocks base method. +func (m *MockReplicator) HandleTransmissionTask(ctx context.Context, domainOperation types.DomainOperation, info *persistence.DomainInfo, config *persistence.DomainConfig, replicationConfig *persistence.DomainReplicationConfig, configVersion, failoverVersion, previousFailoverVersion int64, isGlobalDomainEnabled bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HandleTransmissionTask", ctx, domainOperation, info, config, replicationConfig, configVersion, failoverVersion, previousFailoverVersion, isGlobalDomainEnabled) + ret0, _ := ret[0].(error) + return ret0 +} + +// HandleTransmissionTask indicates an expected call of HandleTransmissionTask. +func (mr *MockReplicatorMockRecorder) HandleTransmissionTask(ctx, domainOperation, info, config, replicationConfig, configVersion, failoverVersion, previousFailoverVersion, isGlobalDomainEnabled interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleTransmissionTask", reflect.TypeOf((*MockReplicator)(nil).HandleTransmissionTask), ctx, domainOperation, info, config, replicationConfig, configVersion, failoverVersion, previousFailoverVersion, isGlobalDomainEnabled) +} From e6c0158a55a731b919b37ae826fe06fb8a184f2c Mon Sep 17 00:00:00 2001 From: Shijie Sheng Date: Fri, 5 Apr 2024 18:30:26 -0700 Subject: [PATCH 2/4] add more unit test (#5883) What changed? Covered most of the branches in history client Why? To ensure correctness and bump coverage How did you test it? unit test --- client/history/client_test.go | 489 ++++++++++++++++++ client/history/peerResolver_test.go | 86 --- .../{peerResolver.go => peer_resolver.go} | 2 +- ...Resolver_mock.go => peer_resolver_mock.go} | 2 +- client/history/peer_resolver_test.go | 217 ++++++++ 5 files changed, 708 insertions(+), 88 deletions(-) delete mode 100644 client/history/peerResolver_test.go rename client/history/{peerResolver.go => peer_resolver.go} (97%) rename client/history/{peerResolver_mock.go => peer_resolver_mock.go} (99%) create mode 100644 client/history/peer_resolver_test.go diff --git a/client/history/client_test.go b/client/history/client_test.go index 31cb06151f0..fd7a60c56c4 100644 --- a/client/history/client_test.go +++ b/client/history/client_test.go @@ -24,6 +24,7 @@ package history import ( "context" + "fmt" "testing" "github.com/golang/mock/gomock" @@ -506,6 +507,494 @@ func TestClient_withResponse(t *testing.T) { }, want: &types.StartWorkflowExecutionResponse{}, }, + { + name: "StartWorkflowExecution peer resolve failure", + op: func(c Client) (any, error) { + return c.StartWorkflowExecution(context.Background(), &types.HistoryStartWorkflowExecutionRequest{ + StartRequest: &types.StartWorkflowExecutionRequest{ + WorkflowID: "test-workflow", + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + p.EXPECT().FromWorkflowID("test-workflow").Return("", fmt.Errorf("some error")).Times(1) + }, + wantError: true, + }, + { + name: "StartWorkflowExecution failure", + op: func(c Client) (any, error) { + return c.StartWorkflowExecution(context.Background(), &types.HistoryStartWorkflowExecutionRequest{ + StartRequest: &types.StartWorkflowExecutionRequest{ + WorkflowID: "test-workflow", + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("StartWorkflowExecution failed")).Times(1) + }, + wantError: true, + }, + { + name: "StartWorkflowExecution redirected success with host lost error", + op: func(c Client) (any, error) { + return c.StartWorkflowExecution(context.Background(), &types.HistoryStartWorkflowExecutionRequest{ + StartRequest: &types.StartWorkflowExecutionRequest{ + WorkflowID: "test-workflow", + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer-1", nil).Times(1) + p.EXPECT().FromHostAddress("host-test-peer-2").Return("test-peer-2", nil).Times(1) + c.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-1")}). + Return(nil, &types.ShardOwnershipLostError{ + Message: "test-peer-1 lost the shard", + Owner: "host-test-peer-2", + }).Times(1) + c.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-2")}). + Return(&types.StartWorkflowExecutionResponse{}, nil).Times(1) + }, + want: &types.StartWorkflowExecutionResponse{}, + }, + { + name: "StartWorkflowExecution redirected failed again with peer resolve", + op: func(c Client) (any, error) { + return c.StartWorkflowExecution(context.Background(), &types.HistoryStartWorkflowExecutionRequest{ + StartRequest: &types.StartWorkflowExecutionRequest{ + WorkflowID: "test-workflow", + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer-1", nil).Times(1) + p.EXPECT().FromHostAddress("host-test-peer-2").Return("", fmt.Errorf("not found")).Times(1) + c.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-1")}). + Return(nil, &types.ShardOwnershipLostError{ + Message: "test-peer-1 lost the shard", + Owner: "host-test-peer-2", + }).Times(1) + }, + wantError: true, + }, + { + name: "StartWorkflowExecution redirected failed again with error", + op: func(c Client) (any, error) { + return c.StartWorkflowExecution(context.Background(), &types.HistoryStartWorkflowExecutionRequest{ + StartRequest: &types.StartWorkflowExecutionRequest{ + WorkflowID: "test-workflow", + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer-1", nil).Times(1) + p.EXPECT().FromHostAddress("host-test-peer-2").Return("test-peer-2", nil).Times(1) + c.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-1")}). + Return(nil, &types.ShardOwnershipLostError{ + Message: "test-peer-1 lost the shard", + Owner: "host-test-peer-2", + }).Times(1) + c.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-2")}). + Return(nil, fmt.Errorf("some error")).Times(1) + }, + wantError: true, + }, + { + name: "GetMutableState fail", + op: func(c Client) (any, error) { + return c.GetMutableState(context.Background(), &types.GetMutableStateRequest{ + Execution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().GetMutableState(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("GetMutableState failed")).Times(1) + }, + wantError: true, + }, + { + name: "PollMutableState fail", + op: func(c Client) (any, error) { + return c.PollMutableState(context.Background(), &types.PollMutableStateRequest{ + Execution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().PollMutableState(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("PollMutableState failed")).Times(1) + }, + wantError: true, + }, + { + name: "ResetWorkflowExecution fail", + op: func(c Client) (any, error) { + return c.ResetWorkflowExecution(context.Background(), &types.HistoryResetWorkflowExecutionRequest{ + ResetRequest: &types.ResetWorkflowExecutionRequest{ + WorkflowExecution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().ResetWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("ResetWorkflowExecution failed")).Times(1) + }, + wantError: true, + }, + { + name: "DescribeWorkflowExecution fail", + op: func(c Client) (any, error) { + return c.DescribeWorkflowExecution(context.Background(), &types.HistoryDescribeWorkflowExecutionRequest{ + Request: &types.DescribeWorkflowExecutionRequest{ + Execution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().DescribeWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("DescribeWorkflowExecution failed")).Times(1) + }, + wantError: true, + }, + { + name: "RecordActivityTaskHeartbeat fail", + op: func(c Client) (any, error) { + return c.RecordActivityTaskHeartbeat(context.Background(), &types.HistoryRecordActivityTaskHeartbeatRequest{ + HeartbeatRequest: &types.RecordActivityTaskHeartbeatRequest{ + TaskToken: []byte(`{"workflowId": "test-workflow"}`), + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().RecordActivityTaskHeartbeat(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("RecordActivityTaskHeartbeat failed")).Times(1) + }, + wantError: true, + }, + { + name: "RecordActivityTaskStarted fail", + op: func(c Client) (any, error) { + return c.RecordActivityTaskStarted(context.Background(), &types.RecordActivityTaskStartedRequest{ + WorkflowExecution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().RecordActivityTaskStarted(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("RecordActivityTaskStarted failed")).Times(1) + }, + wantError: true, + }, + { + name: "RecordDecisionTaskStarted fail", + op: func(c Client) (any, error) { + return c.RecordDecisionTaskStarted(context.Background(), &types.RecordDecisionTaskStartedRequest{ + WorkflowExecution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().RecordDecisionTaskStarted(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("RecordDecisionTaskStarted failed")).Times(1) + }, + wantError: true, + }, + { + name: "GetReplicationMessages fail open on unknow error", + op: func(c Client) (any, error) { + return c.GetReplicationMessages(context.Background(), &types.GetReplicationMessagesRequest{ + Tokens: []*types.ReplicationToken{ + { + ShardID: 100, + }, + { + ShardID: 101, + }, + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(100).Return("test-peer-0", nil).Times(1) + p.EXPECT().FromShardID(101).Return("test-peer-1", nil).Times(1) + c.EXPECT().GetReplicationMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-0")}). + Return(&types.GetReplicationMessagesResponse{ + MessagesByShard: map[int32]*types.ReplicationMessages{100: {}}, + }, nil).Times(1) + c.EXPECT().GetReplicationMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-1")}). + Return(nil, fmt.Errorf("GetReplicationMessages failed")).Times(1) + }, + want: &types.GetReplicationMessagesResponse{ + MessagesByShard: map[int32]*types.ReplicationMessages{ + 100: {}, + }, + }, + wantError: false, + }, + { + name: "GetReplicationMessages fail open on unknow error", + op: func(c Client) (any, error) { + return c.GetReplicationMessages(context.Background(), &types.GetReplicationMessagesRequest{ + Tokens: []*types.ReplicationToken{ + { + ShardID: 100, + }, + { + ShardID: 101, + }, + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(100).Return("test-peer-0", nil).Times(1) + p.EXPECT().FromShardID(101).Return("test-peer-1", nil).Times(1) + c.EXPECT().GetReplicationMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-0")}). + Return(&types.GetReplicationMessagesResponse{ + MessagesByShard: map[int32]*types.ReplicationMessages{100: {}}, + }, nil).Times(1) + c.EXPECT().GetReplicationMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer-1")}). + Return(nil, &types.ServiceBusyError{}).Times(1) + }, + wantError: true, + }, + { + name: "GetDLQReplicationMessages fail", + op: func(c Client) (any, error) { + return c.GetDLQReplicationMessages(context.Background(), &types.GetDLQReplicationMessagesRequest{ + TaskInfos: []*types.ReplicationTaskInfo{ + {WorkflowID: "test-workflow"}, + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().GetDLQReplicationMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("GetDLQReplicationMessages failed")).Times(1) + }, + wantError: true, + }, + { + name: "ReadDLQMessages fail", + op: func(c Client) (any, error) { + return c.ReadDLQMessages(context.Background(), &types.ReadDLQMessagesRequest{ + ShardID: 123, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(123).Return("test-peer", nil).Times(1) + c.EXPECT().ReadDLQMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("ReadDLQMessages failed")).Times(1) + }, + wantError: true, + }, + { + name: "MergeDLQMessages fail", + op: func(c Client) (any, error) { + return c.MergeDLQMessages(context.Background(), &types.MergeDLQMessagesRequest{ + ShardID: 123, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(123).Return("test-peer", nil).Times(1) + c.EXPECT().MergeDLQMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("MergeDLQMessages failed")).Times(1) + }, + wantError: true, + }, + { + name: "GetCrossClusterTasks fail open", + op: func(c Client) (any, error) { + return c.GetCrossClusterTasks(context.Background(), &types.GetCrossClusterTasksRequest{ + ShardIDs: []int32{100}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(100).Return("test-peer", nil).Times(1) + c.EXPECT().GetCrossClusterTasks(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("GetCrossClusterTasks failed")).Times(1) + }, + want: &types.GetCrossClusterTasksResponse{ + TasksByShard: make(map[int32][]*types.CrossClusterTaskRequest), + FailedCauseByShard: map[int32]types.GetTaskFailedCause{ + 100: types.GetTaskFailedCauseUncategorized, + }, + }, + wantError: false, + }, + { + name: "RespondCrossClusterTasksCompleted fail", + op: func(c Client) (any, error) { + return c.RespondCrossClusterTasksCompleted(context.Background(), &types.RespondCrossClusterTasksCompletedRequest{ + ShardID: 123, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(123).Return("test-peer", nil).Times(1) + c.EXPECT().RespondCrossClusterTasksCompleted(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("RespondCrossClusterTasksCompleted failed")).Times(1) + }, + wantError: true, + }, + { + name: "GetFailoverInfo fail", + op: func(c Client) (any, error) { + return c.GetFailoverInfo(context.Background(), &types.GetFailoverInfoRequest{ + DomainID: "test-domain", + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromDomainID("test-domain").Return("test-peer", nil).Times(1) + c.EXPECT().GetFailoverInfo(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("GetFailoverInfo failed")).Times(1) + }, + wantError: true, + }, + { + name: "DescribeMutableState fail", + op: func(c Client) (any, error) { + return c.DescribeMutableState(context.Background(), &types.DescribeMutableStateRequest{ + Execution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID(gomock.Any()).Return("test-peer", nil).Times(1) + c.EXPECT().DescribeMutableState(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("DescribeMutableState failed")).Times(1) + }, + wantError: true, + }, + { + name: "DescribeQueue fail", + op: func(c Client) (any, error) { + return c.DescribeQueue(context.Background(), &types.DescribeQueueRequest{ + ShardID: 123, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromShardID(123).Return("test-peer", nil).Times(1) + c.EXPECT().DescribeQueue(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("DescribeQueue failed")).Times(1) + }, + wantError: true, + }, + { + name: "CountDLQMessages fail", + op: func(c Client) (any, error) { + return c.CountDLQMessages(context.Background(), &types.CountDLQMessagesRequest{}) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().GetAllPeers().Return([]string{"test-peer"}, nil).Times(1) + c.EXPECT().CountDLQMessages(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("CountDLQMessages failed")).Times(1) + }, + wantError: true, + }, + { + name: "QueryWorkflow fail", + op: func(c Client) (any, error) { + return c.QueryWorkflow(context.Background(), &types.HistoryQueryWorkflowRequest{ + Request: &types.QueryWorkflowRequest{ + Execution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID(gomock.Any()).Return("test-peer", nil).Times(1) + c.EXPECT().QueryWorkflow(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("QueryWorkflow failed")).Times(1) + }, + wantError: true, + }, + { + name: "ResetStickyTaskList fail", + op: func(c Client) (any, error) { + return c.ResetStickyTaskList(context.Background(), &types.HistoryResetStickyTaskListRequest{ + Execution: &types.WorkflowExecution{WorkflowID: "test-workflow"}, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().ResetStickyTaskList(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("ResetStickyTaskList failed")).Times(1) + }, + wantError: true, + }, + { + name: "RespondDecisionTaskCompleted fail", + op: func(c Client) (any, error) { + return c.RespondDecisionTaskCompleted(context.Background(), &types.HistoryRespondDecisionTaskCompletedRequest{ + CompleteRequest: &types.RespondDecisionTaskCompletedRequest{ + TaskToken: []byte(`{"workflowId": "test-workflow"}`), + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().RespondDecisionTaskCompleted(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("RespondDecisionTaskCompleted failed")).Times(1) + }, + wantError: true, + }, + { + name: "RespondDecisionTaskCompleted fail", + op: func(c Client) (any, error) { + return c.RespondDecisionTaskCompleted(context.Background(), &types.HistoryRespondDecisionTaskCompletedRequest{ + CompleteRequest: &types.RespondDecisionTaskCompletedRequest{ + TaskToken: []byte(`{"workflowId": "test-workflow"}`), + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().RespondDecisionTaskCompleted(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("RespondDecisionTaskCompleted failed")).Times(1) + }, + wantError: true, + }, + { + name: "SignalWithStartWorkflowExecution fail", + op: func(c Client) (any, error) { + return c.SignalWithStartWorkflowExecution(context.Background(), &types.HistorySignalWithStartWorkflowExecutionRequest{ + SignalWithStartRequest: &types.SignalWithStartWorkflowExecutionRequest{ + WorkflowID: "test-workflow", + }, + }) + }, + mock: func(p *MockPeerResolver, c *MockClient) { + // Add your mock expectations here + p.EXPECT().FromWorkflowID("test-workflow").Return("test-peer", nil).Times(1) + c.EXPECT().SignalWithStartWorkflowExecution(gomock.Any(), gomock.Any(), []yarpc.CallOption{yarpc.WithShardKey("test-peer")}). + Return(nil, fmt.Errorf("SignalWithStartWorkflowExecution failed")).Times(1) + }, + wantError: true, + }, } for _, tt := range tests { diff --git a/client/history/peerResolver_test.go b/client/history/peerResolver_test.go deleted file mode 100644 index 3cc22c319a3..00000000000 --- a/client/history/peerResolver_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2021 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package history - -import ( - "errors" - "testing" - - gomock "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - - "github.com/uber/cadence/common" - "github.com/uber/cadence/common/membership" - "github.com/uber/cadence/common/service" -) - -func TestPeerResolver(t *testing.T) { - numShards := 123 - controller := gomock.NewController(t) - serviceResolver := membership.NewMockResolver(controller) - serviceResolver.EXPECT().Lookup( - service.History, string(rune(common.DomainIDToHistoryShard("domainID", numShards)))).Return( - membership.NewDetailedHostInfo( - "domainHost:123", - "domainHost_123", - membership.PortMap{membership.PortTchannel: 1234}), - nil) - serviceResolver.EXPECT().Lookup(service.History, string(rune(common.WorkflowIDToHistoryShard("workflowID", numShards)))).Return( - membership.NewDetailedHostInfo( - "workflowHost:123", - "workflow", - membership.PortMap{membership.PortTchannel: 1235, membership.PortGRPC: 1666}), nil) - - serviceResolver.EXPECT().Lookup(service.History, string(rune(99))).Return( - membership.NewDetailedHostInfo( - "shardHost:123", - "shard_123", - membership.PortMap{membership.PortTchannel: 1235}), - nil) - - serviceResolver.EXPECT().LookupByAddress(service.History, "invalid address").Return( - membership.HostInfo{}, - errors.New("host not found"), - ) - - serviceResolver.EXPECT().Lookup(service.History, string(rune(11))).Return(membership.HostInfo{}, assert.AnError) - - r := NewPeerResolver(numShards, serviceResolver, membership.PortTchannel) - - peer, err := r.FromDomainID("domainID") - assert.NoError(t, err) - assert.Equal(t, "domainHost:1234", peer) - - peer, err = r.FromWorkflowID("workflowID") - assert.NoError(t, err) - assert.Equal(t, "workflowHost:1235", peer) - - peer, err = r.FromShardID(99) - assert.NoError(t, err) - assert.Equal(t, "shardHost:1235", peer) - - _, err = r.FromShardID(11) - assert.Error(t, err) - - _, err = r.FromHostAddress("invalid address") - assert.Error(t, err) - -} diff --git a/client/history/peerResolver.go b/client/history/peer_resolver.go similarity index 97% rename from client/history/peerResolver.go rename to client/history/peer_resolver.go index f1bc522cb25..2c0c41b4e1c 100644 --- a/client/history/peerResolver.go +++ b/client/history/peer_resolver.go @@ -30,7 +30,7 @@ import ( // Those are deployed instances of Cadence history services that participate in the cluster ring. // The resulting peer is simply an address of form ip:port where RPC calls can be routed to. // -//go:generate mockgen -package $GOPACKAGE -source $GOFILE -destination peerResolver_mock.go -package history github.com/uber/cadence/client/history PeerResolver +//go:generate mockgen -package $GOPACKAGE -source $GOFILE -destination peer_resolver_mock.go -package history github.com/uber/cadence/client/history PeerResolver type PeerResolver interface { FromWorkflowID(workflowID string) (string, error) FromDomainID(domainID string) (string, error) diff --git a/client/history/peerResolver_mock.go b/client/history/peer_resolver_mock.go similarity index 99% rename from client/history/peerResolver_mock.go rename to client/history/peer_resolver_mock.go index 69ecbe7895c..18a5ce4e4b7 100644 --- a/client/history/peerResolver_mock.go +++ b/client/history/peer_resolver_mock.go @@ -21,7 +21,7 @@ // SOFTWARE. // Code generated by MockGen. DO NOT EDIT. -// Source: peerResolver.go +// Source: peer_resolver.go // Package history is a generated GoMock package. package history diff --git a/client/history/peer_resolver_test.go b/client/history/peer_resolver_test.go new file mode 100644 index 00000000000..4a7656e711d --- /dev/null +++ b/client/history/peer_resolver_test.go @@ -0,0 +1,217 @@ +// Copyright (c) 2021 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package history + +import ( + "errors" + "testing" + + gomock "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "github.com/uber/cadence/common" + "github.com/uber/cadence/common/membership" + "github.com/uber/cadence/common/service" +) + +func TestPeerResolver(t *testing.T) { + numShards := 123 + controller := gomock.NewController(t) + serviceResolver := membership.NewMockResolver(controller) + serviceResolver.EXPECT().Lookup( + service.History, string(rune(common.DomainIDToHistoryShard("domainID", numShards)))).Return( + membership.NewDetailedHostInfo( + "domainHost:123", + "domainHost_123", + membership.PortMap{membership.PortTchannel: 1234}), + nil) + serviceResolver.EXPECT().Lookup(service.History, string(rune(common.WorkflowIDToHistoryShard("workflowID", numShards)))).Return( + membership.NewDetailedHostInfo( + "workflowHost:123", + "workflow", + membership.PortMap{membership.PortTchannel: 1235, membership.PortGRPC: 1666}), nil) + + serviceResolver.EXPECT().Lookup(service.History, string(rune(99))).Return( + membership.NewDetailedHostInfo( + "shardHost:123", + "shard_123", + membership.PortMap{membership.PortTchannel: 1235}), + nil) + + serviceResolver.EXPECT().Lookup(service.History, string(rune(11))).Return(membership.HostInfo{}, assert.AnError) + + r := NewPeerResolver(numShards, serviceResolver, membership.PortTchannel) + + peer, err := r.FromDomainID("domainID") + assert.NoError(t, err) + assert.Equal(t, "domainHost:1234", peer) + + peer, err = r.FromWorkflowID("workflowID") + assert.NoError(t, err) + assert.Equal(t, "workflowHost:1235", peer) + + peer, err = r.FromShardID(99) + assert.NoError(t, err) + assert.Equal(t, "shardHost:1235", peer) + + _, err = r.FromShardID(11) + assert.Error(t, err) + + t.Run("FromHostAddress", func(t *testing.T) { + tests := []struct { + name string + address string + mock func(*membership.MockResolver) + want string + wantError bool + }{ + { + name: "success", + address: "addressHost:123", + mock: func(mr *membership.MockResolver) { + mr.EXPECT().LookupByAddress(service.History, "addressHost:123").Return( + membership.NewDetailedHostInfo( + "addressHost:123", + "address", + membership.PortMap{membership.PortTchannel: 1235, membership.PortGRPC: 1666}), + nil, + ) + }, + want: "addressHost:1235", + }, + { + name: "invalid address", + address: "invalid address", + mock: func(mr *membership.MockResolver) { + mr.EXPECT().LookupByAddress(service.History, "invalid address").Return( + membership.HostInfo{}, + errors.New("host not found"), + ) + }, + wantError: true, + }, + { + name: "fail on no port", + address: "addressHost:123", + mock: func(mr *membership.MockResolver) { + mr.EXPECT().LookupByAddress(service.History, "addressHost:123").Return( + membership.NewDetailedHostInfo( + "addressHost:123", + "address", + membership.PortMap{}), + nil, + ) + }, + wantError: true, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + controller := gomock.NewController(t) + serviceResolver := membership.NewMockResolver(controller) + tt.mock(serviceResolver) + r := NewPeerResolver(numShards, serviceResolver, membership.PortTchannel) + res, err := r.FromHostAddress(tt.address) + if tt.wantError { + assert.True(t, common.IsServiceTransientError(err)) + } else { + assert.Equal(t, tt.want, res) + assert.NoError(t, err) + } + }) + } + }) + + t.Run("GetAllPeers", func(t *testing.T) { + tests := []struct { + name string + mock func(*membership.MockResolver) + want []string + wantError bool + }{ + { + name: "success", + mock: func(mr *membership.MockResolver) { + mr.EXPECT().Members(service.History).Return( + []membership.HostInfo{ + membership.NewDetailedHostInfo( + "host1:123", + "address", + membership.PortMap{membership.PortTchannel: 1235, membership.PortGRPC: 1666}), + membership.NewDetailedHostInfo( + "host2:123", + "address", + membership.PortMap{membership.PortTchannel: 1235, membership.PortGRPC: 1666}), + }, + nil, + ) + }, + want: []string{"host1:1235", "host2:1235"}, + }, + { + name: "failed on peer resolve", + mock: func(mr *membership.MockResolver) { + mr.EXPECT().Members(service.History).Return(nil, assert.AnError) + + }, + wantError: true, + }, + { + name: "failed on no port", + mock: func(mr *membership.MockResolver) { + mr.EXPECT().Members(service.History).Return( + []membership.HostInfo{ + membership.NewDetailedHostInfo( + "host1:123", + "address", + membership.PortMap{membership.PortTchannel: 1235, membership.PortGRPC: 1666}), + membership.NewDetailedHostInfo( + "host2:123", + "address", + membership.PortMap{membership.PortGRPC: 1666}), + }, + nil, + ) + }, + wantError: true, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + controller := gomock.NewController(t) + serviceResolver := membership.NewMockResolver(controller) + tt.mock(serviceResolver) + r := NewPeerResolver(numShards, serviceResolver, membership.PortTchannel) + res, err := r.GetAllPeers() + if tt.wantError { + assert.True(t, common.IsServiceTransientError(err)) + } else { + assert.ElementsMatch(t, tt.want, res) + assert.NoError(t, err) + } + }) + } + }) +} From b0655a1945ffc9e2f708d9abf47904b450837125 Mon Sep 17 00:00:00 2001 From: Abhishek Jha Date: Fri, 5 Apr 2024 18:30:31 -0700 Subject: [PATCH 3/4] Licensing --- common/domain/transmissionTaskHandler_mock.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/common/domain/transmissionTaskHandler_mock.go b/common/domain/transmissionTaskHandler_mock.go index a456b62fa62..5afe77d4976 100644 --- a/common/domain/transmissionTaskHandler_mock.go +++ b/common/domain/transmissionTaskHandler_mock.go @@ -1,5 +1,7 @@ -// Copyright (c) 2020 Uber Technologies, Inc. -// +// The MIT License (MIT) + +// Copyright (c) 2017-2020 Uber Technologies Inc. + // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights @@ -7,17 +9,16 @@ // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // Code generated by MockGen. DO NOT EDIT. // Source: transmissionTaskHandler.go From 9d0463442c3af378a43f818b6724271ef41bd988 Mon Sep 17 00:00:00 2001 From: Abhishek Jha Date: Fri, 5 Apr 2024 18:39:30 -0700 Subject: [PATCH 4/4] space --- common/domain/transmissionTaskHandler_mock.go | 1 + 1 file changed, 1 insertion(+) diff --git a/common/domain/transmissionTaskHandler_mock.go b/common/domain/transmissionTaskHandler_mock.go index 5afe77d4976..cb8d614d628 100644 --- a/common/domain/transmissionTaskHandler_mock.go +++ b/common/domain/transmissionTaskHandler_mock.go @@ -19,6 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. + // Code generated by MockGen. DO NOT EDIT. // Source: transmissionTaskHandler.go