encode_test.go 23 KB

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