xref: /aosp_15_r20/external/golang-protobuf/internal/testprotos/nullable/nullable_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2021 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 Willemsenpackage nullable
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"reflect"
9*1c12ee1eSDan Willemsen	"testing"
10*1c12ee1eSDan Willemsen
11*1c12ee1eSDan Willemsen	"github.com/google/go-cmp/cmp"
12*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/proto"
13*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/runtime/protoimpl"
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/testing/protocmp"
16*1c12ee1eSDan Willemsen)
17*1c12ee1eSDan Willemsen
18*1c12ee1eSDan Willemsenfunc Test(t *testing.T) {
19*1c12ee1eSDan Willemsen	for _, mt := range []protoreflect.MessageType{
20*1c12ee1eSDan Willemsen		protoimpl.X.ProtoMessageV2Of((*Proto2)(nil)).ProtoReflect().Type(),
21*1c12ee1eSDan Willemsen		protoimpl.X.ProtoMessageV2Of((*Proto3)(nil)).ProtoReflect().Type(),
22*1c12ee1eSDan Willemsen	} {
23*1c12ee1eSDan Willemsen		t.Run(string(mt.Descriptor().FullName()), func(t *testing.T) {
24*1c12ee1eSDan Willemsen			testEmptyMessage(t, mt.Zero(), false)
25*1c12ee1eSDan Willemsen			testEmptyMessage(t, mt.New(), true)
26*1c12ee1eSDan Willemsen			//testMethods(t, mt)
27*1c12ee1eSDan Willemsen		})
28*1c12ee1eSDan Willemsen	}
29*1c12ee1eSDan Willemsen}
30*1c12ee1eSDan Willemsen
31*1c12ee1eSDan Willemsenvar methodTestProtos = []protoreflect.MessageType{
32*1c12ee1eSDan Willemsen	protoimpl.X.ProtoMessageV2Of((*Methods)(nil)).ProtoReflect().Type(),
33*1c12ee1eSDan Willemsen}
34*1c12ee1eSDan Willemsen
35*1c12ee1eSDan Willemsenfunc TestMethods(t *testing.T) {
36*1c12ee1eSDan Willemsen	for _, mt := range methodTestProtos {
37*1c12ee1eSDan Willemsen		t.Run(string(mt.Descriptor().FullName()), func(t *testing.T) {
38*1c12ee1eSDan Willemsen			testMethods(t, mt)
39*1c12ee1eSDan Willemsen		})
40*1c12ee1eSDan Willemsen	}
41*1c12ee1eSDan Willemsen}
42*1c12ee1eSDan Willemsen
43*1c12ee1eSDan Willemsenfunc testMethods(t *testing.T, mt protoreflect.MessageType) {
44*1c12ee1eSDan Willemsen	m1 := mt.New()
45*1c12ee1eSDan Willemsen	populated := testPopulateMessage(t, m1, 2)
46*1c12ee1eSDan Willemsen	b, err := proto.Marshal(m1.Interface())
47*1c12ee1eSDan Willemsen	if err != nil {
48*1c12ee1eSDan Willemsen		t.Errorf("proto.Marshal error: %v", err)
49*1c12ee1eSDan Willemsen	}
50*1c12ee1eSDan Willemsen	if populated && len(b) == 0 {
51*1c12ee1eSDan Willemsen		t.Errorf("len(proto.Marshal) = 0, want >0")
52*1c12ee1eSDan Willemsen	}
53*1c12ee1eSDan Willemsen	m2 := mt.New()
54*1c12ee1eSDan Willemsen	if err := proto.Unmarshal(b, m2.Interface()); err != nil {
55*1c12ee1eSDan Willemsen		t.Errorf("proto.Unmarshal error: %v", err)
56*1c12ee1eSDan Willemsen	}
57*1c12ee1eSDan Willemsen	if diff := cmp.Diff(m1.Interface(), m2.Interface(), protocmp.Transform()); diff != "" {
58*1c12ee1eSDan Willemsen		t.Errorf("message mismatch:\n%v", diff)
59*1c12ee1eSDan Willemsen	}
60*1c12ee1eSDan Willemsen	proto.Reset(m2.Interface())
61*1c12ee1eSDan Willemsen	testEmptyMessage(t, m2, true)
62*1c12ee1eSDan Willemsen	proto.Merge(m2.Interface(), m1.Interface())
63*1c12ee1eSDan Willemsen	if diff := cmp.Diff(m1.Interface(), m2.Interface(), protocmp.Transform()); diff != "" {
64*1c12ee1eSDan Willemsen		t.Errorf("message mismatch:\n%v", diff)
65*1c12ee1eSDan Willemsen	}
66*1c12ee1eSDan Willemsen	proto.Merge(mt.New().Interface(), mt.Zero().Interface())
67*1c12ee1eSDan Willemsen}
68*1c12ee1eSDan Willemsen
69*1c12ee1eSDan Willemsenfunc testEmptyMessage(t *testing.T, m protoreflect.Message, wantValid bool) {
70*1c12ee1eSDan Willemsen	numFields := func(m protoreflect.Message) (n int) {
71*1c12ee1eSDan Willemsen		m.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool {
72*1c12ee1eSDan Willemsen			n++
73*1c12ee1eSDan Willemsen			return true
74*1c12ee1eSDan Willemsen		})
75*1c12ee1eSDan Willemsen		return n
76*1c12ee1eSDan Willemsen	}
77*1c12ee1eSDan Willemsen
78*1c12ee1eSDan Willemsen	md := m.Descriptor()
79*1c12ee1eSDan Willemsen	if gotValid := m.IsValid(); gotValid != wantValid {
80*1c12ee1eSDan Willemsen		t.Errorf("%v.IsValid = %v, want %v", md.FullName(), gotValid, wantValid)
81*1c12ee1eSDan Willemsen	}
82*1c12ee1eSDan Willemsen	m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
83*1c12ee1eSDan Willemsen		t.Errorf("%v.Range iterated over field %v, want no iteration", md.FullName(), fd.Name())
84*1c12ee1eSDan Willemsen		return true
85*1c12ee1eSDan Willemsen	})
86*1c12ee1eSDan Willemsen	fds := md.Fields()
87*1c12ee1eSDan Willemsen	for i := 0; i < fds.Len(); i++ {
88*1c12ee1eSDan Willemsen		fd := fds.Get(i)
89*1c12ee1eSDan Willemsen		if m.Has(fd) {
90*1c12ee1eSDan Willemsen			t.Errorf("%v.Has(%v) = true, want false", md.FullName(), fd.Name())
91*1c12ee1eSDan Willemsen		}
92*1c12ee1eSDan Willemsen		v := m.Get(fd)
93*1c12ee1eSDan Willemsen		switch {
94*1c12ee1eSDan Willemsen		case fd.IsList():
95*1c12ee1eSDan Willemsen			if n := v.List().Len(); n > 0 {
96*1c12ee1eSDan Willemsen				t.Errorf("%v.Get(%v).List().Len() = %v, want 0", md.FullName(), fd.Name(), n)
97*1c12ee1eSDan Willemsen			}
98*1c12ee1eSDan Willemsen			ls := m.NewField(fd).List()
99*1c12ee1eSDan Willemsen			if fd.Message() != nil {
100*1c12ee1eSDan Willemsen				if n := numFields(ls.NewElement().Message()); n > 0 {
101*1c12ee1eSDan Willemsen					t.Errorf("%v.NewField(%v).List().NewElement().Message().Len() = %v, want 0", md.FullName(), fd.Name(), n)
102*1c12ee1eSDan Willemsen				}
103*1c12ee1eSDan Willemsen			}
104*1c12ee1eSDan Willemsen		case fd.IsMap():
105*1c12ee1eSDan Willemsen			if n := v.Map().Len(); n > 0 {
106*1c12ee1eSDan Willemsen				t.Errorf("%v.Get(%v).Map().Len() = %v, want 0", md.FullName(), fd.Name(), n)
107*1c12ee1eSDan Willemsen			}
108*1c12ee1eSDan Willemsen			ms := m.NewField(fd).Map()
109*1c12ee1eSDan Willemsen			if fd.MapValue().Message() != nil {
110*1c12ee1eSDan Willemsen				if n := numFields(ms.NewValue().Message()); n > 0 {
111*1c12ee1eSDan Willemsen					t.Errorf("%v.NewField(%v).Map().NewValue().Message().Len() = %v, want 0", md.FullName(), fd.Name(), n)
112*1c12ee1eSDan Willemsen				}
113*1c12ee1eSDan Willemsen			}
114*1c12ee1eSDan Willemsen		case fd.Message() != nil:
115*1c12ee1eSDan Willemsen			if n := numFields(v.Message()); n > 0 {
116*1c12ee1eSDan Willemsen				t.Errorf("%v.Get(%v).Message().Len() = %v, want 0", md.FullName(), fd.Name(), n)
117*1c12ee1eSDan Willemsen			}
118*1c12ee1eSDan Willemsen			if n := numFields(m.NewField(fd).Message()); n > 0 {
119*1c12ee1eSDan Willemsen				t.Errorf("%v.NewField(%v).Message().Len() = %v, want 0", md.FullName(), fd.Name(), n)
120*1c12ee1eSDan Willemsen			}
121*1c12ee1eSDan Willemsen		default:
122*1c12ee1eSDan Willemsen			if !reflect.DeepEqual(v.Interface(), fd.Default().Interface()) {
123*1c12ee1eSDan Willemsen				t.Errorf("%v.Get(%v) = %v, want %v", md.FullName(), fd.Name(), v, fd.Default())
124*1c12ee1eSDan Willemsen			}
125*1c12ee1eSDan Willemsen			m.NewField(fd) // should not panic
126*1c12ee1eSDan Willemsen		}
127*1c12ee1eSDan Willemsen	}
128*1c12ee1eSDan Willemsen	ods := md.Oneofs()
129*1c12ee1eSDan Willemsen	for i := 0; i < ods.Len(); i++ {
130*1c12ee1eSDan Willemsen		od := ods.Get(i)
131*1c12ee1eSDan Willemsen		if fd := m.WhichOneof(od); fd != nil {
132*1c12ee1eSDan Willemsen			t.Errorf("%v.WhichOneof(%v) = %v, want nil", md.FullName(), od.Name(), fd.Name())
133*1c12ee1eSDan Willemsen		}
134*1c12ee1eSDan Willemsen	}
135*1c12ee1eSDan Willemsen	if b := m.GetUnknown(); b != nil {
136*1c12ee1eSDan Willemsen		t.Errorf("%v.GetUnknown() = %v, want nil", md.FullName(), b)
137*1c12ee1eSDan Willemsen	}
138*1c12ee1eSDan Willemsen}
139*1c12ee1eSDan Willemsen
140*1c12ee1eSDan Willemsenfunc testPopulateMessage(t *testing.T, m protoreflect.Message, depth int) bool {
141*1c12ee1eSDan Willemsen	if depth == 0 {
142*1c12ee1eSDan Willemsen		return false
143*1c12ee1eSDan Willemsen	}
144*1c12ee1eSDan Willemsen	md := m.Descriptor()
145*1c12ee1eSDan Willemsen	fds := md.Fields()
146*1c12ee1eSDan Willemsen	var populatedMessage bool
147*1c12ee1eSDan Willemsen	for i := 0; i < fds.Len(); i++ {
148*1c12ee1eSDan Willemsen		populatedField := true
149*1c12ee1eSDan Willemsen		fd := fds.Get(i)
150*1c12ee1eSDan Willemsen		m.Clear(fd) // should not panic
151*1c12ee1eSDan Willemsen		switch {
152*1c12ee1eSDan Willemsen		case fd.IsList():
153*1c12ee1eSDan Willemsen			ls := m.Mutable(fd).List()
154*1c12ee1eSDan Willemsen			if fd.Message() == nil {
155*1c12ee1eSDan Willemsen				ls.Append(scalarValue(fd.Kind()))
156*1c12ee1eSDan Willemsen			} else {
157*1c12ee1eSDan Willemsen				populatedField = testPopulateMessage(t, ls.AppendMutable().Message(), depth-1)
158*1c12ee1eSDan Willemsen			}
159*1c12ee1eSDan Willemsen		case fd.IsMap():
160*1c12ee1eSDan Willemsen			ms := m.Mutable(fd).Map()
161*1c12ee1eSDan Willemsen			if fd.MapValue().Message() == nil {
162*1c12ee1eSDan Willemsen				ms.Set(
163*1c12ee1eSDan Willemsen					scalarValue(fd.MapKey().Kind()).MapKey(),
164*1c12ee1eSDan Willemsen					scalarValue(fd.MapValue().Kind()),
165*1c12ee1eSDan Willemsen				)
166*1c12ee1eSDan Willemsen			} else {
167*1c12ee1eSDan Willemsen				// NOTE: Map.Mutable does not work with non-nullable fields.
168*1c12ee1eSDan Willemsen				m2 := ms.NewValue().Message()
169*1c12ee1eSDan Willemsen				populatedField = testPopulateMessage(t, m2, depth-1)
170*1c12ee1eSDan Willemsen				ms.Set(
171*1c12ee1eSDan Willemsen					scalarValue(fd.MapKey().Kind()).MapKey(),
172*1c12ee1eSDan Willemsen					protoreflect.ValueOfMessage(m2),
173*1c12ee1eSDan Willemsen				)
174*1c12ee1eSDan Willemsen			}
175*1c12ee1eSDan Willemsen		case fd.Message() != nil:
176*1c12ee1eSDan Willemsen			populatedField = testPopulateMessage(t, m.Mutable(fd).Message(), depth-1)
177*1c12ee1eSDan Willemsen		default:
178*1c12ee1eSDan Willemsen			m.Set(fd, scalarValue(fd.Kind()))
179*1c12ee1eSDan Willemsen		}
180*1c12ee1eSDan Willemsen		if populatedField && !m.Has(fd) {
181*1c12ee1eSDan Willemsen			t.Errorf("%v.Has(%v) = false, want true", md.FullName(), fd.Name())
182*1c12ee1eSDan Willemsen		}
183*1c12ee1eSDan Willemsen		populatedMessage = populatedMessage || populatedField
184*1c12ee1eSDan Willemsen	}
185*1c12ee1eSDan Willemsen	m.SetUnknown(m.GetUnknown()) // should not panic
186*1c12ee1eSDan Willemsen	return populatedMessage
187*1c12ee1eSDan Willemsen}
188*1c12ee1eSDan Willemsen
189*1c12ee1eSDan Willemsenfunc scalarValue(k protoreflect.Kind) protoreflect.Value {
190*1c12ee1eSDan Willemsen	switch k {
191*1c12ee1eSDan Willemsen	case protoreflect.BoolKind:
192*1c12ee1eSDan Willemsen		return protoreflect.ValueOfBool(true)
193*1c12ee1eSDan Willemsen	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
194*1c12ee1eSDan Willemsen		return protoreflect.ValueOfInt32(-32)
195*1c12ee1eSDan Willemsen	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
196*1c12ee1eSDan Willemsen		return protoreflect.ValueOfInt64(-64)
197*1c12ee1eSDan Willemsen	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
198*1c12ee1eSDan Willemsen		return protoreflect.ValueOfUint32(32)
199*1c12ee1eSDan Willemsen	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
200*1c12ee1eSDan Willemsen		return protoreflect.ValueOfUint64(64)
201*1c12ee1eSDan Willemsen	case protoreflect.FloatKind:
202*1c12ee1eSDan Willemsen		return protoreflect.ValueOfFloat32(32.32)
203*1c12ee1eSDan Willemsen	case protoreflect.DoubleKind:
204*1c12ee1eSDan Willemsen		return protoreflect.ValueOfFloat64(64.64)
205*1c12ee1eSDan Willemsen	case protoreflect.StringKind:
206*1c12ee1eSDan Willemsen		return protoreflect.ValueOfString(string("string"))
207*1c12ee1eSDan Willemsen	case protoreflect.BytesKind:
208*1c12ee1eSDan Willemsen		return protoreflect.ValueOfBytes([]byte("bytes"))
209*1c12ee1eSDan Willemsen	case protoreflect.EnumKind:
210*1c12ee1eSDan Willemsen		return protoreflect.ValueOfEnum(1)
211*1c12ee1eSDan Willemsen	default:
212*1c12ee1eSDan Willemsen		panic("unknown kind: " + k.String())
213*1c12ee1eSDan Willemsen	}
214*1c12ee1eSDan Willemsen}
215