other_test.go 6.2 KB

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