From bbe0caf5669905231b3f7d93a60c579d5a178ed1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 07:25:43 +0000 Subject: [PATCH] fix(assertions): guard copyExportedFields against nil interface values in slices, maps, and pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When copyExportedFields recursively processes elements in slices, maps, or pointer targets that are nil interfaces, it returns nil. Calling reflect.ValueOf(nil) produces a zero reflect.Value, which panics when passed to Set. Add nil guards after each recursive call. Also removes a stale rapid fail file and regenerates docs. Signed-off-by: Frédéric BIDON Co-Authored-by: copilot-swe-agent[bot] <198982749+copilot-swe-agent[bot]@users.noreply.github.com> --- docs/doc-site/api/comparison.md | 6 +++--- docs/doc-site/api/ordering.md | 20 +++++++++---------- docs/doc-site/api/panic.md | 8 ++++---- docs/doc-site/api/type.md | 18 ++++++++--------- internal/assertions/equal.go | 12 ++++++++--- ...etyExportedValues-20260619051753-8674.fail | 6 ------ 6 files changed, 35 insertions(+), 35 deletions(-) delete mode 100644 internal/testintegration/assertions/testdata/rapid/TestNilSafetyExportedValues/TestNilSafetyExportedValues-20260619051753-8674.fail diff --git a/docs/doc-site/api/comparison.md b/docs/doc-site/api/comparison.md index 3d7a016c9..034bc49a2 100644 --- a/docs/doc-site/api/comparison.md +++ b/docs/doc-site/api/comparison.md @@ -1108,7 +1108,7 @@ func main() { |--|--| | [`assertions.Negative(t T, e any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#Negative) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Negative](https://github.com/go-openapi/testify/blob/master/internal/assertions/compare.go#L320) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Negative](https://github.com/go-openapi/testify/blob/master/internal/assertions/compare.go#L324) {{% /tab %}} {{< /tabs >}} @@ -1216,7 +1216,7 @@ func main() { |--|--| | [`assertions.NegativeT[SignedNumber SignedNumeric](t T, e SignedNumber, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NegativeT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NegativeT](https://github.com/go-openapi/testify/blob/master/internal/assertions/compare.go#L341) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NegativeT](https://github.com/go-openapi/testify/blob/master/internal/assertions/compare.go#L349) {{% /tab %}} {{< /tabs >}} @@ -1436,7 +1436,7 @@ func main() { |--|--| | [`assertions.PositiveT[SignedNumber SignedNumeric](t T, e SignedNumber, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#PositiveT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#PositiveT](https://github.com/go-openapi/testify/blob/master/internal/assertions/compare.go#L294) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#PositiveT](https://github.com/go-openapi/testify/blob/master/internal/assertions/compare.go#L298) {{% /tab %}} {{< /tabs >}} diff --git a/docs/doc-site/api/ordering.md b/docs/doc-site/api/ordering.md index 2f4c6781a..801ba0223 100644 --- a/docs/doc-site/api/ordering.md +++ b/docs/doc-site/api/ordering.md @@ -161,7 +161,7 @@ func main() { |--|--| | [`assertions.IsDecreasing(t T, collection any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsDecreasing) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsDecreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L205) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsDecreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L206) {{% /tab %}} {{< /tabs >}} @@ -270,7 +270,7 @@ func main() { |--|--| | [`assertions.IsDecreasingT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsDecreasingT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsDecreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L236) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsDecreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L237) {{% /tab %}} {{< /tabs >}} @@ -383,7 +383,7 @@ func main() { |--|--| | [`assertions.IsIncreasing(t T, collection any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsIncreasing) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsIncreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L24) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsIncreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L25) {{% /tab %}} {{< /tabs >}} @@ -492,7 +492,7 @@ func main() { |--|--| | [`assertions.IsIncreasingT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsIncreasingT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsIncreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L54) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsIncreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L55) {{% /tab %}} {{< /tabs >}} @@ -611,7 +611,7 @@ func main() { |--|--| | [`assertions.IsNonDecreasing(t T, collection any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsNonDecreasing) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonDecreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L269) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonDecreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L270) {{% /tab %}} {{< /tabs >}} @@ -726,7 +726,7 @@ func main() { |--|--| | [`assertions.IsNonDecreasingT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsNonDecreasingT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonDecreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L304) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonDecreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L305) {{% /tab %}} {{< /tabs >}} @@ -845,7 +845,7 @@ func main() { |--|--| | [`assertions.IsNonIncreasing(t T, collection any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsNonIncreasing) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonIncreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L144) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonIncreasing](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L145) {{% /tab %}} {{< /tabs >}} @@ -960,7 +960,7 @@ func main() { |--|--| | [`assertions.IsNonIncreasingT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsNonIncreasingT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonIncreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L179) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNonIncreasingT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L180) {{% /tab %}} {{< /tabs >}} @@ -1071,7 +1071,7 @@ func main() { |--|--| | [`assertions.NotSortedT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotSortedT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotSortedT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L112) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotSortedT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L113) {{% /tab %}} {{< /tabs >}} @@ -1182,7 +1182,7 @@ func main() { |--|--| | [`assertions.SortedT[OrderedSlice ~[]E, E Ordered](t T, collection OrderedSlice, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#SortedT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SortedT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L83) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#SortedT](https://github.com/go-openapi/testify/blob/master/internal/assertions/order.go#L84) {{% /tab %}} {{< /tabs >}} diff --git a/docs/doc-site/api/panic.md b/docs/doc-site/api/panic.md index 61225da0c..5557b3bfc 100644 --- a/docs/doc-site/api/panic.md +++ b/docs/doc-site/api/panic.md @@ -142,7 +142,7 @@ func main() { |--|--| | [`assertions.NotPanics(t T, f func(), msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotPanics) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotPanics](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L112) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotPanics](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L113) {{% /tab %}} {{< /tabs >}} @@ -257,7 +257,7 @@ func main() { |--|--| | [`assertions.Panics(t T, f func(), msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#Panics) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Panics](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L25) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Panics](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L26) {{% /tab %}} {{< /tabs >}} @@ -374,7 +374,7 @@ func main() { |--|--| | [`assertions.PanicsWithError(t T, errString string, f func(), msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#PanicsWithError) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#PanicsWithError](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L78) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#PanicsWithError](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L79) {{% /tab %}} {{< /tabs >}} @@ -490,7 +490,7 @@ func main() { |--|--| | [`assertions.PanicsWithValue(t T, expected any, f func(), msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#PanicsWithValue) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#PanicsWithValue](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L50) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#PanicsWithValue](https://github.com/go-openapi/testify/blob/master/internal/assertions/panic.go#L51) {{% /tab %}} {{< /tabs >}} diff --git a/docs/doc-site/api/type.md b/docs/doc-site/api/type.md index f5d5068c1..73243029f 100644 --- a/docs/doc-site/api/type.md +++ b/docs/doc-site/api/type.md @@ -296,7 +296,7 @@ type myType float64 |--|--| | [`assertions.IsNotOfTypeT[EType any](t T, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsNotOfTypeT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNotOfTypeT](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L144) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNotOfTypeT](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L152) {{% /tab %}} {{< /tabs >}} @@ -407,7 +407,7 @@ func main() { |--|--| | [`assertions.IsNotType(t T, theType any, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsNotType) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNotType](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L123) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsNotType](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L131) {{% /tab %}} {{< /tabs >}} @@ -518,7 +518,7 @@ type myType float64 |--|--| | [`assertions.IsOfTypeT[EType any](t T, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsOfTypeT) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsOfTypeT](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L98) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsOfTypeT](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L106) {{% /tab %}} {{< /tabs >}} @@ -629,7 +629,7 @@ func main() { |--|--| | [`assertions.IsType(t T, expectedType any, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#IsType) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsType](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L76) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#IsType](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L84) {{% /tab %}} {{< /tabs >}} @@ -745,7 +745,7 @@ func main() { |--|--| | [`assertions.Kind(t T, expectedKind reflect.Kind, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#Kind) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Kind](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L214) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Kind](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L222) {{% /tab %}} {{< /tabs >}} @@ -856,7 +856,7 @@ func main() { |--|--| | [`assertions.NotImplements(t T, interfaceObject any, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotImplements) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotImplements](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L49) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotImplements](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L53) {{% /tab %}} {{< /tabs >}} @@ -972,7 +972,7 @@ func main() { |--|--| | [`assertions.NotKind(t T, expectedKind reflect.Kind, object any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotKind) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotKind](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L248) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotKind](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L256) {{% /tab %}} {{< /tabs >}} @@ -1083,7 +1083,7 @@ func main() { |--|--| | [`assertions.NotZero(t T, i any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#NotZero) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotZero](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L190) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#NotZero](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L198) {{% /tab %}} {{< /tabs >}} @@ -1194,7 +1194,7 @@ func main() { |--|--| | [`assertions.Zero(t T, i any, msgAndArgs ...any) bool`](https://pkg.go.dev/github.com/go-openapi/testify/v2/internal/assertions#Zero) | internal implementation | -**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Zero](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L168) +**Source:** [github.com/go-openapi/testify/v2/internal/assertions#Zero](https://github.com/go-openapi/testify/blob/master/internal/assertions/type.go#L176) {{% /tab %}} {{< /tabs >}} diff --git a/internal/assertions/equal.go b/internal/assertions/equal.go index 07910c5f4..223df40d7 100644 --- a/internal/assertions/equal.go +++ b/internal/assertions/equal.go @@ -378,7 +378,9 @@ func copyExportedFields(expected any) any { case reflect.Pointer: result := reflect.New(expectedType.Elem()) unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) - result.Elem().Set(reflect.ValueOf(unexportedRemoved)) + if unexportedRemoved != nil { + result.Elem().Set(reflect.ValueOf(unexportedRemoved)) + } return result.Interface() case reflect.Array, reflect.Slice: @@ -395,7 +397,9 @@ func copyExportedFields(expected any) any { panic(fmt.Errorf("internal error: can't resolve Interface() for value %v", index)) } unexportedRemoved := copyExportedFields(index.Interface()) - result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) + if unexportedRemoved != nil { + result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) + } } return result.Interface() @@ -408,7 +412,9 @@ func copyExportedFields(expected any) any { panic(fmt.Errorf("internal error: can't resolve Interface() for value %v", index)) } unexportedRemoved := copyExportedFields(index.Interface()) - result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) + if unexportedRemoved != nil { + result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) + } } return result.Interface() diff --git a/internal/testintegration/assertions/testdata/rapid/TestNilSafetyExportedValues/TestNilSafetyExportedValues-20260619051753-8674.fail b/internal/testintegration/assertions/testdata/rapid/TestNilSafetyExportedValues/TestNilSafetyExportedValues-20260619051753-8674.fail deleted file mode 100644 index 3b88bb249..000000000 --- a/internal/testintegration/assertions/testdata/rapid/TestNilSafetyExportedValues/TestNilSafetyExportedValues-20260619051753-8674.fail +++ /dev/null @@ -1,6 +0,0 @@ -# -v0.4.8#8907104496899871461 -0x38e38e38e38e4 -0x2 -0x38e38e38e38e4 -0x3 \ No newline at end of file