encode_test.go 11 KB

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