decode_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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: "null-terminated string16",
  134. prototype: &struct {
  135. Val string `oscar:"len_prefix=uint16,nullterm"`
  136. }{},
  137. want: &struct {
  138. Val string `oscar:"len_prefix=uint16,nullterm"`
  139. }{
  140. Val: "test-value",
  141. },
  142. given: append(
  143. []byte{0x0, 0xb}, /* len prefix */
  144. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00}...), /* str val */
  145. },
  146. {
  147. name: "null-terminated string16 with len 0",
  148. prototype: &struct {
  149. Val string `oscar:"len_prefix=uint16,nullterm"`
  150. }{},
  151. want: &struct {
  152. Val string `oscar:"len_prefix=uint16,nullterm"`
  153. }{
  154. Val: "",
  155. },
  156. given: []byte{0x0, 0x00}, /* len prefix */
  157. },
  158. {
  159. name: "null-terminated string16 without null terminator",
  160. prototype: &struct {
  161. Val string `oscar:"len_prefix=uint16,nullterm"`
  162. }{},
  163. wantErr: errNotNullTerminated,
  164. given: append(
  165. []byte{0x0, 0xa}, /* len prefix */
  166. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  167. },
  168. {
  169. name: "string16 read error",
  170. prototype: &struct {
  171. Val string `oscar:"len_prefix=uint16"`
  172. }{},
  173. given: []byte{},
  174. wantErr: io.EOF,
  175. },
  176. {
  177. name: "unsupported string prefix type",
  178. prototype: &struct {
  179. Val string `oscar:"len_prefix=uint128"`
  180. }{},
  181. wantErr: ErrUnmarshalFailure,
  182. given: append(
  183. []byte{0x0, 0xa}, /* len prefix */
  184. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  185. },
  186. {
  187. name: "string with missing len_prefix",
  188. prototype: &struct {
  189. Val string
  190. }{},
  191. wantErr: ErrUnmarshalFailure,
  192. given: append(
  193. []byte{0x0, 0xa}, /* len prefix */
  194. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  195. },
  196. {
  197. name: "partial string8",
  198. prototype: &struct {
  199. Val string `oscar:"len_prefix=uint8"`
  200. }{},
  201. wantErr: io.EOF,
  202. given: append(
  203. []byte{0xa}, /* len prefix */
  204. []byte{}...), /* truncated payload */
  205. },
  206. {
  207. name: "byte slice with uint8 len_prefix",
  208. prototype: &struct {
  209. Val []byte `oscar:"len_prefix=uint8"`
  210. }{},
  211. want: &struct {
  212. Val []byte `oscar:"len_prefix=uint8"`
  213. }{
  214. Val: []byte(`hello`),
  215. },
  216. given: append(
  217. []byte{0x05}, /* len prefix */
  218. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  219. },
  220. {
  221. name: "slice of invalid type with uint8 len_prefix",
  222. prototype: &struct {
  223. Val []int `oscar:"len_prefix=uint8"`
  224. }{},
  225. wantErr: ErrUnmarshalFailure,
  226. given: []byte{0x04, 0x65, 0x6c, 0x6c, 0x6f},
  227. },
  228. {
  229. name: "byte slice with uint8 len_prefix with read error",
  230. prototype: &struct {
  231. Val []byte `oscar:"len_prefix=uint8"`
  232. }{},
  233. wantErr: io.EOF,
  234. given: append(
  235. []byte{0x05}, /* len prefix */
  236. []byte{}...), /* slice val */
  237. },
  238. {
  239. name: "byte slice with uint8 len_prefix read error",
  240. prototype: &struct {
  241. Val []byte `oscar:"len_prefix=uint8"`
  242. }{},
  243. wantErr: io.EOF,
  244. given: []byte{},
  245. },
  246. {
  247. name: "byte slice with uint16 len_prefix",
  248. prototype: &struct {
  249. Val []byte `oscar:"len_prefix=uint16"`
  250. }{},
  251. want: &struct {
  252. Val []byte `oscar:"len_prefix=uint16"`
  253. }{
  254. Val: []byte(`hello`),
  255. },
  256. given: append(
  257. []byte{0x00, 0x05}, /* len prefix */
  258. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  259. },
  260. {
  261. name: "byte slice with uint16 len_prefix read error",
  262. prototype: &struct {
  263. Val []byte `oscar:"len_prefix=uint16"`
  264. }{},
  265. wantErr: io.EOF,
  266. given: []byte{},
  267. },
  268. {
  269. name: "byte slice with invalid len_prefix",
  270. prototype: &struct {
  271. Val []byte `oscar:"len_prefix=uint128"`
  272. }{},
  273. wantErr: ErrUnmarshalFailure,
  274. given: append(
  275. []byte{0x00, 0x05}, /* len prefix */
  276. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  277. },
  278. {
  279. name: "struct slice without prefix",
  280. prototype: &struct {
  281. Val []TLV
  282. }{},
  283. want: &struct {
  284. Val []TLV
  285. }{
  286. Val: []TLV{
  287. NewTLVBE(10, uint16(1234)),
  288. NewTLVBE(20, uint16(1234)),
  289. },
  290. },
  291. given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  292. },
  293. {
  294. name: "slice of unsupported type without prefix",
  295. prototype: &struct {
  296. Val []int
  297. }{},
  298. wantErr: ErrUnmarshalFailure,
  299. given: []byte{0x0, 0xa, 0x0, 0x2},
  300. },
  301. {
  302. name: "struct slice with uint8 count_prefix",
  303. prototype: &struct {
  304. Val []TLV `oscar:"count_prefix=uint8"`
  305. }{},
  306. want: &struct {
  307. Val []TLV `oscar:"count_prefix=uint8"`
  308. }{
  309. Val: []TLV{
  310. NewTLVBE(10, uint16(1234)),
  311. NewTLVBE(20, uint16(1234)),
  312. },
  313. },
  314. given: append(
  315. []byte{0x02}, /* count prefix */
  316. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  317. },
  318. {
  319. name: "struct slice with uint8 count_prefix and unsupported type",
  320. prototype: &struct {
  321. Val []struct {
  322. Val int16
  323. } `oscar:"count_prefix=uint8"`
  324. }{},
  325. wantErr: ErrUnmarshalFailure,
  326. given: append(
  327. []byte{0x02}, /* count prefix */
  328. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  329. },
  330. {
  331. name: "struct slice with uint8 count_prefix read error",
  332. prototype: &struct {
  333. Val []TLV `oscar:"count_prefix=uint8"`
  334. }{},
  335. wantErr: io.EOF,
  336. given: []byte{},
  337. },
  338. {
  339. name: "struct slice with uint16 count_prefix",
  340. prototype: &struct {
  341. Val []TLV `oscar:"count_prefix=uint16"`
  342. }{},
  343. want: &struct {
  344. Val []TLV `oscar:"count_prefix=uint16"`
  345. }{
  346. Val: []TLV{
  347. NewTLVBE(10, uint16(1234)),
  348. NewTLVBE(20, uint16(1234)),
  349. },
  350. },
  351. given: append(
  352. []byte{0x0, 0x02}, /* count prefix */
  353. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  354. },
  355. {
  356. name: "struct slice with uint16 count_prefix and unsupported type",
  357. prototype: &struct {
  358. Val []struct {
  359. Val int16
  360. } `oscar:"count_prefix=uint16"`
  361. }{},
  362. wantErr: ErrUnmarshalFailure,
  363. given: append(
  364. []byte{0x0, 0x02}, /* count prefix */
  365. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  366. },
  367. {
  368. name: "struct slice with uint16 count_prefix read error",
  369. prototype: &struct {
  370. Val []TLV `oscar:"count_prefix=uint16"`
  371. }{},
  372. wantErr: io.EOF,
  373. given: []byte{},
  374. },
  375. {
  376. name: "struct slice with invalid count_prefix",
  377. prototype: &struct {
  378. Val []TLV `oscar:"count_prefix=uint128"`
  379. }{},
  380. wantErr: ErrUnmarshalFailure,
  381. given: append(
  382. []byte{0x0, 0x02}, /* count prefix */
  383. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  384. },
  385. {
  386. name: "struct with uint8 len_prefix",
  387. prototype: &struct {
  388. Val0 uint8
  389. Val1 struct {
  390. Val2 uint16
  391. Val3 uint8
  392. } `oscar:"len_prefix=uint8"`
  393. Val4 uint16
  394. }{},
  395. want: &struct {
  396. Val0 uint8
  397. Val1 struct {
  398. Val2 uint16
  399. Val3 uint8
  400. } `oscar:"len_prefix=uint8"`
  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. 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",
  423. prototype: &struct {
  424. Val0 uint8
  425. Val1 struct {
  426. Val2 uint16
  427. Val3 uint8
  428. } `oscar:"len_prefix=uint16"`
  429. Val4 uint16
  430. }{},
  431. want: &struct {
  432. Val0 uint8
  433. Val1 struct {
  434. Val2 uint16
  435. Val3 uint8
  436. } `oscar:"len_prefix=uint16"`
  437. Val4 uint16
  438. }{
  439. Val0: 34,
  440. Val1: struct {
  441. Val2 uint16
  442. Val3 uint8
  443. }{
  444. Val2: 16,
  445. Val3: 10,
  446. },
  447. Val4: 32,
  448. },
  449. given: []byte{
  450. 0x22, // Val0
  451. 0x00, 0x03, // Val1 struct len
  452. 0x00, 0x10, // Val2
  453. 0x0A, // Val3
  454. 0x00, 0x20, // Val2
  455. },
  456. },
  457. {
  458. name: "struct with uint16 len_prefix with read error",
  459. prototype: &struct {
  460. Val1 struct {
  461. Val2 uint16
  462. } `oscar:"len_prefix=uint16"`
  463. }{},
  464. given: []byte{
  465. 0x00, 0x10, // 16 byte len, but the body is truncated
  466. },
  467. wantErr: io.EOF,
  468. },
  469. {
  470. name: "struct with unknown len_prefix",
  471. prototype: &struct {
  472. Val1 struct {
  473. Val2 uint16
  474. } `oscar:"len_prefix=uint128"`
  475. }{},
  476. wantErr: ErrUnmarshalFailure,
  477. },
  478. {
  479. name: "optional struct has value",
  480. prototype: &struct {
  481. Val0 uint16
  482. Optional *struct {
  483. Val1 uint16
  484. } `oscar:"optional"`
  485. }{},
  486. want: &struct {
  487. Val0 uint16
  488. Optional *struct {
  489. Val1 uint16
  490. } `oscar:"optional"`
  491. }{
  492. Val0: 34,
  493. Optional: &struct {
  494. Val1 uint16
  495. }{
  496. Val1: 100,
  497. },
  498. },
  499. given: []byte{
  500. 0x00, 0x22, // Val0
  501. 0x00, 0x64, // Val1
  502. },
  503. },
  504. {
  505. name: "optional struct with value missing `optional` struct tag",
  506. prototype: &struct {
  507. Val0 uint16
  508. Optional *struct {
  509. Val1 uint16
  510. }
  511. }{},
  512. given: []byte{
  513. 0x00, 0x22, // Val0
  514. 0x00, 0x64, // Val1
  515. },
  516. wantErr: ErrUnmarshalFailure,
  517. },
  518. {
  519. name: "optional struct doesn't have value",
  520. prototype: &struct {
  521. Val0 uint16
  522. Optional *struct {
  523. Val1 uint16
  524. } `oscar:"optional"`
  525. }{},
  526. want: &struct {
  527. Val0 uint16
  528. Optional *struct {
  529. Val1 uint16
  530. } `oscar:"optional"`
  531. }{
  532. Val0: 34,
  533. Optional: nil,
  534. },
  535. given: []byte{
  536. 0x00, 0x22, // Val0
  537. },
  538. },
  539. {
  540. name: "optional struct followed by value throws error",
  541. prototype: &struct {
  542. Optional *struct {
  543. Val0 uint16
  544. } `oscar:"optional"`
  545. Val1 uint16
  546. }{},
  547. wantErr: ErrUnmarshalFailure,
  548. given: []byte{
  549. 0x00, 0x22, // Val0
  550. 0x00, 0x22, // Val1
  551. },
  552. },
  553. {
  554. name: "optional non-struct field throws error",
  555. prototype: &struct {
  556. Optional *uint16 `oscar:"optional"`
  557. }{},
  558. wantErr: ErrUnmarshalFailure,
  559. given: []byte{
  560. 0x00, 0x22, // Val0
  561. },
  562. },
  563. {
  564. name: "non-struct pointer value throws error",
  565. prototype: func() any {
  566. val := 10
  567. ptr1 := &val
  568. return &ptr1
  569. }(),
  570. wantErr: ErrUnmarshalFailure,
  571. given: []byte{
  572. 0x00, 0x22, // Val0
  573. },
  574. },
  575. {
  576. name: "optional struct with uint16 len_prefix and value",
  577. prototype: &struct {
  578. Val0 uint8
  579. Val1 *struct {
  580. Val2 uint16
  581. Val3 uint8
  582. } `oscar:"len_prefix=uint16,optional"`
  583. }{},
  584. want: &struct {
  585. Val0 uint8
  586. Val1 *struct {
  587. Val2 uint16
  588. Val3 uint8
  589. } `oscar:"len_prefix=uint16,optional"`
  590. }{
  591. Val0: 34,
  592. Val1: &struct {
  593. Val2 uint16
  594. Val3 uint8
  595. }{
  596. Val2: 16,
  597. Val3: 10,
  598. },
  599. },
  600. given: []byte{
  601. 0x22, // Val0
  602. 0x00, 0x03, // Val1 struct len
  603. 0x00, 0x10, // Val2
  604. 0x0A, // Val3
  605. 0x00, 0x20, // Val2
  606. },
  607. },
  608. {
  609. name: "optional struct with uint16 len_prefix and no value",
  610. prototype: &struct {
  611. Val0 uint8
  612. Val1 *struct {
  613. Val2 uint16
  614. Val3 uint8
  615. } `oscar:"len_prefix=uint16,optional"`
  616. }{},
  617. want: &struct {
  618. Val0 uint8
  619. Val1 *struct {
  620. Val2 uint16
  621. Val3 uint8
  622. } `oscar:"len_prefix=uint16,optional"`
  623. }{
  624. Val0: 34,
  625. Val1: nil,
  626. },
  627. given: []byte{
  628. 0x22, // Val0
  629. },
  630. },
  631. {
  632. name: "optional field that isn't a pointer to a struct is unsupported",
  633. prototype: &struct {
  634. Val1 *string `oscar:"optional"`
  635. }{},
  636. given: []byte{
  637. 0x00,
  638. },
  639. wantErr: errNonOptionalPointer,
  640. },
  641. {
  642. name: "byte array",
  643. prototype: &struct {
  644. Val [5]byte
  645. }{},
  646. want: &struct {
  647. Val [5]byte
  648. }{
  649. Val: [5]byte{'h', 'e', 'l', 'l', 'o'},
  650. },
  651. given: []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f},
  652. },
  653. {
  654. name: "array of invalid type",
  655. prototype: &struct {
  656. Val [5]int
  657. }{},
  658. wantErr: ErrUnmarshalFailure,
  659. given: []byte{1, 2, 3, 4, 5},
  660. },
  661. {
  662. name: "struct array",
  663. prototype: &struct {
  664. Val [2]TLV
  665. }{},
  666. want: &struct {
  667. Val [2]TLV
  668. }{
  669. Val: [2]TLV{
  670. NewTLVBE(10, uint16(1234)),
  671. NewTLVBE(20, uint16(1234)),
  672. },
  673. },
  674. given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  675. },
  676. }
  677. for _, tt := range tests {
  678. t.Run(tt.name, func(t *testing.T) {
  679. r := bytes.NewBuffer(tt.given)
  680. err := UnmarshalBE(tt.prototype, r)
  681. assert.ErrorIs(t, err, tt.wantErr)
  682. if tt.wantErr == nil {
  683. assert.Equal(t, tt.want, tt.prototype)
  684. }
  685. })
  686. }
  687. }