other_test.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 prototext_test
  5. import (
  6. "testing"
  7. "google.golang.org/protobuf/encoding/prototext"
  8. "google.golang.org/protobuf/internal/impl"
  9. pimpl "google.golang.org/protobuf/internal/impl"
  10. "google.golang.org/protobuf/internal/scalar"
  11. "google.golang.org/protobuf/proto"
  12. preg "google.golang.org/protobuf/reflect/protoregistry"
  13. "google.golang.org/protobuf/encoding/testprotos/pb2"
  14. "google.golang.org/protobuf/types/known/anypb"
  15. "google.golang.org/protobuf/types/known/durationpb"
  16. "google.golang.org/protobuf/types/known/emptypb"
  17. "google.golang.org/protobuf/types/known/structpb"
  18. "google.golang.org/protobuf/types/known/timestamppb"
  19. "google.golang.org/protobuf/types/known/wrapperspb"
  20. )
  21. func TestRoundTrip(t *testing.T) {
  22. tests := []struct {
  23. desc string
  24. resolver *preg.Types
  25. message proto.Message
  26. }{{
  27. desc: "well-known type fields set to empty messages",
  28. message: &pb2.KnownTypes{
  29. OptBool: &wrapperspb.BoolValue{},
  30. OptInt32: &wrapperspb.Int32Value{},
  31. OptInt64: &wrapperspb.Int64Value{},
  32. OptUint32: &wrapperspb.UInt32Value{},
  33. OptUint64: &wrapperspb.UInt64Value{},
  34. OptFloat: &wrapperspb.FloatValue{},
  35. OptDouble: &wrapperspb.DoubleValue{},
  36. OptString: &wrapperspb.StringValue{},
  37. OptBytes: &wrapperspb.BytesValue{},
  38. OptDuration: &durationpb.Duration{},
  39. OptTimestamp: &timestamppb.Timestamp{},
  40. OptStruct: &structpb.Struct{},
  41. OptList: &structpb.ListValue{},
  42. OptValue: &structpb.Value{},
  43. OptEmpty: &emptypb.Empty{},
  44. OptAny: &anypb.Any{},
  45. },
  46. }, {
  47. desc: "well-known type scalar fields",
  48. message: &pb2.KnownTypes{
  49. OptBool: &wrapperspb.BoolValue{
  50. Value: true,
  51. },
  52. OptInt32: &wrapperspb.Int32Value{
  53. Value: -42,
  54. },
  55. OptInt64: &wrapperspb.Int64Value{
  56. Value: -42,
  57. },
  58. OptUint32: &wrapperspb.UInt32Value{
  59. Value: 0xff,
  60. },
  61. OptUint64: &wrapperspb.UInt64Value{
  62. Value: 0xffff,
  63. },
  64. OptFloat: &wrapperspb.FloatValue{
  65. Value: 1.234,
  66. },
  67. OptDouble: &wrapperspb.DoubleValue{
  68. Value: 1.23e308,
  69. },
  70. OptString: &wrapperspb.StringValue{
  71. Value: "谷歌",
  72. },
  73. OptBytes: &wrapperspb.BytesValue{
  74. Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
  75. },
  76. },
  77. }, {
  78. desc: "well-known type time-related fields",
  79. message: &pb2.KnownTypes{
  80. OptDuration: &durationpb.Duration{
  81. Seconds: -3600,
  82. Nanos: -123,
  83. },
  84. OptTimestamp: &timestamppb.Timestamp{
  85. Seconds: 1257894000,
  86. Nanos: 123,
  87. },
  88. },
  89. }, {
  90. desc: "Struct field and different Value types",
  91. message: &pb2.KnownTypes{
  92. OptStruct: &structpb.Struct{
  93. Fields: map[string]*structpb.Value{
  94. "bool": &structpb.Value{
  95. Kind: &structpb.Value_BoolValue{
  96. BoolValue: true,
  97. },
  98. },
  99. "double": &structpb.Value{
  100. Kind: &structpb.Value_NumberValue{
  101. NumberValue: 3.1415,
  102. },
  103. },
  104. "null": &structpb.Value{
  105. Kind: &structpb.Value_NullValue{
  106. NullValue: structpb.NullValue_NULL_VALUE,
  107. },
  108. },
  109. "string": &structpb.Value{
  110. Kind: &structpb.Value_StringValue{
  111. StringValue: "string",
  112. },
  113. },
  114. "struct": &structpb.Value{
  115. Kind: &structpb.Value_StructValue{
  116. StructValue: &structpb.Struct{
  117. Fields: map[string]*structpb.Value{
  118. "bool": &structpb.Value{
  119. Kind: &structpb.Value_BoolValue{
  120. BoolValue: false,
  121. },
  122. },
  123. },
  124. },
  125. },
  126. },
  127. "list": &structpb.Value{
  128. Kind: &structpb.Value_ListValue{
  129. ListValue: &structpb.ListValue{
  130. Values: []*structpb.Value{
  131. {
  132. Kind: &structpb.Value_BoolValue{
  133. BoolValue: false,
  134. },
  135. },
  136. {
  137. Kind: &structpb.Value_StringValue{
  138. StringValue: "hello",
  139. },
  140. },
  141. },
  142. },
  143. },
  144. },
  145. },
  146. },
  147. },
  148. }, {
  149. desc: "Any field without registered type",
  150. resolver: preg.NewTypes(),
  151. message: func() proto.Message {
  152. m := &pb2.Nested{
  153. OptString: scalar.String("embedded inside Any"),
  154. OptNested: &pb2.Nested{
  155. OptString: scalar.String("inception"),
  156. },
  157. }
  158. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  159. if err != nil {
  160. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  161. }
  162. return &pb2.KnownTypes{
  163. OptAny: &anypb.Any{
  164. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  165. Value: b,
  166. },
  167. }
  168. }(),
  169. }, {
  170. desc: "Any field with registered type",
  171. resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  172. message: func() *pb2.KnownTypes {
  173. m := &pb2.Nested{
  174. OptString: scalar.String("embedded inside Any"),
  175. OptNested: &pb2.Nested{
  176. OptString: scalar.String("inception"),
  177. },
  178. }
  179. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  180. if err != nil {
  181. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  182. }
  183. return &pb2.KnownTypes{
  184. OptAny: &anypb.Any{
  185. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  186. Value: b,
  187. },
  188. }
  189. }(),
  190. }, {
  191. desc: "Any field containing Any message",
  192. resolver: func() *preg.Types {
  193. mt1 := impl.Export{}.MessageTypeOf(&pb2.Nested{})
  194. mt2 := impl.Export{}.MessageTypeOf(&anypb.Any{})
  195. return preg.NewTypes(mt1, mt2)
  196. }(),
  197. message: func() *pb2.KnownTypes {
  198. m1 := &pb2.Nested{
  199. OptString: scalar.String("message inside Any of another Any field"),
  200. }
  201. b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
  202. if err != nil {
  203. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  204. }
  205. m2 := &anypb.Any{
  206. TypeUrl: "pb2.Nested",
  207. Value: b1,
  208. }
  209. b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
  210. if err != nil {
  211. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  212. }
  213. return &pb2.KnownTypes{
  214. OptAny: &anypb.Any{
  215. TypeUrl: "google.protobuf.Any",
  216. Value: b2,
  217. },
  218. }
  219. }(),
  220. }}
  221. for _, tt := range tests {
  222. tt := tt
  223. t.Run(tt.desc, func(t *testing.T) {
  224. t.Parallel()
  225. b, err := prototext.MarshalOptions{Resolver: tt.resolver}.Marshal(tt.message)
  226. if err != nil {
  227. t.Errorf("Marshal() returned error: %v\n\n", err)
  228. }
  229. gotMessage := new(pb2.KnownTypes)
  230. err = prototext.UnmarshalOptions{Resolver: tt.resolver}.Unmarshal(b, gotMessage)
  231. if err != nil {
  232. t.Errorf("Unmarshal() returned error: %v\n\n", err)
  233. }
  234. if !proto.Equal(gotMessage, tt.message) {
  235. t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
  236. }
  237. })
  238. }
  239. }