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 5package binary 6 7import ( 8 "bytes" 9 "io" 10 "math" 11 "testing" 12) 13 14func 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 22func TestConstants(t *testing.T) { 23 testConstant(t, 16, MaxVarintLen16) 24 testConstant(t, 32, MaxVarintLen32) 25 testConstant(t, 64, MaxVarintLen64) 26} 27 28func 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 54func 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 80var 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 101func 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 112func 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 121func 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 143func 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 197func 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 214func 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 220func 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 229func 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 239func 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