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: 20.8% 16 / 0 / 77
Functions: 40.0% 4 / 0 / 10
Branches: 8.3% 4 / 0 / 48

app/FtsIndexCoordinator.cpp
Line Branch Exec Source
1 #include "FtsIndexCoordinator.h"
2
3 #include <QThread>
4 #include <QTimer>
5
6 #include <algorithm>
7 #include <memory>
8 #include <utility>
9
10 820 FtsIndexCoordinator::FtsIndexCoordinator(RebuildJob rebuildJob,
11 QObject *parent,
12 820 QList<int> retryDelaysMs)
13 820 : QObject(parent), m_rebuildJob(std::move(rebuildJob)),
14 1640 m_retryDelaysMs(std::move(retryDelaysMs)) {}
15
16 1640 FtsIndexCoordinator::~FtsIndexCoordinator() { shutdown(); }
17
18 ✗ void FtsIndexCoordinator::requestRebuild() {
19 ✗ if (m_state == State::ShuttingDown)
20 ✗ return;
21 ✗ if (m_state == State::Queued || m_state == State::Running) {
22 ✗ ++m_coalescedRequests;
23 ✗ return;
24 }
25
26 ✗ m_terminalError.clear();
27 ✗ m_retriesScheduled = 0;
28 ✗ m_oldestRequest.start();
29 ✗ setState(State::Queued);
30 ✗ QTimer::singleShot(0, this, &FtsIndexCoordinator::startQueuedRebuild);
31 }
32
33 ✗ void FtsIndexCoordinator::startQueuedRebuild() {
34 ✗ if (m_state != State::Queued || m_worker)
35 ✗ return;
36
37 ✗ setState(State::Running);
38 ✗ auto result = std::make_shared<bool>(false);
39 ✗ const RebuildJob job = m_rebuildJob;
40 ✗ m_worker = QThread::create([job, result]() {
41 ✗ if (job)
42 ✗ *result = job();
43 ✗ });
44 ✗ connect(m_worker, &QThread::finished, this, [this, result]() {
45 ✗ QThread *finishedWorker = m_worker;
46 ✗ m_worker = nullptr;
47 ✗ if (m_state != State::ShuttingDown) {
48 ✗ if (*result) {
49 ✗ ++m_completionGeneration;
50 ✗ m_retriesScheduled = 0;
51 ✗ m_terminalError.clear();
52 ✗ setState(State::Ready);
53 ✗ emit rebuildFinished(true, m_completionGeneration);
54 ✗ } else if (m_retriesScheduled < m_retryDelaysMs.size()) {
55 const int delayMs =
56 ✗ std::max(0, m_retryDelaysMs.at(m_retriesScheduled));
57 ✗ ++m_retriesScheduled;
58 ✗ setState(State::Queued);
59 ✗ emit rebuildRetryScheduled(int(m_retriesScheduled + 1),
60 ✗ int(m_retryDelaysMs.size() + 1), delayMs);
61 ✗ QTimer::singleShot(delayMs, this,
62 ✗ &FtsIndexCoordinator::startQueuedRebuild);
63 } else {
64 ✗ m_terminalError = tr("FTS index rebuild failed");
65 ✗ setState(State::Failed);
66 ✗ emit rebuildFinished(false, m_completionGeneration);
67 }
68 }
69 // finished() is emitted just before the thread ends; deleting it before
70 // then aborts ("Destroyed while thread is still running").
71 ✗ finishedWorker->wait();
72 ✗ finishedWorker->deleteLater();
73 ✗ });
74 ✗ m_worker->start();
75 ✗ }
76
77 1640 void FtsIndexCoordinator::shutdown() {
78
2/2
✓ Branch 2 → 3 taken 820 times.
✓ Branch 2 → 4 taken 820 times.
1640 if (m_state == State::ShuttingDown)
79 820 return;
80 820 setState(State::ShuttingDown);
81
1/2
✓ Branch 5 → 6 taken 820 times.
✗ Branch 5 → 7 not taken.
820 if (!m_worker)
82 820 return;
83
84 ✗ QThread *worker = m_worker;
85 ✗ m_worker = nullptr;
86 ✗ disconnect(worker, nullptr, this, nullptr);
87 ✗ worker->requestInterruption();
88 ✗ worker->quit();
89 ✗ worker->wait();
90 ✗ delete worker;
91 }
92
93 ✗ int FtsIndexCoordinator::queueDepth() const {
94 ✗ return m_state == State::Queued || m_state == State::Running ? 1 : 0;
95 }
96
97 ✗ qint64 FtsIndexCoordinator::oldestAgeMs() const {
98 ✗ return queueDepth() > 0 && m_oldestRequest.isValid()
99 ✗ ? m_oldestRequest.elapsed()
100 ✗ : 0;
101 }
102
103 820 void FtsIndexCoordinator::setState(State state) {
104
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 820 times.
820 if (m_state == state)
105 ✗ return;
106 820 m_state = state;
107 820 emit stateChanged(state);
108 }
109