encode_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  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: []byte{0x0, 0x0}, /* len prefix */
  126. },
  127. {
  128. name: "string16 write error",
  129. w: errWriter{},
  130. given: struct {
  131. Val string `oscar:"len_prefix=uint16"`
  132. }{
  133. Val: "test-value",
  134. },
  135. wantErr: io.EOF,
  136. },
  137. {
  138. name: "string with unknown prefix type",
  139. w: &bytes.Buffer{},
  140. given: struct {
  141. Val string `oscar:"len_prefix=uint128"`
  142. }{
  143. Val: "test-value",
  144. },
  145. wantErr: ErrMarshalFailure,
  146. },
  147. {
  148. name: "byte slice with no prefix",
  149. w: &bytes.Buffer{},
  150. given: struct {
  151. Val []byte
  152. }{
  153. Val: []byte(`hello`),
  154. },
  155. want: []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f},
  156. },
  157. {
  158. name: "byte slice with no prefix with write error",
  159. w: &bytes.Buffer{},
  160. given: struct {
  161. Val []int
  162. }{
  163. Val: []int{1, 2, 3, 4},
  164. },
  165. wantErr: ErrMarshalFailure,
  166. },
  167. {
  168. name: "byte slice with no prefix with write error",
  169. w: errWriter{},
  170. given: struct {
  171. Val []byte
  172. }{
  173. Val: []byte(`hello`),
  174. },
  175. wantErr: io.EOF,
  176. },
  177. {
  178. name: "empty byte slice",
  179. w: &bytes.Buffer{},
  180. given: struct {
  181. Val []byte
  182. }{
  183. Val: []byte{},
  184. },
  185. want: []byte(nil),
  186. },
  187. {
  188. name: "byte slice with uint8 len_prefix",
  189. w: &bytes.Buffer{},
  190. given: struct {
  191. Val []byte `oscar:"len_prefix=uint8"`
  192. }{
  193. Val: []byte(`hello`),
  194. },
  195. want: append(
  196. []byte{0x05}, /* len prefix */
  197. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  198. },
  199. {
  200. name: "byte slice with uint8 len_prefix with error",
  201. w: errWriter{},
  202. given: struct {
  203. Val []byte `oscar:"len_prefix=uint8"`
  204. }{
  205. Val: []byte(`hello`),
  206. },
  207. wantErr: io.EOF,
  208. },
  209. {
  210. name: "byte slice with uint16 len_prefix",
  211. w: &bytes.Buffer{},
  212. given: struct {
  213. Val []byte `oscar:"len_prefix=uint16"`
  214. }{
  215. Val: []byte(`hello`),
  216. },
  217. want: append(
  218. []byte{0x00, 0x05}, /* len prefix */
  219. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  220. },
  221. {
  222. name: "byte slice with uint16 len_prefix with error",
  223. w: errWriter{},
  224. given: struct {
  225. Val []byte `oscar:"len_prefix=uint16"`
  226. }{
  227. Val: []byte(`hello`),
  228. },
  229. wantErr: io.EOF,
  230. },
  231. {
  232. name: "empty struct slice",
  233. w: &bytes.Buffer{},
  234. given: struct {
  235. Val []TLV
  236. }{
  237. Val: []TLV{},
  238. },
  239. want: []byte(nil),
  240. },
  241. {
  242. name: "struct slice with invalid type in struct",
  243. w: &bytes.Buffer{},
  244. given: struct {
  245. Val []struct {
  246. Val int16
  247. }
  248. }{
  249. Val: []struct {
  250. Val int16
  251. }{
  252. {
  253. Val: 1234,
  254. },
  255. },
  256. },
  257. wantErr: ErrMarshalFailure,
  258. },
  259. {
  260. name: "struct slice with uint8 count_prefix",
  261. w: &bytes.Buffer{},
  262. given: struct {
  263. Val []TLV `oscar:"count_prefix=uint8"`
  264. }{
  265. Val: []TLV{
  266. NewTLVBE(10, uint16(1234)),
  267. NewTLVBE(20, uint16(1234)),
  268. },
  269. },
  270. want: append(
  271. []byte{0x02}, /* count prefix */
  272. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  273. },
  274. {
  275. name: "struct slice with uint8 count_prefix with error",
  276. w: errWriter{},
  277. given: struct {
  278. Val []TLV `oscar:"count_prefix=uint8"`
  279. }{
  280. Val: []TLV{
  281. NewTLVBE(10, uint16(1234)),
  282. },
  283. },
  284. wantErr: io.EOF,
  285. },
  286. {
  287. name: "struct slice with uint16 count_prefix",
  288. w: &bytes.Buffer{},
  289. given: struct {
  290. Val []TLV `oscar:"count_prefix=uint16"`
  291. }{
  292. Val: []TLV{
  293. NewTLVBE(10, uint16(1234)),
  294. NewTLVBE(20, uint16(1234)),
  295. },
  296. },
  297. want: append(
  298. []byte{0x00, 0x02}, /* count prefix */
  299. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  300. },
  301. {
  302. name: "struct slice with uint16 count_prefix with error",
  303. w: errWriter{},
  304. given: struct {
  305. Val []TLV `oscar:"count_prefix=uint16"`
  306. }{
  307. Val: []TLV{
  308. NewTLVBE(10, uint16(1234)),
  309. },
  310. },
  311. wantErr: io.EOF,
  312. },
  313. {
  314. name: "byte slice with uint16 len_prefix and uint16 count_prefix",
  315. w: &bytes.Buffer{},
  316. given: struct {
  317. Val []byte `oscar:"len_prefix=uint16,count_prefix=uint16"`
  318. }{
  319. Val: []byte(`hello`),
  320. },
  321. wantErr: ErrMarshalFailure,
  322. },
  323. {
  324. name: "byte slice with unknown len_prefix type",
  325. w: &bytes.Buffer{},
  326. given: struct {
  327. Val []byte `oscar:"len_prefix=uint128"`
  328. }{
  329. Val: []byte(`hello`),
  330. },
  331. wantErr: ErrMarshalFailure,
  332. },
  333. {
  334. name: "byte slice with unknown count_prefix type",
  335. w: &bytes.Buffer{},
  336. given: struct {
  337. Val []byte `oscar:"count_prefix=uint128"`
  338. }{
  339. Val: []byte(`hello`),
  340. },
  341. wantErr: errInvalidStructTag,
  342. },
  343. {
  344. name: "empty snac",
  345. w: &bytes.Buffer{},
  346. given: nil,
  347. wantErr: errMarshalFailureNilSNAC,
  348. },
  349. {
  350. name: "struct with uint8 len_prefix",
  351. w: &bytes.Buffer{},
  352. given: struct {
  353. Val0 uint8
  354. Val1 struct {
  355. Val2 uint16
  356. Val3 uint8
  357. } `oscar:"len_prefix=uint8"`
  358. Val4 uint16
  359. }{
  360. Val0: 34,
  361. Val1: struct {
  362. Val2 uint16
  363. Val3 uint8
  364. }{
  365. Val2: 16,
  366. Val3: 10,
  367. },
  368. Val4: 32,
  369. },
  370. want: []byte{
  371. 0x22, // Val0
  372. 0x03, // Val1 struct len
  373. 0x00, 0x10, // Val2
  374. 0x0A, // Val3
  375. 0x00, 0x20, // Val2
  376. },
  377. },
  378. {
  379. name: "struct with uint16 len_prefix",
  380. w: &bytes.Buffer{},
  381. given: struct {
  382. Val0 uint8
  383. Val1 struct {
  384. Val2 uint16
  385. Val3 uint8
  386. } `oscar:"len_prefix=uint16"`
  387. Val4 uint16
  388. }{
  389. Val0: 34,
  390. Val1: struct {
  391. Val2 uint16
  392. Val3 uint8
  393. }{
  394. Val2: 16,
  395. Val3: 10,
  396. },
  397. Val4: 32,
  398. },
  399. want: []byte{
  400. 0x22, // Val0
  401. 0x00, 0x03, // Val1 struct len
  402. 0x00, 0x10, // Val2
  403. 0x0A, // Val3
  404. 0x00, 0x20, // Val2
  405. },
  406. },
  407. {
  408. name: "invalid struct with uint16 len_prefix",
  409. w: &bytes.Buffer{},
  410. given: struct {
  411. Val1 struct {
  412. Val2 int
  413. } `oscar:"len_prefix=uint16"`
  414. }{
  415. Val1: struct {
  416. Val2 int
  417. }{
  418. Val2: 16,
  419. },
  420. },
  421. wantErr: ErrMarshalFailure,
  422. },
  423. {
  424. name: "empty struct with uint16 len_prefix",
  425. w: &bytes.Buffer{},
  426. given: struct {
  427. Val1 struct {
  428. } `oscar:"len_prefix=uint16"`
  429. }{
  430. Val1: struct {
  431. }{},
  432. },
  433. want: []byte{
  434. 0x00, 0x00, // 0-len
  435. },
  436. },
  437. {
  438. name: "struct with unknown len_prefix",
  439. w: &bytes.Buffer{},
  440. given: struct {
  441. Val1 struct {
  442. Val2 uint16
  443. } `oscar:"len_prefix=uint128"`
  444. }{
  445. Val1: struct {
  446. Val2 uint16
  447. }{
  448. Val2: 16,
  449. },
  450. },
  451. wantErr: errInvalidStructTag,
  452. },
  453. {
  454. name: "optional struct has value",
  455. w: &bytes.Buffer{},
  456. given: struct {
  457. Val0 uint16
  458. Optional *struct {
  459. Val1 uint16
  460. } `oscar:"optional"`
  461. }{
  462. Val0: 34,
  463. Optional: &struct {
  464. Val1 uint16
  465. }{
  466. Val1: 100,
  467. },
  468. },
  469. want: []byte{
  470. 0x00, 0x22, // Val0
  471. 0x00, 0x64, // Val1
  472. },
  473. },
  474. {
  475. name: "optional struct with value missing `optional` struct tag",
  476. w: &bytes.Buffer{},
  477. given: struct {
  478. Val0 uint16
  479. Optional *struct {
  480. Val1 uint16
  481. }
  482. }{
  483. Val0: 34,
  484. Optional: &struct {
  485. Val1 uint16
  486. }{
  487. Val1: 100,
  488. },
  489. },
  490. wantErr: errNonOptionalPointer,
  491. },
  492. {
  493. name: "optional struct doesn't have value",
  494. w: &bytes.Buffer{},
  495. given: struct {
  496. Val0 uint16
  497. Optional *struct {
  498. Val1 uint16
  499. } `oscar:"optional"`
  500. }{
  501. Val0: 34,
  502. Optional: nil,
  503. },
  504. want: []byte{
  505. 0x00, 0x22, // Val0
  506. },
  507. },
  508. {
  509. name: "optional struct not last field throws error",
  510. w: &bytes.Buffer{},
  511. given: struct {
  512. Optional *struct {
  513. Val1 uint16
  514. } `oscar:"optional"`
  515. Val0 uint16
  516. }{
  517. Optional: nil,
  518. Val0: 34,
  519. },
  520. wantErr: ErrMarshalFailure,
  521. },
  522. {
  523. name: "optional non-pointer struct field throws error",
  524. w: &bytes.Buffer{},
  525. given: struct {
  526. Optional *string `oscar:"optional"`
  527. }{
  528. Optional: func() *string {
  529. v := "blahblah"
  530. return &v
  531. }(),
  532. },
  533. wantErr: ErrMarshalFailure,
  534. },
  535. {
  536. name: "non-struct pointer value throws error",
  537. w: &bytes.Buffer{},
  538. given: func() *string {
  539. v := "blahblah"
  540. return &v
  541. }(),
  542. wantErr: ErrMarshalFailure,
  543. },
  544. {
  545. name: "optional struct with uint16 len_prefix and 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: &struct {
  555. Val1 uint16
  556. }{
  557. Val1: 100,
  558. },
  559. },
  560. want: []byte{
  561. 0x00, 0x22, // Val0
  562. 0x00, 0x02, // Val0
  563. 0x00, 0x64, // Val1
  564. },
  565. },
  566. {
  567. name: "optional struct with uint16 len_prefix and no value",
  568. w: &bytes.Buffer{},
  569. given: struct {
  570. Val0 uint16
  571. Optional *struct {
  572. Val1 uint16
  573. } `oscar:"len_prefix=uint16,optional"`
  574. }{
  575. Val0: 34,
  576. Optional: nil,
  577. },
  578. want: []byte{
  579. 0x00, 0x22, // Val0
  580. },
  581. },
  582. {
  583. name: "optional field that isn't a pointer is unsupported",
  584. w: &bytes.Buffer{},
  585. given: struct {
  586. Val0 uint16
  587. Optional struct {
  588. Val1 uint16
  589. } `oscar:"len_prefix=uint16,optional"`
  590. }{
  591. Val0: 34,
  592. Optional: struct {
  593. Val1 uint16
  594. }{
  595. Val1: 100,
  596. },
  597. },
  598. wantErr: errOptionalNonPointer,
  599. },
  600. {
  601. name: "optional field that isn't a pointer to a struct is unsupported",
  602. w: &bytes.Buffer{},
  603. given: struct {
  604. Optional *string `oscar:"len_prefix=uint16,optional"`
  605. }{
  606. Optional: func() *string {
  607. v := "blahblah"
  608. return &v
  609. }(),
  610. },
  611. wantErr: ErrMarshalFailure,
  612. },
  613. {
  614. name: "struct with any type field containing a struct",
  615. w: &bytes.Buffer{},
  616. given: struct {
  617. Val1 uint8
  618. Val2 any
  619. }{
  620. Val1: 0x12,
  621. Val2: struct {
  622. Field1 uint16
  623. Field2 uint8
  624. }{
  625. Field1: 0x1234,
  626. Field2: 0x56,
  627. },
  628. },
  629. want: []byte{
  630. 0x12, // Val1
  631. 0x12, 0x34, // Val2.Field1 (uint16)
  632. 0x56, // Val2.Field2 (uint8)
  633. },
  634. },
  635. {
  636. name: "struct with any type field containing an empty struct",
  637. w: &bytes.Buffer{},
  638. given: struct {
  639. Val1 uint8
  640. Val2 any
  641. }{
  642. Val1: 0x12,
  643. Val2: struct{}{}, // empty struct
  644. },
  645. want: []byte{
  646. 0x12, // Val1
  647. },
  648. },
  649. {
  650. name: "struct with any type field containing a non-struct value",
  651. w: &bytes.Buffer{},
  652. given: struct {
  653. Val1 uint8
  654. Val2 any
  655. }{
  656. Val1: 0x12,
  657. Val2: "non-struct value", // non-struct value
  658. },
  659. wantErr: ErrMarshalFailure, // expecting an error because Val2 is not a struct
  660. },
  661. {
  662. name: "struct with ICQMessageReplyEnvelope field",
  663. w: &bytes.Buffer{},
  664. given: struct {
  665. Val1 uint16
  666. Val2 ICQMessageReplyEnvelope
  667. }{
  668. Val1: 0x1234,
  669. Val2: ICQMessageReplyEnvelope{
  670. Message: struct {
  671. Val3 uint16
  672. }{
  673. Val3: 0x1234,
  674. },
  675. },
  676. },
  677. want: []byte{
  678. // Big-endian encoding for Val1
  679. 0x12, 0x34, // Val1
  680. // Little-endian encoding for Val2.Message.Val3
  681. 0x2, 0x0, // Val2 len
  682. 0x34, 0x12, // Val2.Message.Val3
  683. },
  684. },
  685. {
  686. name: "byte array",
  687. w: &bytes.Buffer{},
  688. given: struct {
  689. Val [5]byte
  690. }{
  691. Val: [5]byte{'h', 'e', 'l', 'l', 'o'},
  692. },
  693. want: []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f},
  694. },
  695. {
  696. name: "byte array with error",
  697. w: errWriter{},
  698. given: struct {
  699. Val [5]byte
  700. }{
  701. Val: [5]byte{'h', 'e', 'l', 'l', 'o'},
  702. },
  703. wantErr: io.EOF,
  704. },
  705. {
  706. name: "struct array",
  707. w: &bytes.Buffer{},
  708. given: struct {
  709. Val [2]TLV
  710. }{
  711. Val: [2]TLV{
  712. NewTLVBE(10, uint16(1234)),
  713. NewTLVBE(20, uint16(1234)),
  714. },
  715. },
  716. want: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  717. },
  718. {
  719. name: "struct array with error",
  720. w: errWriter{},
  721. given: struct {
  722. Val [2]TLV
  723. }{
  724. Val: [2]TLV{
  725. NewTLVBE(10, uint16(1234)),
  726. NewTLVBE(20, uint16(1234)),
  727. },
  728. },
  729. wantErr: io.EOF,
  730. },
  731. {
  732. name: "duplicate quirk keys in oscar tag",
  733. w: &bytes.Buffer{},
  734. given: struct {
  735. V uint8 `oscar:"quirk=a,quirk=b"`
  736. }{V: 1},
  737. wantErr: errInvalidStructTag,
  738. },
  739. {
  740. name: "empty quirk value",
  741. w: &bytes.Buffer{},
  742. given: struct {
  743. V uint8 `oscar:"quirk="`
  744. }{V: 1},
  745. wantErr: errInvalidStructTag,
  746. },
  747. }
  748. for _, tt := range tests {
  749. t.Run(tt.name, func(t *testing.T) {
  750. err := MarshalBE(tt.given, tt.w)
  751. assert.ErrorIs(t, err, tt.wantErr)
  752. if tt.wantErr == nil {
  753. if w, ok := tt.w.(*bytes.Buffer); ok {
  754. assert.Equal(t, tt.want, w.Bytes())
  755. }
  756. }
  757. })
  758. }
  759. }