github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/common/hexutil/json_test.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package hexutil 18 19 import ( 20 "bytes" 21 "encoding/hex" 22 "encoding/json" 23 "errors" 24 "math/big" 25 "testing" 26 27 "github.com/holiman/uint256" 28 ) 29 30 func checkError(t *testing.T, input string, got, want error) bool { 31 if got == nil { 32 if want != nil { 33 t.Errorf("input %s: got no error, want %q", input, want) 34 return false 35 } 36 return true 37 } 38 if want == nil { 39 t.Errorf("input %s: unexpected error %q", input, got) 40 } else if got.Error() != want.Error() { 41 t.Errorf("input %s: got error %q, want %q", input, got, want) 42 } 43 return false 44 } 45 46 func referenceBig(s string) *big.Int { 47 b, ok := new(big.Int).SetString(s, 16) 48 if !ok { 49 panic("invalid") 50 } 51 return b 52 } 53 54 func referenceBytes(s string) []byte { 55 b, err := hex.DecodeString(s) 56 if err != nil { 57 panic(err) 58 } 59 return b 60 } 61 62 var errJSONEOF = errors.New("unexpected end of JSON input") 63 64 var unmarshalBytesTests = []unmarshalTest{ 65 // invalid encoding 66 {input: "", wantErr: errJSONEOF}, 67 {input: "null", wantErr: errNonString(bytesT)}, 68 {input: "10", wantErr: errNonString(bytesT)}, 69 {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bytesT)}, 70 {input: `"0x0"`, wantErr: wrapTypeError(ErrOddLength, bytesT)}, 71 {input: `"0xxx"`, wantErr: wrapTypeError(ErrSyntax, bytesT)}, 72 {input: `"0x01zz01"`, wantErr: wrapTypeError(ErrSyntax, bytesT)}, 73 74 // valid encoding 75 {input: `""`, want: referenceBytes("")}, 76 {input: `"0x"`, want: referenceBytes("")}, 77 {input: `"0x02"`, want: referenceBytes("02")}, 78 {input: `"0X02"`, want: referenceBytes("02")}, 79 {input: `"0xffffffffff"`, want: referenceBytes("ffffffffff")}, 80 { 81 input: `"0xffffffffffffffffffffffffffffffffffff"`, 82 want: referenceBytes("ffffffffffffffffffffffffffffffffffff"), 83 }, 84 } 85 86 func TestUnmarshalBytes(t *testing.T) { 87 for _, test := range unmarshalBytesTests { 88 var v Bytes 89 err := json.Unmarshal([]byte(test.input), &v) 90 if !checkError(t, test.input, err, test.wantErr) { 91 continue 92 } 93 if !bytes.Equal(test.want.([]byte), v) { 94 t.Errorf("input %s: value mismatch: got %x, want %x", test.input, &v, test.want) 95 continue 96 } 97 } 98 } 99 100 func BenchmarkUnmarshalBytes(b *testing.B) { 101 input := []byte(`"0x123456789abcdef123456789abcdef"`) 102 for i := 0; i < b.N; i++ { 103 var v Bytes 104 if err := v.UnmarshalJSON(input); err != nil { 105 b.Fatal(err) 106 } 107 } 108 } 109 110 func TestMarshalBytes(t *testing.T) { 111 for _, test := range encodeBytesTests { 112 in := test.input.([]byte) 113 out, err := json.Marshal(Bytes(in)) 114 if err != nil { 115 t.Errorf("%x: %v", in, err) 116 continue 117 } 118 if want := `"` + test.want + `"`; string(out) != want { 119 t.Errorf("%x: MarshalJSON output mismatch: got %q, want %q", in, out, want) 120 continue 121 } 122 if out := Bytes(in).String(); out != test.want { 123 t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) 124 continue 125 } 126 } 127 } 128 129 var unmarshalBigTests = []unmarshalTest{ 130 // invalid encoding 131 {input: "", wantErr: errJSONEOF}, 132 {input: "null", wantErr: errNonString(bigT)}, 133 {input: "10", wantErr: errNonString(bigT)}, 134 {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bigT)}, 135 {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, bigT)}, 136 {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, bigT)}, 137 {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, bigT)}, 138 {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, bigT)}, 139 { 140 input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`, 141 wantErr: wrapTypeError(ErrBig256Range, bigT), 142 }, 143 144 // valid encoding 145 {input: `""`, want: big.NewInt(0)}, 146 {input: `"0x0"`, want: big.NewInt(0)}, 147 {input: `"0x2"`, want: big.NewInt(0x2)}, 148 {input: `"0x2F2"`, want: big.NewInt(0x2f2)}, 149 {input: `"0X2F2"`, want: big.NewInt(0x2f2)}, 150 {input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)}, 151 {input: `"0xbBb"`, want: big.NewInt(0xbbb)}, 152 {input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)}, 153 { 154 input: `"0x112233445566778899aabbccddeeff"`, 155 want: referenceBig("112233445566778899aabbccddeeff"), 156 }, 157 { 158 input: `"0xffffffffffffffffffffffffffffffffffff"`, 159 want: referenceBig("ffffffffffffffffffffffffffffffffffff"), 160 }, 161 { 162 input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`, 163 want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), 164 }, 165 } 166 167 func TestUnmarshalBig(t *testing.T) { 168 for _, test := range unmarshalBigTests { 169 var v Big 170 err := json.Unmarshal([]byte(test.input), &v) 171 if !checkError(t, test.input, err, test.wantErr) { 172 continue 173 } 174 if test.want != nil && test.want.(*big.Int).Cmp((*big.Int)(&v)) != 0 { 175 t.Errorf("input %s: value mismatch: got %x, want %x", test.input, (*big.Int)(&v), test.want) 176 continue 177 } 178 } 179 } 180 181 var unmarshalU256Tests = []unmarshalTest{ 182 // invalid encoding 183 {input: "", wantErr: errJSONEOF}, 184 {input: "null", wantErr: errNonString(u256T)}, 185 {input: "10", wantErr: errNonString(u256T)}, 186 {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, u256T)}, 187 {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, u256T)}, 188 {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, u256T)}, 189 {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, u256T)}, 190 {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, u256T)}, 191 { 192 input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`, 193 wantErr: wrapTypeError(ErrBig256Range, u256T), 194 }, 195 196 // valid encoding 197 {input: `""`, want: big.NewInt(0)}, 198 {input: `"0x0"`, want: big.NewInt(0)}, 199 {input: `"0x2"`, want: big.NewInt(0x2)}, 200 {input: `"0x2F2"`, want: big.NewInt(0x2f2)}, 201 {input: `"0X2F2"`, want: big.NewInt(0x2f2)}, 202 {input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)}, 203 {input: `"0xbBb"`, want: big.NewInt(0xbbb)}, 204 {input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)}, 205 { 206 input: `"0x112233445566778899aabbccddeeff"`, 207 want: referenceBig("112233445566778899aabbccddeeff"), 208 }, 209 { 210 input: `"0xffffffffffffffffffffffffffffffffffff"`, 211 want: referenceBig("ffffffffffffffffffffffffffffffffffff"), 212 }, 213 { 214 input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`, 215 want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), 216 }, 217 } 218 219 func TestUnmarshalU256(t *testing.T) { 220 for _, test := range unmarshalU256Tests { 221 var v U256 222 err := json.Unmarshal([]byte(test.input), &v) 223 if !checkError(t, test.input, err, test.wantErr) { 224 continue 225 } 226 if test.want == nil { 227 continue 228 } 229 want := new(uint256.Int) 230 want.SetFromBig(test.want.(*big.Int)) 231 have := (*uint256.Int)(&v) 232 if want.Cmp(have) != 0 { 233 t.Errorf("input %s: value mismatch: have %x, want %x", test.input, have, want) 234 continue 235 } 236 } 237 } 238 239 func BenchmarkUnmarshalBig(b *testing.B) { 240 input := []byte(`"0x123456789abcdef123456789abcdef"`) 241 for i := 0; i < b.N; i++ { 242 var v Big 243 if err := v.UnmarshalJSON(input); err != nil { 244 b.Fatal(err) 245 } 246 } 247 } 248 249 func TestMarshalBig(t *testing.T) { 250 for _, test := range encodeBigTests { 251 in := test.input.(*big.Int) 252 out, err := json.Marshal((*Big)(in)) 253 if err != nil { 254 t.Errorf("%d: %v", in, err) 255 continue 256 } 257 if want := `"` + test.want + `"`; string(out) != want { 258 t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) 259 continue 260 } 261 if out := (*Big)(in).String(); out != test.want { 262 t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) 263 continue 264 } 265 } 266 } 267 268 var unmarshalUint64Tests = []unmarshalTest{ 269 // invalid encoding 270 {input: "", wantErr: errJSONEOF}, 271 {input: "null", wantErr: errNonString(uint64T)}, 272 {input: "10", wantErr: errNonString(uint64T)}, 273 {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uint64T)}, 274 {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uint64T)}, 275 {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uint64T)}, 276 {input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUint64Range, uint64T)}, 277 {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uint64T)}, 278 {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uint64T)}, 279 280 // valid encoding 281 {input: `""`, want: uint64(0)}, 282 {input: `"0x0"`, want: uint64(0)}, 283 {input: `"0x2"`, want: uint64(0x2)}, 284 {input: `"0x2F2"`, want: uint64(0x2f2)}, 285 {input: `"0X2F2"`, want: uint64(0x2f2)}, 286 {input: `"0x1122aaff"`, want: uint64(0x1122aaff)}, 287 {input: `"0xbbb"`, want: uint64(0xbbb)}, 288 {input: `"0xffffffffffffffff"`, want: uint64(0xffffffffffffffff)}, 289 } 290 291 func TestUnmarshalUint64(t *testing.T) { 292 for _, test := range unmarshalUint64Tests { 293 var v Uint64 294 err := json.Unmarshal([]byte(test.input), &v) 295 if !checkError(t, test.input, err, test.wantErr) { 296 continue 297 } 298 if uint64(v) != test.want.(uint64) { 299 t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want) 300 continue 301 } 302 } 303 } 304 305 func BenchmarkUnmarshalUint64(b *testing.B) { 306 input := []byte(`"0x123456789abcdf"`) 307 for i := 0; i < b.N; i++ { 308 var v Uint64 309 v.UnmarshalJSON(input) 310 } 311 } 312 313 func TestMarshalUint64(t *testing.T) { 314 for _, test := range encodeUint64Tests { 315 in := test.input.(uint64) 316 out, err := json.Marshal(Uint64(in)) 317 if err != nil { 318 t.Errorf("%d: %v", in, err) 319 continue 320 } 321 if want := `"` + test.want + `"`; string(out) != want { 322 t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) 323 continue 324 } 325 if out := (Uint64)(in).String(); out != test.want { 326 t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) 327 continue 328 } 329 } 330 } 331 332 func TestMarshalUint(t *testing.T) { 333 for _, test := range encodeUintTests { 334 in := test.input.(uint) 335 out, err := json.Marshal(Uint(in)) 336 if err != nil { 337 t.Errorf("%d: %v", in, err) 338 continue 339 } 340 if want := `"` + test.want + `"`; string(out) != want { 341 t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) 342 continue 343 } 344 if out := (Uint)(in).String(); out != test.want { 345 t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) 346 continue 347 } 348 } 349 } 350 351 var ( 352 // These are variables (not constants) to avoid constant overflow 353 // checks in the compiler on 32bit platforms. 354 maxUint33bits = uint64(^uint32(0)) + 1 355 maxUint64bits = ^uint64(0) 356 ) 357 358 var unmarshalUintTests = []unmarshalTest{ 359 // invalid encoding 360 {input: "", wantErr: errJSONEOF}, 361 {input: "null", wantErr: errNonString(uintT)}, 362 {input: "10", wantErr: errNonString(uintT)}, 363 {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uintT)}, 364 {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uintT)}, 365 {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uintT)}, 366 {input: `"0x100000000"`, want: uint(maxUint33bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)}, 367 {input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUintRange, uintT)}, 368 {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uintT)}, 369 {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uintT)}, 370 371 // valid encoding 372 {input: `""`, want: uint(0)}, 373 {input: `"0x0"`, want: uint(0)}, 374 {input: `"0x2"`, want: uint(0x2)}, 375 {input: `"0x2F2"`, want: uint(0x2f2)}, 376 {input: `"0X2F2"`, want: uint(0x2f2)}, 377 {input: `"0x1122aaff"`, want: uint(0x1122aaff)}, 378 {input: `"0xbbb"`, want: uint(0xbbb)}, 379 {input: `"0xffffffff"`, want: uint(0xffffffff)}, 380 {input: `"0xffffffffffffffff"`, want: uint(maxUint64bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)}, 381 } 382 383 func TestUnmarshalUint(t *testing.T) { 384 for _, test := range unmarshalUintTests { 385 var v Uint 386 err := json.Unmarshal([]byte(test.input), &v) 387 if uintBits == 32 && test.wantErr32bit != nil { 388 checkError(t, test.input, err, test.wantErr32bit) 389 continue 390 } 391 if !checkError(t, test.input, err, test.wantErr) { 392 continue 393 } 394 if uint(v) != test.want.(uint) { 395 t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want) 396 continue 397 } 398 } 399 } 400 401 func TestUnmarshalFixedUnprefixedText(t *testing.T) { 402 tests := []struct { 403 input string 404 want []byte 405 wantErr error 406 }{ 407 {input: "0x2", wantErr: ErrOddLength}, 408 {input: "2", wantErr: ErrOddLength}, 409 {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")}, 410 {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")}, 411 // check that output is not modified for partially correct input 412 {input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}}, 413 {input: "0x444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}}, 414 // valid inputs 415 {input: "44444444", want: []byte{0x44, 0x44, 0x44, 0x44}}, 416 {input: "0x44444444", want: []byte{0x44, 0x44, 0x44, 0x44}}, 417 } 418 419 for _, test := range tests { 420 out := make([]byte, 4) 421 err := UnmarshalFixedUnprefixedText("x", []byte(test.input), out) 422 switch { 423 case err == nil && test.wantErr != nil: 424 t.Errorf("%q: got no error, expected %q", test.input, test.wantErr) 425 case err != nil && test.wantErr == nil: 426 t.Errorf("%q: unexpected error %q", test.input, err) 427 case err != nil && err.Error() != test.wantErr.Error(): 428 t.Errorf("%q: error mismatch: got %q, want %q", test.input, err, test.wantErr) 429 } 430 if test.want != nil && !bytes.Equal(out, test.want) { 431 t.Errorf("%q: output mismatch: got %x, want %x", test.input, out, test.want) 432 } 433 } 434 }