fix race in test setup/teardown

not easily triggered, but it happened just now on a build server.
This commit is contained in:
Mechiel Lukkien 2023-08-07 23:14:31 +02:00
parent 849b4ec9e9
commit 49cf16d3f2
No known key found for this signature in database
15 changed files with 29 additions and 36 deletions

View file

@ -38,8 +38,7 @@ func TestCtl(t *testing.T) {
if errs := mox.LoadConfig(ctxbg, true, false); len(errs) > 0 {
t.Fatalf("loading mox config: %v", errs)
}
switchDone := store.Switchboard()
defer close(switchDone)
defer store.Switchboard()()
xlog := mlog.New("ctl")

View file

@ -71,8 +71,7 @@ func FuzzServer(f *testing.F) {
if err != nil {
f.Fatalf("set password: %v", err)
}
done := store.Switchboard()
defer close(done)
defer store.Switchboard()()
comm := store.RegisterComm(acc)
defer comm.Unregister()

View file

@ -346,11 +346,9 @@ func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS bool) *testconn
err = acc.SetPassword("testtest")
tcheck(t, err, "set password")
}
var switchDone chan struct{}
switchStop := func() {}
if first {
switchDone = store.Switchboard()
} else {
switchDone = make(chan struct{}) // Dummy, that can be closed.
switchStop = store.Switchboard()
}
serverConn, clientConn := net.Pipe()
@ -368,7 +366,7 @@ func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS bool) *testconn
cid := connCounter
go func() {
serve("test", cid, tlsConfig, serverConn, isTLS, allowLoginWithoutTLS)
close(switchDone)
switchStop()
close(done)
}()
client, err := imapclient.New(clientConn, true)

View file

@ -118,8 +118,7 @@ func xcmdXImport(mbox bool, c *cmd) {
mox.Conf.Dynamic.Accounts = map[string]config.Account{
account: {},
}
switchDone := store.Switchboard()
defer close(switchDone)
defer store.Switchboard()()
xlog := mlog.New("import")
cconn, sconn := net.Pipe()

View file

@ -45,14 +45,14 @@ func setup(t *testing.T) (*store.Account, func()) {
tcheck(t, err, "open account")
err = acc.SetPassword("testtest")
tcheck(t, err, "set password")
switchDone := store.Switchboard()
switchStop := store.Switchboard()
mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
return acc, func() {
acc.Close()
mox.ShutdownCancel()
mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
Shutdown()
close(switchDone)
switchStop()
}
}

View file

@ -624,7 +624,8 @@ func start(mtastsdbRefresher, skipForkExec bool) error {
http.Serve()
go func() {
<-store.Switchboard()
store.Switchboard()
<-make(chan struct{})
}()
return nil
}

View file

@ -43,8 +43,7 @@ func FuzzServer(f *testing.F) {
if err != nil {
f.Fatalf("set password: %v", err)
}
done := store.Switchboard()
defer close(done)
defer store.Switchboard()()
err = queue.Init()
if err != nil {
f.Fatalf("queue init: %v", err)

View file

@ -75,7 +75,7 @@ test email
type testserver struct {
t *testing.T
acc *store.Account
switchDone chan struct{}
switchStop func()
comm *store.Comm
cid int64
resolver dns.Resolver
@ -101,7 +101,7 @@ func newTestServer(t *testing.T, configPath string, resolver dns.Resolver) *test
tcheck(t, err, "open account")
err = ts.acc.SetPassword("testtest")
tcheck(t, err, "set password")
ts.switchDone = store.Switchboard()
ts.switchStop = store.Switchboard()
err = queue.Init()
tcheck(t, err, "queue init")
@ -116,7 +116,7 @@ func (ts *testserver) close() {
}
ts.comm.Unregister()
queue.Shutdown()
close(ts.switchDone)
ts.switchStop()
err := ts.acc.Close()
tcheck(ts.t, err, "closing account")
ts.acc = nil

View file

@ -36,8 +36,7 @@ func TestMailbox(t *testing.T) {
err = acc.Close()
tcheck(t, err, "closing account")
}()
switchDone := Switchboard()
defer close(switchDone)
defer Switchboard()()
log := mlog.New("store")

View file

@ -25,8 +25,7 @@ func TestExport(t *testing.T) {
acc, err := OpenAccount("mjl")
tcheck(t, err, "open account")
defer acc.Close()
switchDone := Switchboard()
defer close(switchDone)
defer Switchboard()()
log := mlog.New("export")

View file

@ -101,7 +101,7 @@ type ChangeMailboxKeywords struct {
var switchboardBusy atomic.Bool
// Switchboard distributes changes to accounts to interested listeners. See Comm and Change.
func Switchboard() chan struct{} {
func Switchboard() (stop func()) {
regs := map[*Account]map[*Comm]struct{}{}
done := make(chan struct{})
@ -145,14 +145,18 @@ func Switchboard() chan struct{} {
chReq.done <- struct{}{}
case <-done:
if !switchboardBusy.CompareAndSwap(true, false) {
panic("switchboard already unregistered?")
}
done <- struct{}{}
return
}
}
}()
return done
return func() {
done <- struct{}{}
<-done
if !switchboardBusy.CompareAndSwap(true, false) {
panic("switchboard already unregistered?")
}
}
}
// Comm handles communication with the goroutine that maintains the

View file

@ -46,8 +46,7 @@ func TestAccount(t *testing.T) {
err = acc.Close()
tcheck(t, err, "closing account")
}()
switchDone := store.Switchboard()
defer close(switchDone)
defer store.Switchboard()()
log := mlog.New("store")

View file

@ -45,8 +45,7 @@ func TestAPI(t *testing.T) {
mox.Context = ctxbg
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
mox.MustLoadConfig(true, false)
switchDone := store.Switchboard()
defer close(switchDone)
defer store.Switchboard()()
acc, err := store.OpenAccount("mjl")
tcheck(t, err, "open account")

View file

@ -25,8 +25,7 @@ func TestView(t *testing.T) {
mox.Context = ctxbg
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
mox.MustLoadConfig(true, false)
switchDone := store.Switchboard()
defer close(switchDone)
defer store.Switchboard()()
acc, err := store.OpenAccount("mjl")
tcheck(t, err, "open account")

View file

@ -266,8 +266,7 @@ func TestWebmail(t *testing.T) {
mox.Context = ctxbg
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
mox.MustLoadConfig(true, false)
switchDone := store.Switchboard()
defer close(switchDone)
defer store.Switchboard()()
acc, err := store.OpenAccount("mjl")
tcheck(t, err, "open account")