decode_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  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 jsonpb_test
  5. import (
  6. "math"
  7. "testing"
  8. protoV1 "github.com/golang/protobuf/proto"
  9. "github.com/golang/protobuf/v2/encoding/jsonpb"
  10. "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
  11. "github.com/golang/protobuf/v2/encoding/testprotos/pb3"
  12. "github.com/golang/protobuf/v2/internal/scalar"
  13. "github.com/golang/protobuf/v2/proto"
  14. )
  15. func TestUnmarshal(t *testing.T) {
  16. tests := []struct {
  17. desc string
  18. umo jsonpb.UnmarshalOptions
  19. inputMessage proto.Message
  20. inputText string
  21. wantMessage proto.Message
  22. // TODO: verify expected error message substring.
  23. wantErr bool
  24. }{{
  25. desc: "proto2 empty message",
  26. inputMessage: &pb2.Scalars{},
  27. inputText: "{}",
  28. wantMessage: &pb2.Scalars{},
  29. }, {
  30. desc: "unexpected value instead of EOF",
  31. inputMessage: &pb2.Scalars{},
  32. inputText: "{} {}",
  33. wantErr: true,
  34. }, {
  35. desc: "proto2 optional scalars set to zero values",
  36. inputMessage: &pb2.Scalars{},
  37. inputText: `{
  38. "optBool": false,
  39. "optInt32": 0,
  40. "optInt64": 0,
  41. "optUint32": 0,
  42. "optUint64": 0,
  43. "optSint32": 0,
  44. "optSint64": 0,
  45. "optFixed32": 0,
  46. "optFixed64": 0,
  47. "optSfixed32": 0,
  48. "optSfixed64": 0,
  49. "optFloat": 0,
  50. "optDouble": 0,
  51. "optBytes": "",
  52. "optString": ""
  53. }`,
  54. wantMessage: &pb2.Scalars{
  55. OptBool: scalar.Bool(false),
  56. OptInt32: scalar.Int32(0),
  57. OptInt64: scalar.Int64(0),
  58. OptUint32: scalar.Uint32(0),
  59. OptUint64: scalar.Uint64(0),
  60. OptSint32: scalar.Int32(0),
  61. OptSint64: scalar.Int64(0),
  62. OptFixed32: scalar.Uint32(0),
  63. OptFixed64: scalar.Uint64(0),
  64. OptSfixed32: scalar.Int32(0),
  65. OptSfixed64: scalar.Int64(0),
  66. OptFloat: scalar.Float32(0),
  67. OptDouble: scalar.Float64(0),
  68. OptBytes: []byte{},
  69. OptString: scalar.String(""),
  70. },
  71. }, {
  72. desc: "proto3 scalars set to zero values",
  73. inputMessage: &pb3.Scalars{},
  74. inputText: `{
  75. "sBool": false,
  76. "sInt32": 0,
  77. "sInt64": 0,
  78. "sUint32": 0,
  79. "sUint64": 0,
  80. "sSint32": 0,
  81. "sSint64": 0,
  82. "sFixed32": 0,
  83. "sFixed64": 0,
  84. "sSfixed32": 0,
  85. "sSfixed64": 0,
  86. "sFloat": 0,
  87. "sDouble": 0,
  88. "sBytes": "",
  89. "sString": ""
  90. }`,
  91. wantMessage: &pb3.Scalars{},
  92. }, {
  93. desc: "proto2 optional scalars set to null",
  94. inputMessage: &pb2.Scalars{},
  95. inputText: `{
  96. "optBool": null,
  97. "optInt32": null,
  98. "optInt64": null,
  99. "optUint32": null,
  100. "optUint64": null,
  101. "optSint32": null,
  102. "optSint64": null,
  103. "optFixed32": null,
  104. "optFixed64": null,
  105. "optSfixed32": null,
  106. "optSfixed64": null,
  107. "optFloat": null,
  108. "optDouble": null,
  109. "optBytes": null,
  110. "optString": null
  111. }`,
  112. wantMessage: &pb2.Scalars{},
  113. }, {
  114. desc: "proto3 scalars set to null",
  115. inputMessage: &pb3.Scalars{},
  116. inputText: `{
  117. "sBool": null,
  118. "sInt32": null,
  119. "sInt64": null,
  120. "sUint32": null,
  121. "sUint64": null,
  122. "sSint32": null,
  123. "sSint64": null,
  124. "sFixed32": null,
  125. "sFixed64": null,
  126. "sSfixed32": null,
  127. "sSfixed64": null,
  128. "sFloat": null,
  129. "sDouble": null,
  130. "sBytes": null,
  131. "sString": null
  132. }`,
  133. wantMessage: &pb3.Scalars{},
  134. }, {
  135. desc: "boolean",
  136. inputMessage: &pb3.Scalars{},
  137. inputText: `{"sBool": true}`,
  138. wantMessage: &pb3.Scalars{
  139. SBool: true,
  140. },
  141. }, {
  142. desc: "not boolean",
  143. inputMessage: &pb3.Scalars{},
  144. inputText: `{"sBool": "true"}`,
  145. wantErr: true,
  146. }, {
  147. desc: "float and double",
  148. inputMessage: &pb3.Scalars{},
  149. inputText: `{
  150. "sFloat": 1.234,
  151. "sDouble": 5.678
  152. }`,
  153. wantMessage: &pb3.Scalars{
  154. SFloat: 1.234,
  155. SDouble: 5.678,
  156. },
  157. }, {
  158. desc: "float and double in string",
  159. inputMessage: &pb3.Scalars{},
  160. inputText: `{
  161. "sFloat": "1.234",
  162. "sDouble": "5.678"
  163. }`,
  164. wantMessage: &pb3.Scalars{
  165. SFloat: 1.234,
  166. SDouble: 5.678,
  167. },
  168. }, {
  169. desc: "float and double in E notation",
  170. inputMessage: &pb3.Scalars{},
  171. inputText: `{
  172. "sFloat": 12.34E-1,
  173. "sDouble": 5.678e4
  174. }`,
  175. wantMessage: &pb3.Scalars{
  176. SFloat: 1.234,
  177. SDouble: 56780,
  178. },
  179. }, {
  180. desc: "float and double in string E notation",
  181. inputMessage: &pb3.Scalars{},
  182. inputText: `{
  183. "sFloat": "12.34E-1",
  184. "sDouble": "5.678e4"
  185. }`,
  186. wantMessage: &pb3.Scalars{
  187. SFloat: 1.234,
  188. SDouble: 56780,
  189. },
  190. }, {
  191. desc: "float exceeds limit",
  192. inputMessage: &pb3.Scalars{},
  193. inputText: `{"sFloat": 3.4e39}`,
  194. wantErr: true,
  195. }, {
  196. desc: "float in string exceeds limit",
  197. inputMessage: &pb3.Scalars{},
  198. inputText: `{"sFloat": "-3.4e39"}`,
  199. wantErr: true,
  200. }, {
  201. desc: "double exceeds limit",
  202. inputMessage: &pb3.Scalars{},
  203. inputText: `{"sFloat": -1.79e+309}`,
  204. wantErr: true,
  205. }, {
  206. desc: "double in string exceeds limit",
  207. inputMessage: &pb3.Scalars{},
  208. inputText: `{"sFloat": "1.79e+309"}`,
  209. wantErr: true,
  210. }, {
  211. desc: "infinites",
  212. inputMessage: &pb3.Scalars{},
  213. inputText: `{"sFloat": "Infinity", "sDouble": "-Infinity"}`,
  214. wantMessage: &pb3.Scalars{
  215. SFloat: float32(math.Inf(+1)),
  216. SDouble: math.Inf(-1),
  217. },
  218. }, {
  219. desc: "not float",
  220. inputMessage: &pb3.Scalars{},
  221. inputText: `{"sFloat": true}`,
  222. wantErr: true,
  223. }, {
  224. desc: "not double",
  225. inputMessage: &pb3.Scalars{},
  226. inputText: `{"sDouble": "not a number"}`,
  227. wantErr: true,
  228. }, {
  229. desc: "integers",
  230. inputMessage: &pb3.Scalars{},
  231. inputText: `{
  232. "sInt32": 1234,
  233. "sInt64": -1234,
  234. "sUint32": 1e2,
  235. "sUint64": 100E-2,
  236. "sSint32": 1.0,
  237. "sSint64": -1.0,
  238. "sFixed32": 1.234e+5,
  239. "sFixed64": 1200E-2,
  240. "sSfixed32": -1.234e05,
  241. "sSfixed64": -1200e-02
  242. }`,
  243. wantMessage: &pb3.Scalars{
  244. SInt32: 1234,
  245. SInt64: -1234,
  246. SUint32: 100,
  247. SUint64: 1,
  248. SSint32: 1,
  249. SSint64: -1,
  250. SFixed32: 123400,
  251. SFixed64: 12,
  252. SSfixed32: -123400,
  253. SSfixed64: -12,
  254. },
  255. }, {
  256. desc: "integers in string",
  257. inputMessage: &pb3.Scalars{},
  258. inputText: `{
  259. "sInt32": "1234",
  260. "sInt64": "-1234",
  261. "sUint32": "1e2",
  262. "sUint64": "100E-2",
  263. "sSint32": "1.0",
  264. "sSint64": "-1.0",
  265. "sFixed32": "1.234e+5",
  266. "sFixed64": "1200E-2",
  267. "sSfixed32": "-1.234e05",
  268. "sSfixed64": "-1200e-02"
  269. }`,
  270. wantMessage: &pb3.Scalars{
  271. SInt32: 1234,
  272. SInt64: -1234,
  273. SUint32: 100,
  274. SUint64: 1,
  275. SSint32: 1,
  276. SSint64: -1,
  277. SFixed32: 123400,
  278. SFixed64: 12,
  279. SSfixed32: -123400,
  280. SSfixed64: -12,
  281. },
  282. }, {
  283. desc: "integers in escaped string",
  284. inputMessage: &pb3.Scalars{},
  285. inputText: `{"sInt32": "\u0031\u0032"}`,
  286. wantMessage: &pb3.Scalars{
  287. SInt32: 12,
  288. },
  289. }, {
  290. desc: "number is not an integer",
  291. inputMessage: &pb3.Scalars{},
  292. inputText: `{"sInt32": 1.001}`,
  293. wantErr: true,
  294. }, {
  295. desc: "32-bit int exceeds limit",
  296. inputMessage: &pb3.Scalars{},
  297. inputText: `{"sInt32": 2e10}`,
  298. wantErr: true,
  299. }, {
  300. desc: "64-bit int exceeds limit",
  301. inputMessage: &pb3.Scalars{},
  302. inputText: `{"sSfixed64": -9e19}`,
  303. wantErr: true,
  304. }, {
  305. desc: "not integer",
  306. inputMessage: &pb3.Scalars{},
  307. inputText: `{"sInt32": "not a number"}`,
  308. wantErr: true,
  309. }, {
  310. desc: "not unsigned integer",
  311. inputMessage: &pb3.Scalars{},
  312. inputText: `{"sUint32": "not a number"}`,
  313. wantErr: true,
  314. }, {
  315. desc: "number is not an unsigned integer",
  316. inputMessage: &pb3.Scalars{},
  317. inputText: `{"sUint32": -1}`,
  318. wantErr: true,
  319. }, {
  320. desc: "string",
  321. inputMessage: &pb2.Scalars{},
  322. inputText: `{"optString": "谷歌"}`,
  323. wantMessage: &pb2.Scalars{
  324. OptString: scalar.String("谷歌"),
  325. },
  326. }, {
  327. desc: "string with invalid UTF-8",
  328. inputMessage: &pb3.Scalars{},
  329. inputText: "{\"sString\": \"\xff\"}",
  330. wantMessage: &pb3.Scalars{
  331. SString: "\xff",
  332. },
  333. wantErr: true,
  334. }, {
  335. desc: "not string",
  336. inputMessage: &pb2.Scalars{},
  337. inputText: `{"optString": 42}`,
  338. wantErr: true,
  339. }, {
  340. desc: "bytes",
  341. inputMessage: &pb3.Scalars{},
  342. inputText: `{"sBytes": "aGVsbG8gd29ybGQ"}`,
  343. wantMessage: &pb3.Scalars{
  344. SBytes: []byte("hello world"),
  345. },
  346. }, {
  347. desc: "bytes padded",
  348. inputMessage: &pb3.Scalars{},
  349. inputText: `{"sBytes": "aGVsbG8gd29ybGQ="}`,
  350. wantMessage: &pb3.Scalars{
  351. SBytes: []byte("hello world"),
  352. },
  353. }, {
  354. desc: "not bytes",
  355. inputMessage: &pb3.Scalars{},
  356. inputText: `{"sBytes": true}`,
  357. wantErr: true,
  358. }, {
  359. desc: "proto2 enum",
  360. inputMessage: &pb2.Enums{},
  361. inputText: `{
  362. "optEnum": "ONE",
  363. "optNestedEnum": "UNO"
  364. }`,
  365. wantMessage: &pb2.Enums{
  366. OptEnum: pb2.Enum_ONE.Enum(),
  367. OptNestedEnum: pb2.Enums_UNO.Enum(),
  368. },
  369. }, {
  370. desc: "proto3 enum",
  371. inputMessage: &pb3.Enums{},
  372. inputText: `{
  373. "sEnum": "ONE",
  374. "sNestedEnum": "DIEZ"
  375. }`,
  376. wantMessage: &pb3.Enums{
  377. SEnum: pb3.Enum_ONE,
  378. SNestedEnum: pb3.Enums_DIEZ,
  379. },
  380. }, {
  381. desc: "enum numeric value",
  382. inputMessage: &pb3.Enums{},
  383. inputText: `{
  384. "sEnum": 2,
  385. "sNestedEnum": 2
  386. }`,
  387. wantMessage: &pb3.Enums{
  388. SEnum: pb3.Enum_TWO,
  389. SNestedEnum: pb3.Enums_DOS,
  390. },
  391. }, {
  392. desc: "enum unnamed numeric value",
  393. inputMessage: &pb3.Enums{},
  394. inputText: `{
  395. "sEnum": 101,
  396. "sNestedEnum": -101
  397. }`,
  398. wantMessage: &pb3.Enums{
  399. SEnum: 101,
  400. SNestedEnum: -101,
  401. },
  402. }, {
  403. desc: "enum set to number string",
  404. inputMessage: &pb3.Enums{},
  405. inputText: `{
  406. "sEnum": "1",
  407. }`,
  408. wantErr: true,
  409. }, {
  410. desc: "enum set to invalid named",
  411. inputMessage: &pb3.Enums{},
  412. inputText: `{
  413. "sEnum": "UNNAMED",
  414. }`,
  415. wantErr: true,
  416. }, {
  417. desc: "enum set to not enum",
  418. inputMessage: &pb3.Enums{},
  419. inputText: `{
  420. "sEnum": true,
  421. }`,
  422. wantErr: true,
  423. }, {
  424. desc: "proto name",
  425. inputMessage: &pb3.JSONNames{},
  426. inputText: `{
  427. "s_string": "proto name used"
  428. }`,
  429. wantMessage: &pb3.JSONNames{
  430. SString: "proto name used",
  431. },
  432. }, {
  433. desc: "json_name",
  434. inputMessage: &pb3.JSONNames{},
  435. inputText: `{
  436. "foo_bar": "json_name used"
  437. }`,
  438. wantMessage: &pb3.JSONNames{
  439. SString: "json_name used",
  440. },
  441. }, {
  442. desc: "camelCase name",
  443. inputMessage: &pb3.JSONNames{},
  444. inputText: `{
  445. "sString": "camelcase used"
  446. }`,
  447. wantErr: true,
  448. }, {
  449. desc: "proto name and json_name",
  450. inputMessage: &pb3.JSONNames{},
  451. inputText: `{
  452. "foo_bar": "json_name used",
  453. "s_string": "proto name used"
  454. }`,
  455. wantErr: true,
  456. }, {
  457. desc: "duplicate field names",
  458. inputMessage: &pb3.JSONNames{},
  459. inputText: `{
  460. "foo_bar": "one",
  461. "foo_bar": "two",
  462. }`,
  463. wantErr: true,
  464. }, {
  465. desc: "null message",
  466. inputMessage: &pb2.Nests{},
  467. inputText: "null",
  468. wantErr: true,
  469. }, {
  470. desc: "proto2 nested message not set",
  471. inputMessage: &pb2.Nests{},
  472. inputText: "{}",
  473. wantMessage: &pb2.Nests{},
  474. }, {
  475. desc: "proto2 nested message set to null",
  476. inputMessage: &pb2.Nests{},
  477. inputText: `{
  478. "optNested": null,
  479. "optgroup": null
  480. }`,
  481. wantMessage: &pb2.Nests{},
  482. }, {
  483. desc: "proto2 nested message set to empty",
  484. inputMessage: &pb2.Nests{},
  485. inputText: `{
  486. "optNested": {},
  487. "optgroup": {}
  488. }`,
  489. wantMessage: &pb2.Nests{
  490. OptNested: &pb2.Nested{},
  491. Optgroup: &pb2.Nests_OptGroup{},
  492. },
  493. }, {
  494. desc: "proto2 nested messages",
  495. inputMessage: &pb2.Nests{},
  496. inputText: `{
  497. "optNested": {
  498. "optString": "nested message",
  499. "optNested": {
  500. "optString": "another nested message"
  501. }
  502. }
  503. }`,
  504. wantMessage: &pb2.Nests{
  505. OptNested: &pb2.Nested{
  506. OptString: scalar.String("nested message"),
  507. OptNested: &pb2.Nested{
  508. OptString: scalar.String("another nested message"),
  509. },
  510. },
  511. },
  512. }, {
  513. desc: "proto2 groups",
  514. inputMessage: &pb2.Nests{},
  515. inputText: `{
  516. "optgroup": {
  517. "optString": "inside a group",
  518. "optNested": {
  519. "optString": "nested message inside a group"
  520. },
  521. "optnestedgroup": {
  522. "optFixed32": 47
  523. }
  524. }
  525. }`,
  526. wantMessage: &pb2.Nests{
  527. Optgroup: &pb2.Nests_OptGroup{
  528. OptString: scalar.String("inside a group"),
  529. OptNested: &pb2.Nested{
  530. OptString: scalar.String("nested message inside a group"),
  531. },
  532. Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
  533. OptFixed32: scalar.Uint32(47),
  534. },
  535. },
  536. },
  537. }, {
  538. desc: "proto3 nested message not set",
  539. inputMessage: &pb3.Nests{},
  540. inputText: "{}",
  541. wantMessage: &pb3.Nests{},
  542. }, {
  543. desc: "proto3 nested message set to null",
  544. inputMessage: &pb3.Nests{},
  545. inputText: `{"sNested": null}`,
  546. wantMessage: &pb3.Nests{},
  547. }, {
  548. desc: "proto3 nested message set to empty",
  549. inputMessage: &pb3.Nests{},
  550. inputText: `{"sNested": {}}`,
  551. wantMessage: &pb3.Nests{
  552. SNested: &pb3.Nested{},
  553. },
  554. }, {
  555. desc: "proto3 nested message",
  556. inputMessage: &pb3.Nests{},
  557. inputText: `{
  558. "sNested": {
  559. "sString": "nested message",
  560. "sNested": {
  561. "sString": "another nested message"
  562. }
  563. }
  564. }`,
  565. wantMessage: &pb3.Nests{
  566. SNested: &pb3.Nested{
  567. SString: "nested message",
  568. SNested: &pb3.Nested{
  569. SString: "another nested message",
  570. },
  571. },
  572. },
  573. }, {
  574. desc: "message set to non-message",
  575. inputMessage: &pb3.Nests{},
  576. inputText: `"not valid"`,
  577. wantErr: true,
  578. }, {
  579. desc: "nested message set to non-message",
  580. inputMessage: &pb3.Nests{},
  581. inputText: `{"sNested": true}`,
  582. wantErr: true,
  583. }, {
  584. desc: "oneof not set",
  585. inputMessage: &pb3.Oneofs{},
  586. inputText: "{}",
  587. wantMessage: &pb3.Oneofs{},
  588. }, {
  589. desc: "oneof set to empty string",
  590. inputMessage: &pb3.Oneofs{},
  591. inputText: `{"oneofString": ""}`,
  592. wantMessage: &pb3.Oneofs{
  593. Union: &pb3.Oneofs_OneofString{},
  594. },
  595. }, {
  596. desc: "oneof set to string",
  597. inputMessage: &pb3.Oneofs{},
  598. inputText: `{"oneofString": "hello"}`,
  599. wantMessage: &pb3.Oneofs{
  600. Union: &pb3.Oneofs_OneofString{
  601. OneofString: "hello",
  602. },
  603. },
  604. }, {
  605. desc: "oneof set to enum",
  606. inputMessage: &pb3.Oneofs{},
  607. inputText: `{"oneofEnum": "ZERO"}`,
  608. wantMessage: &pb3.Oneofs{
  609. Union: &pb3.Oneofs_OneofEnum{
  610. OneofEnum: pb3.Enum_ZERO,
  611. },
  612. },
  613. }, {
  614. desc: "oneof set to empty message",
  615. inputMessage: &pb3.Oneofs{},
  616. inputText: `{"oneofNested": {}}`,
  617. wantMessage: &pb3.Oneofs{
  618. Union: &pb3.Oneofs_OneofNested{
  619. OneofNested: &pb3.Nested{},
  620. },
  621. },
  622. }, {
  623. desc: "oneof set to message",
  624. inputMessage: &pb3.Oneofs{},
  625. inputText: `{
  626. "oneofNested": {
  627. "sString": "nested message"
  628. }
  629. }`,
  630. wantMessage: &pb3.Oneofs{
  631. Union: &pb3.Oneofs_OneofNested{
  632. OneofNested: &pb3.Nested{
  633. SString: "nested message",
  634. },
  635. },
  636. },
  637. }, {
  638. desc: "repeated null fields",
  639. inputMessage: &pb2.Repeats{},
  640. inputText: `{
  641. "rptString": null,
  642. "rptInt32" : null,
  643. "rptFloat" : null,
  644. "rptBytes" : null
  645. }`,
  646. wantMessage: &pb2.Repeats{},
  647. }, {
  648. desc: "repeated scalars",
  649. inputMessage: &pb2.Repeats{},
  650. inputText: `{
  651. "rptString": ["hello", "world"],
  652. "rptInt32" : [-1, 0, 1],
  653. "rptBool" : [false, true]
  654. }`,
  655. wantMessage: &pb2.Repeats{
  656. RptString: []string{"hello", "world"},
  657. RptInt32: []int32{-1, 0, 1},
  658. RptBool: []bool{false, true},
  659. },
  660. }, {
  661. desc: "repeated enums",
  662. inputMessage: &pb2.Enums{},
  663. inputText: `{
  664. "rptEnum" : ["TEN", 1, 42],
  665. "rptNestedEnum": ["DOS", 2, -47]
  666. }`,
  667. wantMessage: &pb2.Enums{
  668. RptEnum: []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
  669. RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
  670. },
  671. }, {
  672. desc: "repeated messages",
  673. inputMessage: &pb2.Nests{},
  674. inputText: `{
  675. "rptNested": [
  676. {
  677. "optString": "repeat nested one"
  678. },
  679. {
  680. "optString": "repeat nested two",
  681. "optNested": {
  682. "optString": "inside repeat nested two"
  683. }
  684. },
  685. {}
  686. ]
  687. }`,
  688. wantMessage: &pb2.Nests{
  689. RptNested: []*pb2.Nested{
  690. {
  691. OptString: scalar.String("repeat nested one"),
  692. },
  693. {
  694. OptString: scalar.String("repeat nested two"),
  695. OptNested: &pb2.Nested{
  696. OptString: scalar.String("inside repeat nested two"),
  697. },
  698. },
  699. {},
  700. },
  701. },
  702. }, {
  703. desc: "repeated groups",
  704. inputMessage: &pb2.Nests{},
  705. inputText: `{
  706. "rptgroup": [
  707. {
  708. "rptString": ["hello", "world"]
  709. },
  710. {}
  711. ]
  712. }
  713. `,
  714. wantMessage: &pb2.Nests{
  715. Rptgroup: []*pb2.Nests_RptGroup{
  716. {
  717. RptString: []string{"hello", "world"},
  718. },
  719. {},
  720. },
  721. },
  722. }, {
  723. desc: "repeated scalars containing invalid type",
  724. inputMessage: &pb2.Repeats{},
  725. inputText: `{"rptString": ["hello", null, "world"]}`,
  726. wantErr: true,
  727. }, {
  728. desc: "repeated messages containing invalid type",
  729. inputMessage: &pb2.Nests{},
  730. inputText: `{"rptNested": [{}, null]}`,
  731. wantErr: true,
  732. }, {
  733. desc: "map fields 1",
  734. inputMessage: &pb3.Maps{},
  735. inputText: `{
  736. "int32ToStr": {
  737. "-101": "-101",
  738. "0" : "zero",
  739. "255" : "0xff"
  740. },
  741. "boolToUint32": {
  742. "false": 101,
  743. "true" : "42"
  744. }
  745. }`,
  746. wantMessage: &pb3.Maps{
  747. Int32ToStr: map[int32]string{
  748. -101: "-101",
  749. 0xff: "0xff",
  750. 0: "zero",
  751. },
  752. BoolToUint32: map[bool]uint32{
  753. true: 42,
  754. false: 101,
  755. },
  756. },
  757. }, {
  758. desc: "map fields 2",
  759. inputMessage: &pb3.Maps{},
  760. inputText: `{
  761. "uint64ToEnum": {
  762. "1" : "ONE",
  763. "2" : 2,
  764. "10": 101
  765. }
  766. }`,
  767. wantMessage: &pb3.Maps{
  768. Uint64ToEnum: map[uint64]pb3.Enum{
  769. 1: pb3.Enum_ONE,
  770. 2: pb3.Enum_TWO,
  771. 10: 101,
  772. },
  773. },
  774. }, {
  775. desc: "map fields 3",
  776. inputMessage: &pb3.Maps{},
  777. inputText: `{
  778. "strToNested": {
  779. "nested_one": {
  780. "sString": "nested in a map"
  781. },
  782. "nested_two": {}
  783. }
  784. }`,
  785. wantMessage: &pb3.Maps{
  786. StrToNested: map[string]*pb3.Nested{
  787. "nested_one": {
  788. SString: "nested in a map",
  789. },
  790. "nested_two": {},
  791. },
  792. },
  793. }, {
  794. desc: "map fields 4",
  795. inputMessage: &pb3.Maps{},
  796. inputText: `{
  797. "strToOneofs": {
  798. "nested": {
  799. "oneofNested": {
  800. "sString": "nested oneof in map field value"
  801. }
  802. },
  803. "string": {
  804. "oneofString": "hello"
  805. }
  806. }
  807. }`,
  808. wantMessage: &pb3.Maps{
  809. StrToOneofs: map[string]*pb3.Oneofs{
  810. "string": {
  811. Union: &pb3.Oneofs_OneofString{
  812. OneofString: "hello",
  813. },
  814. },
  815. "nested": {
  816. Union: &pb3.Oneofs_OneofNested{
  817. OneofNested: &pb3.Nested{
  818. SString: "nested oneof in map field value",
  819. },
  820. },
  821. },
  822. },
  823. },
  824. }, {
  825. desc: "map contains duplicate keys",
  826. inputMessage: &pb3.Maps{},
  827. inputText: `{
  828. "int32ToStr": {
  829. "0": "cero",
  830. "0": "zero"
  831. }
  832. }
  833. `,
  834. wantErr: true,
  835. }, {
  836. desc: "map key empty string",
  837. inputMessage: &pb3.Maps{},
  838. inputText: `{
  839. "strToNested": {
  840. "": {}
  841. }
  842. }`,
  843. wantMessage: &pb3.Maps{
  844. StrToNested: map[string]*pb3.Nested{
  845. "": {},
  846. },
  847. },
  848. }, {
  849. desc: "map contains invalid key 1",
  850. inputMessage: &pb3.Maps{},
  851. inputText: `{
  852. "int32ToStr": {
  853. "invalid": "cero"
  854. }`,
  855. wantErr: true,
  856. }, {
  857. desc: "map contains invalid key 2",
  858. inputMessage: &pb3.Maps{},
  859. inputText: `{
  860. "int32ToStr": {
  861. "1.02": "float"
  862. }`,
  863. wantErr: true,
  864. }, {
  865. desc: "map contains invalid key 3",
  866. inputMessage: &pb3.Maps{},
  867. inputText: `{
  868. "int32ToStr": {
  869. "2147483648": "exceeds 32-bit integer max limit"
  870. }`,
  871. wantErr: true,
  872. }, {
  873. desc: "map contains invalid key 4",
  874. inputMessage: &pb3.Maps{},
  875. inputText: `{
  876. "uint64ToEnum": {
  877. "-1": 0
  878. }
  879. }`,
  880. wantErr: true,
  881. }, {
  882. desc: "map contains invalid value",
  883. inputMessage: &pb3.Maps{},
  884. inputText: `{
  885. "int32ToStr": {
  886. "101": true
  887. }`,
  888. wantErr: true,
  889. }, {
  890. desc: "map contains null for scalar value",
  891. inputMessage: &pb3.Maps{},
  892. inputText: `{
  893. "int32ToStr": {
  894. "101": null
  895. }`,
  896. wantErr: true,
  897. }, {
  898. desc: "map contains null for message value",
  899. inputMessage: &pb3.Maps{},
  900. inputText: `{
  901. "strToNested": {
  902. "hello": null
  903. }
  904. }`,
  905. wantErr: true,
  906. }}
  907. for _, tt := range tests {
  908. tt := tt
  909. t.Run(tt.desc, func(t *testing.T) {
  910. err := tt.umo.Unmarshal(tt.inputMessage, []byte(tt.inputText))
  911. if err != nil && !tt.wantErr {
  912. t.Errorf("Unmarshal() returned error: %v\n\n", err)
  913. }
  914. if err == nil && tt.wantErr {
  915. t.Error("Unmarshal() got nil error, want error\n\n")
  916. }
  917. if tt.wantMessage != nil && !protoV1.Equal(tt.inputMessage.(protoV1.Message), tt.wantMessage.(protoV1.Message)) {
  918. t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
  919. }
  920. })
  921. }
  922. }