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: 98.5% 132 / 0 / 134
Functions: 96.3% 52 / 0 / 54
Branches: 100.0% 14 / 0 / 14

service/ImapServiceUnits.cpp
Line Branch Exec Source
1 // Composition root of ImapService (Sprint 92 S92.1.x): constructs the seven
2 // internal units in the service constructor's initializer order and binds
3 // their Deps — calls into other units, the failure path and the notifiers
4 // that emit the service's signals. Kept apart from ImapService.cpp, which
5 // holds the protocol state machine and the response dispatch.
6
7 #include "ImapService.h"
8
9 #include "ImapAppendStream.h"
10 #include "ImapBodyFetch.h"
11 #include "ImapCommandTable.h"
12 #include "ImapConnectionSetup.h"
13 #include "ImapLineReader.h"
14 #include "ImapMutationCommands.h"
15 #include "ImapPushSession.h"
16
17 // S92.1.2: the command table reaches the push session, mutation tracking,
18 // the failure path and the E2E phase reporting of this service.
19 1401 std::unique_ptr<ImapCommandTable> ImapService::createCommandTable() {
20 1401 ImapCommandTable::Deps deps;
21 2740 deps.isIdling = [this] { return m_push->isIdling(); };
22 2675 deps.isNotifying = [this] { return m_push->isNotifying(); };
23 1883 deps.idleStartPending = [this] { return m_push->idleStartPending(); };
24 1403 deps.startIdle = [this] { m_push->startIdle(); };
25 1413 deps.stopIdle = [this] { m_push->stopIdle(); };
26 2809 deps.failConnection = [this](const QString &error, DisconnectReason reason) {
27 7 failConnection(error, reason);
28 1401 };
29 2806 deps.completeMutation = [this](qint64 token, MutationOutcome outcome,
30 const QString &error) {
31
1/1
✓ Branch 4 → 5 taken 4 times.
4 m_mutations->completeMutation(token, outcome, error);
32 1405 };
33 #ifdef MAILJD_E2E_TESTING
34 1377 deps.reportE2eTransportPhase = [this](const QString &phase, quint64 requestToken) {
35 393 reportE2eTransportPhase(phase, requestToken);
36 492 };
37 1377 deps.e2eRequestTokenFor = [this](const ImapPendingCommand &command) {
38 393 return e2eRequestTokenFor(command);
39 492 };
40 #endif
41 ✗ return std::make_unique<ImapCommandTable>(this, m_socket, m_selectedFolder,
42
2/2
✓ Branch 11 → 12 taken 909 times.
✓ Branch 13 → 14 taken 492 times.
2802 std::move(deps));
43 1401 }
44
45 // S92.1.3: connection setup changes the service state, fails the session and
46 // checks the reader's buffer before the TLS handshake.
47 1401 std::unique_ptr<ImapConnectionSetup> ImapService::createConnectionSetup() {
48 1401 ImapConnectionSetup::Deps deps;
49 1671 deps.setState = [this](State state) { setState(state); };
50 2818 deps.failConnection = [this](const QString &error, DisconnectReason reason) {
51 16 failConnection(error, reason);
52 1401 };
53 1404 deps.readBufferEmpty = [this] { return m_reader->readBuffer().isEmpty(); };
54 #ifdef MAILJD_E2E_TESTING
55 1117 deps.reportE2eTransportPhase = [this](const QString &phase, quint64 requestToken) {
56 133 reportE2eTransportPhase(phase, requestToken);
57 492 };
58 #endif
59 1401 return std::make_unique<ImapConnectionSetup>(this, m_socket, *m_commands, m_capabilities,
60
2/2
✓ Branch 8 → 9 taken 909 times.
✓ Branch 9 → 10 taken 492 times.
4203 std::move(deps));
61 1401 }
62
63 // S92.1.4: the push session changes the service state, fails the session and
64 // asks the service for the negotiated IDLE/NOTIFY capabilities.
65 1401 std::unique_ptr<ImapPushSession> ImapService::createPushSession() {
66 1401 ImapPushSession::Deps deps;
67 1429 deps.setState = [this](State state) { setState(state); };
68 2811 deps.failConnection = [this](const QString &error, DisconnectReason reason) {
69 9 failConnection(error, reason);
70 1401 };
71 1498 deps.hasIdleCapability = [this] { return hasIdleCapability(); };
72 1409 deps.hasNotifyCapability = [this] { return hasNotifyCapability(); };
73 1604 deps.quietMs = [this] { return m_reader->quietMs(); };
74 #ifdef MAILJD_E2E_TESTING
75 1012 deps.reportE2eTransportPhase = [this](const QString &phase, quint64 requestToken) {
76 28 reportE2eTransportPhase(phase, requestToken);
77 492 };
78 #endif
79 1401 return std::make_unique<ImapPushSession>(this, m_socket, *m_commands, m_state,
80
2/2
✓ Branch 10 → 11 taken 909 times.
✓ Branch 11 → 12 taken 492 times.
4203 std::move(deps));
81 1401 }
82
83 // S92.1.5: body fetches emit the service's body signals; the selected
84 // mailbox stays with the service.
85 1401 std::unique_ptr<ImapBodyFetch> ImapService::createBodyFetch() {
86 1401 ImapBodyFetch::Deps deps;
87 2824 deps.bodyRequestCompleted = [this](const BodyResult &result) {
88 22 emit bodyRequestCompleted(result);
89 1401 };
90 2808 deps.bodyMailboxSelected = [this](quint64 requestId, bool success) {
91 6 emit bodyMailboxSelected(requestId, success);
92 1401 };
93 1401 deps.errorOccurred = [this](const QString &error) { emit errorOccurred(error); };
94 return std::make_unique<ImapBodyFetch>(
95 1401 this, *m_commands, *m_push, m_state,
96 ✗ ImapBodyFetch::SelectedMailbox{m_selectedFolder,
97 1401 m_selectedMessageCount, m_selectedUidValidity,
98 1401 m_selectedHighestModseq},
99
1/1
✓ Branch 9 → 10 taken 1401 times.
4203 std::move(deps));
100 1401 }
101
102 // S92.1.6: mutation commands emit the service's mutation and move signals;
103 // the selected mailbox and capabilities stay with the service.
104 1401 std::unique_ptr<ImapMutationCommands> ImapService::createMutationCommands() {
105 1401 ImapMutationCommands::Deps deps;
106 1413 deps.storeComplete = [this] { emit storeComplete(); };
107 1457 deps.mutationDispatched = [this](qint64 token) { emit mutationDispatched(token); };
108 2881 deps.mutationCompleted = [this](qint64 token, MutationOutcome outcome,
109 const QString &error, const QString &uidPlusEvidence) {
110 79 emit mutationCompleted(token, outcome, error, uidPlusEvidence);
111 1401 };
112 2836 deps.messageMoved = [this](qint64 uid, const QString &targetFolder) {
113 34 emit messageMoved(uid, targetFolder);
114 1401 };
115 2822 deps.messagesMoved = [this](const QList<qint64> &uids, const QString &targetFolder) {
116 20 emit messagesMoved(uids, targetFolder);
117 1401 };
118 2806 deps.messageCopied = [this](qint64 uid, const QString &targetFolder) {
119 4 emit messageCopied(uid, targetFolder);
120 1401 };
121 1417 deps.moveError = [this](const QString &error) { emit moveError(error); };
122 1407 deps.expungeComplete = [this] { emit expungeComplete(); };
123 1406 deps.expungeFailed = [this](const QString &error) { emit expungeFailed(error); };
124 1406 deps.errorOccurred = [this](const QString &error) { emit errorOccurred(error); };
125 1401 return std::make_unique<ImapMutationCommands>(*m_commands, *m_push, m_state,
126 1401 m_selectedFolder, m_selectedUidValidity,
127
1/1
✓ Branch 16 → 17 taken 1401 times.
4203 m_capabilities, std::move(deps));
128 1401 }
129
130 // S92.1.7: the APPEND stream fails the session and emits the service's
131 // APPEND signals.
132 1401 std::unique_ptr<ImapAppendStream> ImapService::createAppendStream() {
133 1401 ImapAppendStream::Deps deps;
134 1401 deps.failConnection = [this](const QString &error) { failConnection(error); };
135 2832 deps.messageAppended = [this](const QString &folder, qint64 uid) {
136 30 emit messageAppended(folder, uid);
137 1401 };
138 1413 deps.appendError = [this](const QString &error) { emit appendError(error); };
139 2832 deps.appendCompleted = [this](quint64 requestId, const QString &folder, qint64 uid, quint32 uidValidity) {
140 30 emit appendCompleted(requestId, folder, uid, uidValidity);
141 1401 };
142 2814 deps.appendFailed = [this](quint64 requestId, const QString &error) {
143 12 emit appendFailed(requestId, error);
144 1401 };
145 #ifdef MAILJD_E2E_TESTING
146 1004 deps.reportE2eTransportPhase = [this](const QString &phase, quint64 requestToken) {
147 20 reportE2eTransportPhase(phase, requestToken);
148 492 };
149 #endif
150 1401 return std::make_unique<ImapAppendStream>(this, m_socket, *m_commands, *m_push,
151
2/2
✓ Branch 12 → 13 taken 909 times.
✓ Branch 13 → 14 taken 492 times.
4203 *m_mutations, m_state, std::move(deps));
152 1401 }
153
154 // S92.1.1: the line reader dispatches complete lines to this service and
155 // completes body requests through it; the active body request stays here.
156 1401 std::unique_ptr<ImapLineReader> ImapService::createLineReader() {
157 1401 ImapLineReader::Deps deps;
158 101788 deps.handleUntagged = [this](const QString &line) { handleUntagged(line); };
159 1714 deps.handleTagged = [this](const QString &line) { handleTagged(line); };
160 1432 deps.handleContinuation = [this](const QString &line) { m_append->handleContinuation(line); };
161 1403 deps.failConnection = [this](const QString &error) { failConnection(error); };
162 2843 deps.completeBodyRequest = [this](BodyOutcome outcome, QByteArray bytes,
163 const QString &error, qint64 maxBytes) {
164
1/1
✓ Branch 5 → 6 taken 41 times.
41 m_body->completeBodyRequest(outcome, std::move(bytes), error, maxBytes);
165 1442 };
166 2838 deps.rawBodyReceived = [this](qint64 uid, const QByteArray &rawBody) {
167 36 emit rawBodyReceived(uid, rawBody);
168 1401 };
169 2806 deps.bodyFetchTooLarge = [this](qint64 uid, qint64 maxBytes) {
170 4 emit bodyFetchTooLarge(uid, maxBytes);
171 1401 };
172 4448 deps.nowMs = [this] { return m_nowMs(); };
173 #ifdef MAILJD_E2E_TESTING
174 1008 deps.reportE2eTransportPhase = [this](const QString &phase, quint64 requestToken) {
175 24 reportE2eTransportPhase(phase, requestToken);
176 492 };
177 #endif
178 return std::make_unique<ImapLineReader>(
179 2802 m_socket, *m_commands,
180 2802 ImapLineReader::BodyRequest{m_body->activeBodyFetchUid(), m_body->activeBodyFetchLimit(),
181 1401 m_body->activeBodyFetchRequestBytes(),
182 1401 m_body->bodyFetchRequiresSelect(),
183 1401 m_body->activeBodyRequestId()},
184
2/2
✓ Branch 23 → 24 taken 909 times.
✓ Branch 24 → 25 taken 492 times.
4203 std::move(deps));
185 1401 }
186