You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
4.2 KiB

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