other_test.go 6.5 KB

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