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()

[((14, 8, 14, 29), 'random.randint', 'random.randint', ({(14, 23, 14, 24): '1', (14, 26, 14, 28): '64'}, {}), '(1, 64)', False, 'import random\n'), ((77, 4, 77, 19), 'unittest.main', 'unittest.main', ({}, {}), '()', False, 'import unittest\n'), ((60, 9, 60, 25), 'common.realtime.sec_since_boot', 'sec_since_boot', ({}, {}), '()', False, 'from common.realtime import sec_since_boot\n'), ((63, 9, 63, 25), 'common.realtime.sec_since_boot', 'sec_since_boot', ({}, {}), '()', False, 'from common.realtime import sec_since_boot\n'), ((67, 9, 67, 25), 'common.realtime.sec_since_boot', 'sec_since_boot', ({}, {}), '()', False, 'from common.realtime import sec_since_boot\n'), ((70, 9, 70, 25), 'common.realtime.sec_since_boot', 'sec_since_boot', ({}, {}), '()', False, 'from common.realtime import sec_since_boot\n'), ((16, 31, 16, 51), 'random.randint', 'random.randint', ({(16, 46, 16, 47): '1', (16, 49, 16, 50): '8'}, {}), '(1, 8)', False, 'import random\n'), ((30, 10, 30, 59), 'selfdrive.boardd.boardd.can_list_to_can_capnp', 'boardd.can_list_to_can_capnp', ({(30, 39, 30, 47): 'can_list', (30, 49, 30, 58): '"""sendcan"""'}, {}), "(can_list, 'sendcan')", True, 'import selfdrive.boardd.boardd as boardd\n'), ((32, 15, 32, 42), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', ({(32, 36, 32, 41): 'm_old'}, {}), '(m_old)', False, 'from cereal import log\n'), ((33, 11, 33, 34), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', ({(33, 32, 33, 33): 'm'}, {}), '(m)', False, 'from cereal import log\n'), ((45, 10, 45, 55), 'selfdrive.boardd.boardd.can_list_to_can_capnp', 'boardd.can_list_to_can_capnp', ({(45, 39, 45, 47): 'can_list', (45, 49, 45, 54): '"""can"""'}, {}), "(can_list, 'can')", True, 'import selfdrive.boardd.boardd as boardd\n'), ((47, 15, 47, 42), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', ({(47, 36, 47, 41): 'm_old'}, {}), '(m_old)', False, 'from cereal import log\n'), ((48, 11, 48, 34), 'cereal.log.Event.from_bytes', 'log.Event.from_bytes', ({(48, 32, 48, 33): 'm'}, {}), '(m)', False, 'from cereal import log\n'), ((69, 6, 69, 44), 'selfdrive.boardd.boardd.can_list_to_can_capnp', 'boardd.can_list_to_can_capnp', ({(69, 35, 69, 43): 'can_list'}, {}), '(can_list)', True, 'import selfdrive.boardd.boardd as boardd\n'), ((17, 21, 17, 43), 'random.randint', 'random.randint', ({(17, 36, 17, 37): '(0)', (17, 39, 17, 42): '(128)'}, {}), '(0, 128)', False, 'import random\n'), ((17, 45, 17, 67), 'random.randint', 'random.randint', ({(17, 60, 17, 61): '(0)', (17, 63, 17, 66): '(128)'}, {}), '(0, 128)', False, 'import random\n'), ((17, 79, 17, 101), 'random.randint', 'random.randint', ({(17, 94, 17, 95): '(0)', (17, 97, 17, 100): '(128)'}, {}), '(0, 128)', False, 'import random\n'), ((28, 14, 28, 67), 'selfdrive.boardd.tests.boardd_old.can_list_to_can_capnp', 'boardd_old.can_list_to_can_capnp', ({(28, 47, 28, 55): 'can_list', (28, 57, 28, 66): '"""sendcan"""'}, {}), "(can_list, 'sendcan')", True, 'import selfdrive.boardd.tests.boardd_old as boardd_old\n'), ((43, 14, 43, 63), 'selfdrive.boardd.tests.boardd_old.can_list_to_can_capnp', 'boardd_old.can_list_to_can_capnp', ({(43, 47, 43, 55): 'can_list', (43, 57, 43, 62): '"""can"""'}, {}), "(can_list, 'can')", True, 'import selfdrive.boardd.tests.boardd_old as boardd_old\n'), ((62, 6, 62, 59), 'selfdrive.boardd.tests.boardd_old.can_list_to_can_capnp', 'boardd_old.can_list_to_can_capnp', ({(62, 39, 62, 47): 'can_list', (62, 49, 62, 58): '"""sendcan"""'}, {}), "(can_list, 'sendcan')", True, 'import selfdrive.boardd.tests.boardd_old as boardd_old\n')]