From 3d274eaa87cfc1357e735d4e330b884c4a40e16c Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 29 Jul 2026 18:58:51 +0800 Subject: [PATCH 1/2] =?UTF-8?q?test(wave192):=20media=5Fvalidation=20?= =?UTF-8?q?=E5=AA=92=E4=BD=93=E6=A0=A1=E9=AA=8C=20+56=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/domain/test_media_validation.py | 291 +++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100755 tests/unit/domain/test_media_validation.py diff --git a/tests/unit/domain/test_media_validation.py b/tests/unit/domain/test_media_validation.py new file mode 100755 index 000000000..5683605c5 --- /dev/null +++ b/tests/unit/domain/test_media_validation.py @@ -0,0 +1,291 @@ +"""media_validation 媒体文件校验单测.""" + +import pytest + +from domain.media_validation import ( + MIN_AUDIO_FILE_SIZE, + MIN_IMAGE_FILE_SIZE, + MIN_VIDEO_FILE_SIZE, + SUPPORTED_VIDEO_CODECS, + is_valid_media, + safe_parse_fps, +) + +# ── 常量测试 ───────────────────────────────────────────────────────────────── + + +class TestConstants: + """模块常量""" + + def test_min_sizes(self): + assert MIN_VIDEO_FILE_SIZE == 1024 + assert MIN_AUDIO_FILE_SIZE == 100 + assert MIN_IMAGE_FILE_SIZE == 100 + + def test_supported_codecs_is_frozenset(self): + assert isinstance(SUPPORTED_VIDEO_CODECS, frozenset) + + def test_supported_codecs_includes_common(self): + assert "h264" in SUPPORTED_VIDEO_CODECS + assert "hevc" in SUPPORTED_VIDEO_CODECS + assert "vp9" in SUPPORTED_VIDEO_CODECS + assert "av1" in SUPPORTED_VIDEO_CODECS + assert "mpeg4" in SUPPORTED_VIDEO_CODECS + assert "prores" in SUPPORTED_VIDEO_CODECS + + def test_supported_codecs_count(self): + assert len(SUPPORTED_VIDEO_CODECS) >= 20 + + +# ── safe_parse_fps ─────────────────────────────────────────────────────────── + + +class TestSafeParseFps: + """safe_parse_fps 函数""" + + def test_simple_decimal(self): + assert safe_parse_fps("30.0") == 30.0 + + def test_integer_string(self): + assert safe_parse_fps("24") == 24.0 + + def test_fraction_format(self): + assert abs(safe_parse_fps("30000/1001") - 29.97) < 0.01 + + def test_simple_fraction(self): + assert safe_parse_fps("30/1") == 30.0 + + def test_24fps_fraction(self): + assert safe_parse_fps("24/1") == 24.0 + + def test_60fps_fraction(self): + assert safe_parse_fps("60000/1001") == pytest.approx(59.94, abs=0.01) + + def test_zero_denominator_returns_zero(self): + assert safe_parse_fps("30/0") == 0.0 + + def test_empty_string_returns_zero(self): + assert safe_parse_fps("") == 0.0 + + def test_invalid_string_returns_zero(self): + assert safe_parse_fps("invalid") == 0.0 + + def test_none_numerator_fraction(self): + assert safe_parse_fps("abc/1001") == 0.0 + + def test_negative_fps(self): + assert safe_parse_fps("-30") == -30.0 + + def test_very_high_fps(self): + assert safe_parse_fps("240/1") == 240.0 + + def test_multiple_slashes(self): + # 只按第一个 / 分割 + # "30/1/2" → num="30", den="1/2" → float("1/2") 抛异常 → 返回 0 + assert safe_parse_fps("30/1/2") == 0.0 + + def test_float_fraction(self): + result = safe_parse_fps("29.97/1") + assert result == pytest.approx(29.97) + + def test_zero_fps(self): + assert safe_parse_fps("0") == 0.0 + + def test_zero_numerator(self): + assert safe_parse_fps("0/1000") == 0.0 + + +# ── is_valid_media - video ─────────────────────────────────────────────────── + + +class TestIsValidMediaVideo: + """is_valid_media 视频校验""" + + def test_valid_video(self): + metadata = { + "size_bytes": 1024 * 1024, # 1MB + "duration": 10.0, + "codec": "h264", + "width": 1920, + "height": 1080, + } + assert is_valid_media(metadata, "video") is True + + def test_small_file_invalid(self): + metadata = {"size_bytes": 100, "duration": 10.0} + assert is_valid_media(metadata, "video") is False + + def test_exact_min_size_valid(self): + metadata = {"size_bytes": MIN_VIDEO_FILE_SIZE, "duration": 1.0} + assert is_valid_media(metadata, "video") is True + + def test_zero_duration_invalid(self): + metadata = {"size_bytes": 1024 * 1024, "duration": 0} + assert is_valid_media(metadata, "video") is False + + def test_negative_duration_invalid(self): + metadata = {"size_bytes": 1024 * 1024, "duration": -1.0} + assert is_valid_media(metadata, "video") is False + + def test_unsupported_codec_still_valid(self): + # 非白名单编码仍允许通过(不做严格拦截) + metadata = { + "size_bytes": 1024 * 1024, + "duration": 10.0, + "codec": "unknown_codec_xyz", + } + assert is_valid_media(metadata, "video") is True + + def test_empty_codec_valid(self): + metadata = {"size_bytes": 1024 * 1024, "duration": 10.0, "codec": ""} + assert is_valid_media(metadata, "video") is True + + def test_no_codec_valid(self): + metadata = {"size_bytes": 1024 * 1024, "duration": 10.0} + assert is_valid_media(metadata, "video") is True + + def test_hevc_codec_valid(self): + metadata = { + "size_bytes": 1024 * 1024, + "duration": 10.0, + "codec": "hevc", + } + assert is_valid_media(metadata, "video") is True + + def test_codec_case_insensitive(self): + metadata = { + "size_bytes": 1024 * 1024, + "duration": 10.0, + "codec": "H264", + } + assert is_valid_media(metadata, "video") is True + + def test_missing_size_invalid(self): + metadata = {"duration": 10.0} + assert is_valid_media(metadata, "video") is False + + def test_missing_duration_invalid(self): + metadata = {"size_bytes": 1024 * 1024} + assert is_valid_media(metadata, "video") is False + + def test_empty_metadata_invalid(self): + assert is_valid_media({}, "video") is False + + +# ── is_valid_media - audio ─────────────────────────────────────────────────── + + +class TestIsValidMediaAudio: + """is_valid_media 音频校验""" + + def test_valid_audio(self): + metadata = {"size_bytes": 1024, "duration": 30.0, "codec": "aac"} + assert is_valid_media(metadata, "audio") is True + + def test_small_audio_invalid(self): + metadata = {"size_bytes": 50, "duration": 30.0} + assert is_valid_media(metadata, "audio") is False + + def test_exact_min_size_valid(self): + metadata = {"size_bytes": MIN_AUDIO_FILE_SIZE, "duration": 1.0} + assert is_valid_media(metadata, "audio") is True + + def test_zero_duration_invalid(self): + metadata = {"size_bytes": 1024, "duration": 0} + assert is_valid_media(metadata, "audio") is False + + def test_negative_duration_invalid(self): + metadata = {"size_bytes": 1024, "duration": -5.0} + assert is_valid_media(metadata, "audio") is False + + def test_empty_metadata_invalid(self): + assert is_valid_media({}, "audio") is False + + def test_very_short_audio_valid(self): + metadata = {"size_bytes": 200, "duration": 0.5} + assert is_valid_media(metadata, "audio") is True + + +# ── is_valid_media - image ─────────────────────────────────────────────────── + + +class TestIsValidMediaImage: + """is_valid_media 图片校验""" + + def test_valid_image(self): + metadata = {"size_bytes": 1024, "width": 1920, "height": 1080} + assert is_valid_media(metadata, "image") is True + + def test_small_image_invalid(self): + metadata = {"size_bytes": 50, "width": 1920, "height": 1080} + assert is_valid_media(metadata, "image") is False + + def test_exact_min_size_valid(self): + metadata = { + "size_bytes": MIN_IMAGE_FILE_SIZE, + "width": 100, + "height": 100, + } + assert is_valid_media(metadata, "image") is True + + def test_zero_width_invalid(self): + metadata = {"size_bytes": 1024, "width": 0, "height": 1080} + assert is_valid_media(metadata, "image") is False + + def test_zero_height_invalid(self): + metadata = {"size_bytes": 1024, "width": 1920, "height": 0} + assert is_valid_media(metadata, "image") is False + + def test_negative_width_invalid(self): + metadata = {"size_bytes": 1024, "width": -1, "height": 1080} + assert is_valid_media(metadata, "image") is False + + def test_small_image_valid(self): + metadata = {"size_bytes": 200, "width": 10, "height": 10} + assert is_valid_media(metadata, "image") is True + + def test_missing_width_invalid(self): + metadata = {"size_bytes": 1024, "height": 1080} + assert is_valid_media(metadata, "image") is False + + def test_missing_height_invalid(self): + metadata = {"size_bytes": 1024, "width": 1920} + assert is_valid_media(metadata, "image") is False + + def test_empty_metadata_invalid(self): + assert is_valid_media({}, "image") is False + + +# ── is_valid_media - edge cases ───────────────────────────────────────────── + + +class TestIsValidMediaEdgeCases: + """is_valid_media 边界情况""" + + def test_invalid_media_type(self): + metadata = {"size_bytes": 1024, "duration": 10.0} + assert is_valid_media(metadata, "document") is False + + def test_empty_media_type(self): + metadata = {"size_bytes": 1024} + assert is_valid_media(metadata, "") is False + + def test_string_size_converted(self): + metadata = {"size_bytes": "2048", "duration": "5.0"} + assert is_valid_media(metadata, "video") is True + + def test_video_size_as_string(self): + metadata = {"size_bytes": "1000000", "duration": "30"} + assert is_valid_media(metadata, "video") is True + + def test_invalid_size_string_raises(self): + # int("abc") 会抛 ValueError + metadata = {"size_bytes": "abc", "duration": 10.0} + with pytest.raises(ValueError): + is_valid_media(metadata, "video") + + def test_none_size_raises(self): + # int(None) 会抛 TypeError + metadata = {"size_bytes": None, "duration": 10.0} + with pytest.raises(TypeError): + is_valid_media(metadata, "video") -- 2.54.0 From bc324baf3e3703b4b0c3188038dcf552c18c0ca2 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Wed, 29 Jul 2026 11:08:40 +0000 Subject: [PATCH 2/2] style: auto-format with black + isort + prettier [skip ci-format-check] --- tests/unit/domain/test_media_validation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/domain/test_media_validation.py b/tests/unit/domain/test_media_validation.py index 5683605c5..2aa1dca44 100755 --- a/tests/unit/domain/test_media_validation.py +++ b/tests/unit/domain/test_media_validation.py @@ -1,7 +1,6 @@ """media_validation 媒体文件校验单测.""" import pytest - from domain.media_validation import ( MIN_AUDIO_FILE_SIZE, MIN_IMAGE_FILE_SIZE, -- 2.54.0