2018-11-28 18:25:20 -08:00
|
|
|
// Copyright 2018 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.
|
|
|
|
|
2019-05-14 12:44:37 -07:00
|
|
|
package prototext_test
|
2018-11-28 18:25:20 -08:00
|
|
|
|
|
|
|
import (
|
2023-04-27 11:07:10 +01:00
|
|
|
"bytes"
|
2018-11-28 18:25:20 -08:00
|
|
|
"math"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
2020-02-25 12:51:10 -08:00
|
|
|
|
2019-05-14 12:44:37 -07:00
|
|
|
"google.golang.org/protobuf/encoding/prototext"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/internal/detrand"
|
2019-07-11 18:23:08 -07:00
|
|
|
"google.golang.org/protobuf/internal/flags"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/proto"
|
2022-05-24 05:12:23 +09:00
|
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
2020-02-14 18:13:14 -08:00
|
|
|
"google.golang.org/protobuf/testing/protopack"
|
2018-11-28 18:25:20 -08:00
|
|
|
|
2020-01-10 23:31:25 -08:00
|
|
|
pb2 "google.golang.org/protobuf/internal/testprotos/textpb2"
|
|
|
|
pb3 "google.golang.org/protobuf/internal/testprotos/textpb3"
|
2024-02-23 13:03:15 +01:00
|
|
|
pbeditions "google.golang.org/protobuf/internal/testprotos/textpbeditions"
|
2019-05-16 12:47:20 -07:00
|
|
|
"google.golang.org/protobuf/types/known/anypb"
|
2018-11-28 18:25:20 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
// Disable detrand to enable direct comparisons on outputs.
|
|
|
|
detrand.Disable()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarshal(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
desc string
|
2019-05-14 12:44:37 -07:00
|
|
|
mo prototext.MarshalOptions
|
2018-12-13 14:19:50 -08:00
|
|
|
input proto.Message
|
2018-11-28 18:25:20 -08:00
|
|
|
want string
|
2019-03-20 18:05:16 -07:00
|
|
|
wantErr bool // TODO: Verify error message content.
|
2019-07-11 18:23:08 -07:00
|
|
|
skip bool
|
2018-11-28 18:25:20 -08:00
|
|
|
}{{
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "proto2 optional scalars not set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Scalars{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2024-02-23 13:03:15 +01:00
|
|
|
}, {
|
|
|
|
desc: "protoeditions optional scalars not set",
|
|
|
|
input: &pbeditions.Scalars{},
|
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "proto3 scalars not set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2020-04-28 14:44:38 -07:00
|
|
|
}, {
|
|
|
|
desc: "proto3 optional not set",
|
|
|
|
input: &pb3.Proto3Optional{},
|
|
|
|
want: "",
|
2024-02-23 13:03:15 +01:00
|
|
|
}, {
|
|
|
|
desc: "protoeditions implicit not set",
|
|
|
|
input: &pbeditions.ImplicitScalars{},
|
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "proto2 optional scalars set to zero values",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Scalars{
|
2019-07-10 16:17:16 -07:00
|
|
|
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),
|
2018-11-28 18:25:20 -08:00
|
|
|
OptBytes: []byte{},
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String(""),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
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: ""
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
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: ""
|
2020-04-28 14:44:38 -07:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 optional set to zero values",
|
|
|
|
input: &pb3.Proto3Optional{
|
|
|
|
OptBool: proto.Bool(false),
|
|
|
|
OptInt32: proto.Int32(0),
|
|
|
|
OptInt64: proto.Int64(0),
|
|
|
|
OptUint32: proto.Uint32(0),
|
|
|
|
OptUint64: proto.Uint64(0),
|
|
|
|
OptFloat: proto.Float32(0),
|
|
|
|
OptDouble: proto.Float64(0),
|
|
|
|
OptString: proto.String(""),
|
|
|
|
OptBytes: []byte{},
|
|
|
|
OptEnum: pb3.Enum_ZERO.Enum(),
|
|
|
|
OptMessage: &pb3.Nested{},
|
|
|
|
},
|
|
|
|
want: `opt_bool: false
|
|
|
|
opt_int32: 0
|
|
|
|
opt_int64: 0
|
|
|
|
opt_uint32: 0
|
|
|
|
opt_uint64: 0
|
|
|
|
opt_float: 0
|
|
|
|
opt_double: 0
|
|
|
|
opt_string: ""
|
|
|
|
opt_bytes: ""
|
|
|
|
opt_enum: ZERO
|
|
|
|
opt_message: {}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "proto3 scalars set to zero values",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
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: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2024-02-23 13:03:15 +01:00
|
|
|
}, {
|
|
|
|
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: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "proto2 optional scalars set to some values",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Scalars{
|
2019-07-10 16:17:16 -07:00
|
|
|
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),
|
2019-02-13 14:13:21 -08:00
|
|
|
OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("谷歌"),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
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
|
2019-01-17 19:31:47 -08:00
|
|
|
opt_float: 1.02
|
|
|
|
opt_double: 1.0199999809265137
|
2018-11-28 18:25:20 -08:00
|
|
|
opt_bytes: "谷歌"
|
|
|
|
opt_string: "谷歌"
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
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: "谷歌"
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
2019-04-08 17:32:44 -07:00
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "proto2 string with invalid UTF-8",
|
|
|
|
input: &pb2.Scalars{
|
|
|
|
OptString: proto.String("abc\xff"),
|
|
|
|
},
|
|
|
|
want: `opt_string: "abc\xff"
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "protoeditions string with invalid UTF-8",
|
|
|
|
input: &pbeditions.Scalars{
|
|
|
|
OptString: proto.String("abc\xff"),
|
|
|
|
},
|
|
|
|
want: `opt_string: "abc\xff"
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 string with invalid UTF-8",
|
2019-04-08 17:32:44 -07:00
|
|
|
input: &pb3.Scalars{
|
|
|
|
SString: "abc\xff",
|
|
|
|
},
|
|
|
|
wantErr: true,
|
2024-02-23 13:03:15 +01:00
|
|
|
}, {
|
|
|
|
desc: "protoeditions utf8 validated string with invalid UTF-8",
|
|
|
|
input: &pbeditions.UTF8Validated{
|
|
|
|
ValidatedString: "abc\xff",
|
|
|
|
},
|
|
|
|
wantErr: true,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "float nan",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
SFloat: float32(math.NaN()),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: "s_float: nan\n",
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "float positive infinity",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
SFloat: float32(math.Inf(1)),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: "s_float: inf\n",
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "float negative infinity",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
SFloat: float32(math.Inf(-1)),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: "s_float: -inf\n",
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "double nan",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
SDouble: math.NaN(),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: "s_double: nan\n",
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "double positive infinity",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
SDouble: math.Inf(1),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: "s_double: inf\n",
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "double negative infinity",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Scalars{
|
2018-11-28 18:25:20 -08:00
|
|
|
SDouble: math.Inf(-1),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: "s_double: -inf\n",
|
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "proto2 enum not set",
|
|
|
|
input: &pb2.Enums{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "proto2 enum set to zero value",
|
|
|
|
input: &pb2.Enums{
|
2019-07-09 23:11:13 -07:00
|
|
|
OptEnum: pb2.Enum(0).Enum(),
|
|
|
|
OptNestedEnum: pb2.Enums_NestedEnum(0).Enum(),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `opt_enum: 0
|
2018-12-06 15:28:53 -08:00
|
|
|
opt_nested_enum: 0
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
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
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "proto2 enum",
|
|
|
|
input: &pb2.Enums{
|
2019-02-13 14:13:21 -08:00
|
|
|
OptEnum: pb2.Enum_ONE.Enum(),
|
2018-11-28 18:25:20 -08:00
|
|
|
OptNestedEnum: pb2.Enums_UNO.Enum(),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `opt_enum: ONE
|
2018-11-28 18:25:20 -08:00
|
|
|
opt_nested_enum: UNO
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "protoeditions enum",
|
|
|
|
input: &pbeditions.Enums{
|
|
|
|
OptEnum: pbeditions.Enum_ONE.Enum(),
|
|
|
|
OptNestedEnum: pbeditions.Enums_UNO.Enum(),
|
|
|
|
},
|
|
|
|
want: `opt_enum: ONE
|
|
|
|
opt_nested_enum: UNO
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "proto2 enum set to numeric values",
|
|
|
|
input: &pb2.Enums{
|
2019-07-09 23:11:13 -07:00
|
|
|
OptEnum: pb2.Enum(2).Enum(),
|
|
|
|
OptNestedEnum: pb2.Enums_NestedEnum(2).Enum(),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `opt_enum: TWO
|
2018-12-06 15:28:53 -08:00
|
|
|
opt_nested_enum: DOS
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto2 enum set to unnamed numeric values",
|
|
|
|
input: &pb2.Enums{
|
2019-07-09 23:11:13 -07:00
|
|
|
OptEnum: pb2.Enum(101).Enum(),
|
|
|
|
OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
want: `opt_enum: 101
|
|
|
|
opt_nested_enum: -101
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
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
|
2018-12-06 15:28:53 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 enum not set",
|
|
|
|
input: &pb3.Enums{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
|
|
|
desc: "proto3 enum set to zero value",
|
|
|
|
input: &pb3.Enums{
|
|
|
|
SEnum: pb3.Enum_ZERO,
|
|
|
|
SNestedEnum: pb3.Enums_CERO,
|
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2024-02-23 13:03:15 +01:00
|
|
|
}, {
|
|
|
|
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
|
|
|
|
`,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "proto3 enum",
|
|
|
|
input: &pb3.Enums{
|
|
|
|
SEnum: pb3.Enum_ONE,
|
2019-02-13 14:13:21 -08:00
|
|
|
SNestedEnum: pb3.Enums_UNO,
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
want: `s_enum: ONE
|
2019-02-13 14:13:21 -08:00
|
|
|
s_nested_enum: UNO
|
2018-12-06 15:28:53 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 enum set to numeric values",
|
|
|
|
input: &pb3.Enums{
|
|
|
|
SEnum: 2,
|
2019-02-13 14:13:21 -08:00
|
|
|
SNestedEnum: 2,
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `s_enum: TWO
|
2019-02-13 14:13:21 -08:00
|
|
|
s_nested_enum: DOS
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "protoeditions implicit enum set to unnamed numeric values",
|
|
|
|
input: &pbeditions.Enums{
|
|
|
|
ImplicitEnum: -47,
|
|
|
|
ImplicitNestedEnum: 47,
|
|
|
|
},
|
|
|
|
want: `implicit_enum: -47
|
|
|
|
implicit_nested_enum: 47
|
2018-12-06 15:28:53 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 enum set to unnamed numeric values",
|
|
|
|
input: &pb3.Enums{
|
|
|
|
SEnum: -47,
|
|
|
|
SNestedEnum: 47,
|
|
|
|
},
|
|
|
|
want: `s_enum: -47
|
|
|
|
s_nested_enum: 47
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto2 nested message not set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
|
|
|
desc: "proto2 nested message set to empty",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{
|
2018-11-28 18:25:20 -08:00
|
|
|
OptNested: &pb2.Nested{},
|
|
|
|
Optgroup: &pb2.Nests_OptGroup{},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `opt_nested: {}
|
2019-01-14 15:32:26 -08:00
|
|
|
OptGroup: {}
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "protoeditions nested message set to empty",
|
|
|
|
input: &pbeditions.Nests{
|
|
|
|
OptNested: &pbeditions.Nested{},
|
|
|
|
Optgroup: &pbeditions.Nests_OptGroup{},
|
|
|
|
},
|
|
|
|
want: `opt_nested: {}
|
|
|
|
OptGroup: {}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto2 nested messages",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{
|
2018-11-28 18:25:20 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("nested message"),
|
2018-11-28 18:25:20 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("another nested message"),
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `opt_nested: {
|
|
|
|
opt_string: "nested message"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "another nested message"
|
|
|
|
}
|
|
|
|
}
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
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"
|
|
|
|
}
|
|
|
|
}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "proto2 groups",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{
|
2018-11-28 18:25:20 -08:00
|
|
|
Optgroup: &pb2.Nests_OptGroup{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("inside a group"),
|
2018-11-28 18:25:20 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("nested message inside a group"),
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptFixed32: proto.Uint32(47),
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-01-14 15:32:26 -08:00
|
|
|
want: `OptGroup: {
|
2018-11-28 18:25:20 -08:00
|
|
|
opt_string: "inside a group"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "nested message inside a group"
|
|
|
|
}
|
2019-01-14 15:32:26 -08:00
|
|
|
OptNestedGroup: {
|
2019-02-13 14:13:21 -08:00
|
|
|
opt_fixed32: 47
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
}
|
2024-02-23 13:03:15 +01:00
|
|
|
`,
|
|
|
|
}, {
|
2024-04-02 12:59:48 -07:00
|
|
|
desc: "protoeditions group-like delimited encoded message field",
|
2024-02-23 13:03:15 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2024-04-02 12:59:48 -07:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "protoeditions delimited encoded message field",
|
|
|
|
input: &pbeditions.Nests{
|
|
|
|
DelimitedField: &pbeditions.Nests_OptGroup{
|
|
|
|
OptString: proto.String("second group"),
|
|
|
|
OptNested: &pbeditions.Nested{
|
|
|
|
OptString: proto.String("second nested message inside a group"),
|
|
|
|
},
|
|
|
|
NestedDelimitedField: &pbeditions.Nests_OptGroup_OptNestedGroup{
|
|
|
|
OptFixed32: proto.Uint32(47),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `delimited_field: {
|
|
|
|
opt_string: "second group"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "second nested message inside a group"
|
|
|
|
}
|
|
|
|
nested_delimited_field: {
|
|
|
|
opt_fixed32: 47
|
|
|
|
}
|
|
|
|
}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 nested message not set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Nests{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2019-02-13 14:13:21 -08:00
|
|
|
}, {
|
|
|
|
desc: "proto3 nested message set to empty",
|
|
|
|
input: &pb3.Nests{
|
|
|
|
SNested: &pb3.Nested{},
|
|
|
|
},
|
|
|
|
want: "s_nested: {}\n",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
|
|
|
desc: "proto3 nested message",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb3.Nests{
|
2018-11-28 18:25:20 -08:00
|
|
|
SNested: &pb3.Nested{
|
|
|
|
SString: "nested message",
|
|
|
|
SNested: &pb3.Nested{
|
|
|
|
SString: "another nested message",
|
|
|
|
},
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `s_nested: {
|
|
|
|
s_string: "nested message"
|
|
|
|
s_nested: {
|
|
|
|
s_string: "another nested message"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
2019-04-08 17:32:44 -07:00
|
|
|
}, {
|
|
|
|
desc: "proto3 nested message contains invalid UTF-8",
|
|
|
|
input: &pb3.Nests{
|
|
|
|
SNested: &pb3.Nested{
|
|
|
|
SString: "abc\xff",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantErr: true,
|
2024-02-23 13:03:15 +01:00
|
|
|
}, {
|
|
|
|
desc: "protoeditions nested message contains invalid UTF-8",
|
|
|
|
input: &pbeditions.NestsUTF8Validated{
|
|
|
|
ValidatedMessage: &pbeditions.UTF8Validated{
|
|
|
|
ValidatedString: "abc\xff",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantErr: true,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "oneof not set",
|
|
|
|
input: &pb3.Oneofs{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "oneof set to empty string",
|
|
|
|
input: &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofString{},
|
|
|
|
},
|
|
|
|
want: `oneof_string: ""
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "oneof set to string",
|
|
|
|
input: &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofString{
|
|
|
|
OneofString: "hello",
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `oneof_string: "hello"
|
|
|
|
`,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "oneof set to enum",
|
|
|
|
input: &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofEnum{
|
|
|
|
OneofEnum: pb3.Enum_ZERO,
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `oneof_enum: ZERO
|
|
|
|
`,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "oneof set to empty message",
|
|
|
|
input: &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofNested{
|
|
|
|
OneofNested: &pb3.Nested{},
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: "oneof_nested: {}\n",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "oneof set to message",
|
|
|
|
input: &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofNested{
|
|
|
|
OneofNested: &pb3.Nested{
|
|
|
|
SString: "nested message",
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `oneof_nested: {
|
|
|
|
s_string: "nested message"
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated fields not set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Repeats{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated fields set to empty slices",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Repeats{
|
|
|
|
RptBool: []bool{},
|
|
|
|
RptInt32: []int32{},
|
|
|
|
RptInt64: []int64{},
|
|
|
|
RptUint32: []uint32{},
|
|
|
|
RptUint64: []uint64{},
|
|
|
|
RptFloat: []float32{},
|
|
|
|
RptDouble: []float64{},
|
|
|
|
RptBytes: [][]byte{},
|
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated fields set to some values",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Repeats{
|
|
|
|
RptBool: []bool{true, false, true, true},
|
|
|
|
RptInt32: []int32{1, 6, 0, 0},
|
|
|
|
RptInt64: []int64{-64, 47},
|
|
|
|
RptUint32: []uint32{0xff, 0xffff},
|
|
|
|
RptUint64: []uint64{0xdeadbeef},
|
2019-01-17 19:31:47 -08:00
|
|
|
RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
|
2018-12-06 15:28:53 -08:00
|
|
|
RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
|
|
|
|
RptString: []string{"hello", "世界"},
|
|
|
|
RptBytes: [][]byte{
|
|
|
|
[]byte("hello"),
|
|
|
|
[]byte("\xe4\xb8\x96\xe7\x95\x8c"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `rpt_bool: true
|
|
|
|
rpt_bool: false
|
|
|
|
rpt_bool: true
|
|
|
|
rpt_bool: true
|
|
|
|
rpt_int32: 1
|
|
|
|
rpt_int32: 6
|
|
|
|
rpt_int32: 0
|
|
|
|
rpt_int32: 0
|
|
|
|
rpt_int64: -64
|
|
|
|
rpt_int64: 47
|
|
|
|
rpt_uint32: 255
|
|
|
|
rpt_uint32: 65535
|
|
|
|
rpt_uint64: 3735928559
|
2019-01-17 19:31:47 -08:00
|
|
|
rpt_float: nan
|
|
|
|
rpt_float: inf
|
|
|
|
rpt_float: -inf
|
|
|
|
rpt_float: 1.034
|
2018-12-06 15:28:53 -08:00
|
|
|
rpt_double: nan
|
|
|
|
rpt_double: inf
|
|
|
|
rpt_double: -inf
|
|
|
|
rpt_double: 1.23e-308
|
|
|
|
rpt_string: "hello"
|
|
|
|
rpt_string: "世界"
|
|
|
|
rpt_bytes: "hello"
|
|
|
|
rpt_bytes: "世界"
|
|
|
|
`,
|
2019-04-08 17:32:44 -07:00
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "repeated proto2 contains invalid UTF-8",
|
2019-04-08 17:32:44 -07:00
|
|
|
input: &pb2.Repeats{
|
|
|
|
RptString: []string{"abc\xff"},
|
|
|
|
},
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
want: `rpt_string: "abc\xff"
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "repeated proto3 contains invalid UTF-8",
|
|
|
|
input: &pb3.Repeats{
|
|
|
|
RptString: []string{"abc\xff"},
|
|
|
|
},
|
2019-04-08 17:32:44 -07:00
|
|
|
wantErr: true,
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated enums",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Enums{
|
2019-02-13 14:13:21 -08:00
|
|
|
RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
|
2018-12-06 15:28:53 -08:00
|
|
|
RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
|
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `rpt_enum: ONE
|
|
|
|
rpt_enum: TWO
|
|
|
|
rpt_enum: TEN
|
2018-12-06 15:28:53 -08:00
|
|
|
rpt_enum: 42
|
|
|
|
rpt_nested_enum: DOS
|
|
|
|
rpt_nested_enum: 47
|
|
|
|
rpt_nested_enum: DIEZ
|
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated messages set to empty",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{
|
|
|
|
RptNested: []*pb2.Nested{},
|
|
|
|
Rptgroup: []*pb2.Nests_RptGroup{},
|
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated messages",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{
|
|
|
|
RptNested: []*pb2.Nested{
|
|
|
|
{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("repeat nested one"),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("repeat nested two"),
|
2018-12-06 15:28:53 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("inside repeat nested two"),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `rpt_nested: {
|
|
|
|
opt_string: "repeat nested one"
|
|
|
|
}
|
|
|
|
rpt_nested: {
|
|
|
|
opt_string: "repeat nested two"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "inside repeat nested two"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rpt_nested: {}
|
2019-02-07 20:17:45 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated messages contains nil value",
|
2019-02-07 20:17:45 -08:00
|
|
|
input: &pb2.Nests{
|
|
|
|
RptNested: []*pb2.Nested{nil, {}},
|
|
|
|
},
|
|
|
|
want: `rpt_nested: {}
|
|
|
|
rpt_nested: {}
|
2018-12-06 15:28:53 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "repeated groups",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Nests{
|
|
|
|
Rptgroup: []*pb2.Nests_RptGroup{
|
|
|
|
{
|
2019-02-13 14:13:21 -08:00
|
|
|
RptString: []string{"hello", "world"},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
{},
|
2019-02-13 14:13:21 -08:00
|
|
|
nil,
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
},
|
2019-01-14 19:26:50 -08:00
|
|
|
want: `RptGroup: {
|
2019-02-13 14:13:21 -08:00
|
|
|
rpt_string: "hello"
|
|
|
|
rpt_string: "world"
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-01-14 19:26:50 -08:00
|
|
|
RptGroup: {}
|
2019-02-13 14:13:21 -08:00
|
|
|
RptGroup: {}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "map fields not set",
|
|
|
|
input: &pb3.Maps{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "map fields set to empty",
|
|
|
|
input: &pb3.Maps{
|
|
|
|
Int32ToStr: map[int32]string{},
|
|
|
|
BoolToUint32: map[bool]uint32{},
|
|
|
|
Uint64ToEnum: map[uint64]pb3.Enum{},
|
|
|
|
StrToNested: map[string]*pb3.Nested{},
|
|
|
|
StrToOneofs: map[string]*pb3.Oneofs{},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
|
|
|
desc: "map fields 1",
|
2019-02-13 14:13:21 -08:00
|
|
|
input: &pb3.Maps{
|
2018-11-28 18:25:20 -08:00
|
|
|
Int32ToStr: map[int32]string{
|
|
|
|
-101: "-101",
|
|
|
|
0xff: "0xff",
|
|
|
|
0: "zero",
|
|
|
|
},
|
|
|
|
BoolToUint32: map[bool]uint32{
|
|
|
|
true: 42,
|
|
|
|
false: 101,
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `int32_to_str: {
|
|
|
|
key: -101
|
|
|
|
value: "-101"
|
|
|
|
}
|
|
|
|
int32_to_str: {
|
|
|
|
key: 0
|
|
|
|
value: "zero"
|
|
|
|
}
|
|
|
|
int32_to_str: {
|
|
|
|
key: 255
|
|
|
|
value: "0xff"
|
|
|
|
}
|
|
|
|
bool_to_uint32: {
|
|
|
|
key: false
|
|
|
|
value: 101
|
|
|
|
}
|
|
|
|
bool_to_uint32: {
|
|
|
|
key: true
|
|
|
|
value: 42
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "map fields 2",
|
2019-02-13 14:13:21 -08:00
|
|
|
input: &pb3.Maps{
|
|
|
|
Uint64ToEnum: map[uint64]pb3.Enum{
|
|
|
|
1: pb3.Enum_ONE,
|
|
|
|
2: pb3.Enum_TWO,
|
|
|
|
10: pb3.Enum_TEN,
|
|
|
|
47: 47,
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `uint64_to_enum: {
|
|
|
|
key: 1
|
2019-02-13 14:13:21 -08:00
|
|
|
value: ONE
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
uint64_to_enum: {
|
|
|
|
key: 2
|
2019-02-13 14:13:21 -08:00
|
|
|
value: TWO
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
uint64_to_enum: {
|
|
|
|
key: 10
|
2019-02-13 14:13:21 -08:00
|
|
|
value: TEN
|
|
|
|
}
|
|
|
|
uint64_to_enum: {
|
|
|
|
key: 47
|
|
|
|
value: 47
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "map fields 3",
|
2019-02-13 14:13:21 -08:00
|
|
|
input: &pb3.Maps{
|
|
|
|
StrToNested: map[string]*pb3.Nested{
|
|
|
|
"nested": &pb3.Nested{
|
|
|
|
SString: "nested in a map",
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `str_to_nested: {
|
2019-02-13 14:13:21 -08:00
|
|
|
key: "nested"
|
2018-11-28 18:25:20 -08:00
|
|
|
value: {
|
2019-02-13 14:13:21 -08:00
|
|
|
s_string: "nested in a map"
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "map fields 4",
|
2019-02-13 14:13:21 -08:00
|
|
|
input: &pb3.Maps{
|
|
|
|
StrToOneofs: map[string]*pb3.Oneofs{
|
|
|
|
"string": &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofString{
|
|
|
|
OneofString: "hello",
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
},
|
2019-02-13 14:13:21 -08:00
|
|
|
"nested": &pb3.Oneofs{
|
|
|
|
Union: &pb3.Oneofs_OneofNested{
|
|
|
|
OneofNested: &pb3.Nested{
|
|
|
|
SString: "nested oneof in map field value",
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
2018-11-28 18:25:20 -08:00
|
|
|
want: `str_to_oneofs: {
|
|
|
|
key: "nested"
|
|
|
|
value: {
|
2019-02-13 14:13:21 -08:00
|
|
|
oneof_nested: {
|
|
|
|
s_string: "nested oneof in map field value"
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
str_to_oneofs: {
|
|
|
|
key: "string"
|
|
|
|
value: {
|
2019-02-13 14:13:21 -08:00
|
|
|
oneof_string: "hello"
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
}
|
2019-02-07 20:17:45 -08:00
|
|
|
`,
|
2019-04-08 17:32:44 -07:00
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "proto2 map field value contains invalid UTF-8",
|
|
|
|
input: &pb2.Maps{
|
|
|
|
Int32ToStr: map[int32]string{
|
|
|
|
101: "abc\xff",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `int32_to_str: {
|
|
|
|
key: 101
|
|
|
|
value: "abc\xff"
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto2 map field key contains invalid UTF-8",
|
|
|
|
input: &pb2.Maps{
|
|
|
|
StrToNested: map[string]*pb2.Nested{
|
|
|
|
"abc\xff": {},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `str_to_nested: {
|
|
|
|
key: "abc\xff"
|
|
|
|
value: {}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "proto3 map field value contains invalid UTF-8",
|
2019-04-08 17:32:44 -07:00
|
|
|
input: &pb3.Maps{
|
|
|
|
Int32ToStr: map[int32]string{
|
|
|
|
101: "abc\xff",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantErr: true,
|
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "proto3 map field key contains invalid UTF-8",
|
2019-04-08 17:32:44 -07:00
|
|
|
input: &pb3.Maps{
|
|
|
|
StrToNested: map[string]*pb3.Nested{
|
|
|
|
"abc\xff": {},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantErr: true,
|
2019-02-07 20:17:45 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "map field contains nil value",
|
|
|
|
input: &pb3.Maps{
|
|
|
|
StrToNested: map[string]*pb3.Nested{
|
2019-02-07 20:17:45 -08:00
|
|
|
"nil": nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `str_to_nested: {
|
|
|
|
key: "nil"
|
|
|
|
value: {}
|
|
|
|
}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2019-03-26 16:26:22 -07:00
|
|
|
desc: "required fields not set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Requireds{},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
wantErr: true,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-03-26 16:26:22 -07:00
|
|
|
desc: "required fields partially set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Requireds{
|
2019-07-10 16:17:16 -07:00
|
|
|
ReqBool: proto.Bool(false),
|
|
|
|
ReqSfixed64: proto.Int64(0xbeefcafe),
|
|
|
|
ReqDouble: proto.Float64(math.NaN()),
|
|
|
|
ReqString: proto.String("hello"),
|
2019-02-13 14:13:21 -08:00
|
|
|
ReqEnum: pb2.Enum_ONE.Enum(),
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
want: `req_bool: false
|
|
|
|
req_sfixed64: 3203386110
|
|
|
|
req_double: nan
|
|
|
|
req_string: "hello"
|
2019-02-13 14:13:21 -08:00
|
|
|
req_enum: ONE
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
2018-12-06 15:28:53 -08:00
|
|
|
wantErr: true,
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2019-03-26 16:26:22 -07:00
|
|
|
desc: "required fields not set with AllowPartial",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{AllowPartial: true},
|
2019-03-26 16:26:22 -07:00
|
|
|
input: &pb2.Requireds{
|
2019-07-10 16:17:16 -07:00
|
|
|
ReqBool: proto.Bool(false),
|
|
|
|
ReqSfixed64: proto.Int64(0xbeefcafe),
|
|
|
|
ReqDouble: proto.Float64(math.NaN()),
|
|
|
|
ReqString: proto.String("hello"),
|
2019-03-26 16:26:22 -07:00
|
|
|
ReqEnum: pb2.Enum_ONE.Enum(),
|
|
|
|
},
|
|
|
|
want: `req_bool: false
|
|
|
|
req_sfixed64: 3203386110
|
|
|
|
req_double: nan
|
|
|
|
req_string: "hello"
|
|
|
|
req_enum: ONE
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "required fields all set",
|
2018-12-06 15:28:53 -08:00
|
|
|
input: &pb2.Requireds{
|
2019-07-10 16:17:16 -07:00
|
|
|
ReqBool: proto.Bool(false),
|
|
|
|
ReqSfixed64: proto.Int64(0),
|
|
|
|
ReqDouble: proto.Float64(1.23),
|
|
|
|
ReqString: proto.String(""),
|
2019-02-13 14:13:21 -08:00
|
|
|
ReqEnum: pb2.Enum_ONE.Enum(),
|
2018-12-06 15:28:53 -08:00
|
|
|
ReqNested: &pb2.Nested{},
|
|
|
|
},
|
|
|
|
want: `req_bool: false
|
|
|
|
req_sfixed64: 0
|
2019-02-13 14:13:21 -08:00
|
|
|
req_double: 1.23
|
2018-12-06 15:28:53 -08:00
|
|
|
req_string: ""
|
2019-02-13 14:13:21 -08:00
|
|
|
req_enum: ONE
|
2018-12-06 15:28:53 -08:00
|
|
|
req_nested: {}
|
2018-11-28 18:25:20 -08:00
|
|
|
`,
|
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "indirect required field",
|
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
OptNested: &pb2.NestedWithRequired{},
|
|
|
|
},
|
|
|
|
want: "opt_nested: {}\n",
|
|
|
|
wantErr: true,
|
2019-03-26 16:26:22 -07:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field with AllowPartial",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{AllowPartial: true},
|
2019-03-26 16:26:22 -07:00
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
OptNested: &pb2.NestedWithRequired{},
|
|
|
|
},
|
|
|
|
want: "opt_nested: {}\n",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in empty repeated",
|
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
RptNested: []*pb2.NestedWithRequired{},
|
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in repeated",
|
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
RptNested: []*pb2.NestedWithRequired{
|
|
|
|
&pb2.NestedWithRequired{},
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
want: "rpt_nested: {}\n",
|
|
|
|
wantErr: true,
|
2019-03-26 16:26:22 -07:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in repeated with AllowPartial",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{AllowPartial: true},
|
2019-03-26 16:26:22 -07:00
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
RptNested: []*pb2.NestedWithRequired{
|
|
|
|
&pb2.NestedWithRequired{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: "rpt_nested: {}\n",
|
2018-11-28 18:25:20 -08:00
|
|
|
}, {
|
2018-12-06 15:28:53 -08:00
|
|
|
desc: "indirect required field in empty map",
|
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
StrToNested: map[string]*pb2.NestedWithRequired{},
|
|
|
|
},
|
2019-09-11 15:31:45 -07:00
|
|
|
want: "",
|
2018-12-06 15:28:53 -08:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in map",
|
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
StrToNested: map[string]*pb2.NestedWithRequired{
|
|
|
|
"fail": &pb2.NestedWithRequired{},
|
2018-11-28 18:25:20 -08:00
|
|
|
},
|
2018-12-06 15:28:53 -08:00
|
|
|
},
|
|
|
|
want: `str_to_nested: {
|
|
|
|
key: "fail"
|
|
|
|
value: {}
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
|
|
|
`,
|
2018-12-06 15:28:53 -08:00
|
|
|
wantErr: true,
|
2019-03-26 16:26:22 -07:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in map with AllowPartial",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{AllowPartial: true},
|
2019-03-26 16:26:22 -07:00
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
StrToNested: map[string]*pb2.NestedWithRequired{
|
|
|
|
"fail": &pb2.NestedWithRequired{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: `str_to_nested: {
|
|
|
|
key: "fail"
|
|
|
|
value: {}
|
|
|
|
}
|
|
|
|
`,
|
2019-02-13 14:13:21 -08:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in oneof",
|
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
Union: &pb2.IndirectRequired_OneofNested{
|
|
|
|
OneofNested: &pb2.NestedWithRequired{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: "oneof_nested: {}\n",
|
|
|
|
wantErr: true,
|
2019-03-26 16:26:22 -07:00
|
|
|
}, {
|
|
|
|
desc: "indirect required field in oneof with AllowPartial",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{AllowPartial: true},
|
2019-03-26 16:26:22 -07:00
|
|
|
input: &pb2.IndirectRequired{
|
|
|
|
Union: &pb2.IndirectRequired_OneofNested{
|
|
|
|
OneofNested: &pb2.NestedWithRequired{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: "oneof_nested: {}\n",
|
2019-09-14 19:14:24 -07:00
|
|
|
}, {
|
|
|
|
desc: "unknown fields not printed",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Scalars{
|
|
|
|
OptString: proto.String("this message contains unknown fields"),
|
|
|
|
}
|
2020-02-14 18:13:14 -08:00
|
|
|
m.ProtoReflect().SetUnknown(protopack.Message{
|
|
|
|
protopack.Tag{101, protopack.VarintType}, protopack.Bool(true),
|
|
|
|
protopack.Tag{102, protopack.VarintType}, protopack.Varint(0xff),
|
|
|
|
protopack.Tag{103, protopack.Fixed32Type}, protopack.Uint32(47),
|
|
|
|
protopack.Tag{104, protopack.Fixed64Type}, protopack.Int64(0xdeadbeef),
|
2019-09-14 19:14:24 -07:00
|
|
|
}.Marshal())
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `opt_string: "this message contains unknown fields"
|
|
|
|
`,
|
2018-12-11 21:08:58 -08:00
|
|
|
}, {
|
|
|
|
desc: "unknown varint and fixed types",
|
2019-09-14 19:14:24 -07:00
|
|
|
mo: prototext.MarshalOptions{EmitUnknown: true},
|
2019-06-22 13:20:09 -07:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Scalars{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("this message contains unknown fields"),
|
2019-06-22 13:20:09 -07:00
|
|
|
}
|
2020-02-14 18:13:14 -08:00
|
|
|
m.ProtoReflect().SetUnknown(protopack.Message{
|
|
|
|
protopack.Tag{101, protopack.VarintType}, protopack.Bool(true),
|
|
|
|
protopack.Tag{102, protopack.VarintType}, protopack.Varint(0xff),
|
|
|
|
protopack.Tag{103, protopack.Fixed32Type}, protopack.Uint32(0x47),
|
|
|
|
protopack.Tag{104, protopack.Fixed64Type}, protopack.Int64(0xdeadbeef),
|
2019-06-22 13:20:09 -07:00
|
|
|
}.Marshal())
|
|
|
|
return m
|
|
|
|
}(),
|
2018-12-11 21:08:58 -08:00
|
|
|
want: `opt_string: "this message contains unknown fields"
|
|
|
|
101: 1
|
|
|
|
102: 255
|
2019-10-31 17:10:15 -07:00
|
|
|
103: 0x47
|
|
|
|
104: 0xdeadbeef
|
2018-12-11 21:08:58 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "unknown length-delimited",
|
2019-09-14 19:14:24 -07:00
|
|
|
mo: prototext.MarshalOptions{EmitUnknown: true},
|
2019-06-22 13:20:09 -07:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := new(pb2.Scalars)
|
2020-02-14 18:13:14 -08:00
|
|
|
m.ProtoReflect().SetUnknown(protopack.Message{
|
|
|
|
protopack.Tag{101, protopack.BytesType}, protopack.LengthPrefix{protopack.Bool(true), protopack.Bool(false)},
|
|
|
|
protopack.Tag{102, protopack.BytesType}, protopack.String("hello world"),
|
|
|
|
protopack.Tag{103, protopack.BytesType}, protopack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
|
2019-06-22 13:20:09 -07:00
|
|
|
}.Marshal())
|
|
|
|
return m
|
|
|
|
}(),
|
2018-12-11 21:08:58 -08:00
|
|
|
want: `101: "\x01\x00"
|
|
|
|
102: "hello world"
|
|
|
|
103: "世界"
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "unknown group type",
|
2019-09-14 19:14:24 -07:00
|
|
|
mo: prototext.MarshalOptions{EmitUnknown: true},
|
2019-06-22 13:20:09 -07:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := new(pb2.Scalars)
|
2020-02-14 18:13:14 -08:00
|
|
|
m.ProtoReflect().SetUnknown(protopack.Message{
|
|
|
|
protopack.Tag{101, protopack.StartGroupType}, protopack.Tag{101, protopack.EndGroupType},
|
|
|
|
protopack.Tag{102, protopack.StartGroupType},
|
|
|
|
protopack.Tag{101, protopack.VarintType}, protopack.Bool(false),
|
|
|
|
protopack.Tag{102, protopack.BytesType}, protopack.String("inside a group"),
|
|
|
|
protopack.Tag{102, protopack.EndGroupType},
|
2019-06-22 13:20:09 -07:00
|
|
|
}.Marshal())
|
|
|
|
return m
|
|
|
|
}(),
|
2018-12-11 21:08:58 -08:00
|
|
|
want: `101: {}
|
|
|
|
102: {
|
|
|
|
101: 0
|
|
|
|
102: "inside a group"
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "unknown unpack repeated field",
|
2019-09-14 19:14:24 -07:00
|
|
|
mo: prototext.MarshalOptions{EmitUnknown: true},
|
2019-06-22 13:20:09 -07:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := new(pb2.Scalars)
|
2020-02-14 18:13:14 -08:00
|
|
|
m.ProtoReflect().SetUnknown(protopack.Message{
|
|
|
|
protopack.Tag{101, protopack.BytesType}, protopack.LengthPrefix{protopack.Bool(true), protopack.Bool(false), protopack.Bool(true)},
|
|
|
|
protopack.Tag{102, protopack.BytesType}, protopack.String("hello"),
|
|
|
|
protopack.Tag{101, protopack.VarintType}, protopack.Bool(true),
|
|
|
|
protopack.Tag{102, protopack.BytesType}, protopack.String("世界"),
|
2019-06-22 13:20:09 -07:00
|
|
|
}.Marshal())
|
|
|
|
return m
|
|
|
|
}(),
|
2018-12-11 21:08:58 -08:00
|
|
|
want: `101: "\x01\x00\x01"
|
|
|
|
102: "hello"
|
2019-04-25 23:48:08 -07:00
|
|
|
101: 1
|
2018-12-11 21:08:58 -08:00
|
|
|
102: "世界"
|
|
|
|
`,
|
2018-12-17 17:13:07 -08:00
|
|
|
}, {
|
|
|
|
desc: "extensions of non-repeated fields",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("non-extension field"),
|
|
|
|
OptBool: proto.Bool(true),
|
|
|
|
OptInt32: proto.Int32(42),
|
2018-12-17 17:13:07 -08:00
|
|
|
}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_OptExtBool, true)
|
|
|
|
proto.SetExtension(m, pb2.E_OptExtString, "extension field")
|
|
|
|
proto.SetExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
|
|
|
|
proto.SetExtension(m, pb2.E_OptExtNested, &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("nested in an extension"),
|
2018-12-17 17:13:07 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("another nested in an extension"),
|
2018-12-17 17:13:07 -08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `opt_string: "non-extension field"
|
|
|
|
opt_bool: true
|
|
|
|
opt_int32: 42
|
|
|
|
[pb2.opt_ext_bool]: true
|
2019-02-13 14:13:21 -08:00
|
|
|
[pb2.opt_ext_enum]: TEN
|
2018-12-17 17:13:07 -08:00
|
|
|
[pb2.opt_ext_nested]: {
|
|
|
|
opt_string: "nested in an extension"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "another nested in an extension"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[pb2.opt_ext_string]: "extension field"
|
2019-04-03 15:42:41 -07:00
|
|
|
`,
|
2019-04-08 17:32:44 -07:00
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "proto2 extension field contains invalid UTF-8",
|
2019-04-08 17:32:44 -07:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_OptExtString, "abc\xff")
|
2019-04-08 17:32:44 -07:00
|
|
|
return m
|
|
|
|
}(),
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
want: `[pb2.opt_ext_string]: "abc\xff"
|
|
|
|
`,
|
2019-04-03 15:42:41 -07:00
|
|
|
}, {
|
|
|
|
desc: "extension partial returns error",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("partial1"),
|
2019-04-03 15:42:41 -07:00
|
|
|
})
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("partial2"),
|
2019-04-03 15:42:41 -07:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
|
|
|
|
opt_string: "partial2"
|
|
|
|
}
|
|
|
|
[pb2.opt_ext_partial]: {
|
|
|
|
opt_string: "partial1"
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
wantErr: true,
|
|
|
|
}, {
|
|
|
|
desc: "extension partial with AllowPartial",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{AllowPartial: true},
|
2019-04-03 15:42:41 -07:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("partial1"),
|
2019-04-03 15:42:41 -07:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `[pb2.opt_ext_partial]: {
|
|
|
|
opt_string: "partial1"
|
|
|
|
}
|
2018-12-17 17:13:07 -08:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "extensions of repeated fields",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{}
|
2019-08-29 11:42:57 -07:00
|
|
|
proto.SetExtension(m, pb2.E_RptExtEnum, []pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
|
|
|
|
proto.SetExtension(m, pb2.E_RptExtFixed32, []uint32{42, 47})
|
|
|
|
proto.SetExtension(m, pb2.E_RptExtNested, []*pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
&pb2.Nested{OptString: proto.String("one")},
|
|
|
|
&pb2.Nested{OptString: proto.String("two")},
|
|
|
|
&pb2.Nested{OptString: proto.String("three")},
|
2018-12-17 17:13:07 -08:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
2019-02-13 14:13:21 -08:00
|
|
|
want: `[pb2.rpt_ext_enum]: TEN
|
2018-12-17 17:13:07 -08:00
|
|
|
[pb2.rpt_ext_enum]: 101
|
2019-02-13 14:13:21 -08:00
|
|
|
[pb2.rpt_ext_enum]: ONE
|
2018-12-17 17:13:07 -08:00
|
|
|
[pb2.rpt_ext_fixed32]: 42
|
|
|
|
[pb2.rpt_ext_fixed32]: 47
|
|
|
|
[pb2.rpt_ext_nested]: {
|
|
|
|
opt_string: "one"
|
|
|
|
}
|
|
|
|
[pb2.rpt_ext_nested]: {
|
|
|
|
opt_string: "two"
|
|
|
|
}
|
|
|
|
[pb2.rpt_ext_nested]: {
|
|
|
|
opt_string: "three"
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "extensions of non-repeated fields in another message",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
|
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
|
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
|
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("nested in an extension"),
|
2018-12-17 17:13:07 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("another nested in an extension"),
|
2018-12-17 17:13:07 -08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
|
2019-02-13 14:13:21 -08:00
|
|
|
[pb2.ExtensionsContainer.opt_ext_enum]: TEN
|
2018-12-17 17:13:07 -08:00
|
|
|
[pb2.ExtensionsContainer.opt_ext_nested]: {
|
|
|
|
opt_string: "nested in an extension"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "another nested in an extension"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "extensions of repeated fields in another message",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Extensions{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("non-extension field"),
|
|
|
|
OptBool: proto.Bool(true),
|
|
|
|
OptInt32: proto.Int32(42),
|
2018-12-17 17:13:07 -08:00
|
|
|
}
|
2019-08-29 11:42:57 -07:00
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, []pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
|
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtString, []string{"hello", "world"})
|
|
|
|
proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtNested, []*pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
&pb2.Nested{OptString: proto.String("one")},
|
|
|
|
&pb2.Nested{OptString: proto.String("two")},
|
|
|
|
&pb2.Nested{OptString: proto.String("three")},
|
2018-12-17 17:13:07 -08:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `opt_string: "non-extension field"
|
|
|
|
opt_bool: true
|
|
|
|
opt_int32: 42
|
2019-02-13 14:13:21 -08:00
|
|
|
[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
|
2018-12-17 17:13:07 -08:00
|
|
|
[pb2.ExtensionsContainer.rpt_ext_enum]: 101
|
2019-02-13 14:13:21 -08:00
|
|
|
[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
|
2018-12-17 17:13:07 -08:00
|
|
|
[pb2.ExtensionsContainer.rpt_ext_nested]: {
|
|
|
|
opt_string: "one"
|
|
|
|
}
|
|
|
|
[pb2.ExtensionsContainer.rpt_ext_nested]: {
|
|
|
|
opt_string: "two"
|
|
|
|
}
|
|
|
|
[pb2.ExtensionsContainer.rpt_ext_nested]: {
|
|
|
|
opt_string: "three"
|
|
|
|
}
|
|
|
|
[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
|
|
|
|
[pb2.ExtensionsContainer.rpt_ext_string]: "world"
|
|
|
|
`,
|
2019-01-07 18:56:57 -08:00
|
|
|
}, {
|
|
|
|
desc: "MessageSet",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.MessageSet{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("a messageset extension"),
|
2019-01-07 18:56:57 -08:00
|
|
|
})
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("not a messageset extension"),
|
2019-01-07 18:56:57 -08:00
|
|
|
})
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("just a regular extension"),
|
2019-01-07 18:56:57 -08:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
2020-06-24 14:28:07 -07:00
|
|
|
want: `[pb2.MessageSetExtension.ext_nested]: {
|
2019-01-07 18:56:57 -08:00
|
|
|
opt_string: "just a regular extension"
|
|
|
|
}
|
2020-06-24 14:28:07 -07:00
|
|
|
[pb2.MessageSetExtension]: {
|
|
|
|
opt_string: "a messageset extension"
|
|
|
|
}
|
2019-01-07 18:56:57 -08:00
|
|
|
[pb2.MessageSetExtension.not_message_set_extension]: {
|
|
|
|
opt_string: "not a messageset extension"
|
|
|
|
}
|
|
|
|
`,
|
2019-08-08 13:31:59 -07:00
|
|
|
skip: !flags.ProtoLegacy,
|
2019-01-07 18:56:57 -08:00
|
|
|
}, {
|
|
|
|
desc: "not real MessageSet 1",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.FakeMessageSet{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("not a messageset extension"),
|
2019-01-07 18:56:57 -08:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
|
|
|
|
opt_string: "not a messageset extension"
|
|
|
|
}
|
|
|
|
`,
|
2019-08-08 13:31:59 -07:00
|
|
|
skip: !flags.ProtoLegacy,
|
2019-01-07 18:56:57 -08:00
|
|
|
}, {
|
|
|
|
desc: "not real MessageSet 2",
|
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.MessageSet{}
|
2019-08-02 16:58:08 -07:00
|
|
|
proto.SetExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("another not a messageset extension"),
|
2019-01-07 18:56:57 -08:00
|
|
|
})
|
|
|
|
return m
|
|
|
|
}(),
|
|
|
|
want: `[pb2.message_set_extension]: {
|
|
|
|
opt_string: "another not a messageset extension"
|
|
|
|
}
|
|
|
|
`,
|
2019-08-08 13:31:59 -07:00
|
|
|
skip: !flags.ProtoLegacy,
|
2019-01-02 15:46:07 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "Any not expanded",
|
2019-05-14 12:44:37 -07:00
|
|
|
mo: prototext.MarshalOptions{
|
2022-05-24 05:12:23 +09:00
|
|
|
Resolver: new(protoregistry.Types),
|
2019-01-04 14:08:41 -08:00
|
|
|
},
|
2019-01-02 15:46:07 -08:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("embedded inside Any"),
|
2019-01-02 15:46:07 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("inception"),
|
2019-01-02 15:46:07 -08:00
|
|
|
},
|
|
|
|
}
|
2019-03-15 18:22:36 -07:00
|
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
2019-01-02 15:46:07 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
2019-05-16 12:47:20 -07:00
|
|
|
return &anypb.Any{
|
2019-01-04 14:08:41 -08:00
|
|
|
TypeUrl: "pb2.Nested",
|
2019-01-02 15:46:07 -08:00
|
|
|
Value: b,
|
2019-03-20 18:05:16 -07:00
|
|
|
}
|
2019-01-02 15:46:07 -08:00
|
|
|
}(),
|
|
|
|
want: `type_url: "pb2.Nested"
|
|
|
|
value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
|
|
|
|
`,
|
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "Any expanded",
|
2019-01-02 15:46:07 -08:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("embedded inside Any"),
|
2019-01-02 15:46:07 -08:00
|
|
|
OptNested: &pb2.Nested{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("inception"),
|
2019-01-02 15:46:07 -08:00
|
|
|
},
|
|
|
|
}
|
2019-03-15 18:22:36 -07:00
|
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
2019-01-02 15:46:07 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
2019-05-16 12:47:20 -07:00
|
|
|
return &anypb.Any{
|
2019-01-04 14:08:41 -08:00
|
|
|
TypeUrl: "foo/pb2.Nested",
|
2019-01-02 15:46:07 -08:00
|
|
|
Value: b,
|
2019-03-20 18:05:16 -07:00
|
|
|
}
|
2019-01-02 15:46:07 -08:00
|
|
|
}(),
|
2019-01-04 14:08:41 -08:00
|
|
|
want: `[foo/pb2.Nested]: {
|
2019-01-02 15:46:07 -08:00
|
|
|
opt_string: "embedded inside Any"
|
|
|
|
opt_nested: {
|
|
|
|
opt_string: "inception"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
2019-06-19 10:41:09 -07:00
|
|
|
desc: "Any expanded with missing required",
|
2019-01-02 15:46:07 -08:00
|
|
|
input: func() proto.Message {
|
|
|
|
m := &pb2.PartialRequired{
|
2019-07-10 16:17:16 -07:00
|
|
|
OptString: proto.String("embedded inside Any"),
|
2019-01-02 15:46:07 -08:00
|
|
|
}
|
2019-04-03 12:17:24 -07:00
|
|
|
b, err := proto.MarshalOptions{
|
|
|
|
AllowPartial: true,
|
|
|
|
Deterministic: true,
|
|
|
|
}.Marshal(m)
|
2019-03-20 18:05:16 -07:00
|
|
|
if err != nil {
|
2019-01-02 15:46:07 -08:00
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
2019-05-16 12:47:20 -07:00
|
|
|
return &anypb.Any{
|
2019-05-01 12:29:25 -07:00
|
|
|
TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
|
2019-01-02 15:46:07 -08:00
|
|
|
Value: b,
|
2019-03-20 18:05:16 -07:00
|
|
|
}
|
2019-01-02 15:46:07 -08:00
|
|
|
}(),
|
|
|
|
want: `[pb2.PartialRequired]: {
|
|
|
|
opt_string: "embedded inside Any"
|
|
|
|
}
|
2019-04-08 17:32:44 -07:00
|
|
|
`,
|
2019-01-03 15:39:58 -08:00
|
|
|
}, {
|
2019-02-13 14:13:21 -08:00
|
|
|
desc: "Any with invalid value",
|
2019-05-16 12:47:20 -07:00
|
|
|
input: &anypb.Any{
|
2019-01-04 14:08:41 -08:00
|
|
|
TypeUrl: "foo/pb2.Nested",
|
2019-07-09 23:11:13 -07:00
|
|
|
Value: []byte("\x80"),
|
2019-03-20 18:05:16 -07:00
|
|
|
},
|
2019-01-04 14:08:41 -08:00
|
|
|
want: `type_url: "foo/pb2.Nested"
|
2019-01-03 15:39:58 -08:00
|
|
|
value: "\x80"
|
2019-10-31 17:10:15 -07:00
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "Any expanded in another message",
|
|
|
|
input: func() *pb2.KnownTypes {
|
|
|
|
m1 := &pb2.Nested{
|
|
|
|
OptString: proto.String("message inside Any of another Any field"),
|
|
|
|
}
|
|
|
|
b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
|
|
|
m2 := &anypb.Any{
|
|
|
|
TypeUrl: "pb2.Nested",
|
|
|
|
Value: b1,
|
|
|
|
}
|
|
|
|
b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
|
|
|
return &pb2.KnownTypes{
|
|
|
|
OptAny: &anypb.Any{
|
|
|
|
TypeUrl: "google.protobuf.Any",
|
|
|
|
Value: b2,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
want: `opt_any: {
|
|
|
|
[google.protobuf.Any]: {
|
|
|
|
[pb2.Nested]: {
|
|
|
|
opt_string: "message inside Any of another Any field"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "Any expanded with invalid UTF-8 in proto2",
|
2019-10-31 17:10:15 -07:00
|
|
|
input: func() *pb2.KnownTypes {
|
|
|
|
m := &pb2.Nested{
|
|
|
|
OptString: proto.String("invalid UTF-8 abc\xff"),
|
|
|
|
}
|
|
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
|
|
|
return &pb2.KnownTypes{
|
|
|
|
OptAny: &anypb.Any{
|
|
|
|
TypeUrl: "pb2.Nested",
|
|
|
|
Value: b,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
want: `opt_any: {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
[pb2.Nested]: {
|
|
|
|
opt_string: "invalid UTF-8 abc\xff"
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
desc: "Any not expanded due to invalid data",
|
|
|
|
mo: prototext.MarshalOptions{EmitASCII: true},
|
|
|
|
input: func() *pb2.KnownTypes {
|
|
|
|
return &pb2.KnownTypes{
|
|
|
|
OptAny: &anypb.Any{
|
|
|
|
TypeUrl: "pb3.Scalar",
|
|
|
|
Value: []byte("\xde\xad\xbe\xef"),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
want: `opt_any: {
|
|
|
|
type_url: "pb3.Scalar"
|
|
|
|
value: "\u07ad\xbe\xef"
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "Any inside Any expanded",
|
2019-10-31 17:10:15 -07:00
|
|
|
input: func() *pb2.KnownTypes {
|
|
|
|
m1 := &pb2.Nested{
|
|
|
|
OptString: proto.String("invalid UTF-8 abc\xff"),
|
|
|
|
}
|
|
|
|
b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
|
|
|
m2 := &anypb.Any{
|
|
|
|
TypeUrl: "pb2.Nested",
|
|
|
|
Value: b1,
|
|
|
|
}
|
|
|
|
b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
|
|
|
return &pb2.KnownTypes{
|
|
|
|
OptAny: &anypb.Any{
|
|
|
|
TypeUrl: "google.protobuf.Any",
|
|
|
|
Value: b2,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
want: `opt_any: {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
[google.protobuf.Any]: {
|
|
|
|
[pb2.Nested]: {
|
|
|
|
opt_string: "invalid UTF-8 abc\xff"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}, {
|
|
|
|
desc: "Any inside Any not expanded due to invalid data",
|
|
|
|
mo: prototext.MarshalOptions{EmitASCII: true},
|
|
|
|
input: func() *pb2.KnownTypes {
|
|
|
|
m := &anypb.Any{
|
|
|
|
TypeUrl: "pb2.Nested",
|
|
|
|
Value: []byte("\xde\xad\xbe\xef"),
|
|
|
|
}
|
|
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
|
|
}
|
|
|
|
return &pb2.KnownTypes{
|
|
|
|
OptAny: &anypb.Any{
|
|
|
|
TypeUrl: "google.protobuf.Any",
|
|
|
|
Value: b,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
want: `opt_any: {
|
2019-10-31 17:10:15 -07:00
|
|
|
[google.protobuf.Any]: {
|
|
|
|
type_url: "pb2.Nested"
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
value: "\u07ad\xbe\xef"
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
}
|
2019-01-02 15:46:07 -08:00
|
|
|
`,
|
2018-11-28 18:25:20 -08:00
|
|
|
}}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
tt := tt
|
2019-07-11 18:23:08 -07:00
|
|
|
if tt.skip {
|
|
|
|
continue
|
|
|
|
}
|
2018-11-28 18:25:20 -08:00
|
|
|
t.Run(tt.desc, func(t *testing.T) {
|
2019-03-20 14:04:24 -07:00
|
|
|
// Use 2-space indentation on all MarshalOptions.
|
|
|
|
tt.mo.Indent = " "
|
2019-01-02 15:46:07 -08:00
|
|
|
b, err := tt.mo.Marshal(tt.input)
|
2018-11-28 18:25:20 -08:00
|
|
|
if err != nil && !tt.wantErr {
|
2019-01-02 15:46:07 -08:00
|
|
|
t.Errorf("Marshal() returned error: %v\n", err)
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
if err == nil && tt.wantErr {
|
2019-01-02 15:46:07 -08:00
|
|
|
t.Error("Marshal() got nil error, want error\n")
|
2018-11-28 18:25:20 -08:00
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
got := string(b)
|
2024-02-23 13:03:15 +01:00
|
|
|
if got != tt.want {
|
2018-12-06 15:28:53 -08:00
|
|
|
t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
|
2019-04-25 23:48:08 -07:00
|
|
|
if diff := cmp.Diff(tt.want, got); diff != "" {
|
2018-11-28 18:25:20 -08:00
|
|
|
t.Errorf("Marshal() diff -want +got\n%v\n", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-04-27 11:07:10 +01:00
|
|
|
|
|
|
|
func TestEncodeAppend(t *testing.T) {
|
|
|
|
want := []byte("prefix")
|
|
|
|
got := append([]byte(nil), want...)
|
|
|
|
got, err := prototext.MarshalOptions{}.MarshalAppend(got, &pb3.Scalars{
|
|
|
|
SString: "value",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if !bytes.HasPrefix(got, want) {
|
|
|
|
t.Fatalf("MarshalAppend modified prefix: got %v, want prefix %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarshalAppendAllocations(t *testing.T) {
|
|
|
|
m := &pb3.Scalars{SInt32: 1}
|
|
|
|
const count = 1000
|
|
|
|
size := 9
|
|
|
|
b := make([]byte, size)
|
|
|
|
// AllocsPerRun returns an integral value.
|
|
|
|
marshalAllocs := testing.AllocsPerRun(count, func() {
|
|
|
|
_, err := prototext.MarshalOptions{}.MarshalAppend(b[:0], m)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
b = nil
|
|
|
|
marshalAppendAllocs := testing.AllocsPerRun(count, func() {
|
|
|
|
var err error
|
|
|
|
b, err = prototext.MarshalOptions{}.MarshalAppend(b, m)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
if marshalAllocs != marshalAppendAllocs {
|
|
|
|
t.Errorf("%v allocs/op when writing to a preallocated buffer", marshalAllocs)
|
|
|
|
t.Errorf("%v allocs/op when repeatedly appending to a slice", marshalAppendAllocs)
|
|
|
|
t.Errorf("expect amortized allocs/op to be identical")
|
|
|
|
}
|
|
|
|
}
|