2023-09-20 10:35:57 -07:00
import os
2022-04-22 09:00:49 -07:00
import subprocess
import time
import unittest
2023-09-20 10:35:57 -07:00
2022-04-22 09:00:49 -07:00
from multiprocessing import Queue
from cereal import messaging
2023-08-20 20:49:55 -07:00
from openpilot . common . basedir import BASEDIR
2022-06-11 15:32:12 -07:00
SIM_DIR = os . path . join ( BASEDIR , " tools/sim " )
2022-04-22 09:00:49 -07:00
2023-09-20 10:35:57 -07:00
class TestSimBridgeBase ( unittest . TestCase ) :
@classmethod
def setUpClass ( cls ) :
if cls is TestSimBridgeBase :
2023-12-11 20:38:37 -08:00
raise unittest . SkipTest ( " Don ' t run this base class, run test_metadrive_bridge.py instead " )
2022-04-22 09:00:49 -07:00
def setUp ( self ) :
self . processes = [ ]
def test_engage ( self ) :
# Startup manager and bridge.py. Check processes are running, then engage and verify.
2022-06-11 15:32:12 -07:00
p_manager = subprocess . Popen ( " ./launch_openpilot.sh " , cwd = SIM_DIR )
2022-04-22 09:00:49 -07:00
self . processes . append ( p_manager )
2023-12-01 22:48:29 -08:00
sm = messaging . SubMaster ( [ ' controlsState ' , ' onroadEvents ' , ' managerState ' ] )
2022-04-22 09:00:49 -07:00
q = Queue ( )
2023-12-11 20:38:37 -08:00
bridge = self . create_bridge ( )
p_bridge = bridge . run ( q , retries = 10 )
2022-04-22 09:00:49 -07:00
self . processes . append ( p_bridge )
2022-06-11 15:32:12 -07:00
max_time_per_step = 60
2022-04-22 09:00:49 -07:00
# Wait for bridge to startup
start_waiting = time . monotonic ( )
2023-12-11 20:38:37 -08:00
while not bridge . started and time . monotonic ( ) < start_waiting + max_time_per_step :
2022-04-22 09:00:49 -07:00
time . sleep ( 0.1 )
self . assertEqual ( p_bridge . exitcode , None , f " Bridge process should be running, but exited with code { p_bridge . exitcode } " )
start_time = time . monotonic ( )
no_car_events_issues_once = False
car_event_issues = [ ]
not_running = [ ]
while time . monotonic ( ) < start_time + max_time_per_step :
sm . update ( )
not_running = [ p . name for p in sm [ ' managerState ' ] . processes if not p . running and p . shouldBeRunning ]
2023-12-01 22:48:29 -08:00
car_event_issues = [ event . name for event in sm [ ' onroadEvents ' ] if any ( [ event . noEntry , event . softDisable , event . immediateDisable ] ) ]
2022-04-22 09:00:49 -07:00
if sm . all_alive ( ) and len ( car_event_issues ) == 0 and len ( not_running ) == 0 :
no_car_events_issues_once = True
break
2023-08-08 17:13:35 -07:00
self . assertTrue ( no_car_events_issues_once ,
f " Failed because no messages received, or CarEvents ' { car_event_issues } ' or processes not running ' { not_running } ' " )
2022-04-22 09:00:49 -07:00
start_time = time . monotonic ( )
min_counts_control_active = 100
control_active = 0
while time . monotonic ( ) < start_time + max_time_per_step :
sm . update ( )
2022-08-17 18:03:33 -07:00
q . put ( " cruise_down " ) # Try engaging
2022-04-22 09:00:49 -07:00
if sm . all_alive ( ) and sm [ ' controlsState ' ] . active :
control_active + = 1
if control_active == min_counts_control_active :
break
self . assertEqual ( min_counts_control_active , control_active , f " Simulator did not engage a minimal of { min_counts_control_active } steps was { control_active } " )
def tearDown ( self ) :
print ( " Test shutting down. CommIssues are acceptable " )
for p in reversed ( self . processes ) :
p . terminate ( )
for p in reversed ( self . processes ) :
if isinstance ( p , subprocess . Popen ) :
p . wait ( 15 )
else :
p . join ( 15 )
if __name__ == " __main__ " :
unittest . main ( )