| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package hexutil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type marshalTest struct { | 
					
						
							|  |  |  | 	input interface{} | 
					
						
							|  |  |  | 	want  string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type unmarshalTest struct { | 
					
						
							| 
									
										
										
										
											2017-02-22 17:59:59 +01:00
										 |  |  | 	input        string | 
					
						
							|  |  |  | 	want         interface{} | 
					
						
							|  |  |  | 	wantErr      error // if set, decoding must fail on any platform | 
					
						
							|  |  |  | 	wantErr32bit error // if set, decoding must fail on 32bit platforms (used for Uint tests) | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	encodeBytesTests = []marshalTest{ | 
					
						
							|  |  |  | 		{[]byte{}, "0x"}, | 
					
						
							|  |  |  | 		{[]byte{0}, "0x00"}, | 
					
						
							|  |  |  | 		{[]byte{0, 0, 1, 2}, "0x00000102"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	encodeBigTests = []marshalTest{ | 
					
						
							|  |  |  | 		{referenceBig("0"), "0x0"}, | 
					
						
							|  |  |  | 		{referenceBig("1"), "0x1"}, | 
					
						
							|  |  |  | 		{referenceBig("ff"), "0xff"}, | 
					
						
							|  |  |  | 		{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"}, | 
					
						
							| 
									
										
										
										
											2017-01-16 10:20:20 +01:00
										 |  |  | 		{referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"}, | 
					
						
							| 
									
										
										
										
											2017-02-26 19:40:33 +01:00
										 |  |  | 		{referenceBig("-80a7f2c1bcc396c00"), "-0x80a7f2c1bcc396c00"}, | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	encodeUint64Tests = []marshalTest{ | 
					
						
							|  |  |  | 		{uint64(0), "0x0"}, | 
					
						
							|  |  |  | 		{uint64(1), "0x1"}, | 
					
						
							|  |  |  | 		{uint64(0xff), "0xff"}, | 
					
						
							|  |  |  | 		{uint64(0x1122334455667788), "0x1122334455667788"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 17:59:59 +01:00
										 |  |  | 	encodeUintTests = []marshalTest{ | 
					
						
							|  |  |  | 		{uint(0), "0x0"}, | 
					
						
							|  |  |  | 		{uint(1), "0x1"}, | 
					
						
							|  |  |  | 		{uint(0xff), "0xff"}, | 
					
						
							|  |  |  | 		{uint(0x11223344), "0x11223344"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | 	decodeBytesTests = []unmarshalTest{ | 
					
						
							|  |  |  | 		// invalid | 
					
						
							|  |  |  | 		{input: ``, wantErr: ErrEmptyString}, | 
					
						
							|  |  |  | 		{input: `0`, wantErr: ErrMissingPrefix}, | 
					
						
							| 
									
										
										
										
											2017-02-22 17:55:04 +01:00
										 |  |  | 		{input: `0x0`, wantErr: ErrOddLength}, | 
					
						
							|  |  |  | 		{input: `0x023`, wantErr: ErrOddLength}, | 
					
						
							|  |  |  | 		{input: `0xxx`, wantErr: ErrSyntax}, | 
					
						
							|  |  |  | 		{input: `0x01zz01`, wantErr: ErrSyntax}, | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | 		// valid | 
					
						
							|  |  |  | 		{input: `0x`, want: []byte{}}, | 
					
						
							|  |  |  | 		{input: `0X`, want: []byte{}}, | 
					
						
							|  |  |  | 		{input: `0x02`, want: []byte{0x02}}, | 
					
						
							|  |  |  | 		{input: `0X02`, want: []byte{0x02}}, | 
					
						
							|  |  |  | 		{input: `0xffffffffff`, want: []byte{0xff, 0xff, 0xff, 0xff, 0xff}}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: `0xffffffffffffffffffffffffffffffffffff`, | 
					
						
							|  |  |  | 			want:  []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	decodeBigTests = []unmarshalTest{ | 
					
						
							|  |  |  | 		// invalid | 
					
						
							|  |  |  | 		{input: `0`, wantErr: ErrMissingPrefix}, | 
					
						
							|  |  |  | 		{input: `0x`, wantErr: ErrEmptyNumber}, | 
					
						
							|  |  |  | 		{input: `0x01`, wantErr: ErrLeadingZero}, | 
					
						
							|  |  |  | 		{input: `0xx`, wantErr: ErrSyntax}, | 
					
						
							|  |  |  | 		{input: `0x1zz01`, wantErr: ErrSyntax}, | 
					
						
							| 
									
										
										
										
											2017-02-22 17:35:11 +01:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			input:   `0x10000000000000000000000000000000000000000000000000000000000000000`, | 
					
						
							|  |  |  | 			wantErr: ErrBig256Range, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | 		// valid | 
					
						
							|  |  |  | 		{input: `0x0`, want: big.NewInt(0)}, | 
					
						
							|  |  |  | 		{input: `0x2`, want: big.NewInt(0x2)}, | 
					
						
							|  |  |  | 		{input: `0x2F2`, want: big.NewInt(0x2f2)}, | 
					
						
							|  |  |  | 		{input: `0X2F2`, want: big.NewInt(0x2f2)}, | 
					
						
							|  |  |  | 		{input: `0x1122aaff`, want: big.NewInt(0x1122aaff)}, | 
					
						
							|  |  |  | 		{input: `0xbBb`, want: big.NewInt(0xbbb)}, | 
					
						
							|  |  |  | 		{input: `0xfffffffff`, want: big.NewInt(0xfffffffff)}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: `0x112233445566778899aabbccddeeff`, | 
					
						
							|  |  |  | 			want:  referenceBig("112233445566778899aabbccddeeff"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: `0xffffffffffffffffffffffffffffffffffff`, | 
					
						
							|  |  |  | 			want:  referenceBig("ffffffffffffffffffffffffffffffffffff"), | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-02-22 17:35:11 +01:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			input: `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`, | 
					
						
							|  |  |  | 			want:  referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	decodeUint64Tests = []unmarshalTest{ | 
					
						
							|  |  |  | 		// invalid | 
					
						
							|  |  |  | 		{input: `0`, wantErr: ErrMissingPrefix}, | 
					
						
							|  |  |  | 		{input: `0x`, wantErr: ErrEmptyNumber}, | 
					
						
							|  |  |  | 		{input: `0x01`, wantErr: ErrLeadingZero}, | 
					
						
							| 
									
										
										
										
											2016-11-28 13:55:56 +01:00
										 |  |  | 		{input: `0xfffffffffffffffff`, wantErr: ErrUint64Range}, | 
					
						
							| 
									
										
										
										
											2016-09-15 02:57:48 +02:00
										 |  |  | 		{input: `0xx`, wantErr: ErrSyntax}, | 
					
						
							|  |  |  | 		{input: `0x1zz01`, wantErr: ErrSyntax}, | 
					
						
							|  |  |  | 		// valid | 
					
						
							|  |  |  | 		{input: `0x0`, want: uint64(0)}, | 
					
						
							|  |  |  | 		{input: `0x2`, want: uint64(0x2)}, | 
					
						
							|  |  |  | 		{input: `0x2F2`, want: uint64(0x2f2)}, | 
					
						
							|  |  |  | 		{input: `0X2F2`, want: uint64(0x2f2)}, | 
					
						
							|  |  |  | 		{input: `0x1122aaff`, want: uint64(0x1122aaff)}, | 
					
						
							|  |  |  | 		{input: `0xbbb`, want: uint64(0xbbb)}, | 
					
						
							|  |  |  | 		{input: `0xffffffffffffffff`, want: uint64(0xffffffffffffffff)}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestEncode(t *testing.T) { | 
					
						
							|  |  |  | 	for _, test := range encodeBytesTests { | 
					
						
							|  |  |  | 		enc := Encode(test.input.([]byte)) | 
					
						
							|  |  |  | 		if enc != test.want { | 
					
						
							|  |  |  | 			t.Errorf("input %x: wrong encoding %s", test.input, enc) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDecode(t *testing.T) { | 
					
						
							|  |  |  | 	for _, test := range decodeBytesTests { | 
					
						
							|  |  |  | 		dec, err := Decode(test.input) | 
					
						
							|  |  |  | 		if !checkError(t, test.input, err, test.wantErr) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !bytes.Equal(test.want.([]byte), dec) { | 
					
						
							|  |  |  | 			t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestEncodeBig(t *testing.T) { | 
					
						
							|  |  |  | 	for _, test := range encodeBigTests { | 
					
						
							|  |  |  | 		enc := EncodeBig(test.input.(*big.Int)) | 
					
						
							|  |  |  | 		if enc != test.want { | 
					
						
							|  |  |  | 			t.Errorf("input %x: wrong encoding %s", test.input, enc) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDecodeBig(t *testing.T) { | 
					
						
							|  |  |  | 	for _, test := range decodeBigTests { | 
					
						
							|  |  |  | 		dec, err := DecodeBig(test.input) | 
					
						
							|  |  |  | 		if !checkError(t, test.input, err, test.wantErr) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if dec.Cmp(test.want.(*big.Int)) != 0 { | 
					
						
							|  |  |  | 			t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestEncodeUint64(t *testing.T) { | 
					
						
							|  |  |  | 	for _, test := range encodeUint64Tests { | 
					
						
							|  |  |  | 		enc := EncodeUint64(test.input.(uint64)) | 
					
						
							|  |  |  | 		if enc != test.want { | 
					
						
							|  |  |  | 			t.Errorf("input %x: wrong encoding %s", test.input, enc) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDecodeUint64(t *testing.T) { | 
					
						
							|  |  |  | 	for _, test := range decodeUint64Tests { | 
					
						
							|  |  |  | 		dec, err := DecodeUint64(test.input) | 
					
						
							|  |  |  | 		if !checkError(t, test.input, err, test.wantErr) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if dec != test.want.(uint64) { | 
					
						
							|  |  |  | 			t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-10-21 11:43:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkEncodeBig(b *testing.B) { | 
					
						
							|  |  |  | 	for _, bench := range encodeBigTests { | 
					
						
							|  |  |  | 		b.Run(bench.want, func(b *testing.B) { | 
					
						
							|  |  |  | 			b.ReportAllocs() | 
					
						
							|  |  |  | 			bigint := bench.input.(*big.Int) | 
					
						
							|  |  |  | 			for i := 0; i < b.N; i++ { | 
					
						
							|  |  |  | 				EncodeBig(bigint) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |