Fix jpeg validation to accept a broader range of jpeg files (BugFix)#1803
Fix jpeg validation to accept a broader range of jpeg files (BugFix)#1803tomli380576 merged 9 commits intomainfrom
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1803 +/- ##
==========================================
+ Coverage 49.83% 49.93% +0.09%
==========================================
Files 377 378 +1
Lines 40719 40766 +47
Branches 6851 6859 +8
==========================================
+ Hits 20294 20356 +62
+ Misses 19700 19683 -17
- Partials 725 727 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
sry I'm really out of ideas on how to get that last few % of test coverage without an actual image for the validator 😿 |
|
I was checking at a clean solution for this but I didn't found one either.
@patch("os.path.exists")
def test_validate_image_no_dimensions(self, mock_exists):
mock_camera = MagicMock()
mock_exists.return_value = True
with patch("builtins.open", mock_open(read_data=b"")):
with patch("builtins.print") as mocked_print, patch(
"camera_test.check_output"
) as mock_check_output:
mock_check_output.return_value = "image/jpeg"
result = CameraTest._validate_image(
mock_camera, "/tmp/test.jpg", 480, 320
)
# should not even start reading the file if the `file` command
# check didn't pass
mocked_print.assert_any_call(
"Image dimensions not found in JPEG file"
)
self.assertEqual(result, False)
@patch("os.path.exists")
@patch("camera_test.check_output")
def test_validate_image_correct_jpeg_format(self, mock_output, mock_exists):
mock_camera = MagicMock()
mock_exists.return_value = True
# Create a temporary file with a valid 1x1 JPEG image
data = (
"ffd8ffe000104a46494600010101004800480000fffe001343726561746564207"
"76974682047494d50ffdb00430001010101010101010101010101010101010101"
"01010101010101010101010101010101010101010101010101010101010101010"
"1010101010101010101010101ffdb004301010101010101010101010101010101"
"01010101010101010101010101010101010101010101010101010101010101010"
"101010101010101010101010101010101ffc00011080001000103011100021101"
"031101ffc4001400010000000000000000000000000000000bffc400141001000"
"00000000000000000000000000000ffc400140101000000000000000000000000"
"00000000ffc40014110100000000000000000000000000000000ffda000c03010"
"002110311003f003ff07fffd9"
)
from tempfile import NamedTemporaryFile
with NamedTemporaryFile(delete=False) as f:
f.write(bytes.fromhex(data))
f.seek(0)
mock_open.return_value = f
mock_output.return_value = "image/jpeg"
result = CameraTest._validate_image(mock_camera, f.name, 1, 1)
self.assertEqual(result, True)Let me know if you think any of the two or both make sense |
|
bad news EDIT: we can use |
fernando79513
left a comment
There was a problem hiding this comment.
Thank you very much for this fix, and also for being so thorough with the testing, I think these last changes could save us from some issues down the line.
LGTM +1!
|
Tysm for the help and review! |
…1803) * fix: relax jpeg file type check * test: reflect changes in test * fix: param 'flush' should be boolean, not file descriptor * fix: use file command for now * test: reflect changes in test * test: increase coverage * test: apply Fernando's suggestion and use a 1x1 mock image * style: formatting * fix: use gst-typefind that's also available on core
…1803) * fix: relax jpeg file type check * test: reflect changes in test * fix: param 'flush' should be boolean, not file descriptor * fix: use file command for now * test: reflect changes in test * test: increase coverage * test: apply Fernando's suggestion and use a 1x1 mock image * style: formatting * fix: use gst-typefind that's also available on core
…1803) * fix: relax jpeg file type check * test: reflect changes in test * fix: param 'flush' should be boolean, not file descriptor * fix: use file command for now * test: reflect changes in test * test: increase coverage * test: apply Fernando's suggestion and use a 1x1 mock image * style: formatting * fix: use gst-typefind that's also available on core
Description
This PR relaxes the validation step for JPEGs to fix #1796 and prints some more debugging messages.
There was another issue where the resolutions subparser was missing the wait_seconds argument. It's fixed now.
Documentation
The check is now done by
gst-typefind-1.0 filename.jpeg. If the return value doesn't contain "image/jpeg" then we will mark the file as broken.Tests
Original unit tests
Real hardware without
fswebcam:USB cameras that only produce video/x-raw: I couldn't find any :( but they are expected to work since jpegenc will be used to build the final photo.
USB cameras that produces some formats in image/jpeg: 24.04 devices are mostly OK, but I found one 22.04 device that created an image with trailing 0s after ffd9: https://certification.canonical.com/hardware/202503-36385/ and a 20.04 device https://certification.canonical.com/hardware/202112-29820/. Image looks fine though and the
filecommand says it's jpeg.MIPI cameras that uses v4l2loopback: OK, the photos produced by them all run through jpegenc so they are expected to pass