mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-02-21 00:39:54 +00:00
internal/impl: implement Vector fields
Generate functions for wrapping []T to implement protoreflect.Vector. This implementation uses Go reflection instead to provide a single implementation that can handle all Go slice types. The test harness was greatly expanded to be able to test vectors (in addition to messages and maps in the near future). Change-Id: I0106c175f84a1e7e0a0a5b0e02e2489b70b0d177 Reviewed-on: https://go-review.googlesource.com/c/135339 Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
162c12703c
commit
91e1466d6f
@ -215,7 +215,7 @@ func (m *message) KnownFields() pref.KnownFields {
|
||||
func (m *message) UnknownFields() pref.UnknownFields {
|
||||
return (*unknownFields)(m)
|
||||
}
|
||||
func (m *message) Unwrap() interface{} {
|
||||
func (m *message) Unwrap() interface{} { // TODO: unexport?
|
||||
return m.p.asType(m.mi.goType.Elem()).Interface()
|
||||
}
|
||||
func (m *message) Interface() pref.ProtoMessage {
|
||||
@ -266,7 +266,7 @@ func (fs *knownFields) Set(n pref.FieldNumber, v pref.Value) {
|
||||
return
|
||||
}
|
||||
// TODO: Handle extension fields.
|
||||
panic("invalid field")
|
||||
panic(fmt.Sprintf("invalid field: %d", n))
|
||||
}
|
||||
func (fs *knownFields) Clear(n pref.FieldNumber) {
|
||||
if fi := fs.mi.fields[n]; fi != nil {
|
||||
@ -274,14 +274,14 @@ func (fs *knownFields) Clear(n pref.FieldNumber) {
|
||||
return
|
||||
}
|
||||
// TODO: Handle extension fields.
|
||||
panic("invalid field")
|
||||
panic(fmt.Sprintf("invalid field: %d", n))
|
||||
}
|
||||
func (fs *knownFields) Mutable(n pref.FieldNumber) pref.Mutable {
|
||||
if fi := fs.mi.fields[n]; fi != nil {
|
||||
return fi.mutable(fs.p)
|
||||
}
|
||||
// TODO: Handle extension fields.
|
||||
panic("invalid field")
|
||||
panic(fmt.Sprintf("invalid field: %d", n))
|
||||
}
|
||||
func (fs *knownFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
|
||||
for n, fi := range fs.mi.fields {
|
||||
|
@ -41,10 +41,79 @@ func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo
|
||||
}
|
||||
|
||||
func fieldInfoForVector(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
|
||||
// TODO: support vector fields.
|
||||
panic(fmt.Sprintf("invalid field: %v", fd))
|
||||
ft := fs.Type
|
||||
if ft.Kind() != reflect.Slice {
|
||||
panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
|
||||
}
|
||||
conv := matchGoTypePBKind(ft.Elem(), fd.Kind())
|
||||
fieldOffset := offsetOf(fs)
|
||||
// TODO: Implement unsafe fast path?
|
||||
return fieldInfo{
|
||||
has: func(p pointer) bool {
|
||||
rv := p.apply(fieldOffset).asType(fs.Type).Elem()
|
||||
return rv.Len() > 0
|
||||
},
|
||||
get: func(p pointer) pref.Value {
|
||||
rv := p.apply(fieldOffset).asType(fs.Type).Elem()
|
||||
return pref.ValueOf(vectorReflect{rv, conv})
|
||||
},
|
||||
set: func(p pointer, v pref.Value) {
|
||||
rv := p.apply(fieldOffset).asType(fs.Type).Elem()
|
||||
rv.Set(v.Vector().(vectorReflect).v)
|
||||
},
|
||||
clear: func(p pointer) {
|
||||
rv := p.apply(fieldOffset).asType(fs.Type).Elem()
|
||||
rv.Set(reflect.Zero(rv.Type()))
|
||||
},
|
||||
mutable: func(p pointer) pref.Mutable {
|
||||
rv := p.apply(fieldOffset).asType(fs.Type).Elem()
|
||||
return vectorReflect{rv, conv}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type vectorReflect struct {
|
||||
v reflect.Value // addressable []T
|
||||
conv converter
|
||||
}
|
||||
|
||||
func (vs vectorReflect) Len() int {
|
||||
return vs.v.Len()
|
||||
}
|
||||
func (vs vectorReflect) Get(i int) pref.Value {
|
||||
return vs.conv.toPB(vs.v.Index(i))
|
||||
}
|
||||
func (vs vectorReflect) Set(i int, v pref.Value) {
|
||||
vs.v.Index(i).Set(vs.conv.toGo(v))
|
||||
}
|
||||
func (vs vectorReflect) Append(v pref.Value) {
|
||||
vs.v.Set(reflect.Append(vs.v, vs.conv.toGo(v)))
|
||||
}
|
||||
func (vs vectorReflect) Mutable(i int) pref.Mutable {
|
||||
// Mutable is only valid for messages and panics for other kinds.
|
||||
rv := vs.v.Index(i)
|
||||
if rv.IsNil() {
|
||||
pv := pref.ValueOf(vs.conv.newMessage())
|
||||
rv.Set(vs.conv.toGo(pv))
|
||||
}
|
||||
return rv.Interface().(pref.Message)
|
||||
}
|
||||
func (vs vectorReflect) MutableAppend() pref.Mutable {
|
||||
// MutableAppend is only valid for messages and panics for other kinds.
|
||||
pv := pref.ValueOf(vs.conv.newMessage())
|
||||
vs.v.Set(reflect.Append(vs.v, vs.conv.toGo(pv)))
|
||||
return vs.v.Index(vs.Len() - 1).Interface().(pref.Message)
|
||||
}
|
||||
func (vs vectorReflect) Truncate(i int) {
|
||||
vs.v.Set(vs.v.Slice(0, i))
|
||||
}
|
||||
func (vs vectorReflect) Unwrap() interface{} { // TODO: unexport?
|
||||
return vs.v.Interface()
|
||||
}
|
||||
func (vs vectorReflect) ProtoMutable() {}
|
||||
|
||||
var _ pref.Vector = vectorReflect{}
|
||||
|
||||
var emptyBytes = reflect.ValueOf([]byte{})
|
||||
|
||||
func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
|
||||
@ -221,8 +290,9 @@ func matchGoTypePBKind(t reflect.Type, k pref.Kind) converter {
|
||||
// converter provides functions for converting to/from Go reflect.Value types
|
||||
// and protobuf protoreflect.Value types.
|
||||
type converter struct {
|
||||
toPB func(reflect.Value) pref.Value
|
||||
toGo func(pref.Value) reflect.Value
|
||||
toPB func(reflect.Value) pref.Value
|
||||
toGo func(pref.Value) reflect.Value
|
||||
newMessage func() pref.Message
|
||||
}
|
||||
|
||||
func makeScalarConverter(goType, pbType reflect.Type) converter {
|
||||
|
@ -5,10 +5,13 @@
|
||||
package impl
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
ptype "github.com/golang/protobuf/v2/reflect/prototype"
|
||||
@ -22,6 +25,8 @@ func mustMakeMessageDesc(t ptype.StandaloneMessage) pref.MessageDescriptor {
|
||||
return md
|
||||
}
|
||||
|
||||
var V = pref.ValueOf
|
||||
|
||||
type (
|
||||
MyBool bool
|
||||
MyInt32 int32
|
||||
@ -32,266 +37,487 @@ type (
|
||||
MyFloat64 float64
|
||||
MyString string
|
||||
MyBytes []byte
|
||||
|
||||
NamedStrings []MyString
|
||||
NamedBytes []MyBytes
|
||||
)
|
||||
|
||||
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"`
|
||||
// List of test operations to perform on messages, vectors, or maps.
|
||||
type (
|
||||
messageOp interface{} // equalMessage | hasFields | getFields | setFields | clearFields | vectorFields | mapFields
|
||||
messageOps []messageOp
|
||||
|
||||
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"`
|
||||
vectorOp interface{} // equalVector | lenVector | getVector | setVector | appendVector | truncVector
|
||||
vectorOps []vectorOp
|
||||
|
||||
mapOp interface{} // TODO
|
||||
mapOps []mapOp // TODO
|
||||
)
|
||||
|
||||
// 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
|
||||
vectorFields map[pref.FieldNumber]vectorOps
|
||||
mapFields map[pref.FieldNumber]mapOps
|
||||
messageFields map[pref.FieldNumber]messageOps
|
||||
// TODO: Mutable, Range, ExtensionTypes
|
||||
)
|
||||
|
||||
// Test operations performed on a vector.
|
||||
type (
|
||||
equalVector pref.Vector
|
||||
lenVector int
|
||||
getVector map[int]pref.Value
|
||||
setVector map[int]pref.Value
|
||||
appendVector []pref.Value
|
||||
truncVector int
|
||||
// TODO: Mutable, MutableAppend
|
||||
)
|
||||
|
||||
func TestScalarProto2(t *testing.T) {
|
||||
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"`
|
||||
}
|
||||
|
||||
mi := MessageType{Desc: 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"))},
|
||||
},
|
||||
})}
|
||||
|
||||
testMessage(t, nil, mi.MessageOf(&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(mi.MessageOf(&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(mi.MessageOf(&ScalarProto2{})),
|
||||
})
|
||||
}
|
||||
|
||||
var scalarProto2Desc = mustMakeMessageDesc(ptype.StandaloneMessage{
|
||||
Syntax: pref.Proto2,
|
||||
FullName: "ScalarProto2",
|
||||
Fields: []ptype.Field{
|
||||
{Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: pref.ValueOf(bool(true))},
|
||||
{Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: pref.ValueOf(int32(2))},
|
||||
{Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: pref.ValueOf(int64(3))},
|
||||
{Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: pref.ValueOf(uint32(4))},
|
||||
{Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: pref.ValueOf(uint64(5))},
|
||||
{Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: pref.ValueOf(float32(6))},
|
||||
{Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: pref.ValueOf(float64(7))},
|
||||
{Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("8"))},
|
||||
{Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("9"))},
|
||||
{Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("10"))},
|
||||
{Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("11"))},
|
||||
func TestScalarProto3(t *testing.T) {
|
||||
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"`
|
||||
|
||||
{Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: pref.ValueOf(bool(true))},
|
||||
{Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: pref.ValueOf(int32(13))},
|
||||
{Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: pref.ValueOf(int64(14))},
|
||||
{Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: pref.ValueOf(uint32(15))},
|
||||
{Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: pref.ValueOf(uint64(16))},
|
||||
{Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: pref.ValueOf(float32(17))},
|
||||
{Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: pref.ValueOf(float64(18))},
|
||||
{Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("19"))},
|
||||
{Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("20"))},
|
||||
{Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("21"))},
|
||||
{Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("22"))},
|
||||
},
|
||||
})
|
||||
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"`
|
||||
}
|
||||
|
||||
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"`
|
||||
mi := MessageType{Desc: 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},
|
||||
|
||||
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"`
|
||||
{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},
|
||||
},
|
||||
})}
|
||||
|
||||
testMessage(t, nil, mi.MessageOf(&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(mi.MessageOf(&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(mi.MessageOf(&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(mi.MessageOf(&ScalarProto3{})),
|
||||
})
|
||||
}
|
||||
|
||||
var scalarProto3Desc = 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},
|
||||
func TestRepeatedScalars(t *testing.T) {
|
||||
type RepeatedScalars 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"`
|
||||
|
||||
{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},
|
||||
},
|
||||
})
|
||||
MyStrings1 []MyString `protobuf:"12"`
|
||||
MyStrings2 []MyBytes `protobuf:"13"`
|
||||
MyBytes1 []MyBytes `protobuf:"14"`
|
||||
MyBytes2 []MyString `protobuf:"15"`
|
||||
|
||||
func TestKnownFields(t *testing.T) {
|
||||
V := pref.ValueOf
|
||||
type (
|
||||
// has checks that each field matches the list.
|
||||
hasOp []bool
|
||||
// get checks that each field returns values matching the list.
|
||||
getOp []pref.Value
|
||||
// set calls set on each field with the given value in the list.
|
||||
setOp []pref.Value
|
||||
// clear calls clear on each field.
|
||||
clearOp []bool
|
||||
// equal checks that the current message equals the provided value.
|
||||
equalOp struct{ want interface{} }
|
||||
MyStrings3 NamedStrings `protobuf:"16"`
|
||||
MyStrings4 NamedBytes `protobuf:"17"`
|
||||
MyBytes3 NamedBytes `protobuf:"18"`
|
||||
MyBytes4 NamedStrings `protobuf:"19"`
|
||||
}
|
||||
|
||||
testOp interface{} // has | get | set | clear | equal
|
||||
)
|
||||
mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
|
||||
Syntax: pref.Proto2,
|
||||
FullName: "RepeatedScalars",
|
||||
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},
|
||||
|
||||
tests := []struct {
|
||||
structType reflect.Type
|
||||
messageDesc pref.MessageDescriptor
|
||||
testOps []testOp
|
||||
}{{
|
||||
structType: reflect.TypeOf(ScalarProto2{}),
|
||||
messageDesc: scalarProto2Desc,
|
||||
testOps: []testOp{
|
||||
hasOp([]bool{
|
||||
false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false,
|
||||
}),
|
||||
getOp([]pref.Value{
|
||||
V(bool(true)), V(int32(2)), V(int64(3)), V(uint32(4)), V(uint64(5)), V(float32(6)), V(float64(7)), V(string("8")), V(string("9")), V([]byte("10")), V([]byte("11")),
|
||||
V(bool(true)), V(int32(13)), V(int64(14)), V(uint32(15)), V(uint64(16)), V(float32(17)), V(float64(18)), V(string("19")), V(string("20")), V([]byte("21")), V([]byte("22")),
|
||||
}),
|
||||
setOp([]pref.Value{
|
||||
V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
|
||||
V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
|
||||
}),
|
||||
hasOp([]bool{
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
}),
|
||||
equalOp{&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),
|
||||
}},
|
||||
clearOp([]bool{
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
}),
|
||||
equalOp{&ScalarProto2{}},
|
||||
{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},
|
||||
},
|
||||
}, {
|
||||
structType: reflect.TypeOf(ScalarProto3{}),
|
||||
messageDesc: scalarProto3Desc,
|
||||
testOps: []testOp{
|
||||
hasOp([]bool{
|
||||
false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false,
|
||||
}),
|
||||
getOp([]pref.Value{
|
||||
V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
|
||||
V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
|
||||
}),
|
||||
setOp([]pref.Value{
|
||||
V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
|
||||
V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
|
||||
}),
|
||||
hasOp([]bool{
|
||||
false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false,
|
||||
}),
|
||||
equalOp{&ScalarProto3{}},
|
||||
setOp([]pref.Value{
|
||||
V(bool(true)), V(int32(2)), V(int64(3)), V(uint32(4)), V(uint64(5)), V(float32(6)), V(float64(7)), V(string("8")), V(string("9")), V([]byte("10")), V([]byte("11")),
|
||||
V(bool(true)), V(int32(13)), V(int64(14)), V(uint32(15)), V(uint64(16)), V(float32(17)), V(float64(18)), V(string("19")), V(string("20")), V([]byte("21")), V([]byte("22")),
|
||||
}),
|
||||
hasOp([]bool{
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
}),
|
||||
equalOp{&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",
|
||||
}},
|
||||
clearOp([]bool{
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true, true,
|
||||
}),
|
||||
equalOp{&ScalarProto3{}},
|
||||
})}
|
||||
|
||||
empty := mi.MessageOf(&RepeatedScalars{})
|
||||
emptyFS := empty.KnownFields()
|
||||
|
||||
want := mi.MessageOf(&RepeatedScalars{
|
||||
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: NamedStrings{"16", "", "sixteen"},
|
||||
MyStrings4: NamedBytes{[]byte("17"), nil, []byte("seventeen")},
|
||||
MyBytes3: NamedBytes{[]byte("18"), nil, []byte("eighteen")},
|
||||
MyBytes4: NamedStrings{"19", "", "nineteen"},
|
||||
})
|
||||
wantFS := want.KnownFields()
|
||||
|
||||
testMessage(t, nil, mi.MessageOf(&RepeatedScalars{}), 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)},
|
||||
vectorFields{
|
||||
2: {
|
||||
lenVector(0),
|
||||
appendVector{V(int32(2)), V(int32(math.MinInt32)), V(int32(math.MaxInt32))},
|
||||
getVector{0: V(int32(2)), 1: V(int32(math.MinInt32)), 2: V(int32(math.MaxInt32))},
|
||||
equalVector(wantFS.Get(2).Vector()),
|
||||
},
|
||||
4: {
|
||||
appendVector{V(uint32(0)), V(uint32(0)), V(uint32(0))},
|
||||
setVector{0: V(uint32(4)), 1: V(uint32(math.MaxUint32 / 2)), 2: V(uint32(math.MaxUint32))},
|
||||
lenVector(3),
|
||||
},
|
||||
6: {
|
||||
appendVector{V(float32(6)), V(float32(math.SmallestNonzeroFloat32)), V(float32(math.NaN())), V(float32(math.MaxFloat32))},
|
||||
equalVector(wantFS.Get(6).Vector()),
|
||||
},
|
||||
8: {
|
||||
appendVector{V(""), V(""), V(""), V(""), V(""), V("")},
|
||||
lenVector(6),
|
||||
setVector{0: V("8"), 2: V("eight")},
|
||||
truncVector(3),
|
||||
equalVector(wantFS.Get(8).Vector()),
|
||||
},
|
||||
10: {
|
||||
appendVector{V([]byte(nil)), V([]byte(nil))},
|
||||
setVector{0: V([]byte("10"))},
|
||||
appendVector{V([]byte("wrong"))},
|
||||
setVector{2: V([]byte("ten"))},
|
||||
equalVector(wantFS.Get(10).Vector()),
|
||||
},
|
||||
12: {
|
||||
appendVector{V("12"), V("wrong"), V("twelve")},
|
||||
setVector{1: V("")},
|
||||
equalVector(wantFS.Get(12).Vector()),
|
||||
},
|
||||
14: {
|
||||
appendVector{V([]byte("14")), V([]byte(nil)), V([]byte("fourteen"))},
|
||||
equalVector(wantFS.Get(14).Vector()),
|
||||
},
|
||||
16: {
|
||||
appendVector{V("16"), V(""), V("sixteen"), V("extra")},
|
||||
truncVector(3),
|
||||
equalVector(wantFS.Get(16).Vector()),
|
||||
},
|
||||
18: {
|
||||
appendVector{V([]byte("18")), V([]byte(nil)), V([]byte("eighteen"))},
|
||||
equalVector(wantFS.Get(18).Vector()),
|
||||
},
|
||||
},
|
||||
}}
|
||||
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(mi.MessageOf(&RepeatedScalars{})),
|
||||
})
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.structType.Name(), func(t *testing.T) {
|
||||
mi := MessageType{Desc: tt.messageDesc}
|
||||
// TODO: Need to test singular and repeated messages
|
||||
|
||||
// Test the field functions.
|
||||
p := reflect.New(tt.structType).Interface()
|
||||
m := mi.MessageOf(p)
|
||||
fs := m.KnownFields()
|
||||
for i, op := range tt.testOps {
|
||||
switch op := op.(type) {
|
||||
case hasOp:
|
||||
got := map[pref.FieldNumber]bool{}
|
||||
want := map[pref.FieldNumber]bool{}
|
||||
for j, ok := range op {
|
||||
n := pref.FieldNumber(j + 1)
|
||||
got[n] = fs.Has(n)
|
||||
want[n] = ok
|
||||
}
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("operation %d, has mismatch (-want, +got):\n%s", i, diff)
|
||||
}
|
||||
case getOp:
|
||||
got := map[pref.FieldNumber]pref.Value{}
|
||||
want := map[pref.FieldNumber]pref.Value{}
|
||||
for j, v := range op {
|
||||
n := pref.FieldNumber(j + 1)
|
||||
got[n] = fs.Get(n)
|
||||
want[n] = v
|
||||
}
|
||||
xformValue := cmp.Transformer("", func(v pref.Value) interface{} {
|
||||
return v.Interface()
|
||||
})
|
||||
if diff := cmp.Diff(want, got, xformValue); diff != "" {
|
||||
t.Errorf("operation %d, get mismatch (-want, +got):\n%s", i, diff)
|
||||
}
|
||||
case setOp:
|
||||
for j, v := range op {
|
||||
n := pref.FieldNumber(j + 1)
|
||||
fs.Set(n, v)
|
||||
}
|
||||
case clearOp:
|
||||
for j, ok := range op {
|
||||
n := pref.FieldNumber(j + 1)
|
||||
if ok {
|
||||
fs.Clear(n)
|
||||
}
|
||||
}
|
||||
case equalOp:
|
||||
got := m.(interface{ Unwrap() interface{} }).Unwrap()
|
||||
if diff := cmp.Diff(op.want, got); diff != "" {
|
||||
t.Errorf("operation %d, equal mismatch (-want, +got):\n%s", i, diff)
|
||||
}
|
||||
var cmpOpts = cmp.Options{
|
||||
cmp.Transformer("UnwrapValue", func(v pref.Value) interface{} {
|
||||
return v.Interface()
|
||||
}),
|
||||
cmp.Transformer("UnwrapMessage", func(m pref.Message) interface{} {
|
||||
v := m.Interface()
|
||||
if v, ok := v.(interface{ Unwrap() interface{} }); ok {
|
||||
return v.Unwrap()
|
||||
}
|
||||
return v
|
||||
}),
|
||||
cmp.Transformer("UnwrapVector", func(v pref.Vector) 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 vectorFields:
|
||||
for n, tt := range op {
|
||||
p.Push(int(n))
|
||||
testVectors(t, p, fs.Mutable(n).(pref.Vector), tt)
|
||||
p.Pop()
|
||||
}
|
||||
default:
|
||||
t.Fatalf("operation %v, invalid operation: %T", p, op)
|
||||
}
|
||||
p.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
func testVectors(t *testing.T, p path, v pref.Vector, tt vectorOps) {
|
||||
for i, op := range tt {
|
||||
p.Push(i)
|
||||
switch op := op.(type) {
|
||||
case equalVector:
|
||||
if diff := cmp.Diff(op, v, cmpOpts); diff != "" {
|
||||
t.Errorf("operation %v, vector mismatch (-want, +got):\n%s", p, diff)
|
||||
}
|
||||
case lenVector:
|
||||
if got, want := v.Len(), int(op); got != want {
|
||||
t.Errorf("operation %v, Vector.Len = %d, want %d", p, got, want)
|
||||
}
|
||||
case getVector:
|
||||
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, Vector.Get mismatch (-want, +got):\n%s", p, diff)
|
||||
}
|
||||
case setVector:
|
||||
for n, e := range op {
|
||||
v.Set(n, e)
|
||||
}
|
||||
case appendVector:
|
||||
for _, e := range op {
|
||||
v.Append(e)
|
||||
}
|
||||
case truncVector:
|
||||
v.Truncate(int(op))
|
||||
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, ".")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user