Skip to content

Commit 22deba0

Browse files
don't panic on unexported struct key in map
1 parent 429ee0b commit 22deba0

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

assert/assertions.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,23 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
19281928
return t, k
19291929
}
19301930

1931+
func isStructWithUnexportedMapField(t reflect.Type) bool {
1932+
if t.Kind() != reflect.Struct {
1933+
return false
1934+
}
1935+
1936+
for i := 0; i < t.NumField(); i++ {
1937+
field := t.Field(i)
1938+
if !field.IsExported() &&
1939+
field.Type.Kind() == reflect.Map &&
1940+
field.Type.Key().Kind() == reflect.Array {
1941+
return true
1942+
}
1943+
}
1944+
1945+
return false
1946+
}
1947+
19311948
// diff returns a diff of both values as long as both are of the same type and
19321949
// are a struct, map, slice, array or string. Otherwise it returns an empty string.
19331950
func diff(expected interface{}, actual interface{}) string {
@@ -1948,13 +1965,16 @@ func diff(expected interface{}, actual interface{}) string {
19481965

19491966
var e, a string
19501967

1951-
switch et {
1952-
case reflect.TypeOf(""):
1968+
switch {
1969+
case et == reflect.TypeOf(""):
19531970
e = reflect.ValueOf(expected).String()
19541971
a = reflect.ValueOf(actual).String()
1955-
case reflect.TypeOf(time.Time{}):
1972+
case et == reflect.TypeOf(time.Time{}):
19561973
e = spewConfigStringerEnabled.Sdump(expected)
19571974
a = spewConfigStringerEnabled.Sdump(actual)
1975+
case isStructWithUnexportedMapField(et):
1976+
e = reflect.ValueOf(expected).String()
1977+
a = reflect.ValueOf(actual).String()
19581978
default:
19591979
e = spewConfig.Sdump(expected)
19601980
a = spewConfig.Sdump(actual)

assert/assertions_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,12 +593,17 @@ func TestEqual(t *testing.T) {
593593
mockT := new(testing.T)
594594
var m map[string]interface{}
595595

596+
type unexportedKeyType struct {
597+
m map[[1]byte]*struct{}
598+
}
599+
596600
cases := []struct {
597601
expected interface{}
598602
actual interface{}
599603
result bool
600604
remark string
601605
}{
606+
602607
{"Hello World", "Hello World", true, ""},
603608
{123, 123, true, ""},
604609
{123.5, 123.5, true, ""},
@@ -613,6 +618,29 @@ func TestEqual(t *testing.T) {
613618
{m["bar"], "something", false, ""},
614619
{myType("1"), myType("2"), false, ""},
615620

621+
// Test cases for struct with unexported map field containing array keys
622+
{
623+
unexportedKeyType{
624+
map[[1]byte]*struct{}{
625+
{1}: nil,
626+
{2}: nil,
627+
},
628+
}, unexportedKeyType{}, false, "unexported key type is not equal to empty unexported key type",
629+
},
630+
{
631+
unexportedKeyType{
632+
map[[1]byte]*struct{}{
633+
{1}: {},
634+
{2}: {},
635+
},
636+
}, unexportedKeyType{
637+
map[[1]byte]*struct{}{
638+
{3}: {},
639+
{4}: {},
640+
},
641+
}, false, "structs with unexported map fields using array keys are not equal when keys differ",
642+
},
643+
616644
// A case that might be confusing, especially with numeric literals
617645
{10, uint(10), false, ""},
618646
}

0 commit comments

Comments
 (0)