Source file src/encoding/binary/varint_test.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package binary
     6  
     7  import (
     8  	"bytes"
     9  	"io"
    10  	"math"
    11  	"testing"
    12  )
    13  
    14  func testConstant(t *testing.T, w uint, max int) {
    15  	buf := make([]byte, MaxVarintLen64)
    16  	n := PutUvarint(buf, 1<<w-1)
    17  	if n != max {
    18  		t.Errorf("MaxVarintLen%d = %d; want %d", w, max, n)
    19  	}
    20  }
    21  
    22  func TestConstants(t *testing.T) {
    23  	testConstant(t, 16, MaxVarintLen16)
    24  	testConstant(t, 32, MaxVarintLen32)
    25  	testConstant(t, 64, MaxVarintLen64)
    26  }
    27  
    28  func testVarint(t *testing.T, x int64) {
    29  	buf := make([]byte, MaxVarintLen64)
    30  	n := PutVarint(buf, x)
    31  	y, m := Varint(buf[0:n])
    32  	if x != y {
    33  		t.Errorf("Varint(%d): got %d", x, y)
    34  	}
    35  	if n != m {
    36  		t.Errorf("Varint(%d): got n = %d; want %d", x, m, n)
    37  	}
    38  
    39  	y, err := ReadVarint(bytes.NewReader(buf))
    40  	if err != nil {
    41  		t.Errorf("ReadVarint(%d): %s", x, err)
    42  	}
    43  	if x != y {
    44  		t.Errorf("ReadVarint(%d): got %d", x, y)
    45  	}
    46  }
    47  
    48  func testUvarint(t *testing.T, x uint64) {
    49  	buf := make([]byte, MaxVarintLen64)
    50  	n := PutUvarint(buf, x)
    51  	y, m := Uvarint(buf[0:n])
    52  	if x != y {
    53  		t.Errorf("Uvarint(%d): got %d", x, y)
    54  	}
    55  	if n != m {
    56  		t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
    57  	}
    58  
    59  	y, err := ReadUvarint(bytes.NewReader(buf))
    60  	if err != nil {
    61  		t.Errorf("ReadUvarint(%d): %s", x, err)
    62  	}
    63  	if x != y {
    64  		t.Errorf("ReadUvarint(%d): got %d", x, y)
    65  	}
    66  }
    67  
    68  var tests = []int64{
    69  	-1 << 63,
    70  	-1<<63 + 1,
    71  	-1,
    72  	0,
    73  	1,
    74  	2,
    75  	10,
    76  	20,
    77  	63,
    78  	64,
    79  	65,
    80  	127,
    81  	128,
    82  	129,
    83  	255,
    84  	256,
    85  	257,
    86  	1<<63 - 1,
    87  }
    88  
    89  func TestVarint(t *testing.T) {
    90  	for _, x := range tests {
    91  		testVarint(t, x)
    92  		testVarint(t, -x)
    93  	}
    94  	for x := int64(0x7); x != 0; x <<= 1 {
    95  		testVarint(t, x)
    96  		testVarint(t, -x)
    97  	}
    98  }
    99  
   100  func TestUvarint(t *testing.T) {
   101  	for _, x := range tests {
   102  		testUvarint(t, uint64(x))
   103  	}
   104  	for x := uint64(0x7); x != 0; x <<= 1 {
   105  		testUvarint(t, x)
   106  	}
   107  }
   108  
   109  func TestBufferTooSmall(t *testing.T) {
   110  	buf := []byte{0x80, 0x80, 0x80, 0x80}
   111  	for i := 0; i <= len(buf); i++ {
   112  		buf := buf[0:i]
   113  		x, n := Uvarint(buf)
   114  		if x != 0 || n != 0 {
   115  			t.Errorf("Uvarint(%v): got x = %d, n = %d", buf, x, n)
   116  		}
   117  
   118  		x, err := ReadUvarint(bytes.NewReader(buf))
   119  		if x != 0 || err != io.EOF {
   120  			t.Errorf("ReadUvarint(%v): got x = %d, err = %s", buf, x, err)
   121  		}
   122  	}
   123  }
   124  
   125  // Ensure that we catch overflows of bytes going past MaxVarintLen64.
   126  // See issue https://golang.org/issues/41185
   127  func TestBufferTooBigWithOverflow(t *testing.T) {
   128  	tests := []struct {
   129  		in        []byte
   130  		name      string
   131  		wantN     int
   132  		wantValue uint64
   133  	}{
   134  		{
   135  			name: "invalid: 1000 bytes",
   136  			in: func() []byte {
   137  				b := make([]byte, 1000)
   138  				for i := range b {
   139  					b[i] = 0xff
   140  				}
   141  				b[999] = 0
   142  				return b
   143  			}(),
   144  			wantN:     -11,
   145  			wantValue: 0,
   146  		},
   147  		{
   148  			name:      "valid: math.MaxUint64-40",
   149  			in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
   150  			wantValue: math.MaxUint64 - 40,
   151  			wantN:     10,
   152  		},
   153  		{
   154  			name:      "invalid: with more than MaxVarintLen64 bytes",
   155  			in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
   156  			wantN:     -11,
   157  			wantValue: 0,
   158  		},
   159  		{
   160  			name:      "invalid: 10th byte",
   161  			in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
   162  			wantN:     -10,
   163  			wantValue: 0,
   164  		},
   165  	}
   166  
   167  	for _, tt := range tests {
   168  		tt := tt
   169  		t.Run(tt.name, func(t *testing.T) {
   170  			value, n := Uvarint(tt.in)
   171  			if g, w := n, tt.wantN; g != w {
   172  				t.Errorf("bytes returned=%d, want=%d", g, w)
   173  			}
   174  			if g, w := value, tt.wantValue; g != w {
   175  				t.Errorf("value=%d, want=%d", g, w)
   176  			}
   177  		})
   178  	}
   179  }
   180  
   181  func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) {
   182  	x, n := Uvarint(buf)
   183  	if x != 0 || n != n0 {
   184  		t.Errorf("Uvarint(% X): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
   185  	}
   186  
   187  	r := bytes.NewReader(buf)
   188  	len := r.Len()
   189  	x, err := ReadUvarint(r)
   190  	if x != x0 || err != err0 {
   191  		t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want %d, %s", buf, x, err, x0, err0)
   192  	}
   193  	if read := len - r.Len(); read > MaxVarintLen64 {
   194  		t.Errorf("ReadUvarint(%v): read more than MaxVarintLen64 bytes, got %d", buf, read)
   195  	}
   196  }
   197  
   198  func TestOverflow(t *testing.T) {
   199  	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 0, -10, overflow)
   200  	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -11, overflow)
   201  	testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, -11, overflow) // 11 bytes, should overflow
   202  }
   203  
   204  func TestNonCanonicalZero(t *testing.T) {
   205  	buf := []byte{0x80, 0x80, 0x80, 0}
   206  	x, n := Uvarint(buf)
   207  	if x != 0 || n != 4 {
   208  		t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, 4", buf, x, n)
   209  
   210  	}
   211  }
   212  
   213  func BenchmarkPutUvarint32(b *testing.B) {
   214  	buf := make([]byte, MaxVarintLen32)
   215  	b.SetBytes(4)
   216  	for i := 0; i < b.N; i++ {
   217  		for j := uint(0); j < MaxVarintLen32; j++ {
   218  			PutUvarint(buf, 1<<(j*7))
   219  		}
   220  	}
   221  }
   222  
   223  func BenchmarkPutUvarint64(b *testing.B) {
   224  	buf := make([]byte, MaxVarintLen64)
   225  	b.SetBytes(8)
   226  	for i := 0; i < b.N; i++ {
   227  		for j := uint(0); j < MaxVarintLen64; j++ {
   228  			PutUvarint(buf, 1<<(j*7))
   229  		}
   230  	}
   231  }
   232  

View as plain text