protobuf-go/internal/impl/message_test.go
Joe Tsai 4b7aff630a all: rename Vector as List
The terminology Vector does not occur in protobuf documentation at all,
so we should rename the Go use of the term to something more recognizable.
As such, all instances that match the regexp "[Vv]ect(or)?" were replaced.

The C++ documentation uses the term "Repeated", which is a reasonable name.
However, the term became overloaded in 2014, when maps were added as a feature
and implementated under the hood as repeated fields. This is confusing as it
means "repeated" could either refer to repeated fields proper (i.e., explicitly
marked with the "repeated" label in the proto file) or map fields. In the case
of the C++ reflective API, this is not a problem since repeated fields proper
and map fields are interacted with through the same RepeatedField type.

In Go, we do not use a single type to handle both types of repeated fields:
1) We are coming up with the Go protobuf reflection API for the first time
and so do not need to piggy-back on the repeated fields API to remain backwards
compatible since no former usages of Go protobuf reflection exists.
2) Map fields are commonly represented in Go as the Go map type, which do not
preserve ordering information. As such it is fundamentally impossible to present
an unordered map as a consistently ordered list. Thus, Go needs two different
interfaces for lists and maps.

Given the above situation, "Repeated" is not a great term to use since it
refers to two different things (when we only want one of the meanings).
To distinguish between the two, we'll use the terms "List" and "Map" instead.
There is some precedence for the term "List" in the protobuf codebase
(e.g., "getRepeatedInt32List").

Change-Id: Iddcdb6b78e1e60c14fa4ca213c15f45e214b967b
Reviewed-on: https://go-review.googlesource.com/c/149657
Reviewed-by: Damien Neil <dneil@google.com>
2018-11-14 23:03:53 +00:00

1002 lines
42 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 impl
import (
"fmt"
"math"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
protoV1 "github.com/golang/protobuf/proto"
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
ptype "github.com/golang/protobuf/v2/reflect/prototype"
)
func mustMakeMessageDesc(t ptype.StandaloneMessage) pref.MessageDescriptor {
md, err := ptype.NewMessage(&t)
if err != nil {
panic(err)
}
return md
}
var V = pref.ValueOf
type (
MyBool bool
MyInt32 int32
MyInt64 int64
MyUint32 uint32
MyUint64 uint64
MyFloat32 float32
MyFloat64 float64
MyString string
MyBytes []byte
ListStrings []MyString
ListBytes []MyBytes
MapStrings map[MyString]MyString
MapBytes map[MyString]MyBytes
)
// List of test operations to perform on messages, lists, or maps.
type (
messageOp interface{} // equalMessage | hasFields | getFields | setFields | clearFields | listFields | mapFields
messageOps []messageOp
listOp interface{} // equalList | lenList | getList | setList | appendList | truncList
listOps []listOp
mapOp interface{} // equalMap | lenMap | hasMap | getMap | setMap | clearMap | rangeMap
mapOps []mapOp
)
// Test operations performed on a message.
type (
equalMessage pref.Message
hasFields map[pref.FieldNumber]bool
getFields map[pref.FieldNumber]pref.Value
setFields map[pref.FieldNumber]pref.Value
clearFields map[pref.FieldNumber]bool
listFields map[pref.FieldNumber]listOps
mapFields map[pref.FieldNumber]mapOps
messageFields map[pref.FieldNumber]messageOps
// TODO: Mutable, Range, ExtensionTypes
)
// Test operations performed on a list.
type (
equalList pref.List
lenList int
getList map[int]pref.Value
setList map[int]pref.Value
appendList []pref.Value
truncList int
// TODO: Mutable, MutableAppend
)
// Test operations performed on a map.
type (
equalMap pref.Map
lenMap int
hasMap map[interface{}]bool
getMap map[interface{}]pref.Value
setMap map[interface{}]pref.Value
clearMap map[interface{}]bool
rangeMap map[interface{}]pref.Value
// TODO: Mutable
)
type ScalarProto2 struct {
Bool *bool `protobuf:"1"`
Int32 *int32 `protobuf:"2"`
Int64 *int64 `protobuf:"3"`
Uint32 *uint32 `protobuf:"4"`
Uint64 *uint64 `protobuf:"5"`
Float32 *float32 `protobuf:"6"`
Float64 *float64 `protobuf:"7"`
String *string `protobuf:"8"`
StringA []byte `protobuf:"9"`
Bytes []byte `protobuf:"10"`
BytesA *string `protobuf:"11"`
MyBool *MyBool `protobuf:"12"`
MyInt32 *MyInt32 `protobuf:"13"`
MyInt64 *MyInt64 `protobuf:"14"`
MyUint32 *MyUint32 `protobuf:"15"`
MyUint64 *MyUint64 `protobuf:"16"`
MyFloat32 *MyFloat32 `protobuf:"17"`
MyFloat64 *MyFloat64 `protobuf:"18"`
MyString *MyString `protobuf:"19"`
MyStringA MyBytes `protobuf:"20"`
MyBytes MyBytes `protobuf:"21"`
MyBytesA *MyString `protobuf:"22"`
}
var scalarProto2Type = MessageType{Type: ptype.GoMessage(
mustMakeMessageDesc(ptype.StandaloneMessage{
Syntax: pref.Proto2,
FullName: "ScalarProto2",
Fields: []ptype.Field{
{Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
{Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(2))},
{Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(3))},
{Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(4))},
{Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(5))},
{Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(6))},
{Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(7))},
{Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("8"))},
{Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("9"))},
{Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("10"))},
{Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("11"))},
{Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
{Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(13))},
{Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(14))},
{Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(15))},
{Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(16))},
{Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(17))},
{Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(18))},
{Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("19"))},
{Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("20"))},
{Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("21"))},
{Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("22"))},
},
}),
func(pref.MessageType) pref.ProtoMessage {
return new(ScalarProto2)
},
)}
func (m *ScalarProto2) Type() pref.MessageType { return scalarProto2Type.Type }
func (m *ScalarProto2) KnownFields() pref.KnownFields { return scalarProto2Type.KnownFieldsOf(m) }
func (m *ScalarProto2) UnknownFields() pref.UnknownFields { return scalarProto2Type.UnknownFieldsOf(m) }
func (m *ScalarProto2) Interface() pref.ProtoMessage { return m }
func (m *ScalarProto2) ProtoReflect() pref.Message { return m }
func (m *ScalarProto2) ProtoMutable() {}
func TestScalarProto2(t *testing.T) {
testMessage(t, nil, &ScalarProto2{}, messageOps{
hasFields{
1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
},
getFields{
1: V(bool(true)), 2: V(int32(2)), 3: V(int64(3)), 4: V(uint32(4)), 5: V(uint64(5)), 6: V(float32(6)), 7: V(float64(7)), 8: V(string("8")), 9: V(string("9")), 10: V([]byte("10")), 11: V([]byte("11")),
12: V(bool(true)), 13: V(int32(13)), 14: V(int64(14)), 15: V(uint32(15)), 16: V(uint64(16)), 17: V(float32(17)), 18: V(float64(18)), 19: V(string("19")), 20: V(string("20")), 21: V([]byte("21")), 22: V([]byte("22")),
},
setFields{
1: V(bool(false)), 2: V(int32(0)), 3: V(int64(0)), 4: V(uint32(0)), 5: V(uint64(0)), 6: V(float32(0)), 7: V(float64(0)), 8: V(string("")), 9: V(string("")), 10: V([]byte(nil)), 11: V([]byte(nil)),
12: V(bool(false)), 13: V(int32(0)), 14: V(int64(0)), 15: V(uint32(0)), 16: V(uint64(0)), 17: V(float32(0)), 18: V(float64(0)), 19: V(string("")), 20: V(string("")), 21: V([]byte(nil)), 22: V([]byte(nil)),
},
hasFields{
1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
},
equalMessage(&ScalarProto2{
new(bool), new(int32), new(int64), new(uint32), new(uint64), new(float32), new(float64), new(string), []byte{}, []byte{}, new(string),
new(MyBool), new(MyInt32), new(MyInt64), new(MyUint32), new(MyUint64), new(MyFloat32), new(MyFloat64), new(MyString), MyBytes{}, MyBytes{}, new(MyString),
}),
clearFields{
1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
},
equalMessage(&ScalarProto2{}),
})
}
type ScalarProto3 struct {
Bool bool `protobuf:"1"`
Int32 int32 `protobuf:"2"`
Int64 int64 `protobuf:"3"`
Uint32 uint32 `protobuf:"4"`
Uint64 uint64 `protobuf:"5"`
Float32 float32 `protobuf:"6"`
Float64 float64 `protobuf:"7"`
String string `protobuf:"8"`
StringA []byte `protobuf:"9"`
Bytes []byte `protobuf:"10"`
BytesA string `protobuf:"11"`
MyBool MyBool `protobuf:"12"`
MyInt32 MyInt32 `protobuf:"13"`
MyInt64 MyInt64 `protobuf:"14"`
MyUint32 MyUint32 `protobuf:"15"`
MyUint64 MyUint64 `protobuf:"16"`
MyFloat32 MyFloat32 `protobuf:"17"`
MyFloat64 MyFloat64 `protobuf:"18"`
MyString MyString `protobuf:"19"`
MyStringA MyBytes `protobuf:"20"`
MyBytes MyBytes `protobuf:"21"`
MyBytesA MyString `protobuf:"22"`
}
var scalarProto3Type = MessageType{Type: ptype.GoMessage(
mustMakeMessageDesc(ptype.StandaloneMessage{
Syntax: pref.Proto3,
FullName: "ScalarProto3",
Fields: []ptype.Field{
{Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind},
{Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind},
{Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind},
{Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
{Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
{Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind},
{Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind},
{Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind},
{Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind},
{Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind},
{Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind},
{Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind},
{Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind},
{Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind},
{Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
{Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
{Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind},
{Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind},
{Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind},
{Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind},
{Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind},
{Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind},
},
}),
func(pref.MessageType) pref.ProtoMessage {
return new(ScalarProto3)
},
)}
func (m *ScalarProto3) Type() pref.MessageType { return scalarProto3Type.Type }
func (m *ScalarProto3) KnownFields() pref.KnownFields { return scalarProto3Type.KnownFieldsOf(m) }
func (m *ScalarProto3) UnknownFields() pref.UnknownFields { return scalarProto3Type.UnknownFieldsOf(m) }
func (m *ScalarProto3) Interface() pref.ProtoMessage { return m }
func (m *ScalarProto3) ProtoReflect() pref.Message { return m }
func (m *ScalarProto3) ProtoMutable() {}
func TestScalarProto3(t *testing.T) {
testMessage(t, nil, &ScalarProto3{}, messageOps{
hasFields{
1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
},
getFields{
1: V(bool(false)), 2: V(int32(0)), 3: V(int64(0)), 4: V(uint32(0)), 5: V(uint64(0)), 6: V(float32(0)), 7: V(float64(0)), 8: V(string("")), 9: V(string("")), 10: V([]byte(nil)), 11: V([]byte(nil)),
12: V(bool(false)), 13: V(int32(0)), 14: V(int64(0)), 15: V(uint32(0)), 16: V(uint64(0)), 17: V(float32(0)), 18: V(float64(0)), 19: V(string("")), 20: V(string("")), 21: V([]byte(nil)), 22: V([]byte(nil)),
},
setFields{
1: V(bool(false)), 2: V(int32(0)), 3: V(int64(0)), 4: V(uint32(0)), 5: V(uint64(0)), 6: V(float32(0)), 7: V(float64(0)), 8: V(string("")), 9: V(string("")), 10: V([]byte(nil)), 11: V([]byte(nil)),
12: V(bool(false)), 13: V(int32(0)), 14: V(int64(0)), 15: V(uint32(0)), 16: V(uint64(0)), 17: V(float32(0)), 18: V(float64(0)), 19: V(string("")), 20: V(string("")), 21: V([]byte(nil)), 22: V([]byte(nil)),
},
hasFields{
1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
},
equalMessage(&ScalarProto3{}),
setFields{
1: V(bool(true)), 2: V(int32(2)), 3: V(int64(3)), 4: V(uint32(4)), 5: V(uint64(5)), 6: V(float32(6)), 7: V(float64(7)), 8: V(string("8")), 9: V(string("9")), 10: V([]byte("10")), 11: V([]byte("11")),
12: V(bool(true)), 13: V(int32(13)), 14: V(int64(14)), 15: V(uint32(15)), 16: V(uint64(16)), 17: V(float32(17)), 18: V(float64(18)), 19: V(string("19")), 20: V(string("20")), 21: V([]byte("21")), 22: V([]byte("22")),
},
hasFields{
1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
},
equalMessage(&ScalarProto3{
true, 2, 3, 4, 5, 6, 7, "8", []byte("9"), []byte("10"), "11",
true, 13, 14, 15, 16, 17, 18, "19", []byte("20"), []byte("21"), "22",
}),
clearFields{
1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
},
equalMessage(&ScalarProto3{}),
})
}
type ListScalars struct {
Bools []bool `protobuf:"1"`
Int32s []int32 `protobuf:"2"`
Int64s []int64 `protobuf:"3"`
Uint32s []uint32 `protobuf:"4"`
Uint64s []uint64 `protobuf:"5"`
Float32s []float32 `protobuf:"6"`
Float64s []float64 `protobuf:"7"`
Strings []string `protobuf:"8"`
StringsA [][]byte `protobuf:"9"`
Bytes [][]byte `protobuf:"10"`
BytesA []string `protobuf:"11"`
MyStrings1 []MyString `protobuf:"12"`
MyStrings2 []MyBytes `protobuf:"13"`
MyBytes1 []MyBytes `protobuf:"14"`
MyBytes2 []MyString `protobuf:"15"`
MyStrings3 ListStrings `protobuf:"16"`
MyStrings4 ListBytes `protobuf:"17"`
MyBytes3 ListBytes `protobuf:"18"`
MyBytes4 ListStrings `protobuf:"19"`
}
var listScalarsType = MessageType{Type: ptype.GoMessage(
mustMakeMessageDesc(ptype.StandaloneMessage{
Syntax: pref.Proto2,
FullName: "ListScalars",
Fields: []ptype.Field{
{Name: "f1", Number: 1, Cardinality: pref.Repeated, Kind: pref.BoolKind},
{Name: "f2", Number: 2, Cardinality: pref.Repeated, Kind: pref.Int32Kind},
{Name: "f3", Number: 3, Cardinality: pref.Repeated, Kind: pref.Int64Kind},
{Name: "f4", Number: 4, Cardinality: pref.Repeated, Kind: pref.Uint32Kind},
{Name: "f5", Number: 5, Cardinality: pref.Repeated, Kind: pref.Uint64Kind},
{Name: "f6", Number: 6, Cardinality: pref.Repeated, Kind: pref.FloatKind},
{Name: "f7", Number: 7, Cardinality: pref.Repeated, Kind: pref.DoubleKind},
{Name: "f8", Number: 8, Cardinality: pref.Repeated, Kind: pref.StringKind},
{Name: "f9", Number: 9, Cardinality: pref.Repeated, Kind: pref.StringKind},
{Name: "f10", Number: 10, Cardinality: pref.Repeated, Kind: pref.BytesKind},
{Name: "f11", Number: 11, Cardinality: pref.Repeated, Kind: pref.BytesKind},
{Name: "f12", Number: 12, Cardinality: pref.Repeated, Kind: pref.StringKind},
{Name: "f13", Number: 13, Cardinality: pref.Repeated, Kind: pref.StringKind},
{Name: "f14", Number: 14, Cardinality: pref.Repeated, Kind: pref.BytesKind},
{Name: "f15", Number: 15, Cardinality: pref.Repeated, Kind: pref.BytesKind},
{Name: "f16", Number: 16, Cardinality: pref.Repeated, Kind: pref.StringKind},
{Name: "f17", Number: 17, Cardinality: pref.Repeated, Kind: pref.StringKind},
{Name: "f18", Number: 18, Cardinality: pref.Repeated, Kind: pref.BytesKind},
{Name: "f19", Number: 19, Cardinality: pref.Repeated, Kind: pref.BytesKind},
},
}),
func(pref.MessageType) pref.ProtoMessage {
return new(ListScalars)
},
)}
func (m *ListScalars) Type() pref.MessageType { return listScalarsType.Type }
func (m *ListScalars) KnownFields() pref.KnownFields { return listScalarsType.KnownFieldsOf(m) }
func (m *ListScalars) UnknownFields() pref.UnknownFields { return listScalarsType.UnknownFieldsOf(m) }
func (m *ListScalars) Interface() pref.ProtoMessage { return m }
func (m *ListScalars) ProtoReflect() pref.Message { return m }
func (m *ListScalars) ProtoMutable() {}
func TestListScalars(t *testing.T) {
empty := &ListScalars{}
emptyFS := empty.KnownFields()
want := &ListScalars{
Bools: []bool{true, false, true},
Int32s: []int32{2, math.MinInt32, math.MaxInt32},
Int64s: []int64{3, math.MinInt64, math.MaxInt64},
Uint32s: []uint32{4, math.MaxUint32 / 2, math.MaxUint32},
Uint64s: []uint64{5, math.MaxUint64 / 2, math.MaxUint64},
Float32s: []float32{6, math.SmallestNonzeroFloat32, float32(math.NaN()), math.MaxFloat32},
Float64s: []float64{7, math.SmallestNonzeroFloat64, float64(math.NaN()), math.MaxFloat64},
Strings: []string{"8", "", "eight"},
StringsA: [][]byte{[]byte("9"), nil, []byte("nine")},
Bytes: [][]byte{[]byte("10"), nil, []byte("ten")},
BytesA: []string{"11", "", "eleven"},
MyStrings1: []MyString{"12", "", "twelve"},
MyStrings2: []MyBytes{[]byte("13"), nil, []byte("thirteen")},
MyBytes1: []MyBytes{[]byte("14"), nil, []byte("fourteen")},
MyBytes2: []MyString{"15", "", "fifteen"},
MyStrings3: ListStrings{"16", "", "sixteen"},
MyStrings4: ListBytes{[]byte("17"), nil, []byte("seventeen")},
MyBytes3: ListBytes{[]byte("18"), nil, []byte("eighteen")},
MyBytes4: ListStrings{"19", "", "nineteen"},
}
wantFS := want.KnownFields()
testMessage(t, nil, &ListScalars{}, messageOps{
hasFields{1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false, 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false},
getFields{1: emptyFS.Get(1), 3: emptyFS.Get(3), 5: emptyFS.Get(5), 7: emptyFS.Get(7), 9: emptyFS.Get(9), 11: emptyFS.Get(11), 13: emptyFS.Get(13), 15: emptyFS.Get(15), 17: emptyFS.Get(17), 19: emptyFS.Get(19)},
setFields{1: wantFS.Get(1), 3: wantFS.Get(3), 5: wantFS.Get(5), 7: wantFS.Get(7), 9: wantFS.Get(9), 11: wantFS.Get(11), 13: wantFS.Get(13), 15: wantFS.Get(15), 17: wantFS.Get(17), 19: wantFS.Get(19)},
listFields{
2: {
lenList(0),
appendList{V(int32(2)), V(int32(math.MinInt32)), V(int32(math.MaxInt32))},
getList{0: V(int32(2)), 1: V(int32(math.MinInt32)), 2: V(int32(math.MaxInt32))},
equalList(wantFS.Get(2).List()),
},
4: {
appendList{V(uint32(0)), V(uint32(0)), V(uint32(0))},
setList{0: V(uint32(4)), 1: V(uint32(math.MaxUint32 / 2)), 2: V(uint32(math.MaxUint32))},
lenList(3),
},
6: {
appendList{V(float32(6)), V(float32(math.SmallestNonzeroFloat32)), V(float32(math.NaN())), V(float32(math.MaxFloat32))},
equalList(wantFS.Get(6).List()),
},
8: {
appendList{V(""), V(""), V(""), V(""), V(""), V("")},
lenList(6),
setList{0: V("8"), 2: V("eight")},
truncList(3),
equalList(wantFS.Get(8).List()),
},
10: {
appendList{V([]byte(nil)), V([]byte(nil))},
setList{0: V([]byte("10"))},
appendList{V([]byte("wrong"))},
setList{2: V([]byte("ten"))},
equalList(wantFS.Get(10).List()),
},
12: {
appendList{V("12"), V("wrong"), V("twelve")},
setList{1: V("")},
equalList(wantFS.Get(12).List()),
},
14: {
appendList{V([]byte("14")), V([]byte(nil)), V([]byte("fourteen"))},
equalList(wantFS.Get(14).List()),
},
16: {
appendList{V("16"), V(""), V("sixteen"), V("extra")},
truncList(3),
equalList(wantFS.Get(16).List()),
},
18: {
appendList{V([]byte("18")), V([]byte(nil)), V([]byte("eighteen"))},
equalList(wantFS.Get(18).List()),
},
},
hasFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true},
equalMessage(want),
clearFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true},
equalMessage(empty),
})
}
type MapScalars struct {
KeyBools map[bool]string `protobuf:"1"`
KeyInt32s map[int32]string `protobuf:"2"`
KeyInt64s map[int64]string `protobuf:"3"`
KeyUint32s map[uint32]string `protobuf:"4"`
KeyUint64s map[uint64]string `protobuf:"5"`
KeyStrings map[string]string `protobuf:"6"`
ValBools map[string]bool `protobuf:"7"`
ValInt32s map[string]int32 `protobuf:"8"`
ValInt64s map[string]int64 `protobuf:"9"`
ValUint32s map[string]uint32 `protobuf:"10"`
ValUint64s map[string]uint64 `protobuf:"11"`
ValFloat32s map[string]float32 `protobuf:"12"`
ValFloat64s map[string]float64 `protobuf:"13"`
ValStrings map[string]string `protobuf:"14"`
ValStringsA map[string][]byte `protobuf:"15"`
ValBytes map[string][]byte `protobuf:"16"`
ValBytesA map[string]string `protobuf:"17"`
MyStrings1 map[MyString]MyString `protobuf:"18"`
MyStrings2 map[MyString]MyBytes `protobuf:"19"`
MyBytes1 map[MyString]MyBytes `protobuf:"20"`
MyBytes2 map[MyString]MyString `protobuf:"21"`
MyStrings3 MapStrings `protobuf:"22"`
MyStrings4 MapBytes `protobuf:"23"`
MyBytes3 MapBytes `protobuf:"24"`
MyBytes4 MapStrings `protobuf:"25"`
}
func mustMakeMapEntry(n pref.FieldNumber, keyKind, valKind pref.Kind) ptype.Field {
return ptype.Field{
Name: pref.Name(fmt.Sprintf("f%d", n)),
Number: n,
Cardinality: pref.Repeated,
Kind: pref.MessageKind,
MessageType: mustMakeMessageDesc(ptype.StandaloneMessage{
Syntax: pref.Proto2,
FullName: pref.FullName(fmt.Sprintf("MapScalars.F%dEntry", n)),
Fields: []ptype.Field{
{Name: "key", Number: 1, Cardinality: pref.Optional, Kind: keyKind},
{Name: "value", Number: 2, Cardinality: pref.Optional, Kind: valKind},
},
Options: &descriptorV1.MessageOptions{MapEntry: protoV1.Bool(true)},
}),
}
}
var mapScalarsType = MessageType{Type: ptype.GoMessage(
mustMakeMessageDesc(ptype.StandaloneMessage{
Syntax: pref.Proto2,
FullName: "MapScalars",
Fields: []ptype.Field{
mustMakeMapEntry(1, pref.BoolKind, pref.StringKind),
mustMakeMapEntry(2, pref.Int32Kind, pref.StringKind),
mustMakeMapEntry(3, pref.Int64Kind, pref.StringKind),
mustMakeMapEntry(4, pref.Uint32Kind, pref.StringKind),
mustMakeMapEntry(5, pref.Uint64Kind, pref.StringKind),
mustMakeMapEntry(6, pref.StringKind, pref.StringKind),
mustMakeMapEntry(7, pref.StringKind, pref.BoolKind),
mustMakeMapEntry(8, pref.StringKind, pref.Int32Kind),
mustMakeMapEntry(9, pref.StringKind, pref.Int64Kind),
mustMakeMapEntry(10, pref.StringKind, pref.Uint32Kind),
mustMakeMapEntry(11, pref.StringKind, pref.Uint64Kind),
mustMakeMapEntry(12, pref.StringKind, pref.FloatKind),
mustMakeMapEntry(13, pref.StringKind, pref.DoubleKind),
mustMakeMapEntry(14, pref.StringKind, pref.StringKind),
mustMakeMapEntry(15, pref.StringKind, pref.StringKind),
mustMakeMapEntry(16, pref.StringKind, pref.BytesKind),
mustMakeMapEntry(17, pref.StringKind, pref.BytesKind),
mustMakeMapEntry(18, pref.StringKind, pref.StringKind),
mustMakeMapEntry(19, pref.StringKind, pref.StringKind),
mustMakeMapEntry(20, pref.StringKind, pref.BytesKind),
mustMakeMapEntry(21, pref.StringKind, pref.BytesKind),
mustMakeMapEntry(22, pref.StringKind, pref.StringKind),
mustMakeMapEntry(23, pref.StringKind, pref.StringKind),
mustMakeMapEntry(24, pref.StringKind, pref.BytesKind),
mustMakeMapEntry(25, pref.StringKind, pref.BytesKind),
},
}),
func(pref.MessageType) pref.ProtoMessage {
return new(MapScalars)
},
)}
func (m *MapScalars) Type() pref.MessageType { return mapScalarsType.Type }
func (m *MapScalars) KnownFields() pref.KnownFields { return mapScalarsType.KnownFieldsOf(m) }
func (m *MapScalars) UnknownFields() pref.UnknownFields { return mapScalarsType.UnknownFieldsOf(m) }
func (m *MapScalars) Interface() pref.ProtoMessage { return m }
func (m *MapScalars) ProtoReflect() pref.Message { return m }
func (m *MapScalars) ProtoMutable() {}
func TestMapScalars(t *testing.T) {
empty := &MapScalars{}
emptyFS := empty.KnownFields()
want := &MapScalars{
KeyBools: map[bool]string{true: "true", false: "false"},
KeyInt32s: map[int32]string{0: "zero", -1: "one", 2: "two"},
KeyInt64s: map[int64]string{0: "zero", -10: "ten", 20: "twenty"},
KeyUint32s: map[uint32]string{0: "zero", 1: "one", 2: "two"},
KeyUint64s: map[uint64]string{0: "zero", 10: "ten", 20: "twenty"},
KeyStrings: map[string]string{"": "", "foo": "bar"},
ValBools: map[string]bool{"true": true, "false": false},
ValInt32s: map[string]int32{"one": 1, "two": 2, "three": 3},
ValInt64s: map[string]int64{"ten": 10, "twenty": -20, "thirty": 30},
ValUint32s: map[string]uint32{"0x00": 0x00, "0xff": 0xff, "0xdead": 0xdead},
ValUint64s: map[string]uint64{"0x00": 0x00, "0xff": 0xff, "0xdead": 0xdead},
ValFloat32s: map[string]float32{"nan": float32(math.NaN()), "pi": float32(math.Pi)},
ValFloat64s: map[string]float64{"nan": float64(math.NaN()), "pi": float64(math.Pi)},
ValStrings: map[string]string{"s1": "s1", "s2": "s2"},
ValStringsA: map[string][]byte{"s1": []byte("s1"), "s2": []byte("s2")},
ValBytes: map[string][]byte{"s1": []byte("s1"), "s2": []byte("s2")},
ValBytesA: map[string]string{"s1": "s1", "s2": "s2"},
MyStrings1: map[MyString]MyString{"s1": "s1", "s2": "s2"},
MyStrings2: map[MyString]MyBytes{"s1": []byte("s1"), "s2": []byte("s2")},
MyBytes1: map[MyString]MyBytes{"s1": []byte("s1"), "s2": []byte("s2")},
MyBytes2: map[MyString]MyString{"s1": "s1", "s2": "s2"},
MyStrings3: MapStrings{"s1": "s1", "s2": "s2"},
MyStrings4: MapBytes{"s1": []byte("s1"), "s2": []byte("s2")},
MyBytes3: MapBytes{"s1": []byte("s1"), "s2": []byte("s2")},
MyBytes4: MapStrings{"s1": "s1", "s2": "s2"},
}
wantFS := want.KnownFields()
testMessage(t, nil, &MapScalars{}, messageOps{
hasFields{1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false, 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false, 23: false, 24: false, 25: false},
getFields{1: emptyFS.Get(1), 3: emptyFS.Get(3), 5: emptyFS.Get(5), 7: emptyFS.Get(7), 9: emptyFS.Get(9), 11: emptyFS.Get(11), 13: emptyFS.Get(13), 15: emptyFS.Get(15), 17: emptyFS.Get(17), 19: emptyFS.Get(19), 21: emptyFS.Get(21), 23: emptyFS.Get(23), 25: emptyFS.Get(25)},
setFields{1: wantFS.Get(1), 3: wantFS.Get(3), 5: wantFS.Get(5), 7: wantFS.Get(7), 9: wantFS.Get(9), 11: wantFS.Get(11), 13: wantFS.Get(13), 15: wantFS.Get(15), 17: wantFS.Get(17), 19: wantFS.Get(19), 21: wantFS.Get(21), 23: wantFS.Get(23), 25: wantFS.Get(25)},
mapFields{
2: {
lenMap(0),
hasMap{int32(0): false, int32(-1): false, int32(2): false},
setMap{int32(0): V("zero")},
lenMap(1),
hasMap{int32(0): true, int32(-1): false, int32(2): false},
setMap{int32(-1): V("one")},
lenMap(2),
hasMap{int32(0): true, int32(-1): true, int32(2): false},
setMap{int32(2): V("two")},
lenMap(3),
hasMap{int32(0): true, int32(-1): true, int32(2): true},
},
4: {
setMap{uint32(0): V("zero"), uint32(1): V("one"), uint32(2): V("two")},
equalMap(wantFS.Get(4).Map()),
},
6: {
clearMap{"noexist": true},
setMap{"foo": V("bar")},
setMap{"": V("empty")},
getMap{"": V("empty"), "foo": V("bar"), "noexist": V(nil)},
setMap{"": V(""), "extra": V("extra")},
clearMap{"extra": true, "noexist": true},
},
8: {
equalMap(emptyFS.Get(8).Map()),
setMap{"one": V(int32(1)), "two": V(int32(2)), "three": V(int32(3))},
},
10: {
setMap{"0x00": V(uint32(0x00)), "0xff": V(uint32(0xff)), "0xdead": V(uint32(0xdead))},
lenMap(3),
equalMap(wantFS.Get(10).Map()),
getMap{"0x00": V(uint32(0x00)), "0xff": V(uint32(0xff)), "0xdead": V(uint32(0xdead)), "0xdeadbeef": V(nil)},
},
12: {
setMap{"nan": V(float32(math.NaN())), "pi": V(float32(math.Pi)), "e": V(float32(math.E))},
clearMap{"e": true, "phi": true},
rangeMap{"nan": V(float32(math.NaN())), "pi": V(float32(math.Pi))},
},
14: {
equalMap(emptyFS.Get(14).Map()),
setMap{"s1": V("s1"), "s2": V("s2")},
},
16: {
setMap{"s1": V([]byte("s1")), "s2": V([]byte("s2"))},
equalMap(wantFS.Get(16).Map()),
},
18: {
hasMap{"s1": false, "s2": false, "s3": false},
setMap{"s1": V("s1"), "s2": V("s2")},
hasMap{"s1": true, "s2": true, "s3": false},
},
20: {
equalMap(emptyFS.Get(20).Map()),
setMap{"s1": V([]byte("s1")), "s2": V([]byte("s2"))},
},
22: {
rangeMap{},
setMap{"s1": V("s1"), "s2": V("s2")},
rangeMap{"s1": V("s1"), "s2": V("s2")},
lenMap(2),
},
24: {
setMap{"s1": V([]byte("s1")), "s2": V([]byte("s2"))},
equalMap(wantFS.Get(24).Map()),
},
},
hasFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true, 23: true, 24: true, 25: true},
equalMessage(want),
clearFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true, 23: true, 24: true, 25: true},
equalMessage(empty),
})
}
type (
OneofScalars struct {
Union isOneofScalars_Union `protobuf_oneof:"union"`
}
isOneofScalars_Union interface {
isOneofScalars_Union()
}
OneofScalars_Bool struct {
Bool bool `protobuf:"1"`
}
OneofScalars_Int32 struct {
Int32 MyInt32 `protobuf:"2"`
}
OneofScalars_Int64 struct {
Int64 int64 `protobuf:"3"`
}
OneofScalars_Uint32 struct {
Uint32 MyUint32 `protobuf:"4"`
}
OneofScalars_Uint64 struct {
Uint64 uint64 `protobuf:"5"`
}
OneofScalars_Float32 struct {
Float32 MyFloat32 `protobuf:"6"`
}
OneofScalars_Float64 struct {
Float64 float64 `protobuf:"7"`
}
OneofScalars_String struct {
String string `protobuf:"8"`
}
OneofScalars_StringA struct {
StringA []byte `protobuf:"9"`
}
OneofScalars_StringB struct {
StringB MyString `protobuf:"10"`
}
OneofScalars_Bytes struct {
Bytes []byte `protobuf:"11"`
}
OneofScalars_BytesA struct {
BytesA string `protobuf:"12"`
}
OneofScalars_BytesB struct {
BytesB MyBytes `protobuf:"13"`
}
)
var oneofScalarsType = MessageType{Type: ptype.GoMessage(
mustMakeMessageDesc(ptype.StandaloneMessage{
Syntax: pref.Proto2,
FullName: "ScalarProto2",
Fields: []ptype.Field{
{Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true)), OneofName: "union"},
{Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(2)), OneofName: "union"},
{Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(3)), OneofName: "union"},
{Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(4)), OneofName: "union"},
{Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(5)), OneofName: "union"},
{Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(6)), OneofName: "union"},
{Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(7)), OneofName: "union"},
{Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("8")), OneofName: "union"},
{Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("9")), OneofName: "union"},
{Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("10")), OneofName: "union"},
{Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("11")), OneofName: "union"},
{Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("12")), OneofName: "union"},
{Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("13")), OneofName: "union"},
},
Oneofs: []ptype.Oneof{{Name: "union"}},
}),
func(pref.MessageType) pref.ProtoMessage {
return new(OneofScalars)
},
)}
func (m *OneofScalars) Type() pref.MessageType { return oneofScalarsType.Type }
func (m *OneofScalars) KnownFields() pref.KnownFields { return oneofScalarsType.KnownFieldsOf(m) }
func (m *OneofScalars) UnknownFields() pref.UnknownFields { return oneofScalarsType.UnknownFieldsOf(m) }
func (m *OneofScalars) Interface() pref.ProtoMessage { return m }
func (m *OneofScalars) ProtoReflect() pref.Message { return m }
func (m *OneofScalars) ProtoMutable() {}
func (*OneofScalars) XXX_OneofFuncs() (func(protoV1.Message, *protoV1.Buffer) error, func(protoV1.Message, int, int, *protoV1.Buffer) (bool, error), func(protoV1.Message) int, []interface{}) {
return nil, nil, nil, []interface{}{
(*OneofScalars_Bool)(nil),
(*OneofScalars_Int32)(nil),
(*OneofScalars_Int64)(nil),
(*OneofScalars_Uint32)(nil),
(*OneofScalars_Uint64)(nil),
(*OneofScalars_Float32)(nil),
(*OneofScalars_Float64)(nil),
(*OneofScalars_String)(nil),
(*OneofScalars_StringA)(nil),
(*OneofScalars_StringB)(nil),
(*OneofScalars_Bytes)(nil),
(*OneofScalars_BytesA)(nil),
(*OneofScalars_BytesB)(nil),
}
}
func (*OneofScalars_Bool) isOneofScalars_Union() {}
func (*OneofScalars_Int32) isOneofScalars_Union() {}
func (*OneofScalars_Int64) isOneofScalars_Union() {}
func (*OneofScalars_Uint32) isOneofScalars_Union() {}
func (*OneofScalars_Uint64) isOneofScalars_Union() {}
func (*OneofScalars_Float32) isOneofScalars_Union() {}
func (*OneofScalars_Float64) isOneofScalars_Union() {}
func (*OneofScalars_String) isOneofScalars_Union() {}
func (*OneofScalars_StringA) isOneofScalars_Union() {}
func (*OneofScalars_StringB) isOneofScalars_Union() {}
func (*OneofScalars_Bytes) isOneofScalars_Union() {}
func (*OneofScalars_BytesA) isOneofScalars_Union() {}
func (*OneofScalars_BytesB) isOneofScalars_Union() {}
func TestOneofs(t *testing.T) {
empty := &OneofScalars{}
want1 := &OneofScalars{Union: &OneofScalars_Bool{true}}
want2 := &OneofScalars{Union: &OneofScalars_Int32{20}}
want3 := &OneofScalars{Union: &OneofScalars_Int64{30}}
want4 := &OneofScalars{Union: &OneofScalars_Uint32{40}}
want5 := &OneofScalars{Union: &OneofScalars_Uint64{50}}
want6 := &OneofScalars{Union: &OneofScalars_Float32{60}}
want7 := &OneofScalars{Union: &OneofScalars_Float64{70}}
want8 := &OneofScalars{Union: &OneofScalars_String{string("80")}}
want9 := &OneofScalars{Union: &OneofScalars_StringA{[]byte("90")}}
want10 := &OneofScalars{Union: &OneofScalars_StringB{MyString("100")}}
want11 := &OneofScalars{Union: &OneofScalars_Bytes{[]byte("110")}}
want12 := &OneofScalars{Union: &OneofScalars_BytesA{string("120")}}
want13 := &OneofScalars{Union: &OneofScalars_BytesB{MyBytes("130")}}
testMessage(t, nil, &OneofScalars{}, messageOps{
hasFields{1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false, 12: false, 13: false},
getFields{1: V(bool(true)), 2: V(int32(2)), 3: V(int64(3)), 4: V(uint32(4)), 5: V(uint64(5)), 6: V(float32(6)), 7: V(float64(7)), 8: V(string("8")), 9: V(string("9")), 10: V(string("10")), 11: V([]byte("11")), 12: V([]byte("12")), 13: V([]byte("13"))},
setFields{1: V(bool(true))}, hasFields{1: true}, equalMessage(want1),
setFields{2: V(int32(20))}, hasFields{2: true}, equalMessage(want2),
setFields{3: V(int64(30))}, hasFields{3: true}, equalMessage(want3),
setFields{4: V(uint32(40))}, hasFields{4: true}, equalMessage(want4),
setFields{5: V(uint64(50))}, hasFields{5: true}, equalMessage(want5),
setFields{6: V(float32(60))}, hasFields{6: true}, equalMessage(want6),
setFields{7: V(float64(70))}, hasFields{7: true}, equalMessage(want7),
setFields{8: V(string("80"))}, hasFields{8: true}, equalMessage(want8),
setFields{9: V(string("90"))}, hasFields{9: true}, equalMessage(want9),
setFields{10: V(string("100"))}, hasFields{10: true}, equalMessage(want10),
setFields{11: V([]byte("110"))}, hasFields{11: true}, equalMessage(want11),
setFields{12: V([]byte("120"))}, hasFields{12: true}, equalMessage(want12),
setFields{13: V([]byte("130"))}, hasFields{13: true}, equalMessage(want13),
hasFields{1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false, 12: false, 13: true},
getFields{1: V(bool(true)), 2: V(int32(2)), 3: V(int64(3)), 4: V(uint32(4)), 5: V(uint64(5)), 6: V(float32(6)), 7: V(float64(7)), 8: V(string("8")), 9: V(string("9")), 10: V(string("10")), 11: V([]byte("11")), 12: V([]byte("12")), 13: V([]byte("130"))},
clearFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true},
equalMessage(want13),
clearFields{13: true},
equalMessage(empty),
})
}
// TODO: Need to test singular and repeated messages
var cmpOpts = cmp.Options{
cmp.Transformer("UnwrapValue", func(v pref.Value) interface{} {
return v.Interface()
}),
cmp.Transformer("UnwrapList", func(v pref.List) interface{} {
return v.(interface{ Unwrap() interface{} }).Unwrap()
}),
cmp.Transformer("UnwrapMap", func(m pref.Map) interface{} {
return m.(interface{ Unwrap() interface{} }).Unwrap()
}),
cmpopts.EquateNaNs(),
}
func testMessage(t *testing.T, p path, m pref.Message, tt messageOps) {
fs := m.KnownFields()
for i, op := range tt {
p.Push(i)
switch op := op.(type) {
case equalMessage:
if diff := cmp.Diff(op, m, cmpOpts); diff != "" {
t.Errorf("operation %v, message mismatch (-want, +got):\n%s", p, diff)
}
case hasFields:
got := map[pref.FieldNumber]bool{}
want := map[pref.FieldNumber]bool(op)
for n := range want {
got[n] = fs.Has(n)
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("operation %v, KnownFields.Has mismatch (-want, +got):\n%s", p, diff)
}
case getFields:
got := map[pref.FieldNumber]pref.Value{}
want := map[pref.FieldNumber]pref.Value(op)
for n := range want {
got[n] = fs.Get(n)
}
if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
t.Errorf("operation %v, KnownFields.Get mismatch (-want, +got):\n%s", p, diff)
}
case setFields:
for n, v := range op {
fs.Set(n, v)
}
case clearFields:
for n, ok := range op {
if ok {
fs.Clear(n)
}
}
case listFields:
for n, tt := range op {
p.Push(int(n))
testLists(t, p, fs.Mutable(n).(pref.List), tt)
p.Pop()
}
case mapFields:
for n, tt := range op {
p.Push(int(n))
testMaps(t, p, fs.Mutable(n).(pref.Map), tt)
p.Pop()
}
default:
t.Fatalf("operation %v, invalid operation: %T", p, op)
}
p.Pop()
}
}
func testLists(t *testing.T, p path, v pref.List, tt listOps) {
for i, op := range tt {
p.Push(i)
switch op := op.(type) {
case equalList:
if diff := cmp.Diff(op, v, cmpOpts); diff != "" {
t.Errorf("operation %v, list mismatch (-want, +got):\n%s", p, diff)
}
case lenList:
if got, want := v.Len(), int(op); got != want {
t.Errorf("operation %v, List.Len = %d, want %d", p, got, want)
}
case getList:
got := map[int]pref.Value{}
want := map[int]pref.Value(op)
for n := range want {
got[n] = v.Get(n)
}
if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
t.Errorf("operation %v, List.Get mismatch (-want, +got):\n%s", p, diff)
}
case setList:
for n, e := range op {
v.Set(n, e)
}
case appendList:
for _, e := range op {
v.Append(e)
}
case truncList:
v.Truncate(int(op))
default:
t.Fatalf("operation %v, invalid operation: %T", p, op)
}
p.Pop()
}
}
func testMaps(t *testing.T, p path, m pref.Map, tt mapOps) {
for i, op := range tt {
p.Push(i)
switch op := op.(type) {
case equalMap:
if diff := cmp.Diff(op, m, cmpOpts); diff != "" {
t.Errorf("operation %v, map mismatch (-want, +got):\n%s", p, diff)
}
case lenMap:
if got, want := m.Len(), int(op); got != want {
t.Errorf("operation %v, Map.Len = %d, want %d", p, got, want)
}
case hasMap:
got := map[interface{}]bool{}
want := map[interface{}]bool(op)
for k := range want {
got[k] = m.Has(V(k).MapKey())
}
if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
t.Errorf("operation %v, Map.Has mismatch (-want, +got):\n%s", p, diff)
}
case getMap:
got := map[interface{}]pref.Value{}
want := map[interface{}]pref.Value(op)
for k := range want {
got[k] = m.Get(V(k).MapKey())
}
if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
t.Errorf("operation %v, Map.Get mismatch (-want, +got):\n%s", p, diff)
}
case setMap:
for k, v := range op {
m.Set(V(k).MapKey(), v)
}
case clearMap:
for v, ok := range op {
if ok {
m.Clear(V(v).MapKey())
}
}
case rangeMap:
got := map[interface{}]pref.Value{}
want := map[interface{}]pref.Value(op)
m.Range(func(k pref.MapKey, v pref.Value) bool {
got[k.Interface()] = v
return true
})
if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
t.Errorf("operation %v, Map.Range mismatch (-want, +got):\n%s", p, diff)
}
default:
t.Fatalf("operation %v, invalid operation: %T", p, op)
}
p.Pop()
}
}
type path []int
func (p *path) Push(i int) { *p = append(*p, i) }
func (p *path) Pop() { *p = (*p)[:len(*p)-1] }
func (p path) String() string {
var ss []string
for _, i := range p {
ss = append(ss, fmt.Sprint(i))
}
return strings.Join(ss, ".")
}