120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
package cluster
|
|
|
|
import "testing"
|
|
|
|
func TestParseSpot(t *testing.T) {
|
|
cases := []struct {
|
|
line string
|
|
wantCall string
|
|
wantKHz float64
|
|
wantBand string
|
|
wantLoc string
|
|
}{
|
|
{
|
|
`DX de DK0SWL: 14195.5 W1AW CQ Field Day 1745Z`,
|
|
"W1AW", 14195.5, "20m", "",
|
|
},
|
|
{
|
|
`DX de F4XYZ-#: 7074.0 3DA0RU FT8 -10 0823Z JN18`,
|
|
"3DA0RU", 7074.0, "40m", "JN18",
|
|
},
|
|
{
|
|
`DX de N1MM: 14010.0 K1JT 599 NJ 1234Z FN20`,
|
|
"K1JT", 14010.0, "20m", "FN20",
|
|
},
|
|
{
|
|
`DX de YO3JW 3573.0 EA1ABC CQ 2010Z IN73`,
|
|
"EA1ABC", 3573.0, "80m", "IN73",
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
s, ok := parseSpot(c.line)
|
|
if !ok {
|
|
t.Errorf("%q: parse failed", c.line)
|
|
continue
|
|
}
|
|
if s.DXCall != c.wantCall {
|
|
t.Errorf("%q: call=%q want %q", c.line, s.DXCall, c.wantCall)
|
|
}
|
|
if s.FreqKHz != c.wantKHz {
|
|
t.Errorf("%q: kHz=%v want %v", c.line, s.FreqKHz, c.wantKHz)
|
|
}
|
|
if s.Band != c.wantBand {
|
|
t.Errorf("%q: band=%q want %q", c.line, s.Band, c.wantBand)
|
|
}
|
|
if s.Locator != c.wantLoc {
|
|
t.Errorf("%q: loc=%q want %q", c.line, s.Locator, c.wantLoc)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseSpotRejectsNoise(t *testing.T) {
|
|
noise := []string{
|
|
"Welcome to DXCluster",
|
|
"login:",
|
|
"WX bulletin from G4ABC: heavy rain",
|
|
"To ALL de F1XYZ: anyone using XYZ contest log?",
|
|
"",
|
|
"sh/dx 10",
|
|
}
|
|
for _, line := range noise {
|
|
if _, ok := parseSpot(line); ok {
|
|
t.Errorf("noise line parsed as spot: %q", line)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The reply to SH/DX is a TABLE, not the "DX de …" broadcast — a completely
|
|
// different shape. Because only the broadcast form was parsed, a SH/DX/100 reply
|
|
// arrived, matched nothing and was dropped: the command looked like it did
|
|
// nothing at all. These lines must now land in the grid, flagged Historical.
|
|
func TestParseShowDX(t *testing.T) {
|
|
cases := []struct {
|
|
line string
|
|
call string
|
|
khz float64
|
|
spotter string
|
|
}{
|
|
{" 14195.0 EA8DHH 3-Jul-2026 1234Z CQ DX <F5ABC>", "EA8DHH", 14195.0, "F5ABC"},
|
|
{" 7005.5 RA3XYZ 14-Jul-2026 0912Z <DL1ABC>", "RA3XYZ", 7005.5, "DL1ABC"},
|
|
{"21025.0 VK9/DL2XYZ 1-Jan-2026 0001Z up 2 <JA1ABC>", "VK9/DL2XYZ", 21025.0, "JA1ABC"},
|
|
// No spotter brackets — still a spot, just without a DE.
|
|
{" 50313.0 IK0ABC 3-Jul-2026 1500Z FT8", "IK0ABC", 50313.0, ""},
|
|
}
|
|
for _, c := range cases {
|
|
got, ok := parseShowDX(c.line)
|
|
if !ok {
|
|
t.Errorf("parseShowDX(%q) failed — the SH/DX reply would be dropped again", c.line)
|
|
continue
|
|
}
|
|
if got.DXCall != c.call || got.FreqKHz != c.khz || got.Spotter != c.spotter {
|
|
t.Errorf("parseShowDX(%q) = call %q / %.1f / de %q, want %q / %.1f / %q",
|
|
c.line, got.DXCall, got.FreqKHz, got.Spotter, c.call, c.khz, c.spotter)
|
|
}
|
|
if !got.Historical {
|
|
t.Errorf("parseShowDX(%q): must be flagged Historical — otherwise 100 replayed spots fire 100 alerts", c.line)
|
|
}
|
|
if got.Band == "" {
|
|
t.Errorf("parseShowDX(%q): band not derived from %.1f kHz", c.line, c.khz)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The SH/DX parser must not swallow ordinary cluster prose — a console full of
|
|
// chatter turned into fake spots would be worse than no parser at all.
|
|
func TestParseShowDXRejectsNoise(t *testing.T) {
|
|
noise := []string{
|
|
"DX de F5ABC: 14195.0 EA8DHH CQ DX 1234Z", // the broadcast form: spotRE owns it
|
|
"Hello and welcome to the DXSpider cluster",
|
|
"WWV de VE7CC <18Z> : SFI=110, A=16, K=2",
|
|
"F4BPO de GB7DXC 12-Jul-2026 2130Z dxspider >",
|
|
"",
|
|
"There are 42 users online",
|
|
}
|
|
for _, l := range noise {
|
|
if s, ok := parseShowDX(l); ok {
|
|
t.Errorf("parseShowDX(%q) wrongly produced a spot: %+v", l, s)
|
|
}
|
|
}
|
|
}
|