Files
OpsLog/internal/adif/roundtrip_test.go
T
2026-06-06 14:16:30 +02:00

122 lines
4.1 KiB
Go

package adif
import (
"bufio"
"bytes"
"strings"
"testing"
"time"
"hamlog/internal/qso"
)
// TestPromotedFieldsRoundTrip writes a QSO carrying the ADIF 3.1.7 promoted
// fields, parses it back, and checks they survive — guarding the export
// writeRecord ↔ import recordToQSO field-name mapping against typos.
func TestPromotedFieldsRoundTrip(t *testing.T) {
dist := 1234.5
rxp := 5.0
a := 12.0
in := qso.QSO{
Callsign: "EA8ABC", Band: "20m", Mode: "SSB",
QSODate: time.Date(2026, 6, 6, 12, 0, 0, 0, time.UTC),
SIG: "POTA", SIGInfo: "US-0001", MySIG: "WWFF", MySIGInfo: "ONFF-0001",
WWFFRef: "ONFF-0001", MyWWFFRef: "F-FFF-0001",
Distance: &dist, RXPower: &rxp, AIndex: &a,
SKCC: "12345S", FISTS: "999", TenTen: "55555",
ContactedOp: "EA8XYZ", EqCall: "EA8OLD", PFX: "EA8", MyName: "Greg",
Class: "1A", DarcDOK: "A01", MyDarcDOK: "B02", Region: "IV",
SilentKey: "N", SWL: "N", QSOComplete: "Y", QSORandom: "Y",
CreditGranted: "DXCC", CreditSubmitted: "WAS",
MyARRLSect: "EMA", MyVUCCGrids: "FN20,FN21",
}
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
bw.WriteString("<EOH>\n")
writeRecord(bw, in, true)
bw.Flush()
var rec Record
if err := Parse(strings.NewReader(buf.String()), func(r Record) error { rec = r; return nil }); err != nil {
t.Fatalf("parse: %v", err)
}
out, ok := recordToQSO(rec)
if !ok {
t.Fatal("recordToQSO returned !ok")
}
checks := map[string]struct{ got, want string }{
"SIG": {out.SIG, in.SIG},
"SIG_INFO": {out.SIGInfo, in.SIGInfo},
"MY_SIG": {out.MySIG, in.MySIG},
"MY_SIG_INFO": {out.MySIGInfo, in.MySIGInfo},
"WWFF_REF": {out.WWFFRef, in.WWFFRef},
"MY_WWFF_REF": {out.MyWWFFRef, in.MyWWFFRef},
"SKCC": {out.SKCC, in.SKCC},
"FISTS": {out.FISTS, in.FISTS},
"TEN_TEN": {out.TenTen, in.TenTen},
"CONTACTED_OP": {out.ContactedOp, in.ContactedOp},
"EQ_CALL": {out.EqCall, in.EqCall},
"PFX": {out.PFX, in.PFX},
"MY_NAME": {out.MyName, in.MyName},
"CLASS": {out.Class, in.Class},
"DARC_DOK": {out.DarcDOK, in.DarcDOK},
"MY_DARC_DOK": {out.MyDarcDOK, in.MyDarcDOK},
"REGION": {out.Region, in.Region},
"SILENT_KEY": {out.SilentKey, in.SilentKey},
"SWL": {out.SWL, in.SWL},
"QSO_COMPLETE": {out.QSOComplete, in.QSOComplete},
"QSO_RANDOM": {out.QSORandom, in.QSORandom},
"CREDIT_GRANTED": {out.CreditGranted, in.CreditGranted},
"CREDIT_SUBMITTED": {out.CreditSubmitted, in.CreditSubmitted},
"MY_ARRL_SECT": {out.MyARRLSect, in.MyARRLSect},
"MY_VUCC_GRIDS": {out.MyVUCCGrids, in.MyVUCCGrids},
}
for tag, c := range checks {
if c.got != c.want {
t.Errorf("%s round-trip = %q, want %q", tag, c.got, c.want)
}
}
if out.Distance == nil || *out.Distance != dist {
t.Errorf("DISTANCE round-trip = %v, want %v", out.Distance, dist)
}
if out.RXPower == nil || *out.RXPower != rxp {
t.Errorf("RX_PWR round-trip = %v, want %v", out.RXPower, rxp)
}
if out.AIndex == nil || *out.AIndex != a {
t.Errorf("A_INDEX round-trip = %v, want %v", out.AIndex, a)
}
}
// TestStandardExportDropsNonStandard verifies that standard mode strips
// vendor/APP tags while full mode keeps them.
func TestStandardExportDropsNonStandard(t *testing.T) {
q := qso.QSO{
Callsign: "F4BPO", Band: "20m", Mode: "CW",
Extras: map[string]string{
"APP_LOG4OM_FOO": "x",
"DARC_DOK": "A01", // standard → kept in both
"MY_VENDOR_TAG": "y", // non-standard → dropped in standard mode
},
}
standard := renderRecord(q, false)
if strings.Contains(standard, "APP_LOG4OM_FOO") || strings.Contains(standard, "MY_VENDOR_TAG") {
t.Errorf("standard export should drop non-standard tags:\n%s", standard)
}
full := renderRecord(q, true)
if !strings.Contains(full, "APP_LOG4OM_FOO") || !strings.Contains(full, "MY_VENDOR_TAG") {
t.Errorf("full export should keep all extras:\n%s", full)
}
}
func renderRecord(q qso.QSO, includeApp bool) string {
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
writeRecord(bw, q, includeApp)
bw.Flush()
return buf.String()
}