package ultrabeam import ( "bufio" "bytes" "net" "testing" ) // A stale reply left in the stream by an earlier timed-out command must be // DRAINED, not taken for this command's reply. Without seq matching, a STATUS // query would return a lingering READ_BANDS/PROGRESS payload — which showed up // on a remote link as phantom frequencies (a spurious follow-loop re-tune) and // dropped connections. func TestSendCommandDrainsStaleReplyAndMatchesSeq(t *testing.T) { srvConn, cliConn := net.Pipe() defer srvConn.Close() defer cliConn.Close() c := &Client{conn: cliConn, reader: bufio.NewReader(cliConn)} srv := &Client{reader: bufio.NewReader(srvConn)} errc := make(chan error, 1) go func() { // Read the request, learn its seq, then answer with a stale reply (wrong // seq) FIRST, then the real one. req, err := srv.readPacket() if err != nil { errc <- err return } seq, _, _, err := parsePacket(req) if err != nil { errc <- err return } staleSeq := (seq + 1) % 128 if _, err := srvConn.Write(c.buildPacket(staleSeq, UB_OK, []byte{0xAA, 0xBB})); err != nil { errc <- err return } if _, err := srvConn.Write(c.buildPacket(seq, UB_OK, []byte{0x11, 0x22, 0x33})); err != nil { errc <- err return } errc <- nil }() payload, err := c.sendCommand(CMD_STATUS, nil) if err != nil { t.Fatalf("sendCommand: %v", err) } if !bytes.Equal(payload, []byte{0x11, 0x22, 0x33}) { t.Fatalf("payload = % X, want 11 22 33 — stale reply not drained or seq not matched", payload) } if err := <-errc; err != nil { t.Fatalf("server: %v", err) } } // readPacket must resynchronise to the next STX, dropping any partial/garbage // bytes left in the stream, so one corrupt frame can't misalign every frame // after it. func TestReadPacketResyncsToSTX(t *testing.T) { frame := (&Client{}).buildPacket(5, UB_OK, []byte{0x01, 0x02}) stream := append([]byte{0x11, 0x22, 0x33}, frame...) // leading garbage, then a real frame c := &Client{reader: bufio.NewReader(bytes.NewReader(stream))} got, err := c.readPacket() if err != nil { t.Fatalf("readPacket: %v", err) } seq, cmd, payload, err := parsePacket(got) if err != nil { t.Fatalf("parsePacket: %v", err) } if seq != 5 || cmd != UB_OK || !bytes.Equal(payload, []byte{0x01, 0x02}) { t.Fatalf("seq=%d cmd=%d payload=% X, want 5 / OK / 01 02", seq, cmd, payload) } }