257 lines
9.9 KiB
Python
257 lines
9.9 KiB
Python
"""Tests for DWG converter module."""
|
|
|
|
import subprocess
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from pdf2imos.output.dwg_converter import (
|
|
convert_dxf_to_dwg,
|
|
is_oda_converter_available,
|
|
)
|
|
|
|
|
|
class TestIsOdaConverterAvailable:
|
|
"""Tests for is_oda_converter_available function."""
|
|
|
|
def test_returns_bool(self):
|
|
"""Test that function returns a boolean."""
|
|
result = is_oda_converter_available()
|
|
assert isinstance(result, bool)
|
|
|
|
@patch("pdf2imos.output.dwg_converter.shutil.which")
|
|
def test_returns_true_when_found(self, mock_which):
|
|
"""Test returns True when ODAFileConverter found in PATH."""
|
|
mock_which.return_value = "/usr/bin/ODAFileConverter"
|
|
assert is_oda_converter_available() is True
|
|
mock_which.assert_called_once_with("ODAFileConverter")
|
|
|
|
@patch("pdf2imos.output.dwg_converter.shutil.which")
|
|
def test_returns_false_when_not_found(self, mock_which):
|
|
"""Test returns False when ODAFileConverter not in PATH."""
|
|
mock_which.return_value = None
|
|
assert is_oda_converter_available() is False
|
|
mock_which.assert_called_once_with("ODAFileConverter")
|
|
|
|
|
|
class TestConvertDxfToDwg:
|
|
"""Tests for convert_dxf_to_dwg function."""
|
|
|
|
def test_returns_none_when_converter_not_available(self):
|
|
"""Test returns None when ODAFileConverter not available."""
|
|
with patch(
|
|
"pdf2imos.output.dwg_converter.is_oda_converter_available",
|
|
return_value=False,
|
|
):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
result = convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
assert result is None
|
|
assert not dwg_path.exists()
|
|
|
|
@patch("pdf2imos.output.dwg_converter.subprocess.run")
|
|
@patch("pdf2imos.output.dwg_converter.is_oda_converter_available")
|
|
def test_constructs_correct_subprocess_command(
|
|
self, mock_available, mock_run
|
|
):
|
|
"""Test that correct subprocess command is constructed."""
|
|
mock_available.return_value = True
|
|
mock_run.return_value = MagicMock(returncode=0)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "output" / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
with patch(
|
|
"pdf2imos.output.dwg_converter.shutil.copy2"
|
|
) as mock_copy:
|
|
# Mock copy2 to create the expected output file
|
|
def copy_side_effect(src, dst):
|
|
if str(src).endswith(".dxf"):
|
|
Path(dst).write_text("dummy dxf")
|
|
elif str(src).endswith(".dwg"):
|
|
Path(dst).write_text("dummy dwg")
|
|
|
|
mock_copy.side_effect = copy_side_effect
|
|
|
|
# Create a mock temp directory structure
|
|
with patch("tempfile.TemporaryDirectory") as mock_temp:
|
|
temp_input = Path(tmpdir) / "temp_input"
|
|
temp_output = Path(tmpdir) / "temp_output"
|
|
temp_input.mkdir()
|
|
temp_output.mkdir()
|
|
|
|
# Create the expected output file
|
|
(temp_output / "test.dwg").write_text("dummy dwg")
|
|
|
|
mock_temp.return_value.__enter__.side_effect = [
|
|
str(temp_input),
|
|
str(temp_output),
|
|
]
|
|
|
|
convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
# Verify subprocess.run was called with correct command
|
|
assert mock_run.called
|
|
call_args = mock_run.call_args
|
|
cmd = call_args[0][0]
|
|
assert cmd[0] == "ODAFileConverter"
|
|
assert cmd[3] == "ACAD2018"
|
|
assert cmd[4] == "DWG"
|
|
assert cmd[5] == "0"
|
|
assert cmd[6] == "1"
|
|
|
|
@patch("pdf2imos.output.dwg_converter.subprocess.run")
|
|
@patch("pdf2imos.output.dwg_converter.is_oda_converter_available")
|
|
def test_returns_none_on_subprocess_failure(
|
|
self, mock_available, mock_run
|
|
):
|
|
"""Test returns None when subprocess returns non-zero exit code."""
|
|
mock_available.return_value = True
|
|
mock_run.return_value = MagicMock(
|
|
returncode=1, stderr="Conversion failed"
|
|
)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
result = convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
assert result is None
|
|
|
|
@patch("pdf2imos.output.dwg_converter.subprocess.run")
|
|
@patch("pdf2imos.output.dwg_converter.is_oda_converter_available")
|
|
def test_returns_none_on_timeout(self, mock_available, mock_run):
|
|
"""Test returns None when subprocess times out."""
|
|
mock_available.return_value = True
|
|
mock_run.side_effect = subprocess.TimeoutExpired("cmd", 30)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
result = convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
assert result is None
|
|
|
|
@patch("pdf2imos.output.dwg_converter.subprocess.run")
|
|
@patch("pdf2imos.output.dwg_converter.is_oda_converter_available")
|
|
def test_returns_none_when_output_not_created(
|
|
self, mock_available, mock_run
|
|
):
|
|
"""Test returns None if output DWG file not created by converter."""
|
|
mock_available.return_value = True
|
|
mock_run.return_value = MagicMock(returncode=0)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
with patch("tempfile.TemporaryDirectory") as mock_temp:
|
|
temp_input = Path(tmpdir) / "temp_input"
|
|
temp_output = Path(tmpdir) / "temp_output"
|
|
temp_input.mkdir()
|
|
temp_output.mkdir()
|
|
|
|
# Don't create the expected output file
|
|
mock_temp.return_value.__enter__.side_effect = [
|
|
str(temp_input),
|
|
str(temp_output),
|
|
]
|
|
|
|
with patch(
|
|
"pdf2imos.output.dwg_converter.shutil.copy2"
|
|
):
|
|
result = convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
assert result is None
|
|
|
|
@patch("pdf2imos.output.dwg_converter.subprocess.run")
|
|
@patch("pdf2imos.output.dwg_converter.is_oda_converter_available")
|
|
def test_creates_output_directory(self, mock_available, mock_run):
|
|
"""Test that output directory is created if it doesn't exist."""
|
|
mock_available.return_value = True
|
|
mock_run.return_value = MagicMock(returncode=0)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "nested" / "output" / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
with patch("tempfile.TemporaryDirectory") as mock_temp:
|
|
temp_input = Path(tmpdir) / "temp_input"
|
|
temp_output = Path(tmpdir) / "temp_output"
|
|
temp_input.mkdir()
|
|
temp_output.mkdir()
|
|
|
|
(temp_output / "test.dwg").write_text("dummy dwg")
|
|
|
|
mock_temp.return_value.__enter__.side_effect = [
|
|
str(temp_input),
|
|
str(temp_output),
|
|
]
|
|
|
|
with patch(
|
|
"pdf2imos.output.dwg_converter.shutil.copy2"
|
|
) as mock_copy:
|
|
|
|
def copy_side_effect(src, dst):
|
|
Path(dst).parent.mkdir(parents=True, exist_ok=True)
|
|
Path(dst).write_text("dummy")
|
|
|
|
mock_copy.side_effect = copy_side_effect
|
|
|
|
convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
# Verify parent directory was created
|
|
assert dwg_path.parent.exists()
|
|
|
|
@patch("pdf2imos.output.dwg_converter.subprocess.run")
|
|
@patch("pdf2imos.output.dwg_converter.is_oda_converter_available")
|
|
def test_returns_path_on_success(self, mock_available, mock_run):
|
|
"""Test returns Path object on successful conversion."""
|
|
mock_available.return_value = True
|
|
mock_run.return_value = MagicMock(returncode=0)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
dxf_path = Path(tmpdir) / "test.dxf"
|
|
dwg_path = Path(tmpdir) / "test.dwg"
|
|
dxf_path.write_text("dummy dxf content")
|
|
|
|
with patch("tempfile.TemporaryDirectory") as mock_temp:
|
|
temp_input = Path(tmpdir) / "temp_input"
|
|
temp_output = Path(tmpdir) / "temp_output"
|
|
temp_input.mkdir()
|
|
temp_output.mkdir()
|
|
|
|
(temp_output / "test.dwg").write_text("dummy dwg")
|
|
|
|
mock_temp.return_value.__enter__.side_effect = [
|
|
str(temp_input),
|
|
str(temp_output),
|
|
]
|
|
|
|
with patch(
|
|
"pdf2imos.output.dwg_converter.shutil.copy2"
|
|
) as mock_copy:
|
|
|
|
def copy_side_effect(src, dst):
|
|
Path(dst).parent.mkdir(parents=True, exist_ok=True)
|
|
Path(dst).write_text("dummy")
|
|
|
|
mock_copy.side_effect = copy_side_effect
|
|
|
|
result = convert_dxf_to_dwg(dxf_path, dwg_path)
|
|
|
|
assert result == dwg_path
|
|
assert isinstance(result, Path)
|