github.com/segmentio/kafka-go@v0.4.48-0.20240318174348-3f6244eb34fd/protocol_test.go (about) 1 package kafka 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "reflect" 8 "testing" 9 ) 10 11 func TestApiVersionsFormat(t *testing.T) { 12 for _, test := range []struct { 13 version ApiVersion 14 format string 15 output string 16 }{ 17 {version: ApiVersion{1, 2, 5}, format: "%s", output: "Fetch"}, 18 {version: ApiVersion{1, 2, 5}, format: "%d", output: "1"}, 19 {version: ApiVersion{1, 2, 5}, format: "%-d", output: "2"}, 20 {version: ApiVersion{1, 2, 5}, format: "%+d", output: "5"}, 21 {version: ApiVersion{1, 2, 5}, format: "%v", output: "Fetch[v2:v5]"}, 22 {version: ApiVersion{1, 2, 5}, format: "%-v", output: "v2"}, 23 {version: ApiVersion{1, 2, 5}, format: "%+v", output: "v5"}, 24 {version: ApiVersion{1, 2, 5}, format: "%#v", output: "kafka.ApiVersion{ApiKey:1 MinVersion:2 MaxVersion:5}"}, 25 } { 26 t.Run(test.output, func(t *testing.T) { 27 if s := fmt.Sprintf(test.format, test.version); s != test.output { 28 t.Error("output mismatch:", s, "!=", test.output) 29 } 30 }) 31 } 32 } 33 34 func TestProtocol(t *testing.T) { 35 tests := []interface{}{ 36 int8(42), 37 int16(42), 38 int32(42), 39 int64(42), 40 "", 41 "Hello World!", 42 []byte(nil), 43 []byte("Hello World!"), 44 45 requestHeader{ 46 Size: 26, 47 ApiKey: int16(offsetCommit), 48 ApiVersion: int16(v2), 49 CorrelationID: 42, 50 ClientID: "Hello World!", 51 }, 52 53 message{ 54 MagicByte: 1, 55 Timestamp: 42, 56 Key: nil, 57 Value: []byte("Hello World!"), 58 }, 59 60 topicMetadataRequestV1{"A", "B", "C"}, 61 62 metadataResponseV1{ 63 Brokers: []brokerMetadataV1{ 64 {NodeID: 1, Host: "localhost", Port: 9001}, 65 {NodeID: 2, Host: "localhost", Port: 9002, Rack: "rack2"}, 66 }, 67 ControllerID: 2, 68 Topics: []topicMetadataV1{ 69 {TopicErrorCode: 0, Internal: true, Partitions: []partitionMetadataV1{{ 70 PartitionErrorCode: 0, 71 PartitionID: 1, 72 Leader: 2, 73 Replicas: []int32{1}, 74 Isr: []int32{1}, 75 }}}, 76 }, 77 }, 78 79 topicMetadataRequestV6{ 80 Topics: []string{"A", "B", "C"}, 81 AllowAutoTopicCreation: true, 82 }, 83 84 metadataResponseV6{ 85 Brokers: []brokerMetadataV1{ 86 {NodeID: 1, Host: "localhost", Port: 9001}, 87 {NodeID: 2, Host: "localhost", Port: 9002, Rack: "rack2"}, 88 }, 89 ClusterId: "cluster", 90 ControllerID: 2, 91 Topics: []topicMetadataV6{ 92 {TopicErrorCode: 0, Internal: true, Partitions: []partitionMetadataV6{{ 93 PartitionErrorCode: 0, 94 PartitionID: 1, 95 Leader: 2, 96 Replicas: []int32{1}, 97 Isr: []int32{1}, 98 OfflineReplicas: []int32{1}, 99 }}}, 100 }, 101 }, 102 103 listOffsetRequestV1{ 104 ReplicaID: 1, 105 Topics: []listOffsetRequestTopicV1{ 106 {TopicName: "A", Partitions: []listOffsetRequestPartitionV1{ 107 {Partition: 0, Time: -1}, 108 {Partition: 1, Time: -1}, 109 {Partition: 2, Time: -1}, 110 }}, 111 {TopicName: "B", Partitions: []listOffsetRequestPartitionV1{ 112 {Partition: 0, Time: -2}, 113 }}, 114 {TopicName: "C", Partitions: []listOffsetRequestPartitionV1{ 115 {Partition: 0, Time: 42}, 116 }}, 117 }, 118 }, 119 120 listOffsetResponseV1{ 121 {TopicName: "A", PartitionOffsets: []partitionOffsetV1{ 122 {Partition: 0, Timestamp: 42, Offset: 1}, 123 }}, 124 {TopicName: "B", PartitionOffsets: []partitionOffsetV1{ 125 {Partition: 0, Timestamp: 43, Offset: 10}, 126 {Partition: 1, Timestamp: 44, Offset: 100}, 127 }}, 128 }, 129 } 130 131 for _, test := range tests { 132 t.Run(fmt.Sprintf("%T", test), func(t *testing.T) { 133 b := &bytes.Buffer{} 134 r := bufio.NewReader(b) 135 w := &writeBuffer{w: b} 136 w.write(test) 137 138 if size := int(sizeof(test)); size != b.Len() { 139 t.Error("invalid size:", size, "!=", b.Len()) 140 } 141 142 v := reflect.New(reflect.TypeOf(test)) 143 n := b.Len() 144 145 n, err := read(r, n, v.Interface()) 146 if err != nil { 147 t.Fatal(err) 148 } 149 if n != 0 { 150 t.Errorf("%d unread bytes", n) 151 } 152 153 if !reflect.DeepEqual(test, v.Elem().Interface()) { 154 t.Error("values don't match:") 155 t.Logf("expected: %#v", test) 156 t.Logf("found: %#v", v.Elem().Interface()) 157 } 158 }) 159 } 160 }