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  	buf2 := []byte("prefix")
    40  	buf2 = AppendVarint(buf2, x)
    41  	if string(buf2) != "prefix"+string(buf[:n]) {
    42  		t.Errorf("AppendVarint(%d): got %q, want %q", x, buf2, "prefix"+string(buf[:n]))
    43  	}
    44  
    45  	y, err := ReadVarint(bytes.NewReader(buf))
    46  	if err != nil {
    47  		t.Errorf("ReadVarint(%d): %s", x, err)
    48  	}
    49  	if x != y {
    50  		t.Errorf("ReadVarint(%d): got %d", x, y)
    51  	}
    52  }
    53  
    54  func testUvarint(t *testing.T, x uint64) {
    55  	buf := make([]byte, MaxVarintLen64)
    56  	n := PutUvarint(buf, x)
    57  	y, m := Uvarint(buf[0:n])
    58  	if x != y {
    59  		t.Errorf("Uvarint(%d): got %d", x, y)
    60  	}
    61  	if n != m {
    62  		t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
    63  	}
    64  
    65  	buf2 := []byte("prefix")
    66  	buf2 = AppendUvarint(buf2, x)
    67  	if string(buf2) != "prefix"+string(buf[:n]) {
    68  		t.Errorf("AppendUvarint(%d): got %q, want %q", x, buf2, "prefix"+string(buf[:n]))
    69  	}
    70  
    71  	y, err := ReadUvarint(bytes.NewReader(buf))
    72  	if err != nil {
    73  		t.Errorf("ReadUvarint(%d): %s", x, err)
    74  	}
    75  	if x != y {
    76  		t.Errorf("ReadUvarint(%d): got %d", x, y)
    77  	}
    78  }
    79  
    80  var tests = []int64{
    81  	-1 << 63,
    82  	-1<<63 + 1,
    83  	-1,
    84  	0,
    85  	1,
    86  	2,
    87  	10,
    88  	20,
    89  	63,
    90  	64,
    91  	65,
    92  	127,
    93  	128,
    94  	129,
    95  	255,
    96  	256,
    97  	257,
    98  	1<<63 - 1,
    99  }
   100  
   101  func TestVarint(t *testing.T) {
   102  	for _, x := range tests {
   103  		testVarint(t, x)
   104  		testVarint(t, -x)
   105  	}
   106  	for x := int64(0x7); x != 0; x <<= 1 {
   107  		testVarint(t, x)
   108  		testVarint(t, -x)
   109  	}
   110  }
   111  
   112  func TestUvarint(t *testing.T) {
   113  	for _, x := range tests {
   114  		testUvarint(t, uint64(x))
   115  	}
   116  	for x := uint64(0x7); x != 0; x <<= 1 {
   117  		testUvarint(t, x)
   118  	}
   119  }
   120  
   121  func TestBufferTooSmall(t *testing.T) {
   122  	buf := []byte{0x80, 0x80, 0x80, 0x80}
   123  	for i := 0; i <= len(buf); i++ {
   124  		buf := buf[0:i]
   125  		x, n := Uvarint(buf)
   126  		if x != 0 || n != 0 {
   127  			t.Errorf("Uvarint(%v): got x = %d, n = %d", buf, x, n)
   128  		}
   129  
   130  		x, err := ReadUvarint(bytes.NewReader(buf))
   131  		wantErr := io.EOF
   132  		if i > 0 {
   133  			wantErr = io.ErrUnexpectedEOF
   134  		}
   135  		if x != 0 || err != wantErr {
   136  			t.Errorf("ReadUvarint(%v): got x = %d, err = %s", buf, x, err)
   137  		}
   138  	}
   139  }
   140  
   141  // Ensure that we catch overflows of bytes going past MaxVarintLen64.
   142  // See issue https://golang.org/issues/41185
   143  func TestBufferTooBigWithOverflow(t *testing.T) {
   144  	tests := []struct {
   145  		in        []byte
   146  		name      string
   147  		wantN     int
   148  		wantValue uint64
   149  	}{
   150  		{
   151  			name: "invalid: 1000 bytes",
   152  			in: func() []byte {
   153  				b := make([]byte, 1000)
   154  				for i := range b {
   155  					b[i] = 0xff
   156  				}
   157  				b[999] = 0
   158  				return b
   159  			}(),
   160  			wantN:     -11,
   161  			wantValue: 0,
   162  		},
   163  		{
   164  			name:      "valid: math.MaxUint64-40",
   165  			in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
   166  			wantValue: math.MaxUint64 - 40,
   167  			wantN:     10,
   168  		},
   169  		{
   170  			name:      "invalid: with more than MaxVarintLen64 bytes",
   171  			in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
   172  			wantN:     -11,
   173  			wantValue: 0,
   174  		},
   175  		{
   176  			name:      "invalid: 10th byte",
   177  			in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
   178  			wantN:     -10,
   179  			wantValue: 0,
   180  		},
   181  	}
   182  
   183  	for _, tt := range tests {
   184  		tt := tt
   185  		t.Run(tt.name, func(t *testing.T) {
   186  			value, n := Uvarint(tt.in)
   187  			if g, w := n, tt.wantN; g != w {
   188  				t.Errorf("bytes returned=%d, want=%d", g, w)
   189  			}
   190  			if g, w := value, tt.wantValue; g != w {
   191  				t.Errorf("value=%d, want=%d", g, w)
   192  			}
   193  		})
   194  	}
   195  }
   196  
   197  func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) {
   198  	x, n := Uvarint(buf)
   199  	if x != 0 || n != n0 {
   200  		t.Errorf("Uvarint(% X): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
   201  	}
   202  
   203  	r := bytes.NewReader(buf)
   204  	len := r.Len()
   205  	x, err := ReadUvarint(r)
   206  	if x != x0 || err != err0 {
   207  		t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want %d, %s", buf, x, err, x0, err0)
   208  	}
   209  	if read := len - r.Len(); read > MaxVarintLen64 {
   210  		t.Errorf("ReadUvarint(%v): read more than MaxVarintLen64 bytes, got %d", buf, read)
   211  	}
   212  }
   213  
   214  func TestOverflow(t *testing.T) {
   215  	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 0, -10, errOverflow)
   216  	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -11, errOverflow)
   217  	testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, -11, errOverflow) // 11 bytes, should overflow
   218  }
   219  
   220  func TestNonCanonicalZero(t *testing.T) {
   221  	buf := []byte{0x80, 0x80, 0x80, 0}
   222  	x, n := Uvarint(buf)
   223  	if x != 0 || n != 4 {
   224  		t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, 4", buf, x, n)
   225  
   226  	}
   227  }
   228  
   229  func BenchmarkPutUvarint32(b *testing.B) {
   230  	buf := make([]byte, MaxVarintLen32)
   231  	b.SetBytes(4)
   232  	for i := 0; i < b.N; i++ {
   233  		for j := uint(0); j < MaxVarintLen32; j++ {
   234  			PutUvarint(buf, 1<<(j*7))
   235  		}
   236  	}
   237  }
   238  
   239  func BenchmarkPutUvarint64(b *testing.B) {
   240  	buf := make([]byte, MaxVarintLen64)
   241  	b.SetBytes(8)
   242  	for i := 0; i < b.N; i++ {
   243  		for j := uint(0); j < MaxVarintLen64; j++ {
   244  			PutUvarint(buf, 1<<(j*7))
   245  		}
   246  	}
   247  }
   248  

View as plain text