|
|
@ -1,4 +1,3 @@ |
|
|
|
#!/usr/bin/env python3 |
|
|
|
|
|
|
|
import os |
|
|
|
import os |
|
|
|
import capnp |
|
|
|
import capnp |
|
|
|
import multiprocessing |
|
|
|
import multiprocessing |
|
|
@ -6,8 +5,8 @@ import numbers |
|
|
|
import random |
|
|
|
import random |
|
|
|
import threading |
|
|
|
import threading |
|
|
|
import time |
|
|
|
import time |
|
|
|
import unittest |
|
|
|
|
|
|
|
from parameterized import parameterized |
|
|
|
from parameterized import parameterized |
|
|
|
|
|
|
|
import pytest |
|
|
|
|
|
|
|
|
|
|
|
from cereal import log, car |
|
|
|
from cereal import log, car |
|
|
|
import cereal.messaging as messaging |
|
|
|
import cereal.messaging as messaging |
|
|
@ -28,12 +27,6 @@ def zmq_sleep(t=1): |
|
|
|
if "ZMQ" in os.environ: |
|
|
|
if "ZMQ" in os.environ: |
|
|
|
time.sleep(t) |
|
|
|
time.sleep(t) |
|
|
|
|
|
|
|
|
|
|
|
def zmq_expected_failure(func): |
|
|
|
|
|
|
|
if "ZMQ" in os.environ: |
|
|
|
|
|
|
|
return unittest.expectedFailure(func) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
return func |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: this should take any capnp struct and returrn a msg with random populated data |
|
|
|
# TODO: this should take any capnp struct and returrn a msg with random populated data |
|
|
|
def random_carstate(): |
|
|
|
def random_carstate(): |
|
|
@ -58,12 +51,12 @@ def delayed_send(delay, sock, dat): |
|
|
|
threading.Timer(delay, send_func).start() |
|
|
|
threading.Timer(delay, send_func).start() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestMessaging(unittest.TestCase): |
|
|
|
class TestMessaging: |
|
|
|
def setUp(self): |
|
|
|
def setUp(self): |
|
|
|
# TODO: ZMQ tests are too slow; all sleeps will need to be |
|
|
|
# TODO: ZMQ tests are too slow; all sleeps will need to be |
|
|
|
# replaced with logic to block on the necessary condition |
|
|
|
# replaced with logic to block on the necessary condition |
|
|
|
if "ZMQ" in os.environ: |
|
|
|
if "ZMQ" in os.environ: |
|
|
|
raise unittest.SkipTest |
|
|
|
pytest.skip() |
|
|
|
|
|
|
|
|
|
|
|
# ZMQ pub socket takes too long to die |
|
|
|
# ZMQ pub socket takes too long to die |
|
|
|
# sleep to prevent multiple publishers error between tests |
|
|
|
# sleep to prevent multiple publishers error between tests |
|
|
@ -75,9 +68,9 @@ class TestMessaging(unittest.TestCase): |
|
|
|
msg = messaging.new_message(evt) |
|
|
|
msg = messaging.new_message(evt) |
|
|
|
except capnp.lib.capnp.KjException: |
|
|
|
except capnp.lib.capnp.KjException: |
|
|
|
msg = messaging.new_message(evt, random.randrange(200)) |
|
|
|
msg = messaging.new_message(evt, random.randrange(200)) |
|
|
|
self.assertLess(time.monotonic() - msg.logMonoTime, 0.1) |
|
|
|
assert (time.monotonic() - msg.logMonoTime) < 0.1 |
|
|
|
self.assertFalse(msg.valid) |
|
|
|
assert not msg.valid |
|
|
|
self.assertEqual(evt, msg.which()) |
|
|
|
assert evt == msg.which() |
|
|
|
|
|
|
|
|
|
|
|
@parameterized.expand(events) |
|
|
|
@parameterized.expand(events) |
|
|
|
def test_pub_sock(self, evt): |
|
|
|
def test_pub_sock(self, evt): |
|
|
@ -99,8 +92,8 @@ class TestMessaging(unittest.TestCase): |
|
|
|
|
|
|
|
|
|
|
|
# no wait and no msgs in queue |
|
|
|
# no wait and no msgs in queue |
|
|
|
msgs = func(sub_sock) |
|
|
|
msgs = func(sub_sock) |
|
|
|
self.assertIsInstance(msgs, list) |
|
|
|
assert isinstance(msgs, list) |
|
|
|
self.assertEqual(len(msgs), 0) |
|
|
|
assert len(msgs) == 0 |
|
|
|
|
|
|
|
|
|
|
|
# no wait but msgs are queued up |
|
|
|
# no wait but msgs are queued up |
|
|
|
num_msgs = random.randrange(3, 10) |
|
|
|
num_msgs = random.randrange(3, 10) |
|
|
@ -108,9 +101,9 @@ class TestMessaging(unittest.TestCase): |
|
|
|
pub_sock.send(messaging.new_message(sock).to_bytes()) |
|
|
|
pub_sock.send(messaging.new_message(sock).to_bytes()) |
|
|
|
time.sleep(0.1) |
|
|
|
time.sleep(0.1) |
|
|
|
msgs = func(sub_sock) |
|
|
|
msgs = func(sub_sock) |
|
|
|
self.assertIsInstance(msgs, list) |
|
|
|
assert isinstance(msgs, list) |
|
|
|
self.assertTrue(all(isinstance(msg, expected_type) for msg in msgs)) |
|
|
|
assert all(isinstance(msg, expected_type) for msg in msgs) |
|
|
|
self.assertEqual(len(msgs), num_msgs) |
|
|
|
assert len(msgs) == num_msgs |
|
|
|
|
|
|
|
|
|
|
|
def test_recv_sock(self): |
|
|
|
def test_recv_sock(self): |
|
|
|
sock = "carState" |
|
|
|
sock = "carState" |
|
|
@ -120,14 +113,14 @@ class TestMessaging(unittest.TestCase): |
|
|
|
|
|
|
|
|
|
|
|
# no wait and no msg in queue, socket should timeout |
|
|
|
# no wait and no msg in queue, socket should timeout |
|
|
|
recvd = messaging.recv_sock(sub_sock) |
|
|
|
recvd = messaging.recv_sock(sub_sock) |
|
|
|
self.assertTrue(recvd is None) |
|
|
|
assert recvd is None |
|
|
|
|
|
|
|
|
|
|
|
# no wait and one msg in queue |
|
|
|
# no wait and one msg in queue |
|
|
|
msg = random_carstate() |
|
|
|
msg = random_carstate() |
|
|
|
pub_sock.send(msg.to_bytes()) |
|
|
|
pub_sock.send(msg.to_bytes()) |
|
|
|
time.sleep(0.01) |
|
|
|
time.sleep(0.01) |
|
|
|
recvd = messaging.recv_sock(sub_sock) |
|
|
|
recvd = messaging.recv_sock(sub_sock) |
|
|
|
self.assertIsInstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert isinstance(recvd, capnp._DynamicStructReader) |
|
|
|
# https://github.com/python/mypy/issues/13038 |
|
|
|
# https://github.com/python/mypy/issues/13038 |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
|
|
|
|
|
|
|
@ -139,16 +132,16 @@ class TestMessaging(unittest.TestCase): |
|
|
|
|
|
|
|
|
|
|
|
# no msg in queue, socket should timeout |
|
|
|
# no msg in queue, socket should timeout |
|
|
|
recvd = messaging.recv_one(sub_sock) |
|
|
|
recvd = messaging.recv_one(sub_sock) |
|
|
|
self.assertTrue(recvd is None) |
|
|
|
assert recvd is None |
|
|
|
|
|
|
|
|
|
|
|
# one msg in queue |
|
|
|
# one msg in queue |
|
|
|
msg = random_carstate() |
|
|
|
msg = random_carstate() |
|
|
|
pub_sock.send(msg.to_bytes()) |
|
|
|
pub_sock.send(msg.to_bytes()) |
|
|
|
recvd = messaging.recv_one(sub_sock) |
|
|
|
recvd = messaging.recv_one(sub_sock) |
|
|
|
self.assertIsInstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert isinstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
|
|
|
|
|
|
|
|
@zmq_expected_failure |
|
|
|
@pytest.mark.xfail(condition="ZMQ" in os.environ, reason='ZMQ detected') |
|
|
|
def test_recv_one_or_none(self): |
|
|
|
def test_recv_one_or_none(self): |
|
|
|
sock = "carState" |
|
|
|
sock = "carState" |
|
|
|
pub_sock = messaging.pub_sock(sock) |
|
|
|
pub_sock = messaging.pub_sock(sock) |
|
|
@ -157,13 +150,13 @@ class TestMessaging(unittest.TestCase): |
|
|
|
|
|
|
|
|
|
|
|
# no msg in queue, socket shouldn't block |
|
|
|
# no msg in queue, socket shouldn't block |
|
|
|
recvd = messaging.recv_one_or_none(sub_sock) |
|
|
|
recvd = messaging.recv_one_or_none(sub_sock) |
|
|
|
self.assertTrue(recvd is None) |
|
|
|
assert recvd is None |
|
|
|
|
|
|
|
|
|
|
|
# one msg in queue |
|
|
|
# one msg in queue |
|
|
|
msg = random_carstate() |
|
|
|
msg = random_carstate() |
|
|
|
pub_sock.send(msg.to_bytes()) |
|
|
|
pub_sock.send(msg.to_bytes()) |
|
|
|
recvd = messaging.recv_one_or_none(sub_sock) |
|
|
|
recvd = messaging.recv_one_or_none(sub_sock) |
|
|
|
self.assertIsInstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert isinstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
|
|
|
|
|
|
|
|
def test_recv_one_retry(self): |
|
|
|
def test_recv_one_retry(self): |
|
|
@ -179,7 +172,7 @@ class TestMessaging(unittest.TestCase): |
|
|
|
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,)) |
|
|
|
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,)) |
|
|
|
p.start() |
|
|
|
p.start() |
|
|
|
time.sleep(sock_timeout*15) |
|
|
|
time.sleep(sock_timeout*15) |
|
|
|
self.assertTrue(p.is_alive()) |
|
|
|
assert p.is_alive() |
|
|
|
p.terminate() |
|
|
|
p.terminate() |
|
|
|
|
|
|
|
|
|
|
|
# wait 15 socket timeouts before sending |
|
|
|
# wait 15 socket timeouts before sending |
|
|
@ -187,9 +180,6 @@ class TestMessaging(unittest.TestCase): |
|
|
|
delayed_send(sock_timeout*15, pub_sock, msg.to_bytes()) |
|
|
|
delayed_send(sock_timeout*15, pub_sock, msg.to_bytes()) |
|
|
|
start_time = time.monotonic() |
|
|
|
start_time = time.monotonic() |
|
|
|
recvd = messaging.recv_one_retry(sub_sock) |
|
|
|
recvd = messaging.recv_one_retry(sub_sock) |
|
|
|
self.assertGreaterEqual(time.monotonic() - start_time, sock_timeout*15) |
|
|
|
assert (time.monotonic() - start_time) >= sock_timeout*15 |
|
|
|
self.assertIsInstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert isinstance(recvd, capnp._DynamicStructReader) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
assert_carstate(msg.carState, recvd.carState) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
|
|
unittest.main() |
|
|
|
|
|
|
|