From 6e55e43fef09a2df696ab0a4250e396b9c7d9f0b Mon Sep 17 00:00:00 2001 From: Alex Pyrgiotis Date: Tue, 8 Oct 2024 18:47:50 +0300 Subject: [PATCH] Make Dummy isolation provider more realistic Make the Dummy isolation provider follow the rest of the isolation providers and perform the second part of the conversion on the host. The first part of the conversion is just a dummy script that reads a file from stdin and prints pixels to stdout. --- dangerzone/isolation_provider/dummy.py | 67 ++++++++------------------ tests/isolation_provider/test_dummy.py | 35 ++------------ 2 files changed, 22 insertions(+), 80 deletions(-) diff --git a/dangerzone/isolation_provider/dummy.py b/dangerzone/isolation_provider/dummy.py index 80dd17f..9ebc345 100644 --- a/dangerzone/isolation_provider/dummy.py +++ b/dangerzone/isolation_provider/dummy.py @@ -1,18 +1,25 @@ import logging -import os -import shutil import subprocess import sys -import time -from typing import Callable, Optional +from ..conversion.common import DangerzoneConverter from ..document import Document -from ..util import get_resource_path from .base import IsolationProvider, terminate_process_group log = logging.getLogger(__name__) +def dummy_script() -> None: + sys.stdin.buffer.read() + pages = 2 + width = height = 9 + DangerzoneConverter._write_int(pages) + for page in range(pages): + DangerzoneConverter._write_int(width) + DangerzoneConverter._write_int(height) + DangerzoneConverter._write_bytes(width * height * 3 * b"A") + + class Dummy(IsolationProvider): """Dummy Isolation Provider (FOR TESTING ONLY) @@ -32,51 +39,15 @@ class Dummy(IsolationProvider): def install(self) -> bool: return True - def convert( - self, - document: Document, - ocr_lang: Optional[str], - progress_callback: Optional[Callable] = None, - ) -> None: - self.progress_callback = None - log.debug("Dummy converter started:") - log.debug( - f" - document: {os.path.basename(document.input_filename)} ({document.id})" - ) - log.debug(f" - ocr : {ocr_lang}") - log.debug("\n(simulating conversion)") - success = True - progress = [ - [False, "Converting to PDF using GraphicsMagick", 0.0], - [False, "Separating document into pages", 3.0], - [False, "Converting page 1/1 to pixels", 5.0], - [False, "Converted document to pixels", 50.0], - [False, "Converting page 1/1 from pixels to PDF", 50.0], - [False, "Merging 1 pages into a single PDF", 95.0], - [False, "Compressing PDF", 97.0], - [False, "Safe PDF created", 100.0], - ] - for error, text, percentage in progress: - self.print_progress(document, error, text, percentage) # type: ignore [arg-type] - if error: - success = False - if success: - shutil.copy( - get_resource_path("dummy_document.pdf"), document.output_filename - ) - document.mark_as_safe() - if document.archive_after_conversion: - document.archive() - - def pixels_to_pdf( - self, document: Document, tempdir: str, ocr_lang: Optional[str] - ) -> None: - pass - def start_doc_to_pixels_proc(self, document: Document) -> subprocess.Popen: - dummy_cmd = ["python3", "-c", "print('The cake is a lie')"] + cmd = [ + sys.executable, + "-c", + "from dangerzone.isolation_provider.dummy import dummy_script;" + " dummy_script()", + ] return subprocess.Popen( - dummy_cmd, + cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=self.proc_stderr, diff --git a/tests/isolation_provider/test_dummy.py b/tests/isolation_provider/test_dummy.py index 1002687..198a6af 100644 --- a/tests/isolation_provider/test_dummy.py +++ b/tests/isolation_provider/test_dummy.py @@ -1,11 +1,9 @@ import os -import subprocess import pytest from pytest_mock import MockerFixture from dangerzone.conversion import errors -from dangerzone.document import Document from dangerzone.isolation_provider.base import IsolationProvider from dangerzone.isolation_provider.dummy import Dummy @@ -16,24 +14,6 @@ if not os.environ.get("DUMMY_CONVERSION", False): pytest.skip("Dummy conversion is not enabled", allow_module_level=True) -class DummyWait(Dummy): - """Dummy isolation provider that spawns a blocking process.""" - - def start_doc_to_pixels_proc(self, document: Document) -> subprocess.Popen: - return subprocess.Popen( - ["python3"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - start_new_session=True, - ) - - -@pytest.fixture -def provider_wait() -> DummyWait: - return DummyWait() - - @pytest.fixture def provider() -> Dummy: return Dummy() @@ -42,21 +22,12 @@ def provider() -> Dummy: class TestDummyTermination(IsolationProviderTermination): def test_failed( self, - provider_wait: IsolationProvider, + provider: IsolationProvider, mocker: MockerFixture, ) -> None: mocker.patch.object( - provider_wait, + provider, "get_proc_exception", return_value=errors.DocFormatUnsupported(), ) - super().test_failed(provider_wait, mocker) - - def test_linger_unkillable( - self, - provider_wait: IsolationProvider, - mocker: MockerFixture, - ) -> None: - # We have to spawn a blocking process here, else we can't imitate an - # "unkillable" process. - super().test_linger_unkillable(provider_wait, mocker) + super().test_failed(provider, mocker)