encoding/textpb: add AllowPartial option to MarshalOptions and UnmarshalOptions
Provide AllowPartial option to accept messages with missing required
field during marshaling and unmarshaling.
Change-Id: Ia23783870a8125633f8ddc0b686984b4c5ca15ba
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/169500
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/encoding/textpb/decode_test.go b/encoding/textpb/decode_test.go
index 44f4daf..2f4045c 100644
--- a/encoding/textpb/decode_test.go
+++ b/encoding/textpb/decode_test.go
@@ -952,18 +952,18 @@
},
},
}, {
- desc: "proto2 required fields not set",
+ desc: "required fields not set",
inputMessage: &pb2.Requireds{},
wantErr: true,
}, {
- desc: "proto2 required field set",
+ desc: "required field set",
inputMessage: &pb2.PartialRequired{},
inputText: "req_string: 'this is required'",
wantMessage: &pb2.PartialRequired{
ReqString: scalar.String("this is required"),
},
}, {
- desc: "proto2 required fields partially set",
+ desc: "required fields partially set",
inputMessage: &pb2.Requireds{},
inputText: `
req_bool: false
@@ -979,7 +979,23 @@
},
wantErr: true,
}, {
- desc: "proto2 required fields all set",
+ desc: "required fields partially set with AllowPartial",
+ umo: textpb.UnmarshalOptions{AllowPartial: true},
+ inputMessage: &pb2.Requireds{},
+ inputText: `
+req_bool: false
+req_sfixed64: 3203386110
+req_string: "hello"
+req_enum: ONE
+`,
+ wantMessage: &pb2.Requireds{
+ ReqBool: scalar.Bool(false),
+ ReqSfixed64: scalar.Int64(0xbeefcafe),
+ ReqString: scalar.String("hello"),
+ ReqEnum: pb2.Enum_ONE.Enum(),
+ },
+ }, {
+ desc: "required fields all set",
inputMessage: &pb2.Requireds{},
inputText: `
req_bool: false
@@ -1006,6 +1022,14 @@
},
wantErr: true,
}, {
+ desc: "indirect required field with AllowPartial",
+ umo: textpb.UnmarshalOptions{AllowPartial: true},
+ inputMessage: &pb2.IndirectRequired{},
+ inputText: "opt_nested: {}",
+ wantMessage: &pb2.IndirectRequired{
+ OptNested: &pb2.NestedWithRequired{},
+ },
+ }, {
desc: "indirect required field in repeated",
inputMessage: &pb2.IndirectRequired{},
inputText: `
@@ -1013,9 +1037,6 @@
req_string: "one"
}
rpt_nested: {}
-rpt_nested: {
- req_string: "three"
-}
`,
wantMessage: &pb2.IndirectRequired{
RptNested: []*pb2.NestedWithRequired{
@@ -1023,13 +1044,28 @@
ReqString: scalar.String("one"),
},
{},
- {
- ReqString: scalar.String("three"),
- },
},
},
wantErr: true,
}, {
+ desc: "indirect required field in repeated with AllowPartial",
+ umo: textpb.UnmarshalOptions{AllowPartial: true},
+ inputMessage: &pb2.IndirectRequired{},
+ inputText: `
+rpt_nested: {
+ req_string: "one"
+}
+rpt_nested: {}
+`,
+ wantMessage: &pb2.IndirectRequired{
+ RptNested: []*pb2.NestedWithRequired{
+ {
+ ReqString: scalar.String("one"),
+ },
+ {},
+ },
+ },
+ }, {
desc: "indirect required field in map",
inputMessage: &pb2.IndirectRequired{},
inputText: `
@@ -1053,6 +1089,29 @@
},
wantErr: true,
}, {
+ desc: "indirect required field in map with AllowPartial",
+ umo: textpb.UnmarshalOptions{AllowPartial: true},
+ inputMessage: &pb2.IndirectRequired{},
+ inputText: `
+str_to_nested: {
+ key: "missing"
+}
+str_to_nested: {
+ key: "contains"
+ value: {
+ req_string: "here"
+ }
+}
+`,
+ wantMessage: &pb2.IndirectRequired{
+ StrToNested: map[string]*pb2.NestedWithRequired{
+ "missing": &pb2.NestedWithRequired{},
+ "contains": &pb2.NestedWithRequired{
+ ReqString: scalar.String("here"),
+ },
+ },
+ },
+ }, {
desc: "indirect required field in oneof",
inputMessage: &pb2.IndirectRequired{},
inputText: `oneof_nested: {}
@@ -1064,6 +1123,17 @@
},
wantErr: true,
}, {
+ desc: "indirect required field in oneof with AllowPartial",
+ umo: textpb.UnmarshalOptions{AllowPartial: true},
+ inputMessage: &pb2.IndirectRequired{},
+ inputText: `oneof_nested: {}
+`,
+ wantMessage: &pb2.IndirectRequired{
+ Union: &pb2.IndirectRequired_OneofNested{
+ OneofNested: &pb2.NestedWithRequired{},
+ },
+ },
+ }, {
desc: "ignore reserved field",
inputMessage: &pb2.Nests{},
inputText: "reserved_field: 'ignore this'",