Change:
This tree has a commit that demonstrates two obviously different objects that should not pass the semantic DeepEqual but do.
What shall we do with this issue for triage? Labels? Priority?
P2 for when he returns , Satnam Singh wrote:
OK I am now sufficiently worried about this. Fixes incoming.

Discussion:
} return a.Amount.Cmp(b.Amount) == 0 }, <ins> func(a, b util.Time) bool { return a.Unix() == b.Unix() }, </ins> ) var standardResources = util.NewStringSet(

"net/http/httptest" "net/url" "os" <del> // "reflect" </del> <ins> "reflect" </ins> "strings" "testing" "time"

if changed != &r { t.Errorf("returned request should point to the same object") } <del> if !api.Semantic.DeepDerivative(changed, &original) { </del> <ins> if !reflect.DeepEqual(changed, &original) { </ins> t.Errorf("expected %#v, got %#v", &original, changed) } }

import ( "fmt" "reflect" <ins> "strings" </ins> ) // Equalities is a map from type to a function comparing two values of

typ reflect.Type } <ins> // unexportedTypePanic is thrown when you use this DeepEqual on something that has an // unexported type. It indicates a programmer error, so should not occur at runtime, // which is why it's not public and thus impossible to catch. type unexportedTypePanic []reflect.Type func (u unexportedTypePanic) Error() string { return u.String() } func (u unexportedTypePanic) String() string { strs := make([]string, len(u)) for i, t := range u { strs[i] = fmt.Sprintf("%v", t) } return "an unexported field was encountered, nested like this: " + strings.Join(strs, " -> ") } func makeUsefulPanic(v reflect.Value) { if x := recover(); x != nil { if u, ok := x.(unexportedTypePanic); ok { u = append(unexportedTypePanic{v.Type()}, u...) x = u } panic(x) } } </ins> // Tests for deep equality using reflected types. The map argument tracks // comparisons that have already been seen, which allows short circuiting on // recursive types. func (e Equalities) deepValueEqual(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool { <ins> defer makeUsefulPanic(v1) </ins> if !v1.IsValid() || !v2.IsValid() { return v1.IsValid() == v2.IsValid() }

// // An empty slice *is* equal to a nil slice for our purposes; same for maps. // <del> // Unexported field members are not compared. </del> <ins> // Unexported field members cannot be compared and will cause an imformative panic; you must add an Equality // function for these types. </ins> func (e Equalities) DeepEqual(a1, a2 interface{}) bool { if a1 == nil || a2 == nil { return a1 == a2

} func (e Equalities) deepValueDerive(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool { <ins> defer makeUsefulPanic(v1) </ins> if !v1.IsValid() || !v2.IsValid() { return v1.IsValid() == v2.IsValid() }

return false default: // Normal equality suffices <del> if v1.CanInterface() && v2.CanInterface() { return v1.Interface() == v2.Interface() </del> <ins> if !v1.CanInterface() || !v2.CanInterface() { panic(unexportedTypePanic{}) </ins> } <del> return v1.CanInterface() == v2.CanInterface() </del> <ins> return v1.Interface() == v2.Interface() </ins> } }

"encoding/json" "fmt" "io/ioutil" <ins> "reflect" </ins> "strings" "testing"

if controller.Status.Replicas != 2 { t.Errorf("expected 2, got: %d", controller.Status.Replicas) } <del> if !api.Semantic.DeepEqual(fakeLister.s, labels.Set(controller.Spec.Selector).AsSelector()) { </del> <ins> if !reflect.DeepEqual(fakeLister.s, labels.Set(controller.Spec.Selector).AsSelector()) { </ins> t.Errorf("unexpected output: %#v %#v", labels.Set(controller.Spec.Selector).AsSelector(), fakeLister.s) } }