other_test.go 6.1 KB

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