Add compression level validation to CLI
Introduced a `validate_compression_level` function to ensure compression levels are within the valid range (1-22). Updated CLI argument parsing to use this validation and added tests to verify valid, invalid, and non-numeric compression levels.
This commit is contained in:
1 parent
2a3ccefb21
commit
459b695af0
2 files changed
+104
-3
No files matched your search
+33
-3
@@ -50,6 +50,31 @@ def format_size(size: int) -> str:
|
||||
return f"{size_float:6.1f} PB"
|
||||
|
||||
|
||||
def validate_compression_level(value: str) -> int:
|
||||
"""Validate and return compression level.
|
||||
|
||||
Args:
|
||||
value: String value from command line
|
||||
|
||||
Returns:
|
||||
int: Valid compression level (1-22)
|
||||
|
||||
Raises:
|
||||
argparse.ArgumentTypeError: If value is not a valid compression level
|
||||
"""
|
||||
try:
|
||||
level = int(value)
|
||||
if not 1 <= level <= 22:
|
||||
raise argparse.ArgumentTypeError(
|
||||
f"Invalid compression level: {level}. Must be between 1 and 22."
|
||||
)
|
||||
return level
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError(
|
||||
f"Invalid compression level: '{value}'. Must be an integer between 1 and 22."
|
||||
)
|
||||
|
||||
|
||||
def cmd_add(args) -> int:
|
||||
"""Command handler for creating/adding to archives.
|
||||
|
||||
@@ -511,9 +536,8 @@ Documentation:
|
||||
"-l",
|
||||
"--level",
|
||||
dest="compression_level",
|
||||
type=int,
|
||||
type=validate_compression_level,
|
||||
default=3,
|
||||
choices=range(1, 23),
|
||||
metavar="LEVEL",
|
||||
help="Compression level (1-22, default: 3)",
|
||||
)
|
||||
@@ -628,6 +652,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
int: Exit code for the program
|
||||
- 0: Success
|
||||
- 1: No command specified (help displayed)
|
||||
- 2: Argument parsing error (invalid arguments)
|
||||
- Other codes: Specific to individual command handlers
|
||||
|
||||
Note:
|
||||
@@ -642,7 +667,12 @@ def main(argv: list[str] | None = None) -> int:
|
||||
print()
|
||||
|
||||
parser = create_parser()
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
try:
|
||||
args = parser.parse_args(argv)
|
||||
except SystemExit as e:
|
||||
# Handle argparse errors (invalid arguments, help, etc.)
|
||||
return e.code if e.code is not None else 1
|
||||
|
||||
if not hasattr(args, "func"):
|
||||
parser.print_help()
|
||||
|
||||
@@ -1033,3 +1033,74 @@ class TestCLIBoundaryConditions:
|
||||
except OSError:
|
||||
# Skip if filesystem doesn't support such long names
|
||||
pytest.skip("Filesystem doesn't support long filenames")
|
||||
|
||||
|
||||
class TestCompressionLevelValidation:
|
||||
"""Test compression level validation in CLI."""
|
||||
|
||||
def test_valid_compression_levels(self, temp_dir):
|
||||
"""Test that valid compression levels (1-22) work correctly."""
|
||||
test_file = temp_dir / "test.txt"
|
||||
test_file.write_text("Test content")
|
||||
|
||||
# Test boundary values and some middle values
|
||||
valid_levels = [1, 2, 10, 22]
|
||||
|
||||
for level in valid_levels:
|
||||
archive_path = temp_dir / f"test_level_{level}.tzst"
|
||||
result = main(["a", str(archive_path), str(test_file), "-l", str(level)])
|
||||
assert result == 0, f"Compression level {level} should be valid"
|
||||
|
||||
def test_invalid_compression_levels(self, temp_dir):
|
||||
"""Test that invalid compression levels return proper error codes."""
|
||||
test_file = temp_dir / "test.txt"
|
||||
test_file.write_text("Test content")
|
||||
archive_path = temp_dir / "test.tzst"
|
||||
|
||||
# Test invalid levels that should return exit code 2 (argparse error)
|
||||
invalid_levels = [0, 23, 50, 100, -1, -10]
|
||||
|
||||
for level in invalid_levels:
|
||||
result = main(["a", str(archive_path), str(test_file), "-l", str(level)])
|
||||
assert result == 2, (
|
||||
f"Invalid compression level {level} should return exit code 2"
|
||||
)
|
||||
|
||||
def test_non_numeric_compression_levels(self, temp_dir):
|
||||
"""Test that non-numeric compression levels return proper error codes."""
|
||||
test_file = temp_dir / "test.txt"
|
||||
test_file.write_text("Test content")
|
||||
archive_path = temp_dir / "test.tzst"
|
||||
|
||||
# Test non-numeric values
|
||||
invalid_values = ["abc", "1.5", "high", "max", ""]
|
||||
|
||||
for value in invalid_values:
|
||||
result = main(["a", str(archive_path), str(test_file), "-l", value])
|
||||
assert result == 2, (
|
||||
f"Non-numeric compression level '{value}' should return exit code 2"
|
||||
)
|
||||
|
||||
def test_compression_level_clamping(self, temp_dir):
|
||||
"""Test compression level validation with extreme values."""
|
||||
test_file = temp_dir / "test.txt"
|
||||
test_file.write_text("Test content")
|
||||
archive_path = temp_dir / "test.tzst"
|
||||
|
||||
# Test level 50 - should return argparse error code 2
|
||||
result = main(["a", str(archive_path), str(test_file), "-l", "50"])
|
||||
assert result == 2, "Compression level 50 should return exit code 2"
|
||||
|
||||
def test_extreme_compression_levels(self, temp_dir):
|
||||
"""Test extreme compression level values."""
|
||||
test_file = temp_dir / "test.txt"
|
||||
test_file.write_text("Test content")
|
||||
archive_path = temp_dir / "test.tzst"
|
||||
|
||||
# Test level 50 - should return argparse error code 2
|
||||
result = main(["a", str(archive_path), str(test_file), "-l", "50"])
|
||||
assert result == 2, "Extreme compression level 50 should return exit code 2"
|
||||
|
||||
# Test level 0 - should return argparse error code 2
|
||||
result = main(["a", str(archive_path), str(test_file), "-l", "0"])
|
||||
assert result == 2, "Extreme compression level 0 should return exit code 2"
|
||||
Reference in new issue
Block a user