2019-04-30 11:36:39 -07:00
|
|
|
// Copyright 2019 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 prototest exercises protobuf reflection.
|
|
|
|
package prototest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"math"
|
|
|
|
"sort"
|
|
|
|
"testing"
|
|
|
|
|
2019-06-21 08:36:26 -07:00
|
|
|
"google.golang.org/protobuf/encoding/prototext"
|
|
|
|
"google.golang.org/protobuf/internal/encoding/wire"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
pref "google.golang.org/protobuf/reflect/protoreflect"
|
2019-06-21 08:36:26 -07:00
|
|
|
preg "google.golang.org/protobuf/reflect/protoregistry"
|
2019-04-30 11:36:39 -07:00
|
|
|
)
|
|
|
|
|
2019-04-25 23:48:08 -07:00
|
|
|
// TODO: Test read-only properties of unpopulated composite values.
|
|
|
|
// TODO: Test invalid field descriptors or oneof descriptors.
|
|
|
|
// TODO: This should test the functionality that can be provided by fast-paths.
|
2019-04-30 11:36:39 -07:00
|
|
|
|
2019-06-21 08:36:26 -07:00
|
|
|
// MessageOptions configure message tests.
|
|
|
|
type MessageOptions struct {
|
|
|
|
// ExtensionTypes is a list of types to test with.
|
|
|
|
//
|
|
|
|
// If nil, TestMessage will look for extension types in the global registry.
|
|
|
|
ExtensionTypes []pref.ExtensionType
|
2019-07-15 13:39:43 -07:00
|
|
|
|
|
|
|
// Resolver is used for looking up types when unmarshaling extension fields.
|
|
|
|
// If nil, this defaults to using protoregistry.GlobalTypes.
|
|
|
|
Resolver interface {
|
|
|
|
preg.ExtensionTypeResolver
|
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
}
|
|
|
|
|
2019-04-25 23:48:08 -07:00
|
|
|
// TestMessage runs the provided m through a series of tests
|
|
|
|
// exercising the protobuf reflection API.
|
2019-06-21 08:36:26 -07:00
|
|
|
func TestMessage(t testing.TB, m proto.Message, opts MessageOptions) {
|
2019-04-25 23:48:08 -07:00
|
|
|
md := m.ProtoReflect().Descriptor()
|
|
|
|
m1 := m.ProtoReflect().New()
|
2019-04-30 11:36:39 -07:00
|
|
|
for i := 0; i < md.Fields().Len(); i++ {
|
|
|
|
fd := md.Fields().Get(i)
|
2019-04-25 23:48:08 -07:00
|
|
|
testField(t, m1, fd)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
if opts.ExtensionTypes == nil {
|
|
|
|
preg.GlobalTypes.RangeExtensionsByMessage(md.FullName(), func(e pref.ExtensionType) bool {
|
|
|
|
opts.ExtensionTypes = append(opts.ExtensionTypes, e)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
for _, xt := range opts.ExtensionTypes {
|
2019-08-28 11:08:22 -07:00
|
|
|
testField(t, m1, xt.TypeDescriptor())
|
2019-06-21 08:36:26 -07:00
|
|
|
}
|
2019-04-30 11:36:39 -07:00
|
|
|
for i := 0; i < md.Oneofs().Len(); i++ {
|
2019-04-25 23:48:08 -07:00
|
|
|
testOneof(t, m1, md.Oneofs().Get(i))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
testUnknown(t, m1)
|
2019-04-30 11:36:39 -07:00
|
|
|
|
|
|
|
// Test round-trip marshal/unmarshal.
|
2019-04-25 23:48:08 -07:00
|
|
|
m2 := m.ProtoReflect().New().Interface()
|
|
|
|
populateMessage(m2.ProtoReflect(), 1, nil)
|
2019-07-15 13:39:43 -07:00
|
|
|
for _, xt := range opts.ExtensionTypes {
|
|
|
|
m2.ProtoReflect().Set(xt.TypeDescriptor(), newValue(m2.ProtoReflect(), xt.TypeDescriptor(), 1, nil))
|
|
|
|
}
|
|
|
|
b, err := proto.MarshalOptions{
|
|
|
|
AllowPartial: true,
|
|
|
|
}.Marshal(m2)
|
2019-04-30 11:36:39 -07:00
|
|
|
if err != nil {
|
2019-04-25 23:48:08 -07:00
|
|
|
t.Errorf("Marshal() = %v, want nil\n%v", err, marshalText(m2))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
m3 := m.ProtoReflect().New().Interface()
|
2019-07-15 13:39:43 -07:00
|
|
|
if err := (proto.UnmarshalOptions{
|
|
|
|
AllowPartial: true,
|
|
|
|
Resolver: opts.Resolver,
|
|
|
|
}.Unmarshal(b, m3)); err != nil {
|
2019-04-25 23:48:08 -07:00
|
|
|
t.Errorf("Unmarshal() = %v, want nil\n%v", err, marshalText(m2))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
if !proto.Equal(m2, m3) {
|
|
|
|
t.Errorf("round-trip marshal/unmarshal did not preserve message\nOriginal:\n%v\nNew:\n%v", marshalText(m2), marshalText(m3))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func marshalText(m proto.Message) string {
|
2019-05-14 12:44:37 -07:00
|
|
|
b, _ := prototext.MarshalOptions{Indent: " "}.Marshal(m)
|
2019-04-30 11:36:39 -07:00
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
|
2019-04-25 23:48:08 -07:00
|
|
|
// testField exercises set/get/has/clear of a field.
|
2019-04-30 11:36:39 -07:00
|
|
|
func testField(t testing.TB, m pref.Message, fd pref.FieldDescriptor) {
|
|
|
|
name := fd.FullName()
|
2019-04-25 23:48:08 -07:00
|
|
|
num := fd.Number()
|
2019-04-30 11:36:39 -07:00
|
|
|
|
2019-06-21 08:36:26 -07:00
|
|
|
switch {
|
|
|
|
case fd.IsList():
|
|
|
|
testFieldList(t, m, fd)
|
|
|
|
case fd.IsMap():
|
|
|
|
testFieldMap(t, m, fd)
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
case fd.Message() != nil:
|
|
|
|
default:
|
|
|
|
if got, want := m.NewField(fd), fd.Default(); !valueEqual(got, want) {
|
|
|
|
t.Errorf("Message.NewField(%v) = %v, want default value %v", name, formatValue(got), formatValue(want))
|
|
|
|
}
|
|
|
|
if fd.Kind() == pref.FloatKind || fd.Kind() == pref.DoubleKind {
|
|
|
|
testFieldFloat(t, m, fd)
|
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
}
|
|
|
|
|
2019-04-30 11:36:39 -07:00
|
|
|
// Set to a non-zero value, the zero value, different non-zero values.
|
|
|
|
for _, n := range []seed{1, 0, minVal, maxVal} {
|
|
|
|
v := newValue(m, fd, n, nil)
|
2019-04-25 23:48:08 -07:00
|
|
|
m.Set(fd, v)
|
2019-04-30 11:36:39 -07:00
|
|
|
wantHas := true
|
|
|
|
if n == 0 {
|
|
|
|
if fd.Syntax() == pref.Proto3 && fd.Message() == nil {
|
|
|
|
wantHas = false
|
|
|
|
}
|
|
|
|
if fd.Cardinality() == pref.Repeated {
|
|
|
|
wantHas = false
|
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
if fd.IsExtension() {
|
|
|
|
wantHas = true
|
|
|
|
}
|
2019-05-13 14:32:56 -07:00
|
|
|
if fd.ContainingOneof() != nil {
|
2019-04-30 11:36:39 -07:00
|
|
|
wantHas = true
|
|
|
|
}
|
|
|
|
}
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
if fd.Syntax() == pref.Proto3 && fd.Cardinality() != pref.Repeated && fd.ContainingOneof() == nil && fd.Kind() == pref.EnumKind && v.Enum() == 0 {
|
|
|
|
wantHas = false
|
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Has(fd), wantHas; got != want {
|
|
|
|
t.Errorf("after setting %q to %v:\nMessage.Has(%v) = %v, want %v", name, formatValue(v), num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), v; !valueEqual(got, want) {
|
|
|
|
t.Errorf("after setting %q:\nMessage.Get(%v) = %v, want %v", name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
found := false
|
|
|
|
m.Range(func(d pref.FieldDescriptor, got pref.Value) bool {
|
|
|
|
if fd != d {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
found = true
|
|
|
|
if want := v; !valueEqual(got, want) {
|
|
|
|
t.Errorf("after setting %q:\nMessage.Range got value %v, want %v", name, formatValue(got), formatValue(want))
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
if got, want := wantHas, found; got != want {
|
|
|
|
t.Errorf("after setting %q:\nMessageRange saw field: %v, want %v", name, got, want)
|
|
|
|
}
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
|
2019-04-25 23:48:08 -07:00
|
|
|
m.Clear(fd)
|
|
|
|
if got, want := m.Has(fd), false; got != want {
|
|
|
|
t.Errorf("after clearing %q:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
switch {
|
2019-05-13 14:32:56 -07:00
|
|
|
case fd.IsList():
|
2019-04-25 23:48:08 -07:00
|
|
|
if got := m.Get(fd); got.List().Len() != 0 {
|
|
|
|
t.Errorf("after clearing %q:\nMessage.Get(%v) = %v, want empty list", name, num, formatValue(got))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-05-13 14:32:56 -07:00
|
|
|
case fd.IsMap():
|
2019-04-25 23:48:08 -07:00
|
|
|
if got := m.Get(fd); got.Map().Len() != 0 {
|
2019-07-15 13:39:43 -07:00
|
|
|
t.Errorf("after clearing %q:\nMessage.Get(%v) = %v, want empty map", name, num, formatValue(got))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
case fd.Message() == nil:
|
|
|
|
if got, want := m.Get(fd), fd.Default(); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after clearing %q:\nMessage.Get(%v) = %v, want default %v", name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
|
2019-07-15 13:39:43 -07:00
|
|
|
// Set to the default value.
|
|
|
|
switch {
|
|
|
|
case fd.IsList() || fd.IsMap():
|
|
|
|
m.Set(fd, m.Get(fd))
|
|
|
|
if got, want := m.Has(fd), fd.IsExtension() || fd.ContainingOneof() != nil; got != want {
|
|
|
|
t.Errorf("after setting %q to default:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
|
|
|
|
}
|
|
|
|
case fd.Message() == nil:
|
|
|
|
m.Set(fd, m.Get(fd))
|
|
|
|
if got, want := m.Get(fd), fd.Default(); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after setting %q to default:\nMessage.Get(%v) = %v, want default %v", name, num, formatValue(got), formatValue(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m.Clear(fd)
|
|
|
|
|
2019-06-21 08:36:26 -07:00
|
|
|
// Set to the wrong type.
|
|
|
|
v := pref.ValueOf("")
|
|
|
|
if fd.Kind() == pref.StringKind {
|
|
|
|
v = pref.ValueOf(int32(0))
|
|
|
|
}
|
|
|
|
if !panics(func() {
|
|
|
|
m.Set(fd, v)
|
|
|
|
}) {
|
|
|
|
t.Errorf("setting %v to %T succeeds, want panic", name, v.Interface())
|
|
|
|
}
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// testFieldMap tests set/get/has/clear of entries in a map field.
|
|
|
|
func testFieldMap(t testing.TB, m pref.Message, fd pref.FieldDescriptor) {
|
|
|
|
name := fd.FullName()
|
2019-04-25 23:48:08 -07:00
|
|
|
num := fd.Number()
|
|
|
|
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
// New values.
|
2019-04-25 23:48:08 -07:00
|
|
|
m.Clear(fd) // start with an empty map
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
mapv := m.Get(fd).Map()
|
|
|
|
if got, want := mapv.NewValue(), newMapValue(fd, mapv, 0, nil); !valueEqual(got, want) {
|
|
|
|
t.Errorf("message.Get(%v).NewValue() = %v, want %v", name, formatValue(got), formatValue(want))
|
|
|
|
}
|
|
|
|
mapv = m.Mutable(fd).Map() // mutable map
|
|
|
|
if got, want := mapv.NewValue(), newMapValue(fd, mapv, 0, nil); !valueEqual(got, want) {
|
|
|
|
t.Errorf("message.Mutable(%v).NewValue() = %v, want %v", name, formatValue(got), formatValue(want))
|
|
|
|
}
|
2019-04-30 11:36:39 -07:00
|
|
|
|
|
|
|
// Add values.
|
|
|
|
want := make(testMap)
|
|
|
|
for i, n := range []seed{1, 0, minVal, maxVal} {
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Has(fd), i > 0; got != want {
|
|
|
|
t.Errorf("after inserting %d elements to %q:\nMessage.Has(%v) = %v, want %v", i, name, num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
k := newMapKey(fd, n)
|
|
|
|
v := newMapValue(fd, mapv, n, nil)
|
|
|
|
mapv.Set(k, v)
|
|
|
|
want.Set(k, v)
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), pref.ValueOf(want); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after inserting %d elements to %q:\nMessage.Get(%v) = %v, want %v", i, name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set values.
|
|
|
|
want.Range(func(k pref.MapKey, v pref.Value) bool {
|
|
|
|
nv := newMapValue(fd, mapv, 10, nil)
|
|
|
|
mapv.Set(k, nv)
|
|
|
|
want.Set(k, nv)
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), pref.ValueOf(want); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after setting element %v of %q:\nMessage.Get(%v) = %v, want %v", formatValue(k.Value()), name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
// Clear values.
|
|
|
|
want.Range(func(k pref.MapKey, v pref.Value) bool {
|
|
|
|
mapv.Clear(k)
|
|
|
|
want.Clear(k)
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Has(fd), want.Len() > 0; got != want {
|
|
|
|
t.Errorf("after clearing elements of %q:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), pref.ValueOf(want); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after clearing elements of %q:\nMessage.Get(%v) = %v, want %v", name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
// Non-existent map keys.
|
|
|
|
missingKey := newMapKey(fd, 1)
|
|
|
|
if got, want := mapv.Has(missingKey), false; got != want {
|
2019-04-25 23:48:08 -07:00
|
|
|
t.Errorf("non-existent map key in %q: Map.Has(%v) = %v, want %v", name, formatValue(missingKey.Value()), got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
if got, want := mapv.Get(missingKey).IsValid(), false; got != want {
|
2019-04-25 23:48:08 -07:00
|
|
|
t.Errorf("non-existent map key in %q: Map.Get(%v).IsValid() = %v, want %v", name, formatValue(missingKey.Value()), got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
mapv.Clear(missingKey) // noop
|
|
|
|
}
|
|
|
|
|
|
|
|
type testMap map[interface{}]pref.Value
|
|
|
|
|
|
|
|
func (m testMap) Get(k pref.MapKey) pref.Value { return m[k.Interface()] }
|
|
|
|
func (m testMap) Set(k pref.MapKey, v pref.Value) { m[k.Interface()] = v }
|
|
|
|
func (m testMap) Has(k pref.MapKey) bool { return m.Get(k).IsValid() }
|
|
|
|
func (m testMap) Clear(k pref.MapKey) { delete(m, k.Interface()) }
|
|
|
|
func (m testMap) Len() int { return len(m) }
|
|
|
|
func (m testMap) NewMessage() pref.Message { panic("unimplemented") }
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
func (m testMap) NewValue() pref.Value { panic("unimplemented") }
|
2019-04-30 11:36:39 -07:00
|
|
|
func (m testMap) Range(f func(pref.MapKey, pref.Value) bool) {
|
|
|
|
for k, v := range m {
|
|
|
|
if !f(pref.ValueOf(k).MapKey(), v) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// testFieldList exercises set/get/append/truncate of values in a list.
|
|
|
|
func testFieldList(t testing.TB, m pref.Message, fd pref.FieldDescriptor) {
|
|
|
|
name := fd.FullName()
|
2019-04-25 23:48:08 -07:00
|
|
|
num := fd.Number()
|
|
|
|
|
|
|
|
m.Clear(fd) // start with an empty list
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
list := m.Get(fd).List()
|
|
|
|
if got, want := list.NewElement(), newListElement(fd, list, 0, nil); !valueEqual(got, want) {
|
|
|
|
t.Errorf("message.Get(%v).NewElement() = %v, want %v", name, formatValue(got), formatValue(want))
|
|
|
|
}
|
|
|
|
list = m.Mutable(fd).List() // mutable list
|
|
|
|
if got, want := list.NewElement(), newListElement(fd, list, 0, nil); !valueEqual(got, want) {
|
|
|
|
t.Errorf("message.Mutable(%v).NewElement() = %v, want %v", name, formatValue(got), formatValue(want))
|
|
|
|
}
|
2019-04-30 11:36:39 -07:00
|
|
|
|
|
|
|
// Append values.
|
|
|
|
var want pref.List = &testList{}
|
|
|
|
for i, n := range []seed{1, 0, minVal, maxVal} {
|
2019-06-21 08:36:26 -07:00
|
|
|
if got, want := m.Has(fd), i > 0 || fd.IsExtension(); got != want {
|
2019-04-25 23:48:08 -07:00
|
|
|
t.Errorf("after appending %d elements to %q:\nMessage.Has(%v) = %v, want %v", i, name, num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
v := newListElement(fd, list, n, nil)
|
|
|
|
want.Append(v)
|
|
|
|
list.Append(v)
|
|
|
|
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), pref.ValueOf(want); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after appending %d elements to %q:\nMessage.Get(%v) = %v, want %v", i+1, name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set values.
|
|
|
|
for i := 0; i < want.Len(); i++ {
|
|
|
|
v := newListElement(fd, list, seed(i+10), nil)
|
|
|
|
want.Set(i, v)
|
|
|
|
list.Set(i, v)
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), pref.ValueOf(want); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after setting element %d of %q:\nMessage.Get(%v) = %v, want %v", i, name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Truncate.
|
|
|
|
for want.Len() > 0 {
|
|
|
|
n := want.Len() - 1
|
|
|
|
want.Truncate(n)
|
|
|
|
list.Truncate(n)
|
2019-06-21 08:36:26 -07:00
|
|
|
if got, want := m.Has(fd), want.Len() > 0 || fd.IsExtension(); got != want {
|
2019-04-25 23:48:08 -07:00
|
|
|
t.Errorf("after truncating %q to %d:\nMessage.Has(%v) = %v, want %v", name, n, num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), pref.ValueOf(want); !valueEqual(got, want) {
|
|
|
|
t.Errorf("after truncating %q to %d:\nMessage.Get(%v) = %v, want %v", name, n, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type testList struct {
|
|
|
|
a []pref.Value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *testList) Append(v pref.Value) { l.a = append(l.a, v) }
|
|
|
|
func (l *testList) Get(n int) pref.Value { return l.a[n] }
|
|
|
|
func (l *testList) Len() int { return len(l.a) }
|
|
|
|
func (l *testList) Set(n int, v pref.Value) { l.a[n] = v }
|
|
|
|
func (l *testList) Truncate(n int) { l.a = l.a[:n] }
|
|
|
|
func (l *testList) NewMessage() pref.Message { panic("unimplemented") }
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
func (l *testList) NewElement() pref.Value { panic("unimplemented") }
|
2019-04-30 11:36:39 -07:00
|
|
|
|
|
|
|
// testFieldFloat exercises some interesting floating-point scalar field values.
|
|
|
|
func testFieldFloat(t testing.TB, m pref.Message, fd pref.FieldDescriptor) {
|
|
|
|
name := fd.FullName()
|
2019-04-25 23:48:08 -07:00
|
|
|
num := fd.Number()
|
|
|
|
|
2019-04-30 11:36:39 -07:00
|
|
|
for _, v := range []float64{math.Inf(-1), math.Inf(1), math.NaN(), math.Copysign(0, -1)} {
|
|
|
|
var val pref.Value
|
|
|
|
if fd.Kind() == pref.FloatKind {
|
|
|
|
val = pref.ValueOf(float32(v))
|
|
|
|
} else {
|
|
|
|
val = pref.ValueOf(v)
|
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
m.Set(fd, val)
|
2019-04-30 11:36:39 -07:00
|
|
|
// Note that Has is true for -0.
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Has(fd), true; got != want {
|
|
|
|
t.Errorf("after setting %v to %v: Message.Has(%v) = %v, want %v", name, v, num, got, want)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-04-25 23:48:08 -07:00
|
|
|
if got, want := m.Get(fd), val; !valueEqual(got, want) {
|
|
|
|
t.Errorf("after setting %v: Message.Get(%v) = %v, want %v", name, num, formatValue(got), formatValue(want))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// testOneof tests the behavior of fields in a oneof.
|
|
|
|
func testOneof(t testing.TB, m pref.Message, od pref.OneofDescriptor) {
|
2019-04-30 11:36:49 -07:00
|
|
|
for _, mutable := range []bool{false, true} {
|
|
|
|
for i := 0; i < od.Fields().Len(); i++ {
|
|
|
|
fda := od.Fields().Get(i)
|
|
|
|
if mutable {
|
|
|
|
// Set fields by requesting a mutable reference.
|
|
|
|
if !fda.IsMap() && !fda.IsList() && fda.Message() == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
_ = m.Mutable(fda)
|
|
|
|
} else {
|
|
|
|
// Set fields explicitly.
|
|
|
|
m.Set(fda, newValue(m, fda, 1, nil))
|
|
|
|
}
|
|
|
|
if got, want := m.WhichOneof(od), fda; got != want {
|
|
|
|
t.Errorf("after setting oneof field %q:\nWhichOneof(%q) = %v, want %v", fda.FullName(), fda.Name(), got, want)
|
|
|
|
}
|
|
|
|
for j := 0; j < od.Fields().Len(); j++ {
|
|
|
|
fdb := od.Fields().Get(j)
|
|
|
|
if got, want := m.Has(fdb), i == j; got != want {
|
|
|
|
t.Errorf("after setting oneof field %q:\nGet(%q) = %v, want %v", fda.FullName(), fdb.FullName(), got, want)
|
|
|
|
}
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-21 08:36:26 -07:00
|
|
|
// testUnknown tests the behavior of unknown fields.
|
|
|
|
func testUnknown(t testing.TB, m pref.Message) {
|
|
|
|
var b []byte
|
|
|
|
b = wire.AppendTag(b, 1000, wire.VarintType)
|
|
|
|
b = wire.AppendVarint(b, 1001)
|
|
|
|
m.SetUnknown(pref.RawFields(b))
|
|
|
|
if got, want := []byte(m.GetUnknown()), b; !bytes.Equal(got, want) {
|
|
|
|
t.Errorf("after setting unknown fields:\nGetUnknown() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-30 11:36:39 -07:00
|
|
|
func formatValue(v pref.Value) string {
|
|
|
|
switch v := v.Interface().(type) {
|
|
|
|
case pref.List:
|
|
|
|
var buf bytes.Buffer
|
|
|
|
buf.WriteString("list[")
|
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
if i > 0 {
|
|
|
|
buf.WriteString(" ")
|
|
|
|
}
|
|
|
|
buf.WriteString(formatValue(v.Get(i)))
|
|
|
|
}
|
|
|
|
buf.WriteString("]")
|
|
|
|
return buf.String()
|
|
|
|
case pref.Map:
|
|
|
|
var buf bytes.Buffer
|
|
|
|
buf.WriteString("map[")
|
|
|
|
var keys []pref.MapKey
|
|
|
|
v.Range(func(k pref.MapKey, v pref.Value) bool {
|
|
|
|
keys = append(keys, k)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
sort.Slice(keys, func(i, j int) bool {
|
|
|
|
return keys[i].String() < keys[j].String()
|
|
|
|
})
|
|
|
|
for i, k := range keys {
|
|
|
|
if i > 0 {
|
|
|
|
buf.WriteString(" ")
|
|
|
|
}
|
|
|
|
buf.WriteString(formatValue(k.Value()))
|
|
|
|
buf.WriteString(":")
|
|
|
|
buf.WriteString(formatValue(v.Get(k)))
|
|
|
|
}
|
|
|
|
buf.WriteString("]")
|
|
|
|
return buf.String()
|
|
|
|
case pref.Message:
|
2019-05-14 12:44:37 -07:00
|
|
|
b, err := prototext.Marshal(v.Interface())
|
2019-04-30 11:36:39 -07:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Sprintf("<%v>", err)
|
|
|
|
}
|
2019-05-01 12:29:25 -07:00
|
|
|
return fmt.Sprintf("%v{%v}", v.Descriptor().FullName(), string(b))
|
2019-04-30 11:36:39 -07:00
|
|
|
case string:
|
|
|
|
return fmt.Sprintf("%q", v)
|
|
|
|
default:
|
|
|
|
return fmt.Sprint(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func valueEqual(a, b pref.Value) bool {
|
|
|
|
ai, bi := a.Interface(), b.Interface()
|
|
|
|
switch ai.(type) {
|
|
|
|
case pref.Message:
|
|
|
|
return proto.Equal(
|
|
|
|
a.Message().Interface(),
|
|
|
|
b.Message().Interface(),
|
|
|
|
)
|
|
|
|
case pref.List:
|
|
|
|
lista, listb := a.List(), b.List()
|
|
|
|
if lista.Len() != listb.Len() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i := 0; i < lista.Len(); i++ {
|
|
|
|
if !valueEqual(lista.Get(i), listb.Get(i)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
case pref.Map:
|
|
|
|
mapa, mapb := a.Map(), b.Map()
|
|
|
|
if mapa.Len() != mapb.Len() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
equal := true
|
|
|
|
mapa.Range(func(k pref.MapKey, v pref.Value) bool {
|
|
|
|
if !valueEqual(v, mapb.Get(k)) {
|
|
|
|
equal = false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return equal
|
|
|
|
case []byte:
|
|
|
|
return bytes.Equal(a.Bytes(), b.Bytes())
|
2019-05-20 15:19:14 -07:00
|
|
|
case float32:
|
2019-04-30 11:36:39 -07:00
|
|
|
// NaNs are equal, but must be the same NaN.
|
2019-05-20 15:19:14 -07:00
|
|
|
return math.Float32bits(ai.(float32)) == math.Float32bits(bi.(float32))
|
|
|
|
case float64:
|
|
|
|
// NaNs are equal, but must be the same NaN.
|
|
|
|
return math.Float64bits(ai.(float64)) == math.Float64bits(bi.(float64))
|
2019-04-30 11:36:39 -07:00
|
|
|
default:
|
|
|
|
return ai == bi
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A seed is used to vary the content of a value.
|
|
|
|
//
|
|
|
|
// A seed of 0 is the zero value. Messages do not have a zero-value; a 0-seeded messages
|
|
|
|
// is unpopulated.
|
|
|
|
//
|
|
|
|
// A seed of minVal or maxVal is the least or greatest value of the value type.
|
|
|
|
type seed int
|
|
|
|
|
|
|
|
const (
|
|
|
|
minVal seed = -1
|
|
|
|
maxVal seed = -2
|
|
|
|
)
|
|
|
|
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
// newSeed creates new seed values from a base, for example to create seeds for the
|
|
|
|
// elements in a list. If the input seed is minVal or maxVal, so is the output.
|
|
|
|
func newSeed(n seed, adjust ...int) seed {
|
|
|
|
switch n {
|
|
|
|
case minVal, maxVal:
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
for _, a := range adjust {
|
|
|
|
n = 10*n + seed(a)
|
|
|
|
}
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
2019-04-30 11:36:39 -07:00
|
|
|
// newValue returns a new value assignable to a field.
|
|
|
|
//
|
|
|
|
// The stack parameter is used to avoid infinite recursion when populating circular
|
|
|
|
// data structures.
|
2019-05-01 12:29:25 -07:00
|
|
|
func newValue(m pref.Message, fd pref.FieldDescriptor, n seed, stack []pref.MessageDescriptor) pref.Value {
|
2019-04-30 11:36:39 -07:00
|
|
|
switch {
|
2019-05-13 14:32:56 -07:00
|
|
|
case fd.IsList():
|
|
|
|
if n == 0 {
|
2019-07-15 13:39:43 -07:00
|
|
|
return m.New().Get(fd)
|
2019-05-13 14:32:56 -07:00
|
|
|
}
|
2019-07-15 13:39:43 -07:00
|
|
|
list := m.NewField(fd).List()
|
2019-05-13 14:32:56 -07:00
|
|
|
list.Append(newListElement(fd, list, 0, stack))
|
|
|
|
list.Append(newListElement(fd, list, minVal, stack))
|
|
|
|
list.Append(newListElement(fd, list, maxVal, stack))
|
|
|
|
list.Append(newListElement(fd, list, n, stack))
|
|
|
|
return pref.ValueOf(list)
|
2019-04-30 11:36:39 -07:00
|
|
|
case fd.IsMap():
|
|
|
|
if n == 0 {
|
2019-07-15 13:39:43 -07:00
|
|
|
return m.New().Get(fd)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
2019-07-15 13:39:43 -07:00
|
|
|
mapv := m.NewField(fd).Map()
|
2019-04-30 11:36:39 -07:00
|
|
|
mapv.Set(newMapKey(fd, 0), newMapValue(fd, mapv, 0, stack))
|
|
|
|
mapv.Set(newMapKey(fd, minVal), newMapValue(fd, mapv, minVal, stack))
|
|
|
|
mapv.Set(newMapKey(fd, maxVal), newMapValue(fd, mapv, maxVal, stack))
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
mapv.Set(newMapKey(fd, n), newMapValue(fd, mapv, newSeed(n, 0), stack))
|
2019-04-30 11:36:39 -07:00
|
|
|
return pref.ValueOf(mapv)
|
|
|
|
case fd.Message() != nil:
|
2019-07-15 13:39:43 -07:00
|
|
|
//if n == 0 {
|
|
|
|
// return m.New().Get(fd)
|
|
|
|
//}
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
return populateMessage(m.NewField(fd).Message(), n, stack)
|
2019-04-30 11:36:39 -07:00
|
|
|
default:
|
|
|
|
return newScalarValue(fd, n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-01 12:29:25 -07:00
|
|
|
func newListElement(fd pref.FieldDescriptor, list pref.List, n seed, stack []pref.MessageDescriptor) pref.Value {
|
2019-04-30 11:36:39 -07:00
|
|
|
if fd.Message() == nil {
|
|
|
|
return newScalarValue(fd, n)
|
|
|
|
}
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
return populateMessage(list.NewElement().Message(), n, stack)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func newMapKey(fd pref.FieldDescriptor, n seed) pref.MapKey {
|
2019-05-13 14:32:56 -07:00
|
|
|
kd := fd.MapKey()
|
2019-04-30 11:36:39 -07:00
|
|
|
return newScalarValue(kd, n).MapKey()
|
|
|
|
}
|
|
|
|
|
2019-05-01 12:29:25 -07:00
|
|
|
func newMapValue(fd pref.FieldDescriptor, mapv pref.Map, n seed, stack []pref.MessageDescriptor) pref.Value {
|
2019-05-13 14:32:56 -07:00
|
|
|
vd := fd.MapValue()
|
2019-04-30 11:36:39 -07:00
|
|
|
if vd.Message() == nil {
|
|
|
|
return newScalarValue(vd, n)
|
|
|
|
}
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
return populateMessage(mapv.NewValue().Message(), n, stack)
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func newScalarValue(fd pref.FieldDescriptor, n seed) pref.Value {
|
|
|
|
switch fd.Kind() {
|
|
|
|
case pref.BoolKind:
|
|
|
|
return pref.ValueOf(n != 0)
|
|
|
|
case pref.EnumKind:
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
vals := fd.Enum().Values()
|
|
|
|
var i int
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
i = 0
|
|
|
|
case maxVal:
|
|
|
|
i = vals.Len() - 1
|
|
|
|
default:
|
|
|
|
i = int(n) % vals.Len()
|
|
|
|
}
|
|
|
|
return pref.ValueOf(vals.Get(i).Number())
|
2019-04-30 11:36:39 -07:00
|
|
|
case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
return pref.ValueOf(int32(math.MinInt32))
|
|
|
|
case maxVal:
|
|
|
|
return pref.ValueOf(int32(math.MaxInt32))
|
|
|
|
default:
|
|
|
|
return pref.ValueOf(int32(n))
|
|
|
|
}
|
|
|
|
case pref.Uint32Kind, pref.Fixed32Kind:
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
// Only use 0 for the zero value.
|
|
|
|
return pref.ValueOf(uint32(1))
|
|
|
|
case maxVal:
|
|
|
|
return pref.ValueOf(uint32(math.MaxInt32))
|
|
|
|
default:
|
|
|
|
return pref.ValueOf(uint32(n))
|
|
|
|
}
|
|
|
|
case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
return pref.ValueOf(int64(math.MinInt64))
|
|
|
|
case maxVal:
|
|
|
|
return pref.ValueOf(int64(math.MaxInt64))
|
|
|
|
default:
|
|
|
|
return pref.ValueOf(int64(n))
|
|
|
|
}
|
|
|
|
case pref.Uint64Kind, pref.Fixed64Kind:
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
// Only use 0 for the zero value.
|
|
|
|
return pref.ValueOf(uint64(1))
|
|
|
|
case maxVal:
|
|
|
|
return pref.ValueOf(uint64(math.MaxInt64))
|
|
|
|
default:
|
|
|
|
return pref.ValueOf(uint64(n))
|
|
|
|
}
|
|
|
|
case pref.FloatKind:
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
return pref.ValueOf(float32(math.SmallestNonzeroFloat32))
|
|
|
|
case maxVal:
|
|
|
|
return pref.ValueOf(float32(math.MaxFloat32))
|
|
|
|
default:
|
|
|
|
return pref.ValueOf(1.5 * float32(n))
|
|
|
|
}
|
|
|
|
case pref.DoubleKind:
|
|
|
|
switch n {
|
|
|
|
case minVal:
|
|
|
|
return pref.ValueOf(float64(math.SmallestNonzeroFloat64))
|
|
|
|
case maxVal:
|
|
|
|
return pref.ValueOf(float64(math.MaxFloat64))
|
|
|
|
default:
|
|
|
|
return pref.ValueOf(1.5 * float64(n))
|
|
|
|
}
|
|
|
|
case pref.StringKind:
|
|
|
|
if n == 0 {
|
|
|
|
return pref.ValueOf("")
|
|
|
|
}
|
|
|
|
return pref.ValueOf(fmt.Sprintf("%d", n))
|
|
|
|
case pref.BytesKind:
|
|
|
|
if n == 0 {
|
|
|
|
return pref.ValueOf([]byte(nil))
|
|
|
|
}
|
|
|
|
return pref.ValueOf([]byte{byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n)})
|
|
|
|
}
|
|
|
|
panic("unhandled kind")
|
|
|
|
}
|
|
|
|
|
2019-05-01 12:29:25 -07:00
|
|
|
func populateMessage(m pref.Message, n seed, stack []pref.MessageDescriptor) pref.Value {
|
2019-04-30 11:36:39 -07:00
|
|
|
if n == 0 {
|
|
|
|
return pref.ValueOf(m)
|
|
|
|
}
|
2019-05-01 12:29:25 -07:00
|
|
|
md := m.Descriptor()
|
2019-04-30 11:36:39 -07:00
|
|
|
for _, x := range stack {
|
|
|
|
if md == x {
|
|
|
|
return pref.ValueOf(m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stack = append(stack, md)
|
|
|
|
for i := 0; i < md.Fields().Len(); i++ {
|
|
|
|
fd := md.Fields().Get(i)
|
|
|
|
if fd.IsWeak() {
|
|
|
|
continue
|
|
|
|
}
|
all: add NewField, NewElement, NewValue
Add methods to protoreflect.{Message,List,Map} to constrict values
assignable to a message field, list element, or map value. These
methods return the default value for scalar fields, the zero value for
scalar list elements and map values, and an empty, mutable value for
messages, lists, and maps.
Deprecate the NewMessage methods on these types, which are superseded.
Updates golang/protobuf#879
Change-Id: I0f064f60c89a239330ccea81523f559f14fd2c4f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188997
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-08-05 10:48:38 -07:00
|
|
|
m.Set(fd, newValue(m, fd, newSeed(n, i), stack))
|
2019-04-30 11:36:39 -07:00
|
|
|
}
|
|
|
|
return pref.ValueOf(m)
|
|
|
|
}
|
2019-06-21 08:36:26 -07:00
|
|
|
|
|
|
|
func panics(f func()) (didPanic bool) {
|
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
didPanic = true
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
f()
|
|
|
|
return false
|
|
|
|
}
|