encode_test.go 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. // Copyright 2018 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 textpb_test
  5. import (
  6. "encoding/hex"
  7. "math"
  8. "strings"
  9. "testing"
  10. protoV1 "github.com/golang/protobuf/proto"
  11. "github.com/golang/protobuf/protoapi"
  12. "github.com/golang/protobuf/v2/encoding/textpb"
  13. "github.com/golang/protobuf/v2/internal/detrand"
  14. "github.com/golang/protobuf/v2/internal/encoding/pack"
  15. "github.com/golang/protobuf/v2/internal/encoding/wire"
  16. "github.com/golang/protobuf/v2/internal/impl"
  17. "github.com/golang/protobuf/v2/internal/legacy"
  18. "github.com/golang/protobuf/v2/internal/scalar"
  19. "github.com/golang/protobuf/v2/proto"
  20. preg "github.com/golang/protobuf/v2/reflect/protoregistry"
  21. "github.com/google/go-cmp/cmp"
  22. "github.com/google/go-cmp/cmp/cmpopts"
  23. // The legacy package must be imported prior to use of any legacy messages.
  24. // TODO: Remove this when protoV1 registers these hooks for you.
  25. _ "github.com/golang/protobuf/v2/internal/legacy"
  26. anypb "github.com/golang/protobuf/ptypes/any"
  27. "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
  28. "github.com/golang/protobuf/v2/encoding/testprotos/pb3"
  29. )
  30. func init() {
  31. // Disable detrand to enable direct comparisons on outputs.
  32. detrand.Disable()
  33. }
  34. // splitLines is a cmpopts.Option for comparing strings with line breaks.
  35. var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
  36. return strings.Split(s, "\n")
  37. })
  38. func pb2Enum(i int32) *pb2.Enum {
  39. p := new(pb2.Enum)
  40. *p = pb2.Enum(i)
  41. return p
  42. }
  43. func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
  44. p := new(pb2.Enums_NestedEnum)
  45. *p = pb2.Enums_NestedEnum(i)
  46. return p
  47. }
  48. func setExtension(m proto.Message, xd *protoapi.ExtensionDesc, val interface{}) {
  49. xt := legacy.Export{}.ExtensionTypeFromDesc(xd)
  50. knownFields := m.ProtoReflect().KnownFields()
  51. extTypes := knownFields.ExtensionTypes()
  52. extTypes.Register(xt)
  53. if val == nil {
  54. return
  55. }
  56. pval := xt.ValueOf(val)
  57. knownFields.Set(wire.Number(xd.Field), pval)
  58. }
  59. func wrapV1Message(any *anypb.Any) proto.Message {
  60. return impl.Export{}.MessageOf(any).Interface()
  61. }
  62. // dhex decodes a hex-string and returns the bytes and panics if s is invalid.
  63. func dhex(s string) []byte {
  64. b, err := hex.DecodeString(s)
  65. if err != nil {
  66. panic(err)
  67. }
  68. return b
  69. }
  70. func TestMarshal(t *testing.T) {
  71. tests := []struct {
  72. desc string
  73. mo textpb.MarshalOptions
  74. input proto.Message
  75. want string
  76. wantErr bool
  77. }{{
  78. desc: "proto2 optional scalars not set",
  79. input: &pb2.Scalars{},
  80. want: "\n",
  81. }, {
  82. desc: "proto3 scalars not set",
  83. input: &pb3.Scalars{},
  84. want: "\n",
  85. }, {
  86. desc: "proto2 optional scalars set to zero values",
  87. input: &pb2.Scalars{
  88. OptBool: scalar.Bool(false),
  89. OptInt32: scalar.Int32(0),
  90. OptInt64: scalar.Int64(0),
  91. OptUint32: scalar.Uint32(0),
  92. OptUint64: scalar.Uint64(0),
  93. OptSint32: scalar.Int32(0),
  94. OptSint64: scalar.Int64(0),
  95. OptFixed32: scalar.Uint32(0),
  96. OptFixed64: scalar.Uint64(0),
  97. OptSfixed32: scalar.Int32(0),
  98. OptSfixed64: scalar.Int64(0),
  99. OptFloat: scalar.Float32(0),
  100. OptDouble: scalar.Float64(0),
  101. OptBytes: []byte{},
  102. OptString: scalar.String(""),
  103. },
  104. want: `opt_bool: false
  105. opt_int32: 0
  106. opt_int64: 0
  107. opt_uint32: 0
  108. opt_uint64: 0
  109. opt_sint32: 0
  110. opt_sint64: 0
  111. opt_fixed32: 0
  112. opt_fixed64: 0
  113. opt_sfixed32: 0
  114. opt_sfixed64: 0
  115. opt_float: 0
  116. opt_double: 0
  117. opt_bytes: ""
  118. opt_string: ""
  119. `,
  120. }, {
  121. desc: "proto3 scalars set to zero values",
  122. input: &pb3.Scalars{
  123. SBool: false,
  124. SInt32: 0,
  125. SInt64: 0,
  126. SUint32: 0,
  127. SUint64: 0,
  128. SSint32: 0,
  129. SSint64: 0,
  130. SFixed32: 0,
  131. SFixed64: 0,
  132. SSfixed32: 0,
  133. SSfixed64: 0,
  134. SFloat: 0,
  135. SDouble: 0,
  136. SBytes: []byte{},
  137. SString: "",
  138. },
  139. want: "\n",
  140. }, {
  141. desc: "proto2 optional scalars set to some values",
  142. input: &pb2.Scalars{
  143. OptBool: scalar.Bool(true),
  144. OptInt32: scalar.Int32(0xff),
  145. OptInt64: scalar.Int64(0xdeadbeef),
  146. OptUint32: scalar.Uint32(47),
  147. OptUint64: scalar.Uint64(0xdeadbeef),
  148. OptSint32: scalar.Int32(-1001),
  149. OptSint64: scalar.Int64(-0xffff),
  150. OptFixed64: scalar.Uint64(64),
  151. OptSfixed32: scalar.Int32(-32),
  152. OptFloat: scalar.Float32(1.02),
  153. OptDouble: scalar.Float64(1.0199999809265137),
  154. OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
  155. OptString: scalar.String("谷歌"),
  156. },
  157. want: `opt_bool: true
  158. opt_int32: 255
  159. opt_int64: 3735928559
  160. opt_uint32: 47
  161. opt_uint64: 3735928559
  162. opt_sint32: -1001
  163. opt_sint64: -65535
  164. opt_fixed64: 64
  165. opt_sfixed32: -32
  166. opt_float: 1.02
  167. opt_double: 1.0199999809265137
  168. opt_bytes: "谷歌"
  169. opt_string: "谷歌"
  170. `,
  171. }, {
  172. desc: "float nan",
  173. input: &pb3.Scalars{
  174. SFloat: float32(math.NaN()),
  175. },
  176. want: "s_float: nan\n",
  177. }, {
  178. desc: "float positive infinity",
  179. input: &pb3.Scalars{
  180. SFloat: float32(math.Inf(1)),
  181. },
  182. want: "s_float: inf\n",
  183. }, {
  184. desc: "float negative infinity",
  185. input: &pb3.Scalars{
  186. SFloat: float32(math.Inf(-1)),
  187. },
  188. want: "s_float: -inf\n",
  189. }, {
  190. desc: "double nan",
  191. input: &pb3.Scalars{
  192. SDouble: math.NaN(),
  193. },
  194. want: "s_double: nan\n",
  195. }, {
  196. desc: "double positive infinity",
  197. input: &pb3.Scalars{
  198. SDouble: math.Inf(1),
  199. },
  200. want: "s_double: inf\n",
  201. }, {
  202. desc: "double negative infinity",
  203. input: &pb3.Scalars{
  204. SDouble: math.Inf(-1),
  205. },
  206. want: "s_double: -inf\n",
  207. }, {
  208. desc: "proto2 enum not set",
  209. input: &pb2.Enums{},
  210. want: "\n",
  211. }, {
  212. desc: "proto2 enum set to zero value",
  213. input: &pb2.Enums{
  214. OptEnum: pb2Enum(0),
  215. OptNestedEnum: pb2Enums_NestedEnum(0),
  216. },
  217. want: `opt_enum: 0
  218. opt_nested_enum: 0
  219. `,
  220. }, {
  221. desc: "proto2 enum",
  222. input: &pb2.Enums{
  223. OptEnum: pb2.Enum_ONE.Enum(),
  224. OptNestedEnum: pb2.Enums_UNO.Enum(),
  225. },
  226. want: `opt_enum: ONE
  227. opt_nested_enum: UNO
  228. `,
  229. }, {
  230. desc: "proto2 enum set to numeric values",
  231. input: &pb2.Enums{
  232. OptEnum: pb2Enum(2),
  233. OptNestedEnum: pb2Enums_NestedEnum(2),
  234. },
  235. want: `opt_enum: TWO
  236. opt_nested_enum: DOS
  237. `,
  238. }, {
  239. desc: "proto2 enum set to unnamed numeric values",
  240. input: &pb2.Enums{
  241. OptEnum: pb2Enum(101),
  242. OptNestedEnum: pb2Enums_NestedEnum(-101),
  243. },
  244. want: `opt_enum: 101
  245. opt_nested_enum: -101
  246. `,
  247. }, {
  248. desc: "proto3 enum not set",
  249. input: &pb3.Enums{},
  250. want: "\n",
  251. }, {
  252. desc: "proto3 enum set to zero value",
  253. input: &pb3.Enums{
  254. SEnum: pb3.Enum_ZERO,
  255. SNestedEnum: pb3.Enums_CERO,
  256. },
  257. want: "\n",
  258. }, {
  259. desc: "proto3 enum",
  260. input: &pb3.Enums{
  261. SEnum: pb3.Enum_ONE,
  262. SNestedEnum: pb3.Enums_UNO,
  263. },
  264. want: `s_enum: ONE
  265. s_nested_enum: UNO
  266. `,
  267. }, {
  268. desc: "proto3 enum set to numeric values",
  269. input: &pb3.Enums{
  270. SEnum: 2,
  271. SNestedEnum: 2,
  272. },
  273. want: `s_enum: TWO
  274. s_nested_enum: DOS
  275. `,
  276. }, {
  277. desc: "proto3 enum set to unnamed numeric values",
  278. input: &pb3.Enums{
  279. SEnum: -47,
  280. SNestedEnum: 47,
  281. },
  282. want: `s_enum: -47
  283. s_nested_enum: 47
  284. `,
  285. }, {
  286. desc: "proto2 nested message not set",
  287. input: &pb2.Nests{},
  288. want: "\n",
  289. }, {
  290. desc: "proto2 nested message set to empty",
  291. input: &pb2.Nests{
  292. OptNested: &pb2.Nested{},
  293. Optgroup: &pb2.Nests_OptGroup{},
  294. },
  295. want: `opt_nested: {}
  296. OptGroup: {}
  297. `,
  298. }, {
  299. desc: "proto2 nested messages",
  300. input: &pb2.Nests{
  301. OptNested: &pb2.Nested{
  302. OptString: scalar.String("nested message"),
  303. OptNested: &pb2.Nested{
  304. OptString: scalar.String("another nested message"),
  305. },
  306. },
  307. },
  308. want: `opt_nested: {
  309. opt_string: "nested message"
  310. opt_nested: {
  311. opt_string: "another nested message"
  312. }
  313. }
  314. `,
  315. }, {
  316. desc: "proto2 groups",
  317. input: &pb2.Nests{
  318. Optgroup: &pb2.Nests_OptGroup{
  319. OptString: scalar.String("inside a group"),
  320. OptNested: &pb2.Nested{
  321. OptString: scalar.String("nested message inside a group"),
  322. },
  323. Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
  324. OptFixed32: scalar.Uint32(47),
  325. },
  326. },
  327. },
  328. want: `OptGroup: {
  329. opt_string: "inside a group"
  330. opt_nested: {
  331. opt_string: "nested message inside a group"
  332. }
  333. OptNestedGroup: {
  334. opt_fixed32: 47
  335. }
  336. }
  337. `,
  338. }, {
  339. desc: "proto3 nested message not set",
  340. input: &pb3.Nests{},
  341. want: "\n",
  342. }, {
  343. desc: "proto3 nested message set to empty",
  344. input: &pb3.Nests{
  345. SNested: &pb3.Nested{},
  346. },
  347. want: "s_nested: {}\n",
  348. }, {
  349. desc: "proto3 nested message",
  350. input: &pb3.Nests{
  351. SNested: &pb3.Nested{
  352. SString: "nested message",
  353. SNested: &pb3.Nested{
  354. SString: "another nested message",
  355. },
  356. },
  357. },
  358. want: `s_nested: {
  359. s_string: "nested message"
  360. s_nested: {
  361. s_string: "another nested message"
  362. }
  363. }
  364. `,
  365. }, {
  366. desc: "oneof not set",
  367. input: &pb3.Oneofs{},
  368. want: "\n",
  369. }, {
  370. desc: "oneof set to empty string",
  371. input: &pb3.Oneofs{
  372. Union: &pb3.Oneofs_OneofString{},
  373. },
  374. want: `oneof_string: ""
  375. `,
  376. }, {
  377. desc: "oneof set to string",
  378. input: &pb3.Oneofs{
  379. Union: &pb3.Oneofs_OneofString{
  380. OneofString: "hello",
  381. },
  382. },
  383. want: `oneof_string: "hello"
  384. `,
  385. }, {
  386. desc: "oneof set to enum",
  387. input: &pb3.Oneofs{
  388. Union: &pb3.Oneofs_OneofEnum{
  389. OneofEnum: pb3.Enum_ZERO,
  390. },
  391. },
  392. want: `oneof_enum: ZERO
  393. `,
  394. }, {
  395. desc: "oneof set to empty message",
  396. input: &pb3.Oneofs{
  397. Union: &pb3.Oneofs_OneofNested{
  398. OneofNested: &pb3.Nested{},
  399. },
  400. },
  401. want: "oneof_nested: {}\n",
  402. }, {
  403. desc: "oneof set to message",
  404. input: &pb3.Oneofs{
  405. Union: &pb3.Oneofs_OneofNested{
  406. OneofNested: &pb3.Nested{
  407. SString: "nested message",
  408. },
  409. },
  410. },
  411. want: `oneof_nested: {
  412. s_string: "nested message"
  413. }
  414. `,
  415. }, {
  416. desc: "repeated fields not set",
  417. input: &pb2.Repeats{},
  418. want: "\n",
  419. }, {
  420. desc: "repeated fields set to empty slices",
  421. input: &pb2.Repeats{
  422. RptBool: []bool{},
  423. RptInt32: []int32{},
  424. RptInt64: []int64{},
  425. RptUint32: []uint32{},
  426. RptUint64: []uint64{},
  427. RptFloat: []float32{},
  428. RptDouble: []float64{},
  429. RptBytes: [][]byte{},
  430. },
  431. want: "\n",
  432. }, {
  433. desc: "repeated fields set to some values",
  434. input: &pb2.Repeats{
  435. RptBool: []bool{true, false, true, true},
  436. RptInt32: []int32{1, 6, 0, 0},
  437. RptInt64: []int64{-64, 47},
  438. RptUint32: []uint32{0xff, 0xffff},
  439. RptUint64: []uint64{0xdeadbeef},
  440. RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
  441. RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
  442. RptString: []string{"hello", "世界"},
  443. RptBytes: [][]byte{
  444. []byte("hello"),
  445. []byte("\xe4\xb8\x96\xe7\x95\x8c"),
  446. },
  447. },
  448. want: `rpt_bool: true
  449. rpt_bool: false
  450. rpt_bool: true
  451. rpt_bool: true
  452. rpt_int32: 1
  453. rpt_int32: 6
  454. rpt_int32: 0
  455. rpt_int32: 0
  456. rpt_int64: -64
  457. rpt_int64: 47
  458. rpt_uint32: 255
  459. rpt_uint32: 65535
  460. rpt_uint64: 3735928559
  461. rpt_float: nan
  462. rpt_float: inf
  463. rpt_float: -inf
  464. rpt_float: 1.034
  465. rpt_double: nan
  466. rpt_double: inf
  467. rpt_double: -inf
  468. rpt_double: 1.23e-308
  469. rpt_string: "hello"
  470. rpt_string: "世界"
  471. rpt_bytes: "hello"
  472. rpt_bytes: "世界"
  473. `,
  474. }, {
  475. desc: "repeated enums",
  476. input: &pb2.Enums{
  477. RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
  478. RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
  479. },
  480. want: `rpt_enum: ONE
  481. rpt_enum: TWO
  482. rpt_enum: TEN
  483. rpt_enum: 42
  484. rpt_nested_enum: DOS
  485. rpt_nested_enum: 47
  486. rpt_nested_enum: DIEZ
  487. `,
  488. }, {
  489. desc: "repeated messages set to empty",
  490. input: &pb2.Nests{
  491. RptNested: []*pb2.Nested{},
  492. Rptgroup: []*pb2.Nests_RptGroup{},
  493. },
  494. want: "\n",
  495. }, {
  496. desc: "repeated messages",
  497. input: &pb2.Nests{
  498. RptNested: []*pb2.Nested{
  499. {
  500. OptString: scalar.String("repeat nested one"),
  501. },
  502. {
  503. OptString: scalar.String("repeat nested two"),
  504. OptNested: &pb2.Nested{
  505. OptString: scalar.String("inside repeat nested two"),
  506. },
  507. },
  508. {},
  509. },
  510. },
  511. want: `rpt_nested: {
  512. opt_string: "repeat nested one"
  513. }
  514. rpt_nested: {
  515. opt_string: "repeat nested two"
  516. opt_nested: {
  517. opt_string: "inside repeat nested two"
  518. }
  519. }
  520. rpt_nested: {}
  521. `,
  522. }, {
  523. desc: "repeated messages contains nil value",
  524. input: &pb2.Nests{
  525. RptNested: []*pb2.Nested{nil, {}},
  526. },
  527. want: `rpt_nested: {}
  528. rpt_nested: {}
  529. `,
  530. }, {
  531. desc: "repeated groups",
  532. input: &pb2.Nests{
  533. Rptgroup: []*pb2.Nests_RptGroup{
  534. {
  535. RptString: []string{"hello", "world"},
  536. },
  537. {},
  538. nil,
  539. },
  540. },
  541. want: `RptGroup: {
  542. rpt_string: "hello"
  543. rpt_string: "world"
  544. }
  545. RptGroup: {}
  546. RptGroup: {}
  547. `,
  548. }, {
  549. desc: "map fields not set",
  550. input: &pb3.Maps{},
  551. want: "\n",
  552. }, {
  553. desc: "map fields set to empty",
  554. input: &pb3.Maps{
  555. Int32ToStr: map[int32]string{},
  556. BoolToUint32: map[bool]uint32{},
  557. Uint64ToEnum: map[uint64]pb3.Enum{},
  558. StrToNested: map[string]*pb3.Nested{},
  559. StrToOneofs: map[string]*pb3.Oneofs{},
  560. },
  561. want: "\n",
  562. }, {
  563. desc: "map fields 1",
  564. input: &pb3.Maps{
  565. Int32ToStr: map[int32]string{
  566. -101: "-101",
  567. 0xff: "0xff",
  568. 0: "zero",
  569. },
  570. BoolToUint32: map[bool]uint32{
  571. true: 42,
  572. false: 101,
  573. },
  574. },
  575. want: `int32_to_str: {
  576. key: -101
  577. value: "-101"
  578. }
  579. int32_to_str: {
  580. key: 0
  581. value: "zero"
  582. }
  583. int32_to_str: {
  584. key: 255
  585. value: "0xff"
  586. }
  587. bool_to_uint32: {
  588. key: false
  589. value: 101
  590. }
  591. bool_to_uint32: {
  592. key: true
  593. value: 42
  594. }
  595. `,
  596. }, {
  597. desc: "map fields 2",
  598. input: &pb3.Maps{
  599. Uint64ToEnum: map[uint64]pb3.Enum{
  600. 1: pb3.Enum_ONE,
  601. 2: pb3.Enum_TWO,
  602. 10: pb3.Enum_TEN,
  603. 47: 47,
  604. },
  605. },
  606. want: `uint64_to_enum: {
  607. key: 1
  608. value: ONE
  609. }
  610. uint64_to_enum: {
  611. key: 2
  612. value: TWO
  613. }
  614. uint64_to_enum: {
  615. key: 10
  616. value: TEN
  617. }
  618. uint64_to_enum: {
  619. key: 47
  620. value: 47
  621. }
  622. `,
  623. }, {
  624. desc: "map fields 3",
  625. input: &pb3.Maps{
  626. StrToNested: map[string]*pb3.Nested{
  627. "nested": &pb3.Nested{
  628. SString: "nested in a map",
  629. },
  630. },
  631. },
  632. want: `str_to_nested: {
  633. key: "nested"
  634. value: {
  635. s_string: "nested in a map"
  636. }
  637. }
  638. `,
  639. }, {
  640. desc: "map fields 4",
  641. input: &pb3.Maps{
  642. StrToOneofs: map[string]*pb3.Oneofs{
  643. "string": &pb3.Oneofs{
  644. Union: &pb3.Oneofs_OneofString{
  645. OneofString: "hello",
  646. },
  647. },
  648. "nested": &pb3.Oneofs{
  649. Union: &pb3.Oneofs_OneofNested{
  650. OneofNested: &pb3.Nested{
  651. SString: "nested oneof in map field value",
  652. },
  653. },
  654. },
  655. },
  656. },
  657. want: `str_to_oneofs: {
  658. key: "nested"
  659. value: {
  660. oneof_nested: {
  661. s_string: "nested oneof in map field value"
  662. }
  663. }
  664. }
  665. str_to_oneofs: {
  666. key: "string"
  667. value: {
  668. oneof_string: "hello"
  669. }
  670. }
  671. `,
  672. }, {
  673. desc: "map field contains nil value",
  674. input: &pb3.Maps{
  675. StrToNested: map[string]*pb3.Nested{
  676. "nil": nil,
  677. },
  678. },
  679. want: `str_to_nested: {
  680. key: "nil"
  681. value: {}
  682. }
  683. `,
  684. }, {
  685. desc: "proto2 required fields not set",
  686. input: &pb2.Requireds{},
  687. want: "\n",
  688. wantErr: true,
  689. }, {
  690. desc: "proto2 required fields partially set",
  691. input: &pb2.Requireds{
  692. ReqBool: scalar.Bool(false),
  693. ReqSfixed64: scalar.Int64(0xbeefcafe),
  694. ReqDouble: scalar.Float64(math.NaN()),
  695. ReqString: scalar.String("hello"),
  696. ReqEnum: pb2.Enum_ONE.Enum(),
  697. },
  698. want: `req_bool: false
  699. req_sfixed64: 3203386110
  700. req_double: nan
  701. req_string: "hello"
  702. req_enum: ONE
  703. `,
  704. wantErr: true,
  705. }, {
  706. desc: "proto2 required fields all set",
  707. input: &pb2.Requireds{
  708. ReqBool: scalar.Bool(false),
  709. ReqSfixed64: scalar.Int64(0),
  710. ReqDouble: scalar.Float64(1.23),
  711. ReqString: scalar.String(""),
  712. ReqEnum: pb2.Enum_ONE.Enum(),
  713. ReqNested: &pb2.Nested{},
  714. },
  715. want: `req_bool: false
  716. req_sfixed64: 0
  717. req_double: 1.23
  718. req_string: ""
  719. req_enum: ONE
  720. req_nested: {}
  721. `,
  722. }, {
  723. desc: "indirect required field",
  724. input: &pb2.IndirectRequired{
  725. OptNested: &pb2.NestedWithRequired{},
  726. },
  727. want: "opt_nested: {}\n",
  728. wantErr: true,
  729. }, {
  730. desc: "indirect required field in empty repeated",
  731. input: &pb2.IndirectRequired{
  732. RptNested: []*pb2.NestedWithRequired{},
  733. },
  734. want: "\n",
  735. }, {
  736. desc: "indirect required field in repeated",
  737. input: &pb2.IndirectRequired{
  738. RptNested: []*pb2.NestedWithRequired{
  739. &pb2.NestedWithRequired{},
  740. },
  741. },
  742. want: "rpt_nested: {}\n",
  743. wantErr: true,
  744. }, {
  745. desc: "indirect required field in empty map",
  746. input: &pb2.IndirectRequired{
  747. StrToNested: map[string]*pb2.NestedWithRequired{},
  748. },
  749. want: "\n",
  750. }, {
  751. desc: "indirect required field in map",
  752. input: &pb2.IndirectRequired{
  753. StrToNested: map[string]*pb2.NestedWithRequired{
  754. "fail": &pb2.NestedWithRequired{},
  755. },
  756. },
  757. want: `str_to_nested: {
  758. key: "fail"
  759. value: {}
  760. }
  761. `,
  762. wantErr: true,
  763. }, {
  764. desc: "indirect required field in oneof",
  765. input: &pb2.IndirectRequired{
  766. Union: &pb2.IndirectRequired_OneofNested{
  767. OneofNested: &pb2.NestedWithRequired{},
  768. },
  769. },
  770. want: "oneof_nested: {}\n",
  771. wantErr: true,
  772. }, {
  773. desc: "unknown varint and fixed types",
  774. input: &pb2.Scalars{
  775. OptString: scalar.String("this message contains unknown fields"),
  776. XXX_unrecognized: pack.Message{
  777. pack.Tag{101, pack.VarintType}, pack.Bool(true),
  778. pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
  779. pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
  780. pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
  781. }.Marshal(),
  782. },
  783. want: `opt_string: "this message contains unknown fields"
  784. 101: 1
  785. 102: 255
  786. 103: 47
  787. 104: 3735928559
  788. `,
  789. }, {
  790. desc: "unknown length-delimited",
  791. input: &pb2.Scalars{
  792. XXX_unrecognized: pack.Message{
  793. pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
  794. pack.Tag{102, pack.BytesType}, pack.String("hello world"),
  795. pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
  796. }.Marshal(),
  797. },
  798. want: `101: "\x01\x00"
  799. 102: "hello world"
  800. 103: "世界"
  801. `,
  802. }, {
  803. desc: "unknown group type",
  804. input: &pb2.Scalars{
  805. XXX_unrecognized: pack.Message{
  806. pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
  807. pack.Tag{102, pack.StartGroupType},
  808. pack.Tag{101, pack.VarintType}, pack.Bool(false),
  809. pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
  810. pack.Tag{102, pack.EndGroupType},
  811. }.Marshal(),
  812. },
  813. want: `101: {}
  814. 102: {
  815. 101: 0
  816. 102: "inside a group"
  817. }
  818. `,
  819. }, {
  820. desc: "unknown unpack repeated field",
  821. input: &pb2.Scalars{
  822. XXX_unrecognized: pack.Message{
  823. pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
  824. pack.Tag{102, pack.BytesType}, pack.String("hello"),
  825. pack.Tag{101, pack.VarintType}, pack.Bool(true),
  826. pack.Tag{102, pack.BytesType}, pack.String("世界"),
  827. }.Marshal(),
  828. },
  829. want: `101: "\x01\x00\x01"
  830. 101: 1
  831. 102: "hello"
  832. 102: "世界"
  833. `,
  834. }, {
  835. desc: "extensions of non-repeated fields",
  836. input: func() proto.Message {
  837. m := &pb2.Extensions{
  838. OptString: scalar.String("non-extension field"),
  839. OptBool: scalar.Bool(true),
  840. OptInt32: scalar.Int32(42),
  841. }
  842. setExtension(m, pb2.E_OptExtBool, true)
  843. setExtension(m, pb2.E_OptExtString, "extension field")
  844. setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
  845. setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
  846. OptString: scalar.String("nested in an extension"),
  847. OptNested: &pb2.Nested{
  848. OptString: scalar.String("another nested in an extension"),
  849. },
  850. })
  851. return m
  852. }(),
  853. want: `opt_string: "non-extension field"
  854. opt_bool: true
  855. opt_int32: 42
  856. [pb2.opt_ext_bool]: true
  857. [pb2.opt_ext_enum]: TEN
  858. [pb2.opt_ext_nested]: {
  859. opt_string: "nested in an extension"
  860. opt_nested: {
  861. opt_string: "another nested in an extension"
  862. }
  863. }
  864. [pb2.opt_ext_string]: "extension field"
  865. `,
  866. }, {
  867. desc: "extension message field set to nil",
  868. input: func() proto.Message {
  869. m := &pb2.Extensions{}
  870. setExtension(m, pb2.E_OptExtNested, nil)
  871. return m
  872. }(),
  873. want: "\n",
  874. }, {
  875. desc: "extensions of repeated fields",
  876. input: func() proto.Message {
  877. m := &pb2.Extensions{}
  878. setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  879. setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
  880. setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
  881. &pb2.Nested{OptString: scalar.String("one")},
  882. &pb2.Nested{OptString: scalar.String("two")},
  883. &pb2.Nested{OptString: scalar.String("three")},
  884. })
  885. return m
  886. }(),
  887. want: `[pb2.rpt_ext_enum]: TEN
  888. [pb2.rpt_ext_enum]: 101
  889. [pb2.rpt_ext_enum]: ONE
  890. [pb2.rpt_ext_fixed32]: 42
  891. [pb2.rpt_ext_fixed32]: 47
  892. [pb2.rpt_ext_nested]: {
  893. opt_string: "one"
  894. }
  895. [pb2.rpt_ext_nested]: {
  896. opt_string: "two"
  897. }
  898. [pb2.rpt_ext_nested]: {
  899. opt_string: "three"
  900. }
  901. `,
  902. }, {
  903. desc: "extensions of non-repeated fields in another message",
  904. input: func() proto.Message {
  905. m := &pb2.Extensions{}
  906. setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
  907. setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
  908. setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
  909. setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
  910. OptString: scalar.String("nested in an extension"),
  911. OptNested: &pb2.Nested{
  912. OptString: scalar.String("another nested in an extension"),
  913. },
  914. })
  915. return m
  916. }(),
  917. want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
  918. [pb2.ExtensionsContainer.opt_ext_enum]: TEN
  919. [pb2.ExtensionsContainer.opt_ext_nested]: {
  920. opt_string: "nested in an extension"
  921. opt_nested: {
  922. opt_string: "another nested in an extension"
  923. }
  924. }
  925. [pb2.ExtensionsContainer.opt_ext_string]: "extension field"
  926. `,
  927. }, {
  928. desc: "extensions of repeated fields in another message",
  929. input: func() proto.Message {
  930. m := &pb2.Extensions{
  931. OptString: scalar.String("non-extension field"),
  932. OptBool: scalar.Bool(true),
  933. OptInt32: scalar.Int32(42),
  934. }
  935. setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  936. setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
  937. setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
  938. &pb2.Nested{OptString: scalar.String("one")},
  939. &pb2.Nested{OptString: scalar.String("two")},
  940. &pb2.Nested{OptString: scalar.String("three")},
  941. })
  942. return m
  943. }(),
  944. want: `opt_string: "non-extension field"
  945. opt_bool: true
  946. opt_int32: 42
  947. [pb2.ExtensionsContainer.rpt_ext_enum]: TEN
  948. [pb2.ExtensionsContainer.rpt_ext_enum]: 101
  949. [pb2.ExtensionsContainer.rpt_ext_enum]: ONE
  950. [pb2.ExtensionsContainer.rpt_ext_nested]: {
  951. opt_string: "one"
  952. }
  953. [pb2.ExtensionsContainer.rpt_ext_nested]: {
  954. opt_string: "two"
  955. }
  956. [pb2.ExtensionsContainer.rpt_ext_nested]: {
  957. opt_string: "three"
  958. }
  959. [pb2.ExtensionsContainer.rpt_ext_string]: "hello"
  960. [pb2.ExtensionsContainer.rpt_ext_string]: "world"
  961. `,
  962. }, {
  963. desc: "MessageSet",
  964. input: func() proto.Message {
  965. m := &pb2.MessageSet{}
  966. setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
  967. OptString: scalar.String("a messageset extension"),
  968. })
  969. setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
  970. OptString: scalar.String("not a messageset extension"),
  971. })
  972. setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
  973. OptString: scalar.String("just a regular extension"),
  974. })
  975. return m
  976. }(),
  977. want: `[pb2.MessageSetExtension]: {
  978. opt_string: "a messageset extension"
  979. }
  980. [pb2.MessageSetExtension.ext_nested]: {
  981. opt_string: "just a regular extension"
  982. }
  983. [pb2.MessageSetExtension.not_message_set_extension]: {
  984. opt_string: "not a messageset extension"
  985. }
  986. `,
  987. }, {
  988. desc: "not real MessageSet 1",
  989. input: func() proto.Message {
  990. m := &pb2.FakeMessageSet{}
  991. setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
  992. OptString: scalar.String("not a messageset extension"),
  993. })
  994. return m
  995. }(),
  996. want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
  997. opt_string: "not a messageset extension"
  998. }
  999. `,
  1000. }, {
  1001. desc: "not real MessageSet 2",
  1002. input: func() proto.Message {
  1003. m := &pb2.MessageSet{}
  1004. setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1005. OptString: scalar.String("another not a messageset extension"),
  1006. })
  1007. return m
  1008. }(),
  1009. want: `[pb2.message_set_extension]: {
  1010. opt_string: "another not a messageset extension"
  1011. }
  1012. `,
  1013. }, {
  1014. desc: "Any not expanded",
  1015. mo: textpb.MarshalOptions{
  1016. Resolver: preg.NewTypes(),
  1017. },
  1018. input: func() proto.Message {
  1019. m := &pb2.Nested{
  1020. OptString: scalar.String("embedded inside Any"),
  1021. OptNested: &pb2.Nested{
  1022. OptString: scalar.String("inception"),
  1023. },
  1024. }
  1025. // TODO: Switch to V2 marshal when ready.
  1026. b, err := protoV1.Marshal(m)
  1027. if err != nil {
  1028. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1029. }
  1030. return wrapV1Message(&anypb.Any{
  1031. TypeUrl: "pb2.Nested",
  1032. Value: b,
  1033. })
  1034. }(),
  1035. want: `type_url: "pb2.Nested"
  1036. value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
  1037. `,
  1038. }, {
  1039. desc: "Any expanded",
  1040. mo: textpb.MarshalOptions{
  1041. Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
  1042. },
  1043. input: func() proto.Message {
  1044. m := &pb2.Nested{
  1045. OptString: scalar.String("embedded inside Any"),
  1046. OptNested: &pb2.Nested{
  1047. OptString: scalar.String("inception"),
  1048. },
  1049. }
  1050. // TODO: Switch to V2 marshal when ready.
  1051. b, err := protoV1.Marshal(m)
  1052. if err != nil {
  1053. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1054. }
  1055. return wrapV1Message(&anypb.Any{
  1056. TypeUrl: "foo/pb2.Nested",
  1057. Value: b,
  1058. })
  1059. }(),
  1060. want: `[foo/pb2.Nested]: {
  1061. opt_string: "embedded inside Any"
  1062. opt_nested: {
  1063. opt_string: "inception"
  1064. }
  1065. }
  1066. `,
  1067. }, {
  1068. desc: "Any expanded with missing required error",
  1069. mo: textpb.MarshalOptions{
  1070. Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
  1071. },
  1072. input: func() proto.Message {
  1073. m := &pb2.PartialRequired{
  1074. OptString: scalar.String("embedded inside Any"),
  1075. }
  1076. // TODO: Switch to V2 marshal when ready.
  1077. b, err := protoV1.Marshal(m)
  1078. // Ignore required not set error.
  1079. if _, ok := err.(*protoV1.RequiredNotSetError); !ok {
  1080. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1081. }
  1082. return wrapV1Message(&anypb.Any{
  1083. TypeUrl: string(m.ProtoReflect().Type().FullName()),
  1084. Value: b,
  1085. })
  1086. }(),
  1087. want: `[pb2.PartialRequired]: {
  1088. opt_string: "embedded inside Any"
  1089. }
  1090. `,
  1091. wantErr: true,
  1092. }, {
  1093. desc: "Any with invalid value",
  1094. mo: textpb.MarshalOptions{
  1095. Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
  1096. },
  1097. input: wrapV1Message(&anypb.Any{
  1098. TypeUrl: "foo/pb2.Nested",
  1099. Value: dhex("80"),
  1100. }),
  1101. want: `type_url: "foo/pb2.Nested"
  1102. value: "\x80"
  1103. `,
  1104. }}
  1105. for _, tt := range tests {
  1106. tt := tt
  1107. t.Run(tt.desc, func(t *testing.T) {
  1108. t.Parallel()
  1109. b, err := tt.mo.Marshal(tt.input)
  1110. if err != nil && !tt.wantErr {
  1111. t.Errorf("Marshal() returned error: %v\n", err)
  1112. }
  1113. if err == nil && tt.wantErr {
  1114. t.Error("Marshal() got nil error, want error\n")
  1115. }
  1116. got := string(b)
  1117. if tt.want != "" && got != tt.want {
  1118. t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
  1119. if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
  1120. t.Errorf("Marshal() diff -want +got\n%v\n", diff)
  1121. }
  1122. }
  1123. })
  1124. }
  1125. }