def delayed_update_messages(remote_submissions, local_submissions, session, data_dir): assert source_exists(session, source.uuid) deleter.start() time.sleep(1) # This next assert should fail if transactions are working, as # the source should still be visible in this session -- it's # only been deleted in the Deleter's session. If transactions # are *not* working, the deletion will be visible here. assert source_exists(session, source.uuid) is False update_messages(remote_submissions, local_submissions, session, data_dir)
def test_source_exists_true(homedir, mocker): """ Check that method returns True if a source is return from the query. """ session = mocker.MagicMock() source = factory.RemoteSource() source.uuid = "test-source-uuid" session.query().filter_by().one.return_value = source assert source_exists(session, "test-source-uuid")
def test_source_exists_true(homedir, mocker): ''' Check that method returns True if a source is return from the query. ''' session = mocker.MagicMock() source = make_remote_source() source.uuid = 'test-source-uuid' session.query().filter_by().one.return_value = source assert source_exists(session, 'test-source-uuid')
def test_source_exists_false(homedir, mocker): """ Check that method returns False if NoResultFound is thrown when we try to query the source. """ session = mocker.MagicMock() source = mocker.MagicMock() source.uuid = "test-source-uuid" session.query().filter_by().one.side_effect = NoResultFound() assert not source_exists(session, "test-source-uuid")
def test_sync_delete_race(homedir, mocker, session_maker, session): """ Test a race between sync and source deletion (#797). The original failure scenario: 0. New source submits message 1. 1. Sync occurs in client. Journalist sees message 1. 2. Source submits message 2. 3. Journalist simultaneously deletes the source while the sync begins. Deletion completes as it occurs independently of the sync, but by this time the sync has collected the list of new messages, which includes message 2. 4. Source is gone, yet the logic in the sync will attempt to add message 2 which corresponds to a source that is deleted. """ source = factory.RemoteSource() message1 = make_remote_message(source.uuid) sources = [source] submissions = [message1] replies = [] update_local_storage(session, sources, submissions, replies, homedir) assert source_exists(session, source.uuid) get_message(session, message1.uuid) message2 = make_remote_message(source.uuid, file_counter=2) submissions = [message1, message2] class Deleter(QThread): def __init__(self, source_uuid): super().__init__() self.source_uuid = source_uuid def run(self): session = db.make_session_maker(homedir)() session.begin(subtransactions=True) delete_local_source_by_uuid(session, self.source_uuid, homedir) session.commit() self.exit() deleter = Deleter(source.uuid) def delayed_update_messages(remote_submissions, local_submissions, session, data_dir): assert source_exists(session, source.uuid) deleter.start() time.sleep(1) # This next assert should fail if transactions are working, as # the source should still be visible in this session -- it's # only been deleted in the Deleter's session. If transactions # are *not* working, the deletion will be visible here. assert source_exists(session, source.uuid) is False update_messages(remote_submissions, local_submissions, session, data_dir) mocker.patch("securedrop_client.storage.update_messages", delayed_update_messages) # simulate update_local_storage being called as part of the sync operation update_local_storage(session, sources, [message1, message2], [], homedir) assert source_exists(session, source.uuid) is False with pytest.raises(NoResultFound): get_message(session, message1.uuid) assert source_exists(session, source.uuid) is False with pytest.raises(NoResultFound): get_message(session, message1.uuid) get_message(session, message2.uuid)
def get_current_source(self): source_item = self.currentItem() source_widget = self.itemWidget(source_item) if source_widget and source_exists(self.controller.session, source_widget.source.uuid): return source_widget.source