test(locks): promotion under contention, demotion on idle
This commit is contained in:
parent
c248816aa5
commit
ce18f6430c
1 changed files with 63 additions and 0 deletions
63
locks_test.go
Normal file
63
locks_test.go
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestLockController_PromotesUnderContention — N goroutines hit the same
|
||||||
|
// author simultaneously. The controller should observe the queue depth and
|
||||||
|
// move the scope from Coarse to Medium.
|
||||||
|
func TestLockController_PromotesUnderContention(t *testing.T) {
|
||||||
|
s, _, _ := newTestStore(t)
|
||||||
|
cp := &CreatePost{AuthorID: "scott", Body: "lock test"}
|
||||||
|
must(t, Submit(context.Background(), s, cp))
|
||||||
|
|
||||||
|
const N = 80
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var ran atomic.Int64
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
m := &AddComment{PostID: cp.ResolvedPostID(), AuthorID: "hermes", Body: "y"}
|
||||||
|
if err := Submit(context.Background(), s, m); err == nil {
|
||||||
|
ran.Add(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
st := s.lockCtrl.getOrCreate("hermes")
|
||||||
|
// After 80 concurrent submissions, scope may have promoted. We don't
|
||||||
|
// assert the exact scope (depends on timing); we just assert no deadlock
|
||||||
|
// and all ran.
|
||||||
|
if ran.Load() != N {
|
||||||
|
t.Fatalf("expected %d to run, got %d", N, ran.Load())
|
||||||
|
}
|
||||||
|
t.Logf("final scope for hermes: %s (queueDepth=%d)", st.scope, st.queueDepth)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLockController_DemotesOnIdle — after a quiet period, scope should
|
||||||
|
// settle back to Coarse. Trigger Tick() manually to simulate the periodic
|
||||||
|
// controller.
|
||||||
|
func TestLockController_DemotesOnIdle(t *testing.T) {
|
||||||
|
s, _, _ := newTestStore(t)
|
||||||
|
cp := &CreatePost{AuthorID: "scott", Body: "demote test"}
|
||||||
|
must(t, Submit(context.Background(), s, cp))
|
||||||
|
|
||||||
|
// Manually set state to Fine, then tick to decay queue depth and demote.
|
||||||
|
st := s.lockCtrl.getOrCreate("hermes")
|
||||||
|
st.scope = ScopeFine
|
||||||
|
st.queueDepth = 5 // below fineToMediumBelow=100
|
||||||
|
st.belowSince = time.Now().Add(-time.Hour) // way past the demotion window
|
||||||
|
|
||||||
|
s.lockCtrl.Tick()
|
||||||
|
chosen := s.lockCtrl.chooseScope(st)
|
||||||
|
if chosen == ScopeFine {
|
||||||
|
t.Fatalf("expected demotion from Fine, still Fine")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue