CloudWatch: Refactor test mock by removing GetMetricsData from FakeMetricsAPI (#58355)

This commit is contained in:
Shirley 2022-11-08 10:28:50 +01:00 committed by GitHub
parent 326ea86a57
commit 82d09e0647
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 74 deletions

View File

@ -5,41 +5,27 @@ import (
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
type cloudWatchFakeClient struct {
cloudwatchiface.CloudWatchAPI
counterForGetMetricDataWithContext int
}
func (client *cloudWatchFakeClient) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) {
nextToken := "next"
res := []*cloudwatch.MetricDataResult{{
Values: []*float64{aws.Float64(12.3), aws.Float64(23.5)},
}}
if client.counterForGetMetricDataWithContext == 0 {
nextToken = ""
res = []*cloudwatch.MetricDataResult{{
Values: []*float64{aws.Float64(100)},
}}
}
client.counterForGetMetricDataWithContext--
return &cloudwatch.GetMetricDataOutput{
MetricDataResults: res,
NextToken: aws.String(nextToken),
}, nil
}
func TestGetMetricDataExecutorTest(t *testing.T) {
executor := &cloudWatchExecutor{}
inputs := &cloudwatch.GetMetricDataInput{MetricDataQueries: []*cloudwatch.MetricDataQuery{}}
res, err := executor.executeRequest(context.Background(), &cloudWatchFakeClient{counterForGetMetricDataWithContext: 1}, inputs)
mockMetricClient := &mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(
&cloudwatch.GetMetricDataOutput{
MetricDataResults: []*cloudwatch.MetricDataResult{{Values: []*float64{aws.Float64(12.3), aws.Float64(23.5)}}},
NextToken: aws.String("next"),
}, nil).Once()
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(
&cloudwatch.GetMetricDataOutput{
MetricDataResults: []*cloudwatch.MetricDataResult{{Values: []*float64{aws.Float64(100)}}},
}, nil).Once()
res, err := executor.executeRequest(context.Background(), mockMetricClient, inputs)
require.NoError(t, err)
require.Len(t, res, 2)
require.Len(t, res[0].MetricDataResults[0].Values, 2)

View File

@ -10,18 +10,9 @@ import (
type FakeMetricsAPI struct {
cloudwatchiface.CloudWatchAPI
cloudwatch.GetMetricDataOutput
Metrics []*cloudwatch.Metric
MetricsPerPage int
CallsGetMetricDataWithContext []*cloudwatch.GetMetricDataInput
}
func (c *FakeMetricsAPI) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) {
c.CallsGetMetricDataWithContext = append(c.CallsGetMetricDataWithContext, input)
return &c.GetMetricDataOutput, nil
}
func (c *FakeMetricsAPI) ListMetricsPages(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error {
@ -58,12 +49,12 @@ func chunkSlice(slice []*cloudwatch.Metric, chunkSize int) [][]*cloudwatch.Metri
return chunks
}
type MetricsClient struct {
type MetricsAPI struct {
cloudwatchiface.CloudWatchAPI
mock.Mock
}
func (m *MetricsClient) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) {
func (m *MetricsAPI) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) {
args := m.Called(ctx, input, opts)
return args.Get(0).(*cloudwatch.GetMetricDataOutput), args.Error(1)

View File

@ -32,28 +32,22 @@ func TestTimeSeriesQuery(t *testing.T) {
t.Cleanup(func() {
NewCWClient = origNewCWClient
})
var api mocks.FakeMetricsAPI
var api mocks.MetricsAPI
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
return &api
}
t.Run("Custom metrics", func(t *testing.T) {
api = mocks.FakeMetricsAPI{
CloudWatchAPI: nil,
GetMetricDataOutput: cloudwatch.GetMetricDataOutput{
NextToken: nil,
Messages: []*cloudwatch.MessageData{},
MetricDataResults: []*cloudwatch.MetricDataResult{
{
StatusCode: aws.String("Complete"), Id: aws.String("a"), Label: aws.String("NetworkOut"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now},
},
{
StatusCode: aws.String("Complete"), Id: aws.String("b"), Label: aws.String("NetworkIn"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now},
},
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{
MetricDataResults: []*cloudwatch.MetricDataResult{
{
StatusCode: aws.String("Complete"), Id: aws.String("a"), Label: aws.String("NetworkOut"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now},
},
},
}
{
StatusCode: aws.String("Complete"), Id: aws.String("b"), Label: aws.String("NetworkIn"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now},
}}}, nil)
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: &models.CloudWatchSettings{}}, nil
@ -150,7 +144,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
NewCWClient = origNewCWClient
})
var mockMetricClient mocks.MetricsClient
var mockMetricClient mocks.MetricsAPI
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
return &mockMetricClient
}
@ -164,7 +158,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
mockSessionCache.On("GetSession", mock.MatchedBy(
func(config awsds.SessionConfig) bool { return config.Settings.Region == "us-east-1" })). // region from queries is asserted here
Return(&session.Session{Config: &aws.Config{}}, nil).Once()
mockMetricClient = mocks.MetricsClient{}
mockMetricClient = mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
executor := newExecutor(im, newTestConfig(), mockSessionCache, featuremgmt.WithFeatures())
@ -215,7 +209,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
sessionCache.On("GetSession", mock.MatchedBy(
func(config awsds.SessionConfig) bool { return config.Settings.Region == "us-east-2" })).
Return(&session.Session{Config: &aws.Config{}}, nil, nil).Once()
mockMetricClient = mocks.MetricsClient{}
mockMetricClient = mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
executor := newExecutor(im, newTestConfig(), sessionCache, featuremgmt.WithFeatures())
@ -341,7 +335,7 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
NewCWClient = origNewCWClient
})
var api mocks.FakeMetricsAPI
var api mocks.MetricsAPI
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
return &api
@ -352,7 +346,8 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
})
t.Run("passes query label as GetMetricData label when dynamic labels feature toggle is enabled", func(t *testing.T) {
api = mocks.FakeMetricsAPI{}
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchDynamicLabels))
query := newTestQuery(t, queryParameters{
Label: aws.String("${PROP('Period')} some words ${PROP('Dim.InstanceId')}"),
@ -373,11 +368,12 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
})
assert.NoError(t, err)
require.Len(t, api.CallsGetMetricDataWithContext, 1)
require.Len(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries, 1)
require.NotNil(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries[0].Label)
assert.Equal(t, "${PROP('Period')} some words ${PROP('Dim.InstanceId')}", *api.CallsGetMetricDataWithContext[0].MetricDataQueries[0].Label)
require.Len(t, api.Calls, 1)
getMetricDataInput, ok := api.Calls[0].Arguments.Get(1).(*cloudwatch.GetMetricDataInput)
require.True(t, ok)
require.Len(t, getMetricDataInput.MetricDataQueries, 1)
require.NotNil(t, getMetricDataInput.MetricDataQueries[0].Label)
assert.Equal(t, "${PROP('Period')} some words ${PROP('Dim.InstanceId')}", *getMetricDataInput.MetricDataQueries[0].Label)
})
testCases := map[string]struct {
@ -399,7 +395,8 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
api = mocks.FakeMetricsAPI{}
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, tc.feature)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
@ -417,10 +414,12 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
})
assert.NoError(t, err)
require.Len(t, api.CallsGetMetricDataWithContext, 1)
require.Len(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries, 1)
assert.Nil(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries[0].Label)
assert.NoError(t, err)
require.Len(t, api.Calls, 1)
getMetricDataInput, ok := api.Calls[0].Arguments.Get(1).(*cloudwatch.GetMetricDataInput)
require.True(t, ok)
require.Len(t, getMetricDataInput.MetricDataQueries, 1)
require.Nil(t, getMetricDataInput.MetricDataQueries[0].Label)
})
}
}
@ -430,21 +429,20 @@ func Test_QueryData_response_data_frame_names(t *testing.T) {
t.Cleanup(func() {
NewCWClient = origNewCWClient
})
var api mocks.FakeMetricsAPI
var api mocks.MetricsAPI
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
return &api
}
labelFromGetMetricData := "some label"
api = mocks.FakeMetricsAPI{
GetMetricDataOutput: cloudwatch.GetMetricDataOutput{
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).
Return(&cloudwatch.GetMetricDataOutput{
MetricDataResults: []*cloudwatch.MetricDataResult{
{StatusCode: aws.String("Complete"), Id: aws.String(queryId), Label: aws.String(labelFromGetMetricData),
Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{{}}},
},
},
}
}}, nil)
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: &models.CloudWatchSettings{}}, nil
})