|
|
|
@ -577,6 +577,68 @@ func (h *Hostinfo) Equal(h2 *Hostinfo) bool {
|
|
|
|
return reflect.DeepEqual(h, h2)
|
|
|
|
return reflect.DeepEqual(h, h2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// HowUnequal returns a list of paths through Hostinfo where h and h2 differ.
|
|
|
|
|
|
|
|
// If they differ in nil-ness, the path is "nil", otherwise the path is like
|
|
|
|
|
|
|
|
// "ShieldsUp" or "NetInfo.nil" or "NetInfo.PCP".
|
|
|
|
|
|
|
|
func (h *Hostinfo) HowUnequal(h2 *Hostinfo) (path []string) {
|
|
|
|
|
|
|
|
return appendStructPtrDiff(nil, "", reflect.ValueOf(h), reflect.ValueOf(h2))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func appendStructPtrDiff(base []string, pfx string, p1, p2 reflect.Value) (ret []string) {
|
|
|
|
|
|
|
|
ret = base
|
|
|
|
|
|
|
|
if p1.IsNil() && p2.IsNil() {
|
|
|
|
|
|
|
|
return base
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
mkPath := func(b string) string {
|
|
|
|
|
|
|
|
if pfx == "" {
|
|
|
|
|
|
|
|
return b
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return pfx + "." + b
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if p1.IsNil() || p2.IsNil() {
|
|
|
|
|
|
|
|
return append(base, mkPath("nil"))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
v1, v2 := p1.Elem(), p2.Elem()
|
|
|
|
|
|
|
|
t := v1.Type()
|
|
|
|
|
|
|
|
for i, n := 0, t.NumField(); i < n; i++ {
|
|
|
|
|
|
|
|
sf := t.Field(i)
|
|
|
|
|
|
|
|
switch sf.Type.Kind() {
|
|
|
|
|
|
|
|
case reflect.String:
|
|
|
|
|
|
|
|
if v1.Field(i).String() != v2.Field(i).String() {
|
|
|
|
|
|
|
|
ret = append(ret, mkPath(sf.Name))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
case reflect.Bool:
|
|
|
|
|
|
|
|
if v1.Field(i).Bool() != v2.Field(i).Bool() {
|
|
|
|
|
|
|
|
ret = append(ret, mkPath(sf.Name))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
|
|
|
|
if v1.Field(i).Int() != v2.Field(i).Int() {
|
|
|
|
|
|
|
|
ret = append(ret, mkPath(sf.Name))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
|
|
|
|
|
|
if v1.Field(i).Uint() != v2.Field(i).Uint() {
|
|
|
|
|
|
|
|
ret = append(ret, mkPath(sf.Name))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
case reflect.Slice, reflect.Map:
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(v1.Field(i).Interface(), v2.Field(i).Interface()) {
|
|
|
|
|
|
|
|
ret = append(ret, mkPath(sf.Name))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
case reflect.Ptr:
|
|
|
|
|
|
|
|
if sf.Type.Elem().Kind() == reflect.Struct {
|
|
|
|
|
|
|
|
ret = appendStructPtrDiff(ret, sf.Name, v1.Field(i), v2.Field(i))
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
panic(fmt.Sprintf("unsupported type at %s: %s", mkPath(sf.Name), sf.Type.String()))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SignatureType specifies a scheme for signing RegisterRequest messages. It
|
|
|
|
// SignatureType specifies a scheme for signing RegisterRequest messages. It
|
|
|
|
// specifies the crypto algorithms to use, the contents of what is signed, and
|
|
|
|
// specifies the crypto algorithms to use, the contents of what is signed, and
|
|
|
|
// any other relevant details. Historically, requests were unsigned so the zero
|
|
|
|
// any other relevant details. Historically, requests were unsigned so the zero
|
|
|
|
|