| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- package stackit
- import (
- "testing"
- )
- func TestGpuCountFromFlavor(t *testing.T) {
- tests := []struct {
- flavor string
- want int
- }{
- {"n1.14d.g1", 1},
- {"n1.28d.g2", 2},
- {"n3.104d.g8", 8},
- {"c1i.2", 0},
- {"g2i.1", 0},
- {"n1.14d", 0},
- }
- for _, tt := range tests {
- got := gpuCountFromFlavor(tt.flavor)
- if got != tt.want {
- t.Errorf("gpuCountFromFlavor(%q) = %d, want %d", tt.flavor, got, tt.want)
- }
- }
- }
- func TestGpuTypeFromFlavor(t *testing.T) {
- tests := []struct {
- flavor string
- want string
- }{
- {"n1.14d.g1", "NVIDIA A100"},
- {"n2.28d.g2", "NVIDIA L40S"},
- {"n3.104d.g8", "NVIDIA H100 HGX"},
- {"c1i.2", ""},
- }
- for _, tt := range tests {
- got := gpuTypeFromFlavor(tt.flavor)
- if got != tt.want {
- t.Errorf("gpuTypeFromFlavor(%q) = %q, want %q", tt.flavor, got, tt.want)
- }
- }
- }
- func TestParsePIMVMFlavors(t *testing.T) {
- metro := true
- nonMetro := false
- vcpu2 := 2
- ram4 := 4.0
- skus := []pimSKU{
- {
- Name: "g2i.1",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Flavor: "g2i.1",
- VCPU: &vcpu2,
- RAM: &ram4,
- Metro: &nonMetro,
- },
- Prices: []pimPrice{{Value: "0.05045"}},
- },
- {
- // Metro variant should be skipped
- Name: "g2i.1-metro",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Flavor: "g2i.1",
- VCPU: &vcpu2,
- RAM: &ram4,
- Metro: &metro,
- },
- Prices: []pimPrice{{Value: "0.10"}},
- },
- {
- // No flavor -> skipped
- Name: "no-flavor",
- ProductSpecificAttributes: pimProductSpecificAttrs{},
- Prices: []pimPrice{{Value: "0.01"}},
- },
- {
- // No price -> skipped
- Name: "no-price",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Flavor: "c1i.2",
- VCPU: &vcpu2,
- RAM: &ram4,
- },
- Prices: []pimPrice{},
- },
- }
- flavors := parsePIMVMFlavors(skus)
- if len(flavors) != 1 {
- t.Fatalf("expected 1 flavor, got %d", len(flavors))
- }
- f, ok := flavors["g2i.1"]
- if !ok {
- t.Fatal("expected flavor g2i.1")
- }
- if f.HourlyCost != "0.05045" {
- t.Errorf("expected hourly cost 0.05045, got %s", f.HourlyCost)
- }
- if f.VCPU != 2 {
- t.Errorf("expected 2 vCPU, got %d", f.VCPU)
- }
- if f.RAMGB != 4.0 {
- t.Errorf("expected 4.0 RAM GB, got %f", f.RAMGB)
- }
- }
- func TestParsePIMVMFlavorsGPU(t *testing.T) {
- nonMetro := false
- vcpu14 := 14
- ram56 := 56.0
- skus := []pimSKU{
- {
- Name: "n1.14d.g1",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Flavor: "n1.14d.g1",
- VCPU: &vcpu14,
- RAM: &ram56,
- Metro: &nonMetro,
- },
- Prices: []pimPrice{{Value: "3.50"}},
- },
- }
- flavors := parsePIMVMFlavors(skus)
- f, ok := flavors["n1.14d.g1"]
- if !ok {
- t.Fatal("expected flavor n1.14d.g1")
- }
- if f.GPUCount != 1 {
- t.Errorf("expected GPU count 1, got %d", f.GPUCount)
- }
- if f.GPUType != "NVIDIA A100" {
- t.Errorf("expected GPU type NVIDIA A100, got %s", f.GPUType)
- }
- }
- func TestParsePIMVMFlavorsNonGPUNPrefix(t *testing.T) {
- nonMetro := false
- vcpu14 := 14
- ram56 := 56.0
- skus := []pimSKU{
- {
- Name: "n1.14d",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Flavor: "n1.14d",
- VCPU: &vcpu14,
- RAM: &ram56,
- Metro: &nonMetro,
- },
- Prices: []pimPrice{{Value: "1.50"}},
- },
- }
- flavors := parsePIMVMFlavors(skus)
- f, ok := flavors["n1.14d"]
- if !ok {
- t.Fatal("expected flavor n1.14d")
- }
- if f.GPUCount != 0 {
- t.Errorf("expected GPU count 0, got %d", f.GPUCount)
- }
- if f.GPUType != "" {
- t.Errorf("expected empty GPU type for non-GPU n1 flavor, got %q", f.GPUType)
- }
- }
- func TestParsePIMStoragePricing(t *testing.T) {
- nonMetro := false
- skus := []pimSKU{
- {
- Name: "premium-perf0",
- UnitBilling: "per GB/hour",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Class: "storage_premium_perf0",
- Metro: &nonMetro,
- },
- Prices: []pimPrice{{Value: "0.0001"}},
- },
- {
- Name: "premium-perf2",
- UnitBilling: "per GB/hour",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Class: "storage_premium_perf2",
- Metro: &nonMetro,
- },
- Prices: []pimPrice{{Value: "0.0005"}},
- },
- {
- // Non-GB/hour billing -> skipped
- Name: "iops-based",
- UnitBilling: "per IOPS/hour",
- ProductSpecificAttributes: pimProductSpecificAttrs{
- Class: "storage_iops",
- Metro: &nonMetro,
- },
- Prices: []pimPrice{{Value: "0.01"}},
- },
- }
- pricing := parsePIMStoragePricing(skus)
- if _, ok := pricing["storage_premium_perf0"]; !ok {
- t.Error("expected storage_premium_perf0")
- }
- if _, ok := pricing["storage_premium_perf2"]; !ok {
- t.Error("expected storage_premium_perf2")
- }
- if _, ok := pricing["storage_iops"]; ok {
- t.Error("storage_iops should have been skipped (non GB/hour billing)")
- }
- // Default should be the cheapest
- def, ok := pricing["default"]
- if !ok {
- t.Fatal("expected default storage entry")
- }
- if def.CostPerGBHr != "0.0001" {
- t.Errorf("expected default cost 0.0001, got %s", def.CostPerGBHr)
- }
- }
- func TestPaginationTermination(t *testing.T) {
- // Verify that empty data or empty cursor terminates pagination.
- // This is a logic check - fetchAllPIMSKUs breaks on:
- // searchResp.Meta.NextCursor == "" || len(searchResp.Data) == 0
- // We can't call the real API, but we verify the parsing logic
- // handles the termination conditions in parsePIMVMFlavors.
- // Empty input should produce empty output
- flavors := parsePIMVMFlavors(nil)
- if len(flavors) != 0 {
- t.Errorf("expected 0 flavors from nil input, got %d", len(flavors))
- }
- flavors = parsePIMVMFlavors([]pimSKU{})
- if len(flavors) != 0 {
- t.Errorf("expected 0 flavors from empty input, got %d", len(flavors))
- }
- }
|