Просмотр исходного кода

Add unit tests for Scaleway and OTC NodePricing functions

Add test coverage for the enhanced diagnostic logging in NodePricing()
functions for Scaleway and OTC cloud providers.

Tests cover:
- Successful pricing lookup
- Unknown instance type (triggers logging)
- Unknown zone/region (triggers logging)
- Empty pricing data scenarios

Signed-off-by: Warwick Peatey <warwick.peatey@ibm.com>
Claude 3 месяцев назад
Родитель
Сommit
ff24793a49
2 измененных файлов с 232 добавлено и 0 удалено
  1. 108 0
      pkg/cloud/otc/provider_test.go
  2. 124 0
      pkg/cloud/scaleway/provider_test.go

+ 108 - 0
pkg/cloud/otc/provider_test.go

@@ -0,0 +1,108 @@
+package otc
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+// mockKey implements models.Key for testing
+type mockKey struct {
+	features string
+}
+
+func (m *mockKey) Features() string { return m.features }
+func (m *mockKey) GPUType() string  { return "" }
+func (m *mockKey) GPUCount() int    { return 0 }
+func (m *mockKey) ID() string       { return "" }
+
+func TestNodePricing_Success(t *testing.T) {
+	pricing := map[string]*OTCPricing{
+		"eu-de,s2.large.4,Open Linux": {
+			NodeAttributes: &OTCNodeAttributes{
+				Type:  "s2.large.4",
+				OS:    "Open Linux",
+				Price: "0.05",
+				RAM:   "8",
+				VCPU:  "2",
+			},
+		},
+	}
+
+	otc := &OTC{
+		Pricing:          pricing,
+		ValidPricingKeys: map[string]bool{"eu-de,s2.large.4,Open Linux": true},
+		BaseCPUPrice:     "0.01",
+		BaseRAMPrice:     "0.001",
+		BaseGPUPrice:     "0.1",
+	}
+	key := &mockKey{features: "eu-de,s2.large.4,Open Linux"}
+
+	node, meta, err := otc.NodePricing(key)
+
+	assert.NoError(t, err)
+	assert.NotNil(t, node)
+	assert.NotNil(t, meta)
+	assert.Equal(t, "0.05", node.Cost)
+	assert.Equal(t, "2", node.VCPU)
+	assert.Equal(t, "8", node.RAM)
+}
+
+func TestNodePricing_InvalidKey(t *testing.T) {
+	otc := &OTC{
+		Pricing:          map[string]*OTCPricing{},
+		ValidPricingKeys: map[string]bool{},
+		BaseCPUPrice:     "0.01",
+		BaseRAMPrice:     "0.001",
+		BaseGPUPrice:     "0.1",
+	}
+	key := &mockKey{features: "unknown-region,unknown-type,unknown-os"}
+
+	node, _, err := otc.NodePricing(key)
+
+	assert.Error(t, err)
+	assert.Nil(t, node)
+	assert.Contains(t, err.Error(), "invalid Pricing Key")
+}
+
+func TestNodePricing_ValidKeyButNotLoaded(t *testing.T) {
+	// This tests the case where the key is valid but pricing data is not loaded
+	// In a real scenario, DownloadPricingData would be called, but we can't easily mock that
+	// So we test the error path where download fails
+
+	otc := &OTC{
+		Pricing:          map[string]*OTCPricing{},
+		ValidPricingKeys: map[string]bool{"eu-de,s2.large.4,Open Linux": true},
+		BaseCPUPrice:     "0.01",
+		BaseRAMPrice:     "0.001",
+		BaseGPUPrice:     "0.1",
+	}
+	key := &mockKey{features: "eu-de,s2.large.4,Open Linux"}
+
+	// This will trigger the download path which will fail since we're not in a real environment
+	// but it exercises the logging code path
+	node, _, err := otc.NodePricing(key)
+
+	// The function returns a node with base pricing on error
+	assert.Error(t, err)
+	if node != nil {
+		// If we got a node back, it should have base pricing
+		assert.Equal(t, "0.01", node.BaseCPUPrice)
+	}
+}
+
+func TestNodePricing_EmptyPricing(t *testing.T) {
+	otc := &OTC{
+		Pricing:          map[string]*OTCPricing{},
+		ValidPricingKeys: map[string]bool{},
+		BaseCPUPrice:     "0.01",
+		BaseRAMPrice:     "0.001",
+		BaseGPUPrice:     "0.1",
+	}
+	key := &mockKey{features: "eu-de,s2.large.4,Open Linux"}
+
+	node, _, err := otc.NodePricing(key)
+
+	assert.Error(t, err)
+	assert.Nil(t, node)
+}

+ 124 - 0
pkg/cloud/scaleway/provider_test.go

@@ -0,0 +1,124 @@
+package scaleway
+
+import (
+	"testing"
+
+	"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
+	"github.com/stretchr/testify/assert"
+)
+
+// mockKey implements models.Key for testing
+type mockKey struct {
+	features string
+	gpuType  string
+}
+
+func (m *mockKey) Features() string { return m.features }
+func (m *mockKey) GPUType() string  { return m.gpuType }
+func (m *mockKey) ID() string       { return "" }
+
+func TestNodePricing_Success(t *testing.T) {
+	gpuCount := uint64(0)
+	pricing := map[string]*ScalewayPricing{
+		"fr-par-1": {
+			NodesInfos: map[string]*instance.ServerType{
+				"DEV1-S": {
+					HourlyPrice: 0.01,
+					Ncpus:       2,
+					RAM:         2147483648,
+					Gpu:         &gpuCount,
+					PerVolumeConstraint: &instance.ServerTypeVolumeConstraintsByType{
+						LSSD: &instance.ServerTypeVolumeConstraintSizes{
+							MinSize: 20000000000,
+						},
+					},
+				},
+			},
+		},
+	}
+
+	c := &Scaleway{Pricing: pricing}
+	key := &mockKey{features: "fr-par-1,DEV1-S"}
+
+	node, meta, err := c.NodePricing(key)
+
+	assert.NoError(t, err)
+	assert.NotNil(t, node)
+	assert.NotNil(t, meta)
+	assert.Equal(t, "DEV1-S", node.InstanceType)
+	assert.Equal(t, "fr-par-1", node.Region)
+}
+
+func TestNodePricing_UnknownInstanceType(t *testing.T) {
+	gpuCount := uint64(0)
+	pricing := map[string]*ScalewayPricing{
+		"fr-par-1": {
+			NodesInfos: map[string]*instance.ServerType{
+				"DEV1-S": {
+					HourlyPrice: 0.01,
+					Ncpus:       2,
+					RAM:         2147483648,
+					Gpu:         &gpuCount,
+					PerVolumeConstraint: &instance.ServerTypeVolumeConstraintsByType{
+						LSSD: &instance.ServerTypeVolumeConstraintSizes{
+							MinSize: 20000000000,
+						},
+					},
+				},
+			},
+		},
+	}
+
+	c := &Scaleway{Pricing: pricing}
+	key := &mockKey{features: "fr-par-1,UNKNOWN-TYPE"}
+
+	node, _, err := c.NodePricing(key)
+
+	assert.Error(t, err)
+	assert.Nil(t, node)
+	assert.Contains(t, err.Error(), "Unable to find node pricing")
+}
+
+func TestNodePricing_UnknownZone(t *testing.T) {
+	pricing := map[string]*ScalewayPricing{
+		"fr-par-1": {
+			NodesInfos: map[string]*instance.ServerType{},
+		},
+	}
+
+	c := &Scaleway{Pricing: pricing}
+	key := &mockKey{features: "unknown-zone,DEV1-S"}
+
+	node, _, err := c.NodePricing(key)
+
+	assert.Error(t, err)
+	assert.Nil(t, node)
+	assert.Contains(t, err.Error(), "Unable to find node pricing")
+}
+
+func TestNodePricing_EmptyPricing(t *testing.T) {
+	c := &Scaleway{Pricing: map[string]*ScalewayPricing{}}
+	key := &mockKey{features: "fr-par-1,DEV1-S"}
+
+	node, _, err := c.NodePricing(key)
+
+	assert.Error(t, err)
+	assert.Nil(t, node)
+}
+
+func TestNodePricing_SingleElementFeatures(t *testing.T) {
+	pricing := map[string]*ScalewayPricing{
+		"fr-par-1": {
+			NodesInfos: map[string]*instance.ServerType{},
+		},
+	}
+
+	c := &Scaleway{Pricing: pricing}
+	key := &mockKey{features: "fr-par-1"}
+
+	node, _, err := c.NodePricing(key)
+
+	// Should fail because instance type is empty
+	assert.Error(t, err)
+	assert.Nil(t, node)
+}