message_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package impl
  5. import (
  6. "reflect"
  7. "testing"
  8. "github.com/google/go-cmp/cmp"
  9. pref "github.com/golang/protobuf/v2/reflect/protoreflect"
  10. ptype "github.com/golang/protobuf/v2/reflect/prototype"
  11. )
  12. type (
  13. MyBool bool
  14. MyInt32 int32
  15. MyInt64 int64
  16. MyUint32 uint32
  17. MyUint64 uint64
  18. MyFloat32 float32
  19. MyFloat64 float64
  20. MyString string
  21. MyBytes []byte
  22. )
  23. type ScalarProto2 struct {
  24. Bool *bool `protobuf:"1"`
  25. Int32 *int32 `protobuf:"2"`
  26. Int64 *int64 `protobuf:"3"`
  27. Uint32 *uint32 `protobuf:"4"`
  28. Uint64 *uint64 `protobuf:"5"`
  29. Float32 *float32 `protobuf:"6"`
  30. Float64 *float64 `protobuf:"7"`
  31. String *string `protobuf:"8"`
  32. StringA []byte `protobuf:"9"`
  33. Bytes []byte `protobuf:"10"`
  34. BytesA *string `protobuf:"11"`
  35. MyBool *MyBool `protobuf:"12"`
  36. MyInt32 *MyInt32 `protobuf:"13"`
  37. MyInt64 *MyInt64 `protobuf:"14"`
  38. MyUint32 *MyUint32 `protobuf:"15"`
  39. MyUint64 *MyUint64 `protobuf:"16"`
  40. MyFloat32 *MyFloat32 `protobuf:"17"`
  41. MyFloat64 *MyFloat64 `protobuf:"18"`
  42. MyString *MyString `protobuf:"19"`
  43. MyStringA MyBytes `protobuf:"20"`
  44. MyBytes MyBytes `protobuf:"21"`
  45. MyBytesA *MyString `protobuf:"22"`
  46. }
  47. type ScalarProto3 struct {
  48. Bool bool `protobuf:"1"`
  49. Int32 int32 `protobuf:"2"`
  50. Int64 int64 `protobuf:"3"`
  51. Uint32 uint32 `protobuf:"4"`
  52. Uint64 uint64 `protobuf:"5"`
  53. Float32 float32 `protobuf:"6"`
  54. Float64 float64 `protobuf:"7"`
  55. String string `protobuf:"8"`
  56. StringA []byte `protobuf:"9"`
  57. Bytes []byte `protobuf:"10"`
  58. BytesA string `protobuf:"11"`
  59. MyBool MyBool `protobuf:"12"`
  60. MyInt32 MyInt32 `protobuf:"13"`
  61. MyInt64 MyInt64 `protobuf:"14"`
  62. MyUint32 MyUint32 `protobuf:"15"`
  63. MyUint64 MyUint64 `protobuf:"16"`
  64. MyFloat32 MyFloat32 `protobuf:"17"`
  65. MyFloat64 MyFloat64 `protobuf:"18"`
  66. MyString MyString `protobuf:"19"`
  67. MyStringA MyBytes `protobuf:"20"`
  68. MyBytes MyBytes `protobuf:"21"`
  69. MyBytesA MyString `protobuf:"22"`
  70. }
  71. func TestFieldFuncs(t *testing.T) {
  72. V := pref.ValueOf
  73. type (
  74. // has checks that each field matches the list.
  75. hasOp []bool
  76. // get checks that each field returns values matching the list.
  77. getOp []pref.Value
  78. // set calls set on each field with the given value in the list.
  79. setOp []pref.Value
  80. // clear calls clear on each field.
  81. clearOp []bool
  82. // equal checks that the current message equals the provided value.
  83. equalOp struct{ want interface{} }
  84. testOp interface{} // has | get | set | clear | equal
  85. )
  86. tests := []struct {
  87. structType reflect.Type
  88. messageDesc ptype.StandaloneMessage
  89. testOps []testOp
  90. }{{
  91. structType: reflect.TypeOf(ScalarProto2{}),
  92. messageDesc: ptype.StandaloneMessage{
  93. Syntax: pref.Proto2,
  94. FullName: "ScalarProto2",
  95. Fields: []ptype.Field{
  96. {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
  97. {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(2))},
  98. {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(3))},
  99. {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(4))},
  100. {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(5))},
  101. {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(6))},
  102. {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(7))},
  103. {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("8"))},
  104. {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("9"))},
  105. {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("10"))},
  106. {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("11"))},
  107. {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
  108. {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(13))},
  109. {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(14))},
  110. {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(15))},
  111. {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(16))},
  112. {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(17))},
  113. {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(18))},
  114. {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("19"))},
  115. {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("20"))},
  116. {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("21"))},
  117. {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("22"))},
  118. },
  119. },
  120. testOps: []testOp{
  121. hasOp([]bool{
  122. false, false, false, false, false, false, false, false, false, false, false,
  123. false, false, false, false, false, false, false, false, false, false, false,
  124. }),
  125. getOp([]pref.Value{
  126. V(bool(true)), V(int32(2)), V(int64(3)), V(uint32(4)), V(uint64(5)), V(float32(6)), V(float64(7)), V(string("8")), V(string("9")), V([]byte("10")), V([]byte("11")),
  127. V(bool(true)), V(int32(13)), V(int64(14)), V(uint32(15)), V(uint64(16)), V(float32(17)), V(float64(18)), V(string("19")), V(string("20")), V([]byte("21")), V([]byte("22")),
  128. }),
  129. setOp([]pref.Value{
  130. V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
  131. V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
  132. }),
  133. hasOp([]bool{
  134. true, true, true, true, true, true, true, true, true, true, true,
  135. true, true, true, true, true, true, true, true, true, true, true,
  136. }),
  137. equalOp{&ScalarProto2{
  138. new(bool), new(int32), new(int64), new(uint32), new(uint64), new(float32), new(float64), new(string), []byte{}, []byte{}, new(string),
  139. new(MyBool), new(MyInt32), new(MyInt64), new(MyUint32), new(MyUint64), new(MyFloat32), new(MyFloat64), new(MyString), MyBytes{}, MyBytes{}, new(MyString),
  140. }},
  141. clearOp([]bool{
  142. true, true, true, true, true, true, true, true, true, true, true,
  143. true, true, true, true, true, true, true, true, true, true, true,
  144. }),
  145. equalOp{&ScalarProto2{}},
  146. },
  147. }, {
  148. structType: reflect.TypeOf(ScalarProto3{}),
  149. messageDesc: ptype.StandaloneMessage{
  150. Syntax: pref.Proto3,
  151. FullName: "ScalarProto3",
  152. Fields: []ptype.Field{
  153. {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind},
  154. {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind},
  155. {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind},
  156. {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
  157. {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
  158. {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind},
  159. {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind},
  160. {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind},
  161. {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind},
  162. {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind},
  163. {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind},
  164. {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind},
  165. {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind},
  166. {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind},
  167. {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
  168. {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
  169. {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind},
  170. {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind},
  171. {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind},
  172. {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind},
  173. {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind},
  174. {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind},
  175. },
  176. },
  177. testOps: []testOp{
  178. hasOp([]bool{
  179. false, false, false, false, false, false, false, false, false, false, false,
  180. false, false, false, false, false, false, false, false, false, false, false,
  181. }),
  182. getOp([]pref.Value{
  183. V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
  184. V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
  185. }),
  186. setOp([]pref.Value{
  187. V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
  188. V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
  189. }),
  190. hasOp([]bool{
  191. false, false, false, false, false, false, false, false, false, false, false,
  192. false, false, false, false, false, false, false, false, false, false, false,
  193. }),
  194. equalOp{&ScalarProto3{}},
  195. setOp([]pref.Value{
  196. V(bool(true)), V(int32(2)), V(int64(3)), V(uint32(4)), V(uint64(5)), V(float32(6)), V(float64(7)), V(string("8")), V(string("9")), V([]byte("10")), V([]byte("11")),
  197. V(bool(true)), V(int32(13)), V(int64(14)), V(uint32(15)), V(uint64(16)), V(float32(17)), V(float64(18)), V(string("19")), V(string("20")), V([]byte("21")), V([]byte("22")),
  198. }),
  199. hasOp([]bool{
  200. true, true, true, true, true, true, true, true, true, true, true,
  201. true, true, true, true, true, true, true, true, true, true, true,
  202. }),
  203. equalOp{&ScalarProto3{
  204. true, 2, 3, 4, 5, 6, 7, "8", []byte("9"), []byte("10"), "11",
  205. true, 13, 14, 15, 16, 17, 18, "19", []byte("20"), []byte("21"), "22",
  206. }},
  207. clearOp([]bool{
  208. true, true, true, true, true, true, true, true, true, true, true,
  209. true, true, true, true, true, true, true, true, true, true, true,
  210. }),
  211. equalOp{&ScalarProto3{}},
  212. },
  213. }}
  214. for _, tt := range tests {
  215. t.Run(tt.structType.Name(), func(t *testing.T) {
  216. // Construct the message descriptor.
  217. md, err := ptype.NewMessage(&tt.messageDesc)
  218. if err != nil {
  219. t.Fatalf("NewMessage error: %v", err)
  220. }
  221. // Generate the field functions from the message descriptor.
  222. var mi MessageInfo
  223. mi.generateFieldFuncs(tt.structType, md) // must not panic
  224. // Test the field functions.
  225. m := reflect.New(tt.structType)
  226. p := pointerOfValue(m)
  227. for i, op := range tt.testOps {
  228. switch op := op.(type) {
  229. case hasOp:
  230. got := map[pref.FieldNumber]bool{}
  231. want := map[pref.FieldNumber]bool{}
  232. for j, ok := range op {
  233. n := pref.FieldNumber(j + 1)
  234. got[n] = mi.fields[n].has(p)
  235. want[n] = ok
  236. }
  237. if diff := cmp.Diff(want, got); diff != "" {
  238. t.Errorf("operation %d, has mismatch (-want, +got):\n%s", i, diff)
  239. }
  240. case getOp:
  241. got := map[pref.FieldNumber]pref.Value{}
  242. want := map[pref.FieldNumber]pref.Value{}
  243. for j, v := range op {
  244. n := pref.FieldNumber(j + 1)
  245. got[n] = mi.fields[n].get(p)
  246. want[n] = v
  247. }
  248. xformValue := cmp.Transformer("", func(v pref.Value) interface{} {
  249. return v.Interface()
  250. })
  251. if diff := cmp.Diff(want, got, xformValue); diff != "" {
  252. t.Errorf("operation %d, get mismatch (-want, +got):\n%s", i, diff)
  253. }
  254. case setOp:
  255. for j, v := range op {
  256. n := pref.FieldNumber(j + 1)
  257. mi.fields[n].set(p, v)
  258. }
  259. case clearOp:
  260. for j, ok := range op {
  261. n := pref.FieldNumber(j + 1)
  262. if ok {
  263. mi.fields[n].clear(p)
  264. }
  265. }
  266. case equalOp:
  267. got := m.Interface()
  268. if diff := cmp.Diff(op.want, got); diff != "" {
  269. t.Errorf("operation %d, equal mismatch (-want, +got):\n%s", i, diff)
  270. }
  271. }
  272. }
  273. })
  274. }
  275. }