@@ -3,11 +3,14 @@ package kafka
33import (
44 "context"
55 "fmt"
6+ "net"
67 "os"
78 "reflect"
89 "sort"
910 "testing"
1011 "time"
12+
13+ "github.com/segmentio/kafka-go/protocol/describegroups"
1114)
1215
1316func TestClientDescribeGroups (t * testing.T ) {
@@ -128,3 +131,242 @@ func TestClientDescribeGroups(t *testing.T) {
128131 )
129132 }
130133}
134+
135+ // mockRoundTripper is a mock transport that returns a fixed response.
136+ type mockRoundTripper struct {
137+ response Response
138+ err error
139+ }
140+
141+ func (m * mockRoundTripper ) RoundTrip (ctx context.Context , addr net.Addr , req Request ) (Response , error ) {
142+ if m .err != nil {
143+ return nil , m .err
144+ }
145+ return m .response , nil
146+ }
147+
148+ func TestDescribeGroupsErrorHandling (t * testing.T ) {
149+ // This test verifies that when one group has invalid metadata/assignments,
150+ // it doesn't prevent other groups from being returned successfully.
151+
152+ // Create a mock response with multiple groups where one has invalid data.
153+ mockResp := & describegroups.Response {
154+ Groups : []describegroups.ResponseGroup {
155+ {
156+ ErrorCode : 0 ,
157+ GroupID : "valid-group-1" ,
158+ GroupState : "Stable" ,
159+ ProtocolType : "consumer" ,
160+ Members : []describegroups.ResponseGroupMember {
161+ {
162+ MemberID : "member-1" ,
163+ ClientID : "client-1" ,
164+ ClientHost : "/127.0.0.1" ,
165+ // Valid metadata: version (int16) = 0, topics array length (int32) = 0, userdata length (int32) = 0
166+ MemberMetadata : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
167+ // Valid assignments: version (int16) = 0, topics array length (int32) = 0, userdata length (int32) = 0
168+ MemberAssignment : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
169+ },
170+ },
171+ },
172+ {
173+ ErrorCode : 0 ,
174+ GroupID : "invalid-group" ,
175+ GroupState : "Stable" ,
176+ ProtocolType : "consumer" ,
177+ Members : []describegroups.ResponseGroupMember {
178+ {
179+ MemberID : "member-2" ,
180+ ClientID : "client-2" ,
181+ ClientHost : "/127.0.0.1" ,
182+ // Invalid metadata - truncated data
183+ MemberMetadata : []byte {0x00 },
184+ MemberAssignment : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
185+ },
186+ },
187+ },
188+ {
189+ ErrorCode : 0 ,
190+ GroupID : "valid-group-2" ,
191+ GroupState : "Stable" ,
192+ ProtocolType : "consumer" ,
193+ Members : []describegroups.ResponseGroupMember {
194+ {
195+ MemberID : "member-3" ,
196+ ClientID : "client-3" ,
197+ ClientHost : "/127.0.0.1" ,
198+ // Valid metadata
199+ MemberMetadata : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
200+ // Valid assignments
201+ MemberAssignment : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
202+ },
203+ },
204+ },
205+ },
206+ }
207+
208+ client := & Client {
209+ Transport : & mockRoundTripper {response : mockResp },
210+ }
211+
212+ ctx := context .Background ()
213+ resp , err := client .DescribeGroups (ctx , & DescribeGroupsRequest {
214+ Addr : TCP ("localhost:9092" ),
215+ GroupIDs : []string {"valid-group-1" , "invalid-group" , "valid-group-2" },
216+ })
217+
218+ if err != nil {
219+ t .Fatalf ("Unexpected error from DescribeGroups: %v" , err )
220+ }
221+
222+ if len (resp .Groups ) != 3 {
223+ t .Fatalf ("Expected 3 groups, got %d" , len (resp .Groups ))
224+ }
225+
226+ // Verify valid-group-1 has no error and has members
227+ if resp .Groups [0 ].GroupID != "valid-group-1" {
228+ t .Errorf ("Expected first group to be valid-group-1, got %s" , resp .Groups [0 ].GroupID )
229+ }
230+ if resp .Groups [0 ].Error != nil {
231+ t .Errorf ("Expected valid-group-1 to have no error, got %v" , resp .Groups [0 ].Error )
232+ }
233+ if len (resp .Groups [0 ].Members ) != 1 {
234+ t .Errorf ("Expected valid-group-1 to have 1 member, got %d" , len (resp .Groups [0 ].Members ))
235+ }
236+
237+ // Verify invalid-group has an error and no members
238+ if resp .Groups [1 ].GroupID != "invalid-group" {
239+ t .Errorf ("Expected second group to be invalid-group, got %s" , resp .Groups [1 ].GroupID )
240+ }
241+ if resp .Groups [1 ].Error == nil {
242+ t .Error ("Expected invalid-group to have an error, got nil" )
243+ }
244+ if len (resp .Groups [1 ].Members ) != 0 {
245+ t .Errorf ("Expected invalid-group to have 0 members due to error, got %d" , len (resp .Groups [1 ].Members ))
246+ }
247+
248+ // Verify valid-group-2 has no error and has members
249+ if resp .Groups [2 ].GroupID != "valid-group-2" {
250+ t .Errorf ("Expected third group to be valid-group-2, got %s" , resp .Groups [2 ].GroupID )
251+ }
252+ if resp .Groups [2 ].Error != nil {
253+ t .Errorf ("Expected valid-group-2 to have no error, got %v" , resp .Groups [2 ].Error )
254+ }
255+ if len (resp .Groups [2 ].Members ) != 1 {
256+ t .Errorf ("Expected valid-group-2 to have 1 member, got %d" , len (resp .Groups [2 ].Members ))
257+ }
258+ }
259+
260+ func TestDescribeGroupsInvalidAssignments (t * testing.T ) {
261+ // Test the case where assignments are invalid but metadata is valid
262+ mockResp := & describegroups.Response {
263+ Groups : []describegroups.ResponseGroup {
264+ {
265+ ErrorCode : 0 ,
266+ GroupID : "group-with-bad-assignments" ,
267+ GroupState : "Stable" ,
268+ ProtocolType : "consumer" ,
269+ Members : []describegroups.ResponseGroupMember {
270+ {
271+ MemberID : "member-1" ,
272+ ClientID : "client-1" ,
273+ ClientHost : "/127.0.0.1" ,
274+ // Valid metadata
275+ MemberMetadata : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
276+ // Invalid assignments - truncated
277+ MemberAssignment : []byte {0x00 },
278+ },
279+ },
280+ },
281+ },
282+ }
283+
284+ client := & Client {
285+ Transport : & mockRoundTripper {response : mockResp },
286+ }
287+
288+ ctx := context .Background ()
289+ resp , err := client .DescribeGroups (ctx , & DescribeGroupsRequest {
290+ Addr : TCP ("localhost:9092" ),
291+ GroupIDs : []string {"group-with-bad-assignments" },
292+ })
293+
294+ if err != nil {
295+ t .Fatalf ("Unexpected error from DescribeGroups: %v" , err )
296+ }
297+
298+ // Verify we got the group back with an error
299+ if len (resp .Groups ) != 1 {
300+ t .Fatalf ("Expected 1 group, got %d" , len (resp .Groups ))
301+ }
302+
303+ if resp .Groups [0 ].Error == nil {
304+ t .Error ("Expected group to have an error for invalid assignments, got nil" )
305+ }
306+
307+ if len (resp .Groups [0 ].Members ) != 0 {
308+ t .Errorf ("Expected group to have 0 members due to error, got %d" , len (resp .Groups [0 ].Members ))
309+ }
310+ }
311+
312+ func TestDescribeGroupsPartialMembersCleared (t * testing.T ) {
313+ mockResp := & describegroups.Response {
314+ Groups : []describegroups.ResponseGroup {
315+ {
316+ ErrorCode : 0 ,
317+ GroupID : "multi-member-group" ,
318+ GroupState : "Stable" ,
319+ ProtocolType : "consumer" ,
320+ Members : []describegroups.ResponseGroupMember {
321+ {
322+ MemberID : "member-1" , // valid
323+ ClientID : "client-1" ,
324+ ClientHost : "/127.0.0.1" ,
325+ MemberMetadata : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
326+ MemberAssignment : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
327+ },
328+ {
329+ MemberID : "member-2" , // invalid
330+ ClientID : "client-2" ,
331+ ClientHost : "/127.0.0.1" ,
332+ MemberMetadata : []byte {0x00 },
333+ MemberAssignment : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
334+ },
335+ {
336+ MemberID : "member-3" , // valid, but never processed
337+ ClientID : "client-3" ,
338+ ClientHost : "/127.0.0.1" ,
339+ MemberMetadata : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
340+ MemberAssignment : []byte {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
341+ },
342+ },
343+ },
344+ },
345+ }
346+
347+ client := & Client {
348+ Transport : & mockRoundTripper {response : mockResp },
349+ }
350+
351+ ctx := context .Background ()
352+ resp , err := client .DescribeGroups (ctx , & DescribeGroupsRequest {
353+ Addr : TCP ("localhost:9092" ),
354+ GroupIDs : []string {"multi-member-group" },
355+ })
356+
357+ if err != nil {
358+ t .Fatalf ("Unexpected error from DescribeGroups: %v" , err )
359+ }
360+
361+ if len (resp .Groups ) != 1 {
362+ t .Fatalf ("Expected 1 group, got %d" , len (resp .Groups ))
363+ }
364+
365+ group := resp .Groups [0 ]
366+ if group .Error == nil {
367+ t .Fatal ("Expected group to have an error, got nil" )
368+ }
369+ if len (group .Members ) != 0 {
370+ t .Errorf ("Expected 0 members when error occurs, got %d" , len (group .Members ))
371+ }
372+ }
0 commit comments