github.com/pure-x-eth/consensus_tm@v0.0.0-20230502163723-e3c2ff987250/libs/json/encoder_test.go (about)

     1  package json_test
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/pure-x-eth/consensus_tm/libs/json"
    11  )
    12  
    13  func TestMarshal(t *testing.T) {
    14  	s := "string"
    15  	sPtr := &s
    16  	i64 := int64(64)
    17  	ti := time.Date(2020, 6, 2, 18, 5, 13, 4346374, time.FixedZone("UTC+2", 2*60*60))
    18  	car := &Car{Wheels: 4}
    19  	boat := Boat{Sail: true}
    20  
    21  	testcases := map[string]struct {
    22  		value  interface{}
    23  		output string
    24  	}{
    25  		"nil":             {nil, `null`},
    26  		"string":          {"foo", `"foo"`},
    27  		"float32":         {float32(3.14), `3.14`},
    28  		"float32 neg":     {float32(-3.14), `-3.14`},
    29  		"float64":         {float64(3.14), `3.14`},
    30  		"float64 neg":     {float64(-3.14), `-3.14`},
    31  		"int32":           {int32(32), `32`},
    32  		"int64":           {int64(64), `"64"`},
    33  		"int64 neg":       {int64(-64), `"-64"`},
    34  		"int64 ptr":       {&i64, `"64"`},
    35  		"uint64":          {uint64(64), `"64"`},
    36  		"time":            {ti, `"2020-06-02T16:05:13.004346374Z"`},
    37  		"time empty":      {time.Time{}, `"0001-01-01T00:00:00Z"`},
    38  		"time ptr":        {&ti, `"2020-06-02T16:05:13.004346374Z"`},
    39  		"customptr":       {CustomPtr{Value: "x"}, `{"Value":"x"}`}, // same as encoding/json
    40  		"customptr ptr":   {&CustomPtr{Value: "x"}, `"custom"`},
    41  		"customvalue":     {CustomValue{Value: "x"}, `"custom"`},
    42  		"customvalue ptr": {&CustomValue{Value: "x"}, `"custom"`},
    43  		"slice nil":       {[]int(nil), `null`},
    44  		"slice empty":     {[]int{}, `[]`},
    45  		"slice bytes":     {[]byte{1, 2, 3}, `"AQID"`},
    46  		"slice int64":     {[]int64{1, 2, 3}, `["1","2","3"]`},
    47  		"slice int64 ptr": {[]*int64{&i64, nil}, `["64",null]`},
    48  		"array bytes":     {[3]byte{1, 2, 3}, `"AQID"`},
    49  		"array int64":     {[3]int64{1, 2, 3}, `["1","2","3"]`},
    50  		"map nil":         {map[string]int64(nil), `{}`}, // retain Amino compatibility
    51  		"map empty":       {map[string]int64{}, `{}`},
    52  		"map int64":       {map[string]int64{"a": 1, "b": 2, "c": 3}, `{"a":"1","b":"2","c":"3"}`},
    53  		"car":             {car, `{"type":"vehicle/car","value":{"Wheels":4}}`},
    54  		"car value":       {*car, `{"type":"vehicle/car","value":{"Wheels":4}}`},
    55  		"car iface":       {Vehicle(car), `{"type":"vehicle/car","value":{"Wheels":4}}`},
    56  		"car nil":         {(*Car)(nil), `null`},
    57  		"boat":            {boat, `{"type":"vehicle/boat","value":{"Sail":true}}`},
    58  		"boat ptr":        {&boat, `{"type":"vehicle/boat","value":{"Sail":true}}`},
    59  		"boat iface":      {Vehicle(boat), `{"type":"vehicle/boat","value":{"Sail":true}}`},
    60  		"key public":      {PublicKey{1, 2, 3, 4, 5, 6, 7, 8}, `{"type":"key/public","value":"AQIDBAUGBwg="}`},
    61  		"tags": {
    62  			Tags{JSONName: "name", OmitEmpty: "foo", Hidden: "bar", Tags: &Tags{JSONName: "child"}},
    63  			`{"name":"name","OmitEmpty":"foo","tags":{"name":"child"}}`,
    64  		},
    65  		"tags empty": {Tags{}, `{"name":""}`},
    66  		// The encoding of the Car and Boat fields do not have type wrappers, even though they get
    67  		// type wrappers when encoded directly (see "car" and "boat" tests). This is to retain the
    68  		// same behavior as Amino. If the field was a Vehicle interface instead, it would get
    69  		// type wrappers, as seen in the Vehicles field.
    70  		"struct": {
    71  			Struct{
    72  				Bool: true, Float64: 3.14, Int32: 32, Int64: 64, Int64Ptr: &i64,
    73  				String: "foo", StringPtrPtr: &sPtr, Bytes: []byte{1, 2, 3},
    74  				Time: ti, Car: car, Boat: boat, Vehicles: []Vehicle{car, boat},
    75  				Child: &Struct{Bool: false, String: "child"}, private: "private",
    76  			},
    77  			`{
    78  				"Bool":true, "Float64":3.14, "Int32":32, "Int64":"64", "Int64Ptr":"64",
    79  				"String":"foo", "StringPtrPtr": "string", "Bytes":"AQID",
    80  				"Time":"2020-06-02T16:05:13.004346374Z",
    81  				"Car":{"Wheels":4},
    82  				"Boat":{"Sail":true},
    83  				"Vehicles":[
    84  					{"type":"vehicle/car","value":{"Wheels":4}},
    85  					{"type":"vehicle/boat","value":{"Sail":true}}
    86  				],
    87  				"Child":{
    88  					"Bool":false, "Float64":0, "Int32":0, "Int64":"0", "Int64Ptr":null,
    89  					"String":"child", "StringPtrPtr":null, "Bytes":null,
    90  					"Time":"0001-01-01T00:00:00Z",
    91  					"Car":null, "Boat":{"Sail":false}, "Vehicles":null, "Child":null
    92  				}
    93  			}`,
    94  		},
    95  	}
    96  	for name, tc := range testcases {
    97  		tc := tc
    98  		t.Run(name, func(t *testing.T) {
    99  			bz, err := json.Marshal(tc.value)
   100  			require.NoError(t, err)
   101  			assert.JSONEq(t, tc.output, string(bz))
   102  		})
   103  	}
   104  }