Files
rvbox/internal/server/store/quota_test.go
T

110 lines
4.2 KiB
Go

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
}