other_test.go 6.2 KB

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