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
5 changes: 5 additions & 0 deletions providers/azure/services/cache/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func TestCacheClient_GetRegion(t *testing.T) {
func TestCacheClient_GetValidResourceTypes_Fallback(t *testing.T) {
// When API calls fail, GetValidResourceTypes should return common SKUs
client := NewClient(nil, "invalid-subscription", "eastus")
client.SetRedisCachesPager(&MockRedisCachesPager{})

skus, err := client.GetValidResourceTypes(context.Background())
require.NoError(t, err)
Expand All @@ -217,6 +218,7 @@ func TestCacheClient_GetValidResourceTypes_Fallback(t *testing.T) {

func TestCacheClient_ValidateOffering_InvalidSKU(t *testing.T) {
client := NewClient(nil, "sub", "eastus")
client.SetRedisCachesPager(&MockRedisCachesPager{})
rec := common.Recommendation{
ResourceType: "InvalidSKU_X99",
}
Expand Down Expand Up @@ -462,6 +464,7 @@ func TestCacheClient_GetExistingCommitments_Empty(t *testing.T) {
func TestCacheClient_ValidateOffering_ValidSKU(t *testing.T) {
ctx := context.Background()
client := NewClient(nil, "test-subscription", "eastus")
client.SetRedisCachesPager(&MockRedisCachesPager{})

rec := common.Recommendation{
ResourceType: "Premium_P1",
Expand All @@ -477,13 +480,15 @@ func TestCacheClient_ValidateOffering_CaseInsensitive(t *testing.T) {

t.Run("case_insensitive", func(t *testing.T) {
client := NewClient(nil, "test-subscription", "eastus")
client.SetRedisCachesPager(&MockRedisCachesPager{})
rec := common.Recommendation{ResourceType: "premium_p1"}
err := client.ValidateOffering(ctx, rec)
assert.NoError(t, err)
})

t.Run("whitespace_trimmed", func(t *testing.T) {
client := NewClient(nil, "test-subscription", "eastus")
client.SetRedisCachesPager(&MockRedisCachesPager{})
rec := common.Recommendation{ResourceType: " Premium_P1 "}
err := client.ValidateOffering(ctx, rec)
assert.NoError(t, err)
Expand Down
55 changes: 55 additions & 0 deletions providers/azure/services/cache/network_guard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cache

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"sync/atomic"
"testing"

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

"github.com/LeanerCloud/cloud-commitments-go/pkg/common"
)

// externalRequests counts requests that reached the loopback proxy that
// TestMain installs. The Azure SDK builds its own http.Transport, so swapping
// http.DefaultTransport would not see its calls; that transport honors
// HTTPS_PROXY, which does.
var externalRequests atomic.Int64

func TestMain(m *testing.M) {
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
externalRequests.Add(1)
http.Error(w, "network access denied in tests", http.StatusForbidden)
}))
// Set before any request so the proxy lookup, which is cached per process, sees it.
os.Setenv("HTTPS_PROXY", proxy.URL)
os.Setenv("HTTP_PROXY", proxy.URL)
os.Unsetenv("NO_PROXY")
os.Unsetenv("no_proxy")
code := m.Run()
proxy.Close()
if n := externalRequests.Load(); n > 0 && code == 0 {
fmt.Fprintf(os.Stderr, "FAIL: %d test request(s) reached the network; stub the client or pager\n", n)
code = 1
}
os.Exit(code)
}

// TestCacheClient_SKUValidation_MakesNoExternalRequests pins that SKU
// validation with a stubbed Redis caches pager never reaches the network.
func TestCacheClient_SKUValidation_MakesNoExternalRequests(t *testing.T) {
before := externalRequests.Load()
client := NewClient(nil, "test-subscription", "eastus")
client.SetRedisCachesPager(&MockRedisCachesPager{})

skus, err := client.GetValidResourceTypes(context.Background())
require.NoError(t, err)
assert.Contains(t, skus, "Premium_P1")
require.NoError(t, client.ValidateOffering(context.Background(), common.Recommendation{ResourceType: "Premium_P1"}))
assert.Zero(t, externalRequests.Load()-before, "SKU validation must not reach the network")
}
4 changes: 3 additions & 1 deletion providers/azure/services/compute/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ func TestComputeClient_GetRecommendations_WithMock(t *testing.T) {
func TestComputeClient_GetRecommendations_EmitsBothPaymentVariants(t *testing.T) {
ctx := context.Background()
client := NewClient(nil, "test-subscription", "eastus")
client.SetResourceSKUsPager(&mocks.MockResourceSKUsPager{})

// Inject a single recommendation via the mock pager.
apiRec := mocks.BuildLegacyReservationRecommendation(
Expand Down Expand Up @@ -1127,6 +1128,7 @@ func TestComputeClient_ConvertAzureVMRecommendation_NilGuards(t *testing.T) {
// PaymentOption). Subscription/Account comes from the client, not the rec.
func TestComputeClient_ConvertAzureVMRecommendation_PopulatesAllFields(t *testing.T) {
client := NewClient(nil, "test-subscription", "eastus")
client.SetResourceSKUsPager(&mocks.MockResourceSKUsPager{})
rec := mocks.BuildLegacyReservationRecommendation(
mocks.WithRegion("westeurope"),
mocks.WithScope("Shared"),
Expand Down Expand Up @@ -1674,7 +1676,7 @@ func TestPurchaseBody_SKUAndQuantityStayInMatchingUnits(t *testing.T) {
mocks.WithCosts(1000, 600, 400),
)...)

c := &Client{subscriptionID: "sub-1", region: "eastus"}
c := &Client{subscriptionID: "sub-1", region: "eastus", resourceSKUsPager: &mocks.MockResourceSKUsPager{}}
rec := c.convertAzureVMRecommendation(context.Background(), apiRec)
require.NotNil(t, rec)

Expand Down
53 changes: 53 additions & 0 deletions providers/azure/services/compute/network_guard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package compute

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"sync/atomic"
"testing"

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

"github.com/LeanerCloud/cloud-commitments-go/providers/azure/mocks"
)

// externalRequests counts requests that reached the loopback proxy that
// TestMain installs. The Azure SDK builds its own http.Transport, so swapping
// http.DefaultTransport would not see its calls; that transport honors
// HTTPS_PROXY, which does.
var externalRequests atomic.Int64

func TestMain(m *testing.M) {
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
externalRequests.Add(1)
http.Error(w, "network access denied in tests", http.StatusForbidden)
}))
// Set before any request so the proxy lookup, which is cached per process, sees it.
os.Setenv("HTTPS_PROXY", proxy.URL)
os.Setenv("HTTP_PROXY", proxy.URL)
os.Unsetenv("NO_PROXY")
os.Unsetenv("no_proxy")
code := m.Run()
proxy.Close()
if n := externalRequests.Load(); n > 0 && code == 0 {
fmt.Fprintf(os.Stderr, "FAIL: %d test request(s) reached the network; stub the client or pager\n", n)
code = 1
}
os.Exit(code)
}

// TestComputeClient_ConvertAzureVMRecommendation_MakesNoExternalRequests pins
// that conversion with a stubbed resource SKUs pager never reaches the network.
func TestComputeClient_ConvertAzureVMRecommendation_MakesNoExternalRequests(t *testing.T) {
before := externalRequests.Load()
client := NewClient(nil, "test-subscription", "eastus")
client.SetResourceSKUsPager(&mocks.MockResourceSKUsPager{})

rec := mocks.BuildLegacyReservationRecommendation(mocks.WithRegion("eastus"))
require.NotNil(t, client.convertAzureVMRecommendation(context.Background(), rec))
assert.Zero(t, externalRequests.Load()-before, "conversion must not reach the network")
}
3 changes: 3 additions & 0 deletions providers/azure/services/managedredis/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ func TestGetRegion(t *testing.T) {

func TestGetValidResourceTypes_Fallback(t *testing.T) {
c := NewClient(nil, "invalid-sub", "eastus")
c.SetRedisCachesPager(&mockRedisPager{})
skus, err := c.GetValidResourceTypes(context.Background())
require.NoError(t, err)
require.NotEmpty(t, skus)
Expand Down Expand Up @@ -322,12 +323,14 @@ func TestGetValidResourceTypes_MultipleCaches(t *testing.T) {

func TestValidateOffering_ValidSKU(t *testing.T) {
c := NewClient(nil, "sub", "eastus")
c.SetRedisCachesPager(&mockRedisPager{})
err := c.ValidateOffering(context.Background(), common.Recommendation{ResourceType: "Premium_P1"})
assert.NoError(t, err)
}

func TestValidateOffering_InvalidSKU(t *testing.T) {
c := NewClient(nil, "sub", "eastus")
c.SetRedisCachesPager(&mockRedisPager{})
err := c.ValidateOffering(context.Background(), common.Recommendation{ResourceType: "Bogus_Z99"})
require.Error(t, err)
assert.Contains(t, err.Error(), "invalid Azure Cache for Redis SKU")
Expand Down
55 changes: 55 additions & 0 deletions providers/azure/services/managedredis/network_guard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package managedredis

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"sync/atomic"
"testing"

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

"github.com/LeanerCloud/cloud-commitments-go/pkg/common"
)

// externalRequests counts requests that reached the loopback proxy that
// TestMain installs. The Azure SDK builds its own http.Transport, so swapping
// http.DefaultTransport would not see its calls; that transport honors
// HTTPS_PROXY, which does.
var externalRequests atomic.Int64

func TestMain(m *testing.M) {
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
externalRequests.Add(1)
http.Error(w, "network access denied in tests", http.StatusForbidden)
}))
// Set before any request so the proxy lookup, which is cached per process, sees it.
os.Setenv("HTTPS_PROXY", proxy.URL)
os.Setenv("HTTP_PROXY", proxy.URL)
os.Unsetenv("NO_PROXY")
os.Unsetenv("no_proxy")
code := m.Run()
proxy.Close()
if n := externalRequests.Load(); n > 0 && code == 0 {
fmt.Fprintf(os.Stderr, "FAIL: %d test request(s) reached the network; stub the client or pager\n", n)
code = 1
}
os.Exit(code)
}

// TestClient_SKUValidation_MakesNoExternalRequests pins that SKU
// validation with a stubbed Redis caches pager never reaches the network.
func TestClient_SKUValidation_MakesNoExternalRequests(t *testing.T) {
before := externalRequests.Load()
c := NewClient(nil, "test-subscription", "eastus")
c.SetRedisCachesPager(&mockRedisPager{})

skus, err := c.GetValidResourceTypes(context.Background())
require.NoError(t, err)
assert.Contains(t, skus, "Premium_P1")
require.NoError(t, c.ValidateOffering(context.Background(), common.Recommendation{ResourceType: "Premium_P1"}))
assert.Zero(t, externalRequests.Load()-before, "SKU validation must not reach the network")
}
Loading