[PATCH b4 09/27] tests: cover the thank-you send's post-send bookkeeping
Christian Brauner <[email protected]> Fri, 31 Jul 2026 11:21:08 +0200
| Newsgroups | org.kernel.linux.tools |
|---|---|
| Message-ID | <20260731-work-b4-editor-branch-guard-v1-9-de68a7c8e4cb@kernel.org> |
Both of these are about what the maintainer is told once the message is already gone. The note is recorded as read at send time and a broken archive is never reported as "Send failed". Signed-off-by: Christian Brauner (Amutable) <[email protected]> --- src/tests/test_tui_tracking.py | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/tests/test_tui_tracking.py b/src/tests/test_tui_tracking.py index 1212ab1..57cfdc0 100644 --- a/src/tests/test_tui_tracking.py +++ b/src/tests/test_tui_tracking.py @@ -4495,6 +4495,73 @@ class TestTakeThankArchiveChain: assert not notices +class TestSendThankMessage: + """Everything after a successful send is bookkeeping, and bookkeeping + must not be able to claim the send failed.""" + + def _send( + self, archive_raises: bool + ) -> Tuple[List[Tuple[str, str]], List[List[Any]]]: + """Drive _send_thank_message with a send that succeeds. + + Returns (notifications as (message, severity), mark_outgoing_seen + calls). + """ + import contextlib + + notices: List[Tuple[str, str]] = [] + seen_calls: List[List[Any]] = [] + app = TrackingApp.__new__(TrackingApp) + app._email_dryrun = False + app._patatt_sign = False + app._identifier = '' + msg = email.message.EmailMessage() + msg['Message-Id'] = '<[email protected]>' + series = {'change_id': 'send-1', 'revision': 1} + + def _archive(self: Any, _series: Dict[str, Any]) -> None: + if archive_raises: + raise OSError(28, 'No space left on device') + + with ( + patch.object(TrackingApp, 'suspend', lambda self: contextlib.nullcontext()), + patch.object(TrackingApp, '_invalidate_caches', lambda self, cid: None), + patch.object(TrackingApp, '_load_series', lambda self: None), + patch.object(TrackingApp, '_archive_after_thanks', _archive), + patch.object( + TrackingApp, + 'notify', + lambda self, message, severity='information', **k: notices.append( + (str(message), severity) + ), + ), + patch('b4.get_smtp', return_value=(None, '[email protected]')), + patch('b4.send_mail', return_value=1), + patch( + 'b4.review_tui._tracking_app.mark_outgoing_seen', + lambda msgs, dryrun=False: seen_calls.append(list(msgs)), + ), + ): + app._send_thank_message(msg, series, archive_after=True) + return notices, seen_calls + + def test_marks_the_sent_message_seen(self) -> None: + """The thank-you is a reply into the series thread, so it comes back + from the list; recording it at send time keeps the badge dark.""" + _notices, seen_calls = self._send(archive_raises=False) + assert len(seen_calls) == 1 + assert seen_calls[0][0]['Message-Id'] == '<[email protected]>' + + def test_failed_archive_is_not_a_send_failure(self) -> None: + """A broken archive must never read as 'Send failed': that tells the + maintainer to re-send a note that is already on the list.""" + notices, _seen = self._send(archive_raises=True) + texts = [n for n, _sev in notices] + assert 'Thank-you message sent' in texts + assert not any('Send failed' in n for n in texts) + assert any('No space left on device' in n for n in texts) + + # --------------------------------------------------------------------------- # take->merge conflict resolution (must never drop a non-empty commit) # --------------------------------------------------------------------------- -- 2.53.0