tlv_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. package wire
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. )
  6. func TestTLVList_Append(t *testing.T) {
  7. want := TLVList{
  8. {
  9. Tag: 0,
  10. Value: []byte(`0`),
  11. },
  12. {
  13. Tag: 1,
  14. Value: []byte(`1`),
  15. },
  16. {
  17. Tag: 2,
  18. Value: []byte(`2`),
  19. },
  20. }
  21. have := TLVList{}
  22. have.Append(NewTLVBE(0, []byte(`0`)))
  23. have.Append(NewTLVBE(1, []byte(`1`)))
  24. have.Append(NewTLVBE(2, []byte(`2`)))
  25. assert.Equal(t, want, have)
  26. }
  27. func TestTLVList_HasTag(t *testing.T) {
  28. list := TLVList{
  29. {
  30. Tag: 0,
  31. Value: []byte(`0`),
  32. },
  33. {
  34. Tag: 1,
  35. Value: []byte(`1`),
  36. },
  37. {
  38. Tag: 2,
  39. Value: []byte(`2`),
  40. },
  41. }
  42. assert.True(t, list.HasTag(0))
  43. assert.False(t, list.HasTag(3))
  44. }
  45. func TestTLVList_AppendList(t *testing.T) {
  46. want := TLVList{
  47. {
  48. Tag: 0,
  49. Value: []byte(`0`),
  50. },
  51. {
  52. Tag: 1,
  53. Value: []byte(`1`),
  54. },
  55. {
  56. Tag: 2,
  57. Value: []byte(`2`),
  58. },
  59. }
  60. have := TLVList{}
  61. have.AppendList([]TLV{
  62. NewTLVBE(0, []byte(`0`)),
  63. NewTLVBE(1, []byte(`1`)),
  64. NewTLVBE(2, []byte(`2`)),
  65. })
  66. assert.Equal(t, want, have)
  67. }
  68. func TestTLVList_Getters(t *testing.T) {
  69. tests := []struct {
  70. name string
  71. given []TLV
  72. ttype any
  73. lookup func(TLVList) (any, bool)
  74. expect any
  75. found bool
  76. panic bool
  77. }{
  78. {
  79. name: "given a TLV of big-endian uint32, expect found value",
  80. given: []TLV{
  81. NewTLVBE(0, uint32(12)),
  82. NewTLVBE(1, uint32(34)),
  83. NewTLVBE(2, uint32(56)),
  84. },
  85. lookup: func(l TLVList) (any, bool) {
  86. return l.Uint32BE(1)
  87. },
  88. expect: uint32(34),
  89. found: true,
  90. },
  91. {
  92. name: "given a TLV of big-endian uint32, expect not found value",
  93. given: []TLV{
  94. NewTLVBE(0, uint32(12)),
  95. NewTLVBE(1, uint32(34)),
  96. NewTLVBE(2, uint32(56)),
  97. },
  98. lookup: func(l TLVList) (any, bool) {
  99. return l.Uint32BE(3)
  100. },
  101. expect: uint32(0),
  102. found: false,
  103. },
  104. {
  105. name: "given a TLV of big-endian uint16, expect found value",
  106. given: []TLV{
  107. NewTLVBE(0, uint16(12)),
  108. NewTLVBE(1, uint16(34)),
  109. NewTLVBE(2, uint16(56)),
  110. },
  111. lookup: func(l TLVList) (any, bool) {
  112. return l.Uint16BE(1)
  113. },
  114. expect: uint16(34),
  115. found: true,
  116. },
  117. {
  118. name: "given a TLV of big-endian uint16, expect not found value",
  119. given: []TLV{
  120. NewTLVBE(0, uint16(12)),
  121. NewTLVBE(1, uint16(34)),
  122. NewTLVBE(2, uint16(56)),
  123. },
  124. lookup: func(l TLVList) (any, bool) {
  125. return l.Uint16BE(3)
  126. },
  127. expect: uint16(0),
  128. found: false,
  129. },
  130. {
  131. name: "given a TLV of little-endian uint32, expect found value",
  132. given: []TLV{
  133. NewTLVLE(0, uint32(12)),
  134. NewTLVLE(1, uint32(34)),
  135. NewTLVLE(2, uint32(56)),
  136. },
  137. lookup: func(l TLVList) (any, bool) {
  138. return l.Uint32LE(1)
  139. },
  140. expect: uint32(34),
  141. found: true,
  142. },
  143. {
  144. name: "given a TLV of little-endian uint32, expect not found value",
  145. given: []TLV{
  146. NewTLVLE(0, uint32(12)),
  147. NewTLVLE(1, uint32(34)),
  148. NewTLVLE(2, uint32(56)),
  149. },
  150. lookup: func(l TLVList) (any, bool) {
  151. return l.Uint32LE(3)
  152. },
  153. expect: uint32(0),
  154. found: false,
  155. },
  156. {
  157. name: "given a TLV of little-endian uint16, expect found value",
  158. given: []TLV{
  159. NewTLVLE(0, uint16(12)),
  160. NewTLVLE(1, uint16(34)),
  161. NewTLVLE(2, uint16(56)),
  162. },
  163. lookup: func(l TLVList) (any, bool) {
  164. return l.Uint16LE(1)
  165. },
  166. expect: uint16(34),
  167. found: true,
  168. },
  169. {
  170. name: "given a TLV of little-endian uint16, expect not found value",
  171. given: []TLV{
  172. NewTLVLE(0, uint16(12)),
  173. NewTLVLE(1, uint16(34)),
  174. NewTLVLE(2, uint16(56)),
  175. },
  176. lookup: func(l TLVList) (any, bool) {
  177. return l.Uint16LE(3)
  178. },
  179. expect: uint16(0),
  180. found: false,
  181. },
  182. {
  183. name: "given a TLV of uint8, expect found value",
  184. given: []TLV{
  185. NewTLVLE(0, uint8(12)),
  186. NewTLVLE(1, uint8(34)),
  187. NewTLVLE(2, uint8(56)),
  188. },
  189. lookup: func(l TLVList) (any, bool) {
  190. return l.Uint8(1)
  191. },
  192. expect: uint8(34),
  193. found: true,
  194. },
  195. {
  196. name: "given a TLV of uint8, expect not found value",
  197. given: []TLV{
  198. NewTLVLE(0, uint8(12)),
  199. NewTLVLE(1, uint8(34)),
  200. NewTLVLE(2, uint8(56)),
  201. },
  202. lookup: func(l TLVList) (any, bool) {
  203. return l.Uint8(3)
  204. },
  205. expect: uint8(0),
  206. found: false,
  207. },
  208. {
  209. name: "given a TLV of string, expect found value",
  210. given: []TLV{
  211. NewTLVBE(0, "12"),
  212. NewTLVBE(1, "34"),
  213. NewTLVBE(2, "56"),
  214. },
  215. lookup: func(l TLVList) (any, bool) {
  216. return l.String(1)
  217. },
  218. expect: "34",
  219. found: true,
  220. },
  221. {
  222. name: "given a TLV of string, expect not found value",
  223. given: []TLV{
  224. NewTLVBE(0, "12"),
  225. NewTLVBE(1, "34"),
  226. NewTLVBE(2, "56"),
  227. },
  228. lookup: func(l TLVList) (any, bool) {
  229. return l.String(3)
  230. },
  231. expect: "",
  232. found: false,
  233. },
  234. {
  235. name: "given a TLV of slice, expect found value",
  236. given: []TLV{
  237. NewTLVBE(0, []byte(`12`)),
  238. NewTLVBE(1, []byte(`34`)),
  239. NewTLVBE(2, []byte(`56`)),
  240. },
  241. lookup: func(l TLVList) (any, bool) {
  242. return l.Bytes(1)
  243. },
  244. expect: []byte(`34`),
  245. found: true,
  246. },
  247. {
  248. name: "given a TLV of string, expect not found value",
  249. given: []TLV{
  250. NewTLVBE(0, []byte(`12`)),
  251. NewTLVBE(1, []byte(`34`)),
  252. NewTLVBE(2, []byte(`56`)),
  253. },
  254. lookup: func(l TLVList) (any, bool) {
  255. return l.Bytes(3)
  256. },
  257. expect: []byte(nil),
  258. found: false,
  259. },
  260. {
  261. name: "expect a panic when there's a type mismatch between big-endian uint16 and uint32",
  262. given: []TLV{
  263. NewTLVBE(0, uint16(12)),
  264. NewTLVBE(1, uint16(34)),
  265. NewTLVBE(2, uint16(56)),
  266. },
  267. lookup: func(l TLVList) (any, bool) {
  268. return l.Uint32BE(1)
  269. },
  270. panic: true,
  271. },
  272. {
  273. name: "expect a panic when there's a type mismatch between little-endian uint16 and uint32",
  274. given: []TLV{
  275. NewTLVLE(0, uint16(12)),
  276. NewTLVLE(1, uint16(34)),
  277. NewTLVLE(2, uint16(56)),
  278. },
  279. lookup: func(l TLVList) (any, bool) {
  280. return l.Uint32LE(1)
  281. },
  282. panic: true,
  283. },
  284. {
  285. name: "given a TLV of big-endian uint16 slice, expect found value",
  286. given: []TLV{
  287. NewTLVBE(200, []uint16{12, 34, 56}),
  288. },
  289. lookup: func(l TLVList) (any, bool) {
  290. return l.Uint16SliceBE(200)
  291. },
  292. expect: []uint16{12, 34, 56},
  293. found: true,
  294. },
  295. {
  296. name: "given a TLV of big-endian uint16 slice, expect not found value",
  297. given: []TLV{
  298. NewTLVBE(200, []uint16{12, 34, 56}),
  299. },
  300. lookup: func(l TLVList) (any, bool) {
  301. return l.Uint16SliceBE(50)
  302. },
  303. expect: []uint16{},
  304. found: false,
  305. },
  306. }
  307. for _, tt := range tests {
  308. t.Run(tt.name, func(t *testing.T) {
  309. if tt.panic {
  310. assert.Panics(t, func() { tt.lookup(tt.given) })
  311. return
  312. }
  313. have, found := tt.lookup(tt.given)
  314. assert.Equal(t, tt.expect, have)
  315. assert.Equal(t, tt.found, found)
  316. })
  317. }
  318. }
  319. func TestTLVList_NewTLVBEPanic(t *testing.T) {
  320. // make sure NewTLVBE panics when it encounters an unsupported type, in this
  321. // case it's int.
  322. assert.Panics(t, func() {
  323. NewTLVBE(1, 30)
  324. })
  325. }
  326. func TestTLVList_NewTLVLEPanic(t *testing.T) {
  327. // make sure NewTLVLE panics when it encounters an unsupported type, in this
  328. // case it's int.
  329. assert.Panics(t, func() {
  330. NewTLVLE(1, 30)
  331. })
  332. }
  333. func TestTLVList_ICQString(t *testing.T) {
  334. // Create a new TLV list
  335. tlv := TLVList{}
  336. // Add a valid ICQ string TLV entry to the list
  337. tlv.Append(NewTLVLE(0x01, []byte{0x09, 0x00, 'k', 'n', 'i', 't', 't', 'i', 'n', 'g', '\x00'}))
  338. t.Run("Valid ICQString", func(t *testing.T) {
  339. // Test retrieving a valid ICQ string
  340. str, ok := tlv.ICQString(0x01)
  341. assert.True(t, ok)
  342. assert.Equal(t, "knitting", str)
  343. })
  344. t.Run("Non-existent Tag", func(t *testing.T) {
  345. // Test retrieving an ICQ string for a non-existent tag
  346. str, ok := tlv.ICQString(0x02)
  347. assert.False(t, ok)
  348. assert.Empty(t, str)
  349. })
  350. t.Run("Malformed ICQString", func(t *testing.T) {
  351. // Add a malformed TLV entry (length prefix too short)
  352. tlvMalformed := TLVList{}
  353. tlvMalformed.Append(NewTLVLE(0x03, []byte{0x02, 0x00, 'a'})) // Length 2 but only 1 character and no null terminator
  354. str, ok := tlvMalformed.ICQString(0x03)
  355. assert.True(t, ok)
  356. assert.Empty(t, str)
  357. })
  358. t.Run("Incorrect Length Prefix", func(t *testing.T) {
  359. // Add an incorrect length prefix (does not match actual string length)
  360. tlvIncorrectLength := TLVList{}
  361. tlvIncorrectLength.Append(NewTLVLE(0x04, []byte{0x0A, 0x00, 'k', 'n', 'i', 't', 't', 'i', 'n', 'g', '\x00'})) // Length prefix is 9 but actual length is 7 + 1 (null terminator)
  362. str, ok := tlvIncorrectLength.ICQString(0x04)
  363. assert.True(t, ok)
  364. assert.Empty(t, str)
  365. })
  366. t.Run("Short Length Prefix", func(t *testing.T) {
  367. // Add a TLV with a length prefix, but the data is too short to contain a valid ICQ string
  368. tlvShortLength := TLVList{}
  369. tlvShortLength.Append(NewTLVLE(0x05, []byte{0x05, 0x00})) // Length prefix is 5 but no data
  370. str, ok := tlvShortLength.ICQString(0x05)
  371. assert.True(t, ok)
  372. assert.Empty(t, str)
  373. })
  374. t.Run("Empty String", func(t *testing.T) {
  375. // Add a TLV with an empty ICQ string (just the length prefix and null terminator)
  376. tlvEmptyString := TLVList{}
  377. tlvEmptyString.Append(NewTLVLE(0x06, []byte{0x01, 0x00, '\x00'})) // Length prefix is 1 with just null terminator
  378. str, ok := tlvEmptyString.ICQString(0x06)
  379. assert.True(t, ok)
  380. assert.Empty(t, str)
  381. })
  382. }
  383. func TestTLVList_Set(t *testing.T) {
  384. tests := []struct {
  385. name string
  386. given TLVList
  387. want TLVList
  388. replacement TLV
  389. }{
  390. {
  391. name: "replace multiple TLVs",
  392. given: TLVList{
  393. NewTLVLE(0x01, []byte{0x01}),
  394. NewTLVLE(0x02, []byte{0x02}),
  395. NewTLVLE(0x01, []byte{0x03}),
  396. NewTLVLE(0x03, []byte{0x04}),
  397. },
  398. replacement: NewTLVLE(0x01, []byte{0xAA}),
  399. want: TLVList{
  400. NewTLVLE(0x01, []byte{0xAA}),
  401. NewTLVLE(0x02, []byte{0x02}),
  402. NewTLVLE(0x01, []byte{0xAA}),
  403. NewTLVLE(0x03, []byte{0x04}),
  404. },
  405. },
  406. {
  407. name: "no matching tags",
  408. given: TLVList{
  409. NewTLVLE(0x01, []byte{0x01}),
  410. NewTLVLE(0x02, []byte{0x02}),
  411. NewTLVLE(0x01, []byte{0x03}),
  412. NewTLVLE(0x03, []byte{0x04}),
  413. },
  414. replacement: NewTLVLE(0x07, []byte{0xAA}),
  415. want: TLVList{
  416. NewTLVLE(0x01, []byte{0x01}),
  417. NewTLVLE(0x02, []byte{0x02}),
  418. NewTLVLE(0x01, []byte{0x03}),
  419. NewTLVLE(0x03, []byte{0x04}),
  420. NewTLVLE(0x07, []byte{0xAA}),
  421. },
  422. },
  423. }
  424. for _, tt := range tests {
  425. t.Run(tt.name, func(t *testing.T) {
  426. tt.given.Set(tt.replacement)
  427. assert.Equal(t, tt.want, tt.given)
  428. })
  429. }
  430. }
  431. func TestTLVList_Remove(t *testing.T) {
  432. tests := []struct {
  433. name string
  434. given TLVList
  435. tag uint16
  436. want TLVList
  437. }{
  438. {
  439. name: "remove multiple TLVs with the same tag",
  440. given: TLVList{
  441. NewTLVLE(0x01, []byte{0x01}),
  442. NewTLVLE(0x02, []byte{0x02}),
  443. NewTLVLE(0x01, []byte{0x03}),
  444. NewTLVLE(0x03, []byte{0x04}),
  445. },
  446. tag: 0x01,
  447. want: TLVList{
  448. NewTLVLE(0x02, []byte{0x02}),
  449. NewTLVLE(0x03, []byte{0x04}),
  450. },
  451. },
  452. {
  453. name: "remove a single TLV",
  454. given: TLVList{
  455. NewTLVLE(0x01, []byte{0x01}),
  456. NewTLVLE(0x02, []byte{0x02}),
  457. NewTLVLE(0x03, []byte{0x04}),
  458. },
  459. tag: 0x02,
  460. want: TLVList{
  461. NewTLVLE(0x01, []byte{0x01}),
  462. NewTLVLE(0x03, []byte{0x04}),
  463. },
  464. },
  465. {
  466. name: "no matching tag leaves the list unchanged",
  467. given: TLVList{
  468. NewTLVLE(0x01, []byte{0x01}),
  469. NewTLVLE(0x02, []byte{0x02}),
  470. },
  471. tag: 0x07,
  472. want: TLVList{
  473. NewTLVLE(0x01, []byte{0x01}),
  474. NewTLVLE(0x02, []byte{0x02}),
  475. },
  476. },
  477. {
  478. name: "remove from an empty list",
  479. given: TLVList{},
  480. tag: 0x01,
  481. want: TLVList{},
  482. },
  483. }
  484. for _, tt := range tests {
  485. t.Run(tt.name, func(t *testing.T) {
  486. tt.given.Remove(tt.tag)
  487. assert.Equal(t, tt.want, tt.given)
  488. })
  489. }
  490. }