diff --git a/assert/assertions.go b/assert/assertions.go index 1419e4776..1e9c914cb 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -1013,14 +1013,14 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true // we consider nil to be equal to the nil set } - listKind := reflect.TypeOf(list).Kind() + listKind := kindOfList(list) if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + return Fail(t, unsupportedListTypeMessage(list, listKind), msgAndArgs...) } - subsetKind := reflect.TypeOf(subset).Kind() + subsetKind := kindOfList(subset) if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + return Fail(t, unsupportedListTypeMessage(subset, subsetKind), msgAndArgs...) } if subsetKind == reflect.Map && listKind == reflect.Map { @@ -1081,14 +1081,14 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) } - listKind := reflect.TypeOf(list).Kind() + listKind := kindOfList(list) if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%#v has an unsupported type %s", list, listKind), msgAndArgs...) + return Fail(t, unsupportedListTypeMessage(list, listKind), msgAndArgs...) } - subsetKind := reflect.TypeOf(subset).Kind() + subsetKind := kindOfList(subset) if subsetKind != reflect.Array && subsetKind != reflect.Slice && subsetKind != reflect.Map { - return Fail(t, fmt.Sprintf("%#v has an unsupported type %s", subset, subsetKind), msgAndArgs...) + return Fail(t, unsupportedListTypeMessage(subset, subsetKind), msgAndArgs...) } if subsetKind == reflect.Map && listKind == reflect.Map { @@ -1132,6 +1132,21 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) return Fail(t, fmt.Sprintf("%s is a subset of %s", truncatingFormat("%#v", subset), truncatingFormat("%#v", list)), msgAndArgs...) } +func kindOfList(list interface{}) reflect.Kind { + listType := reflect.TypeOf(list) + if listType == nil { + return reflect.Invalid + } + return listType.Kind() +} + +func unsupportedListTypeMessage(list interface{}, kind reflect.Kind) string { + if kind == reflect.Invalid { + return fmt.Sprintf("%#v has an unsupported type ", list) + } + return fmt.Sprintf("%#v has an unsupported type %s", list, kind) +} + // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 11642e096..906a87aab 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -1288,6 +1288,44 @@ func TestNotSubsetNil(t *testing.T) { } } +func TestSubsetNotSubsetWithNilList(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + assertion func(TestingT, interface{}, interface{}, ...interface{}) bool + }{ + {"Subset", Subset}, + {"NotSubset", NotSubset}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + mockT := new(mockTestingT) + var result bool + + funcDidPanic, panicValue, _ := didPanic(func() { + result = tc.assertion(mockT, nil, []int{1}) + }) + + False(t, funcDidPanic, "%s should not panic: %#v", tc.name, panicValue) + False(t, result) + Contains(t, mockT.errorString(), " has an unsupported type ") + }) + } +} + +func TestSubsetFormatsUnsupportedNonStringListCorrectly(t *testing.T) { + t.Parallel() + + mockT := new(mockTestingT) + Subset(mockT, true, []bool{true}) + + errStr := mockT.errorString() + NotContains(t, errStr, "%!q", "Subset error message should not contain %%q formatting artifacts") + Contains(t, errStr, "true has an unsupported type bool") +} + func Test_containsElement(t *testing.T) { t.Parallel()