-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement V4L2 compliance parser (New) #1569
base: main
Are you sure you want to change the base?
Conversation
da66a9d
to
8bf354d
Compare
8bf354d
to
c001bcb
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1569 +/- ##
==========================================
+ Coverage 48.00% 48.04% +0.04%
==========================================
Files 371 371
Lines 39833 39877 +44
Branches 6730 6739 +9
==========================================
+ Hits 19121 19159 +38
- Misses 19994 20000 +6
Partials 718 718
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job here, sorry it took me a while to review it. Consider my comments below, the only one that is blocking is the one about pkg_resource
, because soon it will go away, and when it does I will have to patch half of checkbox to add the workaroud I suggested.
lines = [] # type: list[str] | ||
for line in out.stdout.splitlines(): | ||
clean_line = line.strip() | ||
if clean_line != "": | ||
lines.append(clean_line) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lines = [] # type: list[str] | |
for line in out.stdout.splitlines(): | |
clean_line = line.strip() | |
if clean_line != "": | |
lines.append(clean_line) | |
lines = [line.strip() for line in out.stdout.splitlines() if line.strip()] |
summary = {} | ||
if match_output: | ||
summary = { | ||
"device_name": match_output.group(1), | ||
"total": int(match_output.group(2)), | ||
"succeeded": int(match_output.group(3)), | ||
"failed": int(match_output.group(4)), | ||
"warnings": int(match_output.group(5)), | ||
} | ||
|
||
assert summary != {}, ( | ||
"There's no summary line in v4l2-compliance's output. " | ||
"Output might be corrupted." | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, never hide the output if you can, especially when it fails an expectation
summary = {} | |
if match_output: | |
summary = { | |
"device_name": match_output.group(1), | |
"total": int(match_output.group(2)), | |
"succeeded": int(match_output.group(3)), | |
"failed": int(match_output.group(4)), | |
"warnings": int(match_output.group(5)), | |
} | |
assert summary != {}, ( | |
"There's no summary line in v4l2-compliance's output. " | |
"Output might be corrupted." | |
) | |
if not match_output: | |
raise SystemExit( | |
"There's no summary line in v4l2-compliance's output. " | |
"Output might be corrupted. Last line is: \n {}".format(lines[-1]) | |
) | |
summary = { | |
"device_name": match_output.group(1), | |
"total": int(match_output.group(2)), | |
"succeeded": int(match_output.group(3)), | |
"failed": int(match_output.group(4)), | |
"warnings": int(match_output.group(5)), | |
} |
for line in lines: | ||
if line.endswith(": OK"): | ||
name, is_ioctl_name = get_test_name_from_line(line) | ||
if is_ioctl_name: | ||
# ignore unknown test names, just don't append | ||
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | ||
details["succeeded"].append(ioctl_name) | ||
elif line.endswith(": OK (Not Supported)"): | ||
name, is_ioctl_name = get_test_name_from_line(line) | ||
if is_ioctl_name: | ||
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | ||
details["not_supported"].append(ioctl_name) | ||
elif line.endswith(": FAIL"): | ||
name, is_ioctl_name = get_test_name_from_line(line) | ||
if is_ioctl_name: | ||
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | ||
details["failed"].append(ioctl_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
slightly easier to read imo
for line in lines: | |
if line.endswith(": OK"): | |
name, is_ioctl_name = get_test_name_from_line(line) | |
if is_ioctl_name: | |
# ignore unknown test names, just don't append | |
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | |
details["succeeded"].append(ioctl_name) | |
elif line.endswith(": OK (Not Supported)"): | |
name, is_ioctl_name = get_test_name_from_line(line) | |
if is_ioctl_name: | |
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | |
details["not_supported"].append(ioctl_name) | |
elif line.endswith(": FAIL"): | |
name, is_ioctl_name = get_test_name_from_line(line) | |
if is_ioctl_name: | |
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | |
details["failed"].append(ioctl_name) | |
for line in lines: | |
if line.endswith(": OK"): | |
result = "succeeded" | |
elif line.endswith(": OK (Not Supported)"): | |
result = "not_supported" | |
elif line.endswith(": FAIL"): | |
result = "failed" | |
else: | |
continue | |
name, is_ioctl_name = get_test_name_from_line(line) | |
if is_ioctl_name: | |
# ignore unknown test names, just don't append | |
for ioctl_name in TEST_NAME_TO_IOCTL_MAP.get(name, []): | |
details[result].append(ioctl_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh that's a lot cleaner ty
from pkg_resources import resource_filename | ||
|
||
|
||
def read_file_as_str(name: str): | ||
resource = "parsers/tests/v4l2_compliance_data/{}.txt".format(name) | ||
filename = resource_filename("checkbox_support", resource) | ||
with open(filename) as f: | ||
return f.read() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point pkg_resources is very deprecated, lets avoid it if possible
from pkg_resources import resource_filename | |
def read_file_as_str(name: str): | |
resource = "parsers/tests/v4l2_compliance_data/{}.txt".format(name) | |
filename = resource_filename("checkbox_support", resource) | |
with open(filename) as f: | |
return f.read() | |
try: | |
# new in python 3.9 | |
from importlib.resources import files | |
def read_file_as_str(name: str): | |
resource_path = "parsers/tests/v4l2_compliance_data/{}.txt".format(name) | |
ref = resources.files("checkbox_support") | |
file_ref = ref.joinpath(resource_path) | |
with file_ref.open('r') as f: | |
return f.read() | |
except ImportError: | |
from pkg_resources import resource_filename | |
def read_file_as_str(name: str): | |
resource = "parsers/tests/v4l2_compliance_data/{}.txt".format(name) | |
filename = resource_filename("checkbox_support", resource) | |
with open(filename) as f: | |
return f.read() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, I used pkg_resource because I saw another parser test using that to get the test input files. (Also does this mean we are moving towards python 3.9? :D)
], | ||
"VIDIOC_G/S_AUDIO": ["VIDIOC_G_AUDIO", "VIDIOC_S_AUDIO"], | ||
"VIDIOC_G/S_MODULATOR": ["VIDIOC_G_MODULATOR", "VIDIOC_S_MODULATOR"], | ||
"VIDIOC_G/S_FREQUENCY": ["VIDIOC_G_FREQUENCY", "VIDIOC_S_FREQUENCY"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this one is duplicated
"VIDIOC_G/S_FREQUENCY": ["VIDIOC_G_FREQUENCY", "VIDIOC_S_FREQUENCY"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the catch!
Description
This PR implements a V4L2 compliance test parser in checkbox support for test cases to validate that the ioctl requests they need to use are actually supported.
Requires #1566
Resolved issues
Documentation
Test cases can
from checkbox_support.parsers.v4l2_compliance import parse_v4l2_compliance
and call the function for a device, such asparse_v4l2_compliance('/dev/video0')
Tests
Unit tests