cbor/json_test.go
Faye Amacker d1b239987b Rename ByteSliceMode to ByteSliceLaterFormatMode
Also renamed related options to be consistent.
2024-06-09 21:16:42 -05:00

133 lines
3.4 KiB
Go

package cbor_test
import (
"encoding/json"
"reflect"
"testing"
"github.com/fxamacker/cbor/v2"
)
// TestStdlibJSONCompatibility tests compatibility as a drop-in replacement for the standard library
// encoding/json package on a round trip encoding from Go object to interface{}.
func TestStdlibJSONCompatibility(t *testing.T) {
// TODO: With better coverage and compatibility, it could be useful to expose these option
// configurations to users.
enc, err := cbor.EncOptions{
ByteSliceLaterFormat: cbor.ByteSliceLaterFormatBase64,
String: cbor.StringToByteString,
ByteArray: cbor.ByteArrayToArray,
}.EncMode()
if err != nil {
t.Fatal(err)
}
dec, err := cbor.DecOptions{
DefaultByteStringType: reflect.TypeOf(""),
ByteStringToString: cbor.ByteStringToStringAllowedWithExpectedLaterEncoding,
ByteStringExpectedFormat: cbor.ByteStringExpectedBase64,
}.DecMode()
if err != nil {
t.Fatal(err)
}
for _, tc := range []struct {
name string
original interface{}
ifaceEqual bool // require equal intermediate interface{} values from both protocols
}{
{
name: "byte slice to base64-encoded string",
original: []byte("hello world"),
ifaceEqual: true,
},
{
name: "byte array to array of integers",
original: [11]byte{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'},
ifaceEqual: false, // encoding/json decodes the array elements to float64
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Logf("original: %#v", tc.original)
j1, err := json.Marshal(tc.original)
if err != nil {
t.Fatal(err)
}
t.Logf("original to json: %s", string(j1))
c1, err := enc.Marshal(tc.original)
if err != nil {
t.Fatal(err)
}
diag1, err := cbor.Diagnose(c1)
if err != nil {
t.Fatal(err)
}
t.Logf("original to cbor: %s", diag1)
var jintf interface{}
err = json.Unmarshal(j1, &jintf)
if err != nil {
t.Fatal(err)
}
t.Logf("json to interface{} (%T): %#v", jintf, jintf)
var cintf interface{}
err = dec.Unmarshal(c1, &cintf)
if err != nil {
t.Fatal(err)
}
t.Logf("cbor to interface{} (%T): %#v", cintf, cintf)
j2, err := json.Marshal(jintf)
if err != nil {
t.Fatal(err)
}
t.Logf("interface{} to json: %s", string(j2))
c2, err := enc.Marshal(cintf)
if err != nil {
t.Fatal(err)
}
diag2, err := cbor.Diagnose(c2)
if err != nil {
t.Fatal(err)
}
t.Logf("interface{} to cbor: %s", diag2)
if !reflect.DeepEqual(jintf, cintf) {
if tc.ifaceEqual {
t.Errorf("native-to-interface{} via cbor differed from native-to-interface{} via json")
} else {
t.Logf("native-to-interface{} via cbor differed from native-to-interface{} via json")
}
}
jfinalValue := reflect.New(reflect.TypeOf(tc.original))
err = json.Unmarshal(j2, jfinalValue.Interface())
if err != nil {
t.Fatal(err)
}
jfinal := jfinalValue.Elem().Interface()
t.Logf("json to native: %#v", jfinal)
if !reflect.DeepEqual(tc.original, jfinal) {
t.Error("diff in json roundtrip")
}
cfinalValue := reflect.New(reflect.TypeOf(tc.original))
err = dec.Unmarshal(c2, cfinalValue.Interface())
if err != nil {
t.Fatal(err)
}
cfinal := cfinalValue.Elem().Interface()
t.Logf("cbor to native: %#v", cfinal)
if !reflect.DeepEqual(tc.original, cfinal) {
t.Error("diff in cbor roundtrip")
}
})
}
}