Skip to content
Merged
Show file tree
Hide file tree
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
17 changes: 10 additions & 7 deletions ci_cd_sanity_tests/cmd/sanity/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ import (
"github.com/LeanerCloud/cloud-commitments-go/ci_cd_sanity_tests/pkg/sanity/aws"
)

// validateInt32Range reports an error when n is outside [1, math.MaxInt32].
func validateInt32Range(flagName string, n int) error {
if n < 1 || n > math.MaxInt32 {
return fmt.Errorf("%s must be between 1 and %d, got %d", flagName, math.MaxInt32, n)
}
return nil
}

// requireInt32Range exits with an error when n is outside [1, math.MaxInt32].
func requireInt32Range(flagName string, n int) {
if n < 1 || n > (1<<31-1) {
fmt.Fprintf(os.Stderr, "ERROR: %s must be between 1 and math.MaxInt32\n", flagName)
if err := validateInt32Range(flagName, n); err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
os.Exit(2)
}
}
Expand All @@ -29,11 +37,6 @@ func main() {
flag.Parse()
requireInt32Range("--max-list", *maxList)

if *maxList < 1 || *maxList > math.MaxInt32 {
fmt.Fprintf(os.Stderr, "ERROR: --max-list must be between 1 and %d, got %d\n", math.MaxInt32, *maxList)
os.Exit(2)
}

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)

rep, err := aws.Run(ctx, aws.Options{
Expand Down
40 changes: 40 additions & 0 deletions ci_cd_sanity_tests/cmd/sanity/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

import (
"math"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestValidateInt32Range(t *testing.T) {
// Computed at run time so the test still compiles where int is 32 bits;
// there it wraps to math.MinInt32, which is rejected as well.
aboveMax := math.MaxInt32
aboveMax++

tests := []struct {
name string
n int
wantErr bool
}{
{name: "zero", n: 0, wantErr: true},
{name: "negative", n: -1, wantErr: true},
{name: "lower bound", n: 1, wantErr: false},
{name: "default", n: 5, wantErr: false},
{name: "upper bound", n: math.MaxInt32, wantErr: false},
{name: "above upper bound", n: aboveMax, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validateInt32Range("--max-list", tt.n)
if !tt.wantErr {
assert.NoError(t, err)
return
}
require.Error(t, err)
assert.Contains(t, err.Error(), "--max-list must be between 1 and 2147483647")
})
}
}
95 changes: 37 additions & 58 deletions providers/azure/services/cache/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,27 +90,6 @@ func (m *MockRedisCachesPager) NextPage(ctx context.Context) (armredis.ClientLis
return page, nil
}

// MockHTTPClient mocks HTTP client for testing.
type MockHTTPClient struct {
mock.Mock
}

func (m *MockHTTPClient) Do(req *http.Request) (*http.Response, error) {
args := m.Called(req)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*http.Response), args.Error(1)
}

func createMockHTTPResponse(statusCode int, body string) *http.Response {
return &http.Response{
StatusCode: statusCode,
Body: io.NopCloser(bytes.NewBufferString(body)),
Header: make(http.Header),
}
}

func createSampleRedisPricingResponse() string {
return `{
"Items": [
Expand Down Expand Up @@ -273,7 +252,7 @@ func TestRedisPricingStructure(t *testing.T) {

func TestNewClientWithHTTP(t *testing.T) {
t.Parallel()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)

require.NotNil(t, client)
Expand All @@ -285,10 +264,10 @@ func TestNewClientWithHTTP(t *testing.T) {
func TestCacheClient_GetOfferingDetails_WithMock(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)

response1 := createMockHTTPResponse(http.StatusOK, createSampleRedisPricingResponse())
response1 := mocks.CreateMockHTTPResponse(http.StatusOK, createSampleRedisPricingResponse())
t.Cleanup(func() {
require.NoError(t, response1.Body.Close())
})
Expand All @@ -313,10 +292,10 @@ func TestCacheClient_GetOfferingDetails_WithMock(t *testing.T) {
func TestCacheClient_GetOfferingDetails_3YearTerm(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)

response2 := createMockHTTPResponse(http.StatusOK, createSampleRedisPricingResponse())
response2 := mocks.CreateMockHTTPResponse(http.StatusOK, createSampleRedisPricingResponse())
t.Cleanup(func() {
require.NoError(t, response2.Body.Close())
})
Expand All @@ -340,10 +319,10 @@ func TestCacheClient_GetOfferingDetails_3YearTerm(t *testing.T) {
func TestCacheClient_GetOfferingDetails_NoUpfront(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)

response3 := createMockHTTPResponse(http.StatusOK, createSampleRedisPricingResponse())
response3 := mocks.CreateMockHTTPResponse(http.StatusOK, createSampleRedisPricingResponse())
t.Cleanup(func() {
require.NoError(t, response3.Body.Close())
})
Expand All @@ -367,10 +346,10 @@ func TestCacheClient_GetOfferingDetails_NoUpfront(t *testing.T) {
func TestCacheClient_GetOfferingDetails_APIError(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)

response4 := createMockHTTPResponse(http.StatusInternalServerError, "Internal Server Error")
response4 := mocks.CreateMockHTTPResponse(http.StatusInternalServerError, "Internal Server Error")
t.Cleanup(func() {
require.NoError(t, response4.Body.Close())
})
Expand All @@ -392,10 +371,10 @@ func TestCacheClient_GetOfferingDetails_APIError(t *testing.T) {
func TestCacheClient_GetOfferingDetails_NoPricing(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)

response5 := createMockHTTPResponse(http.StatusOK, `{"Items": []}`)
response5 := mocks.CreateMockHTTPResponse(http.StatusOK, `{"Items": []}`)
t.Cleanup(func() {
require.NoError(t, response5.Body.Close())
})
Expand Down Expand Up @@ -437,9 +416,9 @@ func TestCacheClient_GetOfferingDetails_NoReservationPricing(t *testing.T) {
"NextPageLink": ""
}`

mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
client := NewClientWithHTTP(nil, "test-subscription", "eastus", mockHTTP)
response6 := createMockHTTPResponse(http.StatusOK, onDemandOnly)
response6 := mocks.CreateMockHTTPResponse(http.StatusOK, onDemandOnly)
t.Cleanup(func() {
require.NoError(t, response6.Body.Close())
})
Expand Down Expand Up @@ -1090,18 +1069,18 @@ func calcPriceRespJSON(orderID string) string {
func TestCacheClient_PurchaseCommitment_Success(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

calculateResp7 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-001"))
calculateResp7 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-001"))
t.Cleanup(func() {
require.NoError(t, calculateResp7.Body.Close())
})
mockHTTP.On("Do", mock.MatchedBy(func(r *http.Request) bool {
return r.URL.Path == "/providers/Microsoft.Capacity/calculatePrice"
})).Return(calculateResp7, nil).Once()
purchaseResp8 := createMockHTTPResponse(http.StatusOK, `{}`)
purchaseResp8 := mocks.CreateMockHTTPResponse(http.StatusOK, `{}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp8.Body.Close())
})
Expand Down Expand Up @@ -1129,18 +1108,18 @@ func TestCacheClient_PurchaseCommitment_Success(t *testing.T) {
func TestCacheClient_PurchaseCommitment_3YearTerm(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

calculateResp9 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-3yr"))
calculateResp9 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-3yr"))
t.Cleanup(func() {
require.NoError(t, calculateResp9.Body.Close())
})
mockHTTP.On("Do", mock.MatchedBy(func(r *http.Request) bool {
return r.URL.Path == "/providers/Microsoft.Capacity/calculatePrice"
})).Return(calculateResp9, nil).Once()
purchaseResp10 := createMockHTTPResponse(http.StatusCreated, `{}`)
purchaseResp10 := mocks.CreateMockHTTPResponse(http.StatusCreated, `{}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp10.Body.Close())
})
Expand All @@ -1166,18 +1145,18 @@ func TestCacheClient_PurchaseCommitment_3YearTerm(t *testing.T) {
func TestCacheClient_PurchaseCommitment_Accepted(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

calculateResp11 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-202"))
calculateResp11 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-202"))
t.Cleanup(func() {
require.NoError(t, calculateResp11.Body.Close())
})
mockHTTP.On("Do", mock.MatchedBy(func(r *http.Request) bool {
return r.URL.Path == "/providers/Microsoft.Capacity/calculatePrice"
})).Return(calculateResp11, nil).Once()
purchaseResp12 := createMockHTTPResponse(http.StatusAccepted, `{}`)
purchaseResp12 := mocks.CreateMockHTTPResponse(http.StatusAccepted, `{}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp12.Body.Close())
})
Expand All @@ -1202,7 +1181,7 @@ func TestCacheClient_PurchaseCommitment_Accepted(t *testing.T) {
func TestCacheClient_PurchaseCommitment_TokenError(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{err: errors.New("token error")}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

Expand All @@ -1222,7 +1201,7 @@ func TestCacheClient_PurchaseCommitment_TokenError(t *testing.T) {
func TestCacheClient_PurchaseCommitment_HTTPError(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

Expand All @@ -1246,18 +1225,18 @@ func TestCacheClient_PurchaseCommitment_HTTPError(t *testing.T) {
func TestCacheClient_PurchaseCommitment_BadStatus(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

calculateResp13 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-bad"))
calculateResp13 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON("cache-order-bad"))
t.Cleanup(func() {
require.NoError(t, calculateResp13.Body.Close())
})
mockHTTP.On("Do", mock.MatchedBy(func(r *http.Request) bool {
return r.URL.Path == "/providers/Microsoft.Capacity/calculatePrice"
})).Return(calculateResp13, nil).Once()
purchaseResp14 := createMockHTTPResponse(http.StatusBadRequest, `{"error": "invalid request"}`)
purchaseResp14 := mocks.CreateMockHTTPResponse(http.StatusBadRequest, `{"error": "invalid request"}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp14.Body.Close())
})
Expand Down Expand Up @@ -1291,12 +1270,12 @@ func TestCacheClient_PurchaseCommitment_TagInjection(t *testing.T) {
const source = common.PurchaseSourceWeb

ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

var capturedBody []byte
calculateResp15 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON(orderID))
calculateResp15 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON(orderID))
t.Cleanup(func() {
require.NoError(t, calculateResp15.Body.Close())
})
Expand All @@ -1308,7 +1287,7 @@ func TestCacheClient_PurchaseCommitment_TagInjection(t *testing.T) {
r.Body = io.NopCloser(bytes.NewReader(capturedBody))
return true
})).Return(calculateResp15, nil).Once()
purchaseResp16 := createMockHTTPResponse(http.StatusOK, `{}`)
purchaseResp16 := mocks.CreateMockHTTPResponse(http.StatusOK, `{}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp16.Body.Close())
})
Expand Down Expand Up @@ -1352,7 +1331,7 @@ func TestCacheClient_PurchaseCommitment_BillingPlan(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

Expand All @@ -1369,7 +1348,7 @@ func TestCacheClient_PurchaseCommitment_BillingPlan(t *testing.T) {

const orderID = "cache-billingplan-test"
var capturedBody []byte
calculateResp17 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON(orderID))
calculateResp17 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON(orderID))
t.Cleanup(func() {
require.NoError(t, calculateResp17.Body.Close())
})
Expand All @@ -1381,7 +1360,7 @@ func TestCacheClient_PurchaseCommitment_BillingPlan(t *testing.T) {
r.Body = io.NopCloser(bytes.NewReader(capturedBody))
return true
})).Return(calculateResp17, nil).Once()
purchaseResp18 := createMockHTTPResponse(http.StatusOK, `{}`)
purchaseResp18 := mocks.CreateMockHTTPResponse(http.StatusOK, `{}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp18.Body.Close())
})
Expand Down Expand Up @@ -1418,7 +1397,7 @@ func TestCacheClient_PurchaseCommitment_BillingPlan(t *testing.T) {
func TestCacheClient_PurchaseCommitment_RequiresSource(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

Expand All @@ -1437,13 +1416,13 @@ func TestCacheClient_PurchaseCommitment_RequiresSource(t *testing.T) {
func TestCacheClient_PurchaseCommitment_DisplayNameConformsToAzureAllowlist(t *testing.T) {
t.Parallel()
ctx := context.Background()
mockHTTP := &MockHTTPClient{}
mockHTTP := &mocks.MockHTTPClient{}
mockCred := &MockTokenCredential{token: "test-token"}
client := NewClientWithHTTP(mockCred, "test-subscription", "eastus", mockHTTP)

const orderID = "azure-cache-displayname"
var capturedDisplayName string
calculateResp19 := createMockHTTPResponse(http.StatusOK, calcPriceRespJSON(orderID))
calculateResp19 := mocks.CreateMockHTTPResponse(http.StatusOK, calcPriceRespJSON(orderID))
t.Cleanup(func() {
require.NoError(t, calculateResp19.Body.Close())
})
Expand All @@ -1466,7 +1445,7 @@ func TestCacheClient_PurchaseCommitment_DisplayNameConformsToAzureAllowlist(t *t
}
return true
})).Return(calculateResp19, nil).Once()
purchaseResp20 := createMockHTTPResponse(http.StatusOK, `{}`)
purchaseResp20 := mocks.CreateMockHTTPResponse(http.StatusOK, `{}`)
t.Cleanup(func() {
require.NoError(t, purchaseResp20.Body.Close())
})
Expand Down
Loading
Loading