other_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  151. if err != nil {
  152. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  153. }
  154. return &pb2.KnownTypes{
  155. OptAny: &knownpb.Any{
  156. TypeUrl: string(m.ProtoReflect().Type().FullName()),
  157. Value: b,
  158. },
  159. }
  160. }(),
  161. }, {
  162. desc: "Any field with registered type",
  163. resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
  164. message: func() proto.Message {
  165. m := &pb2.Nested{
  166. OptString: scalar.String("embedded inside Any"),
  167. OptNested: &pb2.Nested{
  168. OptString: scalar.String("inception"),
  169. },
  170. }
  171. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  172. if err != nil {
  173. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  174. }
  175. return &pb2.KnownTypes{
  176. OptAny: &knownpb.Any{
  177. TypeUrl: string(m.ProtoReflect().Type().FullName()),
  178. Value: b,
  179. },
  180. }
  181. }(),
  182. }, {
  183. desc: "Any field containing Any message",
  184. resolver: func() *preg.Types {
  185. mt1 := (&pb2.Nested{}).ProtoReflect().Type()
  186. mt2 := impl.Export{}.MessageTypeOf(&knownpb.Any{})
  187. return preg.NewTypes(mt1, mt2)
  188. }(),
  189. message: func() proto.Message {
  190. m1 := &pb2.Nested{
  191. OptString: scalar.String("message inside Any of another Any field"),
  192. }
  193. b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
  194. if err != nil {
  195. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  196. }
  197. m2 := &knownpb.Any{
  198. TypeUrl: "pb2.Nested",
  199. Value: b1,
  200. }
  201. b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
  202. if err != nil {
  203. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  204. }
  205. return &pb2.KnownTypes{
  206. OptAny: &knownpb.Any{
  207. TypeUrl: "google.protobuf.Any",
  208. Value: b2,
  209. },
  210. }
  211. }(),
  212. }}
  213. for _, tt := range tests {
  214. tt := tt
  215. t.Run(tt.desc, func(t *testing.T) {
  216. t.Parallel()
  217. mo := textpb.MarshalOptions{Resolver: tt.resolver}
  218. umo := textpb.UnmarshalOptions{Resolver: tt.resolver}
  219. b, err := mo.Marshal(tt.message)
  220. if err != nil {
  221. t.Errorf("Marshal() returned error: %v\n\n", err)
  222. }
  223. gotMessage := tt.message.ProtoReflect().Type().New().Interface()
  224. err = umo.Unmarshal(gotMessage, b)
  225. if err != nil {
  226. t.Errorf("Unmarshal() returned error: %v\n\n", err)
  227. }
  228. if !protoV1.Equal(gotMessage.(protoV1.Message), tt.message.(protoV1.Message)) {
  229. t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
  230. }
  231. })
  232. }
  233. }