protobuf-go/encoding/textpb/decode_test.go
Herbie Ong 800c990248 encoding/textpb: initial textproto unmarshaling
This initial textproto unmarshaling implementation covers messages
without the use of extensions, Any expansion, nor weak.

Updated encoding tests. Split some testcases to keep each simpler.

Added TestRoundTrip for example messages like the well-known types.

Change-Id: Icffab02834aa004fa8409a9da70624f687f604fb
Reviewed-on: https://go-review.googlesource.com/c/153020
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2018-12-13 03:14:40 +00:00

986 lines
20 KiB
Go

// 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.
package textpb_test
import (
"math"
"testing"
protoV1 "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/v2/encoding/textpb"
"github.com/golang/protobuf/v2/internal/scalar"
// The legacy package must be imported prior to use of any legacy messages.
// TODO: Remove this when protoV1 registers these hooks for you.
_ "github.com/golang/protobuf/v2/internal/legacy"
"github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb2"
"github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb3"
)
func TestUnmarshal(t *testing.T) {
// TODO: Switch to using proto.Message for inputMessage and wantMessage fields when v2
// proto.Equal is implemented.
tests := []struct {
desc string
inputMessage protoV1.Message
inputText string
wantMessage protoV1.Message
wantErr bool
}{{
desc: "proto2 empty message",
inputMessage: &pb2.Scalars{},
wantMessage: &pb2.Scalars{},
}, {
desc: "proto2 optional scalar fields set to zero values",
inputMessage: &pb2.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: &pb2.Scalars{
OptBool: scalar.Bool(false),
OptInt32: scalar.Int32(0),
OptInt64: scalar.Int64(0),
OptUint32: scalar.Uint32(0),
OptUint64: scalar.Uint64(0),
OptSint32: scalar.Int32(0),
OptSint64: scalar.Int64(0),
OptFixed32: scalar.Uint32(0),
OptFixed64: scalar.Uint64(0),
OptSfixed32: scalar.Int32(0),
OptSfixed64: scalar.Int64(0),
OptFloat: scalar.Float32(0),
OptDouble: scalar.Float64(0),
OptBytes: []byte{},
OptString: scalar.String(""),
},
}, {
desc: "proto3 scalar fields set to zero values",
inputMessage: &pb3.Scalars{},
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: &pb3.Scalars{},
}, {
desc: "proto2 optional scalar fields",
inputMessage: &pb2.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: &pb2.Scalars{
OptBool: scalar.Bool(true),
OptInt32: scalar.Int32(0xff),
OptInt64: scalar.Int64(0xdeadbeef),
OptUint32: scalar.Uint32(0xff),
OptUint64: scalar.Uint64(0xdeadbeef),
OptSint32: scalar.Int32(-1001),
OptSint64: scalar.Int64(-0xffff),
OptFixed64: scalar.Uint64(64),
OptSfixed32: scalar.Int32(-32),
OptFloat: scalar.Float32(1.234),
OptDouble: scalar.Float64(1.23e100),
OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
OptString: scalar.String("谷歌"),
},
}, {
desc: "proto3 scalar fields",
inputMessage: &pb3.Scalars{},
inputText: `s_bool: true
s_int32: 255
s_int64: 3735928559
s_uint32: 0xff
s_uint64: 0xdeadbeef
s_sint32: -1001
s_sint64: -0xffff
s_fixed64: 64
s_sfixed32: -32
s_float: 1.234
s_double: 1.23e+100
s_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
s_string: "谷歌"
`,
wantMessage: &pb3.Scalars{
SBool: true,
SInt32: 0xff,
SInt64: 0xdeadbeef,
SUint32: 0xff,
SUint64: 0xdeadbeef,
SSint32: -1001,
SSint64: -0xffff,
SFixed64: 64,
SSfixed32: -32,
SFloat: 1.234,
SDouble: 1.23e100,
SBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
SString: "谷歌",
},
}, {
desc: "proto2 message contains unknown field",
inputMessage: &pb2.Scalars{},
inputText: "unknown_field: 123",
wantErr: true,
}, {
desc: "proto3 message contains unknown field",
inputMessage: &pb3.Scalars{},
inputText: "unknown_field: 456",
wantErr: true,
}, {
desc: "proto2 numeric key field",
inputMessage: &pb2.Scalars{},
inputText: "1: true",
wantErr: true,
}, {
desc: "proto3 numeric key field",
inputMessage: &pb3.Scalars{},
inputText: "1: true",
wantErr: true,
}, {
desc: "invalid bool value",
inputMessage: &pb3.Scalars{},
inputText: "s_bool: 123",
wantErr: true,
}, {
desc: "invalid int32 value",
inputMessage: &pb3.Scalars{},
inputText: "s_int32: not_a_num",
wantErr: true,
}, {
desc: "invalid int64 value",
inputMessage: &pb3.Scalars{},
inputText: "s_int64: 'not a num either'",
wantErr: true,
}, {
desc: "invalid uint32 value",
inputMessage: &pb3.Scalars{},
inputText: "s_fixed32: -42",
wantErr: true,
}, {
desc: "invalid uint64 value",
inputMessage: &pb3.Scalars{},
inputText: "s_uint64: -47",
wantErr: true,
}, {
desc: "invalid sint32 value",
inputMessage: &pb3.Scalars{},
inputText: "s_sint32: '42'",
wantErr: true,
}, {
desc: "invalid sint64 value",
inputMessage: &pb3.Scalars{},
inputText: "s_sint64: '-47'",
wantErr: true,
}, {
desc: "invalid fixed32 value",
inputMessage: &pb3.Scalars{},
inputText: "s_fixed32: -42",
wantErr: true,
}, {
desc: "invalid fixed64 value",
inputMessage: &pb3.Scalars{},
inputText: "s_fixed64: -42",
wantErr: true,
}, {
desc: "invalid sfixed32 value",
inputMessage: &pb3.Scalars{},
inputText: "s_sfixed32: 'not valid'",
wantErr: true,
}, {
desc: "invalid sfixed64 value",
inputMessage: &pb3.Scalars{},
inputText: "s_sfixed64: bad",
wantErr: true,
}, {
desc: "float32 positive infinity",
inputMessage: &pb3.Scalars{},
inputText: "s_float: inf",
wantMessage: &pb3.Scalars{
SFloat: float32(math.Inf(1)),
},
}, {
desc: "float32 negative infinity",
inputMessage: &pb3.Scalars{},
inputText: "s_float: -inf",
wantMessage: &pb3.Scalars{
SFloat: float32(math.Inf(-1)),
},
}, {
desc: "float64 positive infinity",
inputMessage: &pb3.Scalars{},
inputText: "s_double: inf",
wantMessage: &pb3.Scalars{
SDouble: math.Inf(1),
},
}, {
desc: "float64 negative infinity",
inputMessage: &pb3.Scalars{},
inputText: "s_double: -inf",
wantMessage: &pb3.Scalars{
SDouble: math.Inf(-1),
},
}, {
desc: "invalid string value",
inputMessage: &pb3.Scalars{},
inputText: "s_string: invalid_string",
wantErr: true,
}, {
desc: "proto2 bytes set to empty string",
inputMessage: &pb2.Scalars{},
inputText: "opt_bytes: ''",
wantMessage: &pb2.Scalars{
OptBytes: []byte(""),
},
}, {
desc: "proto3 bytes set to empty string",
inputMessage: &pb3.Scalars{},
inputText: "s_bytes: ''",
wantMessage: &pb3.Scalars{},
}, {
desc: "proto2 duplicate singular field",
inputMessage: &pb2.Scalars{},
inputText: `
opt_bool: true
opt_bool: false
`,
wantErr: true,
}, {
desc: "proto2 invalid singular field",
inputMessage: &pb2.Scalars{},
inputText: `
opt_bool: [true, false]
`,
wantErr: true,
}, {
desc: "proto2 more duplicate singular field",
inputMessage: &pb2.Scalars{},
inputText: `
opt_bool: true
opt_string: "hello"
opt_bool: false
`,
wantErr: true,
}, {
desc: "proto3 duplicate singular field",
inputMessage: &pb3.Scalars{},
inputText: `
s_bool: false
s_bool: true
`,
wantErr: true,
}, {
desc: "proto3 more duplicate singular field",
inputMessage: &pb3.Scalars{},
inputText: `
s_bool: false
s_string: ""
s_bool: true
`,
wantErr: true,
}, {
desc: "proto2 enum",
inputMessage: &pb2.Enums{},
inputText: `
opt_enum: FIRST
opt_nested_enum: UNO
`,
wantMessage: &pb2.Enums{
OptEnum: pb2.Enum_FIRST.Enum(),
OptNestedEnum: pb2.Enums_UNO.Enum(),
},
}, {
desc: "proto2 enum set to numeric values",
inputMessage: &pb2.Enums{},
inputText: `
opt_enum: 1
opt_nested_enum: 2
`,
wantMessage: &pb2.Enums{
OptEnum: pb2.Enum_FIRST.Enum(),
OptNestedEnum: pb2.Enums_DOS.Enum(),
},
}, {
desc: "proto2 enum set to unnamed numeric values",
inputMessage: &pb2.Enums{},
inputText: `
opt_enum: 101
opt_nested_enum: -101
`,
wantMessage: &pb2.Enums{
OptEnum: pb2Enum(101),
OptNestedEnum: pb2Enums_NestedEnum(-101),
},
}, {
desc: "proto2 enum set to invalid named",
inputMessage: &pb2.Enums{},
inputText: `
opt_enum: UNNAMED
opt_nested_enum: UNNAMED_TOO
`,
wantErr: true,
}, {
desc: "proto3 enum name value",
inputMessage: &pb3.Enums{},
inputText: `
s_enum: ONE
s_nested_enum: DIEZ
`,
wantMessage: &pb3.Enums{
SEnum: pb3.Enum_ONE,
SNestedEnum: pb3.Enums_DIEZ,
},
}, {
desc: "proto3 enum numeric value",
inputMessage: &pb3.Enums{},
inputText: `
s_enum: 2
s_nested_enum: 1
`,
wantMessage: &pb3.Enums{
SEnum: pb3.Enum_TWO,
SNestedEnum: pb3.Enums_UNO,
},
}, {
desc: "proto3 enum unnamed numeric value",
inputMessage: &pb3.Enums{},
inputText: `
s_enum: 0x7fffffff
s_nested_enum: -0x80000000
`,
wantMessage: &pb3.Enums{
SEnum: 0x7fffffff,
SNestedEnum: -0x80000000,
},
}, {
desc: "proto2 nested empty messages",
inputMessage: &pb2.Nests{},
inputText: `
opt_nested: {}
optgroup: {}
`,
wantMessage: &pb2.Nests{
OptNested: &pb2.Nested{},
Optgroup: &pb2.Nests_OptGroup{},
},
}, {
desc: "proto2 nested messages",
inputMessage: &pb2.Nests{},
inputText: `
opt_nested: {
opt_string: "nested message"
opt_nested: {
opt_string: "another nested message"
}
}
`,
wantMessage: &pb2.Nests{
OptNested: &pb2.Nested{
OptString: scalar.String("nested message"),
OptNested: &pb2.Nested{
OptString: scalar.String("another nested message"),
},
},
},
}, {
desc: "proto3 nested empty message",
inputMessage: &pb3.Nests{},
inputText: "s_nested: {}",
wantMessage: &pb3.Nests{
SNested: &pb3.Nested{},
},
}, {
desc: "proto3 nested message",
inputMessage: &pb3.Nests{},
inputText: `
s_nested: {
s_string: "nested message"
s_nested: {
s_string: "another nested message"
}
}
`,
wantMessage: &pb3.Nests{
SNested: &pb3.Nested{
SString: "nested message",
SNested: &pb3.Nested{
SString: "another nested message",
},
},
},
}, {
desc: "oneof field set to empty string",
inputMessage: &pb2.Oneofs{},
inputText: "str: ''",
wantMessage: &pb2.Oneofs{
Union: &pb2.Oneofs_Str{},
},
}, {
desc: "oneof field set to string",
inputMessage: &pb2.Oneofs{},
inputText: "str: 'hello'",
wantMessage: &pb2.Oneofs{
Union: &pb2.Oneofs_Str{
Str: "hello",
},
},
}, {
desc: "oneof field set to empty message",
inputMessage: &pb2.Oneofs{},
inputText: "msg: {}",
wantMessage: &pb2.Oneofs{
Union: &pb2.Oneofs_Msg{
Msg: &pb2.Nested{},
},
},
}, {
desc: "oneof field set to message",
inputMessage: &pb2.Oneofs{},
inputText: `
msg: {
opt_string: "nested message"
}
`,
wantMessage: &pb2.Oneofs{
Union: &pb2.Oneofs_Msg{
Msg: &pb2.Nested{
OptString: scalar.String("nested message"),
},
},
},
}, {
desc: "repeated scalar using same field name",
inputMessage: &pb2.Repeats{},
inputText: `
rpt_string: "a"
rpt_string: "b"
rpt_int32: 0xff
rpt_float: 1.23
rpt_bytes: "bytes"
`,
wantMessage: &pb2.Repeats{
RptString: []string{"a", "b"},
RptInt32: []int32{0xff},
RptFloat: []float32{1.23},
RptBytes: [][]byte{[]byte("bytes")},
},
}, {
desc: "repeated using mix of [] and repeated field name",
inputMessage: &pb2.Repeats{},
inputText: `
rpt_string: "a"
rpt_bool: true
rpt_string: ["x", "y"]
rpt_bool: [ false, true ]
rpt_string: "b"
`,
wantMessage: &pb2.Repeats{
RptString: []string{"a", "x", "y", "b"},
RptBool: []bool{true, false, true},
},
}, {
desc: "repeated enums",
inputMessage: &pb2.Enums{},
inputText: `
rpt_enum: TENTH
rpt_enum: 1
rpt_nested_enum: [DOS, 2]
rpt_enum: 42
rpt_nested_enum: -47
`,
wantMessage: &pb2.Enums{
RptEnum: []pb2.Enum{pb2.Enum_TENTH, pb2.Enum_FIRST, 42},
RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
},
}, {
desc: "repeated nested messages",
inputMessage: &pb2.Nests{},
inputText: `
rpt_nested: {
opt_string: "repeat nested one"
}
rpt_nested: {
opt_string: "repeat nested two"
opt_nested: {
opt_string: "inside repeat nested two"
}
}
rpt_nested: {}
`,
wantMessage: &pb2.Nests{
RptNested: []*pb2.Nested{
{
OptString: scalar.String("repeat nested one"),
},
{
OptString: scalar.String("repeat nested two"),
OptNested: &pb2.Nested{
OptString: scalar.String("inside repeat nested two"),
},
},
{},
},
},
}, {
desc: "repeated group fields",
inputMessage: &pb2.Nests{},
inputText: `
rptgroup: {
rpt_bool: true
rpt_bool: false
}
rptgroup: {}
`,
wantMessage: &pb2.Nests{
Rptgroup: []*pb2.Nests_RptGroup{
{
RptBool: []bool{true, false},
},
{},
},
},
}, {
desc: "map fields 1",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: -101
value: "-101"
}
int32_to_str: {
key: 0
value: "zero"
}
sfixed64_to_bool: {
key: 0
value: false
}
int32_to_str: {
key: 255
value: "0xff"
}
bool_to_uint32: {
key: false
value: 101
}
sfixed64_to_bool: {
key: 51966
value: true
}
bool_to_uint32: {
key: true
value: 42
}
`,
wantMessage: &pb2.Maps{
Int32ToStr: map[int32]string{
-101: "-101",
0xff: "0xff",
0: "zero",
},
Sfixed64ToBool: map[int64]bool{
0xcafe: true,
0: false,
},
BoolToUint32: map[bool]uint32{
true: 42,
false: 101,
},
},
}, {
desc: "map fields 2",
inputMessage: &pb2.Maps{},
inputText: `
uint64_to_enum: {
key: 1
value: FIRST
}
uint64_to_enum: {
key: 2
value: SECOND
}
uint64_to_enum: {
key: 10
value: TENTH
}
`,
wantMessage: &pb2.Maps{
Uint64ToEnum: map[uint64]pb2.Enum{
1: pb2.Enum_FIRST,
2: pb2.Enum_SECOND,
10: pb2.Enum_TENTH,
},
},
}, {
desc: "map fields 3",
inputMessage: &pb2.Maps{},
inputText: `
str_to_nested: {
key: "nested_one"
value: {
opt_string: "nested in a map"
}
}
`,
wantMessage: &pb2.Maps{
StrToNested: map[string]*pb2.Nested{
"nested_one": &pb2.Nested{
OptString: scalar.String("nested in a map"),
},
},
},
}, {
desc: "map fields 4",
inputMessage: &pb2.Maps{},
inputText: `
str_to_oneofs: {
key: "nested"
value: {
msg: {
opt_string: "nested oneof in map field value"
}
}
}
str_to_oneofs: {
key: "string"
value: {
str: "hello"
}
}
`,
wantMessage: &pb2.Maps{
StrToOneofs: map[string]*pb2.Oneofs{
"string": &pb2.Oneofs{
Union: &pb2.Oneofs_Str{
Str: "hello",
},
},
"nested": &pb2.Oneofs{
Union: &pb2.Oneofs_Msg{
Msg: &pb2.Nested{
OptString: scalar.String("nested oneof in map field value"),
},
},
},
},
},
}, {
desc: "map contains duplicate keys",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 0
value: "cero"
}
int32_to_str: {
key: 0
value: "zero"
}
`,
wantMessage: &pb2.Maps{
Int32ToStr: map[int32]string{
0: "zero",
},
},
}, {
desc: "map contains duplicate key fields",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 0
key: 1
value: "cero"
}
`,
wantErr: true,
}, {
desc: "map contains duplicate value fields",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 1
value: "cero"
value: "uno"
}
`,
wantErr: true,
}, {
desc: "map contains missing key",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
value: "zero"
}
`,
wantMessage: &pb2.Maps{
Int32ToStr: map[int32]string{
0: "zero",
},
},
}, {
desc: "map contains missing value",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 100
}
`,
wantMessage: &pb2.Maps{
Int32ToStr: map[int32]string{
100: "",
},
},
}, {
desc: "map contains missing key and value",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {}
`,
wantMessage: &pb2.Maps{
Int32ToStr: map[int32]string{
0: "",
},
},
}, {
desc: "map contains unknown field",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 0
value: "cero"
unknown: "bad"
}
`,
wantErr: true,
}, {
desc: "map contains extension-like key field",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
[key]: 10
value: "ten"
}
`,
wantErr: true,
}, {
desc: "map contains invalid key",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: "invalid"
value: "cero"
}
`,
wantErr: true,
}, {
desc: "map contains invalid value",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 100
value: 101
}
`,
wantErr: true,
}, {
desc: "map using mix of [] and repeated",
inputMessage: &pb2.Maps{},
inputText: `
int32_to_str: {
key: 1
value: "one"
}
int32_to_str: [
{
key: 2
value: "not this"
},
{
},
{
key: 3
value: "three"
}
]
int32_to_str: {
key: 2
value: "two"
}
`,
wantMessage: &pb2.Maps{
Int32ToStr: map[int32]string{
0: "",
1: "one",
2: "two",
3: "three",
},
},
}, {
desc: "proto2 required fields not set",
inputMessage: &pb2.Requireds{},
wantErr: true,
}, {
desc: "proto2 required field set but not optional",
inputMessage: &pb2.PartialRequired{},
inputText: "req_string: 'this is required'",
wantMessage: &pb2.PartialRequired{
ReqString: scalar.String("this is required"),
},
}, {
desc: "proto2 required fields partially set",
inputMessage: &pb2.Requireds{},
inputText: `
req_bool: false
req_fixed32: 47
req_sfixed64: 3203386110
req_string: "hello"
req_enum: FIRST
`,
wantMessage: &pb2.Requireds{
ReqBool: scalar.Bool(false),
ReqFixed32: scalar.Uint32(47),
ReqSfixed64: scalar.Int64(0xbeefcafe),
ReqString: scalar.String("hello"),
ReqEnum: pb2.Enum_FIRST.Enum(),
},
wantErr: true,
}, {
desc: "proto2 required fields all set",
inputMessage: &pb2.Requireds{},
inputText: `
req_bool: false
req_fixed32: 0
req_fixed64: 0
req_sfixed32: 0
req_sfixed64: 0
req_float: 0
req_double: 0
req_string: ""
req_bytes: ""
req_enum: UNKNOWN
req_nested: {}
`,
wantMessage: &pb2.Requireds{
ReqBool: scalar.Bool(false),
ReqFixed32: scalar.Uint32(0),
ReqFixed64: scalar.Uint64(0),
ReqSfixed32: scalar.Int32(0),
ReqSfixed64: scalar.Int64(0),
ReqFloat: scalar.Float32(0),
ReqDouble: scalar.Float64(0),
ReqString: scalar.String(""),
ReqEnum: pb2.Enum_UNKNOWN.Enum(),
ReqBytes: []byte{},
ReqNested: &pb2.Nested{},
},
}, {
desc: "indirect required field",
inputMessage: &pb2.IndirectRequired{},
inputText: "opt_nested: {}",
wantMessage: &pb2.IndirectRequired{
OptNested: &pb2.NestedWithRequired{},
},
wantErr: true,
}, {
desc: "indirect required field in repeated",
inputMessage: &pb2.IndirectRequired{},
inputText: `
rpt_nested: {
req_string: "one"
}
rpt_nested: {}
rpt_nested: {
req_string: "three"
}
`,
wantMessage: &pb2.IndirectRequired{
RptNested: []*pb2.NestedWithRequired{
{
ReqString: scalar.String("one"),
},
{},
{
ReqString: scalar.String("three"),
},
},
},
wantErr: true,
}, {
desc: "indirect required field in map",
inputMessage: &pb2.IndirectRequired{},
inputText: `
str_to_nested: {
key: "missing"
}
str_to_nested: {
key: "contains"
value: {
req_string: "here"
}
}
`,
wantMessage: &pb2.IndirectRequired{
StrToNested: map[string]*pb2.NestedWithRequired{
"missing": &pb2.NestedWithRequired{},
"contains": &pb2.NestedWithRequired{
ReqString: scalar.String("here"),
},
},
},
wantErr: true,
}}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
err := textpb.Unmarshal(M(tt.inputMessage), []byte(tt.inputText))
if err != nil && !tt.wantErr {
t.Errorf("Unmarshal() returned error: %v\n\n", err)
}
if err == nil && tt.wantErr {
t.Error("Unmarshal() got nil error, want error\n\n")
}
if tt.wantMessage != nil && !protoV1.Equal(tt.inputMessage, tt.wantMessage) {
t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
}
})
}
}