148 lines
4.8 KiB
Python
148 lines
4.8 KiB
Python
"""Tests for image_manager module."""
|
|
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from src.core.image_manager import (
|
|
ImageError,
|
|
create_sparse_image,
|
|
delete_image,
|
|
get_image_info,
|
|
resize_image,
|
|
)
|
|
|
|
|
|
class TestCreateSparseImage:
|
|
"""Tests for create_sparse_image function."""
|
|
|
|
def test_create_sparse_image(self) -> None:
|
|
"""Test creating a sparse image."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
|
|
create_sparse_image(path, size_mb=10)
|
|
|
|
assert path.exists()
|
|
# File should be 10MB in logical size
|
|
assert path.stat().st_size == 10 * 1024 * 1024
|
|
|
|
def test_create_sparse_image_is_sparse(self) -> None:
|
|
"""Test that created image is actually sparse (uses less disk space)."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
|
|
create_sparse_image(path, size_mb=100)
|
|
|
|
stat = path.stat()
|
|
# Actual disk usage should be much less than logical size
|
|
# st_blocks is in 512-byte units
|
|
actual_size = stat.st_blocks * 512
|
|
logical_size = stat.st_size
|
|
|
|
# Actual size should be less than 10% of logical size for a sparse file
|
|
# (exFAT metadata takes some space, so not 0)
|
|
assert actual_size < logical_size * 0.1
|
|
|
|
def test_create_sparse_image_already_exists(self) -> None:
|
|
"""Test that creating image fails if file exists."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
path.touch()
|
|
|
|
with pytest.raises(ImageError, match="already exists"):
|
|
create_sparse_image(path, size_mb=10)
|
|
|
|
def test_create_sparse_image_invalid_path(self) -> None:
|
|
"""Test that creating image fails for invalid path."""
|
|
path = Path("/nonexistent/directory/test.vault")
|
|
|
|
with pytest.raises(ImageError):
|
|
create_sparse_image(path, size_mb=10)
|
|
|
|
|
|
class TestResizeImage:
|
|
"""Tests for resize_image function."""
|
|
|
|
def test_resize_image(self) -> None:
|
|
"""Test resizing an image."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
create_sparse_image(path, size_mb=10)
|
|
|
|
resize_image(path, new_size_mb=20)
|
|
|
|
assert path.stat().st_size == 20 * 1024 * 1024
|
|
|
|
def test_resize_image_smaller_fails(self) -> None:
|
|
"""Test that shrinking an image fails."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
create_sparse_image(path, size_mb=20)
|
|
|
|
with pytest.raises(ImageError, match="must be larger"):
|
|
resize_image(path, new_size_mb=10)
|
|
|
|
def test_resize_image_same_size_fails(self) -> None:
|
|
"""Test that resizing to same size fails."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
create_sparse_image(path, size_mb=10)
|
|
|
|
with pytest.raises(ImageError, match="must be larger"):
|
|
resize_image(path, new_size_mb=10)
|
|
|
|
def test_resize_nonexistent_image(self) -> None:
|
|
"""Test that resizing nonexistent image fails."""
|
|
path = Path("/nonexistent/test.vault")
|
|
|
|
with pytest.raises(ImageError, match="not found"):
|
|
resize_image(path, new_size_mb=20)
|
|
|
|
|
|
class TestGetImageInfo:
|
|
"""Tests for get_image_info function."""
|
|
|
|
def test_get_image_info(self) -> None:
|
|
"""Test getting image info."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
create_sparse_image(path, size_mb=50)
|
|
|
|
info = get_image_info(path)
|
|
|
|
assert info["path"] == str(path)
|
|
assert info["size_mb"] == 50
|
|
assert info["actual_size_mb"] < 50 # Sparse file
|
|
assert 0 < info["sparse_ratio"] < 1
|
|
|
|
def test_get_image_info_nonexistent(self) -> None:
|
|
"""Test getting info for nonexistent image."""
|
|
path = Path("/nonexistent/test.vault")
|
|
|
|
with pytest.raises(ImageError, match="not found"):
|
|
get_image_info(path)
|
|
|
|
|
|
class TestDeleteImage:
|
|
"""Tests for delete_image function."""
|
|
|
|
def test_delete_image(self) -> None:
|
|
"""Test deleting an image."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
path = Path(tmpdir) / "test.vault"
|
|
create_sparse_image(path, size_mb=10)
|
|
assert path.exists()
|
|
|
|
delete_image(path)
|
|
|
|
assert not path.exists()
|
|
|
|
def test_delete_nonexistent_image(self) -> None:
|
|
"""Test deleting nonexistent image fails."""
|
|
path = Path("/nonexistent/test.vault")
|
|
|
|
with pytest.raises(ImageError, match="not found"):
|
|
delete_image(path)
|