You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.0 KiB
125 lines
4.0 KiB
4 years ago
|
#!/usr/bin/env python3
|
||
|
import math
|
||
|
import os
|
||
|
import random
|
||
|
import shutil
|
||
|
import subprocess
|
||
|
import time
|
||
|
import unittest
|
||
|
from parameterized import parameterized
|
||
|
from pathlib import Path
|
||
|
from tqdm import trange
|
||
|
|
||
|
from common.params import Params
|
||
|
from common.timeout import Timeout
|
||
|
from selfdrive.hardware import EON, TICI
|
||
|
from selfdrive.test.helpers import with_processes
|
||
|
from selfdrive.loggerd.config import ROOT, CAMERA_FPS
|
||
|
|
||
|
|
||
|
# baseline file sizes for a 2s segment, in bytes
|
||
|
FULL_SIZE = 1253786
|
||
|
if EON:
|
||
|
CAMERAS = {
|
||
|
"fcamera": FULL_SIZE,
|
||
|
"dcamera": 770920,
|
||
|
"qcamera": 38533,
|
||
|
}
|
||
|
elif TICI:
|
||
|
CAMERAS = {f"{c}camera": FULL_SIZE if c!="q" else 38533 for c in ["f", "e", "d", "q"]}
|
||
|
else:
|
||
|
CAMERAS = {}
|
||
|
|
||
|
ALL_CAMERA_COMBINATIONS = [(cameras,) for cameras in [CAMERAS, {k:CAMERAS[k] for k in CAMERAS if k!='dcamera'}]]
|
||
|
|
||
|
FRAME_TOLERANCE = 0
|
||
|
FILE_SIZE_TOLERANCE = 0.5
|
||
|
|
||
|
class TestEncoder(unittest.TestCase):
|
||
|
|
||
|
# TODO: all of loggerd should work on PC
|
||
|
@classmethod
|
||
|
def setUpClass(cls):
|
||
|
if not (EON or TICI):
|
||
|
raise unittest.SkipTest
|
||
|
|
||
|
def setUp(self):
|
||
|
self._clear_logs()
|
||
|
|
||
|
self.segment_length = 2
|
||
|
os.environ["LOGGERD_TEST"] = "1"
|
||
|
os.environ["LOGGERD_SEGMENT_LENGTH"] = str(self.segment_length)
|
||
|
|
||
|
def tearDown(self):
|
||
|
self._clear_logs()
|
||
|
|
||
|
def _clear_logs(self):
|
||
|
if os.path.exists(ROOT):
|
||
|
shutil.rmtree(ROOT)
|
||
|
|
||
|
def _get_latest_segment_path(self):
|
||
|
last_route = sorted(Path(ROOT).iterdir(), key=os.path.getmtime)[-1]
|
||
|
return os.path.join(ROOT, last_route)
|
||
|
|
||
|
# TODO: this should run faster than real time
|
||
|
@parameterized.expand(ALL_CAMERA_COMBINATIONS)
|
||
|
@with_processes(['camerad', 'sensord', 'loggerd'], init_time=5)
|
||
|
def test_log_rotation(self, cameras):
|
||
|
print("checking targets:", cameras)
|
||
|
Params().put("RecordFront", "1" if 'dcamera' in cameras else "0")
|
||
|
|
||
|
num_segments = random.randint(80, 150)
|
||
|
if "CI" in os.environ:
|
||
|
num_segments = random.randint(15, 20) # ffprobe is slow on comma two
|
||
|
|
||
|
# wait for loggerd to make the dir for first segment
|
||
|
time.sleep(10)
|
||
|
route_prefix_path = None
|
||
|
with Timeout(30):
|
||
|
while route_prefix_path is None:
|
||
|
try:
|
||
|
route_prefix_path = self._get_latest_segment_path().rsplit("--", 1)[0]
|
||
|
except Exception:
|
||
|
time.sleep(2)
|
||
|
continue
|
||
|
|
||
|
for i in trange(num_segments):
|
||
|
# poll for next segment
|
||
|
if i < num_segments - 1:
|
||
|
with Timeout(self.segment_length*3, error_msg=f"timed out waiting for segment {i}"):
|
||
|
while True:
|
||
|
seg_num = int(self._get_latest_segment_path().rsplit("--", 1)[1])
|
||
|
if seg_num > i:
|
||
|
break
|
||
|
time.sleep(0.1)
|
||
|
else:
|
||
|
time.sleep(self.segment_length)
|
||
|
|
||
|
# check each camera file size
|
||
|
for camera, size in cameras.items():
|
||
|
ext = "ts" if camera=='qcamera' else "hevc"
|
||
|
file_path = f"{route_prefix_path}--{i}/{camera}.{ext}"
|
||
|
|
||
|
# check file size
|
||
|
self.assertTrue(os.path.exists(file_path), f"couldn't find {file_path}")
|
||
|
file_size = os.path.getsize(file_path)
|
||
|
self.assertTrue(math.isclose(file_size, size, rel_tol=FILE_SIZE_TOLERANCE),
|
||
|
f"{camera} failed size check: expected {size}, got {file_size}")
|
||
|
|
||
|
if camera == 'qcamera':
|
||
|
continue
|
||
|
|
||
|
# check frame count
|
||
|
cmd = f"ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames \
|
||
|
-of default=nokey=1:noprint_wrappers=1 {file_path}"
|
||
|
expected_frames = self.segment_length * CAMERA_FPS // 2 if (EON and camera=='dcamera') else self.segment_length * CAMERA_FPS
|
||
|
frame_tolerance = FRAME_TOLERANCE+1 if (EON and camera=='dcamera') or i==0 else FRAME_TOLERANCE
|
||
|
frame_count = int(subprocess.check_output(cmd, shell=True, encoding='utf8').strip())
|
||
|
|
||
|
self.assertTrue(abs(expected_frames - frame_count) <= frame_tolerance,
|
||
|
f"{camera} failed frame count check: expected {expected_frames}, got {frame_count}")
|
||
|
shutil.rmtree(f"{route_prefix_path}--{i}")
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
unittest.main()
|