diff --git a/matchers.go b/matchers.go index 6a17bbddc..82e5ebb98 100644 --- a/matchers.go +++ b/matchers.go @@ -27,10 +27,10 @@ func BeEquivalentTo(expected interface{}) types.GomegaMatcher { } } -//Compare uses gocmp.Equal to compare. You can pass cmp.Option as options. +//BeComparableTo uses gocmp.Equal to compare. You can pass cmp.Option as options. //It is an error for actual and expected to be nil. Use BeNil() instead. -func Compare(expected interface{}, opts ...cmp.Option) types.GomegaMatcher { - return &matchers.CompareMatcher{ +func BeComparableTo(expected interface{}, opts ...cmp.Option) types.GomegaMatcher { + return &matchers.BeComparableToMatcher{ Expected: expected, Options: opts, } diff --git a/matchers/compare_matcher.go b/matchers/be_comparable_to_matcher.go similarity index 79% rename from matchers/compare_matcher.go rename to matchers/be_comparable_to_matcher.go index b180ee416..2205d8c23 100644 --- a/matchers/compare_matcher.go +++ b/matchers/be_comparable_to_matcher.go @@ -7,12 +7,12 @@ import ( "github.com/onsi/gomega/format" ) -type CompareMatcher struct { +type BeComparableToMatcher struct { Expected interface{} Options cmp.Options } -func (matcher *CompareMatcher) Match(actual interface{}) (success bool, matchErr error) { +func (matcher *BeComparableToMatcher) Match(actual interface{}) (success bool, matchErr error) { if actual == nil && matcher.Expected == nil { return false, fmt.Errorf("Refusing to compare to .\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.") } @@ -39,10 +39,10 @@ func (matcher *CompareMatcher) Match(actual interface{}) (success bool, matchErr return cmp.Equal(actual, matcher.Expected, matcher.Options...), nil } -func (matcher *CompareMatcher) FailureMessage(actual interface{}) (message string) { +func (matcher *BeComparableToMatcher) FailureMessage(actual interface{}) (message string) { return cmp.Diff(matcher.Expected, actual) } -func (matcher *CompareMatcher) NegatedFailureMessage(actual interface{}) (message string) { +func (matcher *BeComparableToMatcher) NegatedFailureMessage(actual interface{}) (message string) { return format.Message(actual, "not to equal", matcher.Expected) } diff --git a/matchers/be_comparable_to_matcher_test.go b/matchers/be_comparable_to_matcher_test.go new file mode 100644 index 000000000..083d3c609 --- /dev/null +++ b/matchers/be_comparable_to_matcher_test.go @@ -0,0 +1,130 @@ +package matchers_test + +import ( + "errors" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/matchers" +) + +type wrapError struct { + msg string + err error +} + +func (e wrapError) Error() string { + return e.msg +} + +func (e wrapError) Unwrap() error { + return e.err +} + +var _ = Describe("BeComparableTo", func() { + When("asserting that nil is comparable to nil", func() { + It("should error", func() { + success, err := (&BeComparableToMatcher{Expected: nil}).Match(nil) + + Expect(success).Should(BeFalse()) + Expect(err).Should(HaveOccurred()) + }) + }) + + Context("When asserting on nil", func() { + It("should do the right thing", func() { + Expect("foo").ShouldNot(BeComparableTo(nil)) + Expect(nil).ShouldNot(BeComparableTo(3)) + Expect([]int{1, 2}).ShouldNot(BeComparableTo(nil)) + }) + }) + + Context("When asserting time with different location ", func() { + var t1, t2, t3 time.Time + + BeforeEach(func() { + t1 = time.Time{} + t2 = time.Time{}.Local() + t3 = t1.Add(time.Second) + }) + + It("should do the right thing", func() { + Expect(t1).Should(BeComparableTo(t2)) + Expect(t1).ShouldNot(BeComparableTo(t3)) + }) + }) + + Context("When struct contain unexported fields", func() { + type structWithUnexportedFields struct { + unexported string + Exported string + } + + var s1, s2 structWithUnexportedFields + + BeforeEach(func() { + s1 = structWithUnexportedFields{unexported: "unexported", Exported: "Exported"} + s2 = structWithUnexportedFields{unexported: "unexported", Exported: "Exported"} + }) + + It("should get match err", func() { + success, err := (&BeComparableToMatcher{Expected: s1}).Match(s2) + Expect(success).Should(BeFalse()) + Expect(err).Should(HaveOccurred()) + }) + + It("should do the right thing", func() { + Expect(s1).Should(BeComparableTo(s2, cmpopts.IgnoreUnexported(structWithUnexportedFields{}))) + }) + }) + + Context("When compare error", func() { + var err1, err2 error + + It("not equal", func() { + err1 = errors.New("error") + err2 = errors.New("error") + Expect(err1).ShouldNot(BeComparableTo(err2, cmpopts.EquateErrors())) + }) + + It("equal if err1 is err2", func() { + err1 = errors.New("error") + err2 = &wrapError{ + msg: "some error", + err: err1, + } + + Expect(err1).Should(BeComparableTo(err2, cmpopts.EquateErrors())) + }) + }) + + Context("When asserting equal between objects", func() { + It("should do the right thing", func() { + Expect(5).Should(BeComparableTo(5)) + Expect(5.0).Should(BeComparableTo(5.0)) + + Expect(5).ShouldNot(BeComparableTo("5")) + Expect(5).ShouldNot(BeComparableTo(5.0)) + Expect(5).ShouldNot(BeComparableTo(3)) + + Expect("5").Should(BeComparableTo("5")) + Expect([]int{1, 2}).Should(BeComparableTo([]int{1, 2})) + Expect([]int{1, 2}).ShouldNot(BeComparableTo([]int{2, 1})) + Expect([]byte{'f', 'o', 'o'}).Should(BeComparableTo([]byte{'f', 'o', 'o'})) + Expect([]byte{'f', 'o', 'o'}).ShouldNot(BeComparableTo([]byte{'b', 'a', 'r'})) + Expect(map[string]string{"a": "b", "c": "d"}).Should(BeComparableTo(map[string]string{"a": "b", "c": "d"})) + Expect(map[string]string{"a": "b", "c": "d"}).ShouldNot(BeComparableTo(map[string]string{"a": "b", "c": "e"})) + + Expect(myCustomType{s: "abc", n: 3, f: 2.0, arr: []string{"a", "b"}}).Should(BeComparableTo(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}, cmpopts.IgnoreUnexported(myCustomType{}))) + + Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).Should(BeComparableTo(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) + Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(BeComparableTo(myCustomType{s: "bar", n: 3, f: 2.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) + Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(BeComparableTo(myCustomType{s: "foo", n: 2, f: 2.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) + Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(BeComparableTo(myCustomType{s: "foo", n: 3, f: 3.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) + Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(BeComparableTo(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b", "c"}}, cmp.AllowUnexported(myCustomType{}))) + }) + }) +}) diff --git a/matchers/compare_matcher_test.go b/matchers/compare_matcher_test.go deleted file mode 100644 index 1bc30b7b0..000000000 --- a/matchers/compare_matcher_test.go +++ /dev/null @@ -1,130 +0,0 @@ -package matchers_test - -import ( - "errors" - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "time" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - . "github.com/onsi/gomega/matchers" -) - -type wrapError struct { - msg string - err error -} - -func (e wrapError) Error() string { - return e.msg -} - -func (e wrapError) Unwrap() error { - return e.err -} - -var _ = Describe("Compare", func() { - When("asserting that nil compare equal nil", func() { - It("should error", func() { - success, err := (&CompareMatcher{Expected: nil}).Match(nil) - - Expect(success).Should(BeFalse()) - Expect(err).Should(HaveOccurred()) - }) - }) - - Context("When asserting on nil", func() { - It("should do the right thing", func() { - Expect("foo").ShouldNot(Compare(nil)) - Expect(nil).ShouldNot(Compare(3)) - Expect([]int{1, 2}).ShouldNot(Compare(nil)) - }) - }) - - Context("When asserting time with different location ", func() { - var t1, t2, t3 time.Time - - BeforeEach(func() { - t1 = time.Time{} - t2 = time.Time{}.Local() - t3 = t1.Add(time.Second) - }) - - It("should do the right thing", func() { - Expect(t1).Should(Compare(t2)) - Expect(t1).ShouldNot(Compare(t3)) - }) - }) - - Context("When struct contain unexported fields", func() { - type structWithUnexportedFields struct { - unexported string - Exported string - } - - var s1, s2 structWithUnexportedFields - - BeforeEach(func() { - s1 = structWithUnexportedFields{unexported: "unexported", Exported: "Exported"} - s2 = structWithUnexportedFields{unexported: "unexported", Exported: "Exported"} - }) - - It("should get match err", func() { - success, err := (&CompareMatcher{Expected: s1}).Match(s2) - Expect(success).Should(BeFalse()) - Expect(err).Should(HaveOccurred()) - }) - - It("should do the right thing", func() { - Expect(s1).Should(Compare(s2, cmpopts.IgnoreUnexported(structWithUnexportedFields{}))) - }) - }) - - Context("When compare error", func() { - var err1, err2 error - - It("not equal", func() { - err1 = errors.New("error") - err2 = errors.New("error") - Expect(err1).ShouldNot(Compare(err2, cmpopts.EquateErrors())) - }) - - It("equal if err1 is err2", func() { - err1 = errors.New("error") - err2 = &wrapError{ - msg: "some error", - err: err1, - } - - Expect(err1).Should(Compare(err2, cmpopts.EquateErrors())) - }) - }) - - Context("When asserting equal between objects", func() { - It("should do the right thing", func() { - Expect(5).Should(Compare(5)) - Expect(5.0).Should(Compare(5.0)) - - Expect(5).ShouldNot(Compare("5")) - Expect(5).ShouldNot(Compare(5.0)) - Expect(5).ShouldNot(Compare(3)) - - Expect("5").Should(Compare("5")) - Expect([]int{1, 2}).Should(Compare([]int{1, 2})) - Expect([]int{1, 2}).ShouldNot(Compare([]int{2, 1})) - Expect([]byte{'f', 'o', 'o'}).Should(Compare([]byte{'f', 'o', 'o'})) - Expect([]byte{'f', 'o', 'o'}).ShouldNot(Compare([]byte{'b', 'a', 'r'})) - Expect(map[string]string{"a": "b", "c": "d"}).Should(Compare(map[string]string{"a": "b", "c": "d"})) - Expect(map[string]string{"a": "b", "c": "d"}).ShouldNot(Compare(map[string]string{"a": "b", "c": "e"})) - - Expect(myCustomType{s: "abc", n: 3, f: 2.0, arr: []string{"a", "b"}}).Should(Compare(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}, cmpopts.IgnoreUnexported(myCustomType{}))) - - Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).Should(Compare(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) - Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Compare(myCustomType{s: "bar", n: 3, f: 2.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) - Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Compare(myCustomType{s: "foo", n: 2, f: 2.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) - Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Compare(myCustomType{s: "foo", n: 3, f: 3.0, arr: []string{"a", "b"}}, cmp.AllowUnexported(myCustomType{}))) - Expect(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Compare(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b", "c"}}, cmp.AllowUnexported(myCustomType{}))) - }) - }) -})