tlv_test.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. for _, tt := range tests {
  286. t.Run(tt.name, func(t *testing.T) {
  287. if tt.panic {
  288. assert.Panics(t, func() { tt.lookup(tt.given) })
  289. return
  290. }
  291. have, found := tt.lookup(tt.given)
  292. assert.Equal(t, tt.expect, have)
  293. assert.Equal(t, tt.found, found)
  294. })
  295. }
  296. }
  297. func TestTLVList_NewTLVBEPanic(t *testing.T) {
  298. // make sure NewTLVBE panics when it encounters an unsupported type, in this
  299. // case it's int.
  300. assert.Panics(t, func() {
  301. NewTLVBE(1, 30)
  302. })
  303. }
  304. func TestTLVList_NewTLVLEPanic(t *testing.T) {
  305. // make sure NewTLVLE panics when it encounters an unsupported type, in this
  306. // case it's int.
  307. assert.Panics(t, func() {
  308. NewTLVLE(1, 30)
  309. })
  310. }
  311. func TestTLVList_ICQString(t *testing.T) {
  312. // Create a new TLV list
  313. tlv := TLVList{}
  314. // Add a valid ICQ string TLV entry to the list
  315. tlv.Append(NewTLVLE(0x01, []byte{0x09, 0x00, 'k', 'n', 'i', 't', 't', 'i', 'n', 'g', '\x00'}))
  316. t.Run("Valid ICQString", func(t *testing.T) {
  317. // Test retrieving a valid ICQ string
  318. str, ok := tlv.ICQString(0x01)
  319. assert.True(t, ok)
  320. assert.Equal(t, "knitting", str)
  321. })
  322. t.Run("Non-existent Tag", func(t *testing.T) {
  323. // Test retrieving an ICQ string for a non-existent tag
  324. str, ok := tlv.ICQString(0x02)
  325. assert.False(t, ok)
  326. assert.Empty(t, str)
  327. })
  328. t.Run("Malformed ICQString", func(t *testing.T) {
  329. // Add a malformed TLV entry (length prefix too short)
  330. tlvMalformed := TLVList{}
  331. tlvMalformed.Append(NewTLVLE(0x03, []byte{0x02, 0x00, 'a'})) // Length 2 but only 1 character and no null terminator
  332. str, ok := tlvMalformed.ICQString(0x03)
  333. assert.False(t, ok)
  334. assert.Empty(t, str)
  335. })
  336. t.Run("Incorrect Length Prefix", func(t *testing.T) {
  337. // Add an incorrect length prefix (does not match actual string length)
  338. tlvIncorrectLength := TLVList{}
  339. 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)
  340. str, ok := tlvIncorrectLength.ICQString(0x04)
  341. assert.False(t, ok)
  342. assert.Empty(t, str)
  343. })
  344. t.Run("Short Length Prefix", func(t *testing.T) {
  345. // Add a TLV with a length prefix, but the data is too short to contain a valid ICQ string
  346. tlvShortLength := TLVList{}
  347. tlvShortLength.Append(NewTLVLE(0x05, []byte{0x05, 0x00})) // Length prefix is 5 but no data
  348. str, ok := tlvShortLength.ICQString(0x05)
  349. assert.False(t, ok)
  350. assert.Empty(t, str)
  351. })
  352. t.Run("Empty String", func(t *testing.T) {
  353. // Add a TLV with an empty ICQ string (just the length prefix and null terminator)
  354. tlvEmptyString := TLVList{}
  355. tlvEmptyString.Append(NewTLVLE(0x06, []byte{0x01, 0x00, '\x00'})) // Length prefix is 1 with just null terminator
  356. str, ok := tlvEmptyString.ICQString(0x06)
  357. assert.True(t, ok)
  358. assert.Empty(t, str)
  359. })
  360. }
  361. func TestTLVList_Replace(t *testing.T) {
  362. tests := []struct {
  363. name string
  364. given TLVList
  365. want TLVList
  366. replacement TLV
  367. }{
  368. {
  369. name: "replace multiple TLVs",
  370. given: TLVList{
  371. NewTLVLE(0x01, []byte{0x01}),
  372. NewTLVLE(0x02, []byte{0x02}),
  373. NewTLVLE(0x01, []byte{0x03}),
  374. NewTLVLE(0x03, []byte{0x04}),
  375. },
  376. replacement: NewTLVLE(0x01, []byte{0xAA}),
  377. want: TLVList{
  378. NewTLVLE(0x01, []byte{0xAA}),
  379. NewTLVLE(0x02, []byte{0x02}),
  380. NewTLVLE(0x01, []byte{0xAA}),
  381. NewTLVLE(0x03, []byte{0x04}),
  382. },
  383. },
  384. {
  385. name: "no matching tags",
  386. given: TLVList{
  387. NewTLVLE(0x01, []byte{0x01}),
  388. NewTLVLE(0x02, []byte{0x02}),
  389. NewTLVLE(0x01, []byte{0x03}),
  390. NewTLVLE(0x03, []byte{0x04}),
  391. },
  392. replacement: NewTLVLE(0x07, []byte{0xAA}),
  393. want: TLVList{
  394. NewTLVLE(0x01, []byte{0x01}),
  395. NewTLVLE(0x02, []byte{0x02}),
  396. NewTLVLE(0x01, []byte{0x03}),
  397. NewTLVLE(0x03, []byte{0x04}),
  398. },
  399. },
  400. }
  401. for _, tt := range tests {
  402. t.Run(tt.name, func(t *testing.T) {
  403. tt.given.Replace(tt.replacement)
  404. assert.Equal(t, tt.want, tt.given)
  405. })
  406. }
  407. }