mirror of
https://github.com/mjl-/mox.git
synced 2024-12-27 08:53:48 +03:00
fix race in test setup/teardown
not easily triggered, but it happened just now on a build server.
This commit is contained in:
parent
849b4ec9e9
commit
49cf16d3f2
15 changed files with 29 additions and 36 deletions
|
@ -38,8 +38,7 @@ func TestCtl(t *testing.T) {
|
||||||
if errs := mox.LoadConfig(ctxbg, true, false); len(errs) > 0 {
|
if errs := mox.LoadConfig(ctxbg, true, false); len(errs) > 0 {
|
||||||
t.Fatalf("loading mox config: %v", errs)
|
t.Fatalf("loading mox config: %v", errs)
|
||||||
}
|
}
|
||||||
switchDone := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
xlog := mlog.New("ctl")
|
xlog := mlog.New("ctl")
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,7 @@ func FuzzServer(f *testing.F) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Fatalf("set password: %v", err)
|
f.Fatalf("set password: %v", err)
|
||||||
}
|
}
|
||||||
done := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(done)
|
|
||||||
|
|
||||||
comm := store.RegisterComm(acc)
|
comm := store.RegisterComm(acc)
|
||||||
defer comm.Unregister()
|
defer comm.Unregister()
|
||||||
|
|
|
@ -346,11 +346,9 @@ func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS bool) *testconn
|
||||||
err = acc.SetPassword("testtest")
|
err = acc.SetPassword("testtest")
|
||||||
tcheck(t, err, "set password")
|
tcheck(t, err, "set password")
|
||||||
}
|
}
|
||||||
var switchDone chan struct{}
|
switchStop := func() {}
|
||||||
if first {
|
if first {
|
||||||
switchDone = store.Switchboard()
|
switchStop = store.Switchboard()
|
||||||
} else {
|
|
||||||
switchDone = make(chan struct{}) // Dummy, that can be closed.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serverConn, clientConn := net.Pipe()
|
serverConn, clientConn := net.Pipe()
|
||||||
|
@ -368,7 +366,7 @@ func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS bool) *testconn
|
||||||
cid := connCounter
|
cid := connCounter
|
||||||
go func() {
|
go func() {
|
||||||
serve("test", cid, tlsConfig, serverConn, isTLS, allowLoginWithoutTLS)
|
serve("test", cid, tlsConfig, serverConn, isTLS, allowLoginWithoutTLS)
|
||||||
close(switchDone)
|
switchStop()
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
client, err := imapclient.New(clientConn, true)
|
client, err := imapclient.New(clientConn, true)
|
||||||
|
|
|
@ -118,8 +118,7 @@ func xcmdXImport(mbox bool, c *cmd) {
|
||||||
mox.Conf.Dynamic.Accounts = map[string]config.Account{
|
mox.Conf.Dynamic.Accounts = map[string]config.Account{
|
||||||
account: {},
|
account: {},
|
||||||
}
|
}
|
||||||
switchDone := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
xlog := mlog.New("import")
|
xlog := mlog.New("import")
|
||||||
cconn, sconn := net.Pipe()
|
cconn, sconn := net.Pipe()
|
||||||
|
|
|
@ -45,14 +45,14 @@ func setup(t *testing.T) (*store.Account, func()) {
|
||||||
tcheck(t, err, "open account")
|
tcheck(t, err, "open account")
|
||||||
err = acc.SetPassword("testtest")
|
err = acc.SetPassword("testtest")
|
||||||
tcheck(t, err, "set password")
|
tcheck(t, err, "set password")
|
||||||
switchDone := store.Switchboard()
|
switchStop := store.Switchboard()
|
||||||
mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
|
mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
|
||||||
return acc, func() {
|
return acc, func() {
|
||||||
acc.Close()
|
acc.Close()
|
||||||
mox.ShutdownCancel()
|
mox.ShutdownCancel()
|
||||||
mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
|
mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
|
||||||
Shutdown()
|
Shutdown()
|
||||||
close(switchDone)
|
switchStop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
serve.go
3
serve.go
|
@ -624,7 +624,8 @@ func start(mtastsdbRefresher, skipForkExec bool) error {
|
||||||
http.Serve()
|
http.Serve()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-store.Switchboard()
|
store.Switchboard()
|
||||||
|
<-make(chan struct{})
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,7 @@ func FuzzServer(f *testing.F) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Fatalf("set password: %v", err)
|
f.Fatalf("set password: %v", err)
|
||||||
}
|
}
|
||||||
done := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(done)
|
|
||||||
err = queue.Init()
|
err = queue.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Fatalf("queue init: %v", err)
|
f.Fatalf("queue init: %v", err)
|
||||||
|
|
|
@ -75,7 +75,7 @@ test email
|
||||||
type testserver struct {
|
type testserver struct {
|
||||||
t *testing.T
|
t *testing.T
|
||||||
acc *store.Account
|
acc *store.Account
|
||||||
switchDone chan struct{}
|
switchStop func()
|
||||||
comm *store.Comm
|
comm *store.Comm
|
||||||
cid int64
|
cid int64
|
||||||
resolver dns.Resolver
|
resolver dns.Resolver
|
||||||
|
@ -101,7 +101,7 @@ func newTestServer(t *testing.T, configPath string, resolver dns.Resolver) *test
|
||||||
tcheck(t, err, "open account")
|
tcheck(t, err, "open account")
|
||||||
err = ts.acc.SetPassword("testtest")
|
err = ts.acc.SetPassword("testtest")
|
||||||
tcheck(t, err, "set password")
|
tcheck(t, err, "set password")
|
||||||
ts.switchDone = store.Switchboard()
|
ts.switchStop = store.Switchboard()
|
||||||
err = queue.Init()
|
err = queue.Init()
|
||||||
tcheck(t, err, "queue init")
|
tcheck(t, err, "queue init")
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ func (ts *testserver) close() {
|
||||||
}
|
}
|
||||||
ts.comm.Unregister()
|
ts.comm.Unregister()
|
||||||
queue.Shutdown()
|
queue.Shutdown()
|
||||||
close(ts.switchDone)
|
ts.switchStop()
|
||||||
err := ts.acc.Close()
|
err := ts.acc.Close()
|
||||||
tcheck(ts.t, err, "closing account")
|
tcheck(ts.t, err, "closing account")
|
||||||
ts.acc = nil
|
ts.acc = nil
|
||||||
|
|
|
@ -36,8 +36,7 @@ func TestMailbox(t *testing.T) {
|
||||||
err = acc.Close()
|
err = acc.Close()
|
||||||
tcheck(t, err, "closing account")
|
tcheck(t, err, "closing account")
|
||||||
}()
|
}()
|
||||||
switchDone := Switchboard()
|
defer Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
log := mlog.New("store")
|
log := mlog.New("store")
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,7 @@ func TestExport(t *testing.T) {
|
||||||
acc, err := OpenAccount("mjl")
|
acc, err := OpenAccount("mjl")
|
||||||
tcheck(t, err, "open account")
|
tcheck(t, err, "open account")
|
||||||
defer acc.Close()
|
defer acc.Close()
|
||||||
switchDone := Switchboard()
|
defer Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
log := mlog.New("export")
|
log := mlog.New("export")
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ type ChangeMailboxKeywords struct {
|
||||||
var switchboardBusy atomic.Bool
|
var switchboardBusy atomic.Bool
|
||||||
|
|
||||||
// Switchboard distributes changes to accounts to interested listeners. See Comm and Change.
|
// 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{}{}
|
regs := map[*Account]map[*Comm]struct{}{}
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
@ -145,14 +145,18 @@ func Switchboard() chan struct{} {
|
||||||
chReq.done <- struct{}{}
|
chReq.done <- struct{}{}
|
||||||
|
|
||||||
case <-done:
|
case <-done:
|
||||||
if !switchboardBusy.CompareAndSwap(true, false) {
|
done <- struct{}{}
|
||||||
panic("switchboard already unregistered?")
|
|
||||||
}
|
|
||||||
return
|
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
|
// Comm handles communication with the goroutine that maintains the
|
||||||
|
|
|
@ -46,8 +46,7 @@ func TestAccount(t *testing.T) {
|
||||||
err = acc.Close()
|
err = acc.Close()
|
||||||
tcheck(t, err, "closing account")
|
tcheck(t, err, "closing account")
|
||||||
}()
|
}()
|
||||||
switchDone := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
log := mlog.New("store")
|
log := mlog.New("store")
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,7 @@ func TestAPI(t *testing.T) {
|
||||||
mox.Context = ctxbg
|
mox.Context = ctxbg
|
||||||
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
|
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
|
||||||
mox.MustLoadConfig(true, false)
|
mox.MustLoadConfig(true, false)
|
||||||
switchDone := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
acc, err := store.OpenAccount("mjl")
|
acc, err := store.OpenAccount("mjl")
|
||||||
tcheck(t, err, "open account")
|
tcheck(t, err, "open account")
|
||||||
|
|
|
@ -25,8 +25,7 @@ func TestView(t *testing.T) {
|
||||||
mox.Context = ctxbg
|
mox.Context = ctxbg
|
||||||
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
|
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
|
||||||
mox.MustLoadConfig(true, false)
|
mox.MustLoadConfig(true, false)
|
||||||
switchDone := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
acc, err := store.OpenAccount("mjl")
|
acc, err := store.OpenAccount("mjl")
|
||||||
tcheck(t, err, "open account")
|
tcheck(t, err, "open account")
|
||||||
|
|
|
@ -266,8 +266,7 @@ func TestWebmail(t *testing.T) {
|
||||||
mox.Context = ctxbg
|
mox.Context = ctxbg
|
||||||
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
|
mox.ConfigStaticPath = "../testdata/webmail/mox.conf"
|
||||||
mox.MustLoadConfig(true, false)
|
mox.MustLoadConfig(true, false)
|
||||||
switchDone := store.Switchboard()
|
defer store.Switchboard()()
|
||||||
defer close(switchDone)
|
|
||||||
|
|
||||||
acc, err := store.OpenAccount("mjl")
|
acc, err := store.OpenAccount("mjl")
|
||||||
tcheck(t, err, "open account")
|
tcheck(t, err, "open account")
|
||||||
|
|
Loading…
Reference in a new issue