decode_test.go 21 KB

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