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  }