xref: /aosp_15_r20/external/golang-protobuf/reflect/protoreflect/value_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2018 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 protoreflect
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"bytes"
9*1c12ee1eSDan Willemsen	"math"
10*1c12ee1eSDan Willemsen	"reflect"
11*1c12ee1eSDan Willemsen	"testing"
12*1c12ee1eSDan Willemsen)
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsenvar (
15*1c12ee1eSDan Willemsen	fakeMessage = new(struct{ Message })
16*1c12ee1eSDan Willemsen	fakeList    = new(struct{ List })
17*1c12ee1eSDan Willemsen	fakeMap     = new(struct{ Map })
18*1c12ee1eSDan Willemsen)
19*1c12ee1eSDan Willemsen
20*1c12ee1eSDan Willemsenfunc TestValue(t *testing.T) {
21*1c12ee1eSDan Willemsen
22*1c12ee1eSDan Willemsen	tests := []struct {
23*1c12ee1eSDan Willemsen		in   Value
24*1c12ee1eSDan Willemsen		want interface{}
25*1c12ee1eSDan Willemsen	}{
26*1c12ee1eSDan Willemsen		{in: Value{}},
27*1c12ee1eSDan Willemsen		{in: ValueOf(nil)},
28*1c12ee1eSDan Willemsen		{in: ValueOf(true), want: true},
29*1c12ee1eSDan Willemsen		{in: ValueOf(int32(math.MaxInt32)), want: int32(math.MaxInt32)},
30*1c12ee1eSDan Willemsen		{in: ValueOf(int64(math.MaxInt64)), want: int64(math.MaxInt64)},
31*1c12ee1eSDan Willemsen		{in: ValueOf(uint32(math.MaxUint32)), want: uint32(math.MaxUint32)},
32*1c12ee1eSDan Willemsen		{in: ValueOf(uint64(math.MaxUint64)), want: uint64(math.MaxUint64)},
33*1c12ee1eSDan Willemsen		{in: ValueOf(float32(math.MaxFloat32)), want: float32(math.MaxFloat32)},
34*1c12ee1eSDan Willemsen		{in: ValueOf(float64(math.MaxFloat64)), want: float64(math.MaxFloat64)},
35*1c12ee1eSDan Willemsen		{in: ValueOf(string("hello")), want: string("hello")},
36*1c12ee1eSDan Willemsen		{in: ValueOf([]byte("hello")), want: []byte("hello")},
37*1c12ee1eSDan Willemsen		{in: ValueOf(fakeMessage), want: fakeMessage},
38*1c12ee1eSDan Willemsen		{in: ValueOf(fakeList), want: fakeList},
39*1c12ee1eSDan Willemsen		{in: ValueOf(fakeMap), want: fakeMap},
40*1c12ee1eSDan Willemsen	}
41*1c12ee1eSDan Willemsen
42*1c12ee1eSDan Willemsen	for _, tt := range tests {
43*1c12ee1eSDan Willemsen		got := tt.in.Interface()
44*1c12ee1eSDan Willemsen		if !reflect.DeepEqual(got, tt.want) {
45*1c12ee1eSDan Willemsen			t.Errorf("Value(%v).Interface() = %v, want %v", tt.in, got, tt.want)
46*1c12ee1eSDan Willemsen		}
47*1c12ee1eSDan Willemsen
48*1c12ee1eSDan Willemsen		if got := tt.in.IsValid(); got != (tt.want != nil) {
49*1c12ee1eSDan Willemsen			t.Errorf("Value(%v).IsValid() = %v, want %v", tt.in, got, tt.want != nil)
50*1c12ee1eSDan Willemsen		}
51*1c12ee1eSDan Willemsen		switch want := tt.want.(type) {
52*1c12ee1eSDan Willemsen		case int32:
53*1c12ee1eSDan Willemsen			if got := tt.in.Int(); got != int64(want) {
54*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Int() = %v, want %v", tt.in, got, tt.want)
55*1c12ee1eSDan Willemsen			}
56*1c12ee1eSDan Willemsen		case int64:
57*1c12ee1eSDan Willemsen			if got := tt.in.Int(); got != int64(want) {
58*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Int() = %v, want %v", tt.in, got, tt.want)
59*1c12ee1eSDan Willemsen			}
60*1c12ee1eSDan Willemsen		case uint32:
61*1c12ee1eSDan Willemsen			if got := tt.in.Uint(); got != uint64(want) {
62*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Uint() = %v, want %v", tt.in, got, tt.want)
63*1c12ee1eSDan Willemsen			}
64*1c12ee1eSDan Willemsen		case uint64:
65*1c12ee1eSDan Willemsen			if got := tt.in.Uint(); got != uint64(want) {
66*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Uint() = %v, want %v", tt.in, got, tt.want)
67*1c12ee1eSDan Willemsen			}
68*1c12ee1eSDan Willemsen		case float32:
69*1c12ee1eSDan Willemsen			if got := tt.in.Float(); got != float64(want) {
70*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Float() = %v, want %v", tt.in, got, tt.want)
71*1c12ee1eSDan Willemsen			}
72*1c12ee1eSDan Willemsen		case float64:
73*1c12ee1eSDan Willemsen			if got := tt.in.Float(); got != float64(want) {
74*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Float() = %v, want %v", tt.in, got, tt.want)
75*1c12ee1eSDan Willemsen			}
76*1c12ee1eSDan Willemsen		case string:
77*1c12ee1eSDan Willemsen			if got := tt.in.String(); got != string(want) {
78*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).String() = %v, want %v", tt.in, got, tt.want)
79*1c12ee1eSDan Willemsen			}
80*1c12ee1eSDan Willemsen		case []byte:
81*1c12ee1eSDan Willemsen			if got := tt.in.Bytes(); !bytes.Equal(got, want) {
82*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Bytes() = %v, want %v", tt.in, got, tt.want)
83*1c12ee1eSDan Willemsen			}
84*1c12ee1eSDan Willemsen		case EnumNumber:
85*1c12ee1eSDan Willemsen			if got := tt.in.Enum(); got != want {
86*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Enum() = %v, want %v", tt.in, got, tt.want)
87*1c12ee1eSDan Willemsen			}
88*1c12ee1eSDan Willemsen		case Message:
89*1c12ee1eSDan Willemsen			if got := tt.in.Message(); got != want {
90*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Message() = %v, want %v", tt.in, got, tt.want)
91*1c12ee1eSDan Willemsen			}
92*1c12ee1eSDan Willemsen		case List:
93*1c12ee1eSDan Willemsen			if got := tt.in.List(); got != want {
94*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).List() = %v, want %v", tt.in, got, tt.want)
95*1c12ee1eSDan Willemsen			}
96*1c12ee1eSDan Willemsen		case Map:
97*1c12ee1eSDan Willemsen			if got := tt.in.Map(); got != want {
98*1c12ee1eSDan Willemsen				t.Errorf("Value(%v).Map() = %v, want %v", tt.in, got, tt.want)
99*1c12ee1eSDan Willemsen			}
100*1c12ee1eSDan Willemsen		}
101*1c12ee1eSDan Willemsen	}
102*1c12ee1eSDan Willemsen}
103*1c12ee1eSDan Willemsen
104*1c12ee1eSDan Willemsenfunc TestValueEqual(t *testing.T) {
105*1c12ee1eSDan Willemsen	tests := []struct {
106*1c12ee1eSDan Willemsen		x, y Value
107*1c12ee1eSDan Willemsen		want bool
108*1c12ee1eSDan Willemsen	}{
109*1c12ee1eSDan Willemsen		{Value{}, Value{}, true},
110*1c12ee1eSDan Willemsen		{Value{}, ValueOfBool(true), false},
111*1c12ee1eSDan Willemsen		{ValueOfBool(true), ValueOfBool(true), true},
112*1c12ee1eSDan Willemsen		{ValueOfBool(true), ValueOfBool(false), false},
113*1c12ee1eSDan Willemsen		{ValueOfBool(false), ValueOfInt32(0), false},
114*1c12ee1eSDan Willemsen		{ValueOfInt32(0), ValueOfInt32(0), true},
115*1c12ee1eSDan Willemsen		{ValueOfInt32(0), ValueOfInt32(1), false},
116*1c12ee1eSDan Willemsen		{ValueOfInt32(0), ValueOfInt64(0), false},
117*1c12ee1eSDan Willemsen		{ValueOfInt64(123), ValueOfInt64(123), true},
118*1c12ee1eSDan Willemsen		{ValueOfFloat64(0), ValueOfFloat64(0), true},
119*1c12ee1eSDan Willemsen		{ValueOfFloat64(math.NaN()), ValueOfFloat64(math.NaN()), true},
120*1c12ee1eSDan Willemsen		{ValueOfFloat64(math.NaN()), ValueOfFloat64(0), false},
121*1c12ee1eSDan Willemsen		{ValueOfFloat64(math.Inf(1)), ValueOfFloat64(math.Inf(1)), true},
122*1c12ee1eSDan Willemsen		{ValueOfFloat64(math.Inf(-1)), ValueOfFloat64(math.Inf(1)), false},
123*1c12ee1eSDan Willemsen		{ValueOfBytes(nil), ValueOfBytes(nil), true},
124*1c12ee1eSDan Willemsen		{ValueOfBytes(nil), ValueOfBytes([]byte{}), true},
125*1c12ee1eSDan Willemsen		{ValueOfBytes(nil), ValueOfBytes([]byte{1}), false},
126*1c12ee1eSDan Willemsen		{ValueOfEnum(0), ValueOfEnum(0), true},
127*1c12ee1eSDan Willemsen		{ValueOfEnum(0), ValueOfEnum(1), false},
128*1c12ee1eSDan Willemsen		{ValueOfBool(false), ValueOfMessage(fakeMessage), false},
129*1c12ee1eSDan Willemsen		{ValueOfMessage(fakeMessage), ValueOfList(fakeList), false},
130*1c12ee1eSDan Willemsen		{ValueOfList(fakeList), ValueOfMap(fakeMap), false},
131*1c12ee1eSDan Willemsen		{ValueOfMap(fakeMap), ValueOfMessage(fakeMessage), false},
132*1c12ee1eSDan Willemsen
133*1c12ee1eSDan Willemsen		// Composite types are not tested here.
134*1c12ee1eSDan Willemsen		// See proto.TestEqual.
135*1c12ee1eSDan Willemsen	}
136*1c12ee1eSDan Willemsen
137*1c12ee1eSDan Willemsen	for _, tt := range tests {
138*1c12ee1eSDan Willemsen		got := tt.x.Equal(tt.y)
139*1c12ee1eSDan Willemsen		if got != tt.want {
140*1c12ee1eSDan Willemsen			t.Errorf("(%v).Equal(%v) = %v, want %v", tt.x, tt.y, got, tt.want)
141*1c12ee1eSDan Willemsen		}
142*1c12ee1eSDan Willemsen	}
143*1c12ee1eSDan Willemsen}
144*1c12ee1eSDan Willemsen
145*1c12ee1eSDan Willemsenfunc BenchmarkValue(b *testing.B) {
146*1c12ee1eSDan Willemsen	const testdata = "The quick brown fox jumped over the lazy dog."
147*1c12ee1eSDan Willemsen	var sink1 string
148*1c12ee1eSDan Willemsen	var sink2 Value
149*1c12ee1eSDan Willemsen	var sink3 interface{}
150*1c12ee1eSDan Willemsen
151*1c12ee1eSDan Willemsen	// Baseline measures the time to store a string into a native variable.
152*1c12ee1eSDan Willemsen	b.Run("Baseline", func(b *testing.B) {
153*1c12ee1eSDan Willemsen		b.ReportAllocs()
154*1c12ee1eSDan Willemsen		for i := 0; i < b.N; i++ {
155*1c12ee1eSDan Willemsen			sink1 = testdata[:len(testdata)%(i+1)]
156*1c12ee1eSDan Willemsen		}
157*1c12ee1eSDan Willemsen	})
158*1c12ee1eSDan Willemsen
159*1c12ee1eSDan Willemsen	// Inline measures the time to store a string into a Value,
160*1c12ee1eSDan Willemsen	// assuming that the compiler could inline the ValueOf function call.
161*1c12ee1eSDan Willemsen	b.Run("Inline", func(b *testing.B) {
162*1c12ee1eSDan Willemsen		b.ReportAllocs()
163*1c12ee1eSDan Willemsen		for i := 0; i < b.N; i++ {
164*1c12ee1eSDan Willemsen			sink2 = valueOfString(testdata[:len(testdata)%(i+1)])
165*1c12ee1eSDan Willemsen		}
166*1c12ee1eSDan Willemsen	})
167*1c12ee1eSDan Willemsen
168*1c12ee1eSDan Willemsen	// Value measures the time to store a string into a Value using the general
169*1c12ee1eSDan Willemsen	// ValueOf function call. This should be identical to Inline.
170*1c12ee1eSDan Willemsen	//
171*1c12ee1eSDan Willemsen	// NOTE: As of Go1.11, this is not as efficient as Inline due to the lack
172*1c12ee1eSDan Willemsen	// of some compiler optimizations:
173*1c12ee1eSDan Willemsen	//	https://golang.org/issue/22310
174*1c12ee1eSDan Willemsen	//	https://golang.org/issue/25189
175*1c12ee1eSDan Willemsen	b.Run("Value", func(b *testing.B) {
176*1c12ee1eSDan Willemsen		b.ReportAllocs()
177*1c12ee1eSDan Willemsen		for i := 0; i < b.N; i++ {
178*1c12ee1eSDan Willemsen			sink2 = ValueOf(string(testdata[:len(testdata)%(i+1)]))
179*1c12ee1eSDan Willemsen		}
180*1c12ee1eSDan Willemsen	})
181*1c12ee1eSDan Willemsen
182*1c12ee1eSDan Willemsen	// Interface measures the time to store a string into an interface.
183*1c12ee1eSDan Willemsen	b.Run("Interface", func(b *testing.B) {
184*1c12ee1eSDan Willemsen		b.ReportAllocs()
185*1c12ee1eSDan Willemsen		for i := 0; i < b.N; i++ {
186*1c12ee1eSDan Willemsen			sink3 = string(testdata[:len(testdata)%(i+1)])
187*1c12ee1eSDan Willemsen		}
188*1c12ee1eSDan Willemsen	})
189*1c12ee1eSDan Willemsen
190*1c12ee1eSDan Willemsen	_, _, _ = sink1, sink2, sink3
191*1c12ee1eSDan Willemsen}
192