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() { _ = 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) }