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.
This commit is contained in:
John Graham-Cumming 2014-03-27 05:43:13 -07:00 committed by Filippo Valsorda
parent 877e47b4c3
commit 3e97ddb0e0
4 changed files with 113 additions and 63 deletions

View File

@ -386,8 +386,8 @@ func TestNSEC(t *testing.T) {
func TestParseLOC(t *testing.T) { func TestParseLOC(t *testing.T) {
lt := map[string]string{ 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 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 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 0m 0.00m 0.00m 0.00m",
} }
for i, o := range lt { for i, o := range lt {
rr, e := NewRR(i) rr, e := NewRR(i)

122
types.go
View File

@ -160,10 +160,14 @@ const (
_AD = 1 << 5 // authticated data _AD = 1 << 5 // authticated data
_CD = 1 << 4 // checking disabled _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 LOC_HOURS = 60 * 1000
const _LOC_EQUATOR = 1 << 31 LOC_DEGREES = 60 * LOC_HOURS
LOC_ALTITUDEBASE = 100000
)
// RFC 4398, Section 2.1 // RFC 4398, Section 2.1
const ( 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} 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 { func (rr *LOC) String() string {
s := rr.Hdr.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 lat := rr.Latitude
s1 -= 100000 ns := "N"
if rr.Altitude%100 == 0 { if lat > LOC_EQUATOR {
s += fmt.Sprintf("%.2fm ", float32(s1)) lat = lat - LOC_EQUATOR
} else { } else {
s += fmt.Sprintf("%.0fm ", float32(s1)) ns = "S"
lat = LOC_EQUATOR - lat
} }
s += cmToString((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m " h := lat / LOC_DEGREES
s += cmToString((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m " lat = lat % LOC_DEGREES
s += cmToString((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m" 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 return s
} }
@ -1580,23 +1605,6 @@ func saltToString(s string) string {
return strings.ToUpper(s) 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) { func euiToString(eui uint64, bits int) (hex string) {
switch bits { switch bits {
case 64: case 64:

42
types_test.go Normal file
View File

@ -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")
}
}

View File

@ -899,9 +899,9 @@ func appendOrigin(name, origin string) string {
func locCheckNorth(token string, latitude uint32) (uint32, bool) { func locCheckNorth(token string, latitude uint32) (uint32, bool) {
switch token { switch token {
case "n", "N": case "n", "N":
return _LOC_EQUATOR + latitude, true return LOC_EQUATOR + latitude, true
case "s", "S": case "s", "S":
return _LOC_EQUATOR - latitude, true return LOC_EQUATOR - latitude, true
} }
return latitude, false return latitude, false
} }
@ -910,9 +910,9 @@ func locCheckNorth(token string, latitude uint32) (uint32, bool) {
func locCheckEast(token string, longitude uint32) (uint32, bool) { func locCheckEast(token string, longitude uint32) (uint32, bool) {
switch token { switch token {
case "e", "E": case "e", "E":
return _LOC_EQUATOR + longitude, true return LOC_EQUATOR + longitude, true
case "w", "W": case "w", "W":
return _LOC_EQUATOR - longitude, true return LOC_EQUATOR - longitude, true
} }
return longitude, false return longitude, false
} }