ADIF defines CNTY as "STATE,COUNTY" — "GA,BARROW". OpsLog wrote the bare county name, which a receiving logger cannot resolve: county names repeat across states, and there is a Washington County in thirty of them. The award engine here was never affected, since it reads the columns rather than the ADIF; the damage was to every file we hand to someone else. One writer covers everything — writeRecord — so this fixes file exports and the LoTW, Club Log, HRDLog and QRZ uploads together. MY_CNTY gets the same treatment. The county alone is still written when no state is known: a bare name is worth more than nothing, and inventing a prefix would be worse than either. A value that already carries a comma passes through untouched, so re-exporting an imported record cannot double the prefix. Import is the mirror: "GA,BARROW" fills both columns, and a file carrying the bare county — as OpsLog's own older exports do — still imports unchanged. The state parsed out of CNTY only fills a blank STATE, never overrides it: STATE is the dedicated field and the more specific statement.
45 lines
1.4 KiB
Go
45 lines
1.4 KiB
Go
package adif
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Loggers (notably Log4OM's UDP/exported ADIF) sometimes declare a field
|
|
// length as the CHARACTER count instead of the UTF-8 byte count, truncating
|
|
// multibyte values mid-rune. The parser must recover the full value.
|
|
func TestCharCountLengthRepair(t *testing.T) {
|
|
cases := []struct{ name, wantQTH, wantName, adi string }{
|
|
{
|
|
name: "latin",
|
|
wantQTH: "Tóalmás", // 7 chars / 9 bytes, declared 7
|
|
wantName: "Laci Budai",
|
|
adi: "<EOH>\n<CALL:5>HA5XY<QTH:7>Tóalmás<NAME:10>Laci Budai<EOR>\n",
|
|
},
|
|
{
|
|
name: "cyrillic",
|
|
wantQTH: "Дзержинск", // 9 chars / 18 bytes, declared 9
|
|
wantName: "Александр Чайка", // 15 chars / 29 bytes, declared 15
|
|
adi: "<EOH>\n<CALL:6>UA3TFS<NAME:15>Александр Чайка<QTH:9>Дзержинск<EOR>\n",
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
var got Record
|
|
if err := Parse(strings.NewReader(c.adi), func(r Record) error { got = r; return nil }); err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
if got["qth"] != c.wantQTH {
|
|
t.Errorf("qth = %q, want %q", got["qth"], c.wantQTH)
|
|
}
|
|
if got["name"] != c.wantName {
|
|
t.Errorf("name = %q, want %q", got["name"], c.wantName)
|
|
}
|
|
if !utf8.ValidString(got["name"]) || !utf8.ValidString(got["qth"]) {
|
|
t.Errorf("result not valid UTF-8: name=%q qth=%q", got["name"], got["qth"])
|
|
}
|
|
})
|
|
}
|
|
}
|