blob: 1ccd25ff9c772e14daab84a3e589f2020094d48d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
package game
// Single-owner serialization regressions: a full task queue applies
// backpressure instead of bypassing the owner, and the owner-stop path
// keeps its documented inline fallback for shutdown stragglers only.
import (
"sync"
"testing"
"time"
)
// TestFullOwnerQueueAppliesBackpressure: when the owner's task queue is
// full and the owner is blocked inside another task, run() must NOT execute
// the new task inline on the caller's goroutine — that would mutate live
// state concurrently with the owner. It blocks until the owner drains.
func TestFullOwnerQueueAppliesBackpressure(t *testing.T) {
g := &Game{owner: newOwner()}
release := make(chan struct{})
started := make(chan struct{})
g.owner.submit(func() {
close(started)
<-release
})
<-started
var once sync.Once
t.Cleanup(func() {
once.Do(func() { close(release) })
g.stopOwner()
})
for i := 0; i < ownerTaskQueue; i++ {
if !g.owner.submit(func() {}) {
t.Fatal("setup: could not fill the owner queue")
}
}
ran := make(chan struct{})
go g.run(func() { close(ran) })
select {
case <-ran:
t.Fatal("task executed inline while the owner was still running other tasks")
case <-time.After(100 * time.Millisecond):
}
// Release the owner: the queued work drains and the blocked task runs.
once.Do(func() { close(release) })
select {
case <-ran:
case <-time.After(5 * time.Second):
t.Fatal("task never ran after the owner drained its queue")
}
}
// TestStoppedOwnerRunsStragglersInline: after the owner stops (graceful
// shutdown), straggler submissions execute inline rather than blocking
// forever — the documented admissions-closed behavior.
func TestStoppedOwnerRunsStragglersInline(t *testing.T) {
g := &Game{owner: newOwner()}
g.stopOwner()
ran := make(chan struct{})
go g.run(func() { close(ran) })
select {
case <-ran:
case <-time.After(5 * time.Second):
t.Fatal("straggler task blocked forever after the owner stopped")
}
}
|