encode_test.go 12 KB

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