Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for admin cluster commands #6397

Merged
merged 2 commits into from
Oct 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
348 changes: 348 additions & 0 deletions tools/cli/admin_cluster_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ package cli

import (
"flag"
"fmt"
"testing"

"github.com/golang/mock/gomock"
"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"
"github.com/uber/cadence/common/visibility"
"github.com/uber/cadence/service/worker/failovermanager"
)

func TestAdminAddSearchAttribute_isValueTypeValid(t *testing.T) {
Expand Down Expand Up @@ -134,3 +137,348 @@ func TestValidSearchAttributeKey(t *testing.T) {
assert.Error(t, visibility.ValidateSearchAttributeKey("9lives"))
assert.Error(t, visibility.ValidateSearchAttributeKey("tax%"))
}

func TestAdminDescribeCluster(t *testing.T) {
// Initialize mock controller
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed


// Create mock frontend and admin clients
serverFrontendClient := frontend.NewMockClient(mockCtrl)
serverAdminClient := admin.NewMockClient(mockCtrl)
Comment on lines +147 to +148
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's avoid defining mocks at top level like this. If one test case's expectation fails it will fail the rest. better to define these inside inner t.Run for isolation purposes


// Set up the CLI app and mock dependencies
app := NewCliApp(&clientFactoryMock{
serverFrontendClient: serverFrontendClient,
serverAdminClient: serverAdminClient,
})

tests := []struct {
name string
mockSetup func()
expectedError string
}{
{
name: "Success",
mockSetup: func() {
// Expected response from DescribeCluster
expectedResponse := &types.DescribeClusterResponse{
SupportedClientVersions: &types.SupportedClientVersions{
GoSdk: "1.5.0",
},
}
// Mock the DescribeCluster call
serverAdminClient.EXPECT().DescribeCluster(gomock.Any()).Return(expectedResponse, nil).Times(1)
},
expectedError: "",
},
{
name: "DescribeClusterError",
mockSetup: func() {
// Mock DescribeCluster to return an error
serverAdminClient.EXPECT().DescribeCluster(gomock.Any()).Return(nil, fmt.Errorf("DescribeCluster failed")).Times(1)
},
expectedError: "Operation DescribeCluster failed.",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set up mock based on the specific test case
tt.mockSetup()

// Set up CLI context
set := flag.NewFlagSet("test", 0)
c := cli.NewContext(app, set, nil)

// Call AdminDescribeCluster
err := AdminDescribeCluster(c)

// Check the result based on the expected outcome
if tt.expectedError != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}

func TestAdminRebalanceStart(t *testing.T) {
tests := []struct {
name string
mockSetup func(mockFrontClient *frontend.MockClient, mockClientFactory *MockClientFactory)
expectedError string
}{
{
name: "Success",
mockSetup: func(mockFrontClient *frontend.MockClient, mockClientFactory *MockClientFactory) {
// Mock StartWorkflowExecution response
mockResponse := &types.StartWorkflowExecutionResponse{
RunID: "test-run-id",
}
mockClientFactory.EXPECT().ServerFrontendClient(gomock.Any()).Return(mockFrontClient, nil).Times(1)
mockFrontClient.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any()).Return(mockResponse, nil).Times(1)
},
expectedError: "",
},
{
name: "ServerFrontendClientError",
mockSetup: func(mockFrontClient *frontend.MockClient, mockClientFactory *MockClientFactory) {
// Mock ServerFrontendClient to return an error
mockClientFactory.EXPECT().ServerFrontendClient(gomock.Any()).Return(nil, fmt.Errorf("failed to get frontend client")).Times(1)
},
expectedError: "failed to get frontend client",
},
{
name: "StartWorkflowExecutionError",
mockSetup: func(mockFrontClient *frontend.MockClient, mockClientFactory *MockClientFactory) {
// Mock StartWorkflowExecution to return an error
mockClientFactory.EXPECT().ServerFrontendClient(gomock.Any()).Return(mockFrontClient, nil).Times(1)
mockFrontClient.EXPECT().StartWorkflowExecution(gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("failed to start workflow")).Times(1)
},
expectedError: "Failed to start failover workflow",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Initialize mock controller
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

// Create mock Cadence client and client factory
mockFrontClient := frontend.NewMockClient(mockCtrl)
mockClientFactory := NewMockClientFactory(mockCtrl)

// Set up the CLI app
app := cli.NewApp()
app.Metadata = map[string]interface{}{
"deps": &deps{
ClientFactory: mockClientFactory,
},
}

// Set up the mocks for the specific test case
tt.mockSetup(mockFrontClient, mockClientFactory)

// Use setContextMock to set the CLI context
c := setContextMock(app)

// Call AdminRebalanceStart
err := AdminRebalanceStart(c)

// Check the result based on the expected outcome
if tt.expectedError != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}

// Helper function to set up the CLI context for AdminRebalanceStart
func setContextMock(app *cli.App) *cli.Context {
set := flag.NewFlagSet("test", 0)
// You can add any flags relevant to AdminRebalanceStart here
set.String(FlagDomain, "test-domain", "Domain flag")

c := cli.NewContext(app, set, nil)
return c
}

func TestIntValTypeToString(t *testing.T) {
tests := []struct {
name string
valType int
expected string
}{
{
name: "StringType",
valType: 0,
expected: "String",
},
{
name: "KeywordType",
valType: 1,
expected: "Keyword",
},
{
name: "IntType",
valType: 2,
expected: "Int",
},
{
name: "DoubleType",
valType: 3,
expected: "Double",
},
{
name: "BoolType",
valType: 4,
expected: "Bool",
},
{
name: "DatetimeType",
valType: 5,
expected: "Datetime",
},
{
name: "UnknownType",
valType: 999,
expected: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Call the function and check the result
result := intValTypeToString(tt.valType)
assert.Equal(t, tt.expected, result)
})
}
}

func TestAdminRebalanceList(t *testing.T) {
tests := []struct {
name string
prepareEnv func() *cli.Context
expectedError string
}{
{
name: "Success",
prepareEnv: func() *cli.Context {
// Initialize the mock client factory and frontend client
mockFrontClient := frontend.NewMockClient(gomock.NewController(t))
mockClientFactory := NewMockClientFactory(gomock.NewController(t))

// Mock successful ListWorkflow call
mockClientFactory.EXPECT().ServerFrontendClient(gomock.Any()).Return(mockFrontClient, nil).Times(1)
mockFrontClient.EXPECT().CountWorkflowExecutions(gomock.Any(), gomock.Any()).Return(&types.CountWorkflowExecutionsResponse{}, nil).Times(1)
mockFrontClient.EXPECT().ListClosedWorkflowExecutions(gomock.Any(), gomock.Any()).Return(&types.ListClosedWorkflowExecutionsResponse{}, nil).Times(1)

// Create CLI app and set up flag set
app := cli.NewApp()
app.Metadata = map[string]interface{}{
"deps": &deps{
ClientFactory: mockClientFactory,
},
}
set := flag.NewFlagSet("test", 0)
set.String(FlagWorkflowID, "", "workflow ID flag")
set.String(FlagDomain, "", "domain flag")
c := cli.NewContext(app, set, nil)

// Set flags for workflow ID and domain
_ = c.Set(FlagWorkflowID, failovermanager.RebalanceWorkflowID)
_ = c.Set(FlagDomain, common.SystemLocalDomainName)

return c
},
expectedError: "",
},
{
name: "SetWorkflowIDError",
prepareEnv: func() *cli.Context {
// Create CLI app and set up flag set without FlagWorkflowID
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String(FlagDomain, "", "domain flag") // Only Domain flag is set
c := cli.NewContext(app, set, nil)

// Set only the domain flag, so setting FlagWorkflowID should trigger an error
_ = c.Set(FlagDomain, common.SystemLocalDomainName)

return c
},
expectedError: "no such flag -workflow_id",
},
{
name: "SetDomainError",
prepareEnv: func() *cli.Context {
// Create CLI app and set up flag set without FlagDomain
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String(FlagWorkflowID, "", "workflow ID flag") // Only Workflow ID flag is set
c := cli.NewContext(app, set, nil)

// Set workflow ID flag, but not the domain flag
_ = c.Set(FlagWorkflowID, failovermanager.RebalanceWorkflowID)

return c
},
expectedError: "no such flag -domain",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Prepare the test environment for the specific test case
c := tt.prepareEnv()

// Call AdminRebalanceList
err := AdminRebalanceList(c)

// Check the result based on the expected outcome
if tt.expectedError != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}

func TestAdminAddSearchAttribute_errors(t *testing.T) {
tests := []struct {
name string
setupContext func(app *cli.App) *cli.Context
expectedError string
}{
{
name: "MissingSearchAttributesKey",
setupContext: func(app *cli.App) *cli.Context {
// Simulate missing FlagSearchAttributesKey
set := flag.NewFlagSet("test", 0)
// No FlagSearchAttributesKey set
return cli.NewContext(app, set, nil)
},
expectedError: "Required flag not present:",
},
{
name: "InvalidSearchAttributeKey",
setupContext: func(app *cli.App) *cli.Context {
// Provide an invalid key to trigger ValidateSearchAttributeKey error
set := flag.NewFlagSet("test", 0)
set.String(FlagSearchAttributesKey, "123_invalid_key", "Key flag") // Invalid key, starts with number
return cli.NewContext(app, set, nil)
},
expectedError: "Invalid search-attribute key.",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create CLI app
app := cli.NewApp()

// Set up the CLI context for the specific test case
c := tt.setupContext(app)

// Call AdminAddSearchAttribute
err := AdminAddSearchAttribute(c)

// Check the result based on the expected outcome
if tt.expectedError != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}
Loading