diff --git a/assert/assertions.go b/assert/assertions.go index a27e70546..5d1acf816 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -1948,19 +1948,28 @@ func diff(expected interface{}, actual interface{}) string { var e, a string - switch et { - case reflect.TypeOf(""): - e = reflect.ValueOf(expected).String() - a = reflect.ValueOf(actual).String() - case reflect.TypeOf(time.Time{}): - e = spewConfigStringerEnabled.Sdump(expected) - a = spewConfigStringerEnabled.Sdump(actual) - default: - e = spewConfig.Sdump(expected) - a = spewConfig.Sdump(actual) + // Use spew to create string representations of the objects + // We have to guard against panics in spew. + // See https://github.com/stretchr/testify/issues/480 + panicked, _, _ := didPanic(func() { + switch et { + case reflect.TypeOf(""): + e = reflect.ValueOf(expected).String() + a = reflect.ValueOf(actual).String() + case reflect.TypeOf(time.Time{}): + e = spewConfigStringerEnabled.Sdump(expected) + a = spewConfigStringerEnabled.Sdump(actual) + default: + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) + } + }) + if panicked { + // silently ignore diff if we panic during spew, the library is no longer maintained + return "" } - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(e), B: difflib.SplitLines(a), FromFile: "Expected", @@ -1970,6 +1979,11 @@ func diff(expected interface{}, actual interface{}) string { Context: 1, }) + if err != nil { + // silently ignore diff if the external library fails to compute it + return "" + } + return "\n\nDiff:\n" + diff } diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 4975f5e41..46e3ccefa 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -837,6 +837,39 @@ func TestEqualFormatting(t *testing.T) { } } +func TestEqualFormattingWithPanic(t *testing.T) { + t.Parallel() + + type structWithUnexportedMapWithArrayKey struct { + m interface{} + } + + for _, c := range []struct { + a interface{} + b interface{} + }{ + { + // from the issue https://github.com/stretchr/testify/pull/1816 + a: structWithUnexportedMapWithArrayKey{ + map[[1]byte]*struct{}{ + {1}: nil, + {2}: nil, + }, + }, + b: structWithUnexportedMapWithArrayKey{}, + }, + } { + + mockT := new(mockTestingT) + NotPanics(t, func() { + Equal(mockT, c.a, c.b) + }, "should not panic") + + True(t, mockT.Failed(), "should have failed") + Contains(t, mockT.errorString(), "Not equal:", "error message should mention inequality") + } +} + func TestFormatUnequalValues(t *testing.T) { t.Parallel()