|  |  |  | @ -10,22 +10,37 @@ import time | 
			
		
	
		
			
				
					|  |  |  |  | import unittest | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | from parameterized import parameterized | 
			
		
	
		
			
				
					|  |  |  |  | from cereal import messaging, log | 
			
		
	
		
			
				
					|  |  |  |  | from cereal import messaging, car, log | 
			
		
	
		
			
				
					|  |  |  |  | from cereal.visionipc import VisionIpcServer, VisionStreamType | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | from cereal.messaging import SubMaster, PubMaster | 
			
		
	
		
			
				
					|  |  |  |  | from openpilot.common.params import Params | 
			
		
	
		
			
				
					|  |  |  |  | from openpilot.common.realtime import DT_MDL | 
			
		
	
		
			
				
					|  |  |  |  | from openpilot.common.transformations.camera import tici_f_frame_size | 
			
		
	
		
			
				
					|  |  |  |  | from openpilot.selfdrive.test.helpers import with_processes | 
			
		
	
		
			
				
					|  |  |  |  | from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_camera_state | 
			
		
	
		
			
				
					|  |  |  |  | from openpilot.tools.webcam.camera import Camera | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | UI_DELAY = 0.5 # may be slower on CI? | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | NetworkType = log.DeviceState.NetworkType | 
			
		
	
		
			
				
					|  |  |  |  | NetworkStrength = log.DeviceState.NetworkStrength | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | EventName = car.CarEvent.EventName | 
			
		
	
		
			
				
					|  |  |  |  | EVENTS_BY_NAME = {v: k for k, v in EventName.schema.enumerants.items()} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def setup_common(click, pm: PubMaster): | 
			
		
	
		
			
				
					|  |  |  |  |   Params().put("DongleId", "123456789012345") | 
			
		
	
		
			
				
					|  |  |  |  |   dat = messaging.new_message('deviceState') | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.started = True | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.networkType = NetworkType.cell4G | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.networkStrength = NetworkStrength.moderate | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.freeSpacePercent = 80 | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.memoryUsagePercent = 2 | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.cpuTempC = [2,]*3 | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.gpuTempC = [2,]*3 | 
			
		
	
		
			
				
					|  |  |  |  |   dat.deviceState.cpuUsagePercent = [2,]*8 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   pm.send("deviceState", dat) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -47,13 +62,61 @@ def setup_settings_network(click, pm: PubMaster): | 
			
		
	
		
			
				
					|  |  |  |  |   click(300, 600) | 
			
		
	
		
			
				
					|  |  |  |  |   time.sleep(UI_DELAY) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def setup_onroad(click, pm: PubMaster): | 
			
		
	
		
			
				
					|  |  |  |  |   setup_common(click, pm) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   dat = messaging.new_message('pandaStates', 1) | 
			
		
	
		
			
				
					|  |  |  |  |   dat.pandaStates[0].ignitionLine = True | 
			
		
	
		
			
				
					|  |  |  |  |   dat.pandaStates[0].pandaType = log.PandaState.PandaType.uno | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   pm.send("pandaStates", dat) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   server = VisionIpcServer("camerad") | 
			
		
	
		
			
				
					|  |  |  |  |   server.create_buffers(VisionStreamType.VISION_STREAM_ROAD, 40, False, *tici_f_frame_size) | 
			
		
	
		
			
				
					|  |  |  |  |   server.create_buffers(VisionStreamType.VISION_STREAM_DRIVER, 40, False, *tici_f_frame_size) | 
			
		
	
		
			
				
					|  |  |  |  |   server.create_buffers(VisionStreamType.VISION_STREAM_WIDE_ROAD, 40, False, *tici_f_frame_size) | 
			
		
	
		
			
				
					|  |  |  |  |   server.start_listener() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   time.sleep(UI_DELAY) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   IMG = Camera.bgr2nv12(np.random.randint(0, 255, (*tici_f_frame_size,3), dtype=np.uint8)) | 
			
		
	
		
			
				
					|  |  |  |  |   IMG_BYTES = IMG.flatten().tobytes() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   cams = ('roadCameraState', 'wideRoadCameraState') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   frame_id = 0 | 
			
		
	
		
			
				
					|  |  |  |  |   for cam in cams: | 
			
		
	
		
			
				
					|  |  |  |  |     msg = messaging.new_message(cam) | 
			
		
	
		
			
				
					|  |  |  |  |     cs = getattr(msg, cam) | 
			
		
	
		
			
				
					|  |  |  |  |     cs.frameId = frame_id | 
			
		
	
		
			
				
					|  |  |  |  |     cs.timestampSof = int((frame_id * DT_MDL) * 1e9) | 
			
		
	
		
			
				
					|  |  |  |  |     cs.timestampEof = int((frame_id * DT_MDL) * 1e9) | 
			
		
	
		
			
				
					|  |  |  |  |     cam_meta = meta_from_camera_state(cam) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pm.send(msg.which(), msg) | 
			
		
	
		
			
				
					|  |  |  |  |     server.send(cam_meta.stream, IMG_BYTES, cs.frameId, cs.timestampSof, cs.timestampEof) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   time.sleep(UI_DELAY) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def setup_onroad_map(click, pm: PubMaster): | 
			
		
	
		
			
				
					|  |  |  |  |   setup_onroad(click, pm) | 
			
		
	
		
			
				
					|  |  |  |  |   click(500, 500) | 
			
		
	
		
			
				
					|  |  |  |  |   time.sleep(UI_DELAY) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def setup_onroad_sidebar(click, pm: PubMaster): | 
			
		
	
		
			
				
					|  |  |  |  |   setup_onroad_map(click, pm) | 
			
		
	
		
			
				
					|  |  |  |  |   click(500, 500) | 
			
		
	
		
			
				
					|  |  |  |  |   time.sleep(UI_DELAY) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | CASES = { | 
			
		
	
		
			
				
					|  |  |  |  |   "homescreen": setup_homescreen, | 
			
		
	
		
			
				
					|  |  |  |  |   "settings_device": setup_settings_device, | 
			
		
	
		
			
				
					|  |  |  |  |   "settings_network": setup_settings_network, | 
			
		
	
		
			
				
					|  |  |  |  |   "onroad": setup_onroad, | 
			
		
	
		
			
				
					|  |  |  |  |   "onroad_map": setup_onroad_map, | 
			
		
	
		
			
				
					|  |  |  |  |   "onroad_map_sidebar": setup_onroad_sidebar | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | TEST_DIR = pathlib.Path(__file__).parent | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | TEST_OUTPUT_DIR = TEST_DIR / "report" | 
			
		
	
	
		
			
				
					|  |  |  | @ -67,7 +130,7 @@ class TestUI(unittest.TestCase): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def setup(self): | 
			
		
	
		
			
				
					|  |  |  |  |     self.sm = SubMaster(["uiDebug"]) | 
			
		
	
		
			
				
					|  |  |  |  |     self.pm = PubMaster(["deviceState"]) | 
			
		
	
		
			
				
					|  |  |  |  |     self.pm = PubMaster(["deviceState", "pandaStates", "controlsState", 'roadCameraState', 'wideRoadCameraState']) | 
			
		
	
		
			
				
					|  |  |  |  |     while not self.sm.valid["uiDebug"]: | 
			
		
	
		
			
				
					|  |  |  |  |       self.sm.update(1) | 
			
		
	
		
			
				
					|  |  |  |  |     time.sleep(UI_DELAY) # wait a bit more for the UI to finish rendering | 
			
		
	
	
		
			
				
					|  |  |  | @ -102,6 +165,7 @@ def create_html_report(): | 
			
		
	
		
			
				
					|  |  |  |  |     template = jinja2.Template(f.read()) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   cases = {f.stem: (str(f.relative_to(TEST_OUTPUT_DIR)), "reference.png") for f in SCREENSHOTS_DIR.glob("*.png")} | 
			
		
	
		
			
				
					|  |  |  |  |   cases = dict(sorted(cases.items())) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   with open(OUTPUT_FILE, "w") as f: | 
			
		
	
		
			
				
					|  |  |  |  |     f.write(template.render(cases=cases)) | 
			
		
	
	
		
			
				
					|  |  |  | 
 |