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% 198 / 0 / 198
Functions: 100.0% 22 / 0 / 22
Branches: 78.5% 252 / 0 / 321

service/MailDisplayReadService.cpp
Line Branch Exec Source
1 #include "MailDisplayReadService.h"
2 #include "performance/MailOpenPerformanceTracker.h"
3 #include "data/MailCache.h"
4 #include <QCoreApplication>
5 #include <QFutureWatcher>
6 #include <QtConcurrent>
7
8
3/3
✓ Branch 3 → 4 taken 45 times.
✓ Branch 4 → 5 taken 45 times.
✓ Branch 5 → 6 taken 45 times.
45 MailDisplayReadService::MailDisplayReadService(QObject *parent) : QObject(parent) {
9
1/1
✓ Branch 10 → 11 taken 45 times.
45 m_pool.setMaxThreadCount(1);
10
1/1
✓ Branch 11 → 12 taken 45 times.
45 m_pool.setExpiryTimeout(-1);
11
1/1
✓ Branch 12 → 13 taken 45 times.
45 m_countPool.setMaxThreadCount(1);
12
1/1
✓ Branch 13 → 14 taken 45 times.
45 m_countPool.setExpiryTimeout(-1);
13
1/1
✓ Branch 14 → 15 taken 45 times.
45 m_displayPool.setMaxThreadCount(1);
14
1/1
✓ Branch 15 → 16 taken 45 times.
45 m_displayPool.setExpiryTimeout(-1);
15
1/1
✓ Branch 17 → 18 taken 45 times.
45 connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
16 46 this, [this] { stop(); });
17 45 }
18
19 81 MailDisplayReadService::~MailDisplayReadService() { stop(); }
20
21 namespace {
22 QPointer<MailDisplayReadService> sharedMailDisplayReadService;
23 // S106-120: runs first in ~QCoreApplication, while Qt's SQL and plugin state
24 // still exists — aboutToQuit misses a process that ends without the event
25 // loop, and the application-child deletion came only after that state was
26 // gone, with a worker possibly inside QSqlDatabase::open (the crash fixed
27 // for MailSelectionMutationService).
28 } // namespace
29
30 34 void MailDisplayReadService::stopSharedBeforeTeardown() {
31
1/2
✓ Branch 3 → 4 taken 34 times.
✗ Branch 3 → 6 not taken.
34 if (sharedMailDisplayReadService) sharedMailDisplayReadService->stop();
32 34 }
33
34 19266 MailDisplayReadService *MailDisplayReadService::shared() {
35
2/2
✓ Branch 3 → 4 taken 34 times.
✓ Branch 3 → 11 taken 19232 times.
19266 if (!sharedMailDisplayReadService) {
36
3/6
✓ Branch 6 → 7 taken 34 times.
✓ Branch 7 → 8 taken 34 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 34 times.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
34 sharedMailDisplayReadService = new MailDisplayReadService(QCoreApplication::instance());
37 34 qAddPostRoutine(stopSharedBeforeTeardown);
38 }
39 19266 return sharedMailDisplayReadService;
40 }
41
42 80 void MailDisplayReadService::stop() {
43 80 m_stopping = true;
44 80 m_pending.clear();
45
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 80 times.
80 if (m_active) m_active->cancelled->store(true);
46
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 80 times.
80 if (m_countActive) m_countActive->cancelled->store(true);
47
2/2
✓ Branch 14 → 15 taken 6 times.
✓ Branch 14 → 18 taken 74 times.
80 if (m_displayActive) m_displayActive->cancelled->store(true);
48
1/1
✓ Branch 19 → 20 taken 80 times.
80 m_pool.waitForDone();
49
1/1
✓ Branch 21 → 22 taken 80 times.
80 m_countPool.waitForDone();
50
1/1
✓ Branch 23 → 24 taken 80 times.
80 m_displayPool.waitForDone();
51 80 }
52
53 19337 void MailDisplayReadService::cancel(QObject *owner) {
54
6/6
✓ Branch 3 → 4 taken 1934 times.
✓ Branch 3 → 8 taken 17403 times.
✓ Branch 6 → 7 taken 82 times.
✓ Branch 6 → 8 taken 1852 times.
✓ Branch 9 → 10 taken 82 times.
✓ Branch 9 → 13 taken 19255 times.
19337 if (m_active && m_active->owner == owner) m_active->cancelled->store(true);
55
6/6
✓ Branch 14 → 15 taken 115 times.
✓ Branch 14 → 19 taken 19222 times.
✓ Branch 17 → 18 taken 6 times.
✓ Branch 17 → 19 taken 109 times.
✓ Branch 20 → 21 taken 6 times.
✓ Branch 20 → 24 taken 19331 times.
19337 if (m_countActive && m_countActive->owner == owner)
56 6 m_countActive->cancelled->store(true);
57
6/6
✓ Branch 25 → 26 taken 3174 times.
✓ Branch 25 → 30 taken 16163 times.
✓ Branch 28 → 29 taken 510 times.
✓ Branch 28 → 30 taken 2664 times.
✓ Branch 31 → 32 taken 510 times.
✓ Branch 31 → 35 taken 18827 times.
19337 if (m_displayActive && m_displayActive->owner == owner)
58 510 m_displayActive->cancelled->store(true);
59 19337 m_pending.removeIf([owner](const Request &request) {
60
4/4
✓ Branch 3 → 4 taken 823 times.
✓ Branch 3 → 6 taken 11 times.
✓ Branch 5 → 6 taken 171 times.
✓ Branch 5 → 7 taken 652 times.
834 return !request.owner || request.owner == owner;
61 });
62 19337 }
63
64 1286 void MailDisplayReadService::read(QObject *owner, const QString &databasePath,
65 const MailId &mailId, Callback callback,
66 MailDisplaySnapshot::PreferredContent preferred) {
67
1/1
✓ Branch 4 → 5 taken 1286 times.
1286 enqueue(owner, databasePath, mailId, 0, std::move(callback), preferred);
68 1286 }
69
70 23 void MailDisplayReadService::navigate(QObject *owner, const QString &databasePath,
71 const MailId &mailId, int direction, Callback callback,
72 const MailSortOrder &sort) {
73
4/4
✓ Branch 2 → 3 taken 12 times.
✓ Branch 2 → 20 taken 11 times.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 20 taken 11 times.
23 if (direction != -1 && direction != 1) {
74 1 cancel(owner);
75
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 19 not taken.
1 if (owner) {
76 1 MailDisplaySnapshot result;
77 1 result.error = QStringLiteral("Invalid navigation direction");
78
1/1
✓ Branch 15 → 16 taken 1 time.
1 callback(std::move(result));
79 1 }
80 1 return;
81 }
82
1/1
✓ Branch 22 → 23 taken 22 times.
22 enqueue(owner, databasePath, mailId, direction, std::move(callback),
83 MailDisplaySnapshot::PreferredContent::Auto, sort);
84 }
85
86 1308 void MailDisplayReadService::enqueue(QObject *owner, const QString &databasePath,
87 const MailId &mailId, int direction, Callback callback,
88 MailDisplaySnapshot::PreferredContent preferred,
89 const MailSortOrder &sort) {
90 1308 cancel(owner);
91
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1307 times.
1308 if (!owner) return;
92 1307 int queuedDisplays = 0;
93
4/4
✓ Branch 5 → 6 taken 1307 times.
✓ Branch 6 → 7 taken 1307 times.
✓ Branch 14 → 8 taken 50 times.
✓ Branch 14 → 15 taken 1307 times.
1357 for (const auto &request : m_pending)
94
2/2
✓ Branch 10 → 11 taken 38 times.
✓ Branch 10 → 12 taken 12 times.
50 if (!request.page) ++queuedDisplays;
95
4/4
✓ Branch 16 → 17 taken 1289 times.
✓ Branch 16 → 21 taken 18 times.
✓ Branch 18 → 19 taken 1288 times.
✓ Branch 18 → 21 taken 1 time.
2596 if (m_stopping || queuedDisplays >= MaxDisplayPending ||
96
5/6
✓ Branch 15 → 16 taken 1307 times.
✗ Branch 15 → 21 not taken.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 22 taken 1287 times.
✓ Branch 23 → 24 taken 20 times.
✓ Branch 23 → 31 taken 1287 times.
3903 databasePath.size() > 4096 || mailId.accountId.size() > 4096) {
97 20 MailDisplaySnapshot result;
98 20 result.outcome = MailDisplaySnapshot::Outcome::Busy;
99
1/1
✓ Branch 27 → 28 taken 20 times.
20 callback(std::move(result));
100 20 return;
101 20 }
102 // P90.7 trace: a display read waiting behind the active SQL read opens
103 // a queue span; the dispatch closes it. GUI-thread only, so the probe
104 // state is race-free.
105
5/6
✓ Branch 32 → 33 taken 344 times.
✓ Branch 32 → 36 taken 943 times.
✓ Branch 34 → 35 taken 344 times.
✗ Branch 34 → 36 not taken.
✓ Branch 37 → 38 taken 344 times.
✓ Branch 37 → 40 taken 943 times.
1287 if (m_displayActive && mailId.isValid())
106 344 MailJD::Performance::MailOpenPerformanceTracker::instance().sqlQueued(mailId);
107 1287 m_pending.append({owner, databasePath, mailId, {},
108
0/2
✗ Branch 71 → 72 not taken.
✗ Branch 71 → 73 not taken.
2574 [callback = std::move(callback), mailId](Result result) mutable {
109
1/2
✓ Branch 3 → 4 taken 806 times.
✗ Branch 3 → 6 not taken.
806 if (mailId.isValid())
110 806 MailJD::Performance::MailOpenPerformanceTracker::instance()
111 806 .snapshotHandoff(mailId);
112
2/2
✓ Branch 7 → 8 taken 806 times.
✓ Branch 9 → 10 taken 806 times.
806 callback(std::get<MailDisplaySnapshot>(std::move(result)));
113 806 }, direction, preferred});
114 1287 m_pending.last().sort = sort;
115 1287 startNext();
116 2574 }
117
118 961 void MailDisplayReadService::readHeaderPage(QObject *owner, QString databasePath,
119 MailHeaderPageRequest page, PageCallback callback,
120 PagePriority priority) {
121
1/1
✓ Branch 2 → 3 taken 961 times.
961 cancel(owner);
122
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 960 times.
968 if (!owner) return;
123 // Status/count work may be dropped under load; reserve two queue positions
124 // for foreground pages so a background burst cannot reject a user click.
125
2/2
✓ Branch 5 → 6 taken 25 times.
✓ Branch 5 → 7 taken 935 times.
960 const int pendingLimit = priority == PagePriority::Background ? MaxPending - 2 : MaxPending;
126
5/6
✓ Branch 10 → 11 taken 959 times.
✓ Branch 10 → 17 taken 1 time.
✓ Branch 12 → 13 taken 958 times.
✓ Branch 12 → 17 taken 1 time.
✓ Branch 14 → 15 taken 958 times.
✗ Branch 14 → 17 not taken.
1918 if (m_stopping || m_pending.size() >= pendingLimit || databasePath.size() > 4096 ||
127
4/6
✓ Branch 8 → 9 taken 960 times.
✗ Branch 8 → 17 not taken.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 958 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 32 taken 958 times.
2878 page.account.size() > 4096 || page.folder.size() > 4096) {
128 2 MailHeaderPageSnapshot result;
129 2 result.outcome = MailHeaderPageSnapshot::Outcome::Busy;
130 2 result.error = QStringLiteral("Cache reader is busy or the page identity exceeds its budget");
131
1/1
✓ Branch 28 → 29 taken 2 times.
2 callback(std::move(result));
132 2 return;
133 2 }
134
4/4
✓ Branch 35 → 36 taken 957 times.
✓ Branch 35 → 47 taken 1 time.
✓ Branch 37 → 38 taken 956 times.
✓ Branch 37 → 47 taken 1 time.
1916 if (databasePath.isEmpty() || page.account.isEmpty() || page.folder.isEmpty() ||
135
4/4
✓ Branch 38 → 39 taken 955 times.
✓ Branch 38 → 47 taken 1 time.
✓ Branch 39 → 40 taken 954 times.
✓ Branch 39 → 47 taken 1 time.
956 page.folderId <= 0 || page.anchorUid < 0 ||
136
2/4
✓ Branch 41 → 42 taken 29 times.
✗ Branch 41 → 47 not taken.
✓ Branch 42 → 43 taken 29 times.
✗ Branch 42 → 47 not taken.
29 (page.countsOnly ? (!page.includeCounts || page.limit != 0 ||
137
2/4
✓ Branch 43 → 44 taken 29 times.
✗ Branch 43 → 47 not taken.
✓ Branch 44 → 46 taken 29 times.
✗ Branch 44 → 47 not taken.
29 page.anchorUid != 0 || page.anchoredRestore)
138
6/8
✓ Branch 33 → 34 taken 958 times.
✗ Branch 33 → 47 not taken.
✓ Branch 40 → 41 taken 29 times.
✓ Branch 40 → 45 taken 925 times.
✓ Branch 45 → 46 taken 925 times.
✗ Branch 45 → 47 not taken.
✓ Branch 49 → 50 taken 5 times.
✓ Branch 49 → 62 taken 953 times.
2870 : page.limit <= 0) ||
139
2/2
✓ Branch 46 → 47 taken 1 time.
✓ Branch 46 → 48 taken 953 times.
954 page.limit > MailHeaderPageSnapshot::MaximumRows) {
140 5 MailHeaderPageSnapshot result;
141 5 result.error = QStringLiteral("Invalid cached header page request");
142
1/1
✓ Branch 58 → 59 taken 5 times.
5 callback(std::move(result));
143 5 return;
144 5 }
145 2859 Request request{owner, std::move(databasePath), {}, std::move(page),
146 953 [callback = std::move(callback)](Result result) mutable {
147
2/2
✓ Branch 3 → 4 taken 834 times.
✓ Branch 5 → 6 taken 834 times.
834 callback(std::get<MailHeaderPageSnapshot>(std::move(result)));
148
3/13
✓ Branch 62 → 63 taken 953 times.
✓ Branch 69 → 70 taken 953 times.
✓ Branch 70 → 71 taken 953 times.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
✗ Branch 97 → 98 not taken.
✗ Branch 97 → 99 not taken.
✗ Branch 100 → 101 not taken.
✗ Branch 100 → 102 not taken.
✗ Branch 103 → 104 not taken.
✗ Branch 103 → 105 not taken.
✗ Branch 106 → 107 not taken.
✗ Branch 106 → 108 not taken.
2740 }};
149 953 request.priority = priority;
150
1/1
✓ Branch 73 → 74 taken 953 times.
953 m_pending.append(std::move(request));
151
1/1
✓ Branch 74 → 75 taken 953 times.
953 startNext();
152 953 }
153
154 4292 void MailDisplayReadService::startNext() {
155
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 4292 times.
4292 if (m_stopping) return;
156 6914 m_pending.removeIf([](const Request &request) { return !request.owner; });
157 4292 startLane(Lane::Display);
158 4292 startLane(Lane::Page);
159 4292 startLane(Lane::Counts);
160 }
161
162 12876 void MailDisplayReadService::startLane(Lane lane) {
163
4/4
✓ Branch 2 → 3 taken 4292 times.
✓ Branch 2 → 4 taken 8584 times.
✓ Branch 4 → 5 taken 4292 times.
✓ Branch 4 → 6 taken 4292 times.
12876 auto &active = lane == Lane::Display ? m_displayActive
164 : lane == Lane::Counts ? m_countActive : m_active;
165
2/2
✓ Branch 9 → 10 taken 1644 times.
✓ Branch 9 → 11 taken 11232 times.
22051 if (active) return;
166 11232 int next = -1;
167
2/2
✓ Branch 40 → 12 taken 3870 times.
✓ Branch 40 → 41 taken 9217 times.
13087 for (int i = 0; i < m_pending.size(); ++i) {
168
1/1
✓ Branch 12 → 13 taken 3870 times.
3870 const auto &request = m_pending[i];
169
2/2
✓ Branch 14 → 15 taken 2168 times.
✓ Branch 14 → 20 taken 1702 times.
6038 const Lane requestLane = !request.page ? Lane::Display
170
2/2
✓ Branch 16 → 17 taken 82 times.
✓ Branch 16 → 18 taken 2086 times.
2168 : request.page->countsOnly ? Lane::Counts : Lane::Page;
171
2/2
✓ Branch 21 → 22 taken 1813 times.
✓ Branch 21 → 23 taken 2057 times.
3870 if (requestLane != lane) continue;
172
2/2
✓ Branch 23 → 24 taken 1129 times.
✓ Branch 23 → 34 taken 928 times.
2057 if (lane == Lane::Display) {
173 // A selected body must not wait behind a queued header-only navigation.
174
2/9
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 28 taken 1129 times.
✗ Branch 25 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 29 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 29 not taken.
✓ Branch 30 → 31 taken 1129 times.
✗ Branch 30 → 32 not taken.
1129 if (next < 0 || (m_pending[next].direction != 0 && request.direction == 0))
175 1129 next = i;
176
2/2
✓ Branch 32 → 33 taken 1107 times.
✓ Branch 32 → 38 taken 22 times.
1129 if (request.direction == 0) break;
177 } else {
178
1/2
✓ Branch 34 → 35 taken 928 times.
✗ Branch 34 → 36 not taken.
928 if (next < 0) next = i;
179
2/2
✓ Branch 36 → 37 taken 908 times.
✓ Branch 36 → 38 taken 20 times.
928 if (request.priority == PagePriority::Foreground) break;
180 }
181 }
182
2/2
✓ Branch 41 → 42 taken 9175 times.
✓ Branch 41 → 43 taken 2057 times.
11232 if (next < 0) return;
183
1/1
✓ Branch 43 → 44 taken 2057 times.
2057 active = m_pending.takeAt(next);
184
5/6
✓ Branch 46 → 47 taken 1129 times.
✓ Branch 46 → 51 taken 928 times.
✓ Branch 49 → 50 taken 1129 times.
✗ Branch 49 → 51 not taken.
✓ Branch 52 → 53 taken 1129 times.
✓ Branch 52 → 56 taken 928 times.
2057 if (lane == Lane::Display && active->mailId.isValid())
185
1/1
✓ Branch 53 → 54 taken 1129 times.
1129 MailJD::Performance::MailOpenPerformanceTracker::instance()
186
1/1
✓ Branch 55 → 56 taken 1129 times.
1129 .sqlDispatched(active->mailId);
187
2/2
✓ Branch 58 → 59 taken 1107 times.
✓ Branch 58 → 63 taken 22 times.
1129 const auto trace = lane == Lane::Display && active->direction == 0
188
3/3
✓ Branch 56 → 57 taken 1129 times.
✓ Branch 56 → 63 taken 928 times.
✓ Branch 59 → 60 taken 1107 times.
3164 ? MailJD::Performance::MailOpenPerformanceTracker::instance()
189 1107 .operationFor(active->mailId)
190
1/1
✓ Branch 61 → 62 taken 1107 times.
2057 : MailJD::Performance::Operation{};
191
2/4
✓ Branch 64 → 65 taken 2057 times.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 73 taken 2057 times.
✗ Branch 69 → 70 not taken.
2057 if (trace.isValid()) trace.startPhase(QStringLiteral("worker_queue"));
192
3/6
✓ Branch 73 → 74 taken 2057 times.
✓ Branch 74 → 75 taken 2057 times.
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 2057 times.
✗ Branch 122 → 123 not taken.
✗ Branch 122 → 124 not taken.
2057 auto *watcher = new QFutureWatcher<Result>(this);
193
1/1
✓ Branch 78 → 79 taken 2057 times.
2057 connect(watcher, &QFutureWatcher<Result>::finished, this,
194 4114 [this, watcher, lane, trace] {
195
2/2
✓ Branch 2 → 3 taken 1126 times.
✓ Branch 2 → 4 taken 928 times.
2982 auto &active = lane == Lane::Display ? m_displayActive
196
2/2
✓ Branch 4 → 5 taken 24 times.
✓ Branch 4 → 6 taken 904 times.
928 : lane == Lane::Counts ? m_countActive : m_active;
197 2054 auto request = std::move(*active);
198 2054 active.reset();
199 // Each lane produces one snapshot. Remove it from the future before the
200 // GUI handoff so a large body is not retained by the watcher as well as
201 // the reader while the watcher awaits deleteLater().
202
2/2
✓ Branch 12 → 13 taken 2054 times.
✓ Branch 13 → 14 taken 2054 times.
2054 auto result = watcher->future().takeResult();
203
2/4
✓ Branch 15 → 16 taken 2054 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 24 taken 2054 times.
✗ Branch 20 → 21 not taken.
2054 if (trace.isValid()) trace.endPhase(QStringLiteral("snapshot_handoff"));
204
1/1
✓ Branch 24 → 25 taken 2054 times.
2054 watcher->deleteLater();
205
1/1
✓ Branch 25 → 26 taken 2054 times.
2054 QPointer<MailDisplayReadService> guard(this);
206
7/8
✓ Branch 26 → 27 taken 2054 times.
✗ Branch 26 → 33 not taken.
✓ Branch 28 → 29 taken 1935 times.
✓ Branch 28 → 33 taken 119 times.
✓ Branch 31 → 32 taken 1640 times.
✓ Branch 31 → 33 taken 295 times.
✓ Branch 34 → 35 taken 1640 times.
✓ Branch 34 → 40 taken 414 times.
2054 if (!m_stopping && request.owner && !request.cancelled->load())
207
1/1
✓ Branch 37 → 38 taken 1640 times.
1640 request.callback(std::move(result));
208
3/3
✓ Branch 41 → 42 taken 2052 times.
✓ Branch 41 → 43 taken 2 times.
✓ Branch 42 → 43 taken 2052 times.
2054 if (guard) startNext();
209 2054 });
210 2057 const auto databasePath = active->databasePath;
211 2057 const auto mailId = active->mailId;
212
1/1
✓ Branch 86 → 87 taken 2057 times.
2057 const auto page = active->page;
213 2057 const auto cancelled = active->cancelled;
214 2057 const int direction = active->direction;
215 2057 const auto preferred = active->preferred;
216 2057 const auto sort = active->sort;
217
2/2
✓ Branch 92 → 93 taken 1129 times.
✓ Branch 92 → 94 taken 928 times.
2985 auto *pool = lane == Lane::Display ? &m_displayPool
218
2/2
✓ Branch 94 → 95 taken 24 times.
✓ Branch 94 → 96 taken 904 times.
928 : lane == Lane::Counts ? &m_countPool : &m_pool;
219
3/11
✓ Branch 100 → 101 taken 2057 times.
✓ Branch 103 → 104 taken 2057 times.
✓ Branch 104 → 105 taken 2057 times.
✗ Branch 133 → 134 not taken.
✗ Branch 133 → 135 not taken.
✗ Branch 136 → 137 not taken.
✗ Branch 136 → 138 not taken.
✗ Branch 139 → 140 not taken.
✗ Branch 139 → 141 not taken.
✗ Branch 142 → 143 not taken.
✗ Branch 142 → 144 not taken.
2057 watcher->setFuture(QtConcurrent::run(pool, [databasePath, mailId, page, cancelled, direction, preferred, sort, trace]() -> Result {
220
6/6
✓ Branch 3 → 4 taken 928 times.
✓ Branch 3 → 5 taken 1129 times.
✓ Branch 7 → 8 taken 1129 times.
✓ Branch 7 → 9 taken 928 times.
✓ Branch 9 → 10 taken 928 times.
✓ Branch 9 → 11 taken 1129 times.
2057 Result result = page ? Result(MailHeaderPageSnapshot{}) : Result(MailDisplaySnapshot{});
221
2/4
✓ Branch 11 → 12 taken 2057 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 20 taken 2057 times.
✗ Branch 16 → 17 not taken.
2057 if (trace.isValid()) trace.endPhase(QStringLiteral("worker_queue"));
222 3180 const auto handoff = [&trace](Result ready) -> Result {
223
1/3
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 1123 times.
✗ Branch 7 → 8 not taken.
1123 if (trace.isValid()) trace.startPhase(QStringLiteral("snapshot_handoff"));
224 1123 return ready;
225 2057 };
226
2/2
✓ Branch 22 → 23 taken 4 times.
✓ Branch 22 → 25 taken 2053 times.
2057 if (cancelled->load()) return result;
227 // P90.8: the read-only connection is bound to this pool thread and
228 // reused across requests; only a database-path change reopens it. The
229 // per-request SQLite open disappears from the display path.
230
2/2
✓ Branch 25 → 26 taken 56 times.
✓ Branch 25 → 27 taken 1997 times.
2053 static thread_local std::unique_ptr<MailCache> reader;
231
2/2
✓ Branch 27 → 28 taken 56 times.
✓ Branch 27 → 29 taken 1997 times.
2053 static thread_local QString readerPath;
232
4/4
✓ Branch 30 → 31 taken 1994 times.
✓ Branch 30 → 33 taken 59 times.
✓ Branch 32 → 33 taken 1113 times.
✓ Branch 32 → 34 taken 881 times.
2053 const bool reopen = !reader || readerPath != databasePath;
233
7/7
✓ Branch 35 → 36 taken 1172 times.
✓ Branch 35 → 39 taken 881 times.
✓ Branch 37 → 38 taken 1113 times.
✓ Branch 37 → 39 taken 59 times.
✓ Branch 40 → 41 taken 1113 times.
✓ Branch 40 → 44 taken 940 times.
✓ Branch 42 → 43 taken 1113 times.
2053 if (reopen && reader) { reader->close(); reader.reset(); }
234
2/2
✓ Branch 45 → 46 taken 1172 times.
✓ Branch 45 → 80 taken 881 times.
2053 if (!reader) {
235
2/4
✓ Branch 46 → 47 taken 1172 times.
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 55 taken 1172 times.
✗ Branch 51 → 52 not taken.
1172 if (trace.isValid()) trace.startPhase(QStringLiteral("sqlite_open"));
236
1/1
✓ Branch 55 → 56 taken 1172 times.
1172 reader = std::make_unique<MailCache>();
237
1/1
✓ Branch 59 → 60 taken 1172 times.
1172 const bool opened = reader->openReadOnly(databasePath);
238
2/4
✓ Branch 60 → 61 taken 1172 times.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 69 taken 1172 times.
✗ Branch 65 → 66 not taken.
1172 if (trace.isValid()) trace.endPhase(QStringLiteral("sqlite_open"));
239
2/2
✓ Branch 69 → 70 taken 6 times.
✓ Branch 69 → 79 taken 1166 times.
1172 if (!opened) {
240
3/3
MailDisplayReadService::startLane(MailDisplayReadService::Lane)::{lambda()#2}::operator()() const:
✓ Branch 70 → 71 taken 6 times.
auto MailDisplayReadService::startLane(MailDisplayReadService::Lane)::{lambda()#2}::operator()() const::{lambda(auto:1&)#1}::operator()<MailDisplaySnapshot>(MailDisplaySnapshot&) const:
✓ Branch 3 → 4 taken 5 times.
auto MailDisplayReadService::startLane(MailDisplayReadService::Lane)::{lambda()#2}::operator()() const::{lambda(auto:1&)#1}::operator()<MailHeaderPageSnapshot>(MailHeaderPageSnapshot&) const:
✓ Branch 3 → 4 taken 1 time.
12 std::visit([&](auto &value) { value.error = reader->lastError(); }, result);
241 6 reader.reset();
242 6 readerPath.clear();
243
1/1
✓ Branch 75 → 76 taken 6 times.
6 return handoff(std::move(result));
244 }
245 1166 readerPath = databasePath;
246 }
247
2/2
✓ Branch 82 → 83 taken 7 times.
✓ Branch 82 → 84 taken 2040 times.
2047 if (cancelled->load()) return result;
248
3/3
✓ Branch 85 → 86 taken 923 times.
✓ Branch 85 → 93 taken 1117 times.
✓ Branch 89 → 90 taken 923 times.
2040 if (page) return reader->headerPageSnapshot(*page, cancelled.get());
249
2/4
✓ Branch 93 → 94 taken 1117 times.
✗ Branch 94 → 95 not taken.
✓ Branch 94 → 102 taken 1117 times.
✗ Branch 98 → 99 not taken.
1117 if (trace.isValid()) trace.startPhase(QStringLiteral("snapshot_query"));
250
3/3
✓ Branch 102 → 103 taken 19 times.
✓ Branch 102 → 105 taken 1098 times.
✓ Branch 104 → 109 taken 19 times.
2234 result = direction ? reader->navigationSnapshot(mailId.accountId, mailId.folderId, mailId.uid, direction < 0, sort)
251
1/1
✓ Branch 108 → 109 taken 1098 times.
2196 : reader->snapshots().displaySnapshot(mailId.accountId, mailId.folderId, mailId.uid,
252 2215 preferred, cancelled.get());
253
2/4
✓ Branch 111 → 112 taken 1117 times.
✗ Branch 112 → 113 not taken.
✓ Branch 112 → 120 taken 1117 times.
✗ Branch 116 → 117 not taken.
1117 if (trace.isValid()) trace.endPhase(QStringLiteral("snapshot_query"));
254
1/1
✓ Branch 122 → 123 taken 1117 times.
1117 return handoff(std::move(result));
255 2057 }));
256 2057 }
257