decode_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. package wire
  2. import (
  3. "bytes"
  4. "io"
  5. "testing"
  6. "github.com/stretchr/testify/assert"
  7. )
  8. func TestUnmarshal(t *testing.T) {
  9. tests := []struct {
  10. name string
  11. prototype any
  12. given []byte
  13. want any
  14. wantErr error
  15. }{
  16. {
  17. name: "uint8",
  18. prototype: &struct {
  19. Val uint8
  20. }{},
  21. want: &struct {
  22. Val uint8
  23. }{
  24. Val: 100,
  25. },
  26. given: []byte{0x64},
  27. },
  28. {
  29. name: "uint8 with read error",
  30. prototype: &struct {
  31. Val uint8
  32. }{},
  33. wantErr: io.EOF,
  34. given: []byte{},
  35. },
  36. {
  37. name: "uint16",
  38. prototype: &struct {
  39. Val uint16
  40. }{},
  41. want: &struct {
  42. Val uint16
  43. }{
  44. Val: 100,
  45. },
  46. given: []byte{0x0, 0x64},
  47. },
  48. {
  49. name: "uint16 with read error",
  50. prototype: &struct {
  51. Val uint16
  52. }{},
  53. wantErr: io.EOF,
  54. given: []byte{},
  55. },
  56. {
  57. name: "uint32",
  58. prototype: &struct {
  59. Val uint32
  60. }{},
  61. want: &struct {
  62. Val uint32
  63. }{
  64. Val: 100,
  65. },
  66. given: []byte{0x0, 0x0, 0x0, 0x64},
  67. },
  68. {
  69. name: "uint32 with read error",
  70. prototype: &struct {
  71. Val uint32
  72. }{},
  73. wantErr: io.EOF,
  74. given: []byte{},
  75. },
  76. {
  77. name: "uint64",
  78. prototype: &struct {
  79. Val uint64
  80. }{},
  81. want: &struct {
  82. Val uint64
  83. }{
  84. Val: 100,
  85. },
  86. given: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64},
  87. },
  88. {
  89. name: "uint64 with read error",
  90. prototype: &struct {
  91. Val uint64
  92. }{},
  93. wantErr: io.EOF,
  94. given: []byte{},
  95. },
  96. {
  97. name: "string8",
  98. prototype: &struct {
  99. Val string `oscar:"len_prefix=uint8"`
  100. }{},
  101. want: &struct {
  102. Val string `oscar:"len_prefix=uint8"`
  103. }{
  104. Val: "test-value",
  105. },
  106. given: append(
  107. []byte{0xa}, /* len prefix */
  108. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  109. },
  110. {
  111. name: "string8 read error",
  112. prototype: &struct {
  113. Val string `oscar:"len_prefix=uint8"`
  114. }{},
  115. given: []byte{},
  116. wantErr: io.EOF,
  117. },
  118. {
  119. name: "string16",
  120. prototype: &struct {
  121. Val string `oscar:"len_prefix=uint16"`
  122. }{},
  123. want: &struct {
  124. Val string `oscar:"len_prefix=uint16"`
  125. }{
  126. Val: "test-value",
  127. },
  128. given: append(
  129. []byte{0x0, 0xa}, /* len prefix */
  130. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  131. },
  132. {
  133. name: "string16 read error",
  134. prototype: &struct {
  135. Val string `oscar:"len_prefix=uint16"`
  136. }{},
  137. given: []byte{},
  138. wantErr: io.EOF,
  139. },
  140. {
  141. name: "unsupported string prefix type",
  142. prototype: &struct {
  143. Val string `oscar:"len_prefix=uint128"`
  144. }{},
  145. wantErr: ErrUnmarshalFailure,
  146. given: append(
  147. []byte{0x0, 0xa}, /* len prefix */
  148. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  149. },
  150. {
  151. name: "string with missing len_prefix",
  152. prototype: &struct {
  153. Val string
  154. }{},
  155. wantErr: ErrUnmarshalFailure,
  156. given: append(
  157. []byte{0x0, 0xa}, /* len prefix */
  158. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  159. },
  160. {
  161. name: "partial string8",
  162. prototype: &struct {
  163. Val string `oscar:"len_prefix=uint8"`
  164. }{},
  165. wantErr: io.EOF,
  166. given: append(
  167. []byte{0xa}, /* len prefix */
  168. []byte{}...), /* truncated payload */
  169. },
  170. {
  171. name: "byte slice with uint8 len_prefix",
  172. prototype: &struct {
  173. Val []byte `oscar:"len_prefix=uint8"`
  174. }{},
  175. want: &struct {
  176. Val []byte `oscar:"len_prefix=uint8"`
  177. }{
  178. Val: []byte(`hello`),
  179. },
  180. given: append(
  181. []byte{0x05}, /* len prefix */
  182. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  183. },
  184. {
  185. name: "slice of invalid type with uint8 len_prefix",
  186. prototype: &struct {
  187. Val []int `oscar:"len_prefix=uint8"`
  188. }{},
  189. wantErr: ErrUnmarshalFailure,
  190. given: []byte{0x04, 0x65, 0x6c, 0x6c, 0x6f},
  191. },
  192. {
  193. name: "byte slice with uint8 len_prefix with read error",
  194. prototype: &struct {
  195. Val []byte `oscar:"len_prefix=uint8"`
  196. }{},
  197. wantErr: io.EOF,
  198. given: append(
  199. []byte{0x05}, /* len prefix */
  200. []byte{}...), /* slice val */
  201. },
  202. {
  203. name: "byte slice with uint8 len_prefix read error",
  204. prototype: &struct {
  205. Val []byte `oscar:"len_prefix=uint8"`
  206. }{},
  207. wantErr: io.EOF,
  208. given: []byte{},
  209. },
  210. {
  211. name: "byte slice with uint16 len_prefix",
  212. prototype: &struct {
  213. Val []byte `oscar:"len_prefix=uint16"`
  214. }{},
  215. want: &struct {
  216. Val []byte `oscar:"len_prefix=uint16"`
  217. }{
  218. Val: []byte(`hello`),
  219. },
  220. given: append(
  221. []byte{0x00, 0x05}, /* len prefix */
  222. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  223. },
  224. {
  225. name: "byte slice with uint16 len_prefix read error",
  226. prototype: &struct {
  227. Val []byte `oscar:"len_prefix=uint16"`
  228. }{},
  229. wantErr: io.EOF,
  230. given: []byte{},
  231. },
  232. {
  233. name: "byte slice with invalid len_prefix",
  234. prototype: &struct {
  235. Val []byte `oscar:"len_prefix=uint128"`
  236. }{},
  237. wantErr: ErrUnmarshalFailure,
  238. given: append(
  239. []byte{0x00, 0x05}, /* len prefix */
  240. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  241. },
  242. {
  243. name: "struct slice without prefix",
  244. prototype: &struct {
  245. Val []TLV
  246. }{},
  247. want: &struct {
  248. Val []TLV
  249. }{
  250. Val: []TLV{
  251. NewTLV(10, uint16(1234)),
  252. NewTLV(20, uint16(1234)),
  253. },
  254. },
  255. given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  256. },
  257. {
  258. name: "slice of unsupported type without prefix",
  259. prototype: &struct {
  260. Val []int
  261. }{},
  262. wantErr: ErrUnmarshalFailure,
  263. given: []byte{0x0, 0xa, 0x0, 0x2},
  264. },
  265. {
  266. name: "struct slice with uint8 count_prefix",
  267. prototype: &struct {
  268. Val []TLV `oscar:"count_prefix=uint8"`
  269. }{},
  270. want: &struct {
  271. Val []TLV `oscar:"count_prefix=uint8"`
  272. }{
  273. Val: []TLV{
  274. NewTLV(10, uint16(1234)),
  275. NewTLV(20, uint16(1234)),
  276. },
  277. },
  278. given: append(
  279. []byte{0x02}, /* count prefix */
  280. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  281. },
  282. {
  283. name: "struct slice with uint8 count_prefix and unsupported type",
  284. prototype: &struct {
  285. Val []struct {
  286. Val int16
  287. } `oscar:"count_prefix=uint8"`
  288. }{},
  289. wantErr: ErrUnmarshalFailure,
  290. given: append(
  291. []byte{0x02}, /* count prefix */
  292. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  293. },
  294. {
  295. name: "struct slice with uint8 count_prefix read error",
  296. prototype: &struct {
  297. Val []TLV `oscar:"count_prefix=uint8"`
  298. }{},
  299. wantErr: io.EOF,
  300. given: []byte{},
  301. },
  302. {
  303. name: "struct slice with uint16 count_prefix",
  304. prototype: &struct {
  305. Val []TLV `oscar:"count_prefix=uint16"`
  306. }{},
  307. want: &struct {
  308. Val []TLV `oscar:"count_prefix=uint16"`
  309. }{
  310. Val: []TLV{
  311. NewTLV(10, uint16(1234)),
  312. NewTLV(20, uint16(1234)),
  313. },
  314. },
  315. given: append(
  316. []byte{0x0, 0x02}, /* count prefix */
  317. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  318. },
  319. {
  320. name: "struct slice with uint16 count_prefix and unsupported type",
  321. prototype: &struct {
  322. Val []struct {
  323. Val int16
  324. } `oscar:"count_prefix=uint16"`
  325. }{},
  326. wantErr: ErrUnmarshalFailure,
  327. given: append(
  328. []byte{0x0, 0x02}, /* count prefix */
  329. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  330. },
  331. {
  332. name: "struct slice with uint16 count_prefix read error",
  333. prototype: &struct {
  334. Val []TLV `oscar:"count_prefix=uint16"`
  335. }{},
  336. wantErr: io.EOF,
  337. given: []byte{},
  338. },
  339. {
  340. name: "struct slice with invalid count_prefix",
  341. prototype: &struct {
  342. Val []TLV `oscar:"count_prefix=uint128"`
  343. }{},
  344. wantErr: ErrUnmarshalFailure,
  345. given: append(
  346. []byte{0x0, 0x02}, /* count prefix */
  347. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  348. },
  349. {
  350. name: "struct with uint8 len_prefix",
  351. prototype: &struct {
  352. Val0 uint8
  353. Val1 struct {
  354. Val2 uint16
  355. Val3 uint8
  356. } `oscar:"len_prefix=uint8"`
  357. Val4 uint16
  358. }{},
  359. want: &struct {
  360. Val0 uint8
  361. Val1 struct {
  362. Val2 uint16
  363. Val3 uint8
  364. } `oscar:"len_prefix=uint8"`
  365. Val4 uint16
  366. }{
  367. Val0: 34,
  368. Val1: struct {
  369. Val2 uint16
  370. Val3 uint8
  371. }{
  372. Val2: 16,
  373. Val3: 10,
  374. },
  375. Val4: 32,
  376. },
  377. given: []byte{
  378. 0x22, // Val0
  379. 0x03, // Val1 struct len
  380. 0x00, 0x10, // Val2
  381. 0x0A, // Val3
  382. 0x00, 0x20, // Val2
  383. },
  384. },
  385. {
  386. name: "struct with uint16 len_prefix",
  387. prototype: &struct {
  388. Val0 uint8
  389. Val1 struct {
  390. Val2 uint16
  391. Val3 uint8
  392. } `oscar:"len_prefix=uint16"`
  393. Val4 uint16
  394. }{},
  395. want: &struct {
  396. Val0 uint8
  397. Val1 struct {
  398. Val2 uint16
  399. Val3 uint8
  400. } `oscar:"len_prefix=uint16"`
  401. Val4 uint16
  402. }{
  403. Val0: 34,
  404. Val1: struct {
  405. Val2 uint16
  406. Val3 uint8
  407. }{
  408. Val2: 16,
  409. Val3: 10,
  410. },
  411. Val4: 32,
  412. },
  413. given: []byte{
  414. 0x22, // Val0
  415. 0x00, 0x03, // Val1 struct len
  416. 0x00, 0x10, // Val2
  417. 0x0A, // Val3
  418. 0x00, 0x20, // Val2
  419. },
  420. },
  421. {
  422. name: "struct with uint16 len_prefix with read error",
  423. prototype: &struct {
  424. Val1 struct {
  425. Val2 uint16
  426. } `oscar:"len_prefix=uint16"`
  427. }{},
  428. given: []byte{
  429. 0x00, 0x10, // 16 byte len, but the body is truncated
  430. },
  431. wantErr: io.EOF,
  432. },
  433. {
  434. name: "struct with unknown len_prefix",
  435. prototype: &struct {
  436. Val1 struct {
  437. Val2 uint16
  438. } `oscar:"len_prefix=uint128"`
  439. }{},
  440. wantErr: ErrUnmarshalFailure,
  441. },
  442. {
  443. name: "optional struct has value",
  444. prototype: &struct {
  445. Val0 uint16
  446. Optional *struct {
  447. Val1 uint16
  448. } `oscar:"optional"`
  449. }{},
  450. want: &struct {
  451. Val0 uint16
  452. Optional *struct {
  453. Val1 uint16
  454. } `oscar:"optional"`
  455. }{
  456. Val0: 34,
  457. Optional: &struct {
  458. Val1 uint16
  459. }{
  460. Val1: 100,
  461. },
  462. },
  463. given: []byte{
  464. 0x00, 0x22, // Val0
  465. 0x00, 0x64, // Val1
  466. },
  467. },
  468. {
  469. name: "optional struct with value missing `optional` struct tag",
  470. prototype: &struct {
  471. Val0 uint16
  472. Optional *struct {
  473. Val1 uint16
  474. }
  475. }{},
  476. given: []byte{
  477. 0x00, 0x22, // Val0
  478. 0x00, 0x64, // Val1
  479. },
  480. wantErr: ErrUnmarshalFailure,
  481. },
  482. {
  483. name: "optional struct doesn't have value",
  484. prototype: &struct {
  485. Val0 uint16
  486. Optional *struct {
  487. Val1 uint16
  488. } `oscar:"optional"`
  489. }{},
  490. want: &struct {
  491. Val0 uint16
  492. Optional *struct {
  493. Val1 uint16
  494. } `oscar:"optional"`
  495. }{
  496. Val0: 34,
  497. Optional: nil,
  498. },
  499. given: []byte{
  500. 0x00, 0x22, // Val0
  501. },
  502. },
  503. {
  504. name: "optional struct followed by value throws error",
  505. prototype: &struct {
  506. Optional *struct {
  507. Val0 uint16
  508. } `oscar:"optional"`
  509. Val1 uint16
  510. }{},
  511. wantErr: ErrUnmarshalFailure,
  512. given: []byte{
  513. 0x00, 0x22, // Val0
  514. 0x00, 0x22, // Val1
  515. },
  516. },
  517. {
  518. name: "optional non-struct field throws error",
  519. prototype: &struct {
  520. Optional *uint16 `oscar:"optional"`
  521. }{},
  522. wantErr: ErrUnmarshalFailure,
  523. given: []byte{
  524. 0x00, 0x22, // Val0
  525. },
  526. },
  527. {
  528. name: "non-struct pointer value throws error",
  529. prototype: func() any {
  530. val := 10
  531. ptr1 := &val
  532. return &ptr1
  533. }(),
  534. wantErr: ErrUnmarshalFailure,
  535. given: []byte{
  536. 0x00, 0x22, // Val0
  537. },
  538. },
  539. {
  540. name: "optional struct with uint16 len_prefix and value",
  541. prototype: &struct {
  542. Val0 uint8
  543. Val1 *struct {
  544. Val2 uint16
  545. Val3 uint8
  546. } `oscar:"len_prefix=uint16,optional"`
  547. }{},
  548. want: &struct {
  549. Val0 uint8
  550. Val1 *struct {
  551. Val2 uint16
  552. Val3 uint8
  553. } `oscar:"len_prefix=uint16,optional"`
  554. }{
  555. Val0: 34,
  556. Val1: &struct {
  557. Val2 uint16
  558. Val3 uint8
  559. }{
  560. Val2: 16,
  561. Val3: 10,
  562. },
  563. },
  564. given: []byte{
  565. 0x22, // Val0
  566. 0x00, 0x03, // Val1 struct len
  567. 0x00, 0x10, // Val2
  568. 0x0A, // Val3
  569. 0x00, 0x20, // Val2
  570. },
  571. },
  572. {
  573. name: "optional struct with uint16 len_prefix and no value",
  574. prototype: &struct {
  575. Val0 uint8
  576. Val1 *struct {
  577. Val2 uint16
  578. Val3 uint8
  579. } `oscar:"len_prefix=uint16,optional"`
  580. }{},
  581. want: &struct {
  582. Val0 uint8
  583. Val1 *struct {
  584. Val2 uint16
  585. Val3 uint8
  586. } `oscar:"len_prefix=uint16,optional"`
  587. }{
  588. Val0: 34,
  589. Val1: nil,
  590. },
  591. given: []byte{
  592. 0x22, // Val0
  593. },
  594. },
  595. {
  596. name: "optional field that isn't a pointer to a struct is unsupported",
  597. prototype: &struct {
  598. Val1 *string `oscar:"optional"`
  599. }{},
  600. given: []byte{
  601. 0x00,
  602. },
  603. wantErr: errNonOptionalPointer,
  604. },
  605. }
  606. for _, tt := range tests {
  607. t.Run(tt.name, func(t *testing.T) {
  608. r := bytes.NewBuffer(tt.given)
  609. err := UnmarshalBE(tt.prototype, r)
  610. assert.ErrorIs(t, err, tt.wantErr)
  611. if tt.wantErr == nil {
  612. assert.Equal(t, tt.want, tt.prototype)
  613. }
  614. })
  615. }
  616. }