42 lines
859 B
Go
42 lines
859 B
Go
package serve
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"reasonix/internal/control"
|
|
)
|
|
|
|
// TestControllerAccessorIsRaceSafe guards the switchModel concurrency contract:
|
|
// handlers read the controller through ctl() while a swap runs under the write
|
|
// lock. With the lock removed this fails under `go test -race` (the CI race job).
|
|
func TestControllerAccessorIsRaceSafe(t *testing.T) {
|
|
a, b := &control.Controller{}, &control.Controller{}
|
|
s := &Server{ctrl: a}
|
|
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 64; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
if got := s.ctl(); got != a && got != b {
|
|
t.Errorf("ctl() returned a pointer that was never set")
|
|
}
|
|
}()
|
|
}
|
|
for i := 0; i < 16; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
s.mu.Lock()
|
|
if s.ctrl == a {
|
|
s.ctrl = b
|
|
} else {
|
|
s.ctrl = a
|
|
}
|
|
s.mu.Unlock()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
}
|