package economics import ( "math" "testing" "github.com/carlosframework/platform/internal/usage" ) func approx(t *testing.T, name string, got, want float64) { t.Helper() if math.Abs(got-want) > 1e-9 { t.Fatalf("%s = %v, want %v", name, got, want) } } // A 2-core/2GB box at $0.10/h with no EBS, 100h period, one tenant using // 50 core-hours (25% of 200 available) and 100 GB-hours (50% of 200). func testBox() (RateCard, BoxLoad) { rc := RateCard{Boxes: map[string]BoxSpec{"": {HourUSD: 0.10, Cores: 2, MemGB: 2}}} b := BoxLoad{Box: "box1", Hours: 100, ByAccount: map[string]BoxAccountLoad{ "bab": {CPUCoreHours: 50, MemGBHours: 100}, }} return rc, b } func TestAllocateBoxPolicies(t *testing.T) { rc, b := testBox() per, idle, total := AllocateBox(rc, Allocation{Policy: "cpu"}, b) approx(t, "total", total, 10.0) approx(t, "cpu share", per["bab"], 2.5) // 25% of $10 approx(t, "cpu idle", idle, 7.5) per, idle, _ = AllocateBox(rc, Allocation{Policy: "mem"}, b) approx(t, "mem share", per["bab"], 5.0) // 50% of $10 approx(t, "mem idle", idle, 5.0) per, idle, _ = AllocateBox(rc, Allocation{Policy: "blend", CPUWeight: 0.5}, b) approx(t, "blend share", per["bab"], 3.75) // (0.5*25% + 0.5*50%) of $10 approx(t, "blend idle", idle, 6.25) } func TestAllocateBoxEBSAndFallbackSpec(t *testing.T) { rc := RateCard{ Boxes: map[string]BoxSpec{"": {HourUSD: 0.10, Cores: 2, MemGB: 2, EBSGB: 73}}, EBSGBMonthUSD: 0.10, } b := BoxLoad{Box: "unlisted-box", Hours: 730, ByAccount: nil} _, idle, total := AllocateBox(rc, Allocation{Policy: "cpu"}, b) // 730h of $0.10 = $73, plus 73GB*$0.10/GB-month * (730/730) = $7.30. approx(t, "total", total, 80.3) approx(t, "all idle", idle, 80.3) } func TestPriceAccountCostPlusEightyMarginIsFiveX(t *testing.T) { sc := DefaultScenario() sc.RateCard.EgressGBUSD = 0.10 sc.RateCard.RequestsPer1kUSD = 0 sc.RateCard.StorageGBMonthUSD = 0 sc.FreeTier = FreeTier{} // no free tier: pure margin check meters := map[string]float64{usage.MeterEgressGB: 10} // $1 of egress cost ae := PriceAccount(sc, "bab", meters, 0) approx(t, "cost", ae.CostUSD, 1.0) approx(t, "revenue", ae.RevenueUSD, 5.0) // 80% margin = 5x cost approx(t, "margin", ae.MarginFrac, 0.8) if ae.FreeTierPos != "paying" { t.Fatalf("pos = %q", ae.FreeTierPos) } } func TestPriceAccountFreeTierSubtraction(t *testing.T) { sc := DefaultScenario() sc.Mode = "rate-sheet" sc.Sheet = RateSheet{AppMonthUSD: 5, EgressGBUSD: 0.15} sc.FreeTier = FreeTier{Apps: 1, EgressGB: 10} meters := map[string]float64{usage.MeterAppMonths: 2, usage.MeterEgressGB: 14} ae := PriceAccount(sc, "bab", meters, 0) // Billable: 1 app-month, 4 GB egress = $5 + $0.60. approx(t, "revenue", ae.RevenueUSD, 5.6) if ae.FreeTierPos != "partial" { t.Fatalf("pos = %q", ae.FreeTierPos) } inside := PriceAccount(sc, "tiny", map[string]float64{usage.MeterAppMonths: 1, usage.MeterEgressGB: 2}, 0) approx(t, "inside revenue", inside.RevenueUSD, 0) if inside.FreeTierPos != "inside" { t.Fatalf("inside pos = %q", inside.FreeTierPos) } } func TestPriceAccountComputeFraction(t *testing.T) { sc := DefaultScenario() sc.Mode = "cost-plus" sc.Margin = 0.5 sc.RateCard.EgressGBUSD, sc.RateCard.RequestsPer1kUSD, sc.RateCard.StorageGBMonthUSD = 0, 0, 0 sc.FreeTier = FreeTier{MemGBHours: 100} meters := map[string]float64{usage.MeterMemGBHours: 400} // $8 allocated, 300/400 billable -> $6 billable cost -> $12 revenue at 50%. ae := PriceAccount(sc, "bab", meters, 8) approx(t, "cost", ae.CostUSD, 8) approx(t, "revenue", ae.RevenueUSD, 12) } func TestProject(t *testing.T) { approx(t, "project", Project(10, 10, 30), 30) approx(t, "zero covered", Project(10, 0, 30), 0) } func TestPriceAccountFleetBoxes(t *testing.T) { sc := DefaultScenario() sc.Mode = "rate-sheet" sc.Sheet = RateSheet{BoxMonthServerUSD: 5, BoxMonthDeviceUSD: 1} sc.FreeTier = FreeTier{} // 2 server boxes + 5 device boxes, full month. meters := map[string]float64{ usage.MeterFleetBoxHoursServer: 2 * 730, usage.MeterFleetBoxHoursDevice: 5 * 730, } ae := PriceAccount(sc, "bae", meters, 0) approx(t, "fleet revenue", ae.RevenueUSD, 2*5+5*1) // $15 } func TestPriceAccountFleetVolumeBreak(t *testing.T) { sc := DefaultScenario() sc.Mode = "rate-sheet" sc.Sheet = RateSheet{BoxMonthServerUSD: 5} sc.FleetBreak = FleetBreak{MinBoxes: 10, Discount: 0.4} sc.FreeTier = FreeTier{} meters := map[string]float64{usage.MeterFleetBoxHoursServer: 12 * 730} ae := PriceAccount(sc, "bae", meters, 0) approx(t, "discounted", ae.RevenueUSD, 12*5*0.6) // $36 // 9.99 avg boxes: no break. meters[usage.MeterFleetBoxHoursServer] = 9.99 * 730 ae = PriceAccount(sc, "bae", meters, 0) approx(t, "no break", ae.RevenueUSD, 9.99*5) } func TestPriceAccountFleetAddsInCostPlusToo(t *testing.T) { sc := DefaultScenario() sc.Mode = "cost-plus" sc.Margin = 0.5 sc.Sheet.BoxMonthServerUSD = 5 sc.RateCard.EgressGBUSD = 0.10 sc.RateCard.RequestsPer1kUSD, sc.RateCard.StorageGBMonthUSD = 0, 0 sc.FreeTier = FreeTier{} meters := map[string]float64{ usage.MeterEgressGB: 10, // $1 cost -> $2 cost-plus revenue usage.MeterFleetBoxHoursServer: 1 * 730, // + $5 box-month } ae := PriceAccount(sc, "bae", meters, 0) approx(t, "combined", ae.RevenueUSD, 2+5) } func TestPriceAccountMemOverage(t *testing.T) { sc := DefaultScenario() sc.Mode = "rate-sheet" sc.Sheet = RateSheet{MemGBHourUSD: 0.01} sc.FreeTier = FreeTier{MemGBHours: 100} meters := map[string]float64{usage.MeterMemGBHours: 400} ae := PriceAccount(sc, "bab", meters, 0) approx(t, "overage", ae.RevenueUSD, 3.0) // 300 over * $0.01 }