other_test.go 6.5 KB

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