extension_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright 2019 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 proto_test
  5. import (
  6. "fmt"
  7. "reflect"
  8. "sync"
  9. "testing"
  10. "github.com/google/go-cmp/cmp"
  11. "google.golang.org/protobuf/proto"
  12. "google.golang.org/protobuf/reflect/protoreflect"
  13. "google.golang.org/protobuf/runtime/protoimpl"
  14. "google.golang.org/protobuf/testing/protocmp"
  15. legacy1pb "google.golang.org/protobuf/internal/testprotos/legacy/proto2_20160225_2fc053c5"
  16. testpb "google.golang.org/protobuf/internal/testprotos/test"
  17. test3pb "google.golang.org/protobuf/internal/testprotos/test3"
  18. descpb "google.golang.org/protobuf/types/descriptorpb"
  19. )
  20. func TestExtensionFuncs(t *testing.T) {
  21. for _, test := range []struct {
  22. message proto.Message
  23. ext protoreflect.ExtensionType
  24. wantDefault interface{}
  25. value interface{}
  26. }{
  27. {
  28. message: &testpb.TestAllExtensions{},
  29. ext: testpb.E_OptionalInt32,
  30. wantDefault: int32(0),
  31. value: int32(1),
  32. },
  33. {
  34. message: &testpb.TestAllExtensions{},
  35. ext: testpb.E_RepeatedString,
  36. wantDefault: ([]string)(nil),
  37. value: []string{"a", "b", "c"},
  38. },
  39. {
  40. message: protoimpl.X.MessageOf(&legacy1pb.Message{}).Interface(),
  41. ext: legacy1pb.E_Message_ExtensionOptionalBool,
  42. wantDefault: false,
  43. value: true,
  44. },
  45. } {
  46. desc := fmt.Sprintf("Extension %v, value %v", test.ext.TypeDescriptor().FullName(), test.value)
  47. if proto.HasExtension(test.message, test.ext) {
  48. t.Errorf("%v:\nbefore setting extension HasExtension(...) = true, want false", desc)
  49. }
  50. got := proto.GetExtension(test.message, test.ext)
  51. if d := cmp.Diff(test.wantDefault, got); d != "" {
  52. t.Errorf("%v:\nbefore setting extension GetExtension(...) returns unexpected value (-want,+got):\n%v", desc, d)
  53. }
  54. proto.SetExtension(test.message, test.ext, test.value)
  55. if !proto.HasExtension(test.message, test.ext) {
  56. t.Errorf("%v:\nafter setting extension HasExtension(...) = false, want true", desc)
  57. }
  58. got = proto.GetExtension(test.message, test.ext)
  59. if d := cmp.Diff(test.value, got); d != "" {
  60. t.Errorf("%v:\nafter setting extension GetExtension(...) returns unexpected value (-want,+got):\n%v", desc, d)
  61. }
  62. proto.ClearExtension(test.message, test.ext)
  63. if proto.HasExtension(test.message, test.ext) {
  64. t.Errorf("%v:\nafter clearing extension HasExtension(...) = true, want false", desc)
  65. }
  66. }
  67. }
  68. func TestIsValid(t *testing.T) {
  69. tests := []struct {
  70. xt protoreflect.ExtensionType
  71. vi interface{}
  72. want bool
  73. }{
  74. {testpb.E_OptionalBool, nil, false},
  75. {testpb.E_OptionalBool, bool(true), true},
  76. {testpb.E_OptionalBool, new(bool), false},
  77. {testpb.E_OptionalInt32, nil, false},
  78. {testpb.E_OptionalInt32, int32(0), true},
  79. {testpb.E_OptionalInt32, new(int32), false},
  80. {testpb.E_OptionalInt64, nil, false},
  81. {testpb.E_OptionalInt64, int64(0), true},
  82. {testpb.E_OptionalInt64, new(int64), false},
  83. {testpb.E_OptionalUint32, nil, false},
  84. {testpb.E_OptionalUint32, uint32(0), true},
  85. {testpb.E_OptionalUint32, new(uint32), false},
  86. {testpb.E_OptionalUint64, nil, false},
  87. {testpb.E_OptionalUint64, uint64(0), true},
  88. {testpb.E_OptionalUint64, new(uint64), false},
  89. {testpb.E_OptionalFloat, nil, false},
  90. {testpb.E_OptionalFloat, float32(0), true},
  91. {testpb.E_OptionalFloat, new(float32), false},
  92. {testpb.E_OptionalDouble, nil, false},
  93. {testpb.E_OptionalDouble, float64(0), true},
  94. {testpb.E_OptionalDouble, new(float32), false},
  95. {testpb.E_OptionalString, nil, false},
  96. {testpb.E_OptionalString, string(""), true},
  97. {testpb.E_OptionalString, new(string), false},
  98. {testpb.E_OptionalNestedEnum, nil, false},
  99. {testpb.E_OptionalNestedEnum, testpb.TestAllTypes_BAZ, true},
  100. {testpb.E_OptionalNestedEnum, testpb.TestAllTypes_BAZ.Enum(), false},
  101. {testpb.E_OptionalNestedMessage, nil, false},
  102. {testpb.E_OptionalNestedMessage, (*testpb.TestAllExtensions_NestedMessage)(nil), true},
  103. {testpb.E_OptionalNestedMessage, new(testpb.TestAllExtensions_NestedMessage), true},
  104. {testpb.E_OptionalNestedMessage, new(testpb.TestAllExtensions), false},
  105. {testpb.E_RepeatedBool, nil, false},
  106. {testpb.E_RepeatedBool, []bool(nil), true},
  107. {testpb.E_RepeatedBool, []bool{}, true},
  108. {testpb.E_RepeatedBool, []bool{false}, true},
  109. {testpb.E_RepeatedBool, []*bool{}, false},
  110. {testpb.E_RepeatedInt32, nil, false},
  111. {testpb.E_RepeatedInt32, []int32(nil), true},
  112. {testpb.E_RepeatedInt32, []int32{}, true},
  113. {testpb.E_RepeatedInt32, []int32{0}, true},
  114. {testpb.E_RepeatedInt32, []*int32{}, false},
  115. {testpb.E_RepeatedInt64, nil, false},
  116. {testpb.E_RepeatedInt64, []int64(nil), true},
  117. {testpb.E_RepeatedInt64, []int64{}, true},
  118. {testpb.E_RepeatedInt64, []int64{0}, true},
  119. {testpb.E_RepeatedInt64, []*int64{}, false},
  120. {testpb.E_RepeatedUint32, nil, false},
  121. {testpb.E_RepeatedUint32, []uint32(nil), true},
  122. {testpb.E_RepeatedUint32, []uint32{}, true},
  123. {testpb.E_RepeatedUint32, []uint32{0}, true},
  124. {testpb.E_RepeatedUint32, []*uint32{}, false},
  125. {testpb.E_RepeatedUint64, nil, false},
  126. {testpb.E_RepeatedUint64, []uint64(nil), true},
  127. {testpb.E_RepeatedUint64, []uint64{}, true},
  128. {testpb.E_RepeatedUint64, []uint64{0}, true},
  129. {testpb.E_RepeatedUint64, []*uint64{}, false},
  130. {testpb.E_RepeatedFloat, nil, false},
  131. {testpb.E_RepeatedFloat, []float32(nil), true},
  132. {testpb.E_RepeatedFloat, []float32{}, true},
  133. {testpb.E_RepeatedFloat, []float32{0}, true},
  134. {testpb.E_RepeatedFloat, []*float32{}, false},
  135. {testpb.E_RepeatedDouble, nil, false},
  136. {testpb.E_RepeatedDouble, []float64(nil), true},
  137. {testpb.E_RepeatedDouble, []float64{}, true},
  138. {testpb.E_RepeatedDouble, []float64{0}, true},
  139. {testpb.E_RepeatedDouble, []*float64{}, false},
  140. {testpb.E_RepeatedString, nil, false},
  141. {testpb.E_RepeatedString, []string(nil), true},
  142. {testpb.E_RepeatedString, []string{}, true},
  143. {testpb.E_RepeatedString, []string{""}, true},
  144. {testpb.E_RepeatedString, []*string{}, false},
  145. {testpb.E_RepeatedNestedEnum, nil, false},
  146. {testpb.E_RepeatedNestedEnum, []testpb.TestAllTypes_NestedEnum(nil), true},
  147. {testpb.E_RepeatedNestedEnum, []testpb.TestAllTypes_NestedEnum{}, true},
  148. {testpb.E_RepeatedNestedEnum, []testpb.TestAllTypes_NestedEnum{0}, true},
  149. {testpb.E_RepeatedNestedEnum, []*testpb.TestAllTypes_NestedEnum{}, false},
  150. {testpb.E_RepeatedNestedMessage, nil, false},
  151. {testpb.E_RepeatedNestedMessage, []*testpb.TestAllExtensions_NestedMessage(nil), true},
  152. {testpb.E_RepeatedNestedMessage, []*testpb.TestAllExtensions_NestedMessage{}, true},
  153. {testpb.E_RepeatedNestedMessage, []*testpb.TestAllExtensions_NestedMessage{{}}, true},
  154. {testpb.E_RepeatedNestedMessage, []*testpb.TestAllExtensions{}, false},
  155. }
  156. for _, tt := range tests {
  157. // Check the results of IsValidInterface.
  158. got := tt.xt.IsValidInterface(tt.vi)
  159. if got != tt.want {
  160. t.Errorf("%v.IsValidInterface() = %v, want %v", tt.xt.TypeDescriptor().FullName(), got, tt.want)
  161. }
  162. if !got {
  163. continue
  164. }
  165. // Set the extension value and verify the results of Has.
  166. wantHas := true
  167. pv := tt.xt.ValueOf(tt.vi)
  168. switch v := pv.Interface().(type) {
  169. case protoreflect.List:
  170. wantHas = v.Len() > 0
  171. case protoreflect.Message:
  172. wantHas = v.IsValid()
  173. }
  174. m := &testpb.TestAllExtensions{}
  175. proto.SetExtension(m, tt.xt, tt.vi)
  176. gotHas := proto.HasExtension(m, tt.xt)
  177. if gotHas != wantHas {
  178. t.Errorf("HasExtension(%q) = %v, want %v", tt.xt.TypeDescriptor().FullName(), gotHas, wantHas)
  179. }
  180. // Check consistency of IsValidInterface and IsValidValue.
  181. got = tt.xt.IsValidValue(pv)
  182. if got != tt.want {
  183. t.Errorf("%v.IsValidValue() = %v, want %v", tt.xt.TypeDescriptor().FullName(), got, tt.want)
  184. }
  185. if !got {
  186. continue
  187. }
  188. // Use of reflect.DeepEqual is intentional.
  189. // We really do want to ensure that the memory layout is identical.
  190. vi := tt.xt.InterfaceOf(pv)
  191. if !reflect.DeepEqual(vi, tt.vi) {
  192. t.Errorf("InterfaceOf(ValueOf(...)) round-trip mismatch: got %v, want %v", vi, tt.vi)
  193. }
  194. }
  195. }
  196. func TestExtensionRanger(t *testing.T) {
  197. tests := []struct {
  198. msg proto.Message
  199. want map[protoreflect.ExtensionType]interface{}
  200. }{{
  201. msg: &testpb.TestAllExtensions{},
  202. want: map[protoreflect.ExtensionType]interface{}{
  203. testpb.E_OptionalInt32: int32(5),
  204. testpb.E_OptionalString: string("hello"),
  205. testpb.E_OptionalNestedMessage: &testpb.TestAllExtensions_NestedMessage{},
  206. testpb.E_OptionalNestedEnum: testpb.TestAllTypes_BAZ,
  207. testpb.E_RepeatedFloat: []float32{+32.32, -32.32},
  208. testpb.E_RepeatedNestedMessage: []*testpb.TestAllExtensions_NestedMessage{{}},
  209. testpb.E_RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAZ},
  210. },
  211. }, {
  212. msg: &descpb.MessageOptions{},
  213. want: map[protoreflect.ExtensionType]interface{}{
  214. test3pb.E_OptionalInt32: int32(5),
  215. test3pb.E_OptionalString: string("hello"),
  216. test3pb.E_OptionalForeignMessage: &test3pb.ForeignMessage{},
  217. test3pb.E_OptionalForeignEnum: test3pb.ForeignEnum_FOREIGN_BAR,
  218. test3pb.E_OptionalOptionalInt32: int32(5),
  219. test3pb.E_OptionalOptionalString: string("hello"),
  220. test3pb.E_OptionalOptionalForeignMessage: &test3pb.ForeignMessage{},
  221. test3pb.E_OptionalOptionalForeignEnum: test3pb.ForeignEnum_FOREIGN_BAR,
  222. },
  223. }}
  224. for _, tt := range tests {
  225. for xt, v := range tt.want {
  226. proto.SetExtension(tt.msg, xt, v)
  227. }
  228. got := make(map[protoreflect.ExtensionType]interface{})
  229. proto.RangeExtensions(tt.msg, func(xt protoreflect.ExtensionType, v interface{}) bool {
  230. got[xt] = v
  231. return true
  232. })
  233. if diff := cmp.Diff(tt.want, got, protocmp.Transform()); diff != "" {
  234. t.Errorf("proto.RangeExtensions mismatch (-want +got):\n%s", diff)
  235. }
  236. }
  237. }
  238. func TestExtensionGetRace(t *testing.T) {
  239. // Concurrently fetch an extension value while marshaling the message containing it.
  240. // Create the message with proto.Unmarshal to give lazy extension decoding (if present)
  241. // a chance to occur.
  242. want := int32(42)
  243. m1 := &testpb.TestAllExtensions{}
  244. proto.SetExtension(m1, testpb.E_OptionalNestedMessage, &testpb.TestAllExtensions_NestedMessage{A: proto.Int32(want)})
  245. b, err := proto.Marshal(m1)
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. m := &testpb.TestAllExtensions{}
  250. if err := proto.Unmarshal(b, m); err != nil {
  251. t.Fatal(err)
  252. }
  253. var wg sync.WaitGroup
  254. for i := 0; i < 3; i++ {
  255. wg.Add(1)
  256. go func() {
  257. defer wg.Done()
  258. if _, err := proto.Marshal(m); err != nil {
  259. t.Error(err)
  260. }
  261. }()
  262. wg.Add(1)
  263. go func() {
  264. defer wg.Done()
  265. got := proto.GetExtension(m, testpb.E_OptionalNestedMessage).(*testpb.TestAllExtensions_NestedMessage).GetA()
  266. if got != want {
  267. t.Errorf("GetExtension(optional_nested_message).a = %v, want %v", got, want)
  268. }
  269. }()
  270. }
  271. wg.Wait()
  272. }