From aaaebc88db86cd09de460a07f266669fc028eaf1 Mon Sep 17 00:00:00 2001 From: Gyan Gupta Date: Fri, 17 Jan 2025 12:49:50 +0530 Subject: [PATCH] sc-14371 added test cases for client and exporter --- go.mod | 2 +- go.sum | 2 ++ sendgrid/client.go | 6 ++++-- sendgrid/client_test.go | 19 +++++++++++++++++-- sendgrid/exporter_test.go | 38 ++++++++++++++++++++++++++++---------- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 6ddb15d..f951533 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21.1 require ( github.com/jarcoal/httpmock v1.3.1 github.com/prometheus/client_golang v1.20.3 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 ) require ( diff --git a/go.sum b/go.sum index 6e423cf..e54efd4 100644 --- a/go.sum +++ b/go.sum @@ -35,6 +35,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= diff --git a/sendgrid/client.go b/sendgrid/client.go index e8a323c..98dd033 100644 --- a/sendgrid/client.go +++ b/sendgrid/client.go @@ -8,6 +8,8 @@ import ( "time" ) +const BaseURL = "https://api.sendgrid.com/v3" + // Client struct holds the API keys for the accounts type Client struct { APIKeys map[string]string @@ -34,7 +36,7 @@ func (c *Client) FetchMetrics(accountName string) (*SendgridCreditsResponse, int } start := time.Now() - url := "https://api.sendgrid.com/v3/user/credits" + url := fmt.Sprintf("%s/user/credits", BaseURL) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, 0, 0, err @@ -69,7 +71,7 @@ func (c *Client) FetchMetricsForSubuser(subuserName, accountName string) (*Sendg } start := time.Now() - url := fmt.Sprintf("https://api.sendgrid.com/v3/subusers/%s/credits", subuserName) + url := fmt.Sprintf("%s/subusers/%s/credits", BaseURL, subuserName) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, 0, 0, err diff --git a/sendgrid/client_test.go b/sendgrid/client_test.go index e527ebf..8b76834 100644 --- a/sendgrid/client_test.go +++ b/sendgrid/client_test.go @@ -1,4 +1,5 @@ package sendgrid_test + import ( "bytes" "encoding/json" @@ -6,25 +7,30 @@ import ( "net/http" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/simpledotorg/rtsl_exporter/sendgrid" ) + // MockTransport mocks HTTP responses for testing purposes. type MockTransport struct { Response *http.Response Error error } + // RoundTrip simulates the HTTP transport layer for testing. func (m *MockTransport) RoundTrip(req *http.Request) (*http.Response, error) { // Simulate network errors or responses return m.Response, m.Error } + // TestContext holds the shared state and setup for the tests. type TestContext struct { client *sendgrid.Client originalTransport http.RoundTripper mockTransport *MockTransport } + // Initialize sets up the TestContext with the provided mock responses and status codes. func (tc *TestContext) Initialize(apiKeys map[string]string, mockResponse *sendgrid.SendgridCreditsResponse, statusCode int, err error) { mockResponseBody, _ := json.Marshal(mockResponse) @@ -39,10 +45,12 @@ func (tc *TestContext) Initialize(apiKeys map[string]string, mockResponse *sendg tc.originalTransport = http.DefaultTransport http.DefaultTransport = tc.mockTransport } + // Cleanup restores the original HTTP transport after tests. func (tc *TestContext) Cleanup() { http.DefaultTransport = tc.originalTransport } + // TestFetchMetrics_Success tests successful fetching of metrics. func TestFetchMetrics_Success(t *testing.T) { tc := &TestContext{} @@ -57,6 +65,7 @@ func TestFetchMetrics_Success(t *testing.T) { } tc.Initialize(map[string]string{mockAccountName: mockAPIKey}, &mockResponse, http.StatusOK, nil) defer tc.Cleanup() + metrics, statusCode, _, err := tc.client.FetchMetrics(mockAccountName) assert.NoError(t, err) assert.Equal(t, http.StatusOK, statusCode) @@ -64,6 +73,7 @@ func TestFetchMetrics_Success(t *testing.T) { assert.InDelta(t, 800, metrics.Remaining, 0.001) assert.InDelta(t, 200, metrics.Used, 0.001) } + // TestFetchMetrics_AccountNotFound tests handling of an account not found error. func TestFetchMetrics_AccountNotFound(t *testing.T) { tc := &TestContext{} @@ -71,11 +81,13 @@ func TestFetchMetrics_AccountNotFound(t *testing.T) { mockAccountName := "mockAccount" tc.Initialize(map[string]string{mockAccountName: mockAPIKey}, nil, http.StatusNotFound, nil) defer tc.Cleanup() + metrics, statusCode, _, err := tc.client.FetchMetrics(mockAccountName) assert.Error(t, err) assert.Nil(t, metrics) assert.Equal(t, http.StatusNotFound, statusCode) } + // TestFetchMetrics_HTTPError tests handling of HTTP errors. func TestFetchMetrics_HTTPError(t *testing.T) { tc := &TestContext{} @@ -83,11 +95,13 @@ func TestFetchMetrics_HTTPError(t *testing.T) { mockAccountName := "mockAccount" tc.Initialize(map[string]string{mockAccountName: mockAPIKey}, nil, 0, http.ErrHandlerTimeout) defer tc.Cleanup() + metrics, statusCode, _, err := tc.client.FetchMetrics(mockAccountName) assert.Error(t, err) assert.Nil(t, metrics) assert.Equal(t, 0, statusCode) } + // TestFetchMetrics_Timeout tests handling of timeouts. func TestFetchMetrics_Timeout(t *testing.T) { tc := &TestContext{} @@ -102,8 +116,9 @@ func TestFetchMetrics_Timeout(t *testing.T) { originalTransport := http.DefaultTransport defer func() { http.DefaultTransport = originalTransport }() http.DefaultTransport = tc.mockTransport + metrics, statusCode, _, err := tc.client.FetchMetrics(mockAccountName) assert.Error(t, err) assert.Nil(t, metrics) - assert.Equal(t, 0, statusCode) -} \ No newline at end of file + assert.Equal(t, 0, statusCode) +} diff --git a/sendgrid/exporter_test.go b/sendgrid/exporter_test.go index 2b284b3..9649036 100755 --- a/sendgrid/exporter_test.go +++ b/sendgrid/exporter_test.go @@ -10,7 +10,8 @@ func TestExporterCollect(t *testing.T) { // Activate the HTTP mock httpmock.Activate() defer httpmock.DeactivateAndReset() - // Mock a successful SendGrid API response + + // Mock a successful SendGrid API response for the main account httpmock.RegisterResponder("GET", "https://api.sendgrid.com/v3/user/credits", httpmock.NewStringResponder(200, `{ "total": 1000, @@ -18,27 +19,44 @@ func TestExporterCollect(t *testing.T) { "used": 200, "next_reset": "2024-02-20" }`)) - // Created a new Exporter + + // Mock a successful SendGrid API response for a subuser + httpmock.RegisterResponder("GET", "https://api.sendgrid.com/v3/subusers/mockSubuser/credits", + httpmock.NewStringResponder(200, `{ + "total": 500, + "remain": 300, + "used": 200 + }`)) + + // Created a new Exporter with subuser configuration accountConfigs := map[string]AccountConfig{ "mockAccount": { AccountName: "mockAccount", APIKey: "mockAPIKey", TimeZone: "UTC", + Subusers: []SubuserConfig{ + { + SubuserName: "mockSubuser", + APIKey: "mockSubuserAPIKey", + TimeZone: "UTC", + }, + }, }, } + exporter := NewExporter(accountConfigs) - t.Run("Successful metrics collection", func(t *testing.T) { + t.Run("Successful metrics collection for main account and subuser", func(t *testing.T) { expectedMetrics := []string{ - "sendgrid_email_limit_count", - "sendgrid_email_remaining_count", - "sendgrid_email_used_count", - "sendgrid_monitoring_http_return_code", - "sendgrid_monitoring_http_response_time_seconds", - "sendgrid_plan_expiration_seconds", + "sendgrid_email_limit_count", // main account and subuser + "sendgrid_email_remaining_count", // main account and subuser + "sendgrid_email_used_count", // main account and subuser + "sendgrid_monitoring_http_return_code", // main account and subuser + "sendgrid_monitoring_http_response_time_seconds", // main account and subuser } + // Collect and count the metrics count := testutil.CollectAndCount(exporter, expectedMetrics...) - expectedCount := len(expectedMetrics) + expectedCount := len(expectedMetrics) * 2 if count != expectedCount { t.Errorf("expected %d metrics, but got %d", expectedCount, count) }