feat: enforce client spool quota tiers
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package spool
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCheckReservationQuotaTiers_BH_RET_01(t *testing.T) {
|
||||
t.Parallel()
|
||||
limits := QuotaLimits{HardAllocationBytes: 1_000, CommandOutputBytes: 1_200, CommandTotalBytes: 2_000, ClientTotalBytes: 3_000, CloseoutReserveBytes: 400}
|
||||
cases := []struct {
|
||||
name string
|
||||
state ReservationState
|
||||
request ReservationRequest
|
||||
tier CapacityTier
|
||||
}{
|
||||
{name: "hard allocation", request: ReservationRequest{ChargedBytes: 1_001}, tier: CapacityTierHardMaximum},
|
||||
{name: "output", state: ReservationState{CommandOutputCharged: 1_100}, request: ReservationRequest{ChargedBytes: 101, Output: true}, tier: CapacityTierCommandOut},
|
||||
{name: "normal preserves closeout", state: ReservationState{CommandTotalCharged: 1_500, CloseoutRemaining: 400}, request: ReservationRequest{ChargedBytes: 101}, tier: CapacityTierCommand},
|
||||
{name: "client", state: ReservationState{ClientTotalCharged: 2_900, CloseoutRemaining: 400}, request: ReservationRequest{ChargedBytes: 101}, tier: CapacityTierClient},
|
||||
}
|
||||
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("CheckReservation error = %v, want tier %q", err, test.tier)
|
||||
}
|
||||
})
|
||||
}
|
||||
decision, err := CheckReservation(limits, ReservationState{CommandTotalCharged: 1_500, CloseoutRemaining: 400}, ReservationRequest{ChargedBytes: 400, UseCloseout: true})
|
||||
if err != nil || decision.CloseoutRemaining != 0 || decision.CommandTotalCharged != 1_900 {
|
||||
t.Fatalf("closeout reservation = %#v, %v", decision, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpoolAcknowledgementReleasesQuota_HP_CLIENT_08(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
limits := QuotaLimits{HardAllocationBytes: 1_000, CommandOutputBytes: 800, CommandTotalBytes: 2_000, ClientTotalBytes: 3_000, CloseoutReserveBytes: 400}
|
||||
store, err := Open(ctx, Options{DataDir: filepath.Join(t.TempDir(), "spool"), BusyTimeout: time.Second, QuotaLimits: limits})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = store.Close() })
|
||||
issue := testUUID(t, "019c46f1-1d02-7000-8000-000000000021")
|
||||
if _, err := store.AcceptCommand(ctx, testCommand(issue, []byte("quota")), time.Now().UTC()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
input := EventInput{Kind: 1, Compression: 1, RawBytes: 200, Payload: make([]byte, 200), Output: true, CreatedAt: time.Now().UTC()}
|
||||
if _, err := store.AppendEvent(ctx, issue, input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := store.AppendEvent(ctx, issue, input); !errors.Is(err, ErrCapacityExhausted) {
|
||||
t.Fatalf("second output append error = %v, want ErrCapacityExhausted", err)
|
||||
}
|
||||
if _, err := store.AssignSendWindow(ctx, issue, 1, 1<<20); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := store.Ack(ctx, issue, 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := store.AppendEvent(ctx, issue, input); err != nil {
|
||||
t.Fatalf("append after acknowledgement did not release quota: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user