Skip to content

Commit

Permalink
sc-14371 added test cases for client and exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
Gyan-Gupta-Rtsl committed Jan 17, 2025
1 parent e9be873 commit aaaebc8
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 15 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
6 changes: 4 additions & 2 deletions sendgrid/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
19 changes: 17 additions & 2 deletions sendgrid/client_test.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
package sendgrid_test

import (
"bytes"
"encoding/json"
"io/ioutil"
"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)
Expand All @@ -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{}
Expand All @@ -57,37 +65,43 @@ 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)
assert.InDelta(t, 1000, metrics.Total, 0.001)
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{}
mockAPIKey := "mockAPIKey"
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{}
mockAPIKey := "mockAPIKey"
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{}
Expand All @@ -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)
}
assert.Equal(t, 0, statusCode)
}
38 changes: 28 additions & 10 deletions sendgrid/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,53 @@ 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,
"remain": 800,
"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)
}
Expand Down

0 comments on commit aaaebc8

Please sign in to comment.