Files
EvoBGP/internal/store/memory_snapshot_lock_test.go
DenozordecandCursor f8e0520817 feat(httpapi): harden control plane and speed up prefix refresh
Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-02 17:23:59 +07:00

60 lines
1.8 KiB
Go

package store
import (
"context"
"errors"
"testing"
"time"
)
func TestMemoryModuleSnapshotLockCancellationAndCleanup(t *testing.T) {
m := NewMemory()
first, err := m.lockModuleSnapshot(context.Background(), "tenant-a", "module-a")
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Millisecond)
defer cancel()
second, err := m.lockModuleSnapshot(ctx, "tenant-a", "module-a")
if second != nil || !errors.Is(err, context.DeadlineExceeded) {
t.Fatalf("waiter not cancelled: unlock=%v err=%v", second != nil, err)
}
if len(m.snapshotLocks) != 1 || m.snapshotLocks[moduleSnapshotKey("tenant-a", "module-a")].refs != 1 {
t.Fatalf("waiter leaked lock ref: %+v", m.snapshotLocks)
}
first()
first()
if len(m.snapshotLocks) != 0 {
t.Fatalf("idle lock leaked: %+v", m.snapshotLocks)
}
third, err := m.lockModuleSnapshot(context.Background(), "tenant-a", "module-a")
if err != nil {
t.Fatal(err)
}
third()
}
func TestMemoryModuleSnapshotLockScopesTenantAndModule(t *testing.T) {
m := NewMemory()
first, err := m.lockModuleSnapshot(context.Background(), "tenant-a", "module-x")
if err != nil {
t.Fatal(err)
}
defer first()
for _, pair := range [][2]string{{"tenant-b", "module-x"}, {"tenant-a", "module-y"}} {
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
unlock, err := m.lockModuleSnapshot(ctx, pair[0], pair[1])
cancel()
if err != nil {
t.Fatalf("unrelated key blocked %v: %v", pair, err)
}
unlock()
}
ctx, cancel := context.WithCancel(context.Background())
cancel()
unlock, err := m.lockModuleSnapshot(ctx, "tenant-a", "module-x")
if unlock != nil || !errors.Is(err, context.Canceled) {
t.Fatalf("cancelled context acquired: unlock=%v err=%v", unlock != nil, err)
}
}