1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
package protocol
import (
"encoding/binary"
"testing"
)
// This file demonstrates what FIELD-LEVEL testing would look like
// Currently these tests are NOT run automatically because they require
// complex parsing logic for each API.
// TestJoinGroupResponseStructure shows what we SHOULD test but currently don't
func TestJoinGroupResponseStructure(t *testing.T) {
t.Skip("This is a demonstration test - shows what we SHOULD check")
// Hypothetical: build a JoinGroup response
// response := buildJoinGroupResponseV6(correlationID, generationID, protocolType, ...)
// What we SHOULD verify:
t.Log("Field-level checks we should perform:")
t.Log(" 1. Error code (int16) - always present")
t.Log(" 2. Generation ID (int32) - always present")
t.Log(" 3. Protocol type (string/compact string) - nullable in some versions")
t.Log(" 4. Protocol name (string/compact string) - always present")
t.Log(" 5. Leader (string/compact string) - always present")
t.Log(" 6. Member ID (string/compact string) - always present")
t.Log(" 7. Members array - NON-NULLABLE, can be empty but must exist")
t.Log(" ^-- THIS is where the current bug is!")
// Example of what parsing would look like:
// offset := 0
// errorCode := binary.BigEndian.Uint16(response[offset:])
// offset += 2
// generationID := binary.BigEndian.Uint32(response[offset:])
// offset += 4
// ... parse protocol type ...
// ... parse protocol name ...
// ... parse leader ...
// ... parse member ID ...
// membersLength := parseCompactArray(response[offset:])
// if membersLength < 0 {
// t.Error("Members array is null, but it should be non-nullable!")
// }
}
// TestProduceResponseStructure shows another example
func TestProduceResponseStructure(t *testing.T) {
t.Skip("This is a demonstration test - shows what we SHOULD check")
t.Log("Produce response v7 structure:")
t.Log(" 1. Topics array - must not be null")
t.Log(" - Topic name (string)")
t.Log(" - Partitions array - must not be null")
t.Log(" - Partition ID (int32)")
t.Log(" - Error code (int16)")
t.Log(" - Base offset (int64)")
t.Log(" - Log append time (int64)")
t.Log(" - Log start offset (int64)")
t.Log(" 2. Throttle time (int32) - v1+")
}
// CompareWithReferenceImplementation shows ideal testing approach
func TestCompareWithReferenceImplementation(t *testing.T) {
t.Skip("This would require a reference Kafka broker or client library")
// Ideal approach:
t.Log("1. Generate test data")
t.Log("2. Build response with our Gateway")
t.Log("3. Build response with kafka-go or Sarama library")
t.Log("4. Compare byte-by-byte")
t.Log("5. If different, highlight which fields differ")
// This would catch:
// - Wrong field order
// - Wrong field encoding
// - Missing fields
// - Null vs empty distinctions
}
// CurrentTestingApproach documents what we actually do
func TestCurrentTestingApproach(t *testing.T) {
t.Log("Current testing strategy (as of Oct 2025):")
t.Log("")
t.Log("LEVEL 1: Static Code Analysis")
t.Log(" Tool: check_responses.sh")
t.Log(" Checks: Correlation ID patterns")
t.Log(" Coverage: Good for known issues")
t.Log("")
t.Log("LEVEL 2: Protocol Format Tests")
t.Log(" Tool: TestFlexibleResponseHeaderFormat")
t.Log(" Checks: Flexible vs non-flexible classification")
t.Log(" Coverage: Header format only")
t.Log("")
t.Log("LEVEL 3: Integration Testing")
t.Log(" Tool: Schema Registry, kafka-go, Sarama, Java client")
t.Log(" Checks: Real client compatibility")
t.Log(" Coverage: Complete but requires manual debugging")
t.Log("")
t.Log("MISSING: Field-level response body validation")
t.Log(" This is why JoinGroup issue wasn't caught by unit tests")
}
// parseCompactArray is a helper that would be needed for field-level testing
func parseCompactArray(data []byte) int {
// Compact array encoding: varint length (length+1 for non-null, 0 for null)
length := int(data[0])
if length == 0 {
return -1 // null
}
return length - 1 // actual length
}
// Example of a REAL field-level test we could write
func TestMetadataResponseHasBrokers(t *testing.T) {
t.Skip("Example of what a real field-level test would look like")
// Build a minimal metadata response
response := make([]byte, 0, 256)
// Brokers array (non-nullable)
brokerCount := uint32(1)
response = append(response,
byte(brokerCount>>24),
byte(brokerCount>>16),
byte(brokerCount>>8),
byte(brokerCount))
// Broker 1
response = append(response, 0, 0, 0, 1) // node_id = 1
// ... more fields ...
// Parse it back
offset := 0
parsedCount := binary.BigEndian.Uint32(response[offset : offset+4])
// Verify
if parsedCount == 0 {
t.Error("Metadata response has 0 brokers - should have at least 1")
}
t.Logf("✓ Metadata response correctly has %d broker(s)", parsedCount)
}
|