decode_test.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  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 `len_prefix:"uint8"`
  100. }{},
  101. want: &struct {
  102. Val string `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 `len_prefix:"uint8"`
  114. }{},
  115. given: []byte{},
  116. wantErr: io.EOF,
  117. },
  118. {
  119. name: "string16",
  120. prototype: &struct {
  121. Val string `len_prefix:"uint16"`
  122. }{},
  123. want: &struct {
  124. Val string `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: "string16 read error",
  134. prototype: &struct {
  135. Val string `len_prefix:"uint16"`
  136. }{},
  137. given: []byte{},
  138. wantErr: io.EOF,
  139. },
  140. {
  141. name: "unsupported string prefix type",
  142. prototype: &struct {
  143. Val string `len_prefix:"uint128"`
  144. }{},
  145. wantErr: ErrUnmarshalFailure,
  146. given: append(
  147. []byte{0x0, 0xa}, /* len prefix */
  148. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  149. },
  150. {
  151. name: "string with missing len_prefix",
  152. prototype: &struct {
  153. Val string
  154. }{},
  155. wantErr: ErrUnmarshalFailure,
  156. given: append(
  157. []byte{0x0, 0xa}, /* len prefix */
  158. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  159. },
  160. {
  161. name: "partial string8",
  162. prototype: &struct {
  163. Val string `len_prefix:"uint8"`
  164. }{},
  165. wantErr: io.EOF,
  166. given: append(
  167. []byte{0xa}, /* len prefix */
  168. []byte{}...), /* truncated payload */
  169. },
  170. {
  171. name: "byte slice with uint8 len_prefix",
  172. prototype: &struct {
  173. Val []byte `len_prefix:"uint8"`
  174. }{},
  175. want: &struct {
  176. Val []byte `len_prefix:"uint8"`
  177. }{
  178. Val: []byte(`hello`),
  179. },
  180. given: append(
  181. []byte{0x05}, /* len prefix */
  182. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  183. },
  184. {
  185. name: "slice of invalid type with uint8 len_prefix",
  186. prototype: &struct {
  187. Val []int `len_prefix:"uint8"`
  188. }{},
  189. wantErr: ErrUnmarshalFailure,
  190. given: []byte{0x04, 0x65, 0x6c, 0x6c, 0x6f},
  191. },
  192. {
  193. name: "byte slice with uint8 len_prefix with read error",
  194. prototype: &struct {
  195. Val []byte `len_prefix:"uint8"`
  196. }{},
  197. wantErr: io.EOF,
  198. given: append(
  199. []byte{0x05}, /* len prefix */
  200. []byte{}...), /* slice val */
  201. },
  202. {
  203. name: "byte slice with uint8 len_prefix read error",
  204. prototype: &struct {
  205. Val []byte `len_prefix:"uint8"`
  206. }{},
  207. wantErr: io.EOF,
  208. given: []byte{},
  209. },
  210. {
  211. name: "byte slice with uint16 len_prefix",
  212. prototype: &struct {
  213. Val []byte `len_prefix:"uint16"`
  214. }{},
  215. want: &struct {
  216. Val []byte `len_prefix:"uint16"`
  217. }{
  218. Val: []byte(`hello`),
  219. },
  220. given: append(
  221. []byte{0x00, 0x05}, /* len prefix */
  222. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  223. },
  224. {
  225. name: "byte slice with uint16 len_prefix read error",
  226. prototype: &struct {
  227. Val []byte `len_prefix:"uint16"`
  228. }{},
  229. wantErr: io.EOF,
  230. given: []byte{},
  231. },
  232. {
  233. name: "byte slice with invalid len_prefix",
  234. prototype: &struct {
  235. Val []byte `len_prefix:"uint128"`
  236. }{},
  237. wantErr: ErrUnmarshalFailure,
  238. given: append(
  239. []byte{0x00, 0x05}, /* len prefix */
  240. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  241. },
  242. {
  243. name: "struct slice without prefix",
  244. prototype: &struct {
  245. Val []TLV
  246. }{},
  247. want: &struct {
  248. Val []TLV
  249. }{
  250. Val: []TLV{
  251. NewTLV(10, uint16(1234)),
  252. NewTLV(20, uint16(1234)),
  253. },
  254. },
  255. given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  256. },
  257. {
  258. name: "slice of unsupported type without prefix",
  259. prototype: &struct {
  260. Val []int
  261. }{},
  262. wantErr: ErrUnmarshalFailure,
  263. given: []byte{0x0, 0xa, 0x0, 0x2},
  264. },
  265. {
  266. name: "struct slice with uint8 count_prefix",
  267. prototype: &struct {
  268. Val []TLV `count_prefix:"uint8"`
  269. }{},
  270. want: &struct {
  271. Val []TLV `count_prefix:"uint8"`
  272. }{
  273. Val: []TLV{
  274. NewTLV(10, uint16(1234)),
  275. NewTLV(20, uint16(1234)),
  276. },
  277. },
  278. given: append(
  279. []byte{0x02}, /* count prefix */
  280. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  281. },
  282. {
  283. name: "struct slice with uint8 count_prefix and unsupported type",
  284. prototype: &struct {
  285. Val []struct {
  286. Val int16
  287. } `count_prefix:"uint8"`
  288. }{},
  289. wantErr: ErrUnmarshalFailure,
  290. given: append(
  291. []byte{0x02}, /* count prefix */
  292. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  293. },
  294. {
  295. name: "struct slice with uint8 count_prefix read error",
  296. prototype: &struct {
  297. Val []TLV `count_prefix:"uint8"`
  298. }{},
  299. wantErr: io.EOF,
  300. given: []byte{},
  301. },
  302. {
  303. name: "struct slice with uint16 count_prefix",
  304. prototype: &struct {
  305. Val []TLV `count_prefix:"uint16"`
  306. }{},
  307. want: &struct {
  308. Val []TLV `count_prefix:"uint16"`
  309. }{
  310. Val: []TLV{
  311. NewTLV(10, uint16(1234)),
  312. NewTLV(20, uint16(1234)),
  313. },
  314. },
  315. given: append(
  316. []byte{0x0, 0x02}, /* count prefix */
  317. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  318. },
  319. {
  320. name: "struct slice with uint16 count_prefix and unsupported type",
  321. prototype: &struct {
  322. Val []struct {
  323. Val int16
  324. } `count_prefix:"uint16"`
  325. }{},
  326. wantErr: ErrUnmarshalFailure,
  327. given: append(
  328. []byte{0x0, 0x02}, /* count prefix */
  329. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  330. },
  331. {
  332. name: "struct slice with uint16 count_prefix read error",
  333. prototype: &struct {
  334. Val []TLV `count_prefix:"uint16"`
  335. }{},
  336. wantErr: io.EOF,
  337. given: []byte{},
  338. },
  339. {
  340. name: "struct slice with invalid count_prefix",
  341. prototype: &struct {
  342. Val []TLV `count_prefix:"uint128"`
  343. }{},
  344. wantErr: ErrUnmarshalFailure,
  345. given: append(
  346. []byte{0x0, 0x02}, /* count prefix */
  347. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  348. },
  349. }
  350. for _, tt := range tests {
  351. t.Run(tt.name, func(t *testing.T) {
  352. r := bytes.NewBuffer(tt.given)
  353. err := Unmarshal(tt.prototype, r)
  354. assert.ErrorIs(t, err, tt.wantErr)
  355. if tt.wantErr == nil {
  356. assert.Equal(t, tt.want, tt.prototype)
  357. }
  358. })
  359. }
  360. }