From 6420365fcfc49d21a545d1c80f6c67dc2baf3dc9 Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Thu, 8 Dec 2022 11:59:28 -0500 Subject: [PATCH 1/3] Add CompareFunctions (issue 46) --- deep.go | 20 +++++++++++++++++- deep_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/deep.go b/deep.go index 3e6636c..2399b74 100644 --- a/deep.go +++ b/deep.go @@ -32,6 +32,12 @@ var ( // fields cannot be called. CompareUnexportedFields = false + // CompareFunctions compares functions the same as reflect.DeepEqual: + // only two nil functions are equal. Every other combination is not equal. + // This is disabled by default because previous versions of this package + // ignored functions. Enabling it can possibly report new diffs. + CompareFunctions = false + // NilSlicesAreEmpty causes a nil slice to be equal to an empty slice. NilSlicesAreEmpty = false @@ -392,7 +398,19 @@ func (c *cmp) equals(a, b reflect.Value, level int) { if a.String() != b.String() { c.saveDiff(a.String(), b.String()) } - + case reflect.Func: + if CompareFunctions { + if !a.IsNil() || !b.IsNil() { + aVal, bVal := "nil func", "nil func" + if !a.IsNil() { + aVal = "func" + } + if !b.IsNil() { + bVal = "func" + } + c.saveDiff(aVal, bVal) + } + } default: logError(ErrNotHandled) } diff --git a/deep_test.go b/deep_test.go index 98fba1f..d1612cd 100644 --- a/deep_test.go +++ b/deep_test.go @@ -310,15 +310,6 @@ func TestMaxDiff(t *testing.T) { } } -func TestNotHandled(t *testing.T) { - a := func(int) {} - b := func(int) {} - diff := deep.Equal(a, b) - if len(diff) > 0 { - t.Error("got diffs:", diff) - } -} - func TestStruct(t *testing.T) { type s1 struct { id int @@ -1437,3 +1428,54 @@ func TestNil(t *testing.T) { t.Error("Nil value to comparison should not be equal") } } + +var testFunc = func() {} + +func TestFunc(t *testing.T) { + // https://github.com/go-test/deep/issues/46 + type TestStruct struct { + Function func() + } + t1 := TestStruct{ + Function: testFunc, + } + t2 := TestStruct{ + Function: testFunc, + } + + // CompareFunctions is off by default, so this should report no diff: + diff := deep.Equal(t1, t2) + if len(diff) != 0 { + t.Fatalf("expected 0 diff when CompareFunctions=false, got %d: %s", len(diff), diff) + } + + deep.CompareFunctions = true + defer func() { deep.CompareFunctions = false }() + + // Two funcs are not equal (even if they're the same func) + diff = deep.Equal(t1, t2) + if len(diff) != 1 { + t.Fatalf("expected 1 diff, got %d: %s", len(diff), diff) + } + if diff[0] != "Function: func != func" { + t.Errorf("got '%s', expected 'Function: func != func'", diff[0]) + } + + // One func nil, the other set: not equal + t1.Function = nil + diff = deep.Equal(t1, t2) + if len(diff) != 1 { + t.Fatalf("expected 1 diff, got %d: %s", len(diff), diff) + } + if diff[0] != "Function: nil func != func" { + t.Errorf("got '%s', expected 'Function: nil func != func'", diff[0]) + } + + // Two nil funcs are equal + t1.Function = nil + t2.Function = nil + diff = deep.Equal(t1, t2) + if len(diff) != 0 { + t.Errorf("expected 0 diff, got %d: %s", len(diff), diff) + } +} From 847b0437a20bca7be9dd4f473d0119e70b9cfe30 Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Thu, 8 Dec 2022 12:05:35 -0500 Subject: [PATCH 2/3] Add back TestNotHandled for 100% coverage --- deep_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/deep_test.go b/deep_test.go index d1612cd..6fe81bb 100644 --- a/deep_test.go +++ b/deep_test.go @@ -310,6 +310,17 @@ func TestMaxDiff(t *testing.T) { } } +func TestNotHandled(t *testing.T) { + // UnsafePointer is pretty much the only kind not handled now + v := []int{1} + a := reflect.ValueOf(v).UnsafePointer() + b := reflect.ValueOf(v).UnsafePointer() + diff := deep.Equal(a, b) + if len(diff) > 0 { + t.Error("got diffs:", diff) + } +} + func TestStruct(t *testing.T) { type s1 struct { id int From d97d7b6c4d00c752db4ffb890c31ee3ced3957c9 Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Thu, 8 Dec 2022 12:10:50 -0500 Subject: [PATCH 3/3] Make TestNotHandled work with Go 1.17 --- deep_test.go | 9 +++++++-- test/coverage | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100755 test/coverage diff --git a/deep_test.go b/deep_test.go index 6fe81bb..055a230 100644 --- a/deep_test.go +++ b/deep_test.go @@ -6,6 +6,7 @@ import ( "reflect" "testing" "time" + "unsafe" "github.com/go-test/deep" v1 "github.com/go-test/deep/test/v1" @@ -313,8 +314,12 @@ func TestMaxDiff(t *testing.T) { func TestNotHandled(t *testing.T) { // UnsafePointer is pretty much the only kind not handled now v := []int{1} - a := reflect.ValueOf(v).UnsafePointer() - b := reflect.ValueOf(v).UnsafePointer() + a := unsafe.Pointer(&v) + b := unsafe.Pointer(&v) + // UnsafePointer added in Go 1.88. Use these lines once this pkg + // no longer supports Go 1.17. + //a := reflect.ValueOf(v).UnsafePointer() + //b := reflect.ValueOf(v).UnsafePointer() diff := deep.Equal(a, b) if len(diff) > 0 { t.Error("got diffs:", diff) diff --git a/test/coverage b/test/coverage new file mode 100755 index 0000000..e328944 --- /dev/null +++ b/test/coverage @@ -0,0 +1,3 @@ +#!/bin/sh +go test -coverprofile=coverage.out "$@" +go tool cover -html=coverage.out