diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index f758a85ee..c05c31243 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -646,17 +646,17 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi for local_file_item, zip_file_item in write_list: total_size += local_file_item.stat().st_size self.log_debug('ServiceManager.save_file - ZIP contents size is %i bytes' % total_size) - self.main_window.display_progress_bar(total_size) + self.main_window.display_progress_bar(1000) try: with NamedTemporaryFile(dir=str(file_path.parent), prefix='.') as temp_file, \ zipfile.ZipFile(temp_file, 'w') as zip_file: # First we add service contents.. zip_file.writestr('service_data.osj', service_content) - self.main_window.increment_progress_bar(service_content_size) + self.main_window.increment_progress_bar(service_content_size / total_size * 1000) # Finally add all the listed media files. for local_file_item, zip_file_item in write_list: zip_file.write(str(local_file_item), str(zip_file_item)) - self.main_window.increment_progress_bar(local_file_item.stat().st_size) + self.main_window.increment_progress_bar(local_file_item.stat().st_size / total_size * 1000) with suppress(FileNotFoundError): file_path.unlink() os.link(temp_file.name, file_path) diff --git a/tests/functional/openlp_core/ui/test_servicemanager.py b/tests/functional/openlp_core/ui/test_servicemanager.py index 87574be4b..33655bb20 100644 --- a/tests/functional/openlp_core/ui/test_servicemanager.py +++ b/tests/functional/openlp_core/ui/test_servicemanager.py @@ -655,6 +655,43 @@ def test_save_file_raises_permission_error(mocked_os, mocked_save_file_as, mocke mocked_save_file_as.assert_called_with() +@patch('openlp.core.ui.servicemanager.zipfile') +@patch('openlp.core.ui.servicemanager.ServiceManager.save_file_as') +@patch('openlp.core.ui.servicemanager.os') +@patch('openlp.core.ui.servicemanager.len') +def test_save_file_large_file(mocked_len, mocked_os, mocked_save_file_as, mocked_zipfile, registry): + """ + Test that when a file size size larger than a 32bit signed int is attempted to save, the progress bar + should be provided a value that fits in a 32bit int (because it's passed to C++ as a 32bit unsigned int) + """ + # GIVEN: A service manager, a service to save, and len() returns a huge value (file size) + def check_for_i32_overflow(val): + if val > 2147483647: + raise OverflowError + mocked_main_window = MagicMock() + mocked_main_window.display_progress_bar.side_effect = check_for_i32_overflow + Registry().register('main_window', mocked_main_window) + Registry().register('application', MagicMock()) + mocked_settings = MagicMock() + Registry().register('settings', mocked_settings) + service_manager = ServiceManager(None) + service_manager._service_path = MagicMock() + service_manager._save_lite = False + service_manager.service_items = [] + service_manager.service_theme = 'Default' + service_manager.service_manager_list = MagicMock() + mocked_save_file_as.return_value = True + mocked_zipfile.ZipFile.return_value = MagicMock() + mocked_len.return_value = 10000000000000 + + # WHEN: The service is saved and no error is raised + result = service_manager.save_file() + + # THEN: The "save_as" method is called to save the service + assert result is True + mocked_save_file_as.assert_called_with() + + @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') def test_theme_change_global(mocked_regenerate_service_items, registry): """