1 package matchers_test
2
3 import (
4 "errors"
5 "time"
6
7 "github.com/google/go-cmp/cmp"
8 "github.com/google/go-cmp/cmp/cmpopts"
9
10 . "github.com/onsi/ginkgo/v2"
11 . "github.com/onsi/gomega"
12 . "github.com/onsi/gomega/matchers"
13 )
14
15 type wrapError struct {
16 msg string
17 err error
18 }
19
20 func (e wrapError) Error() string {
21 return e.msg
22 }
23
24 func (e wrapError) Unwrap() error {
25 return e.err
26 }
27
28 var _ = Describe("BeComparableTo", func() {
29 When("asserting that nil is comparable to nil", func() {
30 It("should error", func() {
31 success, err := (&BeComparableToMatcher{Expected: nil}).Match(nil)
32
33 Expect(success).Should(BeFalse())
34 Expect(err).Should(HaveOccurred())
35 })
36 })
37
38 Context("When asserting on nil", func() {
39 It("should do the right thing", func() {
40 Expect("foo").ShouldNot(BeComparableTo(nil))
41 Expect(nil).ShouldNot(BeComparableTo(3))
42 Expect([]int{1, 2}).ShouldNot(BeComparableTo(nil))
43 })
44 })
45
46 Context("When asserting time with different location ", func() {
47 var t1, t2, t3 time.Time
48
49 BeforeEach(func() {
50 t1 = time.Time{}
51 t2 = time.Time{}.Local()
52 t3 = t1.Add(time.Second)
53 })
54
55 It("should do the right thing", func() {
56 Expect(t1).Should(BeComparableTo(t2))
57 Expect(t1).ShouldNot(BeComparableTo(t3))
58 })
59 })
60
61 Context("When struct contain unexported fields", func() {
62 type structWithUnexportedFields struct {
63 unexported string
64 Exported string
65 }
66
67 var s1, s2 structWithUnexportedFields
68
69 BeforeEach(func() {
70 s1 = structWithUnexportedFields{unexported: "unexported", Exported: "Exported"}
71 s2 = structWithUnexportedFields{unexported: "unexported", Exported: "Exported"}
72 })
73
74 It("should get match err", func() {
75 success, err := (&BeComparableToMatcher{Expected: s1}).Match(s2)
76 Expect(success).Should(BeFalse())
77 Expect(err).Should(HaveOccurred())
78 })
79
80 It("should do the right thing", func() {
81 Expect(s1).Should(BeComparableTo(s2, cmpopts.IgnoreUnexported(structWithUnexportedFields{})))
82 })
83 })
84
85 Context("When compare error", func() {
86 var err1, err2 error
87
88 It("not equal", func() {
89 err1 = errors.New("error")
90 err2 = errors.New("error")
91 Expect(err1).ShouldNot(BeComparableTo(err2, cmpopts.EquateErrors()))
92 })
93
94 It("equal if err1 is err2", func() {
95 err1 = errors.New("error")
96 err2 = &wrapError{
97 msg: "some error",
98 err: err1,
99 }
100
101 Expect(err1).Should(BeComparableTo(err2, cmpopts.EquateErrors()))
102 })
103 })
104
105 Context("When asserting equal between objects", func() {
106 Context("with no additional cmp.Options", func() {
107 It("should do the right thing", func() {
108 Expect(5).Should(BeComparableTo(5))
109 Expect(5.0).Should(BeComparableTo(5.0))
110
111 Expect(5).ShouldNot(BeComparableTo("5"))
112 Expect(5).ShouldNot(BeComparableTo(5.0))
113 Expect(5).ShouldNot(BeComparableTo(3))
114
115 Expect("5").Should(BeComparableTo("5"))
116 Expect([]int{1, 2}).Should(BeComparableTo([]int{1, 2}))
117 Expect([]int{1, 2}).ShouldNot(BeComparableTo([]int{2, 1}))
118 Expect([]byte{'f', 'o', 'o'}).Should(BeComparableTo([]byte{'f', 'o', 'o'}))
119 Expect([]byte{'f', 'o', 'o'}).ShouldNot(BeComparableTo([]byte{'b', 'a', 'r'}))
120 Expect(map[string]string{"a": "b", "c": "d"}).Should(BeComparableTo(map[string]string{"a": "b", "c": "d"}))
121 Expect(map[string]string{"a": "b", "c": "d"}).ShouldNot(BeComparableTo(map[string]string{"a": "b", "c": "e"}))
122 })
123 })
124
125 Context("with custom cmp.Options", func() {
126 It("should do the right thing", func() {
127 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{})))
128
129 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{})))
130 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{})))
131 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{})))
132 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{})))
133 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{})))
134 })
135
136 type structWithUnexportedFields struct {
137 unexported string
138 Exported string
139 }
140
141 It("should produce failure message according to passed cmp.Option", func() {
142 actual := structWithUnexportedFields{unexported: "xxx", Exported: "exported field value"}
143 expectedEqual := structWithUnexportedFields{unexported: "yyy", Exported: "exported field value"}
144 matcherWithEqual := BeComparableTo(expectedEqual, cmpopts.IgnoreUnexported(structWithUnexportedFields{}))
145
146 Expect(matcherWithEqual.FailureMessage(actual)).To(BeEquivalentTo("Expected object to be comparable, diff: "))
147
148 expectedDiffernt := structWithUnexportedFields{unexported: "xxx", Exported: "other value"}
149 matcherWithDifference := BeComparableTo(expectedDiffernt, cmpopts.IgnoreUnexported(structWithUnexportedFields{}))
150 Expect(matcherWithDifference.FailureMessage(actual)).To(ContainSubstring("1 ignored field"))
151 Expect(matcherWithDifference.FailureMessage(actual)).To(ContainSubstring("Exported: \"other value\""))
152 Expect(matcherWithDifference.FailureMessage(actual)).To(ContainSubstring("Exported: \"exported field value\""))
153 })
154 })
155 })
156 })
157
View as plain text