mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-29 18:32:46 +00:00
encoding/prototext: add proto editions and fuzz tests
Change-Id: I2afc5ae83bf68600def3568e1d3ad51ef00e7671 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/566395 Auto-Submit: Lasse Folger <lassefolger@google.com> Reviewed-by: Michael Stapelberg <stapelberg@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
2caa6b02a2
commit
055c812a4f
@ -9,7 +9,7 @@ package goproto.protoc.import_public;
|
||||
// Same Go package.
|
||||
import public "cmd/protoc-gen-go/testdata/import_public/b.proto";
|
||||
|
||||
// Different Go package.
|
||||
// Different Go package.
|
||||
import public "cmd/protoc-gen-go/testdata/import_public/sub/a.proto";
|
||||
|
||||
option go_package = "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/import_public";
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
weakpb "google.golang.org/protobuf/internal/testprotos/test/weak1"
|
||||
pb2 "google.golang.org/protobuf/internal/testprotos/textpb2"
|
||||
pb3 "google.golang.org/protobuf/internal/testprotos/textpb3"
|
||||
pbeditions "google.golang.org/protobuf/internal/testprotos/textpbeditions"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
)
|
||||
|
||||
@ -70,6 +71,62 @@ opt_string: ""
|
||||
OptBytes: []byte{},
|
||||
OptString: proto.String(""),
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions explicit scalars set to zero values",
|
||||
inputMessage: &pbeditions.Scalars{},
|
||||
inputText: `opt_bool: false
|
||||
opt_int32: 0
|
||||
opt_int64: 0
|
||||
opt_uint32: 0
|
||||
opt_uint64: 0
|
||||
opt_sint32: 0
|
||||
opt_sint64: 0
|
||||
opt_fixed32: 0
|
||||
opt_fixed64: 0
|
||||
opt_sfixed32: 0
|
||||
opt_sfixed64: 0
|
||||
opt_float: 0
|
||||
opt_double: 0
|
||||
opt_bytes: ""
|
||||
opt_string: ""
|
||||
`,
|
||||
wantMessage: &pbeditions.Scalars{
|
||||
OptBool: proto.Bool(false),
|
||||
OptInt32: proto.Int32(0),
|
||||
OptInt64: proto.Int64(0),
|
||||
OptUint32: proto.Uint32(0),
|
||||
OptUint64: proto.Uint64(0),
|
||||
OptSint32: proto.Int32(0),
|
||||
OptSint64: proto.Int64(0),
|
||||
OptFixed32: proto.Uint32(0),
|
||||
OptFixed64: proto.Uint64(0),
|
||||
OptSfixed32: proto.Int32(0),
|
||||
OptSfixed64: proto.Int64(0),
|
||||
OptFloat: proto.Float32(0),
|
||||
OptDouble: proto.Float64(0),
|
||||
OptBytes: []byte{},
|
||||
OptString: proto.String(""),
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions implicit scalars set to zero values",
|
||||
inputMessage: &pbeditions.ImplicitScalars{},
|
||||
inputText: `s_bool: false
|
||||
s_int32: 0
|
||||
s_int64: 0
|
||||
s_uint32: 0
|
||||
s_uint64: 0
|
||||
s_sint32: 0
|
||||
s_sint64: 0
|
||||
s_fixed32: 0
|
||||
s_fixed64: 0
|
||||
s_sfixed32: 0
|
||||
s_sfixed64: 0
|
||||
s_float: 0
|
||||
s_double: 0
|
||||
s_bytes: ""
|
||||
s_string: ""
|
||||
`,
|
||||
wantMessage: &pbeditions.ImplicitScalars{},
|
||||
}, {
|
||||
desc: "proto3 scalars set to zero values",
|
||||
inputMessage: &pb3.Scalars{},
|
||||
@ -150,6 +207,38 @@ opt_string: "谷歌"
|
||||
OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
||||
OptString: proto.String("谷歌"),
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions explicit scalars",
|
||||
inputMessage: &pbeditions.Scalars{},
|
||||
inputText: `opt_bool: true
|
||||
opt_int32: 255
|
||||
opt_int64: 3735928559
|
||||
opt_uint32: 0xff
|
||||
opt_uint64: 0xdeadbeef
|
||||
opt_sint32: -1001
|
||||
opt_sint64: - 0xffff
|
||||
opt_fixed64: 64
|
||||
opt_sfixed32: - 32
|
||||
opt_float: 1.234
|
||||
opt_double: 1.23e+100
|
||||
opt_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
|
||||
opt_string: "谷歌"
|
||||
`,
|
||||
wantMessage: &pbeditions.Scalars{
|
||||
OptBool: proto.Bool(true),
|
||||
OptInt32: proto.Int32(0xff),
|
||||
OptInt64: proto.Int64(0xdeadbeef),
|
||||
OptUint32: proto.Uint32(0xff),
|
||||
OptUint64: proto.Uint64(0xdeadbeef),
|
||||
OptSint32: proto.Int32(-1001),
|
||||
OptSint64: proto.Int64(-0xffff),
|
||||
OptFixed64: proto.Uint64(64),
|
||||
OptSfixed32: proto.Int32(-32),
|
||||
OptFloat: proto.Float32(1.234),
|
||||
OptDouble: proto.Float64(1.23e100),
|
||||
OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
||||
OptString: proto.String("谷歌"),
|
||||
},
|
||||
}, {
|
||||
desc: "case sensitive",
|
||||
inputMessage: &pb3.Scalars{},
|
||||
@ -195,6 +284,13 @@ s_string: "谷歌"
|
||||
wantMessage: &pb2.Scalars{
|
||||
OptString: proto.String("abc\xff"),
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions unvalidated string with invalid UTF-8",
|
||||
inputMessage: &pbeditions.Scalars{},
|
||||
inputText: `opt_string: "abc\xff"`,
|
||||
wantMessage: &pbeditions.Scalars{
|
||||
OptString: proto.String("abc\xff"),
|
||||
},
|
||||
}, {
|
||||
desc: "proto3 string with invalid UTF-8",
|
||||
inputMessage: &pb3.Scalars{},
|
||||
@ -215,6 +311,11 @@ s_string: "谷歌"
|
||||
umo: prototext.UnmarshalOptions{DiscardUnknown: true},
|
||||
inputMessage: &pb2.Scalars{},
|
||||
inputText: `unknown_field:123 1000:"hello"`,
|
||||
}, {
|
||||
desc: "protoeditions message contains discarded unknown field",
|
||||
umo: prototext.UnmarshalOptions{DiscardUnknown: true},
|
||||
inputMessage: &pbeditions.Scalars{},
|
||||
inputText: `unknown_field:123 1000:"hello"`,
|
||||
}, {
|
||||
desc: "proto3 message contains discarded unknown field",
|
||||
umo: prototext.UnmarshalOptions{DiscardUnknown: true},
|
||||
@ -408,6 +509,39 @@ opt_nested_enum: UNO
|
||||
OptEnum: pb2.Enum_ONE.Enum(),
|
||||
OptNestedEnum: pb2.Enums_UNO.Enum(),
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions closed enum",
|
||||
inputMessage: &pbeditions.Enums{},
|
||||
inputText: `
|
||||
opt_enum: ONE
|
||||
opt_nested_enum: UNO
|
||||
`,
|
||||
wantMessage: &pbeditions.Enums{
|
||||
OptEnum: pbeditions.Enum_ONE.Enum(),
|
||||
OptNestedEnum: pbeditions.Enums_UNO.Enum(),
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions open enum",
|
||||
inputMessage: &pbeditions.Enums{},
|
||||
inputText: `
|
||||
implicit_enum: EINS
|
||||
implicit_nested_enum: ZEHN
|
||||
`,
|
||||
wantMessage: &pbeditions.Enums{
|
||||
ImplicitEnum: pbeditions.OpenEnum_EINS,
|
||||
ImplicitNestedEnum: pbeditions.Enums_ZEHN,
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions enum numeric value",
|
||||
inputMessage: &pbeditions.Enums{},
|
||||
inputText: `
|
||||
implicit_enum: 1
|
||||
implicit_nested_enum: 10
|
||||
`,
|
||||
wantMessage: &pbeditions.Enums{
|
||||
ImplicitEnum: pbeditions.OpenEnum_EINS,
|
||||
ImplicitNestedEnum: pbeditions.Enums_ZEHN,
|
||||
},
|
||||
}, {
|
||||
desc: "proto2 enum set to numeric values",
|
||||
inputMessage: &pb2.Enums{},
|
||||
@ -482,6 +616,17 @@ OptGroup: {}
|
||||
OptNested: &pb2.Nested{},
|
||||
Optgroup: &pb2.Nests_OptGroup{},
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions nested empty messages",
|
||||
inputMessage: &pbeditions.Nests{},
|
||||
inputText: `
|
||||
opt_nested: {}
|
||||
OptGroup: {}
|
||||
`,
|
||||
wantMessage: &pbeditions.Nests{
|
||||
OptNested: &pbeditions.Nested{},
|
||||
Optgroup: &pbeditions.Nests_OptGroup{},
|
||||
},
|
||||
}, {
|
||||
desc: "message fields with no field separator",
|
||||
inputMessage: &pb2.Nests{},
|
||||
@ -493,11 +638,27 @@ OptGroup {}
|
||||
OptNested: &pb2.Nested{},
|
||||
Optgroup: &pb2.Nests_OptGroup{},
|
||||
},
|
||||
}, {
|
||||
desc: "message fields with no field separator",
|
||||
inputMessage: &pbeditions.Nests{},
|
||||
inputText: `
|
||||
opt_nested {}
|
||||
OptGroup {}
|
||||
`,
|
||||
wantMessage: &pbeditions.Nests{
|
||||
OptNested: &pbeditions.Nested{},
|
||||
Optgroup: &pbeditions.Nests_OptGroup{},
|
||||
},
|
||||
}, {
|
||||
desc: "group field name",
|
||||
inputMessage: &pb2.Nests{},
|
||||
inputText: `optgroup: {}`,
|
||||
wantErr: "unknown field: optgroup",
|
||||
}, {
|
||||
desc: "delimited encoded message field name",
|
||||
inputMessage: &pbeditions.Nests{},
|
||||
inputText: `optgroup: {}`,
|
||||
wantErr: "unknown field: optgroup",
|
||||
}, {
|
||||
desc: "proto2 nested messages",
|
||||
inputMessage: &pb2.Nests{},
|
||||
@ -517,6 +678,25 @@ opt_nested: {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
desc: "protoeditions delimited encoded nested messages",
|
||||
inputMessage: &pbeditions.Nests{},
|
||||
inputText: `
|
||||
opt_nested: {
|
||||
opt_string: "nested message"
|
||||
opt_nested: {
|
||||
opt_string: "another nested message"
|
||||
}
|
||||
}
|
||||
`,
|
||||
wantMessage: &pbeditions.Nests{
|
||||
OptNested: &pbeditions.Nested{
|
||||
OptString: proto.String("nested message"),
|
||||
OptNested: &pbeditions.Nested{
|
||||
OptString: proto.String("another nested message"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
desc: "proto3 nested empty message",
|
||||
inputMessage: &pb3.Nests{},
|
||||
@ -711,6 +891,24 @@ RptGroup: {}
|
||||
{},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
desc: "repeated delimited encoded message fields",
|
||||
inputMessage: &pbeditions.Nests{},
|
||||
inputText: `
|
||||
RptGroup: {
|
||||
rpt_string: "hello"
|
||||
rpt_string: "world"
|
||||
}
|
||||
RptGroup: {}
|
||||
`,
|
||||
wantMessage: &pbeditions.Nests{
|
||||
Rptgroup: []*pbeditions.Nests_RptGroup{
|
||||
{
|
||||
RptString: []string{"hello", "world"},
|
||||
},
|
||||
{},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
desc: "repeated message fields without field separator",
|
||||
inputMessage: &pb2.Nests{},
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
|
||||
pb2 "google.golang.org/protobuf/internal/testprotos/textpb2"
|
||||
pb3 "google.golang.org/protobuf/internal/testprotos/textpb3"
|
||||
pbeditions "google.golang.org/protobuf/internal/testprotos/textpbeditions"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
)
|
||||
|
||||
@ -40,6 +41,10 @@ func TestMarshal(t *testing.T) {
|
||||
desc: "proto2 optional scalars not set",
|
||||
input: &pb2.Scalars{},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "protoeditions optional scalars not set",
|
||||
input: &pbeditions.Scalars{},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "proto3 scalars not set",
|
||||
input: &pb3.Scalars{},
|
||||
@ -48,6 +53,10 @@ func TestMarshal(t *testing.T) {
|
||||
desc: "proto3 optional not set",
|
||||
input: &pb3.Proto3Optional{},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "protoeditions implicit not set",
|
||||
input: &pbeditions.ImplicitScalars{},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "proto2 optional scalars set to zero values",
|
||||
input: &pb2.Scalars{
|
||||
@ -82,6 +91,41 @@ opt_float: 0
|
||||
opt_double: 0
|
||||
opt_bytes: ""
|
||||
opt_string: ""
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions optional scalars set to zero values",
|
||||
input: &pbeditions.Scalars{
|
||||
OptBool: proto.Bool(false),
|
||||
OptInt32: proto.Int32(0),
|
||||
OptInt64: proto.Int64(0),
|
||||
OptUint32: proto.Uint32(0),
|
||||
OptUint64: proto.Uint64(0),
|
||||
OptSint32: proto.Int32(0),
|
||||
OptSint64: proto.Int64(0),
|
||||
OptFixed32: proto.Uint32(0),
|
||||
OptFixed64: proto.Uint64(0),
|
||||
OptSfixed32: proto.Int32(0),
|
||||
OptSfixed64: proto.Int64(0),
|
||||
OptFloat: proto.Float32(0),
|
||||
OptDouble: proto.Float64(0),
|
||||
OptBytes: []byte{},
|
||||
OptString: proto.String(""),
|
||||
},
|
||||
want: `opt_bool: false
|
||||
opt_int32: 0
|
||||
opt_int64: 0
|
||||
opt_uint32: 0
|
||||
opt_uint64: 0
|
||||
opt_sint32: 0
|
||||
opt_sint64: 0
|
||||
opt_fixed32: 0
|
||||
opt_fixed64: 0
|
||||
opt_sfixed32: 0
|
||||
opt_sfixed64: 0
|
||||
opt_float: 0
|
||||
opt_double: 0
|
||||
opt_bytes: ""
|
||||
opt_string: ""
|
||||
`,
|
||||
}, {
|
||||
desc: "proto3 optional set to zero values",
|
||||
@ -130,6 +174,26 @@ opt_message: {}
|
||||
SString: "",
|
||||
},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "protoeditions implicit scalars set to zero values",
|
||||
input: &pbeditions.ImplicitScalars{
|
||||
SBool: false,
|
||||
SInt32: 0,
|
||||
SInt64: 0,
|
||||
SUint32: 0,
|
||||
SUint64: 0,
|
||||
SSint32: 0,
|
||||
SSint64: 0,
|
||||
SFixed32: 0,
|
||||
SFixed64: 0,
|
||||
SSfixed32: 0,
|
||||
SSfixed64: 0,
|
||||
SFloat: 0,
|
||||
SDouble: 0,
|
||||
SBytes: []byte{},
|
||||
SString: "",
|
||||
},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "proto2 optional scalars set to some values",
|
||||
input: &pb2.Scalars{
|
||||
@ -160,6 +224,37 @@ opt_float: 1.02
|
||||
opt_double: 1.0199999809265137
|
||||
opt_bytes: "谷歌"
|
||||
opt_string: "谷歌"
|
||||
`,
|
||||
}, {
|
||||
desc: "proto editions optional scalars set to some values",
|
||||
input: &pbeditions.Scalars{
|
||||
OptBool: proto.Bool(true),
|
||||
OptInt32: proto.Int32(0xff),
|
||||
OptInt64: proto.Int64(0xdeadbeef),
|
||||
OptUint32: proto.Uint32(47),
|
||||
OptUint64: proto.Uint64(0xdeadbeef),
|
||||
OptSint32: proto.Int32(-1001),
|
||||
OptSint64: proto.Int64(-0xffff),
|
||||
OptFixed64: proto.Uint64(64),
|
||||
OptSfixed32: proto.Int32(-32),
|
||||
OptFloat: proto.Float32(1.02),
|
||||
OptDouble: proto.Float64(1.0199999809265137),
|
||||
OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
||||
OptString: proto.String("谷歌"),
|
||||
},
|
||||
want: `opt_bool: true
|
||||
opt_int32: 255
|
||||
opt_int64: 3735928559
|
||||
opt_uint32: 47
|
||||
opt_uint64: 3735928559
|
||||
opt_sint32: -1001
|
||||
opt_sint64: -65535
|
||||
opt_fixed64: 64
|
||||
opt_sfixed32: -32
|
||||
opt_float: 1.02
|
||||
opt_double: 1.0199999809265137
|
||||
opt_bytes: "谷歌"
|
||||
opt_string: "谷歌"
|
||||
`,
|
||||
}, {
|
||||
desc: "proto2 string with invalid UTF-8",
|
||||
@ -167,6 +262,13 @@ opt_string: "谷歌"
|
||||
OptString: proto.String("abc\xff"),
|
||||
},
|
||||
want: `opt_string: "abc\xff"
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions string with invalid UTF-8",
|
||||
input: &pbeditions.Scalars{
|
||||
OptString: proto.String("abc\xff"),
|
||||
},
|
||||
want: `opt_string: "abc\xff"
|
||||
`,
|
||||
}, {
|
||||
desc: "proto3 string with invalid UTF-8",
|
||||
@ -174,6 +276,12 @@ opt_string: "谷歌"
|
||||
SString: "abc\xff",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
desc: "protoeditions utf8 validated string with invalid UTF-8",
|
||||
input: &pbeditions.UTF8Validated{
|
||||
ValidatedString: "abc\xff",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
desc: "float nan",
|
||||
input: &pb3.Scalars{
|
||||
@ -222,6 +330,15 @@ opt_string: "谷歌"
|
||||
},
|
||||
want: `opt_enum: 0
|
||||
opt_nested_enum: 0
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions enum set to zero value",
|
||||
input: &pbeditions.Enums{
|
||||
OptEnum: pbeditions.Enum(0).Enum(),
|
||||
OptNestedEnum: pbeditions.Enums_NestedEnum(0).Enum(),
|
||||
},
|
||||
want: `opt_enum: 0
|
||||
opt_nested_enum: 0
|
||||
`,
|
||||
}, {
|
||||
desc: "proto2 enum",
|
||||
@ -231,6 +348,15 @@ opt_nested_enum: 0
|
||||
},
|
||||
want: `opt_enum: ONE
|
||||
opt_nested_enum: UNO
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions enum",
|
||||
input: &pbeditions.Enums{
|
||||
OptEnum: pbeditions.Enum_ONE.Enum(),
|
||||
OptNestedEnum: pbeditions.Enums_UNO.Enum(),
|
||||
},
|
||||
want: `opt_enum: ONE
|
||||
opt_nested_enum: UNO
|
||||
`,
|
||||
}, {
|
||||
desc: "proto2 enum set to numeric values",
|
||||
@ -249,6 +375,15 @@ opt_nested_enum: DOS
|
||||
},
|
||||
want: `opt_enum: 101
|
||||
opt_nested_enum: -101
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions enum set to unnamed numeric values",
|
||||
input: &pbeditions.Enums{
|
||||
OptEnum: pbeditions.Enum(101).Enum(),
|
||||
OptNestedEnum: pbeditions.Enums_NestedEnum(-101).Enum(),
|
||||
},
|
||||
want: `opt_enum: 101
|
||||
opt_nested_enum: -101
|
||||
`,
|
||||
}, {
|
||||
desc: "proto3 enum not set",
|
||||
@ -261,6 +396,21 @@ opt_nested_enum: -101
|
||||
SNestedEnum: pb3.Enums_CERO,
|
||||
},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "protoeditions implicit enum field set to default value",
|
||||
input: &pbeditions.Enums{
|
||||
ImplicitEnum: pbeditions.OpenEnum_UNKNOWN,
|
||||
},
|
||||
want: "",
|
||||
}, {
|
||||
desc: "protoeditions implicit enum field",
|
||||
input: &pbeditions.Enums{
|
||||
ImplicitEnum: pbeditions.OpenEnum_EINS,
|
||||
ImplicitNestedEnum: pbeditions.Enums_ZEHN,
|
||||
},
|
||||
want: `implicit_enum: EINS
|
||||
implicit_nested_enum: ZEHN
|
||||
`,
|
||||
}, {
|
||||
desc: "proto3 enum",
|
||||
input: &pb3.Enums{
|
||||
@ -278,6 +428,15 @@ s_nested_enum: UNO
|
||||
},
|
||||
want: `s_enum: TWO
|
||||
s_nested_enum: DOS
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions implicit enum set to unnamed numeric values",
|
||||
input: &pbeditions.Enums{
|
||||
ImplicitEnum: -47,
|
||||
ImplicitNestedEnum: 47,
|
||||
},
|
||||
want: `implicit_enum: -47
|
||||
implicit_nested_enum: 47
|
||||
`,
|
||||
}, {
|
||||
desc: "proto3 enum set to unnamed numeric values",
|
||||
@ -300,6 +459,15 @@ s_nested_enum: 47
|
||||
},
|
||||
want: `opt_nested: {}
|
||||
OptGroup: {}
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions nested message set to empty",
|
||||
input: &pbeditions.Nests{
|
||||
OptNested: &pbeditions.Nested{},
|
||||
Optgroup: &pbeditions.Nests_OptGroup{},
|
||||
},
|
||||
want: `opt_nested: {}
|
||||
OptGroup: {}
|
||||
`,
|
||||
}, {
|
||||
desc: "proto2 nested messages",
|
||||
@ -317,6 +485,23 @@ OptGroup: {}
|
||||
opt_string: "another nested message"
|
||||
}
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions nested messages",
|
||||
input: &pbeditions.Nests{
|
||||
OptNested: &pbeditions.Nested{
|
||||
OptString: proto.String("nested message"),
|
||||
OptNested: &pbeditions.Nested{
|
||||
OptString: proto.String("another nested message"),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `opt_nested: {
|
||||
opt_string: "nested message"
|
||||
opt_nested: {
|
||||
opt_string: "another nested message"
|
||||
}
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
desc: "proto2 groups",
|
||||
@ -340,6 +525,29 @@ OptGroup: {}
|
||||
opt_fixed32: 47
|
||||
}
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
desc: "protoeditions delimited encoded meesage field",
|
||||
input: &pbeditions.Nests{
|
||||
Optgroup: &pbeditions.Nests_OptGroup{
|
||||
OptString: proto.String("inside a group"),
|
||||
OptNested: &pbeditions.Nested{
|
||||
OptString: proto.String("nested message inside a group"),
|
||||
},
|
||||
Optnestedgroup: &pbeditions.Nests_OptGroup_OptNestedGroup{
|
||||
OptFixed32: proto.Uint32(47),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `OptGroup: {
|
||||
opt_string: "inside a group"
|
||||
opt_nested: {
|
||||
opt_string: "nested message inside a group"
|
||||
}
|
||||
OptNestedGroup: {
|
||||
opt_fixed32: 47
|
||||
}
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
desc: "proto3 nested message not set",
|
||||
@ -376,6 +584,14 @@ OptGroup: {}
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
desc: "protoeditions nested message contains invalid UTF-8",
|
||||
input: &pbeditions.NestsUTF8Validated{
|
||||
ValidatedMessage: &pbeditions.UTF8Validated{
|
||||
ValidatedString: "abc\xff",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
desc: "oneof not set",
|
||||
input: &pb3.Oneofs{},
|
||||
@ -1427,7 +1643,7 @@ value: "\x80"
|
||||
t.Error("Marshal() got nil error, want error\n")
|
||||
}
|
||||
got := string(b)
|
||||
if tt.want != "" && got != tt.want {
|
||||
if got != tt.want {
|
||||
t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
|
||||
if diff := cmp.Diff(tt.want, got); diff != "" {
|
||||
t.Errorf("Marshal() diff -want +got\n%v\n", diff)
|
||||
|
98
encoding/prototext/fuzz_test.go
Normal file
98
encoding/prototext/fuzz_test.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Go native fuzzing was added in go1.18. Remove this once we stop supporting
|
||||
// go1.17.
|
||||
//go:build go1.18
|
||||
|
||||
package prototext_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
|
||||
testfuzzpb "google.golang.org/protobuf/internal/testprotos/editionsfuzztest"
|
||||
)
|
||||
|
||||
// roundTripAndCompareProto tests if a prototext.Marshal/Unmarshal roundtrip
|
||||
// preserves the contents of the message. Note: wireBytes are a protocol
|
||||
// buffer wire format message, not the proto in text format. We do this because
|
||||
// a random stream of bytes (e.g. generated by the fuzz engine) is more likely
|
||||
// to be valid proto wire format than that it is valid text format.
|
||||
func roundTripAndCompareProto(t *testing.T, wireBytes []byte, messages ...proto.Message) {
|
||||
for _, msg := range messages {
|
||||
src := msg.ProtoReflect().Type().New().Interface()
|
||||
|
||||
if err := proto.Unmarshal(wireBytes, src); err != nil {
|
||||
// Ignoring invalid wire format since we want to test the prototext
|
||||
// implementation, not the wireformat implementation.
|
||||
return
|
||||
}
|
||||
|
||||
// Unknown fields are not marshaled by prototext so we strip them.
|
||||
src.ProtoReflect().SetUnknown(nil)
|
||||
var ranger func(protoreflect.FieldDescriptor, protoreflect.Value) bool
|
||||
stripUnknown := func(m protoreflect.Message) {
|
||||
m.SetUnknown(nil)
|
||||
m.Range(ranger)
|
||||
}
|
||||
ranger = func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
switch {
|
||||
case fd.IsMap():
|
||||
if fd.MapValue().Message() != nil {
|
||||
v.Map().Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
stripUnknown(v.Message())
|
||||
return true
|
||||
})
|
||||
}
|
||||
case fd.Message() != nil:
|
||||
if fd.Cardinality() == protoreflect.Repeated {
|
||||
l := v.List()
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
stripUnknown(l.Get(i).Message())
|
||||
}
|
||||
} else {
|
||||
stripUnknown(v.Message())
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
stripUnknown(src.ProtoReflect())
|
||||
|
||||
textFormat, err := prototext.Marshal(src)
|
||||
if err != nil {
|
||||
t.Errorf("failed to marshal messsage to text format: %v\nmessage: %v", err, src)
|
||||
}
|
||||
dst := msg.ProtoReflect().Type().New().Interface()
|
||||
|
||||
if err := (prototext.Unmarshal(textFormat, dst)); err != nil {
|
||||
t.Errorf("failed to unmarshal messsage from text format: %v\ntext format: %s", err, textFormat)
|
||||
}
|
||||
|
||||
// The cmp package does not deal with NaN on its own and will report
|
||||
// NaN != NaN.
|
||||
optNaN64 := cmp.Comparer(func(x, y float32) bool {
|
||||
return (math.IsNaN(float64(x)) && math.IsNaN(float64(y))) || x == y
|
||||
})
|
||||
optNaN32 := cmp.Comparer(func(x, y float64) bool {
|
||||
return (math.IsNaN(x) && math.IsNaN(y)) || x == y
|
||||
})
|
||||
if diff := cmp.Diff(src, dst, protocmp.Transform(), optNaN64, optNaN32); diff != "" {
|
||||
t.Error(diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzEncodeDecodeRoundTrip(f *testing.F) {
|
||||
f.Add([]byte("Hello World!"))
|
||||
f.Fuzz(func(t *testing.T, in []byte) {
|
||||
roundTripAndCompareProto(t, in, (*testfuzzpb.TestAllTypesProto2)(nil), (*testfuzzpb.TestAllTypesProto2Editions)(nil), (*testfuzzpb.TestAllTypesProto3)(nil), (*testfuzzpb.TestAllTypesProto3Editions)(nil))
|
||||
})
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@ import "google/protobuf/wrappers.proto";
|
||||
|
||||
option go_package = "google.golang.org/protobuf/internal/testprotos/textpbeditions";
|
||||
option features.enum_type = CLOSED;
|
||||
option features.utf8_validation = NONE;
|
||||
|
||||
// Scalars contains scalar fields.
|
||||
message Scalars {
|
||||
@ -74,18 +75,46 @@ enum Enum {
|
||||
TEN = 10;
|
||||
}
|
||||
|
||||
enum OpenEnum {
|
||||
option features.enum_type = OPEN;
|
||||
|
||||
UNKNOWN = 0;
|
||||
EINS = 1;
|
||||
ZWEI = 2;
|
||||
ZEHN = 10;
|
||||
}
|
||||
|
||||
message UTF8Validated {
|
||||
string validated_string = 1
|
||||
[features.utf8_validation = VERIFY, features.field_presence = IMPLICIT];
|
||||
}
|
||||
|
||||
message NestsUTF8Validated {
|
||||
UTF8Validated validated_message = 1;
|
||||
}
|
||||
|
||||
// Message contains enum fields.
|
||||
message Enums {
|
||||
Enum opt_enum = 1;
|
||||
repeated Enum rpt_enum = 2;
|
||||
OpenEnum implicit_enum = 5 [features.field_presence = IMPLICIT];
|
||||
|
||||
enum NestedEnum {
|
||||
UNO = 1;
|
||||
DOS = 2;
|
||||
DIEZ = 10;
|
||||
}
|
||||
enum NestedOpenEnum {
|
||||
option features.enum_type = OPEN;
|
||||
|
||||
UNKNOWN = 0;
|
||||
EINS = 1;
|
||||
ZWEI = 2;
|
||||
ZEHN = 10;
|
||||
}
|
||||
NestedEnum opt_nested_enum = 3;
|
||||
repeated NestedEnum rpt_nested_enum = 4;
|
||||
NestedOpenEnum implicit_nested_enum = 6 [features.field_presence = IMPLICIT];
|
||||
}
|
||||
|
||||
// Message contains repeated fields.
|
||||
|
Loading…
x
Reference in New Issue
Block a user