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