github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/encoding/binary/varint_test.go (about) 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 }