package tracker import ( "sync" "testing" "github.com/emersion/go-imap/v2" ) func TestNew(t *testing.T) { tr := New() if tr == nil { t.Fatal("New() returned nil") } if tr.ids == nil { t.Fatal("New() initialized with nil map") } } func TestLifecycle(t *testing.T) { tr := New() uid := imap.UID(123) // 1. First acquire should succeed. if !tr.TryAcquire(uid) { t.Fatalf( "expected TryAcquire(%d) to return true, got false", uid, ) } // 2. Second acquire on same UID should fail. if tr.TryAcquire(uid) { t.Fatalf( "expected TryAcquire(%d) to return false when already held, got true", uid, ) } // 3. Different UID should succeed. otherUID := imap.UID(456) if !tr.TryAcquire(otherUID) { t.Fatalf( "expected TryAcquire(%d) to return true, got false", otherUID, ) } // 4. Release first UID. tr.Release(uid) // 5. First UID should be acquirable again. if !tr.TryAcquire(uid) { t.Fatalf( "expected TryAcquire(%d) to return true after Release, got false", uid, ) } } func TestConcurrency(t *testing.T) { tr := New() uid := imap.UID(1) routines := 16 var wg sync.WaitGroup // Counter for successful acquisitions. successCount := 0 var mu sync.Mutex for range routines { wg.Go(func() { if tr.TryAcquire(uid) { mu.Lock() successCount++ mu.Unlock() } }) } wg.Wait() if successCount != 1 { t.Errorf( "expected exactly 1 successful acquisition for concurrent access to same UID, got %d", successCount, ) } // Verify we can release safely after concurrent hammer. tr.Release(uid) if !tr.TryAcquire(uid) { t.Error("failed to acquire UID after concurrent test release") } }