|
11 | 11 | Run with: pytest -m "slow" to run only the slow integration tests |
12 | 12 | """ |
13 | 13 |
|
| 14 | +import subprocess |
14 | 15 | import tempfile |
15 | 16 | import zipfile |
16 | 17 | from pathlib import Path |
|
19 | 20 | import pytest |
20 | 21 |
|
21 | 22 | from ffmpeg_normalize import FFmpegNormalize |
| 23 | +from ffmpeg_normalize._cmd_utils import validate_input_file |
22 | 24 | from ffmpeg_normalize._streams import LoudnessStatisticsWithMetadata |
23 | 25 |
|
24 | 26 |
|
@@ -640,3 +642,88 @@ def test_batch_mode_preserves_relative_loudness(self, temp_output_dir): |
640 | 642 | f"Normal file should remain louder than quiet file in batch mode. " |
641 | 643 | f"Got normal={loudness_values[1]:.2f}, quiet={loudness_values[2]:.2f}" |
642 | 644 | ) |
| 645 | + |
| 646 | + |
| 647 | +class TestFileValidationAPI: |
| 648 | + """API-level tests for input file validation.""" |
| 649 | + |
| 650 | + def test_validate_input_file_exists(self): |
| 651 | + """Test validation of existing audio file.""" |
| 652 | + test_file = Path(__file__).parent / "test.mp4" |
| 653 | + is_valid, error_msg = validate_input_file(str(test_file)) |
| 654 | + assert is_valid is True |
| 655 | + assert error_msg is None |
| 656 | + |
| 657 | + def test_validate_input_file_not_exists(self): |
| 658 | + """Test validation fails for non-existent file.""" |
| 659 | + is_valid, error_msg = validate_input_file("nonexistent_file.mp4") |
| 660 | + assert is_valid is False |
| 661 | + assert error_msg is not None |
| 662 | + assert "does not exist" in error_msg |
| 663 | + |
| 664 | + def test_validate_input_file_directory(self, tmp_path): |
| 665 | + """Test validation fails for directories.""" |
| 666 | + is_valid, error_msg = validate_input_file(str(tmp_path)) |
| 667 | + assert is_valid is False |
| 668 | + assert error_msg is not None |
| 669 | + assert "not a file" in error_msg |
| 670 | + |
| 671 | + def test_validate_input_file_no_audio(self, tmp_path): |
| 672 | + """Test validation fails for files without audio streams.""" |
| 673 | + # Create a video-only file using ffmpeg |
| 674 | + video_only = tmp_path / "video_only.mp4" |
| 675 | + cmd = [ |
| 676 | + "ffmpeg", |
| 677 | + "-y", |
| 678 | + "-f", |
| 679 | + "lavfi", |
| 680 | + "-i", |
| 681 | + "color=c=blue:s=320x240:d=1", |
| 682 | + "-an", # no audio |
| 683 | + "-c:v", |
| 684 | + "libx264", |
| 685 | + str(video_only), |
| 686 | + ] |
| 687 | + subprocess.run(cmd, check=True, capture_output=True) |
| 688 | + |
| 689 | + is_valid, error_msg = validate_input_file(str(video_only)) |
| 690 | + assert is_valid is False |
| 691 | + assert error_msg is not None |
| 692 | + assert "audio" in error_msg.lower() |
| 693 | + |
| 694 | + def test_validate_input_files_batch(self): |
| 695 | + """Test batch validation with multiple files.""" |
| 696 | + test_dir = Path(__file__).parent |
| 697 | + valid_files = [ |
| 698 | + str(test_dir / "test.mp4"), |
| 699 | + str(test_dir / "test.m4a"), |
| 700 | + ] |
| 701 | + |
| 702 | + errors = FFmpegNormalize.validate_input_files(valid_files) |
| 703 | + assert len(errors) == 0 |
| 704 | + |
| 705 | + def test_validate_input_files_batch_mixed(self): |
| 706 | + """Test batch validation with mix of valid and invalid files.""" |
| 707 | + test_dir = Path(__file__).parent |
| 708 | + files = [ |
| 709 | + str(test_dir / "test.mp4"), |
| 710 | + "nonexistent1.mp4", |
| 711 | + str(test_dir / "test.m4a"), |
| 712 | + "nonexistent2.mp4", |
| 713 | + ] |
| 714 | + |
| 715 | + errors = FFmpegNormalize.validate_input_files(files) |
| 716 | + assert len(errors) == 2 |
| 717 | + assert any("nonexistent1.mp4" in e for e in errors) |
| 718 | + assert any("nonexistent2.mp4" in e for e in errors) |
| 719 | + |
| 720 | + def test_validate_input_files_all_invalid(self): |
| 721 | + """Test batch validation with all invalid files.""" |
| 722 | + files = [ |
| 723 | + "nonexistent1.mp4", |
| 724 | + "nonexistent2.mp4", |
| 725 | + "nonexistent3.mp4", |
| 726 | + ] |
| 727 | + |
| 728 | + errors = FFmpegNormalize.validate_input_files(files) |
| 729 | + assert len(errors) == 3 |
0 commit comments