MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 12 / 0 / 12
Functions: 100.0% 8 / 0 / 8
Branches: -% 0 / 0 / 0

service/ImapConnectionSetup.h
Line Branch Exec Source
1 #pragma once
2
3 #include <QString>
4 #include <QStringList>
5
6 #include <functional>
7
8 #include "data/AccountConfig.h"
9 #include "service/ImapResponseParser.h"
10 #include "service/ImapService.h"
11
12 class ImapCommandTable;
13 class QObject;
14 class QSslSocket;
15 class QTimer;
16
17 // Connection setup of one IMAP connection (Sprint 92 S92.1.3, extracted
18 // from ImapService): TCP/TLS establishment callbacks, the session-setup
19 // deadline, greeting → CAPABILITY → optional STARTTLS → post-TLS
20 // CAPABILITY → LOGIN (with the post-login capability set), TCP keepalive
21 // tuning and the account credentials (zeroed after use).
22 //
23 // Owner: ImapService (std::unique_ptr), connection thread. Plain class; its
24 // setup timer is a child of the service, which connects it to
25 // ImapService::onTimeout; the socket's connected/encrypted/disconnected
26 // signals are connected to this unit at the former positions. The
27 // negotiated capability list stays with the service (read by every
28 // command) and is written here by reference. connectToServer() stays in
29 // the service because it resets the state of every unit (plan correction,
30 // SPRINT-92.md §9.1); it reaches this unit's state through the accessors.
31 class ImapConnectionSetup {
32 public:
33 using State = ImapService::State;
34 using SetupPhase = ImapService::SetupPhase;
35 using DisconnectReason = ImapService::DisconnectReason;
36
37 struct Deps {
38 std::function<void(State state)> setState;
39 std::function<void(const QString &error, DisconnectReason reason)> failConnection;
40 std::function<bool()> readBufferEmpty;
41 // MAILJD_E2E_TESTING only (present in every build for a stable layout).
42 std::function<void(const QString &phase, quint64 requestToken)> reportE2eTransportPhase;
43 };
44 ImapConnectionSetup(QObject *owner, QSslSocket *socket, ImapCommandTable &commands,
45 QStringList &capabilities, Deps deps);
46
47 void onConnected();
48 void onEncrypted();
49 bool beginLogin();
50 // T-720: Apply SO_KEEPALIVE + platform-specific interval tuning to the
51 // connected socket. Called once from onConnected()/onEncrypted().
52 void tuneKeepAlive();
53 void clearCredentials();
54 // Untagged greeting and CAPABILITY responses during negotiation.
55 // preAuthenticated: the greeting was "* PREAUTH" (RFC 3501 §7.1.4).
56 void handleGreeting(const QString &data, bool preAuthenticated = false);
57 void collectCapabilities(const QString &data);
58 // Tagged completions of the setup commands.
59 void handleTaggedCapability(const TaggedResponse &response);
60 void handleTaggedStartTls(const TaggedResponse &response);
61 void handleTaggedLogin(const TaggedResponse &response);
62
63 // Setup state shared with the service's session lifecycle (single owner:
64 // this unit).
65 102 ImapConfig &config() { return m_config; }
66 2430 SetupPhase &setupPhase() { return m_setupPhase; }
67 2429 QStringList &pendingCapabilities() { return m_pendingCapabilities; }
68 78 bool &keepAliveTuned() { return m_keepAliveTuned; }
69 5287 QTimer *setupTimer() const { return m_timeoutTimer; }
70
71 // SEC-2026-07-21-12: deadline for the pre-auth setup phases (greeting,
72 // TLS handshake, CAPABILITY, LOGIN). Without this, a silent server can
73 // stall the account indefinitely after TCP connect — no error, no
74 // reconnect. The timer is re-armed on each setup-state transition and
75 // stopped once Authenticated is reached (command timeout takes over).
76 static constexpr int SESSION_SETUP_TIMEOUT_MS = 30000; // 30 seconds
77
78 private:
79 270 void setState(State state) { m_deps.setState(state); }
80 16 void failConnection(const QString &error,
81 DisconnectReason reason = DisconnectReason::ProtocolError) {
82 16 m_deps.failConnection(error, reason);
83 16 }
84 133 void reportE2eTransportPhase(const QString &phase, quint64 requestToken = 0) {
85 133 m_deps.reportE2eTransportPhase(phase, requestToken);
86 133 }
87
88 QSslSocket *m_socket;
89 ImapCommandTable &m_commands;
90 QStringList &m_capabilities; // ImapService::m_capabilities
91 Deps m_deps;
92
93 QTimer *m_timeoutTimer = nullptr;
94 ImapConfig m_config;
95 QStringList m_pendingCapabilities;
96 SetupPhase m_setupPhase = SetupPhase::AwaitingGreeting;
97 // T-720: True once tuneKeepAlive() ran (test seam for native tuning).
98 bool m_keepAliveTuned = false;
99 };
100