diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index b2b5d29..c4b41d8 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -16,9 +16,9 @@ jobs: fail-fast: false matrix: go: - - '1.19' - - '1.18' - - '1.17' + - '1.22' + - '1.21' + - '1.20' steps: - uses: actions/checkout@v3 diff --git a/CHANGES.md b/CHANGES.md index 98f8c18..163d6d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,14 +1,25 @@ # go-test/deep Changelog +## v1.1.1 released 2024-06-23 + +* Added `NilPointersAreZero` option: causes a nil pointer to be equal to a zero value (PR #61) (@seveas) +* Updated test matrix to go1.22, go1.21, and go1.20 + +## v1.1.0 released 2022-12-09 + +* Add optional flags: `Equal(a, b, flags..)` and `FLAG_IGNORE_SLICE_ORDER` (issue #28, PR #56) (@alenkacz) + +--- + ## v1.0.9 released 2022-12-09 * Fixed issue #45: Panic when comparing errors in unexported fields (PR #54) (@seveas) * Fixed issue #46: Functions are handled differently from reflect.DeepEqual (PR #55) (@countcb) -* Updated matrix to go1.17, go1.18, and go1.19 and moved testing to GitHub Actions +* Updated test matrix to go1.17, go1.18, and go1.19 and moved testing to GitHub Actions ## v1.0.8 released 2021-10-13 -* Updated matrix to go1.15, go1.16, and go1.17 +* Updated test matrix to go1.15, go1.16, and go1.17 * Added SECURITY.md and GitHub code analysis ## v1.0.7 released 2020-07-11 diff --git a/SECURITY.md b/SECURITY.md index 845584a..d007137 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,8 @@ For security patches, the latest release is supported: | Version | Supported | | ------- | ------------------ | -| 1.0.x | :white_check_mark: | +| 1.1.x | Yes | +| 1.0.x | No | ## Reporting a Vulnerability diff --git a/deep.go b/deep.go index 4aab66a..4be3e1f 100644 --- a/deep.go +++ b/deep.go @@ -43,6 +43,9 @@ var ( // NilMapsAreEmpty causes a nil map to be equal to an empty map. NilMapsAreEmpty = false + + // NilPointersAreZero causes a nil pointer to be equal to a zero value. + NilPointersAreZero = false ) var ( @@ -190,6 +193,12 @@ func (c *cmp) equals(a, b reflect.Value, level int) { if bElem { b = b.Elem() } + if aElem && NilPointersAreZero && !a.IsValid() && b.IsValid() { + a = reflect.Zero(b.Type()) + } + if bElem && NilPointersAreZero && !b.IsValid() && a.IsValid() { + b = reflect.Zero(a.Type()) + } c.equals(a, b, level+1) return } diff --git a/deep_test.go b/deep_test.go index bcb7d5a..74377e1 100644 --- a/deep_test.go +++ b/deep_test.go @@ -957,9 +957,9 @@ func TestNilSlicesAreEmpty(t *testing.T) { } func TestNilMapsAreEmpty(t *testing.T) { - defaultNilMapsAreEmpty := deep.NilSlicesAreEmpty + defaultNilMapsAreEmpty := deep.NilMapsAreEmpty deep.NilMapsAreEmpty = true - defer func() { deep.NilSlicesAreEmpty = defaultNilMapsAreEmpty }() + defer func() { deep.NilMapsAreEmpty = defaultNilMapsAreEmpty }() a := map[int]int{1: 1} b := map[int]int{} @@ -1581,3 +1581,35 @@ func TestSliceOrderStruct(t *testing.T) { t.Fatalf("expected 0 diff, got %d: %s", len(diff), diff) } } + +func TestNilPointersAreZero(t *testing.T) { + defaultNilPointersAreZero := deep.NilPointersAreZero + deep.NilPointersAreZero = true + defer func() { deep.NilPointersAreZero = defaultNilPointersAreZero }() + + type T struct { + S *string + } + + a := T{S: nil} + b := T{S: new(string)} + + diff := deep.Equal(a, b) + if len(diff) != 0 { + t.Fatalf("expected 0 diff, got %d: %s", len(diff), diff) + } + + *b.S = "hello" + diff = deep.Equal(a, b) + if len(diff) != 1 { + t.Fatalf("expected 1 diff, got %d: %s", len(diff), diff) + } + + a.S = new(string) + *a.S = "hi again" + b.S = nil + diff = deep.Equal(a, b) + if len(diff) != 1 { + t.Fatalf("expected 1 diff, got %d: %s", len(diff), diff) + } +}