move nose tests to unittest (#22665)

* move to unittest

* boardd loopback

* no more nose

* phone only

* fix panda decorator
pull/22689/head
Adeeb Shihadeh 4 years ago committed by GitHub
parent e556d3d3d3
commit b5960b9dc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      Jenkinsfile
  2. 40
      selfdrive/boardd/tests/test_boardd_loopback.py
  3. 13
      selfdrive/test/helpers.py
  4. 69
      selfdrive/ui/tests/test_soundd.py
  5. 65
      selfdrive/ui/tests/test_sounds.py

4
Jenkinsfile vendored

@ -170,8 +170,8 @@ pipeline {
steps {
phone_steps("eon", [
["build", "cd selfdrive/manager && ./build.py"],
["test sounds", "nosetests -s selfdrive/ui/tests/test_sounds.py"],
["test boardd loopback", "nosetests -s selfdrive/boardd/tests/test_boardd_loopback.py"],
["test sounds", "python selfdrive/ui/tests/test_soundd.py"],
["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"],
["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"],
["test encoder", "python selfdrive/loggerd/tests/test_encoder.py"],
["test logcatd", "python selfdrive/logcatd/tests/test_logcatd_android.py"],

@ -2,41 +2,50 @@
import os
import random
import time
import unittest
from collections import defaultdict
from functools import wraps
import cereal.messaging as messaging
from cereal import car
from common.basedir import BASEDIR
from common.params import Params
from common.spinner import Spinner
from common.timeout import Timeout
from panda import Panda
from selfdrive.boardd.boardd import can_list_to_can_capnp
from selfdrive.car import make_can_msg
from selfdrive.test.helpers import with_processes
from selfdrive.test.helpers import phone_only, with_processes
def reset_panda(fn):
@wraps(fn)
def wrapper():
def reset_panda(f):
@wraps(f)
def wrapper(*args, **kwargs):
p = Panda()
for i in [0, 1, 2, 0xFFFF]:
p.can_clear(i)
p.reset()
p.close()
fn()
f(*args, **kwargs)
return wrapper
os.environ['STARTED'] = '1'
os.environ['BOARDD_LOOPBACK'] = '1'
os.environ['BASEDIR'] = BASEDIR
class TestBoardd(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.spinner = Spinner()
@classmethod
def tearDownClass(cls):
cls.spinner.close()
@phone_only
@reset_panda
@with_processes(['pandad'])
def test_boardd_loopback():
def test_loopback(self):
# wait for boardd to init
spinner = Spinner()
time.sleep(2)
with Timeout(60, "boardd didn't start"):
@ -51,9 +60,10 @@ def test_boardd_loopback():
safety_config.safetyModel = car.CarParams.SafetyModel.allOutput
cp.safetyConfigs = [safety_config]
Params().put("CarVin", b"0"*17)
Params().put_bool("ControlsReady", True)
Params().put("CarParams", cp.to_bytes())
params = Params()
params.put("CarVin", b"0"*17)
params.put_bool("ControlsReady", True)
params.put("CarParams", cp.to_bytes())
sendcan = messaging.pub_sock('sendcan')
can = messaging.sub_sock('can', conflate=False, timeout=100)
@ -62,7 +72,7 @@ def test_boardd_loopback():
n = 1000
for i in range(n):
spinner.update(f"boardd loopback {i}/{n}")
self.spinner.update(f"boardd loopback {i}/{n}")
sent_msgs = defaultdict(set)
for _ in range(random.randrange(10)):
@ -90,8 +100,6 @@ def test_boardd_loopback():
for bus in range(3):
assert not len(sent_msgs[bus]), f"loop {i}: bus {bus} missing {len(sent_msgs[bus])} messages"
spinner.close()
if __name__ == "__main__":
test_boardd_loopback()
unittest.main()

@ -1,10 +1,9 @@
import time
from functools import wraps
from nose.tools import nottest
from selfdrive.hardware import PC
from selfdrive.version import training_version, terms_version
from selfdrive.manager.process_config import managed_processes
from selfdrive.version import training_version, terms_version
def set_params_enabled():
@ -17,11 +16,13 @@ def set_params_enabled():
params.put_bool("Passive", False)
def phone_only(x):
def phone_only(f):
@wraps(f)
def wrap(self, *args, **kwargs):
if PC:
return nottest(x)
else:
return x
self.skipTest("This test is not meant to run on PC")
f(self, *args, **kwargs)
return wrap
def with_processes(processes, init_time=0, ignore_stopped=None):

@ -0,0 +1,69 @@
#!/usr/bin/env python3
import subprocess
import time
import unittest
from cereal import log, car
import cereal.messaging as messaging
from selfdrive.test.helpers import phone_only, with_processes
# TODO: rewrite for unittest
from common.realtime import DT_CTRL
from selfdrive.hardware import HARDWARE
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
SOUNDS = {
# sound: total writes
AudibleAlert.none: 0,
AudibleAlert.chimeEngage: 173,
AudibleAlert.chimeDisengage: 173,
AudibleAlert.chimeError: 173,
AudibleAlert.chimePrompt: 173,
AudibleAlert.chimeWarning1: 163,
AudibleAlert.chimeWarning2: 216,
AudibleAlert.chimeWarning2Repeat: 470,
AudibleAlert.chimeWarningRepeat: 468,
}
def get_total_writes():
audio_flinger = subprocess.check_output('dumpsys media.audio_flinger', shell=True, encoding='utf-8').strip()
write_lines = [l for l in audio_flinger.split('\n') if l.strip().startswith('Total writes')]
return sum([int(l.split(':')[1]) for l in write_lines])
class TestSoundd(unittest.TestCase):
def test_sound_card_init(self):
assert HARDWARE.get_sound_card_online()
@phone_only
@with_processes(['soundd'])
def test_alert_sounds(self):
pm = messaging.PubMaster(['controlsState'])
# make sure they're all defined
alert_sounds = {v: k for k, v in car.CarControl.HUDControl.AudibleAlert.schema.enumerants.items()}
diff = set(SOUNDS.keys()).symmetric_difference(alert_sounds.keys())
assert len(diff) == 0, f"not all sounds defined in test: {diff}"
# wait for procs to init
time.sleep(1)
for sound, expected_writes in SOUNDS.items():
print(f"testing {alert_sounds[sound]}")
start_writes = get_total_writes()
for _ in range(int(9 / DT_CTRL)):
msg = messaging.new_message('controlsState')
msg.controlsState.alertSound = sound
msg.controlsState.alertType = str(sound)
msg.controlsState.alertText1 = "Testing Sounds"
msg.controlsState.alertText2 = f"playing {alert_sounds[sound]}"
msg.controlsState.alertSize = log.ControlsState.AlertSize.mid
pm.send('controlsState', msg)
time.sleep(DT_CTRL)
tolerance = (expected_writes % 100) * 2
actual_writes = get_total_writes() - start_writes
assert abs(expected_writes - actual_writes) <= tolerance, f"{alert_sounds[sound]}: expected {expected_writes} writes, got {actual_writes}"
if __name__ == "__main__":
unittest.main()

@ -1,65 +0,0 @@
#!/usr/bin/env python3
import time
import subprocess
from cereal import log, car
import cereal.messaging as messaging
from selfdrive.test.helpers import phone_only, with_processes
from common.realtime import DT_CTRL
from selfdrive.hardware import HARDWARE
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
SOUNDS = {
# sound: total writes
AudibleAlert.none: 0,
AudibleAlert.chimeEngage: 173,
AudibleAlert.chimeDisengage: 173,
AudibleAlert.chimeError: 173,
AudibleAlert.chimePrompt: 173,
AudibleAlert.chimeWarning1: 163,
AudibleAlert.chimeWarning2: 216,
AudibleAlert.chimeWarning2Repeat: 470,
AudibleAlert.chimeWarningRepeat: 468,
}
def get_total_writes():
audio_flinger = subprocess.check_output('dumpsys media.audio_flinger', shell=True, encoding='utf-8').strip()
write_lines = [l for l in audio_flinger.split('\n') if l.strip().startswith('Total writes')]
return sum([int(l.split(':')[1]) for l in write_lines])
@phone_only
def test_sound_card_init():
assert HARDWARE.get_sound_card_online()
@phone_only
@with_processes(['soundd'])
def test_alert_sounds():
pm = messaging.PubMaster(['controlsState'])
# make sure they're all defined
alert_sounds = {v: k for k, v in car.CarControl.HUDControl.AudibleAlert.schema.enumerants.items()}
diff = set(SOUNDS.keys()).symmetric_difference(alert_sounds.keys())
assert len(diff) == 0, f"not all sounds defined in test: {diff}"
# wait for procs to init
time.sleep(1)
for sound, expected_writes in SOUNDS.items():
print(f"testing {alert_sounds[sound]}")
start_writes = get_total_writes()
for _ in range(int(9 / DT_CTRL)):
msg = messaging.new_message('controlsState')
msg.controlsState.alertSound = sound
msg.controlsState.alertType = str(sound)
msg.controlsState.alertText1 = "Testing Sounds"
msg.controlsState.alertText2 = f"playing {alert_sounds[sound]}"
msg.controlsState.alertSize = log.ControlsState.AlertSize.mid
pm.send('controlsState', msg)
time.sleep(DT_CTRL)
tolerance = (expected_writes % 100) * 2
actual_writes = get_total_writes() - start_writes
assert abs(expected_writes - actual_writes) <= tolerance, f"{alert_sounds[sound]}: expected {expected_writes} writes, got {actual_writes}"
Loading…
Cancel
Save