Files
promptkit/internal/capacity/manager_test.go

159 lines
3.7 KiB
Go

package capacity
import (
"context"
"errors"
"testing"
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
)
func TestNewManagerRejectsInvalidPolicies(t *testing.T) {
maxInt := int(^uint(0) >> 1)
tests := []struct {
name string
id string
policy domain.BackendCapacityPolicy
}{
{
name: "blank ID",
id: " \t ",
policy: domain.BackendCapacityPolicy{ConcurrencyLimit: 1},
},
{
name: "zero concurrency",
id: "backend",
policy: domain.BackendCapacityPolicy{},
},
{
name: "negative concurrency",
id: "backend",
policy: domain.BackendCapacityPolicy{ConcurrencyLimit: -1},
},
{
name: "negative queue",
id: "backend",
policy: domain.BackendCapacityPolicy{
ConcurrencyLimit: 1,
QueueCapacity: -1,
},
},
{
name: "total overflow",
id: "backend",
policy: domain.BackendCapacityPolicy{
ConcurrencyLimit: maxInt,
QueueCapacity: 1,
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
_, err := NewManager(map[string]domain.BackendCapacityPolicy{
tc.id: tc.policy,
})
if err == nil {
t.Fatal("expected invalid policy error")
}
})
}
}
func TestManagerAdmissionIsBoundedAndReleaseIsIdempotent(t *testing.T) {
policies := map[string]domain.BackendCapacityPolicy{
"limited": {
ConcurrencyLimit: 2,
QueueCapacity: 1,
},
"independent": {
ConcurrencyLimit: 1,
},
}
manager, err := NewManager(policies)
if err != nil {
t.Fatalf("construct manager: %v", err)
}
policies["limited"] = domain.BackendCapacityPolicy{
ConcurrencyLimit: 100,
QueueCapacity: 100,
}
releases := make([]func(), 0, 3)
for range 3 {
release, err := manager.Admit(context.Background(), "limited")
if err != nil {
t.Fatalf("admit within configured capacity: %v", err)
}
releases = append(releases, release)
}
if release, err := manager.Admit(context.Background(), "limited"); release != nil ||
!errors.Is(err, ErrCapacityExceeded) {
t.Fatalf("admission beyond capacity=(release=%t, err=%v), want ErrCapacityExceeded",
release != nil, err)
}
independentRelease, err := manager.Admit(context.Background(), "independent")
if err != nil {
t.Fatalf("admit independent backend while first is full: %v", err)
}
independentRelease()
releases[0]()
releases[0]()
replacement, err := manager.Admit(context.Background(), "limited")
if err != nil {
t.Fatalf("admit after release: %v", err)
}
replacement()
releases[1]()
releases[2]()
pool := manager.pools["limited"]
pool.mu.Lock()
admitted := pool.admitted
pool.mu.Unlock()
if admitted != 0 {
t.Fatalf("admitted runs after releases=%d, want 0", admitted)
}
}
func TestManagerAdmissionHonorsContextAndUnlimitedBackends(t *testing.T) {
manager, err := NewManager(map[string]domain.BackendCapacityPolicy{
"limited": {ConcurrencyLimit: 1},
})
if err != nil {
t.Fatalf("construct manager: %v", err)
}
ctx, cancel := context.WithCancel(context.Background())
cancel()
if release, err := manager.Admit(ctx, "limited"); release != nil ||
!errors.Is(err, context.Canceled) {
t.Fatalf("canceled limited admission=(release=%t, err=%v), want context cancellation",
release != nil, err)
}
var nilManager *Manager
for _, tc := range []struct {
name string
manager *Manager
backendID string
}{
{name: "nil manager", manager: nilManager, backendID: "limited"},
{name: "blank ID", manager: manager},
{name: "unknown ID", manager: manager, backendID: "unknown"},
} {
t.Run(tc.name, func(t *testing.T) {
release, err := tc.manager.Admit(ctx, tc.backendID)
if err != nil {
t.Fatalf("unlimited admission: %v", err)
}
if release == nil {
t.Fatal("unlimited admission returned nil release")
}
release()
release()
})
}
}