From 37cb92006294ef63050e5e24dd03a99a81c3b219 Mon Sep 17 00:00:00 2001 From: liqiang2 Date: Sun, 25 Oct 2026 15:22:57 +0800 Subject: [PATCH] assert: preserve zero-valued elements in collection comparisons --- assert/assertions.go | 22 +++++++++++----------- assert/assertions_test.go | 12 ++++++++++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/assert/assertions.go b/assert/assertions.go index 166f63726..b84e8b2e2 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -1141,10 +1141,6 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface if h, ok := t.(tHelper); ok { h.Helper() } - if isEmpty(listA) && isEmpty(listB) { - return true - } - if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { return false } @@ -1158,8 +1154,11 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) } -// isList checks that the provided value is array or slice. +// isList checks that the provided value is nil, an array, or a slice. func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) { + if list == nil { + return true + } kind := reflect.TypeOf(list).Kind() if kind != reflect.Array && kind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind), @@ -1175,8 +1174,13 @@ func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { aValue := reflect.ValueOf(listA) bValue := reflect.ValueOf(listB) - aLen := aValue.Len() - bLen := bValue.Len() + var aLen, bLen int + if aValue.IsValid() { + aLen = aValue.Len() + } + if bValue.IsValid() { + bLen = bValue.Len() + } // Mark indexes in bValue that we already used visited := make([]bool, bLen) @@ -1242,10 +1246,6 @@ func NotElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interf if h, ok := t.(tHelper); ok { h.Helper() } - if isEmpty(listA) && isEmpty(listB) { - return Fail(t, "listA and listB contain the same elements", msgAndArgs) - } - if !isList(t, listA, msgAndArgs...) { return Fail(t, "listA is not a list type", msgAndArgs...) } diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 11642e096..2fad10947 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -1365,11 +1365,17 @@ func TestElementsMatch(t *testing.T) { {[]string{"hello", "hello", "world"}, []string{"hello", "world", "hello"}, true}, {[3]string{"hello", "hello", "world"}, [3]string{"hello", "world", "hello"}, true}, {[]int{}, nil, true}, + {[0]int{}, nil, true}, + {[2]int{}, []int{0, 0}, true}, // not matching {[]int{1}, []int{1, 1}, false}, {[]int{1, 2}, []int{2, 2}, false}, {[]string{"hello", "hello"}, []string{"hello"}, false}, + {[2]int{}, []int{}, false}, + {[2]int{}, [1]int{}, false}, + {nil, []int{1}, false}, + {[]int{1}, nil, false}, } for _, c := range cases { @@ -1490,6 +1496,10 @@ func TestNotElementsMatch(t *testing.T) { {[]string{"hello"}, []string{"world"}, true}, {[]string{"hello", "hello"}, []string{"world", "world"}, true}, {[3]string{"hello", "hello", "hello"}, [3]string{"world", "world", "world"}, true}, + {[2]int{}, []int{}, true}, + {[2]int{}, [1]int{}, true}, + {nil, []int{1}, true}, + {[]int{1}, nil, true}, // matching {nil, nil, false}, @@ -1504,6 +1514,8 @@ func TestNotElementsMatch(t *testing.T) { {[]string{"hello", "hello"}, []string{"hello", "hello"}, false}, {[]string{"hello", "hello", "world"}, []string{"hello", "world", "hello"}, false}, {[3]string{"hello", "hello", "world"}, [3]string{"hello", "world", "hello"}, false}, + {[0]int{}, nil, false}, + {[2]int{}, []int{0, 0}, false}, } for _, c := range cases {