From d6506caa04f93fd12f7755a527034180e58fcb84 Mon Sep 17 00:00:00 2001 From: Dmitry Rogozhkin Date: Thu, 14 Aug 2025 23:25:54 +0000 Subject: [PATCH] test: rename cpu_and_cuda to all_supported_devices This commit renames a `cpu_and_cuda()` function used for pytest device parameterization to `all_supported_devices()`. This is helpful for those who work on multi-gpu support in torchcodec as `cpu_and_cuda()` was one of the function required to be patched to allow running torchcodec tests on other devices. Rename steps out from binding function to cuda and allows to reduce the change scope to enable non-cuda devices. Signed-off-by: Dmitry Rogozhkin --- test/conftest.py | 2 +- test/test_decoders.py | 46 +++++++++++++++++++++---------------------- test/test_ops.py | 38 +++++++++++++++++------------------ test/utils.py | 2 +- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index f5db4b5d6..bef5291e5 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -23,7 +23,7 @@ def pytest_collection_modifyitems(items): # with the @needs_cuda decorator. It will also exist if it was # parametrized with a parameter that has the mark: for example if a test # is parametrized with - # @pytest.mark.parametrize('device', cpu_and_cuda()) + # @pytest.mark.parametrize('device', all_supported_devices()) # the "instances" of the tests where device == 'cuda' will have the # 'needs_cuda' mark, and the ones with device == 'cpu' won't have the # mark. diff --git a/test/test_decoders.py b/test/test_decoders.py index d7f53dee3..6b54a1a52 100644 --- a/test/test_decoders.py +++ b/test/test_decoders.py @@ -22,9 +22,9 @@ ) from .utils import ( + all_supported_devices, assert_frames_equal, AV1_VIDEO, - cpu_and_cuda, get_ffmpeg_major_version, H264_10BITS, H265_10BITS, @@ -163,7 +163,7 @@ def test_create_fails(self): VideoDecoder(NASA_VIDEO.path, seek_mode="blah") @pytest.mark.parametrize("num_ffmpeg_threads", (1, 4)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_getitem_int(self, num_ffmpeg_threads, device, seek_mode): decoder = VideoDecoder( @@ -213,7 +213,7 @@ def test_getitem_numpy_int(self): assert_frames_equal(ref_frame1, decoder[numpy.uint32(1)]) assert_frames_equal(ref_frame180, decoder[numpy.uint32(180)]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_getitem_slice(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -373,7 +373,7 @@ def test_device_instance(self): decoder = VideoDecoder(NASA_VIDEO.path, device=torch.device("cpu")) assert isinstance(decoder.metadata, VideoStreamMetadata) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_getitem_fails(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -390,7 +390,7 @@ def test_getitem_fails(self, device, seek_mode): with pytest.raises(TypeError, match="Unsupported key type"): frame = decoder[2.3] # noqa - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_iteration(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -437,7 +437,7 @@ def test_iteration_slow(self): assert iterations == len(decoder) == 390 - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frame_at(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -475,7 +475,7 @@ def test_get_frame_at(self, device, seek_mode): frame9 = decoder.get_frame_at(numpy.uint32(9)) assert_frames_equal(ref_frame9, frame9.data) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frame_at_tuple_unpacking(self, device): decoder = VideoDecoder(NASA_VIDEO.path, device=device) @@ -486,7 +486,7 @@ def test_get_frame_at_tuple_unpacking(self, device): assert frame.pts_seconds == pts assert frame.duration_seconds == duration - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frame_at_fails(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -500,7 +500,7 @@ def test_get_frame_at_fails(self, device, seek_mode): with pytest.raises(IndexError, match="must be less than"): frame = decoder.get_frame_at(10000) # noqa - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_at(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -551,7 +551,7 @@ def test_get_frames_at(self, device, seek_mode): frames.duration_seconds, expected_duration_seconds, atol=1e-4, rtol=0 ) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_at_fails(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -568,7 +568,7 @@ def test_get_frames_at_fails(self, device, seek_mode): with pytest.raises(RuntimeError, match="Expected a value of type"): decoder.get_frames_at([0.3]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frame_at_av1(self, device): if device == "cuda" and get_ffmpeg_major_version() == 4: return @@ -581,7 +581,7 @@ def test_get_frame_at_av1(self, device): assert decoded_frame10.pts_seconds == ref_frame_info10.pts_seconds assert_frames_equal(decoded_frame10.data, ref_frame10.to(device=device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frame_played_at(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -610,7 +610,7 @@ def test_get_frame_played_at_h265(self): ref_frame6 = H265_VIDEO.get_frame_data_by_index(5) assert_frames_equal(ref_frame6, decoder.get_frame_played_at(0.5).data) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frame_played_at_fails(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -621,7 +621,7 @@ def test_get_frame_played_at_fails(self, device, seek_mode): with pytest.raises(IndexError, match="Invalid pts in seconds"): frame = decoder.get_frame_played_at(100.0) # noqa - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_played_at(self, device, seek_mode): @@ -660,7 +660,7 @@ def test_get_frames_played_at(self, device, seek_mode): frames.duration_seconds, expected_duration_seconds, atol=1e-4, rtol=0 ) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_played_at_fails(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -674,7 +674,7 @@ def test_get_frames_played_at_fails(self, device, seek_mode): with pytest.raises(RuntimeError, match="Expected a value of type"): decoder.get_frames_played_at(["bad"]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("stream_index", [0, 3, None]) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_in_range(self, stream_index, device, seek_mode): @@ -779,7 +779,7 @@ def test_get_frames_in_range(self, stream_index, device, seek_mode): empty_frames.duration_seconds, NASA_VIDEO.empty_duration_seconds ) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_in_range_slice_indices_syntax(self, device, seek_mode): decoder = VideoDecoder( @@ -831,7 +831,7 @@ def test_get_frames_in_range_slice_indices_syntax(self, device, seek_mode): ).to(device) assert_frames_equal(frames387_None.data, reference_frame387_389) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) @patch("torchcodec._core._metadata._get_stream_json_metadata") def test_get_frames_with_missing_num_frames_metadata( @@ -894,7 +894,7 @@ def test_get_frames_with_missing_num_frames_metadata( lambda decoder: decoder.get_frames_played_in_range(0, 1).data, ), ) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_dimension_order(self, dimension_order, frame_getter, device, seek_mode): decoder = VideoDecoder( @@ -922,7 +922,7 @@ def test_dimension_order_fails(self): VideoDecoder(NASA_VIDEO.path, dimension_order="NCDHW") @pytest.mark.parametrize("stream_index", [0, 3, None]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_by_pts_in_range(self, stream_index, device, seek_mode): decoder = VideoDecoder( @@ -1061,7 +1061,7 @@ def test_get_frames_by_pts_in_range(self, stream_index, device, seek_mode): ) assert_frames_equal(all_frames.data, decoder[:]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize("seek_mode", ("exact", "approximate")) def test_get_frames_by_pts_in_range_fails(self, device, seek_mode): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode) @@ -1075,7 +1075,7 @@ def test_get_frames_by_pts_in_range_fails(self, device, seek_mode): with pytest.raises(ValueError, match="Invalid stop seconds"): frame = decoder.get_frames_played_in_range(0, 23) # noqa - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_key_frame_indices(self, device): decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode="exact") key_frame_indices = decoder._get_key_frame_indices() @@ -1120,7 +1120,7 @@ def test_get_key_frame_indices(self, device): # TODO investigate why this fails internally. @pytest.mark.skipif(in_fbcode(), reason="Compile test fails internally.") - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_compile(self, device): decoder = VideoDecoder(NASA_VIDEO.path, device=device) diff --git a/test/test_ops.py b/test/test_ops.py index d86cb2437..d2f2fd3b1 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -42,8 +42,8 @@ ) from .utils import ( + all_supported_devices, assert_frames_equal, - cpu_and_cuda, get_ffmpeg_major_version, NASA_AUDIO, NASA_AUDIO_MP3, @@ -60,7 +60,7 @@ class TestVideoDecoderOps: - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_seek_and_next(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -77,7 +77,7 @@ def test_seek_and_next(self, device): ) assert_frames_equal(frame_time6, reference_frame_time6.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_seek_to_negative_pts(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -89,7 +89,7 @@ def test_seek_to_negative_pts(self, device): frame0, _, _ = get_next_frame(decoder) assert_frames_equal(frame0, reference_frame0.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frame_at_pts(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -113,7 +113,7 @@ def test_get_frame_at_pts(self, device): with pytest.raises(AssertionError): assert_frames_equal(next_frame, reference_frame6.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frame_at_index(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -131,7 +131,7 @@ def test_get_frame_at_index(self, device): reference_frame389 = NASA_VIDEO.get_frame_data_by_index(389) assert_frames_equal(frame389[0], reference_frame389.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frame_with_info_at_index(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -143,7 +143,7 @@ def test_get_frame_with_info_at_index(self, device): assert pts.item() == pytest.approx(6.006, rel=1e-3) assert duration.item() == pytest.approx(0.03337, rel=1e-3) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frames_at_indices(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -155,7 +155,7 @@ def test_get_frames_at_indices(self, device): assert_frames_equal(frames0and180[0], reference_frame0.to(device)) assert_frames_equal(frames0and180[1], reference_frame180.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frames_at_indices_unsorted_indices(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) _add_video_stream(decoder, device=device) @@ -182,7 +182,7 @@ def test_get_frames_at_indices_unsorted_indices(self, device): with pytest.raises(AssertionError): assert_frames_equal(frames[0], frames[-1]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frames_at_indices_negative_indices(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -196,7 +196,7 @@ def test_get_frames_at_indices_negative_indices(self, device): assert_frames_equal(frames389and387and1[1], reference_frame387.to(device)) assert_frames_equal(frames389and387and1[2], reference_frame1.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frames_at_indices_fail_on_invalid_negative_indices(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -208,7 +208,7 @@ def test_get_frames_at_indices_fail_on_invalid_negative_indices(self, device): decoder, frame_indices=[-10000, -3000] ) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frames_by_pts(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) _add_video_stream(decoder, device=device) @@ -236,7 +236,7 @@ def test_get_frames_by_pts(self, device): with pytest.raises(AssertionError): assert_frames_equal(frames[0], frames[-1]) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_pts_apis_against_index_ref(self, device): # Non-regression test for https://github.com/pytorch/torchcodec/pull/287 # Get all frames in the video, then query all frames with all time-based @@ -291,7 +291,7 @@ def test_pts_apis_against_index_ref(self, device): ) torch.testing.assert_close(pts_seconds, all_pts_seconds_ref, atol=0, rtol=0) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_get_frames_in_range(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -331,7 +331,7 @@ def test_get_frames_in_range(self, device): empty_frame, *_ = get_frames_in_range(decoder, start=5, stop=5) assert_frames_equal(empty_frame, NASA_VIDEO.empty_chw_tensor.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_throws_exception_at_eof(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -346,7 +346,7 @@ def test_throws_exception_at_eof(self, device): with pytest.raises(IndexError, match="no more frames"): get_frame_at_pts(decoder, seconds=1000.0) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_throws_exception_if_seek_too_far(self, device): decoder = create_from_file(str(NASA_VIDEO.path)) add_video_stream(decoder, device=device) @@ -355,7 +355,7 @@ def test_throws_exception_if_seek_too_far(self, device): with pytest.raises(IndexError, match="no more frames"): get_next_frame(decoder) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_compile_seek_and_next(self, device): # TODO_OPEN_ISSUE Scott (T180277797): Get this to work with the inductor stack. Right now # compilation fails because it can't handle tensors of size unknown at @@ -379,7 +379,7 @@ def get_frame1_and_frame_time6(decoder): assert_frames_equal(frame0, reference_frame0.to(device)) assert_frames_equal(frame_time6, reference_frame_time6.to(device)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) @pytest.mark.parametrize( "create_from", ("file", "tensor", "bytes", "file_like_rawio", "file_like_bufferedio"), @@ -509,7 +509,7 @@ def test_seek_mode_custom_frame_mappings_fails(self): get_ffmpeg_major_version() in (4, 5), reason="ffprobe isn't accurate on ffmpeg 4 and 5", ) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_seek_mode_custom_frame_mappings(self, device): stream_index = 3 # custom_frame_index seek mode requires a stream index decoder = create_from_file( @@ -1015,7 +1015,7 @@ def get_all_frames(asset, sample_rate=None, stop_seconds=None): torch.testing.assert_close(frames_downsampled_to_8000, frames_8000_native) @pytest.mark.parametrize("buffering", (0, 1024)) - @pytest.mark.parametrize("device", cpu_and_cuda()) + @pytest.mark.parametrize("device", all_supported_devices()) def test_file_like_decoding(self, buffering, device): # Test to ensure that seeks and reads are actually going through the # methods on the IO object. diff --git a/test/utils.py b/test/utils.py index c258ac440..588fdd6df 100644 --- a/test/utils.py +++ b/test/utils.py @@ -23,7 +23,7 @@ def needs_cuda(test_item): return pytest.mark.needs_cuda(test_item) -def cpu_and_cuda(): +def all_supported_devices(): return ("cpu", pytest.param("cuda", marks=pytest.mark.needs_cuda))