package store import ( "errors" "math" "testing" ) func TestChargeFormulaVersionAndOverflow_HP_STORE_04(t *testing.T) { t.Parallel() if ChargeFormulaVersion != 1 { t.Fatalf("charge formula version = %d", ChargeFormulaVersion) } charge, err := EstimateCharge(ChargeInput{EncodedBytes: 100, SQLiteRows: 2, IndexEntries: 3}) want := uint64(100 + 2*ChargeSQLiteRowBytes + 3*ChargeIndexEntryBytes) if err != nil || charge != want { t.Fatalf("EstimateCharge = (%d, %v), want %d", charge, err, want) } for _, input := range []ChargeInput{ {SQLiteRows: math.MaxUint64}, {IndexEntries: math.MaxUint64}, {EncodedBytes: math.MaxUint64, SQLiteRows: 1}, } { if _, err := EstimateCharge(input); !errors.Is(err, ErrCapacityExhausted) { t.Errorf("EstimateCharge(%+v) error = %v", input, err) } } } func TestTieredReservationOrderAndBoundaries_HP_STORE_05(t *testing.T) { t.Parallel() limits := quotaTestLimits() base := ReservationState{ CommandOutputCharged: 10, CommandTotalCharged: 20, ClientTotalCharged: 30, ServerTotalCharged: 40, CloseoutRemaining: 20, FilesystemFreeBytes: 1000, } decision, err := CheckReservation(limits, base, ReservationRequest{ChargedBytes: 10, PhysicalBytes: 5, Output: true}) if err != nil { t.Fatal(err) } if decision.CommandOutputCharged != 20 || decision.CommandTotalCharged != 30 || decision.ClientTotalCharged != 40 || decision.ServerTotalCharged != 50 || decision.CloseoutRemaining != 20 { t.Fatalf("decision = %+v", decision) } cases := []struct { name string state ReservationState request ReservationRequest tier CapacityTier }{ {"hard maximum first", base, ReservationRequest{ChargedBytes: 101, PhysicalBytes: 1, Output: true}, CapacityTierHardMaximum}, {"output", withState(base, 95, 20, 30, 40, 20, 1000), ReservationRequest{ChargedBytes: 10, PhysicalBytes: 1, Output: true}, CapacityTierCommandOut}, {"command reserve", withState(base, 10, 175, 175, 175, 20, 1000), ReservationRequest{ChargedBytes: 10, PhysicalBytes: 1}, CapacityTierCommand}, {"client", withState(base, 10, 20, 295, 295, 20, 1000), ReservationRequest{ChargedBytes: 10, PhysicalBytes: 1}, CapacityTierClient}, {"server", withState(base, 10, 20, 30, 395, 20, 1000), ReservationRequest{ChargedBytes: 10, PhysicalBytes: 1}, CapacityTierServer}, {"filesystem", withState(base, 10, 20, 30, 40, 20, 54), ReservationRequest{ChargedBytes: 10, PhysicalBytes: 5}, CapacityTierFilesystem}, } for _, test := range cases { t.Run(test.name, func(t *testing.T) { _, err := CheckReservation(limits, test.state, test.request) var capacity *CapacityError if !errors.As(err, &capacity) || capacity.Tier != test.tier { t.Fatalf("error = %v, want tier %s", err, test.tier) } }) } } func TestCloseoutReservationCanBeConsumed_BH_STORE_06(t *testing.T) { t.Parallel() limits := quotaTestLimits() state := ReservationState{ CommandOutputCharged: 90, CommandTotalCharged: 190, ClientTotalCharged: 200, ServerTotalCharged: 200, CloseoutRemaining: 10, FilesystemFreeBytes: 1000, } if _, err := CheckReservation(limits, state, ReservationRequest{ChargedBytes: 10, PhysicalBytes: 1}); err == nil { t.Fatal("normal allocation consumed closeout headroom") } decision, err := CheckReservation(limits, state, ReservationRequest{ChargedBytes: 10, PhysicalBytes: 1, UseCloseout: true}) if err != nil { t.Fatal(err) } if decision.CommandTotalCharged != 200 || decision.CloseoutRemaining != 0 { t.Fatalf("closeout decision = %+v", decision) } if _, err := CheckReservation(limits, state, ReservationRequest{ChargedBytes: math.MaxUint64, PhysicalBytes: 1, UseCloseout: true}); !errors.Is(err, ErrCapacityExhausted) { t.Fatalf("overflow error = %v", err) } } func quotaTestLimits() QuotaLimits { return QuotaLimits{ HardAllocationBytes: 100, CommandOutputBytes: 100, CommandTotalBytes: 200, ClientTotalBytes: 300, ServerTotalBytes: 400, CloseoutReserveBytes: 20, FilesystemFloorBytes: 50, } } func withState(base ReservationState, output, command, client, server, closeout, free uint64) ReservationState { base.CommandOutputCharged = output base.CommandTotalCharged = command base.ClientTotalCharged = client base.ServerTotalCharged = server base.CloseoutRemaining = closeout base.FilesystemFreeBytes = free return base }