From 0b8d712003d6944c389d8b9366de58a944dde137 Mon Sep 17 00:00:00 2001 From: Allie Crevier Date: Mon, 2 Dec 2019 13:58:44 -0800 Subject: [PATCH] get_path_to_file_with_original_name --- securedrop_client/export.py | 11 +--- securedrop_client/logic.py | 83 +++++++++++++------------- tests/gui/test_widgets.py | 4 +- tests/test_export.py | 28 ++++----- tests/test_logic.py | 112 +++++++++++++++++++++++++++--------- tests/test_queue.py | 2 +- 6 files changed, 143 insertions(+), 97 deletions(-) diff --git a/securedrop_client/export.py b/securedrop_client/export.py index 22dd625692..31a7d6cb83 100644 --- a/securedrop_client/export.py +++ b/securedrop_client/export.py @@ -83,6 +83,7 @@ class Export(QObject): begin_print = pyqtSignal(list) print_call_failure = pyqtSignal(object) print_call_success = pyqtSignal() + export_completed = pyqtSignal(list) def __init__(self) -> None: super().__init__() @@ -282,10 +283,7 @@ def send_file_to_usb_device(self, filepaths: List[str], passphrase: str) -> None logger.error(e) self.export_usb_call_failure.emit(e) - # Export is finished, now remove files created when export began - for filepath in filepaths: - if os.path.exists(filepath): - os.remove(filepath) + self.export_completed.emit(filepaths) @pyqtSlot(list) def print(self, filepaths: List[str]) -> None: @@ -306,7 +304,4 @@ def print(self, filepaths: List[str]) -> None: logger.error(e) self.print_call_failure.emit(e) - # Print is finished, now remove files created when print began - for filepath in filepaths: - if os.path.exists(filepath): - os.remove(filepath) + self.export_completed.emit(filepaths) diff --git a/securedrop_client/logic.py b/securedrop_client/logic.py index 64bfc7ef98..90b72036b3 100644 --- a/securedrop_client/logic.py +++ b/securedrop_client/logic.py @@ -181,6 +181,7 @@ def __init__(self, hostname: str, gui, session_maker: sessionmaker, self.gpg = GpgHelper(home, self.session_maker, proxy) self.export = Export() + self.export.export_completed.connect(self.cleanup_hardlinked_file) self.sync_flag = os.path.join(home, 'sync_flag') @@ -588,16 +589,40 @@ def downloaded_file_exists(self, file_uuid: str) -> bool: return False return True - def on_file_open(self, file_uuid: str) -> None: + def cleanup_hardlinked_file(cls, filepaths): + ''' + Once inter-vm communication is complete and we no longer need to keep file copies with the + original filenames, delete them. ''' - Open the file specified by file_uuid. + for filepath in filepaths: + if os.path.exists(filepath): + os.remove(filepath) + + def get_path_to_file_with_original_name( + cls, file_dir: str, filename: str, filename_orig: str + ) -> str: + ''' + Create a hardlink with the original filename and return its path. Once a file is downloaded, it exists in the data directory with the same filename as the server, except with the .gz.gpg stripped off. In order for the Display VM to know which application to open the file in, we create a hard link to this file with the original file name, including its extension. + ''' + + path_to_file_with_original_name = os.path.join(file_dir, filename_orig) + + if not os.path.exists(path_to_file_with_original_name): + fn_no_ext, dummy = os.path.splitext(os.path.splitext(filename)[0]) + filepath = os.path.join(file_dir, fn_no_ext) + os.link(filepath, path_to_file_with_original_name) + + return path_to_file_with_original_name - If the file is missing, update the db so that is_downloaded is set to False. + def on_file_open(self, file_uuid: str) -> None: + ''' + Open the file specified by file_uuid. If the file is missing, update the db so that + is_downloaded is set to False. ''' file = self.get_file(file_uuid) logger.info('Opening file "{}".'.format(file.original_filename)) @@ -606,16 +631,12 @@ def on_file_open(self, file_uuid: str) -> None: self.sync_api() return - path_to_file_with_original_name = os.path.join(self.data_dir, file.original_filename) - - if not os.path.exists(path_to_file_with_original_name): - fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) - filepath = os.path.join(self.data_dir, fn_no_ext) - os.link(filepath, path_to_file_with_original_name) - if not self.qubes: return + path_to_file_with_original_name = self.get_path_to_file_with_original_name( + self.data_dir, file.filename, file.original_filename) + command = "qvm-open-in-vm" args = ['$dispvm:sd-svs-disp', path_to_file_with_original_name] process = QProcess(self) @@ -635,14 +656,8 @@ def run_export_preflight_checks(self): def export_file_to_usb_drive(self, file_uuid: str, passphrase: str) -> None: ''' Send the file specified by file_uuid to the Export VM with the user-provided passphrase for - unlocking the attached transfer device. - - Once a file is downloaded, it exists in the data directory with the same filename as the - server, except with the .gz.gpg stripped off. In order for the user to know which - application to open the file in, we export the file with a different name: the original - filename which includes the file extesion. - - If the file is missing, update the db so that is_downloaded is set to False. + unlocking the attached transfer device. If the file is missing, update the db so that + is_downloaded is set to False. ''' file = self.get_file(file_uuid) logger.info('Exporting file {}'.format(file.original_filename)) @@ -651,28 +666,18 @@ def export_file_to_usb_drive(self, file_uuid: str, passphrase: str) -> None: self.sync_api() return - path_to_file_with_original_name = os.path.join(self.data_dir, file.original_filename) - - if not os.path.exists(path_to_file_with_original_name): - fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) - filepath = os.path.join(self.data_dir, fn_no_ext) - os.link(filepath, path_to_file_with_original_name) - if not self.qubes: return - fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) - filepath = os.path.join(self.data_dir, fn_no_ext) + path_to_file_with_original_name = self.get_path_to_file_with_original_name( + self.data_dir, file.filename, file.original_filename) + self.export.begin_usb_export.emit([path_to_file_with_original_name], passphrase) def print_file(self, file_uuid: str) -> None: ''' - Send the file specified by file_uuid to the Export VM. - - Once a file is downloaded, it exists in the data directory with the same filename as the - server, except with the .gz.gpg stripped off. - - If the file is missing, update the db so that is_downloaded is set to False. + Send the file specified by file_uuid to the Export VM. If the file is missing, update the db + so that is_downloaded is set to False. ''' file = self.get_file(file_uuid) logger.info('Printing file {}'.format(file.original_filename)) @@ -681,18 +686,12 @@ def print_file(self, file_uuid: str) -> None: self.sync_api() return - path_to_file_with_original_name = os.path.join(self.data_dir, file.original_filename) - - if not os.path.exists(path_to_file_with_original_name): - fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) - filepath = os.path.join(self.data_dir, fn_no_ext) - os.link(filepath, path_to_file_with_original_name) - if not self.qubes: return - fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) - filepath = os.path.join(self.data_dir, fn_no_ext) + path_to_file_with_original_name = self.get_path_to_file_with_original_name( + self.data_dir, file.filename, file.original_filename) + self.export.begin_print.emit([path_to_file_with_original_name]) def on_submission_download( diff --git a/tests/gui/test_widgets.py b/tests/gui/test_widgets.py index be54103ccd..252ede6a58 100644 --- a/tests/gui/test_widgets.py +++ b/tests/gui/test_widgets.py @@ -1492,7 +1492,7 @@ def test_FileWidget__on_export_clicked_missing_file(mocker, session, source): def test_FileWidget__on_print_clicked(mocker, session, source): """ - Ensure preflight checks start when the EXPORT button is clicked and that password is requested + Ensure print_file is called when the PRINT button is clicked """ file = factory.File(source=source['source'], is_downloaded=True) session.add(file) @@ -1764,7 +1764,7 @@ def test_ExportDialog__update_after_CALLED_PROCESS_ERROR(mocker): def test_PrintDialog__on_retry_button_clicked(mocker): """ - Ensure happy path runs preflight checks. + Ensure happy path prints the file. """ controller = mocker.MagicMock() dialog = PrintDialog(controller, 'mock_uuid') diff --git a/tests/test_export.py b/tests/test_export.py index 0fa9e68c26..ae3db390ca 100644 --- a/tests/test_export.py +++ b/tests/test_export.py @@ -17,17 +17,16 @@ def test_print(mocker): export = Export() export.print_call_success = mocker.MagicMock() export.print_call_success.emit = mocker.MagicMock() + export.export_completed = mocker.MagicMock() + export.export_completed.emit = mocker.MagicMock() _run_print = mocker.patch.object(export, '_run_print') mocker.patch('os.path.exists', return_value=True) - os_remove = mocker.patch('os.remove') export.print(['path1', 'path2']) _run_print.assert_called_once_with('mock_temp_dir', ['path1', 'path2']) export.print_call_success.emit.assert_called_once_with() - assert os_remove.call_count == 2 - assert os_remove.call_args_list[0][0][0] == 'path1' - assert os_remove.call_args_list[1][0][0] == 'path2' + export.export_completed.emit.assert_called_once_with(['path1', 'path2']) def test_print_error(mocker): @@ -41,18 +40,17 @@ def test_print_error(mocker): export = Export() export.print_call_failure = mocker.MagicMock() export.print_call_failure.emit = mocker.MagicMock() + export.export_completed = mocker.MagicMock() + export.export_completed.emit = mocker.MagicMock() error = ExportError('[mock_filepath]') _run_print = mocker.patch.object(export, '_run_print', side_effect=error) mocker.patch('os.path.exists', return_value=True) - os_remove = mocker.patch('os.remove') export.print(['path1', 'path2']) _run_print.assert_called_once_with('mock_temp_dir', ['path1', 'path2']) export.print_call_failure.emit.assert_called_once_with(error) - assert os_remove.call_count == 2 - assert os_remove.call_args_list[0][0][0] == 'path1' - assert os_remove.call_args_list[1][0][0] == 'path2' + export.export_completed.emit.assert_called_once_with(['path1', 'path2']) def test__run_print(mocker): @@ -99,17 +97,16 @@ def test_send_file_to_usb_device(mocker): export = Export() export.export_usb_call_success = mocker.MagicMock() export.export_usb_call_success.emit = mocker.MagicMock() + export.export_completed = mocker.MagicMock() + export.export_completed.emit = mocker.MagicMock() _run_disk_export = mocker.patch.object(export, '_run_disk_export') mocker.patch('os.path.exists', return_value=True) - os_remove = mocker.patch('os.remove') export.send_file_to_usb_device(['path1', 'path2'], 'mock passphrase') _run_disk_export.assert_called_once_with('mock_temp_dir', ['path1', 'path2'], 'mock passphrase') export.export_usb_call_success.emit.assert_called_once_with() - assert os_remove.call_count == 2 - assert os_remove.call_args_list[0][0][0] == 'path1' - assert os_remove.call_args_list[1][0][0] == 'path2' + export.export_completed.emit.assert_called_once_with(['path1', 'path2']) def test_send_file_to_usb_device_error(mocker): @@ -123,18 +120,17 @@ def test_send_file_to_usb_device_error(mocker): export = Export() export.export_usb_call_failure = mocker.MagicMock() export.export_usb_call_failure.emit = mocker.MagicMock() + export.export_completed = mocker.MagicMock() + export.export_completed.emit = mocker.MagicMock() error = ExportError('[mock_filepath]') _run_disk_export = mocker.patch.object(export, '_run_disk_export', side_effect=error) mocker.patch('os.path.exists', return_value=True) - os_remove = mocker.patch('os.remove') export.send_file_to_usb_device(['path1', 'path2'], 'mock passphrase') _run_disk_export.assert_called_once_with('mock_temp_dir', ['path1', 'path2'], 'mock passphrase') export.export_usb_call_failure.emit.assert_called_once_with(error) - assert os_remove.call_count == 2 - assert os_remove.call_args_list[0][0][0] == 'path1' - assert os_remove.call_args_list[1][0][0] == 'path2' + export.export_completed.emit.assert_called_once_with(['path1', 'path2']) def test_run_preflight_checks(mocker): diff --git a/tests/test_logic.py b/tests/test_logic.py index ba072c045b..27d22d0d89 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -12,6 +12,7 @@ from securedrop_client import storage, db from securedrop_client.crypto import CryptoError +from securedrop_client.export import Export from securedrop_client.logic import APICallRunner, Controller from securedrop_client.api_jobs.downloads import DownloadChecksumMismatchException from securedrop_client.api_jobs.uploads import SendReplyJobError @@ -877,6 +878,57 @@ def test_Controller_on_file_downloaded_checksum_failure(homedir, config, mocker, mock_set_status.assert_not_called() +def test_get_path_to_file_with_original_name(mocker, homedir, session): + ''' + Test that the hardlink is created and returned. + ''' + co = Controller('http://localhost', mocker.MagicMock(), mocker.MagicMock(), homedir) + + with open(os.path.join(homedir, 'mock_filename'), 'w'): + pass + + path_to_file_with_original_name = co.get_path_to_file_with_original_name( + homedir, 'mock_filename', 'mock_filename_orig') + + assert path_to_file_with_original_name == os.path.join(homedir, 'mock_filename_orig') + + +def test_get_path_to_file_with_original_name_already_exists(mocker, homedir, session): + ''' + Test that the hardlink is returned if already exists. + ''' + co = Controller('http://localhost', mocker.MagicMock(), mocker.MagicMock(), homedir) + + with open(os.path.join(homedir, 'mock_filename_orig'), 'w'): + pass + + path_to_file_with_original_name = co.get_path_to_file_with_original_name( + homedir, 'mock_filename', 'mock_filename_orig') + + assert path_to_file_with_original_name == os.path.join(homedir, 'mock_filename_orig') + + +def test_cleanup_hardlinked_file(mocker, homedir): + ''' + Test that we delete all the files in the list. + ''' + co = Controller('http://localhost', mocker.MagicMock(), mocker.MagicMock(), homedir) + + filepath = os.path.join(homedir, 'testfile') + filepath2 = os.path.join(homedir, 'testfile2') + filepaths = [filepath, filepath2] + + for file in filepaths: + with open(file, 'w'): + pass + assert os.path.exists(file) + + co.cleanup_hardlinked_file(filepaths) + + assert not os.path.exists(filepath) + assert not os.path.exists(filepath2) + + def test_Controller_on_file_open(homedir, config, mocker, session, session_maker, source): """ If running on Qubes, a new QProcess with the expected command and args should be started when @@ -894,7 +946,7 @@ def test_Controller_on_file_open(homedir, config, mocker, session, session_maker mock_subprocess = mocker.MagicMock() mock_process = mocker.MagicMock(return_value=mock_subprocess) mocker.patch('securedrop_client.logic.QProcess', mock_process) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -904,15 +956,15 @@ def test_Controller_on_file_open(homedir, config, mocker, session, session_maker co.on_file_open(file.uuid) co.get_file.assert_called_with(file.uuid) + co.get_path_to_file_with_original_name.assert_called_once_with( + os.path.join(homedir, 'data'), file.filename, file.original_filename) mock_process.assert_called_once_with(co) assert mock_subprocess.start.call_count == 1 - assert mock_link.call_count == 1 def test_Controller_on_file_open_not_qubes(homedir, config, mocker, session, session_maker, source): """ - If not running on Qubes, a hard link to the file in the data dir should be created using the - original filename. + Check that we just check if the file exists if not running on Qubes. """ co = Controller('http://localhost', mocker.MagicMock(), session_maker, homedir) co.qubes = False @@ -921,7 +973,7 @@ def test_Controller_on_file_open_not_qubes(homedir, config, mocker, session, ses session.add(file) session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -931,7 +983,7 @@ def test_Controller_on_file_open_not_qubes(homedir, config, mocker, session, ses co.on_file_open(file.uuid) co.get_file.assert_called_with(file.uuid) - assert mock_link.call_count == 1 + co.get_path_to_file_with_original_name.assert_not_called() def test_Controller_on_file_open_when_orig_file_already_exists( @@ -953,7 +1005,7 @@ def test_Controller_on_file_open_when_orig_file_already_exists( mock_subprocess = mocker.MagicMock() mock_process = mocker.MagicMock(return_value=mock_subprocess) mocker.patch('securedrop_client.logic.QProcess', mock_process) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -967,17 +1019,17 @@ def test_Controller_on_file_open_when_orig_file_already_exists( co.on_file_open(file.uuid) co.get_file.assert_called_with(file.uuid) + co.get_path_to_file_with_original_name.assert_called_once_with( + os.path.join(homedir, 'data'), file.filename, file.original_filename) mock_process.assert_called_once_with(co) assert mock_subprocess.start.call_count == 1 - assert mock_link.call_count == 0 def test_Controller_on_file_open_when_orig_file_already_exists_not_qubes( homedir, config, mocker, session, session_maker, source ): """ - If not running on Qubes, a hard link to the file in the data dir should be created using the - original filename. + Check that we just check if the file exists if not running on Qubes. """ co = Controller('http://localhost', mocker.MagicMock(), session_maker, homedir) co.qubes = False @@ -986,7 +1038,7 @@ def test_Controller_on_file_open_when_orig_file_already_exists_not_qubes( session.add(file) session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1000,7 +1052,7 @@ def test_Controller_on_file_open_when_orig_file_already_exists_not_qubes( co.on_file_open(file.uuid) co.get_file.assert_called_with(file.uuid) - assert mock_link.call_count == 0 + co.get_path_to_file_with_original_name.assert_not_called() def test_Controller_on_file_open_file_missing(mocker, homedir, session_maker, session, source): @@ -1505,7 +1557,7 @@ def test_Controller_run_print_file(mocker, session, homedir): session.add(file) session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1515,7 +1567,8 @@ def test_Controller_run_print_file(mocker, session, homedir): co.print_file(file.uuid) co.export.begin_print.emit.call_count == 1 - assert mock_link.call_count == 1 + co.get_path_to_file_with_original_name.assert_called_once_with( + os.path.join(homedir, 'data'), file.filename, file.original_filename) def test_Controller_run_print_file_not_qubes(mocker, session, homedir): @@ -1528,7 +1581,7 @@ def test_Controller_run_print_file_not_qubes(mocker, session, homedir): session.add(file) session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1538,7 +1591,7 @@ def test_Controller_run_print_file_not_qubes(mocker, session, homedir): co.print_file(file.uuid) co.export.begin_print.emit.call_count == 0 - assert mock_link.call_count == 1 + co.get_path_to_file_with_original_name.assert_not_called() def test_Controller_print_file_file_missing(homedir, mocker, session, session_maker): @@ -1607,13 +1660,14 @@ def test_Controller_print_file_when_orig_file_already_exists( session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) mocker.patch('os.path.exists', return_value=True) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() co.print_file(file.uuid) co.export.begin_print.emit.call_count == 1 co.get_file.assert_called_with(file.uuid) - assert mock_link.call_count == 0 + co.get_path_to_file_with_original_name.assert_called_once_with( + os.path.join(homedir, 'data'), file.filename, file.original_filename) def test_Controller_print_file_when_orig_file_already_exists_not_qubes( @@ -1632,7 +1686,7 @@ def test_Controller_print_file_when_orig_file_already_exists_not_qubes( session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) mocker.patch('os.path.exists', return_value=True) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1647,7 +1701,7 @@ def test_Controller_print_file_when_orig_file_already_exists_not_qubes( co.export.begin_print.emit.call_count == 1 co.get_file.assert_called_with(file.uuid) - assert mock_link.call_count == 0 + co.get_path_to_file_with_original_name.assert_not_called() def test_Controller_run_export_preflight_checks(homedir, mocker, session, source): @@ -1693,7 +1747,7 @@ def test_Controller_export_file_to_usb_drive(homedir, mocker, session): session.add(file) session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1703,7 +1757,8 @@ def test_Controller_export_file_to_usb_drive(homedir, mocker, session): co.export_file_to_usb_drive(file.uuid, 'mock passphrase') co.export.begin_usb_export.emit.call_count == 1 - assert mock_link.call_count == 1 + co.get_path_to_file_with_original_name.assert_called_once_with( + os.path.join(homedir, 'data'), file.filename, file.original_filename) def test_Controller_export_file_to_usb_drive_not_qubes(homedir, mocker, session): @@ -1719,7 +1774,7 @@ def test_Controller_export_file_to_usb_drive_not_qubes(homedir, mocker, session) session.add(file) session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1730,7 +1785,7 @@ def test_Controller_export_file_to_usb_drive_not_qubes(homedir, mocker, session) co.export.send_file_to_usb_device.assert_not_called() co.export.begin_usb_export.emit.call_count == 0 - assert mock_link.call_count == 1 + co.get_path_to_file_with_original_name.assert_not_called() def test_Controller_export_file_to_usb_drive_file_missing(homedir, mocker, session, session_maker): @@ -1799,13 +1854,14 @@ def test_Controller_export_file_to_usb_drive_when_orig_file_already_exists( session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) mocker.patch('os.path.exists', return_value=True) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() co.export_file_to_usb_drive(file.uuid, 'mock passphrase') co.export.begin_usb_export.emit.call_count == 1 co.get_file.assert_called_with(file.uuid) - assert mock_link.call_count == 0 + co.get_path_to_file_with_original_name.assert_called_once_with( + os.path.join(homedir, 'data'), file.filename, file.original_filename) def test_Controller_export_file_to_usb_drive_when_orig_file_already_exists_not_qubes( @@ -1824,7 +1880,7 @@ def test_Controller_export_file_to_usb_drive_when_orig_file_already_exists_not_q session.commit() mocker.patch('securedrop_client.logic.Controller.get_file', return_value=file) mocker.patch('os.path.exists', return_value=True) - mock_link = mocker.patch('os.link') + co.get_path_to_file_with_original_name = mocker.MagicMock() fn_no_ext, dummy = os.path.splitext(os.path.splitext(file.filename)[0]) filepath = os.path.join(homedir, 'data', fn_no_ext) @@ -1839,7 +1895,7 @@ def test_Controller_export_file_to_usb_drive_when_orig_file_already_exists_not_q co.export.begin_usb_export.emit.call_count == 1 co.get_file.assert_called_with(file.uuid) - assert mock_link.call_count == 0 + co.get_path_to_file_with_original_name.assert_not_called() def test_get_file(mocker, session, homedir): diff --git a/tests/test_queue.py b/tests/test_queue.py index 080be222a9..cabff3c95f 100644 --- a/tests/test_queue.py +++ b/tests/test_queue.py @@ -273,7 +273,7 @@ def test_ApiJobQueue_pause_queues(mocker): job_queue.on_queue_paused() - job_queue.paused.emit() + job_queue.paused.emit.assert_called_once_with() def test_ApiJobQueue_resume_queues_emits_resume_signal(mocker):