Files
mesh-sdk/go/bus_waits_for_serve_test.go
T

75 lines
2.2 KiB
Go

package stdio
import (
"io"
"testing"
"time"
)
// A bus function called before Serve waits for Serve and proceeds (issue 1966): a module that starts a goroutine
// before stdio.Serve and calls the bus there is no longer refused. It is refused only when the process never serves.
// The test drives the wait itself: serveWait is the test's own timer channel, no row sleeps on a clock.
func TestBusFunctionsWaitForServe(t *testing.T) {
const refusal = "before Serve: a bundle reaches the bus through the runtime that launched it"
for _, tc := range []struct {
name string
serve string // "first": before the call; "during": while the call waits; "never"
wantOK bool
}{
{"a call before Serve completes after Serve", "during", true},
{"a call whose wait ends before Serve is refused", "never", false},
{"a call after Serve is as before", "first", true},
} {
t.Run(tc.name, func(t *testing.T) {
servesAlone(t)
expire := make(chan time.Time)
oldAfter := serveTimer
serveTimer = func() (<-chan time.Time, func()) { return expire, func() {} }
t.Cleanup(func() { serveTimer = oldAfter })
inR, inW := io.Pipe()
outR, outW := io.Pipe()
stopped := make(chan struct{})
serve := func() {
go func() { _ = ServeOn("m", nil, inR, outW); close(stopped) }()
}
t.Cleanup(func() { _ = inW.Close(); go func() { _, _ = io.Copy(io.Discard, outR) }() })
type result struct {
c *channel
err error
}
done := make(chan result, 1)
if tc.serve == "first" {
serve()
<-Served()
c, err := live()
done <- result{c, err}
} else {
go func() { c, err := live(); done <- result{c, err} }()
select {
case r := <-done:
t.Fatalf("live() returned before Serve and before its wait ended: %v", r.err)
default:
}
if tc.serve == "during" {
serve()
} else {
expire <- time.Time{}
}
}
r := <-done
if tc.wantOK != (r.err == nil && r.c != nil) {
t.Fatalf("live() = %v, %v; want ok=%v", r.c, r.err, tc.wantOK)
}
if !tc.wantOK && r.err.Error() != refusal {
t.Fatalf("refusal words changed: %v", r.err)
}
if tc.serve != "never" {
_ = inW.Close()
<-stopped
}
})
}
}