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% 69 / 0 / 69
Functions: 100.0% 8 / 0 / 8
Branches: 62.8% 86 / 0 / 137

app/SearchCoordinator.cpp
Line Branch Exec Source
1 #include "SearchCoordinator.h"
2
3 #include "app/SearchQuery.h"
4 #include "service/MailSearchReadService.h"
5
6
2/2
✓ Branch 3 → 4 taken 796 times.
✓ Branch 5 → 6 taken 796 times.
796 SearchCoordinator::SearchCoordinator(const Deps &deps, QObject *parent) : QObject(parent), m_d(deps) {}
7
8 1591 SearchCoordinator::~SearchCoordinator() {
9
1/2
✓ Branch 2 → 3 taken 796 times.
✗ Branch 2 → 4 not taken.
796 if (m_d.readService) m_d.readService->cancel(&m_previewOwner);
10 1591 }
11
12 9 int SearchCoordinator::adaptiveDebounceMs(qint64 msSincePreviousEdit) {
13
3/4
✓ Branch 2 → 3 taken 3 times.
✓ Branch 2 → 4 taken 6 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3 times.
9 if (msSincePreviousEdit < 0 || msSincePreviousEdit >= BurstQuietGapMs)
14 6 return PromptEditDebounceMs;
15 3 const qint64 shortfall = BurstQuietGapMs - msSincePreviousEdit;
16 3 return PromptEditDebounceMs + int((BurstDebounceCapMs - PromptEditDebounceMs) * shortfall / BurstQuietGapMs);
17 }
18
19 2080 void SearchCoordinator::cancelQuickResults() {
20 2080 ++m_previewGeneration;
21
1/2
✓ Branch 2 → 3 taken 2080 times.
✗ Branch 2 → 4 not taken.
2080 if (m_d.readService) m_d.readService->cancel(&m_previewOwner);
22
1/1
✓ Branch 5 → 6 taken 2080 times.
2080 present({});
23 2080 }
24
25 2115 void SearchCoordinator::present(QList<MailCache::SearchResult> results) {
26 2115 m_quickResults = std::move(results);
27 2115 emit quickResultsChanged();
28 2115 }
29
30 147 MailCache::SearchResult SearchCoordinator::quickResultAt(int index) const {
31
2/4
✓ Branch 2 → 3 taken 147 times.
✗ Branch 2 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 147 times.
147 return index < 0 || index >= m_quickResults.size() ? MailCache::SearchResult{} : m_quickResults.at(index);
32 }
33
34 44 void SearchCoordinator::updateQuickResults(const QString &query) {
35
1/1
✓ Branch 2 → 3 taken 44 times.
44 cancelQuickResults();
36
6/13
✓ Branch 3 → 4 taken 44 times.
✓ Branch 5 → 6 taken 44 times.
✗ Branch 5 → 8 not taken.
✓ Branch 6 → 7 taken 44 times.
✗ Branch 6 → 8 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 44 times.
✓ Branch 10 → 11 taken 44 times.
✗ Branch 10 → 12 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 44 times.
✗ Branch 77 → 78 not taken.
✗ Branch 77 → 79 not taken.
45 if (query.trimmed().isEmpty() || !m_d.readService || !m_d.cache) return;
37
6/7
✓ Branch 15 → 16 taken 44 times.
✗ Branch 15 → 19 not taken.
✓ Branch 16 → 17 taken 44 times.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 19 taken 43 times.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 25 taken 43 times.
44 if (m_d.localIndexReady && !m_d.localIndexReady()) {
38
2/2
✓ Branch 21 → 22 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
1 emit statusMessage(tr("Search index is being updated. Results are temporarily paused."));
39 1 return;
40 }
41 43 MailCache::SearchFilter filter;
42
1/1
✓ Branch 26 → 27 taken 43 times.
43 const QString ftsQuery = parseSearchQuery(query, filter);
43
5/7
✓ Branch 28 → 29 taken 8 times.
✓ Branch 28 → 32 taken 35 times.
✓ Branch 29 → 30 taken 8 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 8 times.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 43 times.
43 if (ftsQuery.isEmpty() && filter.isEmpty()) return;
44 43 const auto generation = m_previewGeneration;
45 43 const auto database = m_d.cache->databasePath();
46
3/7
✓ Branch 37 → 38 taken 43 times.
✗ Branch 37 → 40 not taken.
✓ Branch 38 → 39 taken 43 times.
✓ Branch 41 → 42 taken 43 times.
✗ Branch 41 → 43 not taken.
✗ Branch 84 → 85 not taken.
✗ Branch 84 → 86 not taken.
43 const auto account = m_d.accountScope ? std::optional<QString>{m_d.accountScope()} : std::nullopt;
47
2/3
✓ Branch 44 → 45 taken 43 times.
✗ Branch 44 → 47 not taken.
✓ Branch 45 → 46 taken 43 times.
43 const auto indexGeneration = m_d.localIndexGeneration ? m_d.localIndexGeneration() : 0;
48
1/7
✓ Branch 51 → 52 taken 43 times.
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 90 not taken.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 96 not taken.
43 MailSearchRequest request{database, ftsQuery, filter, account, PreviewRows, 0};
49
1/1
✓ Branch 59 → 60 taken 43 times.
43 m_d.readService->read(&m_previewOwner, std::move(request),
50
2/6
✓ Branch 54 → 55 taken 43 times.
✓ Branch 56 → 57 taken 43 times.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 106 not taken.
✗ Branch 107 → 108 not taken.
✗ Branch 107 → 109 not taken.
86 [this, generation, database, account, indexGeneration, query](MailSearchPage page) {
51
5/10
✓ Branch 2 → 3 taken 37 times.
✗ Branch 2 → 12 not taken.
✓ Branch 5 → 6 taken 37 times.
✗ Branch 5 → 12 not taken.
✓ Branch 7 → 8 taken 37 times.
✗ Branch 7 → 13 not taken.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 22 taken 36 times.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 106 not taken.
148 if (generation != m_previewGeneration || database != m_d.cache->databasePath() ||
52
6/13
✓ Branch 8 → 9 taken 37 times.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 36 times.
✓ Branch 14 → 15 taken 37 times.
✗ Branch 14 → 16 not taken.
✓ Branch 16 → 17 taken 37 times.
✗ Branch 16 → 18 not taken.
✓ Branch 18 → 19 taken 37 times.
✗ Branch 18 → 20 not taken.
✗ Branch 96 → 97 not taken.
✗ Branch 96 → 98 not taken.
✗ Branch 100 → 101 not taken.
✗ Branch 100 → 102 not taken.
114 (m_d.accountScope && account != std::optional<QString>{m_d.accountScope()})) return;
53
6/9
✓ Branch 23 → 24 taken 36 times.
✗ Branch 23 → 26 not taken.
✓ Branch 24 → 25 taken 36 times.
✓ Branch 25 → 26 taken 36 times.
✗ Branch 25 → 30 not taken.
✓ Branch 27 → 28 taken 36 times.
✗ Branch 27 → 31 not taken.
✓ Branch 32 → 33 taken 1 time.
✓ Branch 32 → 35 taken 35 times.
108 if ((m_d.localIndexReady && !m_d.localIndexReady()) ||
54
3/3
✓ Branch 28 → 29 taken 36 times.
✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 31 taken 35 times.
72 (m_d.localIndexGeneration && indexGeneration != m_d.localIndexGeneration())) {
55
1/1
✓ Branch 33 → 34 taken 1 time.
1 updateQuickResults(query); // a newer index generation answers
56 1 return;
57 }
58
2/2
✓ Branch 35 → 36 taken 1 time.
✓ Branch 35 → 47 taken 34 times.
35 if (page.outcome != MailSearchPage::Outcome::Ready) {
59
1/1
✓ Branch 37 → 38 taken 1 time.
1 present({});
60
1/1
✓ Branch 44 → 45 taken 1 time.
1 emit statusMessage(page.outcome == MailSearchPage::Outcome::Limited
61
2/5
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 1 time.
✗ Branch 40 → 44 not taken.
✗ Branch 42 → 44 not taken.
✓ Branch 43 → 44 taken 1 time.
3 ? tr("Search exceeds processing limits. Refine the query and retry.")
62 1 : page.outcome == MailSearchPage::Outcome::Busy
63
1/2
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 1 time.
1 ? tr("Search is busy. Retry the query.") : tr("Local search failed. Retry the query."));
64 1 return;
65 }
66 34 QList<MailCache::SearchResult> results;
67
4/4
✓ Branch 47 → 48 taken 34 times.
✓ Branch 48 → 49 taken 34 times.
✓ Branch 75 → 50 taken 146 times.
✓ Branch 75 → 76 taken 34 times.
180 for (const auto &hit : page.hits) {
68 146 const auto &header = hit.header;
69 146 const MailId identity{account.value_or(QString()), header.folderId, header.uid};
70
5/7
✓ Branch 55 → 56 taken 144 times.
✓ Branch 55 → 59 taken 2 times.
✓ Branch 56 → 57 taken 144 times.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 59 taken 144 times.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 146 times.
146 if (m_d.acceptCachedResult && !m_d.acceptCachedResult(identity, hit.folderPath)) continue;
71 146 MailCache::SearchResult result;
72 146 result.folderId = header.folderId;
73 146 result.uid = header.uid;
74 146 result.folderPath = hit.folderPath;
75 146 result.subject = header.subject;
76 146 result.from = header.from;
77
1/1
✓ Branch 65 → 66 taken 146 times.
146 results.append(result);
78 146 }
79
1/1
✓ Branch 77 → 78 taken 34 times.
34 present(results);
80
5/5
✓ Branch 80 → 81 taken 14 times.
✓ Branch 80 → 88 taken 20 times.
✓ Branch 81 → 82 taken 14 times.
✓ Branch 83 → 84 taken 14 times.
✓ Branch 84 → 85 taken 14 times.
48 if (m_quickResults.isEmpty()) emit statusMessage(tr("No results for '%1'").arg(query));
81
2/2
✓ Branch 88 → 89 taken 20 times.
✓ Branch 89 → 90 taken 20 times.
20 else emit statusMessage(tr("↑↓ select · Enter opens a result or searches all · Esc cancels"));
82 34 });
83 43 }
84