openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
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.

210 lines
8.3 KiB

5 years ago
#!/usr/bin/env python3
import argparse
5 years ago
import os
import sys
from typing import Any
5 years ago
from selfdrive.car.car_helpers import interface_names
from selfdrive.test.openpilotci import get_url, upload_file
3 years ago
from selfdrive.test.process_replay.compare_logs import compare_logs, save_log
from selfdrive.test.process_replay.process_replay import CONFIGS, PROC_REPLAY_DIR, check_enabled, replay_process
from selfdrive.version import get_commit
5 years ago
from tools.lib.logreader import LogReader
original_segments = [
("BODY", "bd6a637565e91581|2022-04-04--22-05-08--0"), # COMMA.BODY
("HYUNDAI", "02c45f73a2e5c6e9|2021-01-01--19-08-22--1"), # HYUNDAI.SONATA
("TOYOTA", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.PRIUS (INDI)
("TOYOTA2", "0982d79ebb0de295|2021-01-03--20-03-36--6"), # TOYOTA.RAV4 (LQR)
("TOYOTA3", "f7d7e3538cda1a2a|2021-08-16--08-55-34--6"), # TOYOTA.COROLLA_TSS2
("HONDA", "eb140f119469d9ab|2021-06-12--10-46-24--27"), # HONDA.CIVIC (NIDEC)
("HONDA2", "7d2244f34d1bbcda|2021-06-25--12-25-37--26"), # HONDA.ACCORD (BOSCH)
("CHRYSLER", "4deb27de11bee626|2021-02-20--11-28-55--8"), # CHRYSLER.PACIFICA
("SUBARU", "4d70bc5e608678be|2021-01-15--17-02-04--5"), # SUBARU.IMPREZA
("GM", "0c58b6a25109da2b|2021-02-23--16-35-50--11"), # GM.VOLT
("NISSAN", "35336926920f3571|2021-02-12--18-38-48--46"), # NISSAN.XTRAIL
4 years ago
("VOLKSWAGEN", "de9592456ad7d144|2021-06-29--11-00-15--6"), # VOLKSWAGEN.GOLF
("MAZDA", "bd6a637565e91581|2021-10-30--15-14-53--2"), # MAZDA.CX9_2021
# Enable when port is tested and dascamOnly is no longer set
#("TESLA", "bb50caf5f0945ab1|2021-06-19--17-20-18--3"), # TESLA.AP2_MODELS
5 years ago
]
segments = [
3 years ago
("BODY", "bd6a637565e91581|2022-04-04--22-05-08--0"),
("HYUNDAI", "fakedata|2022-01-20--17-49-04--0"),
("TOYOTA", "fakedata|2022-04-29--15-57-12--0"),
("TOYOTA2", "fakedata|2022-04-29--16-08-01--0"),
("TOYOTA3", "fakedata|2022-04-29--16-17-39--0"),
3 years ago
("HONDA", "fakedata|2022-01-20--17-56-40--0"),
("HONDA2", "fakedata|2022-04-29--16-31-55--0"),
("CHRYSLER", "fakedata|2022-01-20--18-00-11--0"),
("SUBARU", "fakedata|2022-01-20--18-01-57--0"),
("GM", "fakedata|2022-01-20--18-03-41--0"),
("NISSAN", "fakedata|2022-01-20--18-05-29--0"),
("VOLKSWAGEN", "fakedata|2022-01-20--18-07-15--0"),
("MAZDA", "fakedata|2022-01-20--18-09-32--0"),
]
# dashcamOnly makes don't need to be tested until a full port is done
excluded_interfaces = ["mock", "ford", "mazda", "tesla"]
3 years ago
BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/"
3 years ago
REF_COMMIT_FN = os.path.join(PROC_REPLAY_DIR, "ref_commit")
3 years ago
def test_process(cfg, lr, cmp_log_fn, ignore_fields=None, ignore_msgs=None):
if ignore_fields is None:
ignore_fields = []
if ignore_msgs is None:
ignore_msgs = []
cmp_log_path = cmp_log_fn if os.path.exists(cmp_log_fn) else BASE_URL + os.path.basename(cmp_log_fn)
cmp_log_msgs = list(LogReader(cmp_log_path))
if not len(cmp_log_msgs):
3 years ago
raise Exception("No log messages for ref commit")
log_msgs = replay_process(cfg, lr)
# check to make sure openpilot is engaged in the route
if cfg.proc_name == "controlsd":
if not check_enabled(log_msgs):
segment = cmp_log_fn.split("/")[-1].split("_")[0]
raise Exception(f"Route never enabled: {segment}")
try:
return compare_logs(cmp_log_msgs, log_msgs, ignore_fields + cfg.ignore, ignore_msgs, cfg.tolerance), log_msgs
except Exception as e:
return str(e), log_msgs
3 years ago
def format_diff(results, ref_commit):
diff1, diff2 = "", ""
diff2 += f"***** tested against commit {ref_commit} *****\n"
failed = False
for segment, result in list(results.items()):
diff1 += f"***** results for segment {segment} *****\n"
diff2 += f"***** differences for segment {segment} *****\n"
for proc, diff in list(result.items()):
diff1 += f"\t{proc}\n"
diff2 += f"*** process: {proc} ***\n"
if isinstance(diff, str):
diff1 += f"\t\t{diff}\n"
failed = True
elif len(diff):
cnt = {}
for d in diff:
diff2 += f"\t{str(d)}\n"
k = str(d[1])
cnt[k] = 1 if k not in cnt else cnt[k] + 1
for k, v in sorted(cnt.items()):
diff1 += f"\t\t{k}: {v}\n"
failed = True
return diff1, diff2, failed
5 years ago
3 years ago
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Regression test to identify changes in a process's output")
# whitelist has precedence over blacklist in case both are defined
parser.add_argument("--whitelist-procs", type=str, nargs="*", default=[],
help="Whitelist given processes from the test (e.g. controlsd)")
parser.add_argument("--whitelist-cars", type=str, nargs="*", default=[],
help="Whitelist given cars from the test (e.g. HONDA)")
parser.add_argument("--blacklist-procs", type=str, nargs="*", default=[],
help="Blacklist given processes from the test (e.g. controlsd)")
parser.add_argument("--blacklist-cars", type=str, nargs="*", default=[],
help="Blacklist given cars from the test (e.g. HONDA)")
parser.add_argument("--ignore-fields", type=str, nargs="*", default=[],
help="Extra fields or msgs to ignore (e.g. carState.events)")
parser.add_argument("--ignore-msgs", type=str, nargs="*", default=[],
help="Msgs to ignore (e.g. carEvents)")
parser.add_argument("--update-refs", action="store_true",
3 years ago
help="Regenerates and uploads ref logs on current commit")
parser.add_argument("--upload-only", action="store_true",
help="Skips testing processes and uploads logs from previous test run")
args = parser.parse_args()
full_test = 0 == len(args.whitelist_procs) == len(args.whitelist_cars) == len(args.blacklist_procs) == \
len(args.blacklist_cars) == len(args.ignore_fields) == len(args.ignore_msgs)
upload = args.update_refs or args.upload_only
if upload:
assert full_test, "Can't whitelist or blacklist when uploading logs"
5 years ago
try:
3 years ago
ref_commit = open(REF_COMMIT_FN).read().strip()
except FileNotFoundError:
print("Couldn't find reference commit")
5 years ago
sys.exit(1)
3 years ago
cur_commit = get_commit()
if cur_commit is None:
raise Exception("Couldn't get current commit")
3 years ago
print(f"***** testing against commit {ref_commit} *****")
5 years ago
# check to make sure all car brands are tested
3 years ago
if full_test:
tested_cars = {c.lower() for c, _ in segments}
untested = (set(interface_names) - set(excluded_interfaces)) - tested_cars
assert len(untested) == 0, f"Cars missing routes: {str(untested)}"
results: Any = {}
for car_brand, segment in segments:
if (len(args.whitelist_cars) and car_brand.upper() not in args.whitelist_cars) or \
(not len(args.whitelist_cars) and car_brand.upper() in args.blacklist_cars):
continue
print(f"***** testing route segment {segment} *****\n")
5 years ago
results[segment] = {}
r, n = segment.rsplit("--", 1)
lr = LogReader(get_url(r, n))
5 years ago
for cfg in CONFIGS:
if (len(args.whitelist_procs) and cfg.proc_name not in args.whitelist_procs) or \
(not len(args.whitelist_procs) and cfg.proc_name in args.blacklist_procs):
continue
3 years ago
cur_log_fn = os.path.join(PROC_REPLAY_DIR, f"{segment}_{cfg.proc_name}_{cur_commit}.bz2")
if not args.upload_only:
cmp_log_fn = os.path.join(PROC_REPLAY_DIR, f"{segment}_{cfg.proc_name}_{ref_commit}.bz2")
results[segment][cfg.proc_name], log_msgs = test_process(cfg, lr, cmp_log_fn, args.ignore_fields, args.ignore_msgs)
# save logs so we can upload on process replay failure
save_log(cur_log_fn, log_msgs)
5 years ago
if upload:
assert os.path.exists(cur_log_fn), f"Cannot find log to upload: {cur_log_fn}"
print(f'Uploading: {cur_log_fn}')
upload_file(cur_log_fn, os.path.basename(cur_log_fn))
os.remove(cur_log_fn)
3 years ago
diff1, diff2, failed = format_diff(results, ref_commit)
with open(os.path.join(PROC_REPLAY_DIR, "diff.txt"), "w") as f:
f.write(diff2)
print(diff1)
5 years ago
if failed:
print("TEST FAILED")
3 years ago
if not upload:
print("\n\nTo update the reference logs for this test run:")
print("./test_processes.py --upload-only")
else:
print("TEST SUCCEEDED")
5 years ago
3 years ago
if upload:
with open(REF_COMMIT_FN, "w") as f:
f.write(cur_commit)
3 years ago
print(f"\n\nUpdated reference logs for commit: {ref_commit}")
3 years ago
5 years ago
sys.exit(int(failed))