other_test.go 6.6 KB

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