| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- package pricing
- import (
- "testing"
- "github.com/opencost/opencost/core/pkg/model/shared"
- "github.com/opencost/opencost/core/pkg/unit"
- )
- func nodePricing(instanceType string, price float64) *NodePricing {
- return &NodePricing{
- Properties: NodePricingProperties{
- Provider: shared.Provider("AWS"),
- Region: "us-east-1",
- InstanceType: instanceType,
- },
- Prices: Prices{
- ResourceNode: {Unit: unit.Hour, Price: price},
- },
- }
- }
- func pvPricing(volumeType VolumeType, price float64) *PersistentVolumePricing {
- return &PersistentVolumePricing{
- Properties: PersistentVolumePricingProperties{
- Provider: shared.Provider("AWS"),
- Region: "us-east-1",
- VolumeType: volumeType,
- },
- Prices: Prices{
- ResourceStorage: {Unit: unit.GiBHour, Price: price},
- },
- }
- }
- // TestChecksumPriceSensitivity verifies that the checksum changes when only a
- // price value changes, even if all properties are identical.
- func TestChecksumPriceSensitivity(t *testing.T) {
- a := &PricingSet{NodePricing: []*NodePricing{nodePricing("m5.large", 0.096)}}
- b := &PricingSet{NodePricing: []*NodePricing{nodePricing("m5.large", 0.192)}}
- csA, err := a.Checksum()
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- csB, err := b.Checksum()
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if csA == csB {
- t.Errorf("expected differing checksums for differing prices, got %q for both", csA)
- }
- }
- // TestChecksumOrderStability verifies that the checksum is independent of the
- // ordering of pricing slices.
- func TestChecksumOrderStability(t *testing.T) {
- n1 := nodePricing("m5.large", 0.096)
- n2 := nodePricing("m5.xlarge", 0.192)
- n3 := nodePricing("m5.2xlarge", 0.384)
- forward := &PricingSet{NodePricing: []*NodePricing{n1, n2, n3}}
- reverse := &PricingSet{NodePricing: []*NodePricing{n3, n2, n1}}
- csForward, err := forward.Checksum()
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- csReverse, err := reverse.Checksum()
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if csForward != csReverse {
- t.Errorf("expected checksum to be order-independent, got %q vs %q", csForward, csReverse)
- }
- }
- // TestChecksumNilReceiver verifies that Checksum handles a nil receiver like
- // IsEmpty and Currencies do, rather than panicking.
- func TestChecksumNilReceiver(t *testing.T) {
- var ps *PricingSet
- if _, err := ps.Checksum(); err != nil {
- t.Errorf("unexpected error on nil receiver: %v", err)
- }
- }
- // TestIsEmptyAllKinds verifies that a set holding only Cluster/Network/Service
- // pricing is not reported empty.
- func TestIsEmptyAllKinds(t *testing.T) {
- if !(&PricingSet{}).IsEmpty() {
- t.Errorf("expected empty set to report empty")
- }
- cases := map[string]*PricingSet{
- "cluster": {ClusterPricing: []*ClusterPricing{{Properties: ClusterPricingProperties{Provider: shared.Provider("AWS")}}}},
- "network": {NetworkPricing: []*NetworkPricing{{Properties: NetworkPricingProperties{Provider: shared.Provider("AWS")}}}},
- "node": {NodePricing: []*NodePricing{nodePricing("m5.large", 0.096)}},
- "volume": {PersistentVolumePricing: []*PersistentVolumePricing{pvPricing(VolumeTypeGP3, 0.0001)}},
- "service": {ServicePricing: []*ServicePricing{{Properties: ServicePricingProperties{Provider: shared.Provider("AWS")}}}},
- }
- for name, ps := range cases {
- if ps.IsEmpty() {
- t.Errorf("set with only %s pricing should not be empty", name)
- }
- }
- }
- // TestMockGetPricingSetAllKinds verifies that the mock's GetPricingSet exposes
- // the same kinds as its readers, not just node + persistent volume.
- func TestMockGetPricingSetAllKinds(t *testing.T) {
- mpm, err := NewMockPricingModule()
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- ps, err := mpm.GetPricingSet(t.Context())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(ps.NodePricing) != len(mpm.NodePricing) {
- t.Errorf("expected %d node pricing, got %d", len(mpm.NodePricing), len(ps.NodePricing))
- }
- if len(ps.PersistentVolumePricing) != len(mpm.PersistentVolumePricing) {
- t.Errorf("expected %d volume pricing, got %d", len(mpm.PersistentVolumePricing), len(ps.PersistentVolumePricing))
- }
- if len(ps.ClusterPricing) != len(mpm.ClusterPricing) {
- t.Errorf("expected %d cluster pricing, got %d", len(mpm.ClusterPricing), len(ps.ClusterPricing))
- }
- if len(ps.NetworkPricing) != len(mpm.NetworkPricing) {
- t.Errorf("expected %d network pricing, got %d", len(mpm.NetworkPricing), len(ps.NetworkPricing))
- }
- if len(ps.ServicePricing) != len(mpm.ServicePricing) {
- t.Errorf("expected %d service pricing, got %d", len(mpm.ServicePricing), len(ps.ServicePricing))
- }
- }
|