encode_test.go 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  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 prototext_test
  5. import (
  6. "bytes"
  7. "encoding/hex"
  8. "math"
  9. "strings"
  10. "testing"
  11. "github.com/google/go-cmp/cmp"
  12. "github.com/google/go-cmp/cmp/cmpopts"
  13. "google.golang.org/protobuf/encoding/prototext"
  14. "google.golang.org/protobuf/internal/detrand"
  15. "google.golang.org/protobuf/internal/encoding/pack"
  16. "google.golang.org/protobuf/internal/encoding/wire"
  17. pimpl "google.golang.org/protobuf/internal/impl"
  18. "google.golang.org/protobuf/internal/scalar"
  19. "google.golang.org/protobuf/proto"
  20. preg "google.golang.org/protobuf/reflect/protoregistry"
  21. "google.golang.org/protobuf/runtime/protoiface"
  22. "google.golang.org/protobuf/encoding/testprotos/pb2"
  23. "google.golang.org/protobuf/encoding/testprotos/pb3"
  24. "google.golang.org/protobuf/types/known/anypb"
  25. )
  26. func init() {
  27. // Disable detrand to enable direct comparisons on outputs.
  28. detrand.Disable()
  29. }
  30. // splitLines is a cmpopts.Option for comparing strings with line breaks.
  31. var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
  32. return strings.Split(s, "\n")
  33. })
  34. func pb2Enum(i int32) *pb2.Enum {
  35. p := new(pb2.Enum)
  36. *p = pb2.Enum(i)
  37. return p
  38. }
  39. func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
  40. p := new(pb2.Enums_NestedEnum)
  41. *p = pb2.Enums_NestedEnum(i)
  42. return p
  43. }
  44. func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
  45. knownFields := m.ProtoReflect().KnownFields()
  46. extTypes := knownFields.ExtensionTypes()
  47. extTypes.Register(xd.Type)
  48. if val == nil {
  49. return
  50. }
  51. pval := xd.Type.ValueOf(val)
  52. knownFields.Set(wire.Number(xd.Field), pval)
  53. }
  54. // dhex decodes a hex-string and returns the bytes and panics if s is invalid.
  55. func dhex(s string) []byte {
  56. b, err := hex.DecodeString(s)
  57. if err != nil {
  58. panic(err)
  59. }
  60. return b
  61. }
  62. func TestMarshal(t *testing.T) {
  63. tests := []struct {
  64. desc string
  65. mo prototext.MarshalOptions
  66. input proto.Message
  67. want string
  68. wantErr bool // TODO: Verify error message content.
  69. }{{
  70. desc: "proto2 optional scalars not set",
  71. input: &pb2.Scalars{},
  72. want: "\n",
  73. }, {
  74. desc: "proto3 scalars not set",
  75. input: &pb3.Scalars{},
  76. want: "\n",
  77. }, {
  78. desc: "proto2 optional scalars set to zero values",
  79. input: &pb2.Scalars{
  80. OptBool: scalar.Bool(false),
  81. OptInt32: scalar.Int32(0),
  82. OptInt64: scalar.Int64(0),
  83. OptUint32: scalar.Uint32(0),
  84. OptUint64: scalar.Uint64(0),
  85. OptSint32: scalar.Int32(0),
  86. OptSint64: scalar.Int64(0),
  87. OptFixed32: scalar.Uint32(0),
  88. OptFixed64: scalar.Uint64(0),
  89. OptSfixed32: scalar.Int32(0),
  90. OptSfixed64: scalar.Int64(0),
  91. OptFloat: scalar.Float32(0),
  92. OptDouble: scalar.Float64(0),
  93. OptBytes: []byte{},
  94. OptString: scalar.String(""),
  95. },
  96. want: `opt_bool: false
  97. opt_int32: 0
  98. opt_int64: 0
  99. opt_uint32: 0
  100. opt_uint64: 0
  101. opt_sint32: 0
  102. opt_sint64: 0
  103. opt_fixed32: 0
  104. opt_fixed64: 0
  105. opt_sfixed32: 0
  106. opt_sfixed64: 0
  107. opt_float: 0
  108. opt_double: 0
  109. opt_bytes: ""
  110. opt_string: ""
  111. `,
  112. }, {
  113. desc: "proto3 scalars set to zero values",
  114. input: &pb3.Scalars{
  115. SBool: false,
  116. SInt32: 0,
  117. SInt64: 0,
  118. SUint32: 0,
  119. SUint64: 0,
  120. SSint32: 0,
  121. SSint64: 0,
  122. SFixed32: 0,
  123. SFixed64: 0,
  124. SSfixed32: 0,
  125. SSfixed64: 0,
  126. SFloat: 0,
  127. SDouble: 0,
  128. SBytes: []byte{},
  129. SString: "",
  130. },
  131. want: "\n",
  132. }, {
  133. desc: "proto2 optional scalars set to some values",
  134. input: &pb2.Scalars{
  135. OptBool: scalar.Bool(true),
  136. OptInt32: scalar.Int32(0xff),
  137. OptInt64: scalar.Int64(0xdeadbeef),
  138. OptUint32: scalar.Uint32(47),
  139. OptUint64: scalar.Uint64(0xdeadbeef),
  140. OptSint32: scalar.Int32(-1001),
  141. OptSint64: scalar.Int64(-0xffff),
  142. OptFixed64: scalar.Uint64(64),
  143. OptSfixed32: scalar.Int32(-32),
  144. OptFloat: scalar.Float32(1.02),
  145. OptDouble: scalar.Float64(1.0199999809265137),
  146. OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
  147. OptString: scalar.String("谷歌"),
  148. },
  149. want: `opt_bool: true
  150. opt_int32: 255
  151. opt_int64: 3735928559
  152. opt_uint32: 47
  153. opt_uint64: 3735928559
  154. opt_sint32: -1001
  155. opt_sint64: -65535
  156. opt_fixed64: 64
  157. opt_sfixed32: -32
  158. opt_float: 1.02
  159. opt_double: 1.0199999809265137
  160. opt_bytes: "谷歌"
  161. opt_string: "谷歌"
  162. `,
  163. }, {
  164. desc: "string with invalid UTF-8",
  165. input: &pb3.Scalars{
  166. SString: "abc\xff",
  167. },
  168. want: `s_string: "abc\xff"
  169. `,
  170. wantErr: true,
  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: "proto3 nested message contains invalid UTF-8",
  367. input: &pb3.Nests{
  368. SNested: &pb3.Nested{
  369. SString: "abc\xff",
  370. },
  371. },
  372. want: `s_nested: {
  373. s_string: "abc\xff"
  374. }
  375. `,
  376. wantErr: true,
  377. }, {
  378. desc: "oneof not set",
  379. input: &pb3.Oneofs{},
  380. want: "\n",
  381. }, {
  382. desc: "oneof set to empty string",
  383. input: &pb3.Oneofs{
  384. Union: &pb3.Oneofs_OneofString{},
  385. },
  386. want: `oneof_string: ""
  387. `,
  388. }, {
  389. desc: "oneof set to string",
  390. input: &pb3.Oneofs{
  391. Union: &pb3.Oneofs_OneofString{
  392. OneofString: "hello",
  393. },
  394. },
  395. want: `oneof_string: "hello"
  396. `,
  397. }, {
  398. desc: "oneof set to enum",
  399. input: &pb3.Oneofs{
  400. Union: &pb3.Oneofs_OneofEnum{
  401. OneofEnum: pb3.Enum_ZERO,
  402. },
  403. },
  404. want: `oneof_enum: ZERO
  405. `,
  406. }, {
  407. desc: "oneof set to empty message",
  408. input: &pb3.Oneofs{
  409. Union: &pb3.Oneofs_OneofNested{
  410. OneofNested: &pb3.Nested{},
  411. },
  412. },
  413. want: "oneof_nested: {}\n",
  414. }, {
  415. desc: "oneof set to message",
  416. input: &pb3.Oneofs{
  417. Union: &pb3.Oneofs_OneofNested{
  418. OneofNested: &pb3.Nested{
  419. SString: "nested message",
  420. },
  421. },
  422. },
  423. want: `oneof_nested: {
  424. s_string: "nested message"
  425. }
  426. `,
  427. }, {
  428. desc: "repeated fields not set",
  429. input: &pb2.Repeats{},
  430. want: "\n",
  431. }, {
  432. desc: "repeated fields set to empty slices",
  433. input: &pb2.Repeats{
  434. RptBool: []bool{},
  435. RptInt32: []int32{},
  436. RptInt64: []int64{},
  437. RptUint32: []uint32{},
  438. RptUint64: []uint64{},
  439. RptFloat: []float32{},
  440. RptDouble: []float64{},
  441. RptBytes: [][]byte{},
  442. },
  443. want: "\n",
  444. }, {
  445. desc: "repeated fields set to some values",
  446. input: &pb2.Repeats{
  447. RptBool: []bool{true, false, true, true},
  448. RptInt32: []int32{1, 6, 0, 0},
  449. RptInt64: []int64{-64, 47},
  450. RptUint32: []uint32{0xff, 0xffff},
  451. RptUint64: []uint64{0xdeadbeef},
  452. RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
  453. RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
  454. RptString: []string{"hello", "世界"},
  455. RptBytes: [][]byte{
  456. []byte("hello"),
  457. []byte("\xe4\xb8\x96\xe7\x95\x8c"),
  458. },
  459. },
  460. want: `rpt_bool: true
  461. rpt_bool: false
  462. rpt_bool: true
  463. rpt_bool: true
  464. rpt_int32: 1
  465. rpt_int32: 6
  466. rpt_int32: 0
  467. rpt_int32: 0
  468. rpt_int64: -64
  469. rpt_int64: 47
  470. rpt_uint32: 255
  471. rpt_uint32: 65535
  472. rpt_uint64: 3735928559
  473. rpt_float: nan
  474. rpt_float: inf
  475. rpt_float: -inf
  476. rpt_float: 1.034
  477. rpt_double: nan
  478. rpt_double: inf
  479. rpt_double: -inf
  480. rpt_double: 1.23e-308
  481. rpt_string: "hello"
  482. rpt_string: "世界"
  483. rpt_bytes: "hello"
  484. rpt_bytes: "世界"
  485. `,
  486. }, {
  487. desc: "repeated contains invalid UTF-8",
  488. input: &pb2.Repeats{
  489. RptString: []string{"abc\xff"},
  490. },
  491. want: `rpt_string: "abc\xff"
  492. `,
  493. wantErr: true,
  494. }, {
  495. desc: "repeated enums",
  496. input: &pb2.Enums{
  497. RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
  498. RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
  499. },
  500. want: `rpt_enum: ONE
  501. rpt_enum: TWO
  502. rpt_enum: TEN
  503. rpt_enum: 42
  504. rpt_nested_enum: DOS
  505. rpt_nested_enum: 47
  506. rpt_nested_enum: DIEZ
  507. `,
  508. }, {
  509. desc: "repeated messages set to empty",
  510. input: &pb2.Nests{
  511. RptNested: []*pb2.Nested{},
  512. Rptgroup: []*pb2.Nests_RptGroup{},
  513. },
  514. want: "\n",
  515. }, {
  516. desc: "repeated messages",
  517. input: &pb2.Nests{
  518. RptNested: []*pb2.Nested{
  519. {
  520. OptString: scalar.String("repeat nested one"),
  521. },
  522. {
  523. OptString: scalar.String("repeat nested two"),
  524. OptNested: &pb2.Nested{
  525. OptString: scalar.String("inside repeat nested two"),
  526. },
  527. },
  528. {},
  529. },
  530. },
  531. want: `rpt_nested: {
  532. opt_string: "repeat nested one"
  533. }
  534. rpt_nested: {
  535. opt_string: "repeat nested two"
  536. opt_nested: {
  537. opt_string: "inside repeat nested two"
  538. }
  539. }
  540. rpt_nested: {}
  541. `,
  542. }, {
  543. desc: "repeated messages contains nil value",
  544. input: &pb2.Nests{
  545. RptNested: []*pb2.Nested{nil, {}},
  546. },
  547. want: `rpt_nested: {}
  548. rpt_nested: {}
  549. `,
  550. }, {
  551. desc: "repeated groups",
  552. input: &pb2.Nests{
  553. Rptgroup: []*pb2.Nests_RptGroup{
  554. {
  555. RptString: []string{"hello", "world"},
  556. },
  557. {},
  558. nil,
  559. },
  560. },
  561. want: `RptGroup: {
  562. rpt_string: "hello"
  563. rpt_string: "world"
  564. }
  565. RptGroup: {}
  566. RptGroup: {}
  567. `,
  568. }, {
  569. desc: "map fields not set",
  570. input: &pb3.Maps{},
  571. want: "\n",
  572. }, {
  573. desc: "map fields set to empty",
  574. input: &pb3.Maps{
  575. Int32ToStr: map[int32]string{},
  576. BoolToUint32: map[bool]uint32{},
  577. Uint64ToEnum: map[uint64]pb3.Enum{},
  578. StrToNested: map[string]*pb3.Nested{},
  579. StrToOneofs: map[string]*pb3.Oneofs{},
  580. },
  581. want: "\n",
  582. }, {
  583. desc: "map fields 1",
  584. input: &pb3.Maps{
  585. Int32ToStr: map[int32]string{
  586. -101: "-101",
  587. 0xff: "0xff",
  588. 0: "zero",
  589. },
  590. BoolToUint32: map[bool]uint32{
  591. true: 42,
  592. false: 101,
  593. },
  594. },
  595. want: `int32_to_str: {
  596. key: -101
  597. value: "-101"
  598. }
  599. int32_to_str: {
  600. key: 0
  601. value: "zero"
  602. }
  603. int32_to_str: {
  604. key: 255
  605. value: "0xff"
  606. }
  607. bool_to_uint32: {
  608. key: false
  609. value: 101
  610. }
  611. bool_to_uint32: {
  612. key: true
  613. value: 42
  614. }
  615. `,
  616. }, {
  617. desc: "map fields 2",
  618. input: &pb3.Maps{
  619. Uint64ToEnum: map[uint64]pb3.Enum{
  620. 1: pb3.Enum_ONE,
  621. 2: pb3.Enum_TWO,
  622. 10: pb3.Enum_TEN,
  623. 47: 47,
  624. },
  625. },
  626. want: `uint64_to_enum: {
  627. key: 1
  628. value: ONE
  629. }
  630. uint64_to_enum: {
  631. key: 2
  632. value: TWO
  633. }
  634. uint64_to_enum: {
  635. key: 10
  636. value: TEN
  637. }
  638. uint64_to_enum: {
  639. key: 47
  640. value: 47
  641. }
  642. `,
  643. }, {
  644. desc: "map fields 3",
  645. input: &pb3.Maps{
  646. StrToNested: map[string]*pb3.Nested{
  647. "nested": &pb3.Nested{
  648. SString: "nested in a map",
  649. },
  650. },
  651. },
  652. want: `str_to_nested: {
  653. key: "nested"
  654. value: {
  655. s_string: "nested in a map"
  656. }
  657. }
  658. `,
  659. }, {
  660. desc: "map fields 4",
  661. input: &pb3.Maps{
  662. StrToOneofs: map[string]*pb3.Oneofs{
  663. "string": &pb3.Oneofs{
  664. Union: &pb3.Oneofs_OneofString{
  665. OneofString: "hello",
  666. },
  667. },
  668. "nested": &pb3.Oneofs{
  669. Union: &pb3.Oneofs_OneofNested{
  670. OneofNested: &pb3.Nested{
  671. SString: "nested oneof in map field value",
  672. },
  673. },
  674. },
  675. },
  676. },
  677. want: `str_to_oneofs: {
  678. key: "nested"
  679. value: {
  680. oneof_nested: {
  681. s_string: "nested oneof in map field value"
  682. }
  683. }
  684. }
  685. str_to_oneofs: {
  686. key: "string"
  687. value: {
  688. oneof_string: "hello"
  689. }
  690. }
  691. `,
  692. }, {
  693. desc: "map field value contains invalid UTF-8",
  694. input: &pb3.Maps{
  695. Int32ToStr: map[int32]string{
  696. 101: "abc\xff",
  697. },
  698. },
  699. want: `int32_to_str: {
  700. key: 101
  701. value: "abc\xff"
  702. }
  703. `,
  704. wantErr: true,
  705. }, {
  706. desc: "map field key contains invalid UTF-8",
  707. input: &pb3.Maps{
  708. StrToNested: map[string]*pb3.Nested{
  709. "abc\xff": {},
  710. },
  711. },
  712. want: `str_to_nested: {
  713. key: "abc\xff"
  714. value: {}
  715. }
  716. `,
  717. wantErr: true,
  718. }, {
  719. desc: "map field contains nil value",
  720. input: &pb3.Maps{
  721. StrToNested: map[string]*pb3.Nested{
  722. "nil": nil,
  723. },
  724. },
  725. want: `str_to_nested: {
  726. key: "nil"
  727. value: {}
  728. }
  729. `,
  730. }, {
  731. desc: "required fields not set",
  732. input: &pb2.Requireds{},
  733. want: "\n",
  734. wantErr: true,
  735. }, {
  736. desc: "required fields partially set",
  737. input: &pb2.Requireds{
  738. ReqBool: scalar.Bool(false),
  739. ReqSfixed64: scalar.Int64(0xbeefcafe),
  740. ReqDouble: scalar.Float64(math.NaN()),
  741. ReqString: scalar.String("hello"),
  742. ReqEnum: pb2.Enum_ONE.Enum(),
  743. },
  744. want: `req_bool: false
  745. req_sfixed64: 3203386110
  746. req_double: nan
  747. req_string: "hello"
  748. req_enum: ONE
  749. `,
  750. wantErr: true,
  751. }, {
  752. desc: "required fields not set with AllowPartial",
  753. mo: prototext.MarshalOptions{AllowPartial: true},
  754. input: &pb2.Requireds{
  755. ReqBool: scalar.Bool(false),
  756. ReqSfixed64: scalar.Int64(0xbeefcafe),
  757. ReqDouble: scalar.Float64(math.NaN()),
  758. ReqString: scalar.String("hello"),
  759. ReqEnum: pb2.Enum_ONE.Enum(),
  760. },
  761. want: `req_bool: false
  762. req_sfixed64: 3203386110
  763. req_double: nan
  764. req_string: "hello"
  765. req_enum: ONE
  766. `,
  767. }, {
  768. desc: "required fields all set",
  769. input: &pb2.Requireds{
  770. ReqBool: scalar.Bool(false),
  771. ReqSfixed64: scalar.Int64(0),
  772. ReqDouble: scalar.Float64(1.23),
  773. ReqString: scalar.String(""),
  774. ReqEnum: pb2.Enum_ONE.Enum(),
  775. ReqNested: &pb2.Nested{},
  776. },
  777. want: `req_bool: false
  778. req_sfixed64: 0
  779. req_double: 1.23
  780. req_string: ""
  781. req_enum: ONE
  782. req_nested: {}
  783. `,
  784. }, {
  785. desc: "indirect required field",
  786. input: &pb2.IndirectRequired{
  787. OptNested: &pb2.NestedWithRequired{},
  788. },
  789. want: "opt_nested: {}\n",
  790. wantErr: true,
  791. }, {
  792. desc: "indirect required field with AllowPartial",
  793. mo: prototext.MarshalOptions{AllowPartial: true},
  794. input: &pb2.IndirectRequired{
  795. OptNested: &pb2.NestedWithRequired{},
  796. },
  797. want: "opt_nested: {}\n",
  798. }, {
  799. desc: "indirect required field in empty repeated",
  800. input: &pb2.IndirectRequired{
  801. RptNested: []*pb2.NestedWithRequired{},
  802. },
  803. want: "\n",
  804. }, {
  805. desc: "indirect required field in repeated",
  806. input: &pb2.IndirectRequired{
  807. RptNested: []*pb2.NestedWithRequired{
  808. &pb2.NestedWithRequired{},
  809. },
  810. },
  811. want: "rpt_nested: {}\n",
  812. wantErr: true,
  813. }, {
  814. desc: "indirect required field in repeated with AllowPartial",
  815. mo: prototext.MarshalOptions{AllowPartial: true},
  816. input: &pb2.IndirectRequired{
  817. RptNested: []*pb2.NestedWithRequired{
  818. &pb2.NestedWithRequired{},
  819. },
  820. },
  821. want: "rpt_nested: {}\n",
  822. }, {
  823. desc: "indirect required field in empty map",
  824. input: &pb2.IndirectRequired{
  825. StrToNested: map[string]*pb2.NestedWithRequired{},
  826. },
  827. want: "\n",
  828. }, {
  829. desc: "indirect required field in map",
  830. input: &pb2.IndirectRequired{
  831. StrToNested: map[string]*pb2.NestedWithRequired{
  832. "fail": &pb2.NestedWithRequired{},
  833. },
  834. },
  835. want: `str_to_nested: {
  836. key: "fail"
  837. value: {}
  838. }
  839. `,
  840. wantErr: true,
  841. }, {
  842. desc: "indirect required field in map with AllowPartial",
  843. mo: prototext.MarshalOptions{AllowPartial: true},
  844. input: &pb2.IndirectRequired{
  845. StrToNested: map[string]*pb2.NestedWithRequired{
  846. "fail": &pb2.NestedWithRequired{},
  847. },
  848. },
  849. want: `str_to_nested: {
  850. key: "fail"
  851. value: {}
  852. }
  853. `,
  854. }, {
  855. desc: "indirect required field in oneof",
  856. input: &pb2.IndirectRequired{
  857. Union: &pb2.IndirectRequired_OneofNested{
  858. OneofNested: &pb2.NestedWithRequired{},
  859. },
  860. },
  861. want: "oneof_nested: {}\n",
  862. wantErr: true,
  863. }, {
  864. desc: "indirect required field in oneof with AllowPartial",
  865. mo: prototext.MarshalOptions{AllowPartial: true},
  866. input: &pb2.IndirectRequired{
  867. Union: &pb2.IndirectRequired_OneofNested{
  868. OneofNested: &pb2.NestedWithRequired{},
  869. },
  870. },
  871. want: "oneof_nested: {}\n",
  872. }, {
  873. desc: "unknown varint and fixed types",
  874. input: &pb2.Scalars{
  875. OptString: scalar.String("this message contains unknown fields"),
  876. XXX_unrecognized: pack.Message{
  877. pack.Tag{101, pack.VarintType}, pack.Bool(true),
  878. pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
  879. pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
  880. pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
  881. }.Marshal(),
  882. },
  883. want: `opt_string: "this message contains unknown fields"
  884. 101: 1
  885. 102: 255
  886. 103: 47
  887. 104: 3735928559
  888. `,
  889. }, {
  890. desc: "unknown length-delimited",
  891. input: &pb2.Scalars{
  892. XXX_unrecognized: pack.Message{
  893. pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
  894. pack.Tag{102, pack.BytesType}, pack.String("hello world"),
  895. pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
  896. }.Marshal(),
  897. },
  898. want: `101: "\x01\x00"
  899. 102: "hello world"
  900. 103: "世界"
  901. `,
  902. }, {
  903. desc: "unknown group type",
  904. input: &pb2.Scalars{
  905. XXX_unrecognized: pack.Message{
  906. pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
  907. pack.Tag{102, pack.StartGroupType},
  908. pack.Tag{101, pack.VarintType}, pack.Bool(false),
  909. pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
  910. pack.Tag{102, pack.EndGroupType},
  911. }.Marshal(),
  912. },
  913. want: `101: {}
  914. 102: {
  915. 101: 0
  916. 102: "inside a group"
  917. }
  918. `,
  919. }, {
  920. desc: "unknown unpack repeated field",
  921. input: &pb2.Scalars{
  922. XXX_unrecognized: pack.Message{
  923. pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
  924. pack.Tag{102, pack.BytesType}, pack.String("hello"),
  925. pack.Tag{101, pack.VarintType}, pack.Bool(true),
  926. pack.Tag{102, pack.BytesType}, pack.String("世界"),
  927. }.Marshal(),
  928. },
  929. want: `101: "\x01\x00\x01"
  930. 101: 1
  931. 102: "hello"
  932. 102: "世界"
  933. `,
  934. }, {
  935. desc: "extensions of non-repeated fields",
  936. input: func() proto.Message {
  937. m := &pb2.Extensions{
  938. OptString: scalar.String("non-extension field"),
  939. OptBool: scalar.Bool(true),
  940. OptInt32: scalar.Int32(42),
  941. }
  942. setExtension(m, pb2.E_OptExtBool, true)
  943. setExtension(m, pb2.E_OptExtString, "extension field")
  944. setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
  945. setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
  946. OptString: scalar.String("nested in an extension"),
  947. OptNested: &pb2.Nested{
  948. OptString: scalar.String("another nested in an extension"),
  949. },
  950. })
  951. return m
  952. }(),
  953. want: `opt_string: "non-extension field"
  954. opt_bool: true
  955. opt_int32: 42
  956. [pb2.opt_ext_bool]: true
  957. [pb2.opt_ext_enum]: TEN
  958. [pb2.opt_ext_nested]: {
  959. opt_string: "nested in an extension"
  960. opt_nested: {
  961. opt_string: "another nested in an extension"
  962. }
  963. }
  964. [pb2.opt_ext_string]: "extension field"
  965. `,
  966. }, {
  967. desc: "extension field contains invalid UTF-8",
  968. input: func() proto.Message {
  969. m := &pb2.Extensions{}
  970. setExtension(m, pb2.E_OptExtString, "abc\xff")
  971. return m
  972. }(),
  973. want: `[pb2.opt_ext_string]: "abc\xff"
  974. `,
  975. wantErr: true,
  976. }, {
  977. desc: "extension partial returns error",
  978. input: func() proto.Message {
  979. m := &pb2.Extensions{}
  980. setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
  981. OptString: scalar.String("partial1"),
  982. })
  983. setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
  984. OptString: scalar.String("partial2"),
  985. })
  986. return m
  987. }(),
  988. want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
  989. opt_string: "partial2"
  990. }
  991. [pb2.opt_ext_partial]: {
  992. opt_string: "partial1"
  993. }
  994. `,
  995. wantErr: true,
  996. }, {
  997. desc: "extension partial with AllowPartial",
  998. mo: prototext.MarshalOptions{AllowPartial: true},
  999. input: func() proto.Message {
  1000. m := &pb2.Extensions{}
  1001. setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
  1002. OptString: scalar.String("partial1"),
  1003. })
  1004. return m
  1005. }(),
  1006. want: `[pb2.opt_ext_partial]: {
  1007. opt_string: "partial1"
  1008. }
  1009. `,
  1010. }, {
  1011. desc: "extension message field set to nil",
  1012. input: func() proto.Message {
  1013. m := &pb2.Extensions{}
  1014. setExtension(m, pb2.E_OptExtNested, nil)
  1015. return m
  1016. }(),
  1017. want: "\n",
  1018. }, {
  1019. desc: "extensions of repeated fields",
  1020. input: func() proto.Message {
  1021. m := &pb2.Extensions{}
  1022. setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  1023. setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
  1024. setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
  1025. &pb2.Nested{OptString: scalar.String("one")},
  1026. &pb2.Nested{OptString: scalar.String("two")},
  1027. &pb2.Nested{OptString: scalar.String("three")},
  1028. })
  1029. return m
  1030. }(),
  1031. want: `[pb2.rpt_ext_enum]: TEN
  1032. [pb2.rpt_ext_enum]: 101
  1033. [pb2.rpt_ext_enum]: ONE
  1034. [pb2.rpt_ext_fixed32]: 42
  1035. [pb2.rpt_ext_fixed32]: 47
  1036. [pb2.rpt_ext_nested]: {
  1037. opt_string: "one"
  1038. }
  1039. [pb2.rpt_ext_nested]: {
  1040. opt_string: "two"
  1041. }
  1042. [pb2.rpt_ext_nested]: {
  1043. opt_string: "three"
  1044. }
  1045. `,
  1046. }, {
  1047. desc: "extensions of non-repeated fields in another message",
  1048. input: func() proto.Message {
  1049. m := &pb2.Extensions{}
  1050. setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
  1051. setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
  1052. setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
  1053. setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
  1054. OptString: scalar.String("nested in an extension"),
  1055. OptNested: &pb2.Nested{
  1056. OptString: scalar.String("another nested in an extension"),
  1057. },
  1058. })
  1059. return m
  1060. }(),
  1061. want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
  1062. [pb2.ExtensionsContainer.opt_ext_enum]: TEN
  1063. [pb2.ExtensionsContainer.opt_ext_nested]: {
  1064. opt_string: "nested in an extension"
  1065. opt_nested: {
  1066. opt_string: "another nested in an extension"
  1067. }
  1068. }
  1069. [pb2.ExtensionsContainer.opt_ext_string]: "extension field"
  1070. `,
  1071. }, {
  1072. desc: "extensions of repeated fields in another message",
  1073. input: func() proto.Message {
  1074. m := &pb2.Extensions{
  1075. OptString: scalar.String("non-extension field"),
  1076. OptBool: scalar.Bool(true),
  1077. OptInt32: scalar.Int32(42),
  1078. }
  1079. setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  1080. setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
  1081. setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
  1082. &pb2.Nested{OptString: scalar.String("one")},
  1083. &pb2.Nested{OptString: scalar.String("two")},
  1084. &pb2.Nested{OptString: scalar.String("three")},
  1085. })
  1086. return m
  1087. }(),
  1088. want: `opt_string: "non-extension field"
  1089. opt_bool: true
  1090. opt_int32: 42
  1091. [pb2.ExtensionsContainer.rpt_ext_enum]: TEN
  1092. [pb2.ExtensionsContainer.rpt_ext_enum]: 101
  1093. [pb2.ExtensionsContainer.rpt_ext_enum]: ONE
  1094. [pb2.ExtensionsContainer.rpt_ext_nested]: {
  1095. opt_string: "one"
  1096. }
  1097. [pb2.ExtensionsContainer.rpt_ext_nested]: {
  1098. opt_string: "two"
  1099. }
  1100. [pb2.ExtensionsContainer.rpt_ext_nested]: {
  1101. opt_string: "three"
  1102. }
  1103. [pb2.ExtensionsContainer.rpt_ext_string]: "hello"
  1104. [pb2.ExtensionsContainer.rpt_ext_string]: "world"
  1105. `,
  1106. }, {
  1107. desc: "MessageSet",
  1108. input: func() proto.Message {
  1109. m := &pb2.MessageSet{}
  1110. setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
  1111. OptString: scalar.String("a messageset extension"),
  1112. })
  1113. setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
  1114. OptString: scalar.String("not a messageset extension"),
  1115. })
  1116. setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
  1117. OptString: scalar.String("just a regular extension"),
  1118. })
  1119. return m
  1120. }(),
  1121. want: `[pb2.MessageSetExtension]: {
  1122. opt_string: "a messageset extension"
  1123. }
  1124. [pb2.MessageSetExtension.ext_nested]: {
  1125. opt_string: "just a regular extension"
  1126. }
  1127. [pb2.MessageSetExtension.not_message_set_extension]: {
  1128. opt_string: "not a messageset extension"
  1129. }
  1130. `,
  1131. }, {
  1132. desc: "not real MessageSet 1",
  1133. input: func() proto.Message {
  1134. m := &pb2.FakeMessageSet{}
  1135. setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1136. OptString: scalar.String("not a messageset extension"),
  1137. })
  1138. return m
  1139. }(),
  1140. want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
  1141. opt_string: "not a messageset extension"
  1142. }
  1143. `,
  1144. }, {
  1145. desc: "not real MessageSet 2",
  1146. input: func() proto.Message {
  1147. m := &pb2.MessageSet{}
  1148. setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1149. OptString: scalar.String("another not a messageset extension"),
  1150. })
  1151. return m
  1152. }(),
  1153. want: `[pb2.message_set_extension]: {
  1154. opt_string: "another not a messageset extension"
  1155. }
  1156. `,
  1157. }, {
  1158. desc: "Any not expanded",
  1159. mo: prototext.MarshalOptions{
  1160. Resolver: preg.NewTypes(),
  1161. },
  1162. input: func() proto.Message {
  1163. m := &pb2.Nested{
  1164. OptString: scalar.String("embedded inside Any"),
  1165. OptNested: &pb2.Nested{
  1166. OptString: scalar.String("inception"),
  1167. },
  1168. }
  1169. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1170. if err != nil {
  1171. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1172. }
  1173. return &anypb.Any{
  1174. TypeUrl: "pb2.Nested",
  1175. Value: b,
  1176. }
  1177. }(),
  1178. want: `type_url: "pb2.Nested"
  1179. value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
  1180. `,
  1181. }, {
  1182. desc: "Any expanded",
  1183. mo: prototext.MarshalOptions{
  1184. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1185. },
  1186. input: func() proto.Message {
  1187. m := &pb2.Nested{
  1188. OptString: scalar.String("embedded inside Any"),
  1189. OptNested: &pb2.Nested{
  1190. OptString: scalar.String("inception"),
  1191. },
  1192. }
  1193. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1194. if err != nil {
  1195. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1196. }
  1197. return &anypb.Any{
  1198. TypeUrl: "foo/pb2.Nested",
  1199. Value: b,
  1200. }
  1201. }(),
  1202. want: `[foo/pb2.Nested]: {
  1203. opt_string: "embedded inside Any"
  1204. opt_nested: {
  1205. opt_string: "inception"
  1206. }
  1207. }
  1208. `,
  1209. }, {
  1210. desc: "Any expanded with missing required error",
  1211. mo: prototext.MarshalOptions{
  1212. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
  1213. },
  1214. input: func() proto.Message {
  1215. m := &pb2.PartialRequired{
  1216. OptString: scalar.String("embedded inside Any"),
  1217. }
  1218. b, err := proto.MarshalOptions{
  1219. AllowPartial: true,
  1220. Deterministic: true,
  1221. }.Marshal(m)
  1222. if err != nil {
  1223. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1224. }
  1225. return &anypb.Any{
  1226. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  1227. Value: b,
  1228. }
  1229. }(),
  1230. want: `[pb2.PartialRequired]: {
  1231. opt_string: "embedded inside Any"
  1232. }
  1233. `,
  1234. wantErr: true,
  1235. }, {
  1236. desc: "Any with invalid UTF-8",
  1237. mo: prototext.MarshalOptions{
  1238. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb3.Nested{})),
  1239. },
  1240. input: func() proto.Message {
  1241. m := &pb3.Nested{
  1242. SString: "abcd",
  1243. }
  1244. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1245. if err != nil {
  1246. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1247. }
  1248. return &anypb.Any{
  1249. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  1250. Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
  1251. }
  1252. }(),
  1253. want: `[pb3.Nested]: {
  1254. s_string: "abc\xff"
  1255. }
  1256. `,
  1257. wantErr: true,
  1258. }, {
  1259. desc: "Any with invalid value",
  1260. mo: prototext.MarshalOptions{
  1261. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1262. },
  1263. input: &anypb.Any{
  1264. TypeUrl: "foo/pb2.Nested",
  1265. Value: dhex("80"),
  1266. },
  1267. want: `type_url: "foo/pb2.Nested"
  1268. value: "\x80"
  1269. `,
  1270. }}
  1271. for _, tt := range tests {
  1272. tt := tt
  1273. t.Run(tt.desc, func(t *testing.T) {
  1274. // Use 2-space indentation on all MarshalOptions.
  1275. tt.mo.Indent = " "
  1276. b, err := tt.mo.Marshal(tt.input)
  1277. if err != nil && !tt.wantErr {
  1278. t.Errorf("Marshal() returned error: %v\n", err)
  1279. }
  1280. if err == nil && tt.wantErr {
  1281. t.Error("Marshal() got nil error, want error\n")
  1282. }
  1283. got := string(b)
  1284. if tt.want != "" && got != tt.want {
  1285. t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
  1286. if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
  1287. t.Errorf("Marshal() diff -want +got\n%v\n", diff)
  1288. }
  1289. }
  1290. })
  1291. }
  1292. }