package internal_test import ( "context" "fmt" "net" "strings" "sync" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tildegit.org/tjp/sliderule/internal" ) type captureLogger struct { mu sync.Mutex logs []string } func (cl *captureLogger) Log(keyvals ...any) error { cl.mu.Lock() defer cl.mu.Unlock() for _, val := range keyvals { cl.logs = append(cl.logs, fmt.Sprint(val)) } return nil } func (cl *captureLogger) String() string { cl.mu.Lock() defer cl.mu.Unlock() return strings.Join(cl.logs, " ") } func TestServerRecoversConnectionPanic(t *testing.T) { var logs captureLogger server, err := internal.NewServer( context.Background(), "localhost", "tcp", "127.0.0.1:0", &logs, func(net.Conn) { panic("boom") }, ) require.Nil(t, err) done := make(chan error, 1) go func() { done <- server.Serve() }() conn, err := net.Dial(server.Network(), server.Address()) require.Nil(t, err) _ = conn.Close() require.Eventually(t, func() bool { return strings.Contains(logs.String(), "panic in server goroutine") }, time.Second, 10*time.Millisecond) server.Close() assert.Nil(t, <-done) assert.Contains(t, logs.String(), "boom") }