import random
import numpy as np

import selfdrive.boardd.tests.boardd_old as boardd_old
import selfdrive.boardd.boardd as boardd

from common.realtime import sec_since_boot
from cereal import log
import unittest


def generate_random_can_data_list():
  can_list = []
  cnt = random.randint(1, 64)
  for j in range(cnt):
    can_data = np.random.bytes(random.randint(1, 8))
    can_list.append([random.randint(0, 128), random.randint(0, 128), can_data, random.randint(0, 128)])
  return can_list, cnt


class TestBoarddApiMethods(unittest.TestCase):
  def test_correctness(self):
    for i in range(1000):
      can_list, _ = generate_random_can_data_list()

      # Sendcan
      # Old API
      m_old = boardd_old.can_list_to_can_capnp(can_list, 'sendcan').to_bytes()
      # new API
      m = boardd.can_list_to_can_capnp(can_list, 'sendcan')

      ev_old = log.Event.from_bytes(m_old)
      ev = log.Event.from_bytes(m)

      self.assertEqual(ev_old.which(), ev.which())
      self.assertEqual(len(ev.sendcan), len(ev_old.sendcan))
      for i in range(len(ev.sendcan)):
        attrs = ['address', 'busTime', 'dat', 'src']
        for attr in attrs:
          self.assertEqual(getattr(ev.sendcan[i], attr, 'new'), getattr(ev_old.sendcan[i], attr, 'old'))

      # Can
      m_old = boardd_old.can_list_to_can_capnp(can_list, 'can').to_bytes()
      # new API
      m = boardd.can_list_to_can_capnp(can_list, 'can')

      ev_old = log.Event.from_bytes(m_old)
      ev = log.Event.from_bytes(m)
      self.assertEqual(ev_old.which(), ev.which())
      self.assertEqual(len(ev.can), len(ev_old.can))
      for i in range(len(ev.can)):
        attrs = ['address', 'busTime', 'dat', 'src']
        for attr in attrs:
          self.assertEqual(getattr(ev.can[i], attr, 'new'), getattr(ev_old.can[i], attr, 'old'))

  def test_performance(self):
    can_list, cnt = generate_random_can_data_list()
    recursions = 1000

    n1 = sec_since_boot()
    for i in range(recursions):
      boardd_old.can_list_to_can_capnp(can_list, 'sendcan').to_bytes()
    n2 = sec_since_boot()
    elapsed_old = n2 - n1

    # print('Old API, elapsed time: {} secs'.format(elapsed_old))
    n1 = sec_since_boot()
    for i in range(recursions):
      boardd.can_list_to_can_capnp(can_list)
    n2 = sec_since_boot()
    elapsed_new = n2 - n1
    # print('New API, elapsed time: {} secs'.format(elapsed_new))
    self.assertTrue(elapsed_new < elapsed_old / 2)


if __name__ == '__main__':
    unittest.main()

[((276, 297), 'random.randint', 'random.randint', (['(1)', '(64)'], {}), '(1, 64)\n', (290, 297), False, 'import random\n'), ((2476, 2491), 'unittest.main', 'unittest.main', ([], {}), '()\n', (2489, 2491), False, 'import unittest\n'), ((1932, 1948), 'common.realtime.sec_since_boot', 'sec_since_boot', ([], {}), '()\n', (1946, 1948), False, 'from common.realtime import sec_since_boot\n'), ((2061, 2077), 'common.realtime.sec_since_boot', 'sec_since_boot', ([], {}), '()\n', (2075, 2077), False, 'from common.realtime import sec_since_boot\n'), ((2180, 2196), 'common.realtime.sec_since_boot', 'sec_since_boot', ([], {}), '()\n', (2194, 2196), False, 'from common.realtime import sec_since_boot\n'), ((2283, 2299), 'common.realtime.sec_since_boot', 'sec_since_boot', ([], {}), '()\n', (2297, 2299), False, 'from common.realtime import sec_since_boot\n'), ((352, 372), 'random.randint', 'random.randint', (['(1)', '(8)'], {}), '(1, 8)\n', (366, 372), False, 'import random\n'), ((796, 845), 'selfdrive.boardd.boardd.can_list_to_can_capnp', 'boardd.can_list_to_can_capnp', (['can_list', '"""sendcan"""'], {}), "(can_list, 'sendcan')\n", (824, 845), True, 'import selfdrive.boardd.boardd as boardd\n'), ((862, 889), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', (['m_old'], {}), '(m_old)\n', (882, 889), False, 'from cereal import log\n'), ((901, 924), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', (['m'], {}), '(m)\n', (921, 924), False, 'from cereal import log\n'), ((1376, 1421), 'selfdrive.boardd.boardd.can_list_to_can_capnp', 'boardd.can_list_to_can_capnp', (['can_list', '"""can"""'], {}), "(can_list, 'can')\n", (1404, 1421), True, 'import selfdrive.boardd.boardd as boardd\n'), ((1438, 1465), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', (['m_old'], {}), '(m_old)\n', (1458, 1465), False, 'from cereal import log\n'), ((1477, 1500), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', (['m'], {}), '(m)\n', (1497, 1500), False, 'from cereal import log\n'), ((2235, 2273), 'selfdrive.boardd.boardd.can_list_to_can_capnp', 'boardd.can_list_to_can_capnp', (['can_list'], {}), '(can_list)\n', (2263, 2273), True, 'import selfdrive.boardd.boardd as boardd\n'), ((395, 417), 'random.randint', 'random.randint', (['(0)', '(128)'], {}), '(0, 128)\n', (409, 417), False, 'import random\n'), ((419, 441), 'random.randint', 'random.randint', (['(0)', '(128)'], {}), '(0, 128)\n', (433, 441), False, 'import random\n'), ((453, 475), 'random.randint', 'random.randint', (['(0)', '(128)'], {}), '(0, 128)\n', (467, 475), False, 'import random\n'), ((705, 758), 'selfdrive.boardd.tests.boardd_old.can_list_to_can_capnp', 'boardd_old.can_list_to_can_capnp', (['can_list', '"""sendcan"""'], {}), "(can_list, 'sendcan')\n", (737, 758), True, 'import selfdrive.boardd.tests.boardd_old as boardd_old\n'), ((1289, 1338), 'selfdrive.boardd.tests.boardd_old.can_list_to_can_capnp', 'boardd_old.can_list_to_can_capnp', (['can_list', '"""can"""'], {}), "(can_list, 'can')\n", (1321, 1338), True, 'import selfdrive.boardd.tests.boardd_old as boardd_old\n'), ((1987, 2040), 'selfdrive.boardd.tests.boardd_old.can_list_to_can_capnp', 'boardd_old.can_list_to_can_capnp', (['can_list', '"""sendcan"""'], {}), "(can_list, 'sendcan')\n", (2019, 2040), True, 'import selfdrive.boardd.tests.boardd_old as boardd_old\n')]