101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
package tunergenius
|
|
|
|
import (
|
|
"bufio"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// captureLog redirects the stream applog.Printf always writes to, and returns a
|
|
// stop function yielding what was logged. Reading only after stop keeps the
|
|
// collector goroutine and the test off the same slice.
|
|
func captureLog() func() []string {
|
|
orig := os.Stderr
|
|
r, w, _ := os.Pipe()
|
|
os.Stderr = w
|
|
var lines []string
|
|
done := make(chan struct{})
|
|
go func() {
|
|
sc := bufio.NewScanner(r)
|
|
for sc.Scan() {
|
|
lines = append(lines, sc.Text())
|
|
}
|
|
close(done)
|
|
}()
|
|
return func() []string {
|
|
os.Stderr = orig
|
|
w.Close()
|
|
<-done
|
|
r.Close()
|
|
return lines
|
|
}
|
|
}
|
|
|
|
// A tuner that answers, then vanishes mid-session. A drop used to leave no trace
|
|
// at all, so "did the tuner disconnect, or is the meter just reading a gap
|
|
// between syllables?" was unanswerable from the log. It must now log — and log
|
|
// ONCE, not on every 400 ms retry.
|
|
func TestLinkDownLoggedOnceNotPerRetry(t *testing.T) {
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
port := ln.Addr().(*net.TCPAddr).Port
|
|
|
|
die := make(chan struct{})
|
|
go func() {
|
|
conn, err := ln.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
conn.Write([]byte("V1.2.11\n"))
|
|
buf := make([]byte, 256)
|
|
for {
|
|
n, err := conn.Read(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
id := strings.TrimPrefix(strings.SplitN(string(buf[:n]), "|", 2)[0], "C")
|
|
conn.Write([]byte("R" + id + "|0|status state=1 fwd=60.7 swr=-25 active=1\n"))
|
|
select {
|
|
case <-die:
|
|
conn.Close()
|
|
ln.Close()
|
|
return
|
|
default:
|
|
}
|
|
}
|
|
}()
|
|
|
|
stop := captureLog()
|
|
c := New("127.0.0.1", port, "")
|
|
if err := c.Start(); err != nil {
|
|
stop()
|
|
t.Fatal(err)
|
|
}
|
|
|
|
time.Sleep(1200 * time.Millisecond)
|
|
connected := c.GetStatus().Connected
|
|
close(die)
|
|
time.Sleep(2 * time.Second) // ~5 poll cycles with the tuner gone
|
|
c.Stop()
|
|
lines := stop()
|
|
|
|
if !connected {
|
|
t.Fatal("the client never reached the fake tuner — the rest of the test is meaningless")
|
|
}
|
|
down := 0
|
|
for _, l := range lines {
|
|
if strings.Contains(l, "link DOWN") {
|
|
down++
|
|
}
|
|
}
|
|
t.Logf("logged:\n%s", strings.Join(lines, "\n"))
|
|
if down != 1 {
|
|
t.Errorf("got %d 'link DOWN' lines, want exactly 1 — the poll retries many times in a 3 s outage and must not repeat itself", down)
|
|
}
|
|
}
|