137 lines
2.9 KiB
Go
137 lines
2.9 KiB
Go
package aprs
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"math"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestParse(t *testing.T) {
|
|
tests := []struct {
|
|
Line string
|
|
Want *Frame
|
|
}{
|
|
{
|
|
`PD0MZ-10>APLRG1,WIDE1-1,qAC:=L4:I#P),la !GLoRa APRS iGate / 433.775MHz / 125kHz / SF12 / CR5 Batt=4.25V`,
|
|
&Frame{
|
|
Source: Address{Call: "PD0MZ", SSID: "10"},
|
|
Destination: Address{Call: "APLRG1"},
|
|
Path: Path{{Call: "WIDE1", SSID: "1"}, {Call: "qAC"}},
|
|
Data: &Position{
|
|
Latitude: 51.860004,
|
|
Longitude: 6.309997,
|
|
HasMessaging: true,
|
|
Symbol: "La",
|
|
Comment: "LoRa APRS iGate / 433.775MHz / 125kHz / SF12 / CR5 Batt=4.25V",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Line, func(t *testing.T) {
|
|
f, err := Parse(test.Line)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
//if !reflect.DeepEqual(f, test.Want) {
|
|
// t.Errorf("expected %+#v, got %#+v", test.Want, f)
|
|
//}
|
|
testCompareFrame(t, test.Want, f)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseSamples(t *testing.T) {
|
|
f, err := os.Open(filepath.Join("testdata", "packets.txt"))
|
|
if err != nil {
|
|
t.Skip(err)
|
|
return
|
|
}
|
|
defer func() { _ = f.Close() }()
|
|
|
|
r := bufio.NewReader(f)
|
|
for {
|
|
l, err := r.ReadString('\n')
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
return
|
|
}
|
|
t.Fatal(err)
|
|
}
|
|
|
|
l = testUnescapeHex(strings.TrimSpace(l[25:]))
|
|
if _, err = Parse(l); err != nil {
|
|
t.Errorf("%s: %v", l, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// testUnescapeHex replaces occurrences of <0xHH> (case-insensitive)
|
|
// with the corresponding single byte.
|
|
// Invalid sequences are left unchanged.
|
|
func testUnescapeHex(s string) string {
|
|
if !strings.Contains(s, "<0x") && !strings.Contains(s, "<0X") {
|
|
return s
|
|
}
|
|
|
|
var b strings.Builder
|
|
b.Grow(len(s)) // upper bound; result will not exceed input length
|
|
|
|
for i := 0; i < len(s); {
|
|
// Minimal length for "<0xHH>" is 6
|
|
if i+6 <= len(s) &&
|
|
s[i] == '<' &&
|
|
(s[i+1] == '0') &&
|
|
(s[i+2] == 'x' || s[i+2] == 'X') &&
|
|
testIsHex(s[i+3]) &&
|
|
testIsHex(s[i+4]) &&
|
|
s[i+5] == '>' {
|
|
|
|
// Parse the hex byte
|
|
v, err := strconv.ParseUint(s[i+3:i+5], 16, 8)
|
|
if err == nil {
|
|
b.WriteByte(byte(v))
|
|
i += 6
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Default: copy one byte and continue
|
|
b.WriteByte(s[i])
|
|
i++
|
|
}
|
|
|
|
return b.String()
|
|
}
|
|
|
|
func testIsHex(c byte) bool {
|
|
return ('0' <= c && c <= '9') ||
|
|
('a' <= c && c <= 'f') ||
|
|
('A' <= c && c <= 'F')
|
|
}
|
|
|
|
func testAlmostEqual(a, b float64) bool {
|
|
return math.Abs(a-b) < 1e-5
|
|
}
|
|
|
|
func testCompareFrame(t *testing.T, want, test *Frame) {
|
|
t.Helper()
|
|
|
|
if !test.Source.EqualTo(want.Source) {
|
|
t.Errorf("expected source %s, got %s", want.Source, test.Source)
|
|
}
|
|
if !test.Destination.EqualTo(want.Destination) {
|
|
t.Errorf("expected destination %s, got %s", want.Destination, test.Destination)
|
|
}
|
|
if !test.Path.EqualTo(want.Path) {
|
|
t.Errorf("expected path %q, got %q", want.Path, test.Path)
|
|
}
|
|
testCompareData(t, want.Data, test.Data)
|
|
}
|