package spindle

import (
	"testing"
	"time"

	"github.com/bluesky-social/indigo/atproto/syntax"
)

func TestRepoLockIsFreeAfterTheWorkUnderItPanicked(t *testing.T) {
	var locks stripedLocks
	d := syntax.DID("did:plc:panics")
	func() {
		defer func() { _ = recover() }()
		defer locks.lock(d).Unlock()
		panic("boom")
	}()

	done := goErr(func() error {
		locks.lock(d).Unlock()
		return nil
	})
	waitErr(t, done, time.Second, "the lock stayed held after the work under it panicked")
}

func TestRepoLockCostsNoAllocation(t *testing.T) {
	var locks stripedLocks
	d := syntax.DID("did:plc:warm")
	if allocs := testing.AllocsPerRun(1000, func() { locks.lock(d).Unlock() }); allocs != 0 {
		t.Fatalf("%.2f allocations per lock and unlock, want none", allocs)
	}
}

func BenchmarkRepoLock(b *testing.B) {
	var locks stripedLocks
	d := syntax.DID("did:plc:bench")
	b.ReportAllocs()
	for b.Loop() {
		locks.lock(d).Unlock()
	}
}
