@@ -49,150 +49,12 @@ func ProtoEqual(expected proto.Message) types.GomegaMatcher {
4949 }
5050}
5151
52- // AllProtoEqualMatcher is a custom Gomega matcher to check if all elements in a slice match a protocol buffer
53- type AllProtoEqualMatcher struct {
54- Expected proto.Message
55- }
56-
57- func (matcher * AllProtoEqualMatcher ) Match (actual interface {}) (success bool , err error ) {
58- v := reflect .ValueOf (actual )
59- if v .Kind () != reflect .Slice {
60- return false , nil // Return false, nil for non-slice types, consistent with ProtoEqualMatcher
61- }
62-
63- for i := 0 ; i < v .Len (); i ++ {
64- elem := v .Index (i ).Interface ()
65- actualMessage , ok := elem .(proto.Message )
66- if ! ok {
67- return false , nil // Return false if an element isn’t a proto.Message
68- }
69- if ! proto .Equal (actualMessage , matcher .Expected ) {
70- return false , nil
71- }
72- }
73- return true , nil
74- }
75-
76- func (matcher * AllProtoEqualMatcher ) FailureMessage (actual interface {}) (message string ) {
77- return format .Message (actual , "to have all elements equal" , matcher .Expected )
78- }
79-
80- func (matcher * AllProtoEqualMatcher ) NegatedFailureMessage (actual interface {}) (message string ) {
81- return format .Message (actual , "not to have all elements equal" , matcher .Expected )
82- }
83-
84- // AllProtoEqual returns a Gomega matcher that checks if all elements in a slice are equal to the expected Protobuf message.
85- // It verifies that the input is a slice and that each element implements proto.Message and matches the expected message
86- // using proto.Equal. If the input is not a slice or any element does not match, the matcher fails.
87- //
88- // This matcher is useful for testing scenarios where a collection of Protobuf messages should all conform to a single
89- // expected template, ignoring order. An empty slice is considered a match (vacuously true), and non-slice inputs
90- // result in a mismatch without error.
91- //
92- // Example usage:
93- //
94- // expected := &v1.Foo{Bar: "test", Baz: "baz"}
95- // items := []*v1.Foo{{Bar: "test", Baz: "baz"}, {Bar: "test", Baz: "baz"}}
96- // Expect(items).To(AllProtoEqual(expected)) // Passes
97- // mismatched := []*v1.Foo{{Bar: "test", Baz: "baz"}, {Bar: "different", Baz: "baz"}}
98- // Expect(mismatched).ToNot(AllProtoEqual(expected)) // Passes
99- func AllProtoEqual (expected proto.Message ) types.GomegaMatcher {
100- return & AllProtoEqualMatcher {
101- Expected : expected ,
102- }
103- }
104-
105- // ProtoSliceEqualMatcher is a custom Gomega matcher to check if a slice of protocol buffers matches an expected slice
106- type ProtoSliceEqualMatcher struct {
107- Expected []proto.Message
108- }
109-
110- func (matcher * ProtoSliceEqualMatcher ) Match (actual interface {}) (success bool , err error ) {
111- v := reflect .ValueOf (actual )
112- if v .Kind () != reflect .Slice {
113- return false , nil
114- }
115-
116- if v .Len () != len (matcher .Expected ) {
117- return false , nil
118- }
119-
120- // Convert actual slice to []proto.Message
121- actualSlice := make ([]proto.Message , v .Len ())
122- for i := 0 ; i < v .Len (); i ++ {
123- elem := v .Index (i ).Interface ()
124- actualMessage , ok := elem .(proto.Message )
125- if ! ok {
126- return false , nil
127- }
128- actualSlice [i ] = actualMessage
129- }
130-
131- // Check if slices match in any order
132- return slicesMatch (actualSlice , matcher .Expected ), nil
133- }
134-
135- // slicesMatch checks if two slices contain the same elements in any order
136- func slicesMatch (actual , expected []proto.Message ) bool {
137- if len (actual ) != len (expected ) {
138- return false
139- }
140-
141- // Create a map to track matched expected elements
142- matched := make ([]bool , len (expected ))
143-
144- // For each actual element, try to find a matching expected element
145- for _ , actualMsg := range actual {
146- foundMatch := false
147- for j , expectedMsg := range expected {
148- if ! matched [j ] && proto .Equal (actualMsg , expectedMsg ) {
149- matched [j ] = true
150- foundMatch = true
151- break
152- }
153- }
154- if ! foundMatch {
155- return false
156- }
157- }
158- return true
159- }
160-
161- func (matcher * ProtoSliceEqualMatcher ) FailureMessage (actual interface {}) (message string ) {
162- return format .Message (actual , "to equal slice" , matcher .Expected )
163- }
164-
165- func (matcher * ProtoSliceEqualMatcher ) NegatedFailureMessage (actual interface {}) (message string ) {
166- return format .Message (actual , "not to equal slice" , matcher .Expected )
167- }
168-
169- // ProtoSliceEqual returns a Gomega matcher that checks if a slice of Protobuf messages matches the expected slice.
170- // It verifies that the input is a slice of proto.Message implementations and contains the same elements as the
171- // expected slice in any order, using proto.Equal for comparisons. The slices must be the same length and contain
172- // equivalent messages, but order doesn't matter.
173- //
174- // This matcher is useful for testing scenarios where a collection of Protobuf messages should match an expected
175- // set of messages regardless of their order.
176- //
177- // Example usage:
178- //
179- // expected := []proto.Message{&v1.Foo{Bar: "test"}, &v1.Foo{Bar: "baz"}}
180- // items := []proto.Message{&v1.Foo{Bar: "baz"}, &v1.Foo{Bar: "test"}}
181- // Expect(items).To(ProtoSliceEqual(expected)) // Passes
182- // mismatched := []proto.Message{&v1.Foo{Bar: "test"}, &v1.Foo{Bar: "different"}}
183- // Expect(mismatched).ToNot(ProtoSliceEqual(expected)) // Passes
184- func ProtoSliceEqual (expected []proto.Message ) types.GomegaMatcher {
185- return & ProtoSliceEqualMatcher {
186- Expected : expected ,
187- }
188- }
189-
190- // ProtoSliceContainsMatcher is a custom Gomega matcher to check if a slice of protocol buffers contains specific elements
191- type ProtoSliceContainsMatcher struct {
52+ // ProtoContainsMatcher is a custom Gomega matcher to check if a slice of protocol buffers contains specific elements
53+ type ProtoContainsMatcher struct {
19254 Elements []proto.Message
19355}
19456
195- func (matcher * ProtoSliceContainsMatcher ) Match (actual interface {}) (success bool , err error ) {
57+ func (matcher * ProtoContainsMatcher ) Match (actual interface {}) (success bool , err error ) {
19658 v := reflect .ValueOf (actual )
19759 if v .Kind () != reflect .Slice {
19860 return false , nil
@@ -225,31 +87,35 @@ func (matcher *ProtoSliceContainsMatcher) Match(actual interface{}) (success boo
22587 return true , nil
22688}
22789
228- func (matcher * ProtoSliceContainsMatcher ) FailureMessage (actual interface {}) (message string ) {
90+ func (matcher * ProtoContainsMatcher ) FailureMessage (actual interface {}) (message string ) {
22991 return format .Message (actual , "to contain elements" , matcher .Elements )
23092}
23193
232- func (matcher * ProtoSliceContainsMatcher ) NegatedFailureMessage (actual interface {}) (message string ) {
94+ func (matcher * ProtoContainsMatcher ) NegatedFailureMessage (actual interface {}) (message string ) {
23395 return format .Message (actual , "not to contain elements" , matcher .Elements )
23496}
23597
236- // ProtoSliceContains returns a Gomega matcher that checks if a slice of Protobuf messages contains all the specified elements.
237- // It verifies that the input is a slice of proto.Message implementations and that each element in the expected slice is
238- // present in the actual slice (in any order), using proto.Equal for comparisons. The actual slice may contain additional
239- // elements beyond those specified.
98+ // ProtoContains returns a Gomega matcher that checks if a slice of Protobuf messages contains all the specified elements.
99+ // It verifies that the input is a slice of proto.Message implementations and that each specified element is present in the
100+ // actual slice (in any order), using proto.Equal for comparisons. The actual slice may contain additional elements beyond
101+ // those specified.
240102//
241103// This matcher is useful for testing scenarios where you want to ensure certain Protobuf messages are present in a
242- // collection, regardless of order or additional elements.
104+ // collection, regardless of order or additional elements. It accepts variadic arguments, allowing individual elements to
105+ // be passed directly.
243106//
244107// Example usage:
245108//
246- // expected := []proto.Message{&v1.Foo{Bar: "test1"}, &v1.Foo{Bar: "test2"}}
247- // items := []proto.Message{&v1.Foo{Bar: "test1"}, &v1.Foo{Bar: "test2"}, &v1.Foo{Bar: "test3"}}
248- // Expect(items).To(ProtoSliceContains(expected)) // Passes
249- // missing := []proto.Message{&v1.Foo{Bar: "test1"}}
250- // Expect(missing).ToNot(ProtoSliceContains(expected)) // Passes
251- func ProtoSliceContains (elements ... proto.Message ) types.GomegaMatcher {
252- return & ProtoSliceContainsMatcher {
109+ // Expect(items).To(ProtoContains(
110+ // &v1.Foo{Bar: "test1"},
111+ // &v1.Foo{Bar: "test2"},
112+ // )) // Passes if items contains both elements (and possibly more)
113+ // Expect(missing).ToNot(ProtoContains(
114+ // &v1.Foo{Bar: "test1"},
115+ // &v1.Foo{Bar: "test2"},
116+ // )) // Passes if missing lacks at least one of these elements
117+ func ProtoContains (elements ... proto.Message ) types.GomegaMatcher {
118+ return & ProtoContainsMatcher {
253119 Elements : elements ,
254120 }
255121}
0 commit comments