test_transport.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. import unittest
  2. from uavcan import transport
  3. from uavcan.dsdl import parser
  4. class TestBitsFromBytes(unittest.TestCase):
  5. def test_empty(self):
  6. bits = transport.bits_from_bytes(bytearray(""))
  7. self.assertEqual(bits, "")
  8. def test_single_byte(self):
  9. bits = transport.bits_from_bytes(bytearray("\x00"))
  10. self.assertEqual(bits, "00000000")
  11. bits = transport.bits_from_bytes(bytearray("\xA5"))
  12. self.assertEqual(bits, "10100101")
  13. bits = transport.bits_from_bytes(bytearray("\xFF"))
  14. self.assertEqual(bits, "11111111")
  15. bits = transport.bits_from_bytes(bytearray("\x0F"))
  16. self.assertEqual(bits, "00001111")
  17. bits = transport.bits_from_bytes(bytearray("\xF0"))
  18. self.assertEqual(bits, "11110000")
  19. def test_multiple_bytes(self):
  20. bits = transport.bits_from_bytes(bytearray("\x00\xFF"))
  21. self.assertEqual(bits, "0000000011111111")
  22. bits = transport.bits_from_bytes(bytearray("\xFF\x00"))
  23. self.assertEqual(bits, "1111111100000000")
  24. bits = transport.bits_from_bytes(bytearray("\x00\x00\xAA\x55\xFF\xFF"))
  25. self.assertEqual(
  26. bits, "000000000000000010101010010101011111111111111111")
  27. class TestBytesFromBits(unittest.TestCase):
  28. def test_empty(self):
  29. result_bytes = transport.bytes_from_bits("")
  30. self.assertEqual(result_bytes, b"")
  31. def test_partial_byte(self):
  32. result_bytes = transport.bytes_from_bits("0")
  33. self.assertEqual(result_bytes, b"\x00")
  34. result_bytes = transport.bytes_from_bits("1")
  35. self.assertEqual(result_bytes, b"\x01")
  36. result_bytes = transport.bytes_from_bits("100")
  37. self.assertEqual(result_bytes, b"\x04")
  38. result_bytes = transport.bytes_from_bits("001")
  39. self.assertEqual(result_bytes, b"\x01")
  40. result_bytes = transport.bytes_from_bits("1001")
  41. self.assertEqual(result_bytes, b"\x09")
  42. result_bytes = transport.bytes_from_bits("01001")
  43. self.assertEqual(result_bytes, b"\x09")
  44. result_bytes = transport.bytes_from_bits("0001001")
  45. self.assertEqual(result_bytes, b"\x09")
  46. result_bytes = transport.bytes_from_bits("1001001")
  47. self.assertEqual(result_bytes, b"\x49")
  48. def test_single_byte(self):
  49. result_bytes = transport.bytes_from_bits("10010110")
  50. self.assertEqual(result_bytes, b"\x96")
  51. result_bytes = transport.bytes_from_bits("10100101")
  52. self.assertEqual(result_bytes, b"\xA5")
  53. result_bytes = transport.bytes_from_bits("00000000")
  54. self.assertEqual(result_bytes, b"\x00")
  55. def test_multiple_bytes(self):
  56. result_bytes = transport.bytes_from_bits("1010010110010110")
  57. self.assertEqual(result_bytes, b"\xA5\x96")
  58. result_bytes = transport.bytes_from_bits("11010010110010110")
  59. self.assertEqual(result_bytes, b"\xD2\xCB\x00")
  60. result_bytes = transport.bytes_from_bits("10100101100101101")
  61. self.assertEqual(result_bytes, b"\xA5\x96\x01")
  62. class TestBEFromLEBits(unittest.TestCase):
  63. def test_partial_byte(self):
  64. for bits in ("0", "1", "100", "001", "1001", "01001", "001001",
  65. "1001001"):
  66. out_bits = transport.be_from_le_bits(bits, len(bits))
  67. self.assertEqual(out_bits, bits)
  68. def test_single_byte(self):
  69. for bits in ("10010110", "10100101", "00000000"):
  70. out_bits = transport.be_from_le_bits(bits, 8)
  71. self.assertEqual(out_bits, bits)
  72. def test_multiple_bytes(self):
  73. # llllllllmmmm
  74. out_bits = transport.be_from_le_bits("110110101110", 12)
  75. # mmmmllllllll
  76. self.assertEqual(out_bits, b"111011011010")
  77. # llllllllmmmmmmmm
  78. out_bits = transport.be_from_le_bits("1010010110010110", 16)
  79. # mmmmmmmmllllllll
  80. self.assertEqual(out_bits, b"1001011010100101")
  81. # llllllll........m
  82. out_bits = transport.be_from_le_bits("11010010110010110", 17)
  83. # m........llllllll
  84. self.assertEqual(out_bits, b"01100101111010010")
  85. # llllllll........m
  86. out_bits = transport.be_from_le_bits("10100101100101101", 17)
  87. # m........llllllll
  88. self.assertEqual(out_bits, b"11001011010100101")
  89. class TestLEFromBEBits(unittest.TestCase):
  90. def test_partial_byte(self):
  91. for bits in ("0", "1", "100", "001", "1001", "01001", "001001",
  92. "1001001"):
  93. out_bits = transport.le_from_be_bits(bits, len(bits))
  94. self.assertEqual(out_bits, bits)
  95. def test_single_byte(self):
  96. for bits in ("10010110", "10100101", "00000000"):
  97. out_bits = transport.le_from_be_bits(bits, 8)
  98. self.assertEqual(out_bits, bits)
  99. def test_multiple_bytes(self):
  100. # mmmmllllllll
  101. out_bits = transport.le_from_be_bits("111011011010", 12)
  102. # llllllllmmmm
  103. self.assertEqual(out_bits, b"110110101110")
  104. # mmmmmmmmllllllll
  105. out_bits = transport.le_from_be_bits("1001011010100101", 16)
  106. # llllllllmmmmmmmm
  107. self.assertEqual(out_bits, b"1010010110010110")
  108. # m........llllllll
  109. out_bits = transport.le_from_be_bits("01100101111010010", 17)
  110. # llllllll........m
  111. self.assertEqual(out_bits, b"11010010110010110")
  112. # m........llllllll
  113. out_bits = transport.le_from_be_bits("11001011010100101", 17)
  114. # llllllll........m
  115. self.assertEqual(out_bits, b"10100101100101101")
  116. class TestCast(unittest.TestCase):
  117. def test_truncated_1bit(self):
  118. dtype = parser.PrimitiveType(
  119. parser.PrimitiveType.KIND_UNSIGNED_INT,
  120. 1,
  121. parser.PrimitiveType.CAST_MODE_TRUNCATED)
  122. value = transport.cast(0, dtype)
  123. self.assertEqual(value, 0)
  124. value = transport.cast(1, dtype)
  125. self.assertEqual(value, 1)
  126. value = transport.cast(2, dtype)
  127. self.assertEqual(value, 0)
  128. value = transport.cast(-1, dtype)
  129. self.assertEqual(value, 1)
  130. value = transport.cast(5, dtype)
  131. self.assertEqual(value, 1)
  132. value = transport.cast(-10, dtype)
  133. self.assertEqual(value, 0)
  134. def test_truncated_4bit(self):
  135. dtype = parser.PrimitiveType(
  136. parser.PrimitiveType.KIND_UNSIGNED_INT,
  137. 4,
  138. parser.PrimitiveType.CAST_MODE_TRUNCATED)
  139. value = transport.cast(0, dtype)
  140. self.assertEqual(value, 0)
  141. value = transport.cast(15, dtype)
  142. self.assertEqual(value, 15)
  143. value = transport.cast(16, dtype)
  144. self.assertEqual(value, 0)
  145. value = transport.cast(-1, dtype)
  146. self.assertEqual(value, 15)
  147. value = transport.cast(30, dtype)
  148. self.assertEqual(value, 14)
  149. def test_truncated_33bit(self):
  150. dtype = parser.PrimitiveType(
  151. parser.PrimitiveType.KIND_UNSIGNED_INT,
  152. 33,
  153. parser.PrimitiveType.CAST_MODE_TRUNCATED)
  154. value = transport.cast(0, dtype)
  155. self.assertEqual(value, 0)
  156. value = transport.cast(8589934591, dtype)
  157. self.assertEqual(value, 8589934591)
  158. value = transport.cast(8589934592, dtype)
  159. self.assertEqual(value, 0)
  160. value = transport.cast(-1, dtype)
  161. self.assertEqual(value, 8589934591)
  162. def test_truncated_64bit(self):
  163. dtype = parser.PrimitiveType(
  164. parser.PrimitiveType.KIND_UNSIGNED_INT,
  165. 64,
  166. parser.PrimitiveType.CAST_MODE_TRUNCATED)
  167. value = transport.cast(0, dtype)
  168. self.assertEqual(value, 0)
  169. value = transport.cast(18446744073709551615, dtype)
  170. self.assertEqual(value, 18446744073709551615)
  171. value = transport.cast(-1, dtype)
  172. self.assertEqual(value, 18446744073709551615)
  173. value = transport.cast(18446744073709551617, dtype)
  174. self.assertEqual(value, 1)
  175. value = transport.cast(-18446744073709551615, dtype)
  176. self.assertEqual(value, 1)
  177. def test_unsigned_saturated_1bit(self):
  178. dtype = parser.PrimitiveType(
  179. parser.PrimitiveType.KIND_UNSIGNED_INT,
  180. 1,
  181. parser.PrimitiveType.CAST_MODE_SATURATED)
  182. value = transport.cast(0, dtype)
  183. self.assertEqual(value, 0)
  184. value = transport.cast(1, dtype)
  185. self.assertEqual(value, 1)
  186. value = transport.cast(2, dtype)
  187. self.assertEqual(value, 1)
  188. value = transport.cast(-1, dtype)
  189. self.assertEqual(value, 0)
  190. value = transport.cast(5, dtype)
  191. self.assertEqual(value, 1)
  192. value = transport.cast(-10, dtype)
  193. self.assertEqual(value, 0)
  194. def test_unsigned_saturated_4bit(self):
  195. dtype = parser.PrimitiveType(
  196. parser.PrimitiveType.KIND_UNSIGNED_INT,
  197. 4,
  198. parser.PrimitiveType.CAST_MODE_SATURATED)
  199. value = transport.cast(0, dtype)
  200. self.assertEqual(value, 0)
  201. value = transport.cast(15, dtype)
  202. self.assertEqual(value, 15)
  203. value = transport.cast(16, dtype)
  204. self.assertEqual(value, 15)
  205. value = transport.cast(-1, dtype)
  206. self.assertEqual(value, 0)
  207. value = transport.cast(30, dtype)
  208. self.assertEqual(value, 15)
  209. def test_unsigned_saturated_33bit(self):
  210. dtype = parser.PrimitiveType(
  211. parser.PrimitiveType.KIND_UNSIGNED_INT,
  212. 33,
  213. parser.PrimitiveType.CAST_MODE_SATURATED)
  214. value = transport.cast(0, dtype)
  215. self.assertEqual(value, 0)
  216. value = transport.cast(8589934591, dtype)
  217. self.assertEqual(value, 8589934591)
  218. value = transport.cast(8589934592, dtype)
  219. self.assertEqual(value, 8589934591)
  220. value = transport.cast(-1, dtype)
  221. self.assertEqual(value, 0)
  222. def test_unsigned_saturated_64bit(self):
  223. dtype = parser.PrimitiveType(
  224. parser.PrimitiveType.KIND_UNSIGNED_INT,
  225. 64,
  226. parser.PrimitiveType.CAST_MODE_SATURATED)
  227. value = transport.cast(0, dtype)
  228. self.assertEqual(value, 0)
  229. value = transport.cast(18446744073709551615, dtype)
  230. self.assertEqual(value, 18446744073709551615)
  231. value = transport.cast(-1, dtype)
  232. self.assertEqual(value, 0)
  233. value = transport.cast(18446744073709551617, dtype)
  234. self.assertEqual(value, 18446744073709551615)
  235. value = transport.cast(-18446744073709551615, dtype)
  236. self.assertEqual(value, 0)
  237. def test_signed_saturated_4bit(self):
  238. dtype = parser.PrimitiveType(
  239. parser.PrimitiveType.KIND_SIGNED_INT,
  240. 4,
  241. parser.PrimitiveType.CAST_MODE_SATURATED)
  242. value = transport.cast(0, dtype)
  243. self.assertEqual(value, 0)
  244. value = transport.cast(15, dtype)
  245. self.assertEqual(value, 7)
  246. value = transport.cast(16, dtype)
  247. self.assertEqual(value, 7)
  248. value = transport.cast(-1, dtype)
  249. self.assertEqual(value, -1)
  250. value = transport.cast(-30, dtype)
  251. self.assertEqual(value, -8)
  252. def test_signed_saturated_33bit(self):
  253. dtype = parser.PrimitiveType(
  254. parser.PrimitiveType.KIND_SIGNED_INT,
  255. 33,
  256. parser.PrimitiveType.CAST_MODE_SATURATED)
  257. value = transport.cast(0, dtype)
  258. self.assertEqual(value, 0)
  259. value = transport.cast(8589934591, dtype)
  260. self.assertEqual(value, 4294967295)
  261. value = transport.cast(-8589934592, dtype)
  262. self.assertEqual(value, -4294967296)
  263. value = transport.cast(-1, dtype)
  264. self.assertEqual(value, -1)
  265. def test_signed_saturated_64bit(self):
  266. dtype = parser.PrimitiveType(
  267. parser.PrimitiveType.KIND_SIGNED_INT,
  268. 64,
  269. parser.PrimitiveType.CAST_MODE_SATURATED)
  270. value = transport.cast(0, dtype)
  271. self.assertEqual(value, 0)
  272. value = transport.cast(18446744073709551615, dtype)
  273. self.assertEqual(value, 9223372036854775808)
  274. value = transport.cast(-1, dtype)
  275. self.assertEqual(value, -1)
  276. value = transport.cast(-18446744073709551617, dtype)
  277. self.assertEqual(value, -9223372036854775809)
  278. value = transport.cast(-9223372036854775808, dtype)
  279. self.assertEqual(value, -9223372036854775808)
  280. def test_float16_truncated(self):
  281. pass
  282. def test_float16_saturated(self):
  283. pass
  284. def test_float32_truncated(self):
  285. pass
  286. def test_float32_saturated(self):
  287. pass
  288. class TestArrayBasic(unittest.TestCase):
  289. def setUp(self):
  290. custom_type = parser.CompoundType(
  291. "CustomType",
  292. parser.CompoundType.KIND_MESSAGE,
  293. "source.uavcan",
  294. 0,
  295. ""
  296. )
  297. custom_type.fields = [
  298. parser.Field(
  299. parser.PrimitiveType(
  300. parser.PrimitiveType.KIND_SIGNED_INT,
  301. 8,
  302. parser.PrimitiveType.CAST_MODE_TRUNCATED
  303. ),
  304. "a"
  305. ),
  306. parser.Field(
  307. parser.PrimitiveType(
  308. parser.PrimitiveType.KIND_FLOAT,
  309. 16,
  310. parser.PrimitiveType.CAST_MODE_SATURATED
  311. ),
  312. "b"
  313. ),
  314. parser.Field(
  315. parser.ArrayType(
  316. parser.PrimitiveType(
  317. parser.PrimitiveType.KIND_UNSIGNED_INT,
  318. 1,
  319. parser.PrimitiveType.CAST_MODE_SATURATED
  320. ),
  321. parser.ArrayType.MODE_DYNAMIC,
  322. 5
  323. ),
  324. "c"
  325. )
  326. ]
  327. def custom_type_factory(*args, **kwargs):
  328. return transport.CompoundValue(custom_type, tao=True, *args, **kwargs)
  329. custom_type.__call__ = custom_type_factory
  330. self.a1_type = parser.ArrayType(
  331. parser.PrimitiveType(
  332. parser.PrimitiveType.KIND_SIGNED_INT,
  333. 8,
  334. parser.PrimitiveType.CAST_MODE_TRUNCATED
  335. ),
  336. parser.ArrayType.MODE_STATIC,
  337. 4
  338. )
  339. self.a2_type = parser.ArrayType(
  340. parser.PrimitiveType(
  341. parser.PrimitiveType.KIND_FLOAT,
  342. 16,
  343. parser.PrimitiveType.CAST_MODE_SATURATED
  344. ),
  345. parser.ArrayType.MODE_STATIC,
  346. 2
  347. )
  348. self.a3_type = parser.ArrayType(
  349. custom_type,
  350. parser.ArrayType.MODE_STATIC,
  351. 2
  352. )
  353. def test_size(self):
  354. self.assertEqual(self.a3_type.value_type.fields[2].type.value_type.bitlen, 1)
  355. self.assertEqual(self.a1_type.get_max_bitlen(), 8 * 4)
  356. self.assertEqual(self.a2_type.get_max_bitlen(), 16 * 2)
  357. self.assertEqual(self.a3_type.get_max_bitlen(), (8 + 16 + 5 + 3) * 2)
  358. def test_representation(self):
  359. a1 = transport.ArrayValue(self.a1_type, tao=False)
  360. a2 = transport.ArrayValue(self.a2_type, tao=False)
  361. a3 = transport.ArrayValue(self.a3_type, tao=True)
  362. for i in xrange(4):
  363. a1[i] = i
  364. for i in xrange(2):
  365. a2[i] = i
  366. for i in xrange(2):
  367. a3[i].a = i
  368. a3[i].b = i
  369. for i2 in xrange(5):
  370. a3[i].c.append(i2 & 1)
  371. self.assertEqual(len(a3[i].c), 5)
  372. self.assertEqual(
  373. transport.format_bits(a1.pack()),
  374. "00000000 00000001 00000010 00000011"
  375. )
  376. self.assertEqual(
  377. transport.format_bits(a2.pack()),
  378. "00000000 00000000 00000000 00111100"
  379. )
  380. self.assertEqual(
  381. transport.format_bits(a3.pack()),
  382. "00000000 00000000 00000000 10101010 " +
  383. "00000001 00000000 00111100 10101010"
  384. )
  385. class TestVoid(unittest.TestCase):
  386. def setUp(self):
  387. self.custom_type = parser.CompoundType(
  388. "CustomType",
  389. parser.CompoundType.KIND_MESSAGE,
  390. "source.uavcan",
  391. 0,
  392. ""
  393. )
  394. self.custom_type.fields = [
  395. parser.Field(
  396. parser.PrimitiveType(
  397. parser.PrimitiveType.KIND_FLOAT,
  398. 16,
  399. parser.PrimitiveType.CAST_MODE_SATURATED
  400. ),
  401. "a"
  402. ),
  403. parser.Field(parser.VoidType(3), None),
  404. parser.Field(
  405. parser.PrimitiveType(
  406. parser.PrimitiveType.KIND_UNSIGNED_INT,
  407. 1,
  408. parser.PrimitiveType.CAST_MODE_SATURATED
  409. ),
  410. "b"
  411. )
  412. ]
  413. def custom_type_factory(*args, **kwargs):
  414. return transport.CompoundValue(self.custom_type, tao=True, *args,
  415. **kwargs)
  416. self.custom_type.__call__ = custom_type_factory
  417. def test_size(self):
  418. self.assertEqual(self.custom_type.fields[1].type.bitlen, 3)
  419. self.assertEqual(self.custom_type.get_max_bitlen(), 20)
  420. def test_representation(self):
  421. c1 = self.custom_type()
  422. self.assertEqual(
  423. transport.format_bits(c1.pack()),
  424. "00000000 00000000 0000"
  425. )
  426. c1.a = 1
  427. c1.b = 1
  428. self.assertEqual(
  429. transport.format_bits(c1.pack()),
  430. "00000000 00111100 0001"
  431. )
  432. class TestMessageUnion(unittest.TestCase):
  433. def setUp(self):
  434. self.custom_type = parser.CompoundType(
  435. "CustomType",
  436. parser.CompoundType.KIND_MESSAGE,
  437. "source.uavcan",
  438. 0,
  439. ""
  440. )
  441. self.custom_type.union = True
  442. self.custom_type.fields = [
  443. parser.Field(
  444. parser.PrimitiveType(
  445. parser.PrimitiveType.KIND_FLOAT,
  446. 16,
  447. parser.PrimitiveType.CAST_MODE_SATURATED
  448. ),
  449. "a"
  450. ),
  451. parser.Field(
  452. parser.ArrayType(
  453. parser.PrimitiveType(
  454. parser.PrimitiveType.KIND_UNSIGNED_INT,
  455. 8,
  456. parser.PrimitiveType.CAST_MODE_SATURATED
  457. ),
  458. parser.ArrayType.MODE_STATIC,
  459. 2
  460. ),
  461. "b"
  462. )
  463. ]
  464. def custom_type_factory(*args, **kwargs):
  465. return transport.CompoundValue(self.custom_type, tao=True, *args,
  466. **kwargs)
  467. self.custom_type.__call__ = custom_type_factory
  468. def test_size(self):
  469. self.assertEqual(self.custom_type.fields[0].type.bitlen, 16)
  470. self.assertEqual(self.custom_type.fields[1].type.get_max_bitlen(), 16)
  471. self.assertEqual(self.custom_type.get_max_bitlen(), 17)
  472. def test_representation(self):
  473. c1 = self.custom_type()
  474. self.assertEqual(
  475. transport.format_bits(c1.pack()),
  476. "00000000 00000000 0"
  477. )
  478. c2 = self.custom_type()
  479. c2.a = 1
  480. self.assertEqual(c2.union_field, "a")
  481. self.assertEqual(
  482. transport.format_bits(c2.pack()),
  483. "00000000 00011110 0"
  484. )
  485. c3 = self.custom_type()
  486. c3.b[0] = 1
  487. c3.b[1] = 3
  488. self.assertEqual(c3.union_field, "b")
  489. self.assertEqual(
  490. transport.format_bits(c3.pack()),
  491. "10000000 10000001 1"
  492. )
  493. if __name__ == '__main__':
  494. unittest.main()