Files
funknetz/station/lab_reflector_test.go

82 lines
2.0 KiB
Go

package station_test
import (
"context"
"errors"
"net"
"os"
"strconv"
"syscall"
"testing"
"time"
"gitea.neitzel.de/konrad/funknetz/station"
)
// Lab defaults match svxlink-docker/.env and config/svxreflector.conf.
const (
labHost = "127.0.0.1"
labPort = 5300
labCallsign = "DL0FN-1"
labAuthKey = "local-lab-secret-change-me"
labTalkGroup = 9
)
func TestConnectsToLabReflector(t *testing.T) {
if os.Getenv("FUNKNETZ_LAB") == "0" {
t.Skip("FUNKNETZ_LAB=0")
}
addr := net.JoinHostPort(labHost, strconv.Itoa(labPort))
conn, err := net.DialTimeout("tcp", addr, 500*time.Millisecond)
if err != nil {
t.Skipf("lab reflector not listening on %s: %v", addr, err)
}
conn.Close()
if !labUDPReachable() {
t.Skipf("lab UDP port %s is not reachable", addr)
}
path := writeConfigFile(t, configJSON(t, labHost, labPort, labCallsign, labAuthKey, labTalkGroup))
st, err := station.New(station.Options{ConfigPath: path})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second)
defer cancel()
go func() {
// Run's error is observed through State, which is the station seam.
_ = st.Run(ctx)
}()
state, err := st.Wait(ctx, func(s station.State) bool {
return s.Connection == "Connected"
})
if err != nil {
t.Fatalf("did not reach Connected: %v (last state %#v)", err, st.State())
}
if state.Callsign != labCallsign {
t.Fatalf("callsign = %q, want %q", state.Callsign, labCallsign)
}
if state.TalkGroup != labTalkGroup {
t.Fatalf("talkGroup = %d, want %d", state.TalkGroup, labTalkGroup)
}
}
func labUDPReachable() bool {
peer := &net.UDPAddr{IP: net.ParseIP(labHost), Port: labPort}
conn, err := net.DialUDP("udp", nil, peer)
if err != nil {
return false
}
defer conn.Close()
_, _ = conn.Write([]byte{0})
_ = conn.SetReadDeadline(time.Now().Add(200 * time.Millisecond))
_, err = conn.Read(make([]byte, 1))
if err == nil {
return true
}
var op *net.OpError
return !errors.As(err, &op) || !errors.Is(op.Err, syscall.ECONNREFUSED)
}