diff --git a/assert/assertions.go b/assert/assertions.go index a27e70546..47df9e08f 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -1928,6 +1928,23 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { return t, k } +func isStructWithUnexportedMapField(t reflect.Type) bool { + if t.Kind() != reflect.Struct { + return false + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if !field.IsExported() && + field.Type.Kind() == reflect.Map && + field.Type.Key().Kind() == reflect.Array { + return true + } + } + + return false +} + // diff returns a diff of both values as long as both are of the same type and // are a struct, map, slice, array or string. Otherwise it returns an empty string. func diff(expected interface{}, actual interface{}) string { @@ -1948,13 +1965,16 @@ func diff(expected interface{}, actual interface{}) string { var e, a string - switch et { - case reflect.TypeOf(""): + switch { + case et == reflect.TypeOf(""): e = reflect.ValueOf(expected).String() a = reflect.ValueOf(actual).String() - case reflect.TypeOf(time.Time{}): + case et == reflect.TypeOf(time.Time{}): e = spewConfigStringerEnabled.Sdump(expected) a = spewConfigStringerEnabled.Sdump(actual) + case isStructWithUnexportedMapField(et): + e = fmt.Sprintf("%+v", expected) + a = fmt.Sprintf("%+v", actual) default: e = spewConfig.Sdump(expected) a = spewConfig.Sdump(actual) diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 4975f5e41..d70276b0c 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -593,6 +593,10 @@ func TestEqual(t *testing.T) { mockT := new(testing.T) var m map[string]interface{} + type unexportedKeyType struct { + m map[[1]byte]*struct{} + } + cases := []struct { expected interface{} actual interface{} @@ -613,6 +617,40 @@ func TestEqual(t *testing.T) { {m["bar"], "something", false, ""}, {myType("1"), myType("2"), false, ""}, + // Test cases for struct with unexported map field containing array keys + { + unexportedKeyType{ + map[[1]byte]*struct{}{ + {1}: nil, + {2}: nil, + }, + }, + unexportedKeyType{ + map[[1]byte]*struct{}{ + {1}: nil, + {2}: nil, + }, + }, + true, + "", + }, + { + unexportedKeyType{ + map[[1]byte]*struct{}{ + {1}: {}, + {2}: {}, + }, + }, + unexportedKeyType{ + map[[1]byte]*struct{}{ + {3}: {}, + {4}: {}, + }, + }, + false, + "structs with unexported map fields using array keys are not equal when keys differ", + }, + // A case that might be confusing, especially with numeric literals {10, uint(10), false, ""}, }