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: 97.3% 362 / 0 / 372
Functions: 97.0% 32 / 0 / 33
Branches: 81.3% 436 / 0 / 536

performance/BackgroundPerformanceTracker.cpp
Line Branch Exec Source
1 #include "performance/BackgroundPerformanceTracker.h"
2
3 #include <QApplication>
4 #include <QDir>
5 #include <QEvent>
6 #include <QFile>
7 #include <QFileInfo>
8 #include <QJsonDocument>
9 #include <QJsonObject>
10 #include <QSet>
11 #include <QTimer>
12 #include <QWidget>
13
14 #include <algorithm>
15
16 namespace MailJD::Performance {
17
18 namespace {
19 constexpr auto RowMetric = "realtime.server_to_row.v1";
20 constexpr auto BadgeMetric = "realtime.server_to_badge.v1";
21 constexpr auto NotificationMetric = "realtime.server_to_notification.v1";
22 constexpr auto SettledMetric = "realtime.server_to_settled.v1";
23 constexpr auto AnchorFileName = "realtime-anchor.json";
24 constexpr auto SyncMetric = "sync.total.v1";
25 constexpr auto ThroughputMetric = "sync.items_per_second.v1";
26 constexpr auto MaintenanceMetric = "maintenance.total.v1";
27 constexpr auto ShutdownMetric = "shutdown.input_to_durable_terminal.v1";
28 constexpr auto ContentionBackgroundMetric =
29 "contention.background_throughput.v1";
30 constexpr auto ContentionStallMetric = "contention.event_loop_stall.v1";
31 constexpr auto ContentionBusyMetric = "contention.sqlite_busy.v1";
32 constexpr int EventLoopProbeIntervalMs = 50;
33 constexpr qint64 MaximumAnchorAgeNs = 15LL * 60LL * 1000LL * 1000LL * 1000LL;
34
35 const QSet<QString> AllowedAnchorFields = {
36 QStringLiteral("schema_version"),
37 QStringLiteral("run_id"),
38 QStringLiteral("scenario"),
39 QStringLiteral("server_accepted_monotonic_ns"),
40 QStringLiteral("item_count"),
41 };
42 } // namespace
43
44 3003 BackgroundPerformanceTracker &BackgroundPerformanceTracker::instance() {
45
4/7
✓ Branch 2 → 3 taken 25 times.
✓ Branch 2 → 8 taken 2978 times.
✓ Branch 4 → 5 taken 25 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 25 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
3003 static BackgroundPerformanceTracker tracker;
46 3003 return tracker;
47 }
48
49 25 BackgroundPerformanceTracker::BackgroundPerformanceTracker(QObject *parent)
50
1/1
✓ Branch 12 → 13 taken 25 times.
25 : QObject(parent) {
51
1/1
✓ Branch 13 → 14 taken 25 times.
25 m_eventLoopProbe.setTimerType(Qt::PreciseTimer);
52
1/1
✓ Branch 14 → 15 taken 25 times.
25 m_eventLoopProbe.setInterval(EventLoopProbeIntervalMs);
53 25 connect(&m_eventLoopProbe, &QTimer::timeout, this,
54
1/1
✓ Branch 15 → 16 taken 25 times.
25 &BackgroundPerformanceTracker::probeEventLoop);
55 25 }
56
57 27 bool BackgroundPerformanceTracker::isRealtimeActive() const {
58
4/4
✓ Branch 2 → 3 taken 27 times.
✓ Branch 3 → 4 taken 27 times.
✓ Branch 4 → 5 taken 25 times.
✓ Branch 4 → 13 taken 2 times.
77 return PerformanceTrace::instance().isEnabled() &&
59
5/7
✓ Branch 5 → 6 taken 25 times.
✓ Branch 6 → 7 taken 25 times.
✓ Branch 10 → 11 taken 25 times.
✓ Branch 11 → 12 taken 23 times.
✓ Branch 11 → 13 taken 2 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
77 PerformanceTrace::instance().selectedScenario().startsWith(
60
6/10
✓ Branch 14 → 15 taken 25 times.
✓ Branch 14 → 16 taken 2 times.
✓ Branch 16 → 17 taken 25 times.
✓ Branch 16 → 18 taken 2 times.
✓ Branch 18 → 19 taken 25 times.
✓ Branch 18 → 20 taken 2 times.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
79 QStringLiteral("REALTIME."));
61 }
62
63 10 void BackgroundPerformanceTracker::ensureEventFilterInstalled() {
64
5/6
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 6 taken 9 times.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 11 taken 9 times.
10 if (!m_eventFilterInstalled && qApp) {
65 1 qApp->installEventFilter(this);
66 1 m_eventFilterInstalled = true;
67 }
68 10 }
69
70 3 void BackgroundPerformanceTracker::watchMailViewport(QWidget *viewport) {
71 3 m_mailViewport = viewport;
72
1/2
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 6 not taken.
3 if (isRealtimeActive())
73 3 ensureEventFilterInstalled();
74 3 }
75
76 3 void BackgroundPerformanceTracker::watchBadgeViewport(QWidget *viewport) {
77 3 m_badgeViewport = viewport;
78
1/2
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 6 not taken.
3 if (isRealtimeActive())
79 3 ensureEventFilterInstalled();
80 3 }
81
82 28 void BackgroundPerformanceTracker::reset() {
83
4/8
✓ Branch 3 → 4 taken 28 times.
✗ Branch 3 → 10 not taken.
✓ Branch 5 → 6 taken 28 times.
✗ Branch 5 → 10 not taken.
✓ Branch 7 → 8 taken 28 times.
✗ Branch 7 → 10 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 28 times.
56 if (m_row.isValid() || m_badge.isValid() || m_notification.isValid() ||
84
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 28 times.
28 m_settled.isValid())
85 ✗ failAll(Outcome::Cancelled);
86 28 m_scenario.clear();
87 28 m_expectedCount = 0;
88 28 m_fetchedCount = 0;
89 28 m_appendedCount = 0;
90 28 m_notificationCount = 0;
91 28 m_repaintCount = 0;
92 28 m_rowPaintPending = false;
93 28 m_badgePaintPending = false;
94 28 m_rowPainted = false;
95 28 m_badgePainted = false;
96 28 m_notificationAccepted = false;
97 28 m_settleScheduled = false;
98 28 ++m_generation;
99 28 resetBackground();
100 28 }
101
102 1537 bool BackgroundPerformanceTracker::isBackgroundActive() const {
103
4/4
✓ Branch 2 → 3 taken 1537 times.
✓ Branch 3 → 4 taken 1537 times.
✓ Branch 4 → 5 taken 1496 times.
✓ Branch 4 → 6 taken 41 times.
1537 if (!PerformanceTrace::instance().isEnabled())
104 1496 return false;
105
2/2
✓ Branch 6 → 7 taken 41 times.
✓ Branch 7 → 8 taken 41 times.
41 const QString selected = PerformanceTrace::instance().selectedScenario();
106
4/9
✓ Branch 11 → 12 taken 41 times.
✓ Branch 12 → 13 taken 17 times.
✓ Branch 12 → 18 taken 24 times.
✓ Branch 26 → 27 taken 41 times.
✗ Branch 26 → 28 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 39 → 41 not taken.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
140 return selected.startsWith(QStringLiteral("SYNC_MAINT.")) ||
107
8/13
✓ Branch 16 → 17 taken 17 times.
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 15 times.
✓ Branch 20 → 21 taken 17 times.
✓ Branch 20 → 22 taken 24 times.
✓ Branch 22 → 23 taken 17 times.
✓ Branch 22 → 24 taken 24 times.
✓ Branch 24 → 25 taken 41 times.
✗ Branch 24 → 26 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 37 not taken.
58 selected.startsWith(QStringLiteral("CONTENTION."));
108 41 }
109
110 1537 bool BackgroundPerformanceTracker::selectedOperationMatches(
111 const QStringList &operations) const {
112
3/3
✓ Branch 2 → 3 taken 1537 times.
✓ Branch 3 → 4 taken 1511 times.
✓ Branch 3 → 5 taken 26 times.
1537 if (!isBackgroundActive())
113 1511 return false;
114
2/2
✓ Branch 5 → 6 taken 26 times.
✓ Branch 6 → 7 taken 26 times.
26 const QString selected = PerformanceTrace::instance().selectedScenario();
115
1/1
✓ Branch 9 → 10 taken 26 times.
26 return std::any_of(operations.cbegin(), operations.cend(),
116 34 [&selected](const QString &operation) {
117
1/1
✓ Branch 10 → 11 taken 34 times.
136 return selected.contains(QStringLiteral(".") +
118
1/1
✓ Branch 8 → 9 taken 34 times.
68 operation +
119
1/1
✓ Branch 9 → 10 taken 34 times.
136 QStringLiteral("."));
120 26 });
121 26 }
122
123 1537 void BackgroundPerformanceTracker::beginBackground(
124 const QStringList &operations, qint64 startNs, qint64 itemCount,
125 qint64 byteCount) {
126
8/8
✓ Branch 2 → 3 taken 1537 times.
✓ Branch 3 → 4 taken 24 times.
✓ Branch 3 → 6 taken 1513 times.
✓ Branch 4 → 5 taken 24 times.
✓ Branch 5 → 6 taken 9 times.
✓ Branch 5 → 7 taken 15 times.
✓ Branch 8 → 9 taken 1522 times.
✓ Branch 8 → 10 taken 15 times.
1537 if (!selectedOperationMatches(operations) || m_background.isValid())
127 1522 return;
128
2/2
✓ Branch 10 → 11 taken 15 times.
✓ Branch 11 → 12 taken 15 times.
15 const QString scenario = PerformanceTrace::instance().selectedScenario();
129
1/1
✓ Branch 15 → 16 taken 15 times.
15 const QString operation = scenario.section(QLatin1Char('.'), 1, 1);
130
3/3
✓ Branch 19 → 20 taken 15 times.
✓ Branch 22 → 23 taken 2 times.
✓ Branch 22 → 28 taken 13 times.
15 if (scenario.startsWith(QStringLiteral("CONTENTION."))) {
131
1/1
✓ Branch 24 → 25 taken 2 times.
2 m_backgroundMetric = QString::fromLatin1(ContentionBackgroundMetric);
132
3/3
✓ Branch 31 → 32 taken 13 times.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 34 → 40 taken 12 times.
13 } else if (operation.startsWith(QStringLiteral("shutdown_"))) {
133
1/1
✓ Branch 36 → 37 taken 1 time.
1 m_backgroundMetric = QString::fromLatin1(ShutdownMetric);
134
5/6
✓ Branch 49 → 50 taken 10 times.
✓ Branch 49 → 75 taken 1 time.
✓ Branch 103 → 104 taken 12 times.
✗ Branch 103 → 105 not taken.
✓ Branch 105 → 106 taken 7 times.
✓ Branch 105 → 111 taken 5 times.
35 } else if (operation == QStringLiteral("fts_rebuild") ||
135
5/6
✓ Branch 54 → 55 taken 9 times.
✓ Branch 54 → 75 taken 1 time.
✓ Branch 99 → 100 taken 11 times.
✓ Branch 99 → 101 taken 1 time.
✓ Branch 101 → 102 taken 12 times.
✗ Branch 101 → 103 not taken.
33 operation == QStringLiteral("fts_incremental") ||
136
6/6
✓ Branch 59 → 60 taken 8 times.
✓ Branch 59 → 75 taken 1 time.
✓ Branch 95 → 96 taken 10 times.
✓ Branch 95 → 97 taken 2 times.
✓ Branch 97 → 98 taken 11 times.
✓ Branch 97 → 99 taken 1 time.
31 operation == QStringLiteral("predictor_initial") ||
137
6/6
✓ Branch 64 → 65 taken 7 times.
✓ Branch 64 → 75 taken 1 time.
✓ Branch 91 → 92 taken 9 times.
✓ Branch 91 → 93 taken 3 times.
✓ Branch 93 → 94 taken 10 times.
✓ Branch 93 → 95 taken 2 times.
29 operation == QStringLiteral("predictor_incremental") ||
138
6/6
✓ Branch 69 → 70 taken 6 times.
✓ Branch 69 → 75 taken 1 time.
✓ Branch 87 → 88 taken 8 times.
✓ Branch 87 → 89 taken 4 times.
✓ Branch 89 → 90 taken 9 times.
✓ Branch 89 → 91 taken 3 times.
27 operation == QStringLiteral("migration") ||
139
8/8
✓ Branch 44 → 45 taken 11 times.
✓ Branch 44 → 75 taken 1 time.
✓ Branch 74 → 75 taken 1 time.
✓ Branch 74 → 76 taken 5 times.
✓ Branch 83 → 84 taken 7 times.
✓ Branch 83 → 85 taken 5 times.
✓ Branch 85 → 86 taken 8 times.
✓ Branch 85 → 87 taken 4 times.
54 operation == QStringLiteral("wal_checkpoint") ||
140
6/6
✓ Branch 77 → 78 taken 6 times.
✓ Branch 77 → 79 taken 6 times.
✓ Branch 79 → 80 taken 6 times.
✓ Branch 79 → 81 taken 6 times.
✓ Branch 81 → 82 taken 7 times.
✓ Branch 81 → 83 taken 5 times.
18 operation == QStringLiteral("payload_eviction")) {
141
1/1
✓ Branch 107 → 108 taken 7 times.
7 m_backgroundMetric = QString::fromLatin1(MaintenanceMetric);
142 } else {
143
1/1
✓ Branch 112 → 113 taken 5 times.
5 m_backgroundMetric = QString::fromLatin1(SyncMetric);
144 }
145 15 m_backgroundStartedNs =
146
3/3
✓ Branch 116 → 117 taken 6 times.
✓ Branch 116 → 119 taken 9 times.
✓ Branch 117 → 118 taken 6 times.
15 startNs >= 0 ? startNs : PerformanceTrace::monotonicNowNs();
147 15 m_backgroundItems = 0;
148 15 m_backgroundBytes = 0;
149 15 m_sqliteBusyNs = 0;
150 15 m_maxEventLoopDelayNs = 0;
151 15 m_backgroundClients = 0;
152 15 m_finishedBackgroundClients = 0;
153 15 m_backgroundFailed = false;
154 15 m_backgroundQueueClosed = false;
155
1/1
✓ Branch 120 → 121 taken 15 times.
30 m_background = PerformanceTrace::instance().startMetric(
156
1/1
✓ Branch 121 → 122 taken 15 times.
15 scenario, m_backgroundMetric, m_backgroundStartedNs, itemCount,
157 15 byteCount);
158
1/1
✓ Branch 127 → 128 taken 15 times.
30 m_background.startPhase(QStringLiteral("background_work"));
159
3/3
✓ Branch 133 → 134 taken 15 times.
✓ Branch 136 → 137 taken 13 times.
✓ Branch 136 → 185 taken 2 times.
15 if (scenario.startsWith(QStringLiteral("SYNC_MAINT."))) {
160 65 for (const QString &metric : {QString::fromLatin1(SyncMetric),
161 13 QString::fromLatin1(ThroughputMetric),
162 13 QString::fromLatin1(MaintenanceMetric),
163
6/10
✓ Branch 138 → 139 taken 13 times.
✓ Branch 140 → 141 taken 13 times.
✓ Branch 142 → 143 taken 13 times.
✓ Branch 144 → 145 taken 13 times.
✓ Branch 177 → 148 taken 52 times.
✓ Branch 177 → 178 taken 13 times.
✗ Branch 230 → 231 not taken.
✗ Branch 230 → 234 not taken.
✗ Branch 232 → 233 not taken.
✗ Branch 232 → 234 not taken.
130 QString::fromLatin1(ShutdownMetric)}) {
164
4/4
✓ Branch 149 → 150 taken 39 times.
✓ Branch 149 → 158 taken 13 times.
✓ Branch 153 → 154 taken 15 times.
✓ Branch 153 → 159 taken 24 times.
106 if (metric == m_backgroundMetric ||
165
5/7
✓ Branch 151 → 152 taken 39 times.
✓ Branch 157 → 158 taken 5 times.
✓ Branch 157 → 159 taken 10 times.
✓ Branch 164 → 165 taken 18 times.
✓ Branch 164 → 166 taken 34 times.
✗ Branch 240 → 241 not taken.
✗ Branch 240 → 242 not taken.
106 (m_backgroundMetric == QString::fromLatin1(SyncMetric) &&
166
5/7
✓ Branch 155 → 156 taken 15 times.
✓ Branch 160 → 161 taken 15 times.
✓ Branch 160 → 162 taken 37 times.
✓ Branch 162 → 163 taken 39 times.
✓ Branch 162 → 164 taken 13 times.
✗ Branch 235 → 236 not taken.
✗ Branch 235 → 237 not taken.
67 metric == QString::fromLatin1(ThroughputMetric)))
167 18 continue;
168
2/2
✓ Branch 166 → 167 taken 34 times.
✓ Branch 171 → 172 taken 34 times.
68 PerformanceTrace::instance().markProcessEvent(
169
1/1
✓ Branch 170 → 171 taken 34 times.
68 scenario, metric + QStringLiteral(".inapplicable"));
170 65 }
171 }
172 15 m_probeExpectedNs = m_backgroundStartedNs +
173 static_cast<qint64>(EventLoopProbeIntervalMs) * 1000000;
174
1/1
✓ Branch 185 → 186 taken 15 times.
15 m_eventLoopProbe.start();
175 15 }
176
177 2194 void BackgroundPerformanceTracker::backgroundPhaseStarted(
178 const QString &phase) {
179
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 2191 times.
2194 if (m_background.isValid())
180 3 m_background.startPhase(phase);
181 2194 }
182
183 1432 void BackgroundPerformanceTracker::backgroundPhaseFinished(const QString &phase,
184 qint64 itemCount,
185 qint64 byteCount) {
186
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 1429 times.
1432 if (m_background.isValid())
187 3 m_background.endPhase(phase, itemCount, byteCount);
188 1432 }
189
190 775 void BackgroundPerformanceTracker::addBackgroundWork(qint64 itemCount,
191 qint64 byteCount) {
192
2/2
✓ Branch 3 → 4 taken 764 times.
✓ Branch 3 → 5 taken 11 times.
775 if (!m_background.isValid())
193 764 return;
194 11 m_backgroundItems += std::max<qint64>(0, itemCount);
195 11 m_backgroundBytes += std::max<qint64>(0, byteCount);
196 }
197
198 4 void BackgroundPerformanceTracker::backgroundClientQueued() {
199
5/6
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 6 taken 2 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 9 taken 2 times.
4 if (m_background.isValid() && !m_backgroundQueueClosed)
200 2 ++m_backgroundClients;
201 4 }
202
203 3 void BackgroundPerformanceTracker::backgroundQueueClosed() {
204
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 2 times.
3 if (!m_background.isValid())
205 1 return;
206 2 m_backgroundQueueClosed = true;
207
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 13 taken 1 time.
2 if (m_backgroundClients == 0) {
208
1/1
✓ Branch 9 → 10 taken 1 time.
1 backgroundPhaseFinished(QStringLiteral("dav_sync"));
209 1 backgroundFinished(false);
210 }
211 }
212
213 2 void BackgroundPerformanceTracker::backgroundClientFailed() {
214
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
2 if (m_background.isValid())
215 1 m_backgroundFailed = true;
216 2 }
217
218 4 void BackgroundPerformanceTracker::backgroundClientFinished() {
219
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 2 times.
4 if (!m_background.isValid())
220 2 return;
221 2 ++m_finishedBackgroundClients;
222
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 14 not taken.
2 if (m_backgroundQueueClosed &&
223
2/2
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 14 taken 1 time.
2 m_finishedBackgroundClients >= m_backgroundClients) {
224
1/1
✓ Branch 10 → 11 taken 1 time.
1 backgroundPhaseFinished(QStringLiteral("dav_sync"));
225 1 backgroundFinished(!m_backgroundFailed);
226 }
227 }
228
229 2 void BackgroundPerformanceTracker::addSqliteBusyTime(qint64 durationNs) {
230
1/2
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 6 not taken.
2 if (m_background.isValid())
231 2 m_sqliteBusyNs += std::max<qint64>(0, durationNs);
232 2 }
233
234 1 void BackgroundPerformanceTracker::probeEventLoop() {
235
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 1 time.
1 if (!m_background.isValid()) {
236 ✗ m_eventLoopProbe.stop();
237 ✗ return;
238 }
239 1 const qint64 now = PerformanceTrace::monotonicNowNs();
240 3 m_maxEventLoopDelayNs = std::max(
241 1 m_maxEventLoopDelayNs, std::max<qint64>(0, now - m_probeExpectedNs));
242 1 m_probeExpectedNs =
243 1 now + static_cast<qint64>(EventLoopProbeIntervalMs) * 1000000;
244 }
245
246 769 void BackgroundPerformanceTracker::backgroundFinished(bool success) {
247
3/3
✓ Branch 2 → 3 taken 769 times.
✓ Branch 3 → 4 taken 755 times.
✓ Branch 3 → 5 taken 14 times.
769 if (!m_background.isValid())
248 755 return;
249
1/1
✓ Branch 5 → 6 taken 14 times.
14 m_eventLoopProbe.stop();
250
2/2
✓ Branch 6 → 7 taken 14 times.
✓ Branch 7 → 8 taken 14 times.
14 const QString scenario = PerformanceTrace::instance().selectedScenario();
251 14 const qint64 totalNs = std::max<qint64>(
252
1/1
✓ Branch 8 → 9 taken 14 times.
14 0, PerformanceTrace::monotonicNowNs() - m_backgroundStartedNs);
253
1/1
✓ Branch 13 → 14 taken 14 times.
28 m_background.endPhase(QStringLiteral("background_work"), m_backgroundItems,
254 m_backgroundBytes);
255
8/13
✓ Branch 19 → 20 taken 14 times.
✓ Branch 20 → 21 taken 12 times.
✓ Branch 20 → 26 taken 2 times.
✓ Branch 24 → 25 taken 4 times.
✓ Branch 24 → 26 taken 8 times.
✓ Branch 31 → 32 taken 14 times.
✗ Branch 31 → 33 not taken.
✓ Branch 33 → 34 taken 4 times.
✓ Branch 33 → 40 taken 10 times.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 83 not taken.
✗ Branch 85 → 86 not taken.
✗ Branch 85 → 87 not taken.
54 if (scenario.startsWith(QStringLiteral("SYNC_MAINT.")) &&
256
4/7
✓ Branch 22 → 23 taken 12 times.
✓ Branch 27 → 28 taken 12 times.
✓ Branch 27 → 29 taken 2 times.
✓ Branch 29 → 30 taken 14 times.
✗ Branch 29 → 31 not taken.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
26 m_backgroundMetric == QString::fromLatin1(SyncMetric)) {
257
2/2
✓ Branch 34 → 35 taken 4 times.
✓ Branch 37 → 38 taken 4 times.
8 PerformanceTrace::instance().markProcessEvent(
258
1/1
✓ Branch 36 → 37 taken 4 times.
8 scenario, QString::fromLatin1(ThroughputMetric), -1, totalNs,
259 m_backgroundItems, m_backgroundBytes);
260 }
261
3/3
✓ Branch 43 → 44 taken 14 times.
✓ Branch 46 → 47 taken 2 times.
✓ Branch 46 → 58 taken 12 times.
14 if (scenario.startsWith(QStringLiteral("CONTENTION."))) {
262
2/2
✓ Branch 47 → 48 taken 2 times.
✓ Branch 50 → 51 taken 2 times.
4 PerformanceTrace::instance().markProcessEvent(
263
1/1
✓ Branch 49 → 50 taken 2 times.
4 scenario, QString::fromLatin1(ContentionStallMetric), -1,
264 m_maxEventLoopDelayNs);
265
2/2
✓ Branch 52 → 53 taken 2 times.
✓ Branch 55 → 56 taken 2 times.
4 PerformanceTrace::instance().markProcessEvent(
266
1/1
✓ Branch 54 → 55 taken 2 times.
4 scenario, QString::fromLatin1(ContentionBusyMetric), -1,
267 m_sqliteBusyNs);
268 }
269
3/3
✓ Branch 58 → 59 taken 7 times.
✓ Branch 58 → 60 taken 7 times.
✓ Branch 61 → 62 taken 14 times.
14 m_background.finish(success ? Outcome::Success : Outcome::Failed,
270 m_backgroundItems, m_backgroundBytes);
271 14 m_background = {};
272 14 m_backgroundMetric.clear();
273 14 m_backgroundStartedNs = 0;
274 14 }
275
276 28 void BackgroundPerformanceTracker::resetBackground() {
277 28 m_eventLoopProbe.stop();
278
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 27 times.
28 if (m_background.isValid())
279 1 m_background.finish(Outcome::Cancelled, m_backgroundItems,
280 m_backgroundBytes);
281 28 m_background = {};
282 28 m_backgroundMetric.clear();
283 28 m_backgroundStartedNs = 0;
284 28 m_backgroundItems = 0;
285 28 m_backgroundBytes = 0;
286 28 m_sqliteBusyNs = 0;
287 28 m_probeExpectedNs = 0;
288 28 m_maxEventLoopDelayNs = 0;
289 28 m_backgroundClients = 0;
290 28 m_finishedBackgroundClients = 0;
291 28 m_backgroundFailed = false;
292 28 m_backgroundQueueClosed = false;
293 28 }
294
295 13 bool BackgroundPerformanceTracker::beginFromAnchor(int observedCount) {
296
1/1
✓ Branch 2 → 3 taken 13 times.
13 auto &trace = PerformanceTrace::instance();
297
2/2
✓ Branch 3 → 4 taken 13 times.
✓ Branch 4 → 5 taken 13 times.
13 const QFileInfo traceInfo(trace.outputPath());
298
4/4
✓ Branch 6 → 7 taken 13 times.
✓ Branch 8 → 9 taken 13 times.
✓ Branch 9 → 10 taken 13 times.
✓ Branch 10 → 11 taken 13 times.
13 QFile file(traceInfo.dir().filePath(QString::fromLatin1(AnchorFileName)));
299
3/3
✓ Branch 15 → 16 taken 13 times.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 26 taken 12 times.
13 if (!file.open(QIODevice::ReadOnly)) {
300
2/2
✓ Branch 20 → 21 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
1 trace.markProcessEvent(trace.selectedScenario(),
301 2 QStringLiteral("realtime.anchor_missing"));
302 1 return false;
303 }
304 12 QJsonParseError parseError;
305 const QJsonDocument document =
306
2/2
✓ Branch 26 → 27 taken 12 times.
✓ Branch 27 → 28 taken 12 times.
12 QJsonDocument::fromJson(file.readAll(), &parseError);
307
7/7
✓ Branch 29 → 30 taken 11 times.
✓ Branch 29 → 32 taken 1 time.
✓ Branch 30 → 31 taken 11 times.
✓ Branch 31 → 32 taken 1 time.
✓ Branch 31 → 33 taken 10 times.
✓ Branch 34 → 35 taken 2 times.
✓ Branch 34 → 44 taken 10 times.
12 if (parseError.error != QJsonParseError::NoError || !document.isObject()) {
308
2/2
✓ Branch 38 → 39 taken 2 times.
✓ Branch 39 → 40 taken 2 times.
2 trace.markProcessEvent(trace.selectedScenario(),
309 4 QStringLiteral("realtime.anchor_invalid"));
310 2 return false;
311 }
312
1/1
✓ Branch 44 → 45 taken 10 times.
10 const QJsonObject object = document.object();
313
5/5
✓ Branch 45 → 46 taken 10 times.
✓ Branch 46 → 47 taken 10 times.
✓ Branch 47 → 48 taken 10 times.
✓ Branch 63 → 49 taken 47 times.
✓ Branch 63 → 64 taken 9 times.
56 for (const QString &key : object.keys()) {
314
2/2
✓ Branch 51 → 52 taken 1 time.
✓ Branch 51 → 61 taken 46 times.
47 if (!AllowedAnchorFields.contains(key)) {
315
2/2
✓ Branch 55 → 56 taken 1 time.
✓ Branch 56 → 57 taken 1 time.
1 trace.markProcessEvent(trace.selectedScenario(),
316 2 QStringLiteral("realtime.anchor_unsafe"));
317 1 return false;
318 }
319 10 }
320 const qint64 acceptedNs =
321
1/1
✓ Branch 71 → 73 taken 9 times.
18 object.value(QStringLiteral("server_accepted_monotonic_ns"))
322
1/1
✓ Branch 73 → 74 taken 9 times.
18 .toVariant()
323
1/1
✓ Branch 74 → 75 taken 9 times.
9 .toLongLong();
324
2/2
✓ Branch 82 → 83 taken 9 times.
✓ Branch 83 → 84 taken 9 times.
9 const int itemCount = object.value(QStringLiteral("item_count")).toInt(-1);
325
1/1
✓ Branch 87 → 88 taken 9 times.
9 const qint64 now = PerformanceTrace::monotonicNowNs();
326 const bool valid =
327
5/13
✓ Branch 91 → 92 taken 9 times.
✓ Branch 102 → 103 taken 7 times.
✓ Branch 102 → 117 taken 1 time.
✓ Branch 142 → 143 taken 9 times.
✗ Branch 142 → 144 not taken.
✓ Branch 144 → 145 taken 9 times.
✗ Branch 144 → 146 not taken.
✗ Branch 276 → 277 not taken.
✗ Branch 276 → 278 not taken.
✗ Branch 280 → 281 not taken.
✗ Branch 280 → 282 not taken.
✗ Branch 284 → 285 not taken.
✗ Branch 284 → 286 not taken.
34 object.value(QStringLiteral("schema_version")).toInt() == 1 &&
328
8/16
✓ Branch 99 → 100 taken 8 times.
✓ Branch 100 → 101 taken 8 times.
✓ Branch 130 → 131 taken 8 times.
✓ Branch 130 → 132 taken 1 time.
✓ Branch 132 → 133 taken 8 times.
✓ Branch 132 → 134 taken 1 time.
✓ Branch 134 → 135 taken 8 times.
✓ Branch 134 → 136 taken 1 time.
✗ Branch 252 → 253 not taken.
✗ Branch 252 → 254 not taken.
✗ Branch 256 → 257 not taken.
✗ Branch 256 → 258 not taken.
✗ Branch 260 → 261 not taken.
✗ Branch 260 → 262 not taken.
✗ Branch 264 → 265 not taken.
✗ Branch 264 → 266 not taken.
17 object.value(QStringLiteral("run_id")).toString() ==
329
9/14
✓ Branch 94 → 95 taken 8 times.
✓ Branch 95 → 96 taken 8 times.
✓ Branch 110 → 111 taken 6 times.
✓ Branch 110 → 117 taken 1 time.
✓ Branch 136 → 137 taken 8 times.
✓ Branch 136 → 138 taken 1 time.
✓ Branch 138 → 139 taken 8 times.
✓ Branch 138 → 140 taken 1 time.
✓ Branch 140 → 141 taken 9 times.
✗ Branch 140 → 142 not taken.
✗ Branch 268 → 269 not taken.
✗ Branch 268 → 270 not taken.
✗ Branch 272 → 273 not taken.
✗ Branch 272 → 274 not taken.
31 traceInfo.dir().dirName() &&
330
8/16
✓ Branch 107 → 108 taken 7 times.
✓ Branch 108 → 109 taken 7 times.
✓ Branch 120 → 121 taken 7 times.
✓ Branch 120 → 122 taken 2 times.
✓ Branch 122 → 123 taken 7 times.
✓ Branch 122 → 124 taken 2 times.
✓ Branch 124 → 125 taken 7 times.
✓ Branch 124 → 126 taken 2 times.
✗ Branch 232 → 233 not taken.
✗ Branch 232 → 234 not taken.
✗ Branch 236 → 237 not taken.
✗ Branch 236 → 238 not taken.
✗ Branch 240 → 241 not taken.
✗ Branch 240 → 242 not taken.
✗ Branch 244 → 245 not taken.
✗ Branch 244 → 246 not taken.
16 object.value(QStringLiteral("scenario")).toString() ==
331
7/9
✓ Branch 103 → 104 taken 7 times.
✓ Branch 111 → 112 taken 5 times.
✓ Branch 111 → 117 taken 1 time.
✓ Branch 126 → 127 taken 7 times.
✓ Branch 126 → 128 taken 2 times.
✓ Branch 128 → 129 taken 8 times.
✓ Branch 128 → 130 taken 1 time.
✗ Branch 248 → 249 not taken.
✗ Branch 248 → 250 not taken.
22 trace.selectedScenario() &&
332
2/2
✓ Branch 112 → 113 taken 4 times.
✓ Branch 112 → 117 taken 1 time.
5 acceptedNs > 0 && acceptedNs <= now &&
333
9/9
✓ Branch 92 → 93 taken 9 times.
✓ Branch 93 → 94 taken 8 times.
✓ Branch 93 → 117 taken 1 time.
✓ Branch 113 → 114 taken 3 times.
✓ Branch 113 → 117 taken 1 time.
✓ Branch 114 → 115 taken 2 times.
✓ Branch 114 → 117 taken 1 time.
✓ Branch 115 → 116 taken 1 time.
✓ Branch 115 → 117 taken 1 time.
26 now - acceptedNs <= MaximumAnchorAgeNs && itemCount > 0 &&
334
2/2
✓ Branch 118 → 119 taken 7 times.
✓ Branch 118 → 120 taken 2 times.
9 itemCount == observedCount;
335
2/2
✓ Branch 146 → 147 taken 8 times.
✓ Branch 146 → 156 taken 1 time.
9 if (!valid) {
336
2/2
✓ Branch 150 → 151 taken 8 times.
✓ Branch 151 → 152 taken 8 times.
8 trace.markProcessEvent(trace.selectedScenario(),
337 16 QStringLiteral("realtime.anchor_mismatch"));
338 8 return false;
339 }
340
1/1
✓ Branch 156 → 157 taken 1 time.
1 beginRealtimeDelivery(acceptedNs, itemCount);
341 1 return true;
342 13 }
343
344 14 void BackgroundPerformanceTracker::idleDeliveryObserved(int newCount) {
345
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 13 times.
14 if (!isRealtimeActive())
346 1 return;
347
4/8
✓ Branch 6 → 7 taken 13 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 13 times.
✗ Branch 8 → 13 not taken.
✓ Branch 10 → 11 taken 13 times.
✗ Branch 10 → 13 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 13 times.
26 if (m_row.isValid() || m_badge.isValid() || m_notification.isValid() ||
348
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 13 times.
13 m_settled.isValid()) {
349 ✗ failAll(Outcome::Cancelled);
350 }
351
2/2
✓ Branch 18 → 19 taken 12 times.
✓ Branch 18 → 20 taken 1 time.
13 if (!beginFromAnchor(newCount))
352 12 return;
353
1/1
✓ Branch 23 → 24 taken 1 time.
2 m_row.mark(QStringLiteral("client_idle_observed"), newCount);
354
1/1
✓ Branch 29 → 30 taken 1 time.
2 m_badge.mark(QStringLiteral("client_idle_observed"), newCount);
355
1/1
✓ Branch 35 → 36 taken 1 time.
2 m_notification.mark(QStringLiteral("client_idle_observed"), newCount);
356
1/1
✓ Branch 41 → 42 taken 1 time.
2 m_settled.mark(QStringLiteral("client_idle_observed"), newCount);
357 }
358
359 7 void BackgroundPerformanceTracker::beginRealtimeDelivery(
360 qint64 serverAcceptedNs, int expectedCount) {
361
6/8
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 6 taken 3 times.
✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 4 times.
✓ Branch 8 → 9 taken 3 times.
✓ Branch 8 → 10 taken 4 times.
7 if (!isRealtimeActive() || serverAcceptedNs <= 0 || expectedCount <= 0)
362 3 return;
363 4 reset();
364 4 ensureEventFilterInstalled();
365
2/2
✓ Branch 12 → 13 taken 4 times.
✓ Branch 13 → 14 taken 4 times.
4 m_scenario = PerformanceTrace::instance().selectedScenario();
366 4 m_expectedCount = expectedCount;
367
1/1
✓ Branch 16 → 17 taken 4 times.
8 m_row = PerformanceTrace::instance().startMetric(
368
2/2
✓ Branch 18 → 19 taken 4 times.
✓ Branch 19 → 20 taken 4 times.
8 m_scenario, QString::fromLatin1(RowMetric), serverAcceptedNs,
369 4 expectedCount);
370
1/1
✓ Branch 23 → 24 taken 4 times.
8 m_badge = PerformanceTrace::instance().startMetric(
371
2/2
✓ Branch 25 → 26 taken 4 times.
✓ Branch 26 → 27 taken 4 times.
8 m_scenario, QString::fromLatin1(BadgeMetric), serverAcceptedNs,
372 4 expectedCount);
373
1/1
✓ Branch 30 → 31 taken 4 times.
8 m_notification = PerformanceTrace::instance().startMetric(
374
2/2
✓ Branch 32 → 33 taken 4 times.
✓ Branch 33 → 34 taken 4 times.
8 m_scenario, QString::fromLatin1(NotificationMetric), serverAcceptedNs,
375 4 expectedCount);
376
1/1
✓ Branch 37 → 38 taken 4 times.
8 m_settled = PerformanceTrace::instance().startMetric(
377
2/2
✓ Branch 39 → 40 taken 4 times.
✓ Branch 40 → 41 taken 4 times.
8 m_scenario, QString::fromLatin1(SettledMetric), serverAcceptedNs,
378 4 expectedCount);
379 4 for (const Operation &operation :
380
2/2
✓ Branch 64 → 51 taken 16 times.
✓ Branch 64 → 65 taken 4 times.
40 {m_row, m_badge, m_notification, m_settled}) {
381
1/1
✓ Branch 54 → 55 taken 16 times.
32 operation.mark(QStringLiteral("server_accepted"), expectedCount);
382
1/1
✓ Branch 60 → 61 taken 16 times.
32 operation.startPhase(QStringLiteral("protocol_and_header_fetch"),
383 expectedCount);
384 20 }
385 }
386
387 20 void BackgroundPerformanceTracker::headersCommitted(int fetchedCount,
388 int appendedCount) {
389
8/8
✓ Branch 3 → 4 taken 7 times.
✓ Branch 3 → 6 taken 13 times.
✓ Branch 4 → 5 taken 6 times.
✓ Branch 4 → 6 taken 1 time.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 5 times.
✓ Branch 8 → 9 taken 15 times.
✓ Branch 8 → 10 taken 5 times.
20 if (!m_row.isValid() || fetchedCount <= 0 || appendedCount < 0)
390 15 return;
391 5 m_fetchedCount += fetchedCount;
392 5 m_appendedCount += appendedCount;
393
2/4
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 13 not taken.
✓ Branch 11 → 12 taken 5 times.
✗ Branch 11 → 13 not taken.
5 if (m_fetchedCount > m_expectedCount || m_appendedCount > m_expectedCount ||
394
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 15 taken 4 times.
5 m_fetchedCount != m_appendedCount) {
395 1 failAll(Outcome::Failed);
396 1 return;
397 }
398
2/2
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 17 taken 3 times.
4 if (m_fetchedCount < m_expectedCount)
399 1 return;
400 3 for (const Operation &operation :
401
2/2
✓ Branch 37 → 24 taken 12 times.
✓ Branch 37 → 38 taken 3 times.
30 {m_row, m_badge, m_notification, m_settled}) {
402
1/1
✓ Branch 27 → 28 taken 12 times.
12 operation.endPhase(QStringLiteral("protocol_and_header_fetch"),
403 12 m_fetchedCount);
404
1/1
✓ Branch 33 → 34 taken 12 times.
24 operation.mark(QStringLiteral("headers_committed"), m_fetchedCount);
405 15 }
406
1/1
✓ Branch 47 → 48 taken 3 times.
6 m_row.startPhase(QStringLiteral("row_paint"));
407
1/1
✓ Branch 53 → 54 taken 3 times.
6 m_settled.startPhase(QStringLiteral("visible_settle"));
408 3 m_rowPaintPending = true;
409
2/2
✓ Branch 57 → 58 taken 2 times.
✓ Branch 57 → 60 taken 1 time.
3 if (m_mailViewport)
410 2 m_mailViewport->update();
411 }
412
413 7 void BackgroundPerformanceTracker::badgeCommitted() {
414
2/2
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 7 taken 2 times.
13 if (!m_badge.isValid() || m_fetchedCount != m_expectedCount ||
415
7/8
✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 7 taken 1 time.
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 7 taken 1 time.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 3 times.
✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 11 taken 3 times.
13 m_badgePaintPending || m_badgePainted)
416 4 return;
417
1/1
✓ Branch 14 → 15 taken 3 times.
6 m_badge.startPhase(QStringLiteral("badge_paint"));
418 3 m_badgePaintPending = true;
419
2/2
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 21 taken 1 time.
3 if (m_badgeViewport)
420 2 m_badgeViewport->update();
421 }
422
423 7 void BackgroundPerformanceTracker::notificationCommitted(int representedCount,
424 bool accepted) {
425
6/6
✓ Branch 3 → 4 taken 5 times.
✓ Branch 3 → 5 taken 2 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 4 times.
✓ Branch 7 → 8 taken 3 times.
✓ Branch 7 → 9 taken 4 times.
7 if (!m_notification.isValid() || representedCount <= 0)
426 3 return;
427
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 4 times.
4 if (!accepted) {
428 ✗ failAll(Outcome::Failed);
429 ✗ return;
430 }
431 4 m_notificationCount += representedCount;
432
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 15 taken 3 times.
4 if (m_notificationCount > m_expectedCount) {
433 1 failAll(Outcome::Failed);
434 1 return;
435 }
436
2/2
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 27 taken 1 time.
3 if (m_notificationCount == m_expectedCount) {
437
1/1
✓ Branch 19 → 20 taken 2 times.
2 m_notification.mark(QStringLiteral("notification_service_accepted"),
438 2 m_notificationCount);
439 2 m_notification.finish(Outcome::Success, m_expectedCount);
440 2 m_notification = {};
441 2 m_notificationAccepted = true;
442 2 maybeScheduleSettled();
443 }
444 }
445
446 ✗ void BackgroundPerformanceTracker::failRealtimeDelivery() {
447 ✗ failAll(Outcome::Failed);
448 ✗ }
449
450 2 void BackgroundPerformanceTracker::failAll(Outcome outcome) {
451
2/2
✓ Branch 11 → 4 taken 8 times.
✓ Branch 11 → 12 taken 2 times.
10 for (Operation *operation : {&m_row, &m_badge, &m_notification, &m_settled}) {
452
3/3
✓ Branch 4 → 5 taken 8 times.
✓ Branch 5 → 6 taken 6 times.
✓ Branch 5 → 7 taken 2 times.
8 if (operation->isValid())
453
1/1
✓ Branch 6 → 7 taken 6 times.
6 operation->finish(outcome, m_expectedCount);
454 8 *operation = {};
455 }
456 2 m_rowPaintPending = false;
457 2 m_badgePaintPending = false;
458 2 m_settleScheduled = false;
459 2 ++m_generation;
460 2 }
461
462 8 void BackgroundPerformanceTracker::maybeScheduleSettled() {
463
3/4
✓ Branch 4 → 5 taken 8 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 6 times.
✓ Branch 5 → 8 taken 2 times.
16 if (!m_settled.isValid() || m_settleScheduled || !m_rowPainted ||
464
7/8
✓ Branch 3 → 4 taken 8 times.
✗ Branch 3 → 8 not taken.
✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 8 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 2 times.
✓ Branch 10 → 11 taken 6 times.
✓ Branch 10 → 12 taken 2 times.
16 !m_badgePainted || !m_notificationAccepted)
465 6 return;
466 2 m_settleScheduled = true;
467 2 const quint64 generation = ++m_generation;
468
1/1
✓ Branch 12 → 13 taken 2 times.
2 QTimer::singleShot(100, this, [this, generation]() {
469
3/6
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 2 times.
2 if (!m_settled.isValid() || generation != m_generation)
470 ✗ return;
471
1/1
✓ Branch 12 → 13 taken 2 times.
4 m_settled.endPhase(QStringLiteral("visible_settle"), m_repaintCount);
472
1/1
✓ Branch 18 → 19 taken 2 times.
4 m_settled.mark(QStringLiteral("settled_event_loop_turn"), m_repaintCount);
473 2 m_settled.finish(Outcome::Success, m_expectedCount);
474 2 m_settled = {};
475 2 m_settleScheduled = false;
476 });
477 }
478
479 40 bool BackgroundPerformanceTracker::eventFilter(QObject *watched,
480 QEvent *event) {
481
2/2
✓ Branch 3 → 4 taken 7 times.
✓ Branch 3 → 42 taken 33 times.
40 if (event->type() == QEvent::Paint) {
482
6/8
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 10 taken 4 times.
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 10 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 23 taken 4 times.
7 if (watched == m_mailViewport && m_rowPaintPending && m_row.isValid()) {
483 3 ++m_repaintCount;
484
1/1
✓ Branch 15 → 16 taken 3 times.
6 m_row.endPhase(QStringLiteral("row_paint"), m_expectedCount);
485 3 m_row.finish(Outcome::Success, m_expectedCount);
486 3 m_row = {};
487 3 m_rowPaintPending = false;
488 3 m_rowPainted = true;
489 3 maybeScheduleSettled();
490 }
491
5/6
✓ Branch 24 → 25 taken 3 times.
✓ Branch 24 → 29 taken 4 times.
✓ Branch 25 → 26 taken 3 times.
✗ Branch 25 → 29 not taken.
✓ Branch 30 → 31 taken 3 times.
✓ Branch 30 → 42 taken 4 times.
10 if (watched == m_badgeViewport && m_badgePaintPending &&
492
1/2
✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 29 not taken.
3 m_badge.isValid()) {
493 3 ++m_repaintCount;
494
1/1
✓ Branch 34 → 35 taken 3 times.
6 m_badge.endPhase(QStringLiteral("badge_paint"), m_expectedCount);
495 3 m_badge.finish(Outcome::Success, m_expectedCount);
496 3 m_badge = {};
497 3 m_badgePaintPending = false;
498 3 m_badgePainted = true;
499 3 maybeScheduleSettled();
500 }
501 }
502 40 return QObject::eventFilter(watched, event);
503 }
504
505 } // namespace MailJD::Performance
506