decode_test.go 21 KB

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