From 3e97ddb0e08b494497193074269859d2745f023c Mon Sep 17 00:00:00 2001 From: John Graham-Cumming Date: Thu, 27 Mar 2014 05:43:13 -0700 Subject: [PATCH] Add tests for LOC record String() generation and fix small problems Added tests for the cmToM function to make sure that it's output is correct. Modified the way the Altitude is written to a string. Previously, if the altitude was an exact number of meters it would always be reported with two decimal places. This is not needed. Conversely if it was not an exact number of meters the cm were removed. --- parse_test.go | 4 +- types.go | 122 +++++++++++++++++++++++++++----------------------- types_test.go | 42 +++++++++++++++++ zscan.go | 8 ++-- 4 files changed, 113 insertions(+), 63 deletions(-) create mode 100644 types_test.go diff --git a/parse_test.go b/parse_test.go index 3ff3a93e..dd2799d1 100644 --- a/parse_test.go +++ b/parse_test.go @@ -386,8 +386,8 @@ func TestNSEC(t *testing.T) { func TestParseLOC(t *testing.T) { lt := map[string]string{ - "SW1A2AA.find.me.uk. LOC 51 30 12.748 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m": "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 30 12.748 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m", - "SW1A2AA.find.me.uk. LOC 51 0 0.0 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m": "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 00 0.000 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m", + "SW1A2AA.find.me.uk. LOC 51 30 12.748 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m": "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 30 12.748 N 00 07 39.611 W 0m 0.00m 0.00m 0.00m", + "SW1A2AA.find.me.uk. LOC 51 0 0.0 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m": "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 00 0.000 N 00 07 39.611 W 0m 0.00m 0.00m 0.00m", } for i, o := range lt { rr, e := NewRR(i) diff --git a/types.go b/types.go index 8f86e34e..16bb181b 100644 --- a/types.go +++ b/types.go @@ -160,10 +160,14 @@ const ( _AD = 1 << 5 // authticated data _CD = 1 << 4 // checking disabled -) + LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2. + LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2. -// RFC 1876, Section 2 -const _LOC_EQUATOR = 1 << 31 + LOC_HOURS = 60 * 1000 + LOC_DEGREES = 60 * LOC_HOURS + + LOC_ALTITUDEBASE = 100000 +) // RFC 4398, Section 2.1 const ( @@ -783,48 +787,69 @@ func (rr *LOC) copy() RR { return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude} } +// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent +// format and returns a string in m (two decimals for the cm) +func cmToM(m, e uint8) string { + if e < 2 { + if e == 1 { + m *= 10 + } + + return fmt.Sprintf("0.%02d", m) + } + + s := fmt.Sprintf("%d", m) + for e > 2 { + s += "0" + e -= 1 + } + return s +} + +// String returns a string version of a LOC func (rr *LOC) String() string { s := rr.Hdr.String() - // Copied from ldns - // Latitude - lat := rr.Latitude - north := "N" - if lat > _LOC_EQUATOR { - lat = lat - _LOC_EQUATOR - } else { - north = "S" - lat = _LOC_EQUATOR - lat - } - h := lat / (1000 * 60 * 60) - lat = lat % (1000 * 60 * 60) - m := lat / (1000 * 60) - lat = lat % (1000 * 60) - s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float32(lat) / 1000), north) - // Longitude - lon := rr.Longitude - east := "E" - if lon > _LOC_EQUATOR { - lon = lon - _LOC_EQUATOR - } else { - east = "W" - lon = _LOC_EQUATOR - lon - } - h = lon / (1000 * 60 * 60) - lon = lon % (1000 * 60 * 60) - m = lon / (1000 * 60) - lon = lon % (1000 * 60) - s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float32(lon) / 1000), east) - s1 := rr.Altitude / 100.00 - s1 -= 100000 - if rr.Altitude%100 == 0 { - s += fmt.Sprintf("%.2fm ", float32(s1)) + lat := rr.Latitude + ns := "N" + if lat > LOC_EQUATOR { + lat = lat - LOC_EQUATOR } else { - s += fmt.Sprintf("%.0fm ", float32(s1)) + ns = "S" + lat = LOC_EQUATOR - lat } - s += cmToString((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m " - s += cmToString((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m " - s += cmToString((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m" + h := lat / LOC_DEGREES + lat = lat % LOC_DEGREES + m := lat / LOC_HOURS + lat = lat % LOC_HOURS + s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns) + + lon := rr.Longitude + ew := "E" + if lon > LOC_PRIMEMERIDIAN { + lon = lon - LOC_PRIMEMERIDIAN + } else { + ew = "W" + lon = LOC_PRIMEMERIDIAN - lon + } + h = lon / LOC_DEGREES + lon = lon % LOC_DEGREES + m = lon / LOC_HOURS + lon = lon % LOC_HOURS + s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew) + + var alt float64 = float64(rr.Altitude) / 100 + alt -= LOC_ALTITUDEBASE + if rr.Altitude%100 != 0 { + s += fmt.Sprintf("%.2fm ", alt) + } else { + s += fmt.Sprintf("%.0fm ", alt) + } + + s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m " + s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m " + s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m" + return s } @@ -1580,23 +1605,6 @@ func saltToString(s string) string { return strings.ToUpper(s) } -func cmToString(mantissa, exponent uint8) string { - switch exponent { - case 0, 1: - if exponent == 1 { - mantissa *= 10 - } - return fmt.Sprintf("%.02f", float32(mantissa)) - default: - s := fmt.Sprintf("%d", mantissa) - for i := uint8(0); i < exponent-2; i++ { - s += "0" - } - return s - } - panic("dns: not reached") -} - func euiToString(eui uint64, bits int) (hex string) { switch bits { case 64: diff --git a/types_test.go b/types_test.go new file mode 100644 index 00000000..11861294 --- /dev/null +++ b/types_test.go @@ -0,0 +1,42 @@ +package dns + +import ( + "testing" +) + +func TestCmToM(t *testing.T) { + s := cmToM(0, 0) + if s != "0.00" { + t.Error("0, 0") + } + + s = cmToM(1, 0) + if s != "0.01" { + t.Error("1, 0") + } + + s = cmToM(3, 1) + if s != "0.30" { + t.Error("3, 1") + } + + s = cmToM(4, 2) + if s != "4" { + t.Error("4, 2") + } + + s = cmToM(5, 3) + if s != "50" { + t.Error("5, 3") + } + + s = cmToM(7, 5) + if s != "7000" { + t.Error("7, 5") + } + + s = cmToM(9, 9) + if s != "90000000" { + t.Error("9, 9") + } +} diff --git a/zscan.go b/zscan.go index 41a328e4..7ba51986 100644 --- a/zscan.go +++ b/zscan.go @@ -899,9 +899,9 @@ func appendOrigin(name, origin string) string { func locCheckNorth(token string, latitude uint32) (uint32, bool) { switch token { case "n", "N": - return _LOC_EQUATOR + latitude, true + return LOC_EQUATOR + latitude, true case "s", "S": - return _LOC_EQUATOR - latitude, true + return LOC_EQUATOR - latitude, true } return latitude, false } @@ -910,9 +910,9 @@ func locCheckNorth(token string, latitude uint32) (uint32, bool) { func locCheckEast(token string, longitude uint32) (uint32, bool) { switch token { case "e", "E": - return _LOC_EQUATOR + longitude, true + return LOC_EQUATOR + longitude, true case "w", "W": - return _LOC_EQUATOR - longitude, true + return LOC_EQUATOR - longitude, true } return longitude, false }