|
|
@@ -36,6 +36,7 @@ import (
|
|
|
"encoding/json"
|
|
|
"io"
|
|
|
"reflect"
|
|
|
+ "strings"
|
|
|
"testing"
|
|
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
|
@@ -410,66 +411,69 @@ func TestMarshaling(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
var unmarshalingTests = []struct {
|
|
|
- desc string
|
|
|
- json string
|
|
|
- pb proto.Message
|
|
|
+ desc string
|
|
|
+ unmarshaler Unmarshaler
|
|
|
+ json string
|
|
|
+ pb proto.Message
|
|
|
}{
|
|
|
- {"simple flat object", simpleObjectJSON, simpleObject},
|
|
|
- {"simple pretty object", simpleObjectPrettyJSON, simpleObject},
|
|
|
- {"repeated fields flat object", repeatsObjectJSON, repeatsObject},
|
|
|
- {"repeated fields pretty object", repeatsObjectPrettyJSON, repeatsObject},
|
|
|
- {"nested message/enum flat object", complexObjectJSON, complexObject},
|
|
|
- {"nested message/enum pretty object", complexObjectPrettyJSON, complexObject},
|
|
|
- {"enum-string object", `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
|
|
|
- {"enum-value object", "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
|
|
|
- {"proto3 enum string", `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
|
|
- {"proto3 enum value", `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
|
|
+ {"simple flat object", Unmarshaler{}, simpleObjectJSON, simpleObject},
|
|
|
+ {"simple pretty object", Unmarshaler{}, simpleObjectPrettyJSON, simpleObject},
|
|
|
+ {"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
|
|
|
+ {"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
|
|
|
+ {"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
|
|
|
+ {"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
|
|
|
+ {"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
|
|
|
+ {"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
|
|
|
+ {"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
|
|
|
+ {"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
|
|
+ {"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
|
|
{"unknown enum value object",
|
|
|
+ Unmarshaler{},
|
|
|
"{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}",
|
|
|
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
|
|
|
- {"repeated proto3 enum", `{"rFunny":["PUNS","SLAPSTICK"]}`,
|
|
|
+ {"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
|
|
|
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
|
|
proto3pb.Message_PUNS,
|
|
|
proto3pb.Message_SLAPSTICK,
|
|
|
}}},
|
|
|
- {"repeated proto3 enum as int", `{"rFunny":[1,2]}`,
|
|
|
+ {"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
|
|
|
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
|
|
proto3pb.Message_PUNS,
|
|
|
proto3pb.Message_SLAPSTICK,
|
|
|
}}},
|
|
|
- {"repeated proto3 enum as mix of strings and ints", `{"rFunny":["PUNS",2]}`,
|
|
|
+ {"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
|
|
|
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
|
|
proto3pb.Message_PUNS,
|
|
|
proto3pb.Message_SLAPSTICK,
|
|
|
}}},
|
|
|
- {"unquoted int64 object", `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
|
|
|
- {"unquoted uint64 object", `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
|
|
|
- {"map<int64, int32>", `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
|
|
|
- {"map<string, string>", `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
|
|
|
- {"map<int32, Object>", `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}},
|
|
|
+ {"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
|
|
|
+ {"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
|
|
|
+ {"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
|
|
|
+ {"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
|
|
|
+ {"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}},
|
|
|
// TODO: This is broken.
|
|
|
- //{"map<string, enum>", `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
|
|
|
- {"map<string, enum as int>", `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
|
|
|
- {"oneof", `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
|
|
|
- {"oneof spec name", `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
|
|
|
- {"oneof orig_name", `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
|
|
|
- {"orig_name input", `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
|
|
|
- {"camelName input", `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
|
|
|
-
|
|
|
- {"Duration", `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
|
|
|
- {"Timestamp", `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
|
|
|
-
|
|
|
- {"DoubleValue", `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
|
|
|
- {"FloatValue", `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
|
|
|
- {"Int64Value", `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
|
|
|
- {"UInt64Value", `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
|
|
|
- {"Int32Value", `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
|
|
|
- {"UInt32Value", `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
|
|
|
- {"BoolValue", `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
|
|
|
- {"StringValue", `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
|
|
|
- {"BytesValue", `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
|
|
|
+ //{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
|
|
|
+ {"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
|
|
|
+ {"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
|
|
|
+ {"oneof spec name", Unmarshaler{}, `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
|
|
|
+ {"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
|
|
|
+ {"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
|
|
|
+ {"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
|
|
|
+
|
|
|
+ {"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
|
|
|
+ {"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
|
|
|
+
|
|
|
+ {"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
|
|
|
+ {"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
|
|
|
+ {"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
|
|
|
+ {"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
|
|
|
+ {"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
|
|
|
+ {"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
|
|
|
+ {"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
|
|
|
+ {"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
|
|
|
+ {"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
|
|
|
// `null` is also a permissible value. Let's just test one.
|
|
|
- {"null DoubleValue", `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}},
|
|
|
+ {"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}},
|
|
|
}
|
|
|
|
|
|
func TestUnmarshaling(t *testing.T) {
|
|
|
@@ -477,7 +481,7 @@ func TestUnmarshaling(t *testing.T) {
|
|
|
// Make a new instance of the type of our expected object.
|
|
|
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
|
|
|
|
|
|
- err := UnmarshalString(tt.json, p)
|
|
|
+ err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
|
|
|
if err != nil {
|
|
|
t.Errorf("%s: %v", tt.desc, err)
|
|
|
continue
|
|
|
@@ -507,7 +511,7 @@ func TestUnmarshalNext(t *testing.T) {
|
|
|
// Make a new instance of the type of our expected object.
|
|
|
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
|
|
|
|
|
|
- err := UnmarshalNext(dec, p)
|
|
|
+ err := tt.unmarshaler.UnmarshalNext(dec, p)
|
|
|
if err != nil {
|
|
|
t.Errorf("%s: %v", tt.desc, err)
|
|
|
continue
|
|
|
@@ -522,7 +526,7 @@ func TestUnmarshalNext(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
p := &pb.Simple{}
|
|
|
- err := UnmarshalNext(dec, p)
|
|
|
+ err := new(Unmarshaler).UnmarshalNext(dec, p)
|
|
|
if err != io.EOF {
|
|
|
t.Errorf("eof: got %v, expected io.EOF", err)
|
|
|
}
|
|
|
@@ -535,6 +539,7 @@ var unmarshalingShouldError = []struct {
|
|
|
}{
|
|
|
{"a value", "666", new(pb.Simple)},
|
|
|
{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
|
|
|
+ {"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
|
|
|
{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
|
|
|
}
|
|
|
|