encode_test.go 12 KB

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