encode_test.go 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920
  1. // Copyright 2019 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 protojson_test
  5. import (
  6. "bytes"
  7. "math"
  8. "testing"
  9. "github.com/google/go-cmp/cmp"
  10. "google.golang.org/protobuf/encoding/protojson"
  11. "google.golang.org/protobuf/internal/encoding/pack"
  12. pimpl "google.golang.org/protobuf/internal/impl"
  13. "google.golang.org/protobuf/proto"
  14. preg "google.golang.org/protobuf/reflect/protoregistry"
  15. "google.golang.org/protobuf/runtime/protoiface"
  16. "google.golang.org/protobuf/encoding/testprotos/pb2"
  17. "google.golang.org/protobuf/encoding/testprotos/pb3"
  18. "google.golang.org/protobuf/types/known/anypb"
  19. "google.golang.org/protobuf/types/known/durationpb"
  20. "google.golang.org/protobuf/types/known/emptypb"
  21. "google.golang.org/protobuf/types/known/fieldmaskpb"
  22. "google.golang.org/protobuf/types/known/structpb"
  23. "google.golang.org/protobuf/types/known/timestamppb"
  24. "google.golang.org/protobuf/types/known/wrapperspb"
  25. )
  26. // TODO: Replace this with proto.SetExtension.
  27. func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
  28. m.ProtoReflect().Set(xd.Type, xd.Type.ValueOf(val))
  29. }
  30. func TestMarshal(t *testing.T) {
  31. tests := []struct {
  32. desc string
  33. mo protojson.MarshalOptions
  34. input proto.Message
  35. want string
  36. wantErr bool // TODO: Verify error message substring.
  37. }{{
  38. desc: "proto2 optional scalars not set",
  39. input: &pb2.Scalars{},
  40. want: "{}",
  41. }, {
  42. desc: "proto3 scalars not set",
  43. input: &pb3.Scalars{},
  44. want: "{}",
  45. }, {
  46. desc: "proto2 optional scalars set to zero values",
  47. input: &pb2.Scalars{
  48. OptBool: proto.Bool(false),
  49. OptInt32: proto.Int32(0),
  50. OptInt64: proto.Int64(0),
  51. OptUint32: proto.Uint32(0),
  52. OptUint64: proto.Uint64(0),
  53. OptSint32: proto.Int32(0),
  54. OptSint64: proto.Int64(0),
  55. OptFixed32: proto.Uint32(0),
  56. OptFixed64: proto.Uint64(0),
  57. OptSfixed32: proto.Int32(0),
  58. OptSfixed64: proto.Int64(0),
  59. OptFloat: proto.Float32(0),
  60. OptDouble: proto.Float64(0),
  61. OptBytes: []byte{},
  62. OptString: proto.String(""),
  63. },
  64. want: `{
  65. "optBool": false,
  66. "optInt32": 0,
  67. "optInt64": "0",
  68. "optUint32": 0,
  69. "optUint64": "0",
  70. "optSint32": 0,
  71. "optSint64": "0",
  72. "optFixed32": 0,
  73. "optFixed64": "0",
  74. "optSfixed32": 0,
  75. "optSfixed64": "0",
  76. "optFloat": 0,
  77. "optDouble": 0,
  78. "optBytes": "",
  79. "optString": ""
  80. }`,
  81. }, {
  82. desc: "proto2 optional scalars set to some values",
  83. input: &pb2.Scalars{
  84. OptBool: proto.Bool(true),
  85. OptInt32: proto.Int32(0xff),
  86. OptInt64: proto.Int64(0xdeadbeef),
  87. OptUint32: proto.Uint32(47),
  88. OptUint64: proto.Uint64(0xdeadbeef),
  89. OptSint32: proto.Int32(-1001),
  90. OptSint64: proto.Int64(-0xffff),
  91. OptFixed64: proto.Uint64(64),
  92. OptSfixed32: proto.Int32(-32),
  93. OptFloat: proto.Float32(1.02),
  94. OptDouble: proto.Float64(1.234),
  95. OptBytes: []byte("谷歌"),
  96. OptString: proto.String("谷歌"),
  97. },
  98. want: `{
  99. "optBool": true,
  100. "optInt32": 255,
  101. "optInt64": "3735928559",
  102. "optUint32": 47,
  103. "optUint64": "3735928559",
  104. "optSint32": -1001,
  105. "optSint64": "-65535",
  106. "optFixed64": "64",
  107. "optSfixed32": -32,
  108. "optFloat": 1.02,
  109. "optDouble": 1.234,
  110. "optBytes": "6LC35q2M",
  111. "optString": "谷歌"
  112. }`,
  113. }, {
  114. desc: "string",
  115. input: &pb3.Scalars{
  116. SString: "谷歌",
  117. },
  118. want: `{
  119. "sString": "谷歌"
  120. }`,
  121. }, {
  122. desc: "string with invalid UTF8",
  123. input: &pb3.Scalars{
  124. SString: "abc\xff",
  125. },
  126. wantErr: true,
  127. }, {
  128. desc: "float nan",
  129. input: &pb3.Scalars{
  130. SFloat: float32(math.NaN()),
  131. },
  132. want: `{
  133. "sFloat": "NaN"
  134. }`,
  135. }, {
  136. desc: "float positive infinity",
  137. input: &pb3.Scalars{
  138. SFloat: float32(math.Inf(1)),
  139. },
  140. want: `{
  141. "sFloat": "Infinity"
  142. }`,
  143. }, {
  144. desc: "float negative infinity",
  145. input: &pb3.Scalars{
  146. SFloat: float32(math.Inf(-1)),
  147. },
  148. want: `{
  149. "sFloat": "-Infinity"
  150. }`,
  151. }, {
  152. desc: "double nan",
  153. input: &pb3.Scalars{
  154. SDouble: math.NaN(),
  155. },
  156. want: `{
  157. "sDouble": "NaN"
  158. }`,
  159. }, {
  160. desc: "double positive infinity",
  161. input: &pb3.Scalars{
  162. SDouble: math.Inf(1),
  163. },
  164. want: `{
  165. "sDouble": "Infinity"
  166. }`,
  167. }, {
  168. desc: "double negative infinity",
  169. input: &pb3.Scalars{
  170. SDouble: math.Inf(-1),
  171. },
  172. want: `{
  173. "sDouble": "-Infinity"
  174. }`,
  175. }, {
  176. desc: "proto2 enum not set",
  177. input: &pb2.Enums{},
  178. want: "{}",
  179. }, {
  180. desc: "proto2 enum set to zero value",
  181. input: &pb2.Enums{
  182. OptEnum: pb2.Enum(0).Enum(),
  183. OptNestedEnum: pb2.Enums_NestedEnum(0).Enum(),
  184. },
  185. want: `{
  186. "optEnum": 0,
  187. "optNestedEnum": 0
  188. }`,
  189. }, {
  190. desc: "proto2 enum",
  191. input: &pb2.Enums{
  192. OptEnum: pb2.Enum_ONE.Enum(),
  193. OptNestedEnum: pb2.Enums_UNO.Enum(),
  194. },
  195. want: `{
  196. "optEnum": "ONE",
  197. "optNestedEnum": "UNO"
  198. }`,
  199. }, {
  200. desc: "proto2 enum set to numeric values",
  201. input: &pb2.Enums{
  202. OptEnum: pb2.Enum(2).Enum(),
  203. OptNestedEnum: pb2.Enums_NestedEnum(2).Enum(),
  204. },
  205. want: `{
  206. "optEnum": "TWO",
  207. "optNestedEnum": "DOS"
  208. }`,
  209. }, {
  210. desc: "proto2 enum set to unnamed numeric values",
  211. input: &pb2.Enums{
  212. OptEnum: pb2.Enum(101).Enum(),
  213. OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
  214. },
  215. want: `{
  216. "optEnum": 101,
  217. "optNestedEnum": -101
  218. }`,
  219. }, {
  220. desc: "proto3 enum not set",
  221. input: &pb3.Enums{},
  222. want: "{}",
  223. }, {
  224. desc: "proto3 enum set to zero value",
  225. input: &pb3.Enums{
  226. SEnum: pb3.Enum_ZERO,
  227. SNestedEnum: pb3.Enums_CERO,
  228. },
  229. want: "{}",
  230. }, {
  231. desc: "proto3 enum",
  232. input: &pb3.Enums{
  233. SEnum: pb3.Enum_ONE,
  234. SNestedEnum: pb3.Enums_UNO,
  235. },
  236. want: `{
  237. "sEnum": "ONE",
  238. "sNestedEnum": "UNO"
  239. }`,
  240. }, {
  241. desc: "proto3 enum set to numeric values",
  242. input: &pb3.Enums{
  243. SEnum: 2,
  244. SNestedEnum: 2,
  245. },
  246. want: `{
  247. "sEnum": "TWO",
  248. "sNestedEnum": "DOS"
  249. }`,
  250. }, {
  251. desc: "proto3 enum set to unnamed numeric values",
  252. input: &pb3.Enums{
  253. SEnum: -47,
  254. SNestedEnum: 47,
  255. },
  256. want: `{
  257. "sEnum": -47,
  258. "sNestedEnum": 47
  259. }`,
  260. }, {
  261. desc: "proto2 nested message not set",
  262. input: &pb2.Nests{},
  263. want: "{}",
  264. }, {
  265. desc: "proto2 nested message set to empty",
  266. input: &pb2.Nests{
  267. OptNested: &pb2.Nested{},
  268. Optgroup: &pb2.Nests_OptGroup{},
  269. },
  270. want: `{
  271. "optNested": {},
  272. "optgroup": {}
  273. }`,
  274. }, {
  275. desc: "proto2 nested messages",
  276. input: &pb2.Nests{
  277. OptNested: &pb2.Nested{
  278. OptString: proto.String("nested message"),
  279. OptNested: &pb2.Nested{
  280. OptString: proto.String("another nested message"),
  281. },
  282. },
  283. },
  284. want: `{
  285. "optNested": {
  286. "optString": "nested message",
  287. "optNested": {
  288. "optString": "another nested message"
  289. }
  290. }
  291. }`,
  292. }, {
  293. desc: "proto2 groups",
  294. input: &pb2.Nests{
  295. Optgroup: &pb2.Nests_OptGroup{
  296. OptString: proto.String("inside a group"),
  297. OptNested: &pb2.Nested{
  298. OptString: proto.String("nested message inside a group"),
  299. },
  300. Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
  301. OptFixed32: proto.Uint32(47),
  302. },
  303. },
  304. },
  305. want: `{
  306. "optgroup": {
  307. "optString": "inside a group",
  308. "optNested": {
  309. "optString": "nested message inside a group"
  310. },
  311. "optnestedgroup": {
  312. "optFixed32": 47
  313. }
  314. }
  315. }`,
  316. }, {
  317. desc: "proto3 nested message not set",
  318. input: &pb3.Nests{},
  319. want: "{}",
  320. }, {
  321. desc: "proto3 nested message set to empty",
  322. input: &pb3.Nests{
  323. SNested: &pb3.Nested{},
  324. },
  325. want: `{
  326. "sNested": {}
  327. }`,
  328. }, {
  329. desc: "proto3 nested message",
  330. input: &pb3.Nests{
  331. SNested: &pb3.Nested{
  332. SString: "nested message",
  333. SNested: &pb3.Nested{
  334. SString: "another nested message",
  335. },
  336. },
  337. },
  338. want: `{
  339. "sNested": {
  340. "sString": "nested message",
  341. "sNested": {
  342. "sString": "another nested message"
  343. }
  344. }
  345. }`,
  346. }, {
  347. desc: "oneof not set",
  348. input: &pb3.Oneofs{},
  349. want: "{}",
  350. }, {
  351. desc: "oneof set to empty string",
  352. input: &pb3.Oneofs{
  353. Union: &pb3.Oneofs_OneofString{},
  354. },
  355. want: `{
  356. "oneofString": ""
  357. }`,
  358. }, {
  359. desc: "oneof set to string",
  360. input: &pb3.Oneofs{
  361. Union: &pb3.Oneofs_OneofString{
  362. OneofString: "hello",
  363. },
  364. },
  365. want: `{
  366. "oneofString": "hello"
  367. }`,
  368. }, {
  369. desc: "oneof set to enum",
  370. input: &pb3.Oneofs{
  371. Union: &pb3.Oneofs_OneofEnum{
  372. OneofEnum: pb3.Enum_ZERO,
  373. },
  374. },
  375. want: `{
  376. "oneofEnum": "ZERO"
  377. }`,
  378. }, {
  379. desc: "oneof set to empty message",
  380. input: &pb3.Oneofs{
  381. Union: &pb3.Oneofs_OneofNested{
  382. OneofNested: &pb3.Nested{},
  383. },
  384. },
  385. want: `{
  386. "oneofNested": {}
  387. }`,
  388. }, {
  389. desc: "oneof set to message",
  390. input: &pb3.Oneofs{
  391. Union: &pb3.Oneofs_OneofNested{
  392. OneofNested: &pb3.Nested{
  393. SString: "nested message",
  394. },
  395. },
  396. },
  397. want: `{
  398. "oneofNested": {
  399. "sString": "nested message"
  400. }
  401. }`,
  402. }, {
  403. desc: "repeated fields not set",
  404. input: &pb2.Repeats{},
  405. want: "{}",
  406. }, {
  407. desc: "repeated fields set to empty slices",
  408. input: &pb2.Repeats{
  409. RptBool: []bool{},
  410. RptInt32: []int32{},
  411. RptInt64: []int64{},
  412. RptUint32: []uint32{},
  413. RptUint64: []uint64{},
  414. RptFloat: []float32{},
  415. RptDouble: []float64{},
  416. RptBytes: [][]byte{},
  417. },
  418. want: "{}",
  419. }, {
  420. desc: "repeated fields set to some values",
  421. input: &pb2.Repeats{
  422. RptBool: []bool{true, false, true, true},
  423. RptInt32: []int32{1, 6, 0, 0},
  424. RptInt64: []int64{-64, 47},
  425. RptUint32: []uint32{0xff, 0xffff},
  426. RptUint64: []uint64{0xdeadbeef},
  427. RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
  428. RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
  429. RptString: []string{"hello", "世界"},
  430. RptBytes: [][]byte{
  431. []byte("hello"),
  432. []byte("\xe4\xb8\x96\xe7\x95\x8c"),
  433. },
  434. },
  435. want: `{
  436. "rptBool": [
  437. true,
  438. false,
  439. true,
  440. true
  441. ],
  442. "rptInt32": [
  443. 1,
  444. 6,
  445. 0,
  446. 0
  447. ],
  448. "rptInt64": [
  449. "-64",
  450. "47"
  451. ],
  452. "rptUint32": [
  453. 255,
  454. 65535
  455. ],
  456. "rptUint64": [
  457. "3735928559"
  458. ],
  459. "rptFloat": [
  460. "NaN",
  461. "Infinity",
  462. "-Infinity",
  463. 1.034
  464. ],
  465. "rptDouble": [
  466. "NaN",
  467. "Infinity",
  468. "-Infinity",
  469. 1.23e-308
  470. ],
  471. "rptString": [
  472. "hello",
  473. "世界"
  474. ],
  475. "rptBytes": [
  476. "aGVsbG8=",
  477. "5LiW55WM"
  478. ]
  479. }`,
  480. }, {
  481. desc: "repeated enums",
  482. input: &pb2.Enums{
  483. RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
  484. RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
  485. },
  486. want: `{
  487. "rptEnum": [
  488. "ONE",
  489. "TWO",
  490. "TEN",
  491. 42
  492. ],
  493. "rptNestedEnum": [
  494. "DOS",
  495. 47,
  496. "DIEZ"
  497. ]
  498. }`,
  499. }, {
  500. desc: "repeated messages set to empty",
  501. input: &pb2.Nests{
  502. RptNested: []*pb2.Nested{},
  503. Rptgroup: []*pb2.Nests_RptGroup{},
  504. },
  505. want: "{}",
  506. }, {
  507. desc: "repeated messages",
  508. input: &pb2.Nests{
  509. RptNested: []*pb2.Nested{
  510. {
  511. OptString: proto.String("repeat nested one"),
  512. },
  513. {
  514. OptString: proto.String("repeat nested two"),
  515. OptNested: &pb2.Nested{
  516. OptString: proto.String("inside repeat nested two"),
  517. },
  518. },
  519. {},
  520. },
  521. },
  522. want: `{
  523. "rptNested": [
  524. {
  525. "optString": "repeat nested one"
  526. },
  527. {
  528. "optString": "repeat nested two",
  529. "optNested": {
  530. "optString": "inside repeat nested two"
  531. }
  532. },
  533. {}
  534. ]
  535. }`,
  536. }, {
  537. desc: "repeated messages contains nil value",
  538. input: &pb2.Nests{
  539. RptNested: []*pb2.Nested{nil, {}},
  540. },
  541. want: `{
  542. "rptNested": [
  543. {},
  544. {}
  545. ]
  546. }`,
  547. }, {
  548. desc: "repeated groups",
  549. input: &pb2.Nests{
  550. Rptgroup: []*pb2.Nests_RptGroup{
  551. {
  552. RptString: []string{"hello", "world"},
  553. },
  554. {},
  555. nil,
  556. },
  557. },
  558. want: `{
  559. "rptgroup": [
  560. {
  561. "rptString": [
  562. "hello",
  563. "world"
  564. ]
  565. },
  566. {},
  567. {}
  568. ]
  569. }`,
  570. }, {
  571. desc: "map fields not set",
  572. input: &pb3.Maps{},
  573. want: "{}",
  574. }, {
  575. desc: "map fields set to empty",
  576. input: &pb3.Maps{
  577. Int32ToStr: map[int32]string{},
  578. BoolToUint32: map[bool]uint32{},
  579. Uint64ToEnum: map[uint64]pb3.Enum{},
  580. StrToNested: map[string]*pb3.Nested{},
  581. StrToOneofs: map[string]*pb3.Oneofs{},
  582. },
  583. want: "{}",
  584. }, {
  585. desc: "map fields 1",
  586. input: &pb3.Maps{
  587. BoolToUint32: map[bool]uint32{
  588. true: 42,
  589. false: 101,
  590. },
  591. },
  592. want: `{
  593. "boolToUint32": {
  594. "false": 101,
  595. "true": 42
  596. }
  597. }`,
  598. }, {
  599. desc: "map fields 2",
  600. input: &pb3.Maps{
  601. Int32ToStr: map[int32]string{
  602. -101: "-101",
  603. 0xff: "0xff",
  604. 0: "zero",
  605. },
  606. },
  607. want: `{
  608. "int32ToStr": {
  609. "-101": "-101",
  610. "0": "zero",
  611. "255": "0xff"
  612. }
  613. }`,
  614. }, {
  615. desc: "map fields 3",
  616. input: &pb3.Maps{
  617. Uint64ToEnum: map[uint64]pb3.Enum{
  618. 1: pb3.Enum_ONE,
  619. 2: pb3.Enum_TWO,
  620. 10: pb3.Enum_TEN,
  621. 47: 47,
  622. },
  623. },
  624. want: `{
  625. "uint64ToEnum": {
  626. "1": "ONE",
  627. "2": "TWO",
  628. "10": "TEN",
  629. "47": 47
  630. }
  631. }`,
  632. }, {
  633. desc: "map fields 4",
  634. input: &pb3.Maps{
  635. StrToNested: map[string]*pb3.Nested{
  636. "nested": &pb3.Nested{
  637. SString: "nested in a map",
  638. },
  639. },
  640. },
  641. want: `{
  642. "strToNested": {
  643. "nested": {
  644. "sString": "nested in a map"
  645. }
  646. }
  647. }`,
  648. }, {
  649. desc: "map fields 5",
  650. input: &pb3.Maps{
  651. StrToOneofs: map[string]*pb3.Oneofs{
  652. "string": &pb3.Oneofs{
  653. Union: &pb3.Oneofs_OneofString{
  654. OneofString: "hello",
  655. },
  656. },
  657. "nested": &pb3.Oneofs{
  658. Union: &pb3.Oneofs_OneofNested{
  659. OneofNested: &pb3.Nested{
  660. SString: "nested oneof in map field value",
  661. },
  662. },
  663. },
  664. },
  665. },
  666. want: `{
  667. "strToOneofs": {
  668. "nested": {
  669. "oneofNested": {
  670. "sString": "nested oneof in map field value"
  671. }
  672. },
  673. "string": {
  674. "oneofString": "hello"
  675. }
  676. }
  677. }`,
  678. }, {
  679. desc: "map field contains nil value",
  680. input: &pb3.Maps{
  681. StrToNested: map[string]*pb3.Nested{
  682. "nil": nil,
  683. },
  684. },
  685. want: `{
  686. "strToNested": {
  687. "nil": {}
  688. }
  689. }`,
  690. }, {
  691. desc: "required fields not set",
  692. input: &pb2.Requireds{},
  693. want: `{}`,
  694. wantErr: true,
  695. }, {
  696. desc: "required fields partially set",
  697. input: &pb2.Requireds{
  698. ReqBool: proto.Bool(false),
  699. ReqSfixed64: proto.Int64(0),
  700. ReqDouble: proto.Float64(1.23),
  701. ReqString: proto.String("hello"),
  702. ReqEnum: pb2.Enum_ONE.Enum(),
  703. },
  704. want: `{
  705. "reqBool": false,
  706. "reqSfixed64": "0",
  707. "reqDouble": 1.23,
  708. "reqString": "hello",
  709. "reqEnum": "ONE"
  710. }`,
  711. wantErr: true,
  712. }, {
  713. desc: "required fields not set with AllowPartial",
  714. mo: protojson.MarshalOptions{AllowPartial: true},
  715. input: &pb2.Requireds{
  716. ReqBool: proto.Bool(false),
  717. ReqSfixed64: proto.Int64(0),
  718. ReqDouble: proto.Float64(1.23),
  719. ReqString: proto.String("hello"),
  720. ReqEnum: pb2.Enum_ONE.Enum(),
  721. },
  722. want: `{
  723. "reqBool": false,
  724. "reqSfixed64": "0",
  725. "reqDouble": 1.23,
  726. "reqString": "hello",
  727. "reqEnum": "ONE"
  728. }`,
  729. }, {
  730. desc: "required fields all set",
  731. input: &pb2.Requireds{
  732. ReqBool: proto.Bool(false),
  733. ReqSfixed64: proto.Int64(0),
  734. ReqDouble: proto.Float64(1.23),
  735. ReqString: proto.String("hello"),
  736. ReqEnum: pb2.Enum_ONE.Enum(),
  737. ReqNested: &pb2.Nested{},
  738. },
  739. want: `{
  740. "reqBool": false,
  741. "reqSfixed64": "0",
  742. "reqDouble": 1.23,
  743. "reqString": "hello",
  744. "reqEnum": "ONE",
  745. "reqNested": {}
  746. }`,
  747. }, {
  748. desc: "indirect required field",
  749. input: &pb2.IndirectRequired{
  750. OptNested: &pb2.NestedWithRequired{},
  751. },
  752. want: `{
  753. "optNested": {}
  754. }`,
  755. wantErr: true,
  756. }, {
  757. desc: "indirect required field with AllowPartial",
  758. mo: protojson.MarshalOptions{AllowPartial: true},
  759. input: &pb2.IndirectRequired{
  760. OptNested: &pb2.NestedWithRequired{},
  761. },
  762. want: `{
  763. "optNested": {}
  764. }`,
  765. }, {
  766. desc: "indirect required field in empty repeated",
  767. input: &pb2.IndirectRequired{
  768. RptNested: []*pb2.NestedWithRequired{},
  769. },
  770. want: `{}`,
  771. }, {
  772. desc: "indirect required field in repeated",
  773. input: &pb2.IndirectRequired{
  774. RptNested: []*pb2.NestedWithRequired{
  775. &pb2.NestedWithRequired{},
  776. },
  777. },
  778. want: `{
  779. "rptNested": [
  780. {}
  781. ]
  782. }`,
  783. wantErr: true,
  784. }, {
  785. desc: "indirect required field in repeated with AllowPartial",
  786. mo: protojson.MarshalOptions{AllowPartial: true},
  787. input: &pb2.IndirectRequired{
  788. RptNested: []*pb2.NestedWithRequired{
  789. &pb2.NestedWithRequired{},
  790. },
  791. },
  792. want: `{
  793. "rptNested": [
  794. {}
  795. ]
  796. }`,
  797. }, {
  798. desc: "indirect required field in empty map",
  799. input: &pb2.IndirectRequired{
  800. StrToNested: map[string]*pb2.NestedWithRequired{},
  801. },
  802. want: "{}",
  803. }, {
  804. desc: "indirect required field in map",
  805. input: &pb2.IndirectRequired{
  806. StrToNested: map[string]*pb2.NestedWithRequired{
  807. "fail": &pb2.NestedWithRequired{},
  808. },
  809. },
  810. want: `{
  811. "strToNested": {
  812. "fail": {}
  813. }
  814. }`,
  815. wantErr: true,
  816. }, {
  817. desc: "indirect required field in map with AllowPartial",
  818. mo: protojson.MarshalOptions{AllowPartial: true},
  819. input: &pb2.IndirectRequired{
  820. StrToNested: map[string]*pb2.NestedWithRequired{
  821. "fail": &pb2.NestedWithRequired{},
  822. },
  823. },
  824. want: `{
  825. "strToNested": {
  826. "fail": {}
  827. }
  828. }`,
  829. }, {
  830. desc: "indirect required field in oneof",
  831. input: &pb2.IndirectRequired{
  832. Union: &pb2.IndirectRequired_OneofNested{
  833. OneofNested: &pb2.NestedWithRequired{},
  834. },
  835. },
  836. want: `{
  837. "oneofNested": {}
  838. }`,
  839. wantErr: true,
  840. }, {
  841. desc: "indirect required field in oneof with AllowPartial",
  842. mo: protojson.MarshalOptions{AllowPartial: true},
  843. input: &pb2.IndirectRequired{
  844. Union: &pb2.IndirectRequired_OneofNested{
  845. OneofNested: &pb2.NestedWithRequired{},
  846. },
  847. },
  848. want: `{
  849. "oneofNested": {}
  850. }`,
  851. }, {
  852. desc: "unknown fields are ignored",
  853. input: func() proto.Message {
  854. m := &pb2.Scalars{
  855. OptString: proto.String("no unknowns"),
  856. }
  857. m.ProtoReflect().SetUnknown(pack.Message{
  858. pack.Tag{101, pack.BytesType}, pack.String("hello world"),
  859. }.Marshal())
  860. return m
  861. }(),
  862. want: `{
  863. "optString": "no unknowns"
  864. }`,
  865. }, {
  866. desc: "json_name",
  867. input: &pb3.JSONNames{
  868. SString: "json_name",
  869. },
  870. want: `{
  871. "foo_bar": "json_name"
  872. }`,
  873. }, {
  874. desc: "extensions of non-repeated fields",
  875. input: func() proto.Message {
  876. m := &pb2.Extensions{
  877. OptString: proto.String("non-extension field"),
  878. OptBool: proto.Bool(true),
  879. OptInt32: proto.Int32(42),
  880. }
  881. setExtension(m, pb2.E_OptExtBool, true)
  882. setExtension(m, pb2.E_OptExtString, "extension field")
  883. setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
  884. setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
  885. OptString: proto.String("nested in an extension"),
  886. OptNested: &pb2.Nested{
  887. OptString: proto.String("another nested in an extension"),
  888. },
  889. })
  890. return m
  891. }(),
  892. want: `{
  893. "optString": "non-extension field",
  894. "optBool": true,
  895. "optInt32": 42,
  896. "[pb2.opt_ext_bool]": true,
  897. "[pb2.opt_ext_enum]": "TEN",
  898. "[pb2.opt_ext_nested]": {
  899. "optString": "nested in an extension",
  900. "optNested": {
  901. "optString": "another nested in an extension"
  902. }
  903. },
  904. "[pb2.opt_ext_string]": "extension field"
  905. }`,
  906. }, {
  907. desc: "extensions of repeated fields",
  908. input: func() proto.Message {
  909. m := &pb2.Extensions{}
  910. setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  911. setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
  912. setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
  913. &pb2.Nested{OptString: proto.String("one")},
  914. &pb2.Nested{OptString: proto.String("two")},
  915. &pb2.Nested{OptString: proto.String("three")},
  916. })
  917. return m
  918. }(),
  919. want: `{
  920. "[pb2.rpt_ext_enum]": [
  921. "TEN",
  922. 101,
  923. "ONE"
  924. ],
  925. "[pb2.rpt_ext_fixed32]": [
  926. 42,
  927. 47
  928. ],
  929. "[pb2.rpt_ext_nested]": [
  930. {
  931. "optString": "one"
  932. },
  933. {
  934. "optString": "two"
  935. },
  936. {
  937. "optString": "three"
  938. }
  939. ]
  940. }`,
  941. }, {
  942. desc: "extensions of non-repeated fields in another message",
  943. input: func() proto.Message {
  944. m := &pb2.Extensions{}
  945. setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
  946. setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
  947. setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
  948. setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
  949. OptString: proto.String("nested in an extension"),
  950. OptNested: &pb2.Nested{
  951. OptString: proto.String("another nested in an extension"),
  952. },
  953. })
  954. return m
  955. }(),
  956. want: `{
  957. "[pb2.ExtensionsContainer.opt_ext_bool]": true,
  958. "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
  959. "[pb2.ExtensionsContainer.opt_ext_nested]": {
  960. "optString": "nested in an extension",
  961. "optNested": {
  962. "optString": "another nested in an extension"
  963. }
  964. },
  965. "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
  966. }`,
  967. }, {
  968. desc: "extensions of repeated fields in another message",
  969. input: func() proto.Message {
  970. m := &pb2.Extensions{
  971. OptString: proto.String("non-extension field"),
  972. OptBool: proto.Bool(true),
  973. OptInt32: proto.Int32(42),
  974. }
  975. setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  976. setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
  977. setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
  978. &pb2.Nested{OptString: proto.String("one")},
  979. &pb2.Nested{OptString: proto.String("two")},
  980. &pb2.Nested{OptString: proto.String("three")},
  981. })
  982. return m
  983. }(),
  984. want: `{
  985. "optString": "non-extension field",
  986. "optBool": true,
  987. "optInt32": 42,
  988. "[pb2.ExtensionsContainer.rpt_ext_enum]": [
  989. "TEN",
  990. 101,
  991. "ONE"
  992. ],
  993. "[pb2.ExtensionsContainer.rpt_ext_nested]": [
  994. {
  995. "optString": "one"
  996. },
  997. {
  998. "optString": "two"
  999. },
  1000. {
  1001. "optString": "three"
  1002. }
  1003. ],
  1004. "[pb2.ExtensionsContainer.rpt_ext_string]": [
  1005. "hello",
  1006. "world"
  1007. ]
  1008. }`,
  1009. }, {
  1010. desc: "MessageSet",
  1011. input: func() proto.Message {
  1012. m := &pb2.MessageSet{}
  1013. setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
  1014. OptString: proto.String("a messageset extension"),
  1015. })
  1016. setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
  1017. OptString: proto.String("not a messageset extension"),
  1018. })
  1019. setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
  1020. OptString: proto.String("just a regular extension"),
  1021. })
  1022. return m
  1023. }(),
  1024. want: `{
  1025. "[pb2.MessageSetExtension]": {
  1026. "optString": "a messageset extension"
  1027. },
  1028. "[pb2.MessageSetExtension.ext_nested]": {
  1029. "optString": "just a regular extension"
  1030. },
  1031. "[pb2.MessageSetExtension.not_message_set_extension]": {
  1032. "optString": "not a messageset extension"
  1033. }
  1034. }`,
  1035. }, {
  1036. desc: "not real MessageSet 1",
  1037. input: func() proto.Message {
  1038. m := &pb2.FakeMessageSet{}
  1039. setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1040. OptString: proto.String("not a messageset extension"),
  1041. })
  1042. return m
  1043. }(),
  1044. want: `{
  1045. "[pb2.FakeMessageSetExtension.message_set_extension]": {
  1046. "optString": "not a messageset extension"
  1047. }
  1048. }`,
  1049. }, {
  1050. desc: "not real MessageSet 2",
  1051. input: func() proto.Message {
  1052. m := &pb2.MessageSet{}
  1053. setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1054. OptString: proto.String("another not a messageset extension"),
  1055. })
  1056. return m
  1057. }(),
  1058. want: `{
  1059. "[pb2.message_set_extension]": {
  1060. "optString": "another not a messageset extension"
  1061. }
  1062. }`,
  1063. }, {
  1064. desc: "BoolValue empty",
  1065. input: &wrapperspb.BoolValue{},
  1066. want: `false`,
  1067. }, {
  1068. desc: "BoolValue",
  1069. input: &wrapperspb.BoolValue{Value: true},
  1070. want: `true`,
  1071. }, {
  1072. desc: "Int32Value empty",
  1073. input: &wrapperspb.Int32Value{},
  1074. want: `0`,
  1075. }, {
  1076. desc: "Int32Value",
  1077. input: &wrapperspb.Int32Value{Value: 42},
  1078. want: `42`,
  1079. }, {
  1080. desc: "Int64Value",
  1081. input: &wrapperspb.Int64Value{Value: 42},
  1082. want: `"42"`,
  1083. }, {
  1084. desc: "UInt32Value",
  1085. input: &wrapperspb.UInt32Value{Value: 42},
  1086. want: `42`,
  1087. }, {
  1088. desc: "UInt64Value",
  1089. input: &wrapperspb.UInt64Value{Value: 42},
  1090. want: `"42"`,
  1091. }, {
  1092. desc: "FloatValue",
  1093. input: &wrapperspb.FloatValue{Value: 1.02},
  1094. want: `1.02`,
  1095. }, {
  1096. desc: "FloatValue Infinity",
  1097. input: &wrapperspb.FloatValue{Value: float32(math.Inf(-1))},
  1098. want: `"-Infinity"`,
  1099. }, {
  1100. desc: "DoubleValue",
  1101. input: &wrapperspb.DoubleValue{Value: 1.02},
  1102. want: `1.02`,
  1103. }, {
  1104. desc: "DoubleValue NaN",
  1105. input: &wrapperspb.DoubleValue{Value: math.NaN()},
  1106. want: `"NaN"`,
  1107. }, {
  1108. desc: "StringValue empty",
  1109. input: &wrapperspb.StringValue{},
  1110. want: `""`,
  1111. }, {
  1112. desc: "StringValue",
  1113. input: &wrapperspb.StringValue{Value: "谷歌"},
  1114. want: `"谷歌"`,
  1115. }, {
  1116. desc: "StringValue with invalid UTF8 error",
  1117. input: &wrapperspb.StringValue{Value: "abc\xff"},
  1118. wantErr: true,
  1119. }, {
  1120. desc: "StringValue field with invalid UTF8 error",
  1121. input: &pb2.KnownTypes{
  1122. OptString: &wrapperspb.StringValue{Value: "abc\xff"},
  1123. },
  1124. wantErr: true,
  1125. }, {
  1126. desc: "BytesValue",
  1127. input: &wrapperspb.BytesValue{Value: []byte("hello")},
  1128. want: `"aGVsbG8="`,
  1129. }, {
  1130. desc: "Empty",
  1131. input: &emptypb.Empty{},
  1132. want: `{}`,
  1133. }, {
  1134. desc: "NullValue field",
  1135. input: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
  1136. want: `{
  1137. "optNull": null
  1138. }`,
  1139. }, {
  1140. desc: "Value empty",
  1141. input: &structpb.Value{},
  1142. wantErr: true,
  1143. }, {
  1144. desc: "Value empty field",
  1145. input: &pb2.KnownTypes{
  1146. OptValue: &structpb.Value{},
  1147. },
  1148. wantErr: true,
  1149. }, {
  1150. desc: "Value contains NullValue",
  1151. input: &structpb.Value{Kind: &structpb.Value_NullValue{}},
  1152. want: `null`,
  1153. }, {
  1154. desc: "Value contains BoolValue",
  1155. input: &structpb.Value{Kind: &structpb.Value_BoolValue{}},
  1156. want: `false`,
  1157. }, {
  1158. desc: "Value contains NumberValue",
  1159. input: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
  1160. want: `1.02`,
  1161. }, {
  1162. desc: "Value contains StringValue",
  1163. input: &structpb.Value{Kind: &structpb.Value_StringValue{"hello"}},
  1164. want: `"hello"`,
  1165. }, {
  1166. desc: "Value contains StringValue with invalid UTF8",
  1167. input: &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
  1168. wantErr: true,
  1169. }, {
  1170. desc: "Value contains Struct",
  1171. input: &structpb.Value{
  1172. Kind: &structpb.Value_StructValue{
  1173. &structpb.Struct{
  1174. Fields: map[string]*structpb.Value{
  1175. "null": {Kind: &structpb.Value_NullValue{}},
  1176. "number": {Kind: &structpb.Value_NumberValue{}},
  1177. "string": {Kind: &structpb.Value_StringValue{}},
  1178. "struct": {Kind: &structpb.Value_StructValue{}},
  1179. "list": {Kind: &structpb.Value_ListValue{}},
  1180. "bool": {Kind: &structpb.Value_BoolValue{}},
  1181. },
  1182. },
  1183. },
  1184. },
  1185. want: `{
  1186. "bool": false,
  1187. "list": [],
  1188. "null": null,
  1189. "number": 0,
  1190. "string": "",
  1191. "struct": {}
  1192. }`,
  1193. }, {
  1194. desc: "Value contains ListValue",
  1195. input: &structpb.Value{
  1196. Kind: &structpb.Value_ListValue{
  1197. &structpb.ListValue{
  1198. Values: []*structpb.Value{
  1199. {Kind: &structpb.Value_BoolValue{}},
  1200. {Kind: &structpb.Value_NullValue{}},
  1201. {Kind: &structpb.Value_NumberValue{}},
  1202. {Kind: &structpb.Value_StringValue{}},
  1203. {Kind: &structpb.Value_StructValue{}},
  1204. {Kind: &structpb.Value_ListValue{}},
  1205. },
  1206. },
  1207. },
  1208. },
  1209. want: `[
  1210. false,
  1211. null,
  1212. 0,
  1213. "",
  1214. {},
  1215. []
  1216. ]`,
  1217. }, {
  1218. desc: "Struct with nil map",
  1219. input: &structpb.Struct{},
  1220. want: `{}`,
  1221. }, {
  1222. desc: "Struct with empty map",
  1223. input: &structpb.Struct{
  1224. Fields: map[string]*structpb.Value{},
  1225. },
  1226. want: `{}`,
  1227. }, {
  1228. desc: "Struct",
  1229. input: &structpb.Struct{
  1230. Fields: map[string]*structpb.Value{
  1231. "bool": {Kind: &structpb.Value_BoolValue{true}},
  1232. "null": {Kind: &structpb.Value_NullValue{}},
  1233. "number": {Kind: &structpb.Value_NumberValue{3.1415}},
  1234. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  1235. "struct": {
  1236. Kind: &structpb.Value_StructValue{
  1237. &structpb.Struct{
  1238. Fields: map[string]*structpb.Value{
  1239. "string": {Kind: &structpb.Value_StringValue{"world"}},
  1240. },
  1241. },
  1242. },
  1243. },
  1244. "list": {
  1245. Kind: &structpb.Value_ListValue{
  1246. &structpb.ListValue{
  1247. Values: []*structpb.Value{
  1248. {Kind: &structpb.Value_BoolValue{}},
  1249. {Kind: &structpb.Value_NullValue{}},
  1250. {Kind: &structpb.Value_NumberValue{}},
  1251. },
  1252. },
  1253. },
  1254. },
  1255. },
  1256. },
  1257. want: `{
  1258. "bool": true,
  1259. "list": [
  1260. false,
  1261. null,
  1262. 0
  1263. ],
  1264. "null": null,
  1265. "number": 3.1415,
  1266. "string": "hello",
  1267. "struct": {
  1268. "string": "world"
  1269. }
  1270. }`,
  1271. }, {
  1272. desc: "Struct message with invalid UTF8 string",
  1273. input: &structpb.Struct{
  1274. Fields: map[string]*structpb.Value{
  1275. "string": {Kind: &structpb.Value_StringValue{"\xff"}},
  1276. },
  1277. },
  1278. wantErr: true,
  1279. }, {
  1280. desc: "ListValue with nil values",
  1281. input: &structpb.ListValue{},
  1282. want: `[]`,
  1283. }, {
  1284. desc: "ListValue with empty values",
  1285. input: &structpb.ListValue{
  1286. Values: []*structpb.Value{},
  1287. },
  1288. want: `[]`,
  1289. }, {
  1290. desc: "ListValue",
  1291. input: &structpb.ListValue{
  1292. Values: []*structpb.Value{
  1293. {Kind: &structpb.Value_BoolValue{true}},
  1294. {Kind: &structpb.Value_NullValue{}},
  1295. {Kind: &structpb.Value_NumberValue{3.1415}},
  1296. {Kind: &structpb.Value_StringValue{"hello"}},
  1297. {
  1298. Kind: &structpb.Value_ListValue{
  1299. &structpb.ListValue{
  1300. Values: []*structpb.Value{
  1301. {Kind: &structpb.Value_BoolValue{}},
  1302. {Kind: &structpb.Value_NullValue{}},
  1303. {Kind: &structpb.Value_NumberValue{}},
  1304. },
  1305. },
  1306. },
  1307. },
  1308. {
  1309. Kind: &structpb.Value_StructValue{
  1310. &structpb.Struct{
  1311. Fields: map[string]*structpb.Value{
  1312. "string": {Kind: &structpb.Value_StringValue{"world"}},
  1313. },
  1314. },
  1315. },
  1316. },
  1317. },
  1318. },
  1319. want: `[
  1320. true,
  1321. null,
  1322. 3.1415,
  1323. "hello",
  1324. [
  1325. false,
  1326. null,
  1327. 0
  1328. ],
  1329. {
  1330. "string": "world"
  1331. }
  1332. ]`,
  1333. }, {
  1334. desc: "ListValue with invalid UTF8 string",
  1335. input: &structpb.ListValue{
  1336. Values: []*structpb.Value{
  1337. {Kind: &structpb.Value_StringValue{"\xff"}},
  1338. },
  1339. },
  1340. wantErr: true,
  1341. }, {
  1342. desc: "Duration empty",
  1343. input: &durationpb.Duration{},
  1344. want: `"0s"`,
  1345. }, {
  1346. desc: "Duration with secs",
  1347. input: &durationpb.Duration{Seconds: 3},
  1348. want: `"3s"`,
  1349. }, {
  1350. desc: "Duration with -secs",
  1351. input: &durationpb.Duration{Seconds: -3},
  1352. want: `"-3s"`,
  1353. }, {
  1354. desc: "Duration with nanos",
  1355. input: &durationpb.Duration{Nanos: 1e6},
  1356. want: `"0.001s"`,
  1357. }, {
  1358. desc: "Duration with -nanos",
  1359. input: &durationpb.Duration{Nanos: -1e6},
  1360. want: `"-0.001s"`,
  1361. }, {
  1362. desc: "Duration with large secs",
  1363. input: &durationpb.Duration{Seconds: 1e10, Nanos: 1},
  1364. want: `"10000000000.000000001s"`,
  1365. }, {
  1366. desc: "Duration with 6-digit nanos",
  1367. input: &durationpb.Duration{Nanos: 1e4},
  1368. want: `"0.000010s"`,
  1369. }, {
  1370. desc: "Duration with 3-digit nanos",
  1371. input: &durationpb.Duration{Nanos: 1e6},
  1372. want: `"0.001s"`,
  1373. }, {
  1374. desc: "Duration with -secs -nanos",
  1375. input: &durationpb.Duration{Seconds: -123, Nanos: -450},
  1376. want: `"-123.000000450s"`,
  1377. }, {
  1378. desc: "Duration max value",
  1379. input: &durationpb.Duration{Seconds: 315576000000, Nanos: 999999999},
  1380. want: `"315576000000.999999999s"`,
  1381. }, {
  1382. desc: "Duration min value",
  1383. input: &durationpb.Duration{Seconds: -315576000000, Nanos: -999999999},
  1384. want: `"-315576000000.999999999s"`,
  1385. }, {
  1386. desc: "Duration with +secs -nanos",
  1387. input: &durationpb.Duration{Seconds: 1, Nanos: -1},
  1388. wantErr: true,
  1389. }, {
  1390. desc: "Duration with -secs +nanos",
  1391. input: &durationpb.Duration{Seconds: -1, Nanos: 1},
  1392. wantErr: true,
  1393. }, {
  1394. desc: "Duration with +secs out of range",
  1395. input: &durationpb.Duration{Seconds: 315576000001},
  1396. wantErr: true,
  1397. }, {
  1398. desc: "Duration with -secs out of range",
  1399. input: &durationpb.Duration{Seconds: -315576000001},
  1400. wantErr: true,
  1401. }, {
  1402. desc: "Duration with +nanos out of range",
  1403. input: &durationpb.Duration{Seconds: 0, Nanos: 1e9},
  1404. wantErr: true,
  1405. }, {
  1406. desc: "Duration with -nanos out of range",
  1407. input: &durationpb.Duration{Seconds: 0, Nanos: -1e9},
  1408. wantErr: true,
  1409. }, {
  1410. desc: "Timestamp zero",
  1411. input: &timestamppb.Timestamp{},
  1412. want: `"1970-01-01T00:00:00Z"`,
  1413. }, {
  1414. desc: "Timestamp",
  1415. input: &timestamppb.Timestamp{Seconds: 1553036601},
  1416. want: `"2019-03-19T23:03:21Z"`,
  1417. }, {
  1418. desc: "Timestamp with nanos",
  1419. input: &timestamppb.Timestamp{Seconds: 1553036601, Nanos: 1},
  1420. want: `"2019-03-19T23:03:21.000000001Z"`,
  1421. }, {
  1422. desc: "Timestamp with 6-digit nanos",
  1423. input: &timestamppb.Timestamp{Nanos: 1e3},
  1424. want: `"1970-01-01T00:00:00.000001Z"`,
  1425. }, {
  1426. desc: "Timestamp with 3-digit nanos",
  1427. input: &timestamppb.Timestamp{Nanos: 1e7},
  1428. want: `"1970-01-01T00:00:00.010Z"`,
  1429. }, {
  1430. desc: "Timestamp max value",
  1431. input: &timestamppb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
  1432. want: `"9999-12-31T23:59:59.999999999Z"`,
  1433. }, {
  1434. desc: "Timestamp min value",
  1435. input: &timestamppb.Timestamp{Seconds: -62135596800},
  1436. want: `"0001-01-01T00:00:00Z"`,
  1437. }, {
  1438. desc: "Timestamp with +secs out of range",
  1439. input: &timestamppb.Timestamp{Seconds: 253402300800},
  1440. wantErr: true,
  1441. }, {
  1442. desc: "Timestamp with -secs out of range",
  1443. input: &timestamppb.Timestamp{Seconds: -62135596801},
  1444. wantErr: true,
  1445. }, {
  1446. desc: "Timestamp with -nanos",
  1447. input: &timestamppb.Timestamp{Nanos: -1},
  1448. wantErr: true,
  1449. }, {
  1450. desc: "Timestamp with +nanos out of range",
  1451. input: &timestamppb.Timestamp{Nanos: 1e9},
  1452. wantErr: true,
  1453. }, {
  1454. desc: "FieldMask empty",
  1455. input: &fieldmaskpb.FieldMask{},
  1456. want: `""`,
  1457. }, {
  1458. desc: "FieldMask",
  1459. input: &fieldmaskpb.FieldMask{
  1460. Paths: []string{
  1461. "foo",
  1462. "foo_bar",
  1463. "foo.bar_qux",
  1464. "_foo",
  1465. },
  1466. },
  1467. want: `"foo,fooBar,foo.barQux,Foo"`,
  1468. }, {
  1469. desc: "FieldMask error 1",
  1470. input: &fieldmaskpb.FieldMask{
  1471. Paths: []string{"foo_"},
  1472. },
  1473. wantErr: true,
  1474. }, {
  1475. desc: "FieldMask error 2",
  1476. input: &fieldmaskpb.FieldMask{
  1477. Paths: []string{"foo__bar"},
  1478. },
  1479. wantErr: true,
  1480. }, {
  1481. desc: "Any empty",
  1482. input: &anypb.Any{},
  1483. want: `{}`,
  1484. }, {
  1485. desc: "Any with non-custom message",
  1486. mo: protojson.MarshalOptions{
  1487. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1488. },
  1489. input: func() proto.Message {
  1490. m := &pb2.Nested{
  1491. OptString: proto.String("embedded inside Any"),
  1492. OptNested: &pb2.Nested{
  1493. OptString: proto.String("inception"),
  1494. },
  1495. }
  1496. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1497. if err != nil {
  1498. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1499. }
  1500. return &anypb.Any{
  1501. TypeUrl: "foo/pb2.Nested",
  1502. Value: b,
  1503. }
  1504. }(),
  1505. want: `{
  1506. "@type": "foo/pb2.Nested",
  1507. "optString": "embedded inside Any",
  1508. "optNested": {
  1509. "optString": "inception"
  1510. }
  1511. }`,
  1512. }, {
  1513. desc: "Any with empty embedded message",
  1514. mo: protojson.MarshalOptions{
  1515. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1516. },
  1517. input: &anypb.Any{TypeUrl: "foo/pb2.Nested"},
  1518. want: `{
  1519. "@type": "foo/pb2.Nested"
  1520. }`,
  1521. }, {
  1522. desc: "Any without registered type",
  1523. mo: protojson.MarshalOptions{Resolver: preg.NewTypes()},
  1524. input: &anypb.Any{TypeUrl: "foo/pb2.Nested"},
  1525. wantErr: true,
  1526. }, {
  1527. desc: "Any with missing required",
  1528. mo: protojson.MarshalOptions{
  1529. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
  1530. },
  1531. input: func() proto.Message {
  1532. m := &pb2.PartialRequired{
  1533. OptString: proto.String("embedded inside Any"),
  1534. }
  1535. b, err := proto.MarshalOptions{
  1536. AllowPartial: true,
  1537. Deterministic: true,
  1538. }.Marshal(m)
  1539. if err != nil {
  1540. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1541. }
  1542. return &anypb.Any{
  1543. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  1544. Value: b,
  1545. }
  1546. }(),
  1547. want: `{
  1548. "@type": "pb2.PartialRequired",
  1549. "optString": "embedded inside Any"
  1550. }`,
  1551. }, {
  1552. desc: "Any with partial required and AllowPartial",
  1553. mo: protojson.MarshalOptions{
  1554. AllowPartial: true,
  1555. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
  1556. },
  1557. input: func() proto.Message {
  1558. m := &pb2.PartialRequired{
  1559. OptString: proto.String("embedded inside Any"),
  1560. }
  1561. b, err := proto.MarshalOptions{
  1562. AllowPartial: true,
  1563. Deterministic: true,
  1564. }.Marshal(m)
  1565. if err != nil {
  1566. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1567. }
  1568. return &anypb.Any{
  1569. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  1570. Value: b,
  1571. }
  1572. }(),
  1573. want: `{
  1574. "@type": "pb2.PartialRequired",
  1575. "optString": "embedded inside Any"
  1576. }`,
  1577. }, {
  1578. desc: "Any with invalid UTF8",
  1579. mo: protojson.MarshalOptions{
  1580. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1581. },
  1582. input: func() proto.Message {
  1583. m := &pb2.Nested{
  1584. OptString: proto.String("abc\xff"),
  1585. }
  1586. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1587. if err != nil {
  1588. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1589. }
  1590. return &anypb.Any{
  1591. TypeUrl: "foo/pb2.Nested",
  1592. Value: b,
  1593. }
  1594. }(),
  1595. wantErr: true,
  1596. }, {
  1597. desc: "Any with invalid value",
  1598. mo: protojson.MarshalOptions{
  1599. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1600. },
  1601. input: &anypb.Any{
  1602. TypeUrl: "foo/pb2.Nested",
  1603. Value: []byte("\x80"),
  1604. },
  1605. wantErr: true,
  1606. }, {
  1607. desc: "Any with BoolValue",
  1608. mo: protojson.MarshalOptions{
  1609. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{})),
  1610. },
  1611. input: func() proto.Message {
  1612. m := &wrapperspb.BoolValue{Value: true}
  1613. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1614. if err != nil {
  1615. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1616. }
  1617. return &anypb.Any{
  1618. TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
  1619. Value: b,
  1620. }
  1621. }(),
  1622. want: `{
  1623. "@type": "type.googleapis.com/google.protobuf.BoolValue",
  1624. "value": true
  1625. }`,
  1626. }, {
  1627. desc: "Any with Empty",
  1628. mo: protojson.MarshalOptions{
  1629. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
  1630. },
  1631. input: func() proto.Message {
  1632. m := &emptypb.Empty{}
  1633. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1634. if err != nil {
  1635. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1636. }
  1637. return &anypb.Any{
  1638. TypeUrl: "type.googleapis.com/google.protobuf.Empty",
  1639. Value: b,
  1640. }
  1641. }(),
  1642. want: `{
  1643. "@type": "type.googleapis.com/google.protobuf.Empty",
  1644. "value": {}
  1645. }`,
  1646. }, {
  1647. desc: "Any with StringValue containing invalid UTF8",
  1648. mo: protojson.MarshalOptions{
  1649. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
  1650. },
  1651. input: func() proto.Message {
  1652. m := &wrapperspb.StringValue{Value: "abcd"}
  1653. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1654. if err != nil {
  1655. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1656. }
  1657. return &anypb.Any{
  1658. TypeUrl: "google.protobuf.StringValue",
  1659. Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
  1660. }
  1661. }(),
  1662. wantErr: true,
  1663. }, {
  1664. desc: "Any with Int64Value",
  1665. mo: protojson.MarshalOptions{
  1666. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
  1667. },
  1668. input: func() proto.Message {
  1669. m := &wrapperspb.Int64Value{Value: 42}
  1670. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1671. if err != nil {
  1672. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1673. }
  1674. return &anypb.Any{
  1675. TypeUrl: "google.protobuf.Int64Value",
  1676. Value: b,
  1677. }
  1678. }(),
  1679. want: `{
  1680. "@type": "google.protobuf.Int64Value",
  1681. "value": "42"
  1682. }`,
  1683. }, {
  1684. desc: "Any with Duration",
  1685. mo: protojson.MarshalOptions{
  1686. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&durationpb.Duration{})),
  1687. },
  1688. input: func() proto.Message {
  1689. m := &durationpb.Duration{}
  1690. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1691. if err != nil {
  1692. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1693. }
  1694. return &anypb.Any{
  1695. TypeUrl: "type.googleapis.com/google.protobuf.Duration",
  1696. Value: b,
  1697. }
  1698. }(),
  1699. want: `{
  1700. "@type": "type.googleapis.com/google.protobuf.Duration",
  1701. "value": "0s"
  1702. }`,
  1703. }, {
  1704. desc: "Any with empty Value",
  1705. mo: protojson.MarshalOptions{
  1706. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
  1707. },
  1708. input: func() proto.Message {
  1709. m := &structpb.Value{}
  1710. b, err := proto.Marshal(m)
  1711. if err != nil {
  1712. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1713. }
  1714. return &anypb.Any{
  1715. TypeUrl: "type.googleapis.com/google.protobuf.Value",
  1716. Value: b,
  1717. }
  1718. }(),
  1719. wantErr: true,
  1720. }, {
  1721. desc: "Any with Value of StringValue",
  1722. mo: protojson.MarshalOptions{
  1723. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
  1724. },
  1725. input: func() proto.Message {
  1726. m := &structpb.Value{Kind: &structpb.Value_StringValue{"abcd"}}
  1727. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1728. if err != nil {
  1729. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1730. }
  1731. return &anypb.Any{
  1732. TypeUrl: "type.googleapis.com/google.protobuf.Value",
  1733. Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
  1734. }
  1735. }(),
  1736. wantErr: true,
  1737. }, {
  1738. desc: "Any with Value of NullValue",
  1739. mo: protojson.MarshalOptions{
  1740. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
  1741. },
  1742. input: func() proto.Message {
  1743. m := &structpb.Value{Kind: &structpb.Value_NullValue{}}
  1744. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1745. if err != nil {
  1746. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1747. }
  1748. return &anypb.Any{
  1749. TypeUrl: "type.googleapis.com/google.protobuf.Value",
  1750. Value: b,
  1751. }
  1752. }(),
  1753. want: `{
  1754. "@type": "type.googleapis.com/google.protobuf.Value",
  1755. "value": null
  1756. }`,
  1757. }, {
  1758. desc: "Any with Struct",
  1759. mo: protojson.MarshalOptions{
  1760. Resolver: preg.NewTypes(
  1761. pimpl.Export{}.MessageTypeOf(&structpb.Struct{}),
  1762. pimpl.Export{}.MessageTypeOf(&structpb.Value{}),
  1763. pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{}),
  1764. pimpl.Export{}.EnumTypeOf(structpb.NullValue_NULL_VALUE),
  1765. pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
  1766. ),
  1767. },
  1768. input: func() proto.Message {
  1769. m := &structpb.Struct{
  1770. Fields: map[string]*structpb.Value{
  1771. "bool": {Kind: &structpb.Value_BoolValue{true}},
  1772. "null": {Kind: &structpb.Value_NullValue{}},
  1773. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  1774. "struct": {
  1775. Kind: &structpb.Value_StructValue{
  1776. &structpb.Struct{
  1777. Fields: map[string]*structpb.Value{
  1778. "string": {Kind: &structpb.Value_StringValue{"world"}},
  1779. },
  1780. },
  1781. },
  1782. },
  1783. },
  1784. }
  1785. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1786. if err != nil {
  1787. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1788. }
  1789. return &anypb.Any{
  1790. TypeUrl: "google.protobuf.Struct",
  1791. Value: b,
  1792. }
  1793. }(),
  1794. want: `{
  1795. "@type": "google.protobuf.Struct",
  1796. "value": {
  1797. "bool": true,
  1798. "null": null,
  1799. "string": "hello",
  1800. "struct": {
  1801. "string": "world"
  1802. }
  1803. }
  1804. }`,
  1805. }, {
  1806. desc: "Any with missing type_url",
  1807. mo: protojson.MarshalOptions{
  1808. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{})),
  1809. },
  1810. input: func() proto.Message {
  1811. m := &wrapperspb.BoolValue{Value: true}
  1812. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1813. if err != nil {
  1814. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1815. }
  1816. return &anypb.Any{
  1817. Value: b,
  1818. }
  1819. }(),
  1820. wantErr: true,
  1821. }, {
  1822. desc: "well known types as field values",
  1823. mo: protojson.MarshalOptions{
  1824. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
  1825. },
  1826. input: &pb2.KnownTypes{
  1827. OptBool: &wrapperspb.BoolValue{Value: false},
  1828. OptInt32: &wrapperspb.Int32Value{Value: 42},
  1829. OptInt64: &wrapperspb.Int64Value{Value: 42},
  1830. OptUint32: &wrapperspb.UInt32Value{Value: 42},
  1831. OptUint64: &wrapperspb.UInt64Value{Value: 42},
  1832. OptFloat: &wrapperspb.FloatValue{Value: 1.23},
  1833. OptDouble: &wrapperspb.DoubleValue{Value: 3.1415},
  1834. OptString: &wrapperspb.StringValue{Value: "hello"},
  1835. OptBytes: &wrapperspb.BytesValue{Value: []byte("hello")},
  1836. OptDuration: &durationpb.Duration{Seconds: 123},
  1837. OptTimestamp: &timestamppb.Timestamp{Seconds: 1553036601},
  1838. OptStruct: &structpb.Struct{
  1839. Fields: map[string]*structpb.Value{
  1840. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  1841. },
  1842. },
  1843. OptList: &structpb.ListValue{
  1844. Values: []*structpb.Value{
  1845. {Kind: &structpb.Value_NullValue{}},
  1846. {Kind: &structpb.Value_StringValue{}},
  1847. {Kind: &structpb.Value_StructValue{}},
  1848. {Kind: &structpb.Value_ListValue{}},
  1849. },
  1850. },
  1851. OptValue: &structpb.Value{
  1852. Kind: &structpb.Value_StringValue{"world"},
  1853. },
  1854. OptEmpty: &emptypb.Empty{},
  1855. OptAny: &anypb.Any{
  1856. TypeUrl: "google.protobuf.Empty",
  1857. },
  1858. OptFieldmask: &fieldmaskpb.FieldMask{
  1859. Paths: []string{"foo_bar", "bar_foo"},
  1860. },
  1861. },
  1862. want: `{
  1863. "optBool": false,
  1864. "optInt32": 42,
  1865. "optInt64": "42",
  1866. "optUint32": 42,
  1867. "optUint64": "42",
  1868. "optFloat": 1.23,
  1869. "optDouble": 3.1415,
  1870. "optString": "hello",
  1871. "optBytes": "aGVsbG8=",
  1872. "optDuration": "123s",
  1873. "optTimestamp": "2019-03-19T23:03:21Z",
  1874. "optStruct": {
  1875. "string": "hello"
  1876. },
  1877. "optList": [
  1878. null,
  1879. "",
  1880. {},
  1881. []
  1882. ],
  1883. "optValue": "world",
  1884. "optEmpty": {},
  1885. "optAny": {
  1886. "@type": "google.protobuf.Empty",
  1887. "value": {}
  1888. },
  1889. "optFieldmask": "fooBar,barFoo"
  1890. }`,
  1891. }}
  1892. for _, tt := range tests {
  1893. tt := tt
  1894. t.Run(tt.desc, func(t *testing.T) {
  1895. // Use 2-space indentation on all MarshalOptions.
  1896. tt.mo.Indent = " "
  1897. b, err := tt.mo.Marshal(tt.input)
  1898. if err != nil && !tt.wantErr {
  1899. t.Errorf("Marshal() returned error: %v\n", err)
  1900. }
  1901. if err == nil && tt.wantErr {
  1902. t.Errorf("Marshal() got nil error, want error\n")
  1903. }
  1904. got := string(b)
  1905. if got != tt.want {
  1906. t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
  1907. if diff := cmp.Diff(tt.want, got); diff != "" {
  1908. t.Errorf("Marshal() diff -want +got\n%v\n", diff)
  1909. }
  1910. }
  1911. })
  1912. }
  1913. }