github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/common/hexutil/json_test.go (about)

     1  package hexutil
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"math/big"
     9  	"testing"
    10  )
    11  
    12  func checkError(t *testing.T, input string, got, want error) bool {
    13  	if got == nil {
    14  		if want != nil {
    15  			t.Errorf("input %s: got no error, want %q", input, want)
    16  			return false
    17  		}
    18  		return true
    19  	}
    20  	if want == nil {
    21  		t.Errorf("input %s: unexpected error %q", input, got)
    22  	} else if got.Error() != want.Error() {
    23  		t.Errorf("input %s: got error %q, want %q", input, got, want)
    24  	}
    25  	return false
    26  }
    27  
    28  func referenceBig(s string) *big.Int {
    29  	b, ok := new(big.Int).SetString(s, 16)
    30  	if !ok {
    31  		panic("invalid")
    32  	}
    33  	return b
    34  }
    35  
    36  func referenceBytes(s string) []byte {
    37  	b, err := hex.DecodeString(s)
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	return b
    42  }
    43  
    44  var errJSONEOF = errors.New("unexpected end of JSON input")
    45  
    46  var unmarshalBytesTests = []unmarshalTest{
    47  	// invalid encoding
    48  	{input: "", wantErr: errJSONEOF},
    49  	{input: "null", wantErr: errNonString(bytesT)},
    50  	{input: "10", wantErr: errNonString(bytesT)},
    51  	{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bytesT)},
    52  	{input: `"0x0"`, wantErr: wrapTypeError(ErrOddLength, bytesT)},
    53  	{input: `"0xxx"`, wantErr: wrapTypeError(ErrSyntax, bytesT)},
    54  	{input: `"0x01zz01"`, wantErr: wrapTypeError(ErrSyntax, bytesT)},
    55  
    56  	// valid encoding
    57  	{input: `""`, want: referenceBytes("")},
    58  	{input: `"0x"`, want: referenceBytes("")},
    59  	{input: `"0x02"`, want: referenceBytes("02")},
    60  	{input: `"0X02"`, want: referenceBytes("02")},
    61  	{input: `"0xffffffffff"`, want: referenceBytes("ffffffffff")},
    62  	{
    63  		input: `"0xffffffffffffffffffffffffffffffffffff"`,
    64  		want:  referenceBytes("ffffffffffffffffffffffffffffffffffff"),
    65  	},
    66  }
    67  
    68  func TestUnmarshalBytes(t *testing.T) {
    69  	for _, test := range unmarshalBytesTests {
    70  		var v Bytes
    71  		err := json.Unmarshal([]byte(test.input), &v)
    72  		if !checkError(t, test.input, err, test.wantErr) {
    73  			continue
    74  		}
    75  		if !bytes.Equal(test.want.([]byte), []byte(v)) {
    76  			t.Errorf("input %s: value mismatch: got %x, want %x", test.input, &v, test.want)
    77  			continue
    78  		}
    79  	}
    80  }
    81  
    82  func BenchmarkUnmarshalBytes(b *testing.B) {
    83  	input := []byte(`"0x123456789abcdef123456789abcdef"`)
    84  	for i := 0; i < b.N; i++ {
    85  		var v Bytes
    86  		if err := v.UnmarshalJSON(input); err != nil {
    87  			b.Fatal(err)
    88  		}
    89  	}
    90  }
    91  
    92  func TestMarshalBytes(t *testing.T) {
    93  	for _, test := range encodeBytesTests {
    94  		in := test.input.([]byte)
    95  		out, err := json.Marshal(Bytes(in))
    96  		if err != nil {
    97  			t.Errorf("%x: %v", in, err)
    98  			continue
    99  		}
   100  		if want := `"` + test.want + `"`; string(out) != want {
   101  			t.Errorf("%x: MarshalJSON output mismatch: got %q, want %q", in, out, want)
   102  			continue
   103  		}
   104  		if out := Bytes(in).String(); out != test.want {
   105  			t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
   106  			continue
   107  		}
   108  	}
   109  }
   110  
   111  var unmarshalBigTests = []unmarshalTest{
   112  	// invalid encoding
   113  	{input: "", wantErr: errJSONEOF},
   114  	{input: "null", wantErr: errNonString(bigT)},
   115  	{input: "10", wantErr: errNonString(bigT)},
   116  	{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bigT)},
   117  	{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, bigT)},
   118  	{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, bigT)},
   119  	{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, bigT)},
   120  	{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, bigT)},
   121  	{
   122  		input:   `"0x10000000000000000000000000000000000000000000000000000000000000000"`,
   123  		wantErr: wrapTypeError(ErrBig256Range, bigT),
   124  	},
   125  
   126  	// valid encoding
   127  	{input: `""`, want: big.NewInt(0)},
   128  	{input: `"0x0"`, want: big.NewInt(0)},
   129  	{input: `"0x2"`, want: big.NewInt(0x2)},
   130  	{input: `"0x2F2"`, want: big.NewInt(0x2f2)},
   131  	{input: `"0X2F2"`, want: big.NewInt(0x2f2)},
   132  	{input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)},
   133  	{input: `"0xbBb"`, want: big.NewInt(0xbbb)},
   134  	{input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)},
   135  	{
   136  		input: `"0x112233445566778899aabbccddeeff"`,
   137  		want:  referenceBig("112233445566778899aabbccddeeff"),
   138  	},
   139  	{
   140  		input: `"0xffffffffffffffffffffffffffffffffffff"`,
   141  		want:  referenceBig("ffffffffffffffffffffffffffffffffffff"),
   142  	},
   143  	{
   144  		input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`,
   145  		want:  referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
   146  	},
   147  }
   148  
   149  func TestUnmarshalBig(t *testing.T) {
   150  	for _, test := range unmarshalBigTests {
   151  		var v Big
   152  		err := json.Unmarshal([]byte(test.input), &v)
   153  		if !checkError(t, test.input, err, test.wantErr) {
   154  			continue
   155  		}
   156  		if test.want != nil && test.want.(*big.Int).Cmp((*big.Int)(&v)) != 0 {
   157  			t.Errorf("input %s: value mismatch: got %x, want %x", test.input, (*big.Int)(&v), test.want)
   158  			continue
   159  		}
   160  	}
   161  }
   162  
   163  func BenchmarkUnmarshalBig(b *testing.B) {
   164  	input := []byte(`"0x123456789abcdef123456789abcdef"`)
   165  	for i := 0; i < b.N; i++ {
   166  		var v Big
   167  		if err := v.UnmarshalJSON(input); err != nil {
   168  			b.Fatal(err)
   169  		}
   170  	}
   171  }
   172  
   173  func TestMarshalBig(t *testing.T) {
   174  	for _, test := range encodeBigTests {
   175  		in := test.input.(*big.Int)
   176  		out, err := json.Marshal((*Big)(in))
   177  		if err != nil {
   178  			t.Errorf("%d: %v", in, err)
   179  			continue
   180  		}
   181  		if want := `"` + test.want + `"`; string(out) != want {
   182  			t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
   183  			continue
   184  		}
   185  		if out := (*Big)(in).String(); out != test.want {
   186  			t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
   187  			continue
   188  		}
   189  	}
   190  }
   191  
   192  var unmarshalUint64Tests = []unmarshalTest{
   193  	// invalid encoding
   194  	{input: "", wantErr: errJSONEOF},
   195  	{input: "null", wantErr: errNonString(uint64T)},
   196  	{input: "10", wantErr: errNonString(uint64T)},
   197  	{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uint64T)},
   198  	{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uint64T)},
   199  	{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uint64T)},
   200  	{input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUint64Range, uint64T)},
   201  	{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uint64T)},
   202  	{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uint64T)},
   203  
   204  	// valid encoding
   205  	{input: `""`, want: uint64(0)},
   206  	{input: `"0x0"`, want: uint64(0)},
   207  	{input: `"0x2"`, want: uint64(0x2)},
   208  	{input: `"0x2F2"`, want: uint64(0x2f2)},
   209  	{input: `"0X2F2"`, want: uint64(0x2f2)},
   210  	{input: `"0x1122aaff"`, want: uint64(0x1122aaff)},
   211  	{input: `"0xbbb"`, want: uint64(0xbbb)},
   212  	{input: `"0xffffffffffffffff"`, want: uint64(0xffffffffffffffff)},
   213  }
   214  
   215  func TestUnmarshalUint64(t *testing.T) {
   216  	for _, test := range unmarshalUint64Tests {
   217  		var v Uint64
   218  		err := json.Unmarshal([]byte(test.input), &v)
   219  		if !checkError(t, test.input, err, test.wantErr) {
   220  			continue
   221  		}
   222  		if uint64(v) != test.want.(uint64) {
   223  			t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want)
   224  			continue
   225  		}
   226  	}
   227  }
   228  
   229  func BenchmarkUnmarshalUint64(b *testing.B) {
   230  	input := []byte(`"0x123456789abcdf"`)
   231  	for i := 0; i < b.N; i++ {
   232  		var v Uint64
   233  		v.UnmarshalJSON(input)
   234  	}
   235  }
   236  
   237  func TestMarshalUint64(t *testing.T) {
   238  	for _, test := range encodeUint64Tests {
   239  		in := test.input.(uint64)
   240  		out, err := json.Marshal(Uint64(in))
   241  		if err != nil {
   242  			t.Errorf("%d: %v", in, err)
   243  			continue
   244  		}
   245  		if want := `"` + test.want + `"`; string(out) != want {
   246  			t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
   247  			continue
   248  		}
   249  		if out := (Uint64)(in).String(); out != test.want {
   250  			t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
   251  			continue
   252  		}
   253  	}
   254  }
   255  
   256  func TestMarshalUint(t *testing.T) {
   257  	for _, test := range encodeUintTests {
   258  		in := test.input.(uint)
   259  		out, err := json.Marshal(Uint(in))
   260  		if err != nil {
   261  			t.Errorf("%d: %v", in, err)
   262  			continue
   263  		}
   264  		if want := `"` + test.want + `"`; string(out) != want {
   265  			t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
   266  			continue
   267  		}
   268  		if out := (Uint)(in).String(); out != test.want {
   269  			t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
   270  			continue
   271  		}
   272  	}
   273  }
   274  
   275  var (
   276  	// These are variables (not constants) to avoid constant overflow
   277  	// checks in the compiler on 32bit platforms.
   278  	maxUint33bits = uint64(^uint32(0)) + 1
   279  	maxUint64bits = ^uint64(0)
   280  )
   281  
   282  var unmarshalUintTests = []unmarshalTest{
   283  	// invalid encoding
   284  	{input: "", wantErr: errJSONEOF},
   285  	{input: "null", wantErr: errNonString(uintT)},
   286  	{input: "10", wantErr: errNonString(uintT)},
   287  	{input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uintT)},
   288  	{input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uintT)},
   289  	{input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uintT)},
   290  	{input: `"0x100000000"`, want: uint(maxUint33bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)},
   291  	{input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUintRange, uintT)},
   292  	{input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uintT)},
   293  	{input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uintT)},
   294  
   295  	// valid encoding
   296  	{input: `""`, want: uint(0)},
   297  	{input: `"0x0"`, want: uint(0)},
   298  	{input: `"0x2"`, want: uint(0x2)},
   299  	{input: `"0x2F2"`, want: uint(0x2f2)},
   300  	{input: `"0X2F2"`, want: uint(0x2f2)},
   301  	{input: `"0x1122aaff"`, want: uint(0x1122aaff)},
   302  	{input: `"0xbbb"`, want: uint(0xbbb)},
   303  	{input: `"0xffffffff"`, want: uint(0xffffffff)},
   304  	{input: `"0xffffffffffffffff"`, want: uint(maxUint64bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)},
   305  }
   306  
   307  func TestUnmarshalUint(t *testing.T) {
   308  	for _, test := range unmarshalUintTests {
   309  		var v Uint
   310  		err := json.Unmarshal([]byte(test.input), &v)
   311  		if uintBits == 32 && test.wantErr32bit != nil {
   312  			checkError(t, test.input, err, test.wantErr32bit)
   313  			continue
   314  		}
   315  		if !checkError(t, test.input, err, test.wantErr) {
   316  			continue
   317  		}
   318  		if uint(v) != test.want.(uint) {
   319  			t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want)
   320  			continue
   321  		}
   322  	}
   323  }
   324  
   325  func TestUnmarshalFixedUnprefixedText(t *testing.T) {
   326  	tests := []struct {
   327  		input   string
   328  		want    []byte
   329  		wantErr error
   330  	}{
   331  		{input: "0x2", wantErr: ErrOddLength},
   332  		{input: "2", wantErr: ErrOddLength},
   333  		{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
   334  		{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
   335  		// check that output is not modified for partially correct input
   336  		{input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
   337  		{input: "0x444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
   338  		// valid inputs
   339  		{input: "44444444", want: []byte{0x44, 0x44, 0x44, 0x44}},
   340  		{input: "0x44444444", want: []byte{0x44, 0x44, 0x44, 0x44}},
   341  	}
   342  
   343  	for _, test := range tests {
   344  		out := make([]byte, 4)
   345  		err := UnmarshalFixedUnprefixedText("x", []byte(test.input), out)
   346  		switch {
   347  		case err == nil && test.wantErr != nil:
   348  			t.Errorf("%q: got no error, expected %q", test.input, test.wantErr)
   349  		case err != nil && test.wantErr == nil:
   350  			t.Errorf("%q: unexpected error %q", test.input, err)
   351  		case err != nil && err.Error() != test.wantErr.Error():
   352  			t.Errorf("%q: error mismatch: got %q, want %q", test.input, err, test.wantErr)
   353  		}
   354  		if test.want != nil && !bytes.Equal(out, test.want) {
   355  			t.Errorf("%q: output mismatch: got %x, want %x", test.input, out, test.want)
   356  		}
   357  	}
   358  }