github.com/segmentio/kafka-go@v0.4.48-0.20240318174348-3f6244eb34fd/read_test.go (about) 1 package kafka 2 3 import ( 4 "bufio" 5 "bytes" 6 "errors" 7 "io/ioutil" 8 "math" 9 "reflect" 10 "testing" 11 ) 12 13 type VarIntTestCase struct { 14 v int64 15 r int 16 tc []byte 17 } 18 19 func TestReadVarInt(t *testing.T) { 20 testCases := []*VarIntTestCase{ 21 {v: 0, r: 3, tc: []byte{0, 1, 10, 0}}, 22 {v: -1, r: 3, tc: []byte{1, 1, 10, 0}}, 23 {v: 1, r: 3, tc: []byte{2, 1, 10, 0}}, 24 {v: -2, r: 3, tc: []byte{3, 1, 10, 0}}, 25 {v: 2, r: 3, tc: []byte{4, 1, 10, 0}}, 26 {v: 64, r: 2, tc: []byte{128, 1, 10, 0}}, 27 {v: -64, r: 3, tc: []byte{127, 1, 10, 0}}, 28 {v: -196, r: 2, tc: []byte{135, 3, 10, 0}}, 29 {v: -24772, r: 1, tc: []byte{135, 131, 3, 0}}, 30 } 31 32 for _, tc := range testCases { 33 var v int64 34 rd := bufio.NewReader(bytes.NewReader(tc.tc)) 35 remain, err := readVarInt(rd, len(tc.tc), &v) 36 if err != nil { 37 t.Errorf("Failure during reading: %v", err) 38 } 39 if v != tc.v { 40 t.Errorf("Expected %v; got %v", tc.v, v) 41 } 42 if remain != tc.r { 43 t.Errorf("Expected remain %v; got %v", tc.r, remain) 44 } 45 } 46 } 47 48 func TestReadVarIntFailing(t *testing.T) { 49 var v int64 50 testCase := []byte{135, 135} 51 rd := bufio.NewReader(bytes.NewReader(testCase)) 52 _, err := readVarInt(rd, len(testCase), &v) 53 if !errors.Is(err, errShortRead) { 54 t.Errorf("Expected error while parsing var int: %v", err) 55 } 56 } 57 58 func TestReadStringArray(t *testing.T) { 59 testCases := map[string]struct { 60 Value []string 61 }{ 62 "nil": { 63 Value: nil, 64 }, 65 "multiple elements": { 66 Value: []string{"a", "b", "c"}, 67 }, 68 } 69 70 for label, test := range testCases { 71 t.Run(label, func(t *testing.T) { 72 b := bytes.NewBuffer(nil) 73 w := &writeBuffer{w: b} 74 w.writeStringArray(test.Value) 75 76 var actual []string 77 readStringArray(bufio.NewReader(b), b.Len(), &actual) 78 if !reflect.DeepEqual(test.Value, actual) { 79 t.Errorf("expected %v; got %v", test.Value, actual) 80 } 81 }) 82 } 83 } 84 85 func TestReadMapStringInt32(t *testing.T) { 86 testCases := map[string]struct { 87 Data map[string][]int32 88 }{ 89 "empty": { 90 Data: map[string][]int32{}, 91 }, 92 "single element": { 93 Data: map[string][]int32{ 94 "key": {0, 1, 2}, 95 }, 96 }, 97 } 98 99 for label, test := range testCases { 100 t.Run(label, func(t *testing.T) { 101 b := bytes.NewBuffer(nil) 102 w := &writeBuffer{w: b} 103 w.writeInt32(int32(len(test.Data))) 104 105 for key, values := range test.Data { 106 w.writeString(key) 107 w.writeInt32Array(values) 108 } 109 110 var actual map[string][]int32 111 readMapStringInt32(bufio.NewReader(b), b.Len(), &actual) 112 if !reflect.DeepEqual(test.Data, actual) { 113 t.Errorf("expected %#v; got %#v", test.Data, actual) 114 } 115 }) 116 } 117 } 118 119 func TestReadNewBytes(t *testing.T) { 120 121 t.Run("reads new bytes", func(t *testing.T) { 122 r := bufio.NewReader(bytes.NewReader([]byte("foobar"))) 123 124 b, remain, err := readNewBytes(r, 6, 3) 125 if string(b) != "foo" { 126 t.Error("should have returned 3 bytes") 127 } 128 if remain != 3 { 129 t.Error("should have calculated remaining correctly") 130 } 131 if err != nil { 132 t.Error("should not have errored") 133 } 134 135 b, remain, err = readNewBytes(r, remain, 3) 136 if string(b) != "bar" { 137 t.Error("should have returned 3 bytes") 138 } 139 if remain != 0 { 140 t.Error("should have calculated remaining correctly") 141 } 142 if err != nil { 143 t.Error("should not have errored") 144 } 145 146 b, err = r.Peek(0) 147 if len(b) > 0 { 148 t.Error("not all bytes were consumed") 149 } 150 if err != nil { 151 t.Error("should not have errored during peek") 152 } 153 }) 154 155 t.Run("discards bytes when insufficient", func(t *testing.T) { 156 r := bufio.NewReader(bytes.NewReader([]byte("foo"))) 157 b, remain, err := readNewBytes(bufio.NewReader(r), 3, 4) 158 if string(b) != "foo" { 159 t.Error("should have returned available bytes") 160 } 161 if remain != 0 { 162 t.Error("all bytes should have been consumed") 163 } 164 if !errors.Is(err, errShortRead) { 165 t.Error("should have returned errShortRead") 166 } 167 b, err = r.Peek(0) 168 if len(b) > 0 { 169 t.Error("not all bytes were consumed") 170 } 171 if err != nil { 172 t.Error("should not have errored during peek") 173 } 174 }) 175 } 176 177 func BenchmarkWriteVarInt(b *testing.B) { 178 wb := &writeBuffer{w: ioutil.Discard} 179 180 for i := 0; i < b.N; i++ { 181 wb.writeVarInt(math.MaxInt64) 182 } 183 } 184 185 func BenchmarkReadVarInt(b *testing.B) { 186 b1 := new(bytes.Buffer) 187 wb := &writeBuffer{w: b1} 188 189 const N = math.MaxInt64 190 wb.writeVarInt(N) 191 192 b2 := bytes.NewReader(b1.Bytes()) 193 rb := bufio.NewReader(b2) 194 n := b1.Len() 195 196 for i := 0; i < b.N; i++ { 197 v := int64(0) 198 r, err := readVarInt(rb, n, &v) 199 200 if err != nil { 201 b.Fatalf("unexpected error reading a varint from the input: %v", err) 202 } 203 204 if r != 0 { 205 b.Fatalf("unexpected bytes remaining to be read in the input (%d B)", r) 206 } 207 208 if v != N { 209 b.Fatalf("value mismatch, expected %d but found %d", N, v) 210 } 211 212 b2.Reset(b1.Bytes()) 213 rb.Reset(b2) 214 } 215 }