95 lines
1.6 KiB
Go
95 lines
1.6 KiB
Go
|
|
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")
|
||
|
|
}
|
||
|
|
}
|