xref: /aosp_15_r20/external/golang-protobuf/testing/prototest/message.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsen// Package prototest exercises protobuf reflection.
6*1c12ee1eSDan Willemsenpackage prototest
7*1c12ee1eSDan Willemsen
8*1c12ee1eSDan Willemsenimport (
9*1c12ee1eSDan Willemsen	"bytes"
10*1c12ee1eSDan Willemsen	"fmt"
11*1c12ee1eSDan Willemsen	"math"
12*1c12ee1eSDan Willemsen	"reflect"
13*1c12ee1eSDan Willemsen	"sort"
14*1c12ee1eSDan Willemsen	"strings"
15*1c12ee1eSDan Willemsen	"testing"
16*1c12ee1eSDan Willemsen
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/prototext"
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/protowire"
19*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/proto"
20*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
21*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoregistry"
22*1c12ee1eSDan Willemsen)
23*1c12ee1eSDan Willemsen
24*1c12ee1eSDan Willemsen// TODO: Test invalid field descriptors or oneof descriptors.
25*1c12ee1eSDan Willemsen// TODO: This should test the functionality that can be provided by fast-paths.
26*1c12ee1eSDan Willemsen
27*1c12ee1eSDan Willemsen// Message tests a message implementation.
28*1c12ee1eSDan Willemsentype Message struct {
29*1c12ee1eSDan Willemsen	// Resolver is used to determine the list of extension fields to test with.
30*1c12ee1eSDan Willemsen	// If nil, this defaults to using protoregistry.GlobalTypes.
31*1c12ee1eSDan Willemsen	Resolver interface {
32*1c12ee1eSDan Willemsen		FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
33*1c12ee1eSDan Willemsen		FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
34*1c12ee1eSDan Willemsen		RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
35*1c12ee1eSDan Willemsen	}
36*1c12ee1eSDan Willemsen}
37*1c12ee1eSDan Willemsen
38*1c12ee1eSDan Willemsen// Test performs tests on a MessageType implementation.
39*1c12ee1eSDan Willemsenfunc (test Message) Test(t testing.TB, mt protoreflect.MessageType) {
40*1c12ee1eSDan Willemsen	testType(t, mt)
41*1c12ee1eSDan Willemsen
42*1c12ee1eSDan Willemsen	md := mt.Descriptor()
43*1c12ee1eSDan Willemsen	m1 := mt.New()
44*1c12ee1eSDan Willemsen	for i := 0; i < md.Fields().Len(); i++ {
45*1c12ee1eSDan Willemsen		fd := md.Fields().Get(i)
46*1c12ee1eSDan Willemsen		testField(t, m1, fd)
47*1c12ee1eSDan Willemsen	}
48*1c12ee1eSDan Willemsen	if test.Resolver == nil {
49*1c12ee1eSDan Willemsen		test.Resolver = protoregistry.GlobalTypes
50*1c12ee1eSDan Willemsen	}
51*1c12ee1eSDan Willemsen	var extTypes []protoreflect.ExtensionType
52*1c12ee1eSDan Willemsen	test.Resolver.RangeExtensionsByMessage(md.FullName(), func(e protoreflect.ExtensionType) bool {
53*1c12ee1eSDan Willemsen		extTypes = append(extTypes, e)
54*1c12ee1eSDan Willemsen		return true
55*1c12ee1eSDan Willemsen	})
56*1c12ee1eSDan Willemsen	for _, xt := range extTypes {
57*1c12ee1eSDan Willemsen		testField(t, m1, xt.TypeDescriptor())
58*1c12ee1eSDan Willemsen	}
59*1c12ee1eSDan Willemsen	for i := 0; i < md.Oneofs().Len(); i++ {
60*1c12ee1eSDan Willemsen		testOneof(t, m1, md.Oneofs().Get(i))
61*1c12ee1eSDan Willemsen	}
62*1c12ee1eSDan Willemsen	testUnknown(t, m1)
63*1c12ee1eSDan Willemsen
64*1c12ee1eSDan Willemsen	// Test round-trip marshal/unmarshal.
65*1c12ee1eSDan Willemsen	m2 := mt.New().Interface()
66*1c12ee1eSDan Willemsen	populateMessage(m2.ProtoReflect(), 1, nil)
67*1c12ee1eSDan Willemsen	for _, xt := range extTypes {
68*1c12ee1eSDan Willemsen		m2.ProtoReflect().Set(xt.TypeDescriptor(), newValue(m2.ProtoReflect(), xt.TypeDescriptor(), 1, nil))
69*1c12ee1eSDan Willemsen	}
70*1c12ee1eSDan Willemsen	b, err := proto.MarshalOptions{
71*1c12ee1eSDan Willemsen		AllowPartial: true,
72*1c12ee1eSDan Willemsen	}.Marshal(m2)
73*1c12ee1eSDan Willemsen	if err != nil {
74*1c12ee1eSDan Willemsen		t.Errorf("Marshal() = %v, want nil\n%v", err, prototext.Format(m2))
75*1c12ee1eSDan Willemsen	}
76*1c12ee1eSDan Willemsen	m3 := mt.New().Interface()
77*1c12ee1eSDan Willemsen	if err := (proto.UnmarshalOptions{
78*1c12ee1eSDan Willemsen		AllowPartial: true,
79*1c12ee1eSDan Willemsen		Resolver:     test.Resolver,
80*1c12ee1eSDan Willemsen	}.Unmarshal(b, m3)); err != nil {
81*1c12ee1eSDan Willemsen		t.Errorf("Unmarshal() = %v, want nil\n%v", err, prototext.Format(m2))
82*1c12ee1eSDan Willemsen	}
83*1c12ee1eSDan Willemsen	if !proto.Equal(m2, m3) {
84*1c12ee1eSDan Willemsen		t.Errorf("round-trip marshal/unmarshal did not preserve message\nOriginal:\n%v\nNew:\n%v", prototext.Format(m2), prototext.Format(m3))
85*1c12ee1eSDan Willemsen	}
86*1c12ee1eSDan Willemsen}
87*1c12ee1eSDan Willemsen
88*1c12ee1eSDan Willemsenfunc testType(t testing.TB, mt protoreflect.MessageType) {
89*1c12ee1eSDan Willemsen	m := mt.New().Interface()
90*1c12ee1eSDan Willemsen	want := reflect.TypeOf(m)
91*1c12ee1eSDan Willemsen	if got := reflect.TypeOf(m.ProtoReflect().Interface()); got != want {
92*1c12ee1eSDan Willemsen		t.Errorf("type mismatch: reflect.TypeOf(m) != reflect.TypeOf(m.ProtoReflect().Interface()): %v != %v", got, want)
93*1c12ee1eSDan Willemsen	}
94*1c12ee1eSDan Willemsen	if got := reflect.TypeOf(m.ProtoReflect().New().Interface()); got != want {
95*1c12ee1eSDan Willemsen		t.Errorf("type mismatch: reflect.TypeOf(m) != reflect.TypeOf(m.ProtoReflect().New().Interface()): %v != %v", got, want)
96*1c12ee1eSDan Willemsen	}
97*1c12ee1eSDan Willemsen	if got := reflect.TypeOf(m.ProtoReflect().Type().Zero().Interface()); got != want {
98*1c12ee1eSDan Willemsen		t.Errorf("type mismatch: reflect.TypeOf(m) != reflect.TypeOf(m.ProtoReflect().Type().Zero().Interface()): %v != %v", got, want)
99*1c12ee1eSDan Willemsen	}
100*1c12ee1eSDan Willemsen	if mt, ok := mt.(protoreflect.MessageFieldTypes); ok {
101*1c12ee1eSDan Willemsen		testFieldTypes(t, mt)
102*1c12ee1eSDan Willemsen	}
103*1c12ee1eSDan Willemsen}
104*1c12ee1eSDan Willemsen
105*1c12ee1eSDan Willemsenfunc testFieldTypes(t testing.TB, mt protoreflect.MessageFieldTypes) {
106*1c12ee1eSDan Willemsen	descName := func(d protoreflect.Descriptor) protoreflect.FullName {
107*1c12ee1eSDan Willemsen		if d == nil {
108*1c12ee1eSDan Willemsen			return "<nil>"
109*1c12ee1eSDan Willemsen		}
110*1c12ee1eSDan Willemsen		return d.FullName()
111*1c12ee1eSDan Willemsen	}
112*1c12ee1eSDan Willemsen	typeName := func(mt protoreflect.MessageType) protoreflect.FullName {
113*1c12ee1eSDan Willemsen		if mt == nil {
114*1c12ee1eSDan Willemsen			return "<nil>"
115*1c12ee1eSDan Willemsen		}
116*1c12ee1eSDan Willemsen		return mt.Descriptor().FullName()
117*1c12ee1eSDan Willemsen	}
118*1c12ee1eSDan Willemsen	adjustExpr := func(idx int, expr string) string {
119*1c12ee1eSDan Willemsen		expr = strings.Replace(expr, "fd.", "md.Fields().Get(i).", -1)
120*1c12ee1eSDan Willemsen		expr = strings.Replace(expr, "(fd)", "(md.Fields().Get(i))", -1)
121*1c12ee1eSDan Willemsen		expr = strings.Replace(expr, "mti.", "mt.Message(i).", -1)
122*1c12ee1eSDan Willemsen		expr = strings.Replace(expr, "(i)", fmt.Sprintf("(%d)", idx), -1)
123*1c12ee1eSDan Willemsen		return expr
124*1c12ee1eSDan Willemsen	}
125*1c12ee1eSDan Willemsen	checkEnumDesc := func(idx int, gotExpr, wantExpr string, got, want protoreflect.EnumDescriptor) {
126*1c12ee1eSDan Willemsen		if got != want {
127*1c12ee1eSDan Willemsen			t.Errorf("descriptor mismatch: %v != %v: %v != %v", adjustExpr(idx, gotExpr), adjustExpr(idx, wantExpr), descName(got), descName(want))
128*1c12ee1eSDan Willemsen		}
129*1c12ee1eSDan Willemsen	}
130*1c12ee1eSDan Willemsen	checkMessageDesc := func(idx int, gotExpr, wantExpr string, got, want protoreflect.MessageDescriptor) {
131*1c12ee1eSDan Willemsen		if got != want {
132*1c12ee1eSDan Willemsen			t.Errorf("descriptor mismatch: %v != %v: %v != %v", adjustExpr(idx, gotExpr), adjustExpr(idx, wantExpr), descName(got), descName(want))
133*1c12ee1eSDan Willemsen		}
134*1c12ee1eSDan Willemsen	}
135*1c12ee1eSDan Willemsen	checkMessageType := func(idx int, gotExpr, wantExpr string, got, want protoreflect.MessageType) {
136*1c12ee1eSDan Willemsen		if got != want {
137*1c12ee1eSDan Willemsen			t.Errorf("type mismatch: %v != %v: %v != %v", adjustExpr(idx, gotExpr), adjustExpr(idx, wantExpr), typeName(got), typeName(want))
138*1c12ee1eSDan Willemsen		}
139*1c12ee1eSDan Willemsen	}
140*1c12ee1eSDan Willemsen
141*1c12ee1eSDan Willemsen	fds := mt.Descriptor().Fields()
142*1c12ee1eSDan Willemsen	m := mt.New()
143*1c12ee1eSDan Willemsen	for i := 0; i < fds.Len(); i++ {
144*1c12ee1eSDan Willemsen		fd := fds.Get(i)
145*1c12ee1eSDan Willemsen		switch {
146*1c12ee1eSDan Willemsen		case fd.IsList():
147*1c12ee1eSDan Willemsen			if fd.Enum() != nil {
148*1c12ee1eSDan Willemsen				checkEnumDesc(i,
149*1c12ee1eSDan Willemsen					"mt.Enum(i).Descriptor()", "fd.Enum()",
150*1c12ee1eSDan Willemsen					mt.Enum(i).Descriptor(), fd.Enum())
151*1c12ee1eSDan Willemsen			}
152*1c12ee1eSDan Willemsen			if fd.Message() != nil {
153*1c12ee1eSDan Willemsen				checkMessageDesc(i,
154*1c12ee1eSDan Willemsen					"mt.Message(i).Descriptor()", "fd.Message()",
155*1c12ee1eSDan Willemsen					mt.Message(i).Descriptor(), fd.Message())
156*1c12ee1eSDan Willemsen				checkMessageType(i,
157*1c12ee1eSDan Willemsen					"mt.Message(i)", "m.NewField(fd).List().NewElement().Message().Type()",
158*1c12ee1eSDan Willemsen					mt.Message(i), m.NewField(fd).List().NewElement().Message().Type())
159*1c12ee1eSDan Willemsen			}
160*1c12ee1eSDan Willemsen		case fd.IsMap():
161*1c12ee1eSDan Willemsen			mti := mt.Message(i)
162*1c12ee1eSDan Willemsen			if m := mti.New(); m != nil {
163*1c12ee1eSDan Willemsen				checkMessageDesc(i,
164*1c12ee1eSDan Willemsen					"m.Descriptor()", "fd.Message()",
165*1c12ee1eSDan Willemsen					m.Descriptor(), fd.Message())
166*1c12ee1eSDan Willemsen			}
167*1c12ee1eSDan Willemsen			if m := mti.Zero(); m != nil {
168*1c12ee1eSDan Willemsen				checkMessageDesc(i,
169*1c12ee1eSDan Willemsen					"m.Descriptor()", "fd.Message()",
170*1c12ee1eSDan Willemsen					m.Descriptor(), fd.Message())
171*1c12ee1eSDan Willemsen			}
172*1c12ee1eSDan Willemsen			checkMessageDesc(i,
173*1c12ee1eSDan Willemsen				"mti.Descriptor()", "fd.Message()",
174*1c12ee1eSDan Willemsen				mti.Descriptor(), fd.Message())
175*1c12ee1eSDan Willemsen			if mti := mti.(protoreflect.MessageFieldTypes); mti != nil {
176*1c12ee1eSDan Willemsen				if fd.MapValue().Enum() != nil {
177*1c12ee1eSDan Willemsen					checkEnumDesc(i,
178*1c12ee1eSDan Willemsen						"mti.Enum(fd.MapValue().Index()).Descriptor()", "fd.MapValue().Enum()",
179*1c12ee1eSDan Willemsen						mti.Enum(fd.MapValue().Index()).Descriptor(), fd.MapValue().Enum())
180*1c12ee1eSDan Willemsen				}
181*1c12ee1eSDan Willemsen				if fd.MapValue().Message() != nil {
182*1c12ee1eSDan Willemsen					checkMessageDesc(i,
183*1c12ee1eSDan Willemsen						"mti.Message(fd.MapValue().Index()).Descriptor()", "fd.MapValue().Message()",
184*1c12ee1eSDan Willemsen						mti.Message(fd.MapValue().Index()).Descriptor(), fd.MapValue().Message())
185*1c12ee1eSDan Willemsen					checkMessageType(i,
186*1c12ee1eSDan Willemsen						"mti.Message(fd.MapValue().Index())", "m.NewField(fd).Map().NewValue().Message().Type()",
187*1c12ee1eSDan Willemsen						mti.Message(fd.MapValue().Index()), m.NewField(fd).Map().NewValue().Message().Type())
188*1c12ee1eSDan Willemsen				}
189*1c12ee1eSDan Willemsen			}
190*1c12ee1eSDan Willemsen		default:
191*1c12ee1eSDan Willemsen			if fd.Enum() != nil {
192*1c12ee1eSDan Willemsen				checkEnumDesc(i,
193*1c12ee1eSDan Willemsen					"mt.Enum(i).Descriptor()", "fd.Enum()",
194*1c12ee1eSDan Willemsen					mt.Enum(i).Descriptor(), fd.Enum())
195*1c12ee1eSDan Willemsen			}
196*1c12ee1eSDan Willemsen			if fd.Message() != nil {
197*1c12ee1eSDan Willemsen				checkMessageDesc(i,
198*1c12ee1eSDan Willemsen					"mt.Message(i).Descriptor()", "fd.Message()",
199*1c12ee1eSDan Willemsen					mt.Message(i).Descriptor(), fd.Message())
200*1c12ee1eSDan Willemsen				checkMessageType(i,
201*1c12ee1eSDan Willemsen					"mt.Message(i)", "m.NewField(fd).Message().Type()",
202*1c12ee1eSDan Willemsen					mt.Message(i), m.NewField(fd).Message().Type())
203*1c12ee1eSDan Willemsen			}
204*1c12ee1eSDan Willemsen		}
205*1c12ee1eSDan Willemsen	}
206*1c12ee1eSDan Willemsen}
207*1c12ee1eSDan Willemsen
208*1c12ee1eSDan Willemsen// testField exercises set/get/has/clear of a field.
209*1c12ee1eSDan Willemsenfunc testField(t testing.TB, m protoreflect.Message, fd protoreflect.FieldDescriptor) {
210*1c12ee1eSDan Willemsen	name := fd.FullName()
211*1c12ee1eSDan Willemsen	num := fd.Number()
212*1c12ee1eSDan Willemsen
213*1c12ee1eSDan Willemsen	switch {
214*1c12ee1eSDan Willemsen	case fd.IsList():
215*1c12ee1eSDan Willemsen		testFieldList(t, m, fd)
216*1c12ee1eSDan Willemsen	case fd.IsMap():
217*1c12ee1eSDan Willemsen		testFieldMap(t, m, fd)
218*1c12ee1eSDan Willemsen	case fd.Message() != nil:
219*1c12ee1eSDan Willemsen	default:
220*1c12ee1eSDan Willemsen		if got, want := m.NewField(fd), fd.Default(); !valueEqual(got, want) {
221*1c12ee1eSDan Willemsen			t.Errorf("Message.NewField(%v) = %v, want default value %v", name, formatValue(got), formatValue(want))
222*1c12ee1eSDan Willemsen		}
223*1c12ee1eSDan Willemsen		if fd.Kind() == protoreflect.FloatKind || fd.Kind() == protoreflect.DoubleKind {
224*1c12ee1eSDan Willemsen			testFieldFloat(t, m, fd)
225*1c12ee1eSDan Willemsen		}
226*1c12ee1eSDan Willemsen	}
227*1c12ee1eSDan Willemsen
228*1c12ee1eSDan Willemsen	// Set to a non-zero value, the zero value, different non-zero values.
229*1c12ee1eSDan Willemsen	for _, n := range []seed{1, 0, minVal, maxVal} {
230*1c12ee1eSDan Willemsen		v := newValue(m, fd, n, nil)
231*1c12ee1eSDan Willemsen		m.Set(fd, v)
232*1c12ee1eSDan Willemsen		wantHas := true
233*1c12ee1eSDan Willemsen		if n == 0 {
234*1c12ee1eSDan Willemsen			if fd.Syntax() == protoreflect.Proto3 && fd.Message() == nil {
235*1c12ee1eSDan Willemsen				wantHas = false
236*1c12ee1eSDan Willemsen			}
237*1c12ee1eSDan Willemsen			if fd.IsExtension() {
238*1c12ee1eSDan Willemsen				wantHas = true
239*1c12ee1eSDan Willemsen			}
240*1c12ee1eSDan Willemsen			if fd.Cardinality() == protoreflect.Repeated {
241*1c12ee1eSDan Willemsen				wantHas = false
242*1c12ee1eSDan Willemsen			}
243*1c12ee1eSDan Willemsen			if fd.ContainingOneof() != nil {
244*1c12ee1eSDan Willemsen				wantHas = true
245*1c12ee1eSDan Willemsen			}
246*1c12ee1eSDan Willemsen		}
247*1c12ee1eSDan Willemsen		if fd.Syntax() == protoreflect.Proto3 && fd.Cardinality() != protoreflect.Repeated && fd.ContainingOneof() == nil && fd.Kind() == protoreflect.EnumKind && v.Enum() == 0 {
248*1c12ee1eSDan Willemsen			wantHas = false
249*1c12ee1eSDan Willemsen		}
250*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), wantHas; got != want {
251*1c12ee1eSDan Willemsen			t.Errorf("after setting %q to %v:\nMessage.Has(%v) = %v, want %v", name, formatValue(v), num, got, want)
252*1c12ee1eSDan Willemsen		}
253*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), v; !valueEqual(got, want) {
254*1c12ee1eSDan Willemsen			t.Errorf("after setting %q:\nMessage.Get(%v) = %v, want %v", name, num, formatValue(got), formatValue(want))
255*1c12ee1eSDan Willemsen		}
256*1c12ee1eSDan Willemsen		found := false
257*1c12ee1eSDan Willemsen		m.Range(func(d protoreflect.FieldDescriptor, got protoreflect.Value) bool {
258*1c12ee1eSDan Willemsen			if fd != d {
259*1c12ee1eSDan Willemsen				return true
260*1c12ee1eSDan Willemsen			}
261*1c12ee1eSDan Willemsen			found = true
262*1c12ee1eSDan Willemsen			if want := v; !valueEqual(got, want) {
263*1c12ee1eSDan Willemsen				t.Errorf("after setting %q:\nMessage.Range got value %v, want %v", name, formatValue(got), formatValue(want))
264*1c12ee1eSDan Willemsen			}
265*1c12ee1eSDan Willemsen			return true
266*1c12ee1eSDan Willemsen		})
267*1c12ee1eSDan Willemsen		if got, want := wantHas, found; got != want {
268*1c12ee1eSDan Willemsen			t.Errorf("after setting %q:\nMessageRange saw field: %v, want %v", name, got, want)
269*1c12ee1eSDan Willemsen		}
270*1c12ee1eSDan Willemsen	}
271*1c12ee1eSDan Willemsen
272*1c12ee1eSDan Willemsen	m.Clear(fd)
273*1c12ee1eSDan Willemsen	if got, want := m.Has(fd), false; got != want {
274*1c12ee1eSDan Willemsen		t.Errorf("after clearing %q:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
275*1c12ee1eSDan Willemsen	}
276*1c12ee1eSDan Willemsen	switch {
277*1c12ee1eSDan Willemsen	case fd.IsList():
278*1c12ee1eSDan Willemsen		if got := m.Get(fd); got.List().Len() != 0 {
279*1c12ee1eSDan Willemsen			t.Errorf("after clearing %q:\nMessage.Get(%v) = %v, want empty list", name, num, formatValue(got))
280*1c12ee1eSDan Willemsen		}
281*1c12ee1eSDan Willemsen	case fd.IsMap():
282*1c12ee1eSDan Willemsen		if got := m.Get(fd); got.Map().Len() != 0 {
283*1c12ee1eSDan Willemsen			t.Errorf("after clearing %q:\nMessage.Get(%v) = %v, want empty map", name, num, formatValue(got))
284*1c12ee1eSDan Willemsen		}
285*1c12ee1eSDan Willemsen	case fd.Message() == nil:
286*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), fd.Default(); !valueEqual(got, want) {
287*1c12ee1eSDan Willemsen			t.Errorf("after clearing %q:\nMessage.Get(%v) = %v, want default %v", name, num, formatValue(got), formatValue(want))
288*1c12ee1eSDan Willemsen		}
289*1c12ee1eSDan Willemsen	}
290*1c12ee1eSDan Willemsen
291*1c12ee1eSDan Willemsen	// Set to the default value.
292*1c12ee1eSDan Willemsen	switch {
293*1c12ee1eSDan Willemsen	case fd.IsList() || fd.IsMap():
294*1c12ee1eSDan Willemsen		m.Set(fd, m.Mutable(fd))
295*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), (fd.IsExtension() && fd.Cardinality() != protoreflect.Repeated) || fd.ContainingOneof() != nil; got != want {
296*1c12ee1eSDan Willemsen			t.Errorf("after setting %q to default:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
297*1c12ee1eSDan Willemsen		}
298*1c12ee1eSDan Willemsen	case fd.Message() == nil:
299*1c12ee1eSDan Willemsen		m.Set(fd, m.Get(fd))
300*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), fd.Default(); !valueEqual(got, want) {
301*1c12ee1eSDan Willemsen			t.Errorf("after setting %q to default:\nMessage.Get(%v) = %v, want default %v", name, num, formatValue(got), formatValue(want))
302*1c12ee1eSDan Willemsen		}
303*1c12ee1eSDan Willemsen	}
304*1c12ee1eSDan Willemsen	m.Clear(fd)
305*1c12ee1eSDan Willemsen
306*1c12ee1eSDan Willemsen	// Set to the wrong type.
307*1c12ee1eSDan Willemsen	v := protoreflect.ValueOfString("")
308*1c12ee1eSDan Willemsen	if fd.Kind() == protoreflect.StringKind {
309*1c12ee1eSDan Willemsen		v = protoreflect.ValueOfInt32(0)
310*1c12ee1eSDan Willemsen	}
311*1c12ee1eSDan Willemsen	if !panics(func() {
312*1c12ee1eSDan Willemsen		m.Set(fd, v)
313*1c12ee1eSDan Willemsen	}) {
314*1c12ee1eSDan Willemsen		t.Errorf("setting %v to %T succeeds, want panic", name, v.Interface())
315*1c12ee1eSDan Willemsen	}
316*1c12ee1eSDan Willemsen}
317*1c12ee1eSDan Willemsen
318*1c12ee1eSDan Willemsen// testFieldMap tests set/get/has/clear of entries in a map field.
319*1c12ee1eSDan Willemsenfunc testFieldMap(t testing.TB, m protoreflect.Message, fd protoreflect.FieldDescriptor) {
320*1c12ee1eSDan Willemsen	name := fd.FullName()
321*1c12ee1eSDan Willemsen	num := fd.Number()
322*1c12ee1eSDan Willemsen
323*1c12ee1eSDan Willemsen	// New values.
324*1c12ee1eSDan Willemsen	m.Clear(fd) // start with an empty map
325*1c12ee1eSDan Willemsen	mapv := m.Get(fd).Map()
326*1c12ee1eSDan Willemsen	if mapv.IsValid() {
327*1c12ee1eSDan Willemsen		t.Errorf("after clearing field: message.Get(%v).IsValid() = true, want false", name)
328*1c12ee1eSDan Willemsen	}
329*1c12ee1eSDan Willemsen	if got, want := mapv.NewValue(), newMapValue(fd, mapv, 0, nil); !valueEqual(got, want) {
330*1c12ee1eSDan Willemsen		t.Errorf("message.Get(%v).NewValue() = %v, want %v", name, formatValue(got), formatValue(want))
331*1c12ee1eSDan Willemsen	}
332*1c12ee1eSDan Willemsen	if !panics(func() {
333*1c12ee1eSDan Willemsen		m.Set(fd, protoreflect.ValueOfMap(mapv))
334*1c12ee1eSDan Willemsen	}) {
335*1c12ee1eSDan Willemsen		t.Errorf("message.Set(%v, <invalid>) does not panic", name)
336*1c12ee1eSDan Willemsen	}
337*1c12ee1eSDan Willemsen	if !panics(func() {
338*1c12ee1eSDan Willemsen		mapv.Set(newMapKey(fd, 0), newMapValue(fd, mapv, 0, nil))
339*1c12ee1eSDan Willemsen	}) {
340*1c12ee1eSDan Willemsen		t.Errorf("message.Get(%v).Set(...) of invalid map does not panic", name)
341*1c12ee1eSDan Willemsen	}
342*1c12ee1eSDan Willemsen	mapv = m.Mutable(fd).Map() // mutable map
343*1c12ee1eSDan Willemsen	if !mapv.IsValid() {
344*1c12ee1eSDan Willemsen		t.Errorf("message.Mutable(%v).IsValid() = false, want true", name)
345*1c12ee1eSDan Willemsen	}
346*1c12ee1eSDan Willemsen	if got, want := mapv.NewValue(), newMapValue(fd, mapv, 0, nil); !valueEqual(got, want) {
347*1c12ee1eSDan Willemsen		t.Errorf("message.Mutable(%v).NewValue() = %v, want %v", name, formatValue(got), formatValue(want))
348*1c12ee1eSDan Willemsen	}
349*1c12ee1eSDan Willemsen
350*1c12ee1eSDan Willemsen	// Add values.
351*1c12ee1eSDan Willemsen	want := make(testMap)
352*1c12ee1eSDan Willemsen	for i, n := range []seed{1, 0, minVal, maxVal} {
353*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), i > 0; got != want {
354*1c12ee1eSDan Willemsen			t.Errorf("after inserting %d elements to %q:\nMessage.Has(%v) = %v, want %v", i, name, num, got, want)
355*1c12ee1eSDan Willemsen		}
356*1c12ee1eSDan Willemsen
357*1c12ee1eSDan Willemsen		k := newMapKey(fd, n)
358*1c12ee1eSDan Willemsen		v := newMapValue(fd, mapv, n, nil)
359*1c12ee1eSDan Willemsen		mapv.Set(k, v)
360*1c12ee1eSDan Willemsen		want.Set(k, v)
361*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), protoreflect.ValueOfMap(want); !valueEqual(got, want) {
362*1c12ee1eSDan Willemsen			t.Errorf("after inserting %d elements to %q:\nMessage.Get(%v) = %v, want %v", i, name, num, formatValue(got), formatValue(want))
363*1c12ee1eSDan Willemsen		}
364*1c12ee1eSDan Willemsen	}
365*1c12ee1eSDan Willemsen
366*1c12ee1eSDan Willemsen	// Set values.
367*1c12ee1eSDan Willemsen	want.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
368*1c12ee1eSDan Willemsen		nv := newMapValue(fd, mapv, 10, nil)
369*1c12ee1eSDan Willemsen		mapv.Set(k, nv)
370*1c12ee1eSDan Willemsen		want.Set(k, nv)
371*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), protoreflect.ValueOfMap(want); !valueEqual(got, want) {
372*1c12ee1eSDan Willemsen			t.Errorf("after setting element %v of %q:\nMessage.Get(%v) = %v, want %v", formatValue(k.Value()), name, num, formatValue(got), formatValue(want))
373*1c12ee1eSDan Willemsen		}
374*1c12ee1eSDan Willemsen		return true
375*1c12ee1eSDan Willemsen	})
376*1c12ee1eSDan Willemsen
377*1c12ee1eSDan Willemsen	// Clear values.
378*1c12ee1eSDan Willemsen	want.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
379*1c12ee1eSDan Willemsen		mapv.Clear(k)
380*1c12ee1eSDan Willemsen		want.Clear(k)
381*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), want.Len() > 0; got != want {
382*1c12ee1eSDan Willemsen			t.Errorf("after clearing elements of %q:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
383*1c12ee1eSDan Willemsen		}
384*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), protoreflect.ValueOfMap(want); !valueEqual(got, want) {
385*1c12ee1eSDan Willemsen			t.Errorf("after clearing elements of %q:\nMessage.Get(%v) = %v, want %v", name, num, formatValue(got), formatValue(want))
386*1c12ee1eSDan Willemsen		}
387*1c12ee1eSDan Willemsen		return true
388*1c12ee1eSDan Willemsen	})
389*1c12ee1eSDan Willemsen	if mapv := m.Get(fd).Map(); mapv.IsValid() {
390*1c12ee1eSDan Willemsen		t.Errorf("after clearing all elements: message.Get(%v).IsValid() = true, want false %v", name, formatValue(protoreflect.ValueOfMap(mapv)))
391*1c12ee1eSDan Willemsen	}
392*1c12ee1eSDan Willemsen
393*1c12ee1eSDan Willemsen	// Non-existent map keys.
394*1c12ee1eSDan Willemsen	missingKey := newMapKey(fd, 1)
395*1c12ee1eSDan Willemsen	if got, want := mapv.Has(missingKey), false; got != want {
396*1c12ee1eSDan Willemsen		t.Errorf("non-existent map key in %q: Map.Has(%v) = %v, want %v", name, formatValue(missingKey.Value()), got, want)
397*1c12ee1eSDan Willemsen	}
398*1c12ee1eSDan Willemsen	if got, want := mapv.Get(missingKey).IsValid(), false; got != want {
399*1c12ee1eSDan Willemsen		t.Errorf("non-existent map key in %q: Map.Get(%v).IsValid() = %v, want %v", name, formatValue(missingKey.Value()), got, want)
400*1c12ee1eSDan Willemsen	}
401*1c12ee1eSDan Willemsen	mapv.Clear(missingKey) // noop
402*1c12ee1eSDan Willemsen
403*1c12ee1eSDan Willemsen	// Mutable.
404*1c12ee1eSDan Willemsen	if fd.MapValue().Message() == nil {
405*1c12ee1eSDan Willemsen		if !panics(func() {
406*1c12ee1eSDan Willemsen			mapv.Mutable(newMapKey(fd, 1))
407*1c12ee1eSDan Willemsen		}) {
408*1c12ee1eSDan Willemsen			t.Errorf("Mutable on %q succeeds, want panic", name)
409*1c12ee1eSDan Willemsen		}
410*1c12ee1eSDan Willemsen	} else {
411*1c12ee1eSDan Willemsen		k := newMapKey(fd, 1)
412*1c12ee1eSDan Willemsen		v := mapv.Mutable(k)
413*1c12ee1eSDan Willemsen		if got, want := mapv.Len(), 1; got != want {
414*1c12ee1eSDan Willemsen			t.Errorf("after Mutable on %q, Map.Len() = %v, want %v", name, got, want)
415*1c12ee1eSDan Willemsen		}
416*1c12ee1eSDan Willemsen		populateMessage(v.Message(), 1, nil)
417*1c12ee1eSDan Willemsen		if !valueEqual(mapv.Get(k), v) {
418*1c12ee1eSDan Willemsen			t.Errorf("after Mutable on %q, changing new mutable value does not change map entry", name)
419*1c12ee1eSDan Willemsen		}
420*1c12ee1eSDan Willemsen		mapv.Clear(k)
421*1c12ee1eSDan Willemsen	}
422*1c12ee1eSDan Willemsen}
423*1c12ee1eSDan Willemsen
424*1c12ee1eSDan Willemsentype testMap map[interface{}]protoreflect.Value
425*1c12ee1eSDan Willemsen
426*1c12ee1eSDan Willemsenfunc (m testMap) Get(k protoreflect.MapKey) protoreflect.Value     { return m[k.Interface()] }
427*1c12ee1eSDan Willemsenfunc (m testMap) Set(k protoreflect.MapKey, v protoreflect.Value)  { m[k.Interface()] = v }
428*1c12ee1eSDan Willemsenfunc (m testMap) Has(k protoreflect.MapKey) bool                   { return m.Get(k).IsValid() }
429*1c12ee1eSDan Willemsenfunc (m testMap) Clear(k protoreflect.MapKey)                      { delete(m, k.Interface()) }
430*1c12ee1eSDan Willemsenfunc (m testMap) Mutable(k protoreflect.MapKey) protoreflect.Value { panic("unimplemented") }
431*1c12ee1eSDan Willemsenfunc (m testMap) Len() int                                         { return len(m) }
432*1c12ee1eSDan Willemsenfunc (m testMap) NewValue() protoreflect.Value                     { panic("unimplemented") }
433*1c12ee1eSDan Willemsenfunc (m testMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
434*1c12ee1eSDan Willemsen	for k, v := range m {
435*1c12ee1eSDan Willemsen		if !f(protoreflect.ValueOf(k).MapKey(), v) {
436*1c12ee1eSDan Willemsen			return
437*1c12ee1eSDan Willemsen		}
438*1c12ee1eSDan Willemsen	}
439*1c12ee1eSDan Willemsen}
440*1c12ee1eSDan Willemsenfunc (m testMap) IsValid() bool { return true }
441*1c12ee1eSDan Willemsen
442*1c12ee1eSDan Willemsen// testFieldList exercises set/get/append/truncate of values in a list.
443*1c12ee1eSDan Willemsenfunc testFieldList(t testing.TB, m protoreflect.Message, fd protoreflect.FieldDescriptor) {
444*1c12ee1eSDan Willemsen	name := fd.FullName()
445*1c12ee1eSDan Willemsen	num := fd.Number()
446*1c12ee1eSDan Willemsen
447*1c12ee1eSDan Willemsen	m.Clear(fd) // start with an empty list
448*1c12ee1eSDan Willemsen	list := m.Get(fd).List()
449*1c12ee1eSDan Willemsen	if list.IsValid() {
450*1c12ee1eSDan Willemsen		t.Errorf("message.Get(%v).IsValid() = true, want false", name)
451*1c12ee1eSDan Willemsen	}
452*1c12ee1eSDan Willemsen	if !panics(func() {
453*1c12ee1eSDan Willemsen		m.Set(fd, protoreflect.ValueOfList(list))
454*1c12ee1eSDan Willemsen	}) {
455*1c12ee1eSDan Willemsen		t.Errorf("message.Set(%v, <invalid>) does not panic", name)
456*1c12ee1eSDan Willemsen	}
457*1c12ee1eSDan Willemsen	if !panics(func() {
458*1c12ee1eSDan Willemsen		list.Append(newListElement(fd, list, 0, nil))
459*1c12ee1eSDan Willemsen	}) {
460*1c12ee1eSDan Willemsen		t.Errorf("message.Get(%v).Append(...) of invalid list does not panic", name)
461*1c12ee1eSDan Willemsen	}
462*1c12ee1eSDan Willemsen	if got, want := list.NewElement(), newListElement(fd, list, 0, nil); !valueEqual(got, want) {
463*1c12ee1eSDan Willemsen		t.Errorf("message.Get(%v).NewElement() = %v, want %v", name, formatValue(got), formatValue(want))
464*1c12ee1eSDan Willemsen	}
465*1c12ee1eSDan Willemsen	list = m.Mutable(fd).List() // mutable list
466*1c12ee1eSDan Willemsen	if !list.IsValid() {
467*1c12ee1eSDan Willemsen		t.Errorf("message.Get(%v).IsValid() = false, want true", name)
468*1c12ee1eSDan Willemsen	}
469*1c12ee1eSDan Willemsen	if got, want := list.NewElement(), newListElement(fd, list, 0, nil); !valueEqual(got, want) {
470*1c12ee1eSDan Willemsen		t.Errorf("message.Mutable(%v).NewElement() = %v, want %v", name, formatValue(got), formatValue(want))
471*1c12ee1eSDan Willemsen	}
472*1c12ee1eSDan Willemsen
473*1c12ee1eSDan Willemsen	// Append values.
474*1c12ee1eSDan Willemsen	var want protoreflect.List = &testList{}
475*1c12ee1eSDan Willemsen	for i, n := range []seed{1, 0, minVal, maxVal} {
476*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), i > 0; got != want {
477*1c12ee1eSDan Willemsen			t.Errorf("after appending %d elements to %q:\nMessage.Has(%v) = %v, want %v", i, name, num, got, want)
478*1c12ee1eSDan Willemsen		}
479*1c12ee1eSDan Willemsen		v := newListElement(fd, list, n, nil)
480*1c12ee1eSDan Willemsen		want.Append(v)
481*1c12ee1eSDan Willemsen		list.Append(v)
482*1c12ee1eSDan Willemsen
483*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), protoreflect.ValueOfList(want); !valueEqual(got, want) {
484*1c12ee1eSDan Willemsen			t.Errorf("after appending %d elements to %q:\nMessage.Get(%v) = %v, want %v", i+1, name, num, formatValue(got), formatValue(want))
485*1c12ee1eSDan Willemsen		}
486*1c12ee1eSDan Willemsen	}
487*1c12ee1eSDan Willemsen
488*1c12ee1eSDan Willemsen	// Set values.
489*1c12ee1eSDan Willemsen	for i := 0; i < want.Len(); i++ {
490*1c12ee1eSDan Willemsen		v := newListElement(fd, list, seed(i+10), nil)
491*1c12ee1eSDan Willemsen		want.Set(i, v)
492*1c12ee1eSDan Willemsen		list.Set(i, v)
493*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), protoreflect.ValueOfList(want); !valueEqual(got, want) {
494*1c12ee1eSDan Willemsen			t.Errorf("after setting element %d of %q:\nMessage.Get(%v) = %v, want %v", i, name, num, formatValue(got), formatValue(want))
495*1c12ee1eSDan Willemsen		}
496*1c12ee1eSDan Willemsen	}
497*1c12ee1eSDan Willemsen
498*1c12ee1eSDan Willemsen	// Truncate.
499*1c12ee1eSDan Willemsen	for want.Len() > 0 {
500*1c12ee1eSDan Willemsen		n := want.Len() - 1
501*1c12ee1eSDan Willemsen		want.Truncate(n)
502*1c12ee1eSDan Willemsen		list.Truncate(n)
503*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), want.Len() > 0; got != want {
504*1c12ee1eSDan Willemsen			t.Errorf("after truncating %q to %d:\nMessage.Has(%v) = %v, want %v", name, n, num, got, want)
505*1c12ee1eSDan Willemsen		}
506*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), protoreflect.ValueOfList(want); !valueEqual(got, want) {
507*1c12ee1eSDan Willemsen			t.Errorf("after truncating %q to %d:\nMessage.Get(%v) = %v, want %v", name, n, num, formatValue(got), formatValue(want))
508*1c12ee1eSDan Willemsen		}
509*1c12ee1eSDan Willemsen	}
510*1c12ee1eSDan Willemsen
511*1c12ee1eSDan Willemsen	// AppendMutable.
512*1c12ee1eSDan Willemsen	if fd.Message() == nil {
513*1c12ee1eSDan Willemsen		if !panics(func() {
514*1c12ee1eSDan Willemsen			list.AppendMutable()
515*1c12ee1eSDan Willemsen		}) {
516*1c12ee1eSDan Willemsen			t.Errorf("AppendMutable on %q succeeds, want panic", name)
517*1c12ee1eSDan Willemsen		}
518*1c12ee1eSDan Willemsen	} else {
519*1c12ee1eSDan Willemsen		v := list.AppendMutable()
520*1c12ee1eSDan Willemsen		if got, want := list.Len(), 1; got != want {
521*1c12ee1eSDan Willemsen			t.Errorf("after AppendMutable on %q, list.Len() = %v, want %v", name, got, want)
522*1c12ee1eSDan Willemsen		}
523*1c12ee1eSDan Willemsen		populateMessage(v.Message(), 1, nil)
524*1c12ee1eSDan Willemsen		if !valueEqual(list.Get(0), v) {
525*1c12ee1eSDan Willemsen			t.Errorf("after AppendMutable on %q, changing new mutable value does not change list item 0", name)
526*1c12ee1eSDan Willemsen		}
527*1c12ee1eSDan Willemsen		want.Truncate(0)
528*1c12ee1eSDan Willemsen	}
529*1c12ee1eSDan Willemsen}
530*1c12ee1eSDan Willemsen
531*1c12ee1eSDan Willemsentype testList struct {
532*1c12ee1eSDan Willemsen	a []protoreflect.Value
533*1c12ee1eSDan Willemsen}
534*1c12ee1eSDan Willemsen
535*1c12ee1eSDan Willemsenfunc (l *testList) Append(v protoreflect.Value)       { l.a = append(l.a, v) }
536*1c12ee1eSDan Willemsenfunc (l *testList) AppendMutable() protoreflect.Value { panic("unimplemented") }
537*1c12ee1eSDan Willemsenfunc (l *testList) Get(n int) protoreflect.Value      { return l.a[n] }
538*1c12ee1eSDan Willemsenfunc (l *testList) Len() int                          { return len(l.a) }
539*1c12ee1eSDan Willemsenfunc (l *testList) Set(n int, v protoreflect.Value)   { l.a[n] = v }
540*1c12ee1eSDan Willemsenfunc (l *testList) Truncate(n int)                    { l.a = l.a[:n] }
541*1c12ee1eSDan Willemsenfunc (l *testList) NewElement() protoreflect.Value    { panic("unimplemented") }
542*1c12ee1eSDan Willemsenfunc (l *testList) IsValid() bool                     { return true }
543*1c12ee1eSDan Willemsen
544*1c12ee1eSDan Willemsen// testFieldFloat exercises some interesting floating-point scalar field values.
545*1c12ee1eSDan Willemsenfunc testFieldFloat(t testing.TB, m protoreflect.Message, fd protoreflect.FieldDescriptor) {
546*1c12ee1eSDan Willemsen	name := fd.FullName()
547*1c12ee1eSDan Willemsen	num := fd.Number()
548*1c12ee1eSDan Willemsen
549*1c12ee1eSDan Willemsen	for _, v := range []float64{math.Inf(-1), math.Inf(1), math.NaN(), math.Copysign(0, -1)} {
550*1c12ee1eSDan Willemsen		var val protoreflect.Value
551*1c12ee1eSDan Willemsen		if fd.Kind() == protoreflect.FloatKind {
552*1c12ee1eSDan Willemsen			val = protoreflect.ValueOfFloat32(float32(v))
553*1c12ee1eSDan Willemsen		} else {
554*1c12ee1eSDan Willemsen			val = protoreflect.ValueOfFloat64(float64(v))
555*1c12ee1eSDan Willemsen		}
556*1c12ee1eSDan Willemsen		m.Set(fd, val)
557*1c12ee1eSDan Willemsen		// Note that Has is true for -0.
558*1c12ee1eSDan Willemsen		if got, want := m.Has(fd), true; got != want {
559*1c12ee1eSDan Willemsen			t.Errorf("after setting %v to %v: Message.Has(%v) = %v, want %v", name, v, num, got, want)
560*1c12ee1eSDan Willemsen		}
561*1c12ee1eSDan Willemsen		if got, want := m.Get(fd), val; !valueEqual(got, want) {
562*1c12ee1eSDan Willemsen			t.Errorf("after setting %v: Message.Get(%v) = %v, want %v", name, num, formatValue(got), formatValue(want))
563*1c12ee1eSDan Willemsen		}
564*1c12ee1eSDan Willemsen	}
565*1c12ee1eSDan Willemsen}
566*1c12ee1eSDan Willemsen
567*1c12ee1eSDan Willemsen// testOneof tests the behavior of fields in a oneof.
568*1c12ee1eSDan Willemsenfunc testOneof(t testing.TB, m protoreflect.Message, od protoreflect.OneofDescriptor) {
569*1c12ee1eSDan Willemsen	for _, mutable := range []bool{false, true} {
570*1c12ee1eSDan Willemsen		for i := 0; i < od.Fields().Len(); i++ {
571*1c12ee1eSDan Willemsen			fda := od.Fields().Get(i)
572*1c12ee1eSDan Willemsen			if mutable {
573*1c12ee1eSDan Willemsen				// Set fields by requesting a mutable reference.
574*1c12ee1eSDan Willemsen				if !fda.IsMap() && !fda.IsList() && fda.Message() == nil {
575*1c12ee1eSDan Willemsen					continue
576*1c12ee1eSDan Willemsen				}
577*1c12ee1eSDan Willemsen				_ = m.Mutable(fda)
578*1c12ee1eSDan Willemsen			} else {
579*1c12ee1eSDan Willemsen				// Set fields explicitly.
580*1c12ee1eSDan Willemsen				m.Set(fda, newValue(m, fda, 1, nil))
581*1c12ee1eSDan Willemsen			}
582*1c12ee1eSDan Willemsen			if got, want := m.WhichOneof(od), fda; got != want {
583*1c12ee1eSDan Willemsen				t.Errorf("after setting oneof field %q:\nWhichOneof(%q) = %v, want %v", fda.FullName(), fda.Name(), got, want)
584*1c12ee1eSDan Willemsen			}
585*1c12ee1eSDan Willemsen			for j := 0; j < od.Fields().Len(); j++ {
586*1c12ee1eSDan Willemsen				fdb := od.Fields().Get(j)
587*1c12ee1eSDan Willemsen				if got, want := m.Has(fdb), i == j; got != want {
588*1c12ee1eSDan Willemsen					t.Errorf("after setting oneof field %q:\nGet(%q) = %v, want %v", fda.FullName(), fdb.FullName(), got, want)
589*1c12ee1eSDan Willemsen				}
590*1c12ee1eSDan Willemsen			}
591*1c12ee1eSDan Willemsen		}
592*1c12ee1eSDan Willemsen	}
593*1c12ee1eSDan Willemsen}
594*1c12ee1eSDan Willemsen
595*1c12ee1eSDan Willemsen// testUnknown tests the behavior of unknown fields.
596*1c12ee1eSDan Willemsenfunc testUnknown(t testing.TB, m protoreflect.Message) {
597*1c12ee1eSDan Willemsen	var b []byte
598*1c12ee1eSDan Willemsen	b = protowire.AppendTag(b, 1000, protowire.VarintType)
599*1c12ee1eSDan Willemsen	b = protowire.AppendVarint(b, 1001)
600*1c12ee1eSDan Willemsen	m.SetUnknown(protoreflect.RawFields(b))
601*1c12ee1eSDan Willemsen	if got, want := []byte(m.GetUnknown()), b; !bytes.Equal(got, want) {
602*1c12ee1eSDan Willemsen		t.Errorf("after setting unknown fields:\nGetUnknown() = %v, want %v", got, want)
603*1c12ee1eSDan Willemsen	}
604*1c12ee1eSDan Willemsen}
605*1c12ee1eSDan Willemsen
606*1c12ee1eSDan Willemsenfunc formatValue(v protoreflect.Value) string {
607*1c12ee1eSDan Willemsen	switch v := v.Interface().(type) {
608*1c12ee1eSDan Willemsen	case protoreflect.List:
609*1c12ee1eSDan Willemsen		var buf bytes.Buffer
610*1c12ee1eSDan Willemsen		buf.WriteString("list[")
611*1c12ee1eSDan Willemsen		for i := 0; i < v.Len(); i++ {
612*1c12ee1eSDan Willemsen			if i > 0 {
613*1c12ee1eSDan Willemsen				buf.WriteString(" ")
614*1c12ee1eSDan Willemsen			}
615*1c12ee1eSDan Willemsen			buf.WriteString(formatValue(v.Get(i)))
616*1c12ee1eSDan Willemsen		}
617*1c12ee1eSDan Willemsen		buf.WriteString("]")
618*1c12ee1eSDan Willemsen		return buf.String()
619*1c12ee1eSDan Willemsen	case protoreflect.Map:
620*1c12ee1eSDan Willemsen		var buf bytes.Buffer
621*1c12ee1eSDan Willemsen		buf.WriteString("map[")
622*1c12ee1eSDan Willemsen		var keys []protoreflect.MapKey
623*1c12ee1eSDan Willemsen		v.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
624*1c12ee1eSDan Willemsen			keys = append(keys, k)
625*1c12ee1eSDan Willemsen			return true
626*1c12ee1eSDan Willemsen		})
627*1c12ee1eSDan Willemsen		sort.Slice(keys, func(i, j int) bool {
628*1c12ee1eSDan Willemsen			return keys[i].String() < keys[j].String()
629*1c12ee1eSDan Willemsen		})
630*1c12ee1eSDan Willemsen		for i, k := range keys {
631*1c12ee1eSDan Willemsen			if i > 0 {
632*1c12ee1eSDan Willemsen				buf.WriteString(" ")
633*1c12ee1eSDan Willemsen			}
634*1c12ee1eSDan Willemsen			buf.WriteString(formatValue(k.Value()))
635*1c12ee1eSDan Willemsen			buf.WriteString(":")
636*1c12ee1eSDan Willemsen			buf.WriteString(formatValue(v.Get(k)))
637*1c12ee1eSDan Willemsen		}
638*1c12ee1eSDan Willemsen		buf.WriteString("]")
639*1c12ee1eSDan Willemsen		return buf.String()
640*1c12ee1eSDan Willemsen	case protoreflect.Message:
641*1c12ee1eSDan Willemsen		b, err := prototext.Marshal(v.Interface())
642*1c12ee1eSDan Willemsen		if err != nil {
643*1c12ee1eSDan Willemsen			return fmt.Sprintf("<%v>", err)
644*1c12ee1eSDan Willemsen		}
645*1c12ee1eSDan Willemsen		return fmt.Sprintf("%v{%s}", v.Descriptor().FullName(), b)
646*1c12ee1eSDan Willemsen	case string:
647*1c12ee1eSDan Willemsen		return fmt.Sprintf("%q", v)
648*1c12ee1eSDan Willemsen	default:
649*1c12ee1eSDan Willemsen		return fmt.Sprint(v)
650*1c12ee1eSDan Willemsen	}
651*1c12ee1eSDan Willemsen}
652*1c12ee1eSDan Willemsen
653*1c12ee1eSDan Willemsenfunc valueEqual(a, b protoreflect.Value) bool {
654*1c12ee1eSDan Willemsen	ai, bi := a.Interface(), b.Interface()
655*1c12ee1eSDan Willemsen	switch ai.(type) {
656*1c12ee1eSDan Willemsen	case protoreflect.Message:
657*1c12ee1eSDan Willemsen		return proto.Equal(
658*1c12ee1eSDan Willemsen			a.Message().Interface(),
659*1c12ee1eSDan Willemsen			b.Message().Interface(),
660*1c12ee1eSDan Willemsen		)
661*1c12ee1eSDan Willemsen	case protoreflect.List:
662*1c12ee1eSDan Willemsen		lista, listb := a.List(), b.List()
663*1c12ee1eSDan Willemsen		if lista.Len() != listb.Len() {
664*1c12ee1eSDan Willemsen			return false
665*1c12ee1eSDan Willemsen		}
666*1c12ee1eSDan Willemsen		for i := 0; i < lista.Len(); i++ {
667*1c12ee1eSDan Willemsen			if !valueEqual(lista.Get(i), listb.Get(i)) {
668*1c12ee1eSDan Willemsen				return false
669*1c12ee1eSDan Willemsen			}
670*1c12ee1eSDan Willemsen		}
671*1c12ee1eSDan Willemsen		return true
672*1c12ee1eSDan Willemsen	case protoreflect.Map:
673*1c12ee1eSDan Willemsen		mapa, mapb := a.Map(), b.Map()
674*1c12ee1eSDan Willemsen		if mapa.Len() != mapb.Len() {
675*1c12ee1eSDan Willemsen			return false
676*1c12ee1eSDan Willemsen		}
677*1c12ee1eSDan Willemsen		equal := true
678*1c12ee1eSDan Willemsen		mapa.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
679*1c12ee1eSDan Willemsen			if !valueEqual(v, mapb.Get(k)) {
680*1c12ee1eSDan Willemsen				equal = false
681*1c12ee1eSDan Willemsen				return false
682*1c12ee1eSDan Willemsen			}
683*1c12ee1eSDan Willemsen			return true
684*1c12ee1eSDan Willemsen		})
685*1c12ee1eSDan Willemsen		return equal
686*1c12ee1eSDan Willemsen	case []byte:
687*1c12ee1eSDan Willemsen		return bytes.Equal(a.Bytes(), b.Bytes())
688*1c12ee1eSDan Willemsen	case float32:
689*1c12ee1eSDan Willemsen		// NaNs are equal, but must be the same NaN.
690*1c12ee1eSDan Willemsen		return math.Float32bits(ai.(float32)) == math.Float32bits(bi.(float32))
691*1c12ee1eSDan Willemsen	case float64:
692*1c12ee1eSDan Willemsen		// NaNs are equal, but must be the same NaN.
693*1c12ee1eSDan Willemsen		return math.Float64bits(ai.(float64)) == math.Float64bits(bi.(float64))
694*1c12ee1eSDan Willemsen	default:
695*1c12ee1eSDan Willemsen		return ai == bi
696*1c12ee1eSDan Willemsen	}
697*1c12ee1eSDan Willemsen}
698*1c12ee1eSDan Willemsen
699*1c12ee1eSDan Willemsen// A seed is used to vary the content of a value.
700*1c12ee1eSDan Willemsen//
701*1c12ee1eSDan Willemsen// A seed of 0 is the zero value. Messages do not have a zero-value; a 0-seeded messages
702*1c12ee1eSDan Willemsen// is unpopulated.
703*1c12ee1eSDan Willemsen//
704*1c12ee1eSDan Willemsen// A seed of minVal or maxVal is the least or greatest value of the value type.
705*1c12ee1eSDan Willemsentype seed int
706*1c12ee1eSDan Willemsen
707*1c12ee1eSDan Willemsenconst (
708*1c12ee1eSDan Willemsen	minVal seed = -1
709*1c12ee1eSDan Willemsen	maxVal seed = -2
710*1c12ee1eSDan Willemsen)
711*1c12ee1eSDan Willemsen
712*1c12ee1eSDan Willemsen// newSeed creates new seed values from a base, for example to create seeds for the
713*1c12ee1eSDan Willemsen// elements in a list. If the input seed is minVal or maxVal, so is the output.
714*1c12ee1eSDan Willemsenfunc newSeed(n seed, adjust ...int) seed {
715*1c12ee1eSDan Willemsen	switch n {
716*1c12ee1eSDan Willemsen	case minVal, maxVal:
717*1c12ee1eSDan Willemsen		return n
718*1c12ee1eSDan Willemsen	}
719*1c12ee1eSDan Willemsen	for _, a := range adjust {
720*1c12ee1eSDan Willemsen		n = 10*n + seed(a)
721*1c12ee1eSDan Willemsen	}
722*1c12ee1eSDan Willemsen	return n
723*1c12ee1eSDan Willemsen}
724*1c12ee1eSDan Willemsen
725*1c12ee1eSDan Willemsen// newValue returns a new value assignable to a field.
726*1c12ee1eSDan Willemsen//
727*1c12ee1eSDan Willemsen// The stack parameter is used to avoid infinite recursion when populating circular
728*1c12ee1eSDan Willemsen// data structures.
729*1c12ee1eSDan Willemsenfunc newValue(m protoreflect.Message, fd protoreflect.FieldDescriptor, n seed, stack []protoreflect.MessageDescriptor) protoreflect.Value {
730*1c12ee1eSDan Willemsen	switch {
731*1c12ee1eSDan Willemsen	case fd.IsList():
732*1c12ee1eSDan Willemsen		if n == 0 {
733*1c12ee1eSDan Willemsen			return m.New().Mutable(fd)
734*1c12ee1eSDan Willemsen		}
735*1c12ee1eSDan Willemsen		list := m.NewField(fd).List()
736*1c12ee1eSDan Willemsen		list.Append(newListElement(fd, list, 0, stack))
737*1c12ee1eSDan Willemsen		list.Append(newListElement(fd, list, minVal, stack))
738*1c12ee1eSDan Willemsen		list.Append(newListElement(fd, list, maxVal, stack))
739*1c12ee1eSDan Willemsen		list.Append(newListElement(fd, list, n, stack))
740*1c12ee1eSDan Willemsen		return protoreflect.ValueOfList(list)
741*1c12ee1eSDan Willemsen	case fd.IsMap():
742*1c12ee1eSDan Willemsen		if n == 0 {
743*1c12ee1eSDan Willemsen			return m.New().Mutable(fd)
744*1c12ee1eSDan Willemsen		}
745*1c12ee1eSDan Willemsen		mapv := m.NewField(fd).Map()
746*1c12ee1eSDan Willemsen		mapv.Set(newMapKey(fd, 0), newMapValue(fd, mapv, 0, stack))
747*1c12ee1eSDan Willemsen		mapv.Set(newMapKey(fd, minVal), newMapValue(fd, mapv, minVal, stack))
748*1c12ee1eSDan Willemsen		mapv.Set(newMapKey(fd, maxVal), newMapValue(fd, mapv, maxVal, stack))
749*1c12ee1eSDan Willemsen		mapv.Set(newMapKey(fd, n), newMapValue(fd, mapv, newSeed(n, 0), stack))
750*1c12ee1eSDan Willemsen		return protoreflect.ValueOfMap(mapv)
751*1c12ee1eSDan Willemsen	case fd.Message() != nil:
752*1c12ee1eSDan Willemsen		return populateMessage(m.NewField(fd).Message(), n, stack)
753*1c12ee1eSDan Willemsen	default:
754*1c12ee1eSDan Willemsen		return newScalarValue(fd, n)
755*1c12ee1eSDan Willemsen	}
756*1c12ee1eSDan Willemsen}
757*1c12ee1eSDan Willemsen
758*1c12ee1eSDan Willemsenfunc newListElement(fd protoreflect.FieldDescriptor, list protoreflect.List, n seed, stack []protoreflect.MessageDescriptor) protoreflect.Value {
759*1c12ee1eSDan Willemsen	if fd.Message() == nil {
760*1c12ee1eSDan Willemsen		return newScalarValue(fd, n)
761*1c12ee1eSDan Willemsen	}
762*1c12ee1eSDan Willemsen	return populateMessage(list.NewElement().Message(), n, stack)
763*1c12ee1eSDan Willemsen}
764*1c12ee1eSDan Willemsen
765*1c12ee1eSDan Willemsenfunc newMapKey(fd protoreflect.FieldDescriptor, n seed) protoreflect.MapKey {
766*1c12ee1eSDan Willemsen	kd := fd.MapKey()
767*1c12ee1eSDan Willemsen	return newScalarValue(kd, n).MapKey()
768*1c12ee1eSDan Willemsen}
769*1c12ee1eSDan Willemsen
770*1c12ee1eSDan Willemsenfunc newMapValue(fd protoreflect.FieldDescriptor, mapv protoreflect.Map, n seed, stack []protoreflect.MessageDescriptor) protoreflect.Value {
771*1c12ee1eSDan Willemsen	vd := fd.MapValue()
772*1c12ee1eSDan Willemsen	if vd.Message() == nil {
773*1c12ee1eSDan Willemsen		return newScalarValue(vd, n)
774*1c12ee1eSDan Willemsen	}
775*1c12ee1eSDan Willemsen	return populateMessage(mapv.NewValue().Message(), n, stack)
776*1c12ee1eSDan Willemsen}
777*1c12ee1eSDan Willemsen
778*1c12ee1eSDan Willemsenfunc newScalarValue(fd protoreflect.FieldDescriptor, n seed) protoreflect.Value {
779*1c12ee1eSDan Willemsen	switch fd.Kind() {
780*1c12ee1eSDan Willemsen	case protoreflect.BoolKind:
781*1c12ee1eSDan Willemsen		return protoreflect.ValueOfBool(n != 0)
782*1c12ee1eSDan Willemsen	case protoreflect.EnumKind:
783*1c12ee1eSDan Willemsen		vals := fd.Enum().Values()
784*1c12ee1eSDan Willemsen		var i int
785*1c12ee1eSDan Willemsen		switch n {
786*1c12ee1eSDan Willemsen		case minVal:
787*1c12ee1eSDan Willemsen			i = 0
788*1c12ee1eSDan Willemsen		case maxVal:
789*1c12ee1eSDan Willemsen			i = vals.Len() - 1
790*1c12ee1eSDan Willemsen		default:
791*1c12ee1eSDan Willemsen			i = int(n) % vals.Len()
792*1c12ee1eSDan Willemsen		}
793*1c12ee1eSDan Willemsen		return protoreflect.ValueOfEnum(vals.Get(i).Number())
794*1c12ee1eSDan Willemsen	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
795*1c12ee1eSDan Willemsen		switch n {
796*1c12ee1eSDan Willemsen		case minVal:
797*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt32(math.MinInt32)
798*1c12ee1eSDan Willemsen		case maxVal:
799*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt32(math.MaxInt32)
800*1c12ee1eSDan Willemsen		default:
801*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt32(int32(n))
802*1c12ee1eSDan Willemsen		}
803*1c12ee1eSDan Willemsen	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
804*1c12ee1eSDan Willemsen		switch n {
805*1c12ee1eSDan Willemsen		case minVal:
806*1c12ee1eSDan Willemsen			// Only use 0 for the zero value.
807*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint32(1)
808*1c12ee1eSDan Willemsen		case maxVal:
809*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint32(math.MaxInt32)
810*1c12ee1eSDan Willemsen		default:
811*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint32(uint32(n))
812*1c12ee1eSDan Willemsen		}
813*1c12ee1eSDan Willemsen	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
814*1c12ee1eSDan Willemsen		switch n {
815*1c12ee1eSDan Willemsen		case minVal:
816*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt64(math.MinInt64)
817*1c12ee1eSDan Willemsen		case maxVal:
818*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt64(math.MaxInt64)
819*1c12ee1eSDan Willemsen		default:
820*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt64(int64(n))
821*1c12ee1eSDan Willemsen		}
822*1c12ee1eSDan Willemsen	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
823*1c12ee1eSDan Willemsen		switch n {
824*1c12ee1eSDan Willemsen		case minVal:
825*1c12ee1eSDan Willemsen			// Only use 0 for the zero value.
826*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint64(1)
827*1c12ee1eSDan Willemsen		case maxVal:
828*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint64(math.MaxInt64)
829*1c12ee1eSDan Willemsen		default:
830*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint64(uint64(n))
831*1c12ee1eSDan Willemsen		}
832*1c12ee1eSDan Willemsen	case protoreflect.FloatKind:
833*1c12ee1eSDan Willemsen		switch n {
834*1c12ee1eSDan Willemsen		case minVal:
835*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat32(math.SmallestNonzeroFloat32)
836*1c12ee1eSDan Willemsen		case maxVal:
837*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat32(math.MaxFloat32)
838*1c12ee1eSDan Willemsen		default:
839*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat32(1.5 * float32(n))
840*1c12ee1eSDan Willemsen		}
841*1c12ee1eSDan Willemsen	case protoreflect.DoubleKind:
842*1c12ee1eSDan Willemsen		switch n {
843*1c12ee1eSDan Willemsen		case minVal:
844*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(math.SmallestNonzeroFloat64)
845*1c12ee1eSDan Willemsen		case maxVal:
846*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(math.MaxFloat64)
847*1c12ee1eSDan Willemsen		default:
848*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(1.5 * float64(n))
849*1c12ee1eSDan Willemsen		}
850*1c12ee1eSDan Willemsen	case protoreflect.StringKind:
851*1c12ee1eSDan Willemsen		if n == 0 {
852*1c12ee1eSDan Willemsen			return protoreflect.ValueOfString("")
853*1c12ee1eSDan Willemsen		}
854*1c12ee1eSDan Willemsen		return protoreflect.ValueOfString(fmt.Sprintf("%d", n))
855*1c12ee1eSDan Willemsen	case protoreflect.BytesKind:
856*1c12ee1eSDan Willemsen		if n == 0 {
857*1c12ee1eSDan Willemsen			return protoreflect.ValueOfBytes(nil)
858*1c12ee1eSDan Willemsen		}
859*1c12ee1eSDan Willemsen		return protoreflect.ValueOfBytes([]byte{byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n)})
860*1c12ee1eSDan Willemsen	}
861*1c12ee1eSDan Willemsen	panic("unhandled kind")
862*1c12ee1eSDan Willemsen}
863*1c12ee1eSDan Willemsen
864*1c12ee1eSDan Willemsenfunc populateMessage(m protoreflect.Message, n seed, stack []protoreflect.MessageDescriptor) protoreflect.Value {
865*1c12ee1eSDan Willemsen	if n == 0 {
866*1c12ee1eSDan Willemsen		return protoreflect.ValueOfMessage(m)
867*1c12ee1eSDan Willemsen	}
868*1c12ee1eSDan Willemsen	md := m.Descriptor()
869*1c12ee1eSDan Willemsen	for _, x := range stack {
870*1c12ee1eSDan Willemsen		if md == x {
871*1c12ee1eSDan Willemsen			return protoreflect.ValueOfMessage(m)
872*1c12ee1eSDan Willemsen		}
873*1c12ee1eSDan Willemsen	}
874*1c12ee1eSDan Willemsen	stack = append(stack, md)
875*1c12ee1eSDan Willemsen	for i := 0; i < md.Fields().Len(); i++ {
876*1c12ee1eSDan Willemsen		fd := md.Fields().Get(i)
877*1c12ee1eSDan Willemsen		if fd.IsWeak() {
878*1c12ee1eSDan Willemsen			continue
879*1c12ee1eSDan Willemsen		}
880*1c12ee1eSDan Willemsen		m.Set(fd, newValue(m, fd, newSeed(n, i), stack))
881*1c12ee1eSDan Willemsen	}
882*1c12ee1eSDan Willemsen	return protoreflect.ValueOfMessage(m)
883*1c12ee1eSDan Willemsen}
884*1c12ee1eSDan Willemsen
885*1c12ee1eSDan Willemsenfunc panics(f func()) (didPanic bool) {
886*1c12ee1eSDan Willemsen	defer func() {
887*1c12ee1eSDan Willemsen		if err := recover(); err != nil {
888*1c12ee1eSDan Willemsen			didPanic = true
889*1c12ee1eSDan Willemsen		}
890*1c12ee1eSDan Willemsen	}()
891*1c12ee1eSDan Willemsen	f()
892*1c12ee1eSDan Willemsen	return false
893*1c12ee1eSDan Willemsen}
894