mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 00:37:36 +00:00
133 lines
3.6 KiB
Go
133 lines
3.6 KiB
Go
package deploy
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestReserveAndRelease(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
|
|
if err := rm.Reserve("j1", "org-1", 3, 30*time.Minute); err != nil {
|
|
t.Fatalf("Reserve: %v", err)
|
|
}
|
|
if got := rm.ReservedForOrg("org-1"); got != 3 {
|
|
t.Errorf("expected 3 reserved, got %d", got)
|
|
}
|
|
|
|
rm.Release("j1")
|
|
if got := rm.ReservedForOrg("org-1"); got != 0 {
|
|
t.Errorf("expected 0 after release, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestReserveDuplicate(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
_ = rm.Reserve("j1", "org-1", 2, 30*time.Minute)
|
|
|
|
if err := rm.Reserve("j1", "org-1", 1, 30*time.Minute); err == nil {
|
|
t.Fatal("expected error for duplicate reservation")
|
|
}
|
|
}
|
|
|
|
func TestReserveInvalidSlots(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
if err := rm.Reserve("j1", "org-1", 0, 30*time.Minute); err == nil {
|
|
t.Fatal("expected error for zero slots")
|
|
}
|
|
if err := rm.Reserve("j2", "org-1", -1, 30*time.Minute); err == nil {
|
|
t.Fatal("expected error for negative slots")
|
|
}
|
|
}
|
|
|
|
func TestMultiOrgIsolation(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
_ = rm.Reserve("j1", "org-1", 3, 30*time.Minute)
|
|
_ = rm.Reserve("j2", "org-2", 5, 30*time.Minute)
|
|
|
|
if got := rm.ReservedForOrg("org-1"); got != 3 {
|
|
t.Errorf("expected 3 for org-1, got %d", got)
|
|
}
|
|
if got := rm.ReservedForOrg("org-2"); got != 5 {
|
|
t.Errorf("expected 5 for org-2, got %d", got)
|
|
}
|
|
if got := rm.ReservedForOrg("org-3"); got != 0 {
|
|
t.Errorf("expected 0 for unknown org, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestMultipleReservationsSameOrg(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
_ = rm.Reserve("j1", "org-1", 2, 30*time.Minute)
|
|
_ = rm.Reserve("j2", "org-1", 3, 30*time.Minute)
|
|
|
|
if got := rm.ReservedForOrg("org-1"); got != 5 {
|
|
t.Errorf("expected 5 total, got %d", got)
|
|
}
|
|
|
|
rm.Release("j1")
|
|
if got := rm.ReservedForOrg("org-1"); got != 3 {
|
|
t.Errorf("expected 3 after partial release, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestReserveInvalidTTL(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
if err := rm.Reserve("j1", "org-1", 3, 0); err == nil {
|
|
t.Fatal("expected error for zero TTL")
|
|
}
|
|
if err := rm.Reserve("j2", "org-1", 3, -1*time.Second); err == nil {
|
|
t.Fatal("expected error for negative TTL")
|
|
}
|
|
}
|
|
|
|
func TestTTLExpiry(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
|
|
// Directly inject an already-expired reservation to test expiry counting.
|
|
rm.mu.Lock()
|
|
rm.reservations["j1"] = &Reservation{
|
|
JobID: "j1", OrgID: "org-1", Slots: 3,
|
|
CreatedAt: time.Now().UTC().Add(-2 * time.Minute),
|
|
ExpiresAt: time.Now().UTC().Add(-1 * time.Minute),
|
|
}
|
|
rm.mu.Unlock()
|
|
|
|
// Expired reservations should not be counted.
|
|
if got := rm.ReservedForOrg("org-1"); got != 0 {
|
|
t.Errorf("expected 0 for expired reservation, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestCleanExpired(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
|
|
// Directly inject an already-expired reservation.
|
|
rm.mu.Lock()
|
|
rm.reservations["j1"] = &Reservation{
|
|
JobID: "j1", OrgID: "org-1", Slots: 2,
|
|
CreatedAt: time.Now().UTC().Add(-2 * time.Minute),
|
|
ExpiresAt: time.Now().UTC().Add(-1 * time.Minute),
|
|
}
|
|
rm.mu.Unlock()
|
|
|
|
_ = rm.Reserve("j2", "org-1", 3, 30*time.Minute) // still valid
|
|
|
|
rm.CleanExpired()
|
|
|
|
// j1 should be cleaned up, only j2 remains.
|
|
if got := rm.ReservedForOrg("org-1"); got != 3 {
|
|
t.Errorf("expected 3 after cleanup, got %d", got)
|
|
}
|
|
|
|
// Verify j1 was actually removed (can re-reserve that ID).
|
|
if err := rm.Reserve("j1", "org-1", 1, 30*time.Minute); err != nil {
|
|
t.Errorf("expected to re-reserve cleaned-up job, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestReleaseNonexistent(t *testing.T) {
|
|
rm := NewReservationManager()
|
|
// Should not panic.
|
|
rm.Release("nonexistent")
|
|
}
|