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: 96.4% 163 / 0 / 169
Functions: 100.0% 13 / 0 / 13
Branches: 83.2% 238 / 0 / 286

data/MailSearchSummary.cpp
Line Branch Exec Source
1 #include "data/MailSearchSummary.h"
2
3 #include "data/MailSearchIndex.h"
4 #include "data/SqliteInterruptScope.h"
5 #include "util/AddressListScan.h"
6 #include "util/MessageId.h"
7 #include <QDateTime>
8 #include <QLoggingCategory>
9 #include <QSqlError>
10 #include <QSqlQuery>
11 #include <algorithm>
12
13 // Same category as MailCache (defined there), see docs/LOGGING.md.
14 Q_DECLARE_LOGGING_CATEGORY(lcCache)
15
16 namespace {
17 // Labels get more room than the other facets: the menu drops IMAP-internal
18 // keywords ($Junk, $Forwarded, …) and then shows TopValues of the rest.
19 constexpr int TopLabelValues = 2 * MailSearchSummary::TopValues;
20 // One cell of an aggregate row; huge recipient lists stay bounded.
21 constexpr int MaximumAddressCharacters = 4096;
22 } // namespace
23
24 514 MailSearchSummaryAccumulator::MailSearchSummaryAccumulator(MailSearchSummary::Detail detail,
25 514 const QDate &hoursDay)
26 514 : m_detail(detail), m_hoursDay(hoursDay) {
27
4/4
✓ Branch 13 → 14 taken 514 times.
✓ Branch 14 → 15 taken 9 times.
✓ Branch 14 → 19 taken 505 times.
✓ Branch 15 → 16 taken 9 times.
514 if (m_hoursDay.isValid()) m_hours = QVector<qint64>(24, 0);
28 514 }
29
30 // S106-209: a linear scan (util/AddressListScan.h). The former regex's lazy
31 // name part re-scanned the rest of a long '@'-free header from every start
32 // position — quadratic, up to ~1.5 s for one row, and the summary checks its
33 // budget between rows.
34 28220 QList<QPair<QString, QString>> MailSearchSummaryAccumulator::addresses(const QString &header) {
35
1/1
✓ Branch 4 → 5 taken 28220 times.
28220 return AddressListScan::parse(QStringView(header).left(MaximumAddressCharacters));
36 }
37
38 325768 void MailSearchSummaryAccumulator::count(QHash<QString, Facet> &facet, const QString &value, const QString &label) {
39
2/2
✓ Branch 3 → 4 taken 66828 times.
✓ Branch 3 → 5 taken 258940 times.
325768 if (value.isEmpty()) return;
40 258940 auto &entry = facet[value];
41
4/4
✓ Branch 7 → 8 taken 2221 times.
✓ Branch 7 → 13 taken 256719 times.
✓ Branch 9 → 10 taken 319 times.
✓ Branch 9 → 11 taken 1902 times.
258940 if (entry.label.isEmpty()) entry.label = label.isEmpty() ? value : label;
42 258940 ++entry.count;
43 }
44
45 // D-32: a folder counts every mail with a copy in it, so the count next to
46 // a folder equals the results of picking that folder (the copy elsewhere
47 // may represent the mail in the list).
48 105426 void MailSearchSummaryAccumulator::countFolder(const MailSearchSummaryRow &row) {
49
2/2
✓ Branch 2 → 3 taken 31419 times.
✓ Branch 2 → 4 taken 74007 times.
105426 if (m_detail == MailSearchSummary::Detail::CountOnly) return;
50
2/2
✓ Branch 5 → 6 taken 74007 times.
✓ Branch 6 → 7 taken 74007 times.
74007 const QString key = row.identity + QChar(0x1f) + row.folderPath;
51
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 74007 times.
74007 if (m_seenInFolder.contains(key)) return;
52
1/1
✓ Branch 11 → 12 taken 74007 times.
74007 m_seenInFolder.insert(key);
53
1/1
✓ Branch 12 → 13 taken 74007 times.
74007 count(m_folders, row.folderPath, row.folderPath);
54 74007 }
55
56 // The local day and hour of a Unix time. QDateTime's local-time lookup costs
57 // microseconds per row; the zone's offset is taken once per UTC hour (zone
58 // transitions fall on whole hours in practice) and the rest is arithmetic.
59 101083 QPair<QDate, int> MailSearchSummaryAccumulator::localDayAndHour(qint64 seconds) {
60
1/2
✓ Branch 2 → 3 taken 101083 times.
✗ Branch 2 → 4 not taken.
101083 const qint64 utcHour = seconds >= 0 ? seconds / 3600 : (seconds - 3599) / 3600;
61 101083 auto offset = m_offsetByUtcHour.constFind(utcHour);
62
2/2
✓ Branch 8 → 9 taken 94199 times.
✓ Branch 8 → 15 taken 6884 times.
101083 if (offset == m_offsetByUtcHour.constEnd())
63
3/3
✓ Branch 9 → 10 taken 94199 times.
✓ Branch 10 → 11 taken 94199 times.
✓ Branch 11 → 12 taken 94199 times.
94199 offset = m_offsetByUtcHour.insert(utcHour, QDateTime::fromSecsSinceEpoch(utcHour * 3600).offsetFromUtc());
64 101083 const qint64 local = seconds + offset.value();
65
1/2
✓ Branch 16 → 17 taken 101083 times.
✗ Branch 16 → 18 not taken.
101083 const qint64 days = local >= 0 ? local / 86400 : (local - 86399) / 86400;
66 101083 const qint64 secondOfDay = local - days * 86400;
67
2/2
✓ Branch 19 → 20 taken 101083 times.
✓ Branch 20 → 21 taken 101083 times.
101083 return {QDate(1970, 1, 1).addDays(days), int(secondOfDay / 3600)};
68 }
69
70 // Address headers repeat (a sender writes many mails): each distinct header
71 // is parsed once per summary; the cache is bounded.
72 143442 const QList<QPair<QString, QString>> &MailSearchSummaryAccumulator::cachedAddresses(const QString &header) {
73 143442 auto found = m_addressCache.constFind(header);
74
2/2
✓ Branch 5 → 6 taken 142383 times.
✓ Branch 5 → 7 taken 1059 times.
143442 if (found != m_addressCache.constEnd()) return found.value();
75
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1059 times.
1059 if (m_addressCache.size() >= MaximumCachedHeaders) m_addressCache.clear();
76
2/2
✓ Branch 10 → 11 taken 1059 times.
✓ Branch 11 → 12 taken 1059 times.
1059 return m_addressCache.insert(header, addresses(header)).value();
77 }
78
79 105426 bool MailSearchSummaryAccumulator::add(const MailSearchSummaryRow &row) {
80
1/1
✓ Branch 2 → 3 taken 105426 times.
105426 countFolder(row);
81
2/2
✓ Branch 4 → 5 taken 4343 times.
✓ Branch 4 → 6 taken 101083 times.
105426 if (m_seen.contains(row.identity)) return false;
82
1/1
✓ Branch 6 → 7 taken 101083 times.
101083 m_seen.insert(row.identity);
83 101083 ++m_total;
84
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 101083 times.
101083 if (!row.hasDate) {
85 ✗ ++m_undated;
86 } else {
87
1/1
✓ Branch 9 → 10 taken 101083 times.
101083 const auto [day, hour] = localDayAndHour(row.date);
88
1/1
✓ Branch 12 → 13 taken 101083 times.
101083 ++m_days[day];
89
7/8
✓ Branch 13 → 14 taken 101083 times.
✓ Branch 14 → 15 taken 247 times.
✓ Branch 14 → 18 taken 100836 times.
✓ Branch 16 → 17 taken 247 times.
✗ Branch 16 → 18 not taken.
✓ Branch 19 → 20 taken 247 times.
✓ Branch 19 → 22 taken 100836 times.
✓ Branch 20 → 21 taken 247 times.
101083 if (m_hoursDay.isValid() && day == m_hoursDay) ++m_hours[hour];
90 }
91
2/2
✓ Branch 23 → 24 taken 29362 times.
✓ Branch 23 → 25 taken 71721 times.
101083 if (m_detail == MailSearchSummary::Detail::CountOnly) return true;
92
2/2
✓ Branch 25 → 26 taken 12986 times.
✓ Branch 25 → 27 taken 58735 times.
71721 if (!(row.flags & MailFlag::Seen)) ++m_unread;
93
2/2
✓ Branch 27 → 28 taken 11185 times.
✓ Branch 27 → 29 taken 60536 times.
71721 if (row.flags & MailFlag::Flagged) ++m_flagged;
94
2/2
✓ Branch 29 → 30 taken 3901 times.
✓ Branch 29 → 31 taken 67820 times.
71721 if (row.flags & MailFlag::Answered) ++m_answered;
95
2/2
✓ Branch 31 → 32 taken 9926 times.
✓ Branch 31 → 33 taken 61795 times.
71721 if (row.hasAttachments) ++m_attachments;
96
1/1
✓ Branch 33 → 34 taken 71721 times.
71721 const auto senders = cachedAddresses(row.from);
97
2/3
✓ Branch 36 → 37 taken 71721 times.
✗ Branch 36 → 40 not taken.
✓ Branch 39 → 40 taken 71721 times.
71721 if (!senders.isEmpty()) count(m_senders, senders.first().first, senders.first().second);
98 71721 QSet<QString> recipients;
99
3/3
✓ Branch 41 → 42 taken 71721 times.
✓ Branch 54 → 44 taken 99230 times.
✓ Branch 54 → 55 taken 71721 times.
170951 for (const auto &[address, name] : cachedAddresses(row.recipients)) {
100
1/2
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 99230 times.
99230 if (recipients.contains(address)) continue;
101
1/1
✓ Branch 50 → 51 taken 99230 times.
99230 recipients.insert(address);
102
1/1
✓ Branch 51 → 52 taken 99230 times.
99230 count(m_recipients, address, name);
103 }
104
3/3
✓ Branch 58 → 59 taken 9089 times.
✓ Branch 61 → 57 taken 9089 times.
✓ Branch 61 → 62 taken 71721 times.
80810 for (const QString &label : row.labels) count(m_labels, label, label);
105
1/1
✓ Branch 62 → 63 taken 71721 times.
71721 QString list = row.listId.trimmed();
106
3/9
✓ Branch 65 → 66 taken 71721 times.
✗ Branch 66 → 67 not taken.
✓ Branch 66 → 72 taken 71721 times.
✗ Branch 69 → 70 not taken.
✗ Branch 70 → 71 not taken.
✗ Branch 70 → 72 not taken.
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 79 taken 71721 times.
✗ Branch 75 → 76 not taken.
71721 if (list.startsWith(QLatin1Char('<')) && list.endsWith(QLatin1Char('>'))) list = list.mid(1, list.size() - 2);
107
1/1
✓ Branch 79 → 80 taken 71721 times.
71721 count(m_lists, list, list);
108 71721 return true;
109 71721 }
110
111 2570 QList<MailSearchFacetValue> MailSearchSummaryAccumulator::top(const QHash<QString, Facet> &facet) {
112 2570 QList<MailSearchFacetValue> values;
113
1/1
✓ Branch 3 → 4 taken 2570 times.
2570 values.reserve(facet.size());
114
2/2
✓ Branch 15 → 5 taken 2221 times.
✓ Branch 15 → 16 taken 2570 times.
4791 for (auto it = facet.cbegin(); it != facet.cend(); ++it) values.append({it.key(), it->label, it->count});
115
3/3
✓ Branch 16 → 17 taken 2570 times.
✓ Branch 17 → 18 taken 2570 times.
✓ Branch 18 → 19 taken 2570 times.
2570 std::sort(values.begin(), values.end(), [](const MailSearchFacetValue &a, const MailSearchFacetValue &b) {
116
2/2
✓ Branch 2 → 3 taken 969 times.
✓ Branch 2 → 4 taken 529 times.
1498 if (a.count != b.count) return a.count > b.count;
117 529 const int byLabel = QString::compare(a.label, b.label, Qt::CaseInsensitive);
118
1/2
✓ Branch 5 → 6 taken 529 times.
✗ Branch 5 → 7 not taken.
529 return byLabel != 0 ? byLabel < 0 : a.value < b.value;
119 });
120 2570 return values;
121 2221 }
122
123 514 void MailSearchSummaryAccumulator::finish(MailSearchSummary &summary) const {
124 514 summary.total = m_total;
125 514 summary.undated = m_undated;
126 514 summary.dayCounts = m_days;
127 514 summary.hourCounts = m_hours;
128
5/5
✓ Branch 4 → 5 taken 514 times.
✓ Branch 5 → 6 taken 51 times.
✓ Branch 5 → 7 taken 463 times.
✓ Branch 6 → 9 taken 51 times.
✓ Branch 7 → 8 taken 463 times.
514 summary.firstDate = m_days.isEmpty() ? QDate() : m_days.firstKey();
129
5/5
✓ Branch 9 → 10 taken 514 times.
✓ Branch 10 → 11 taken 51 times.
✓ Branch 10 → 12 taken 463 times.
✓ Branch 11 → 14 taken 51 times.
✓ Branch 12 → 13 taken 463 times.
514 summary.lastDate = m_days.isEmpty() ? QDate() : m_days.lastKey();
130 514 summary.unread = m_unread;
131 514 summary.flagged = m_flagged;
132 514 summary.answered = m_answered;
133 514 summary.withAttachment = m_attachments;
134
2/2
✓ Branch 14 → 15 taken 514 times.
✓ Branch 15 → 16 taken 514 times.
514 summary.topSenders = top(m_senders).mid(0, MailSearchSummary::TopValues);
135
2/2
✓ Branch 19 → 20 taken 514 times.
✓ Branch 20 → 21 taken 514 times.
514 summary.topRecipients = top(m_recipients).mid(0, MailSearchSummary::TopValues);
136
1/1
✓ Branch 24 → 25 taken 514 times.
514 summary.folders = top(m_folders);
137
1/1
✓ Branch 27 → 28 taken 514 times.
514 summary.topFolders = summary.folders.mid(0, MailSearchSummary::TopValues);
138
2/2
✓ Branch 30 → 31 taken 514 times.
✓ Branch 31 → 32 taken 514 times.
514 summary.topLabels = top(m_labels).mid(0, TopLabelValues);
139
2/2
✓ Branch 35 → 36 taken 514 times.
✓ Branch 36 → 37 taken 514 times.
514 summary.topLists = top(m_lists).mid(0, MailSearchSummary::TopValues);
140 514 }
141
142 namespace {
143
144 515 QString summarySql(const QStringList &where, bool full) {
145 1030 const QString columns = QStringLiteral("h.id, h.date, h.message_id, fo.path") +
146
7/11
✓ Branch 2 → 3 taken 366 times.
✓ Branch 2 → 8 taken 149 times.
✓ Branch 7 → 9 taken 366 times.
✓ Branch 16 → 17 taken 366 times.
✓ Branch 16 → 18 taken 149 times.
✓ Branch 18 → 19 taken 366 times.
✓ Branch 18 → 20 taken 149 times.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
1396 (full ? QStringLiteral(", substr(h.from_addr,1,%1), "
147 "substr(coalesce(h.to_addr,'') || ', ' || coalesce(h.cc_addr,''),1,%1), h.flags, "
148 "h.has_attachments, h.list_id, "
149 "(SELECT group_concat(label, char(31)) FROM mail_labels WHERE header_id = h.id)")
150 .arg(MaximumAddressCharacters)
151
1/1
✓ Branch 12 → 13 taken 515 times.
515 : QString());
152
1/1
✓ Branch 33 → 34 taken 515 times.
1030 return QStringLiteral("SELECT ") + columns +
153
1/1
✓ Branch 34 → 35 taken 515 times.
2060 QStringLiteral(" FROM mail_fts f JOIN headers h ON h.id = f.rowid JOIN folders fo ON fo.id = h.folder_id WHERE ") +
154
3/3
✓ Branch 26 → 27 taken 515 times.
✓ Branch 35 → 36 taken 515 times.
✓ Branch 36 → 37 taken 515 times.
2575 where.join(QStringLiteral(" AND ")) + QStringLiteral(" ORDER BY h.date DESC, h.id DESC");
155 515 }
156
157 105470 MailSearchSummaryRow summaryRow(const QSqlQuery &q, bool full) {
158 105470 MailSearchSummaryRow row;
159
2/2
✓ Branch 2 → 3 taken 105470 times.
✓ Branch 3 → 4 taken 105470 times.
105470 row.id = q.value(0).toLongLong();
160
2/2
✓ Branch 5 → 6 taken 105470 times.
✓ Branch 6 → 7 taken 105470 times.
105470 row.hasDate = !q.value(1).isNull();
161
2/2
✓ Branch 8 → 9 taken 105470 times.
✓ Branch 9 → 10 taken 105470 times.
105470 row.date = q.value(1).toLongLong();
162
3/3
✓ Branch 11 → 12 taken 105470 times.
✓ Branch 12 → 13 taken 105470 times.
✓ Branch 13 → 14 taken 105470 times.
105470 const QString messageId = MessageId::canonicalFirst(q.value(2).toString());
163
10/16
✓ Branch 17 → 18 taken 10271 times.
✓ Branch 17 → 23 taken 95199 times.
✓ Branch 18 → 19 taken 10271 times.
✓ Branch 22 → 24 taken 10271 times.
✓ Branch 26 → 27 taken 10271 times.
✓ Branch 26 → 28 taken 95199 times.
✓ Branch 28 → 29 taken 10271 times.
✓ Branch 28 → 30 taken 95199 times.
✓ Branch 30 → 31 taken 10271 times.
✓ Branch 30 → 32 taken 95199 times.
✗ Branch 90 → 91 not taken.
✗ Branch 90 → 92 not taken.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 96 not taken.
✗ Branch 98 → 99 not taken.
✗ Branch 98 → 100 not taken.
115741 row.identity = messageId.isEmpty() ? QStringLiteral("row:") + QString::number(row.id) : messageId;
164
2/2
✓ Branch 32 → 33 taken 105470 times.
✓ Branch 33 → 34 taken 105470 times.
105470 row.folderPath = q.value(3).toString();
165
2/2
✓ Branch 37 → 38 taken 31421 times.
✓ Branch 37 → 39 taken 74049 times.
105470 if (!full) return row;
166
2/2
✓ Branch 39 → 40 taken 74049 times.
✓ Branch 40 → 41 taken 74049 times.
74049 row.from = q.value(4).toString();
167
2/2
✓ Branch 44 → 45 taken 74049 times.
✓ Branch 45 → 46 taken 74049 times.
74049 row.recipients = q.value(5).toString();
168
2/2
✓ Branch 49 → 50 taken 74049 times.
✓ Branch 50 → 51 taken 74049 times.
74049 row.flags = q.value(6).toUInt();
169
2/2
✓ Branch 52 → 53 taken 74049 times.
✓ Branch 53 → 54 taken 74049 times.
74049 row.hasAttachments = q.value(7).toBool();
170
2/2
✓ Branch 55 → 56 taken 74049 times.
✓ Branch 56 → 57 taken 74049 times.
74049 row.listId = q.value(8).toString();
171
2/2
✓ Branch 60 → 61 taken 74049 times.
✓ Branch 61 → 62 taken 74049 times.
74049 const QString labels = q.value(9).toString();
172
3/3
✓ Branch 64 → 65 taken 9119 times.
✓ Branch 64 → 71 taken 64930 times.
✓ Branch 67 → 68 taken 9119 times.
74049 if (!labels.isEmpty()) row.labels = labels.split(QChar(31), Qt::SkipEmptyParts);
173 74049 return row;
174 105470 }
175
176 } // namespace
177
178 523 MailSearchSummary MailSearchIndex::searchSummary(const QString &query, const SearchFilter &filter,
179 const std::optional<QString> &accountId,
180 MailSearchSummary::Detail detail,
181 const std::atomic_bool &cancelled, int timeLimitMs,
182 const QSet<QString> &allowedFolders) const {
183 523 MailSearchSummary summary;
184
7/9
✓ Branch 2 → 3 taken 523 times.
✓ Branch 3 → 4 taken 522 times.
✓ Branch 3 → 9 taken 1 time.
✓ Branch 5 → 6 taken 522 times.
✗ Branch 5 → 10 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 522 times.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 19 taken 522 times.
523 if (!filter.fitsReadLimits(query) || (accountId && accountId->size() > 4096)) {
185 1 summary.outcome = MailSearchSummary::Outcome::Limited;
186 1 summary.error = QStringLiteral("Search request exceeds the bounded summary contract");
187 1 return summary;
188 }
189
2/3
✓ Branch 19 → 20 taken 522 times.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 28 taken 522 times.
522 if (!m_db.isOpen()) { summary.error = QStringLiteral("Search database is not open"); return summary; }
190
2/2
✓ Branch 29 → 30 taken 6 times.
✓ Branch 29 → 31 taken 516 times.
522 if (cancelled.load()) { summary.outcome = MailSearchSummary::Outcome::Cancelled; return summary; }
191 516 QStringList matchTerms, likeTerms;
192
1/1
✓ Branch 31 → 32 taken 516 times.
516 splitSearchTerms(query, matchTerms, likeTerms);
193
9/9
✓ Branch 33 → 34 taken 246 times.
✓ Branch 33 → 39 taken 270 times.
✓ Branch 35 → 36 taken 226 times.
✓ Branch 35 → 39 taken 20 times.
✓ Branch 36 → 37 taken 226 times.
✓ Branch 37 → 38 taken 1 time.
✓ Branch 37 → 39 taken 225 times.
✓ Branch 40 → 41 taken 1 time.
✓ Branch 40 → 42 taken 515 times.
516 if (matchTerms.isEmpty() && likeTerms.isEmpty() && filter.isEmpty()) {
194 1 summary.outcome = MailSearchSummary::Outcome::Ready; // no search: nothing matches (as searchPage)
195 1 return summary;
196 }
197
1/1
✓ Branch 42 → 43 taken 515 times.
515 SqliteInterruptScope interrupt(m_db, cancelled, timeLimitMs);
198
1/2
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 52 taken 515 times.
515 if (!interrupt.valid()) {
199 ✗ summary.error = QStringLiteral("Search reader requires an interruptible SQLite connection");
200 ✗ return summary;
201 }
202 515 QStringList folderPatterns;
203
2/2
✓ Branch 62 → 54 taken 43 times.
✓ Branch 62 → 63 taken 515 times.
558 for (const QString &pattern : filter.folderPatterns)
204
3/4
✓ Branch 55 → 56 taken 43 times.
✓ Branch 58 → 59 taken 43 times.
✗ Branch 58 → 60 not taken.
✓ Branch 59 → 60 taken 43 times.
43 if (!pattern.trimmed().isEmpty()) folderPatterns.append(pattern);
205 515 const bool full = detail == MailSearchSummary::Detail::Full;
206
1/1
✓ Branch 63 → 64 taken 515 times.
515 QSqlQuery q(m_db);
207
1/1
✓ Branch 64 → 65 taken 515 times.
515 q.setForwardOnly(true);
208
5/5
✓ Branch 67 → 68 taken 515 times.
✓ Branch 68 → 69 taken 515 times.
✓ Branch 69 → 70 taken 515 times.
✓ Branch 72 → 73 taken 1 time.
✓ Branch 72 → 79 taken 514 times.
515 if (!q.prepare(summarySql(searchConditions(filter, accountId.has_value(), !matchTerms.isEmpty(), likeTerms,
209 folderPatterns), full))) {
210
2/2
✓ Branch 73 → 74 taken 1 time.
✓ Branch 74 → 75 taken 1 time.
1 summary.error = q.lastError().text();
211 1 return summary;
212 }
213
2/2
✓ Branch 81 → 82 taken 514 times.
✓ Branch 82 → 83 taken 514 times.
514 bindSearchParameters(q, filter, accountId, matchTerms.join(QLatin1Char(' ')), likeTerms, folderPatterns, 0, 0);
214
6/6
✓ Branch 84 → 85 taken 514 times.
✓ Branch 86 → 87 taken 110 times.
✓ Branch 87 → 88 taken 104 times.
✓ Branch 87 → 94 taken 6 times.
✓ Branch 91 → 92 taken 9 times.
✓ Branch 91 → 94 taken 95 times.
728 const QDate hoursDay = filter.dateFrom.isValid() && filter.dateTo.isValid() &&
215
2/2
✓ Branch 88 → 89 taken 104 times.
✓ Branch 89 → 90 taken 104 times.
104 filter.dateFrom.date() == filter.dateTo.date()
216
4/4
✓ Branch 85 → 86 taken 110 times.
✓ Branch 85 → 94 taken 404 times.
✓ Branch 92 → 93 taken 9 times.
✓ Branch 94 → 95 taken 505 times.
624 ? filter.dateFrom.date() : QDate();
217
1/1
✓ Branch 95 → 96 taken 514 times.
514 MailSearchSummaryAccumulator accumulator(detail, hoursDay);
218
1/1
✓ Branch 96 → 97 taken 514 times.
514 const bool executed = q.exec();
219 514 bool exhausted = false; // every row was read (not stopped by a limit)
220
6/6
✓ Branch 118 → 119 taken 105966 times.
✓ Branch 118 → 122 taken 18 times.
✓ Branch 120 → 121 taken 105962 times.
✓ Branch 120 → 122 taken 4 times.
✓ Branch 123 → 98 taken 105962 times.
✓ Branch 123 → 124 taken 22 times.
105984 while (executed && !interrupt.stopped()) {
221
3/3
✓ Branch 98 → 99 taken 105962 times.
✓ Branch 99 → 100 taken 492 times.
✓ Branch 99 → 101 taken 105470 times.
105962 if (!q.next()) { exhausted = true; break; }
222
1/1
✓ Branch 101 → 102 taken 105470 times.
105470 MailSearchSummaryRow row = summaryRow(q, full);
223 // The list admits results of folders the account lists only; so do the counts.
224
6/6
✓ Branch 103 → 104 taken 47682 times.
✓ Branch 103 → 107 taken 57788 times.
✓ Branch 105 → 106 taken 44 times.
✓ Branch 105 → 107 taken 47638 times.
✓ Branch 108 → 109 taken 44 times.
✓ Branch 108 → 110 taken 105426 times.
105470 if (!allowedFolders.isEmpty() && !allowedFolders.contains(row.folderPath)) continue;
225
1/1
✓ Branch 110 → 111 taken 105426 times.
105426 accumulator.add(row);
226 105470 }
227
1/1
✓ Branch 124 → 125 taken 514 times.
514 accumulator.finish(summary);
228 514 summary.elapsedMs = interrupt.elapsedMs();
229
2/2
✓ Branch 127 → 128 taken 21 times.
✓ Branch 127 → 131 taken 493 times.
514 if (cancelled.load()) {
230 21 summary = {};
231 21 summary.outcome = MailSearchSummary::Outcome::Cancelled;
232
6/8
✓ Branch 132 → 133 taken 492 times.
✓ Branch 132 → 135 taken 1 time.
✓ Branch 133 → 134 taken 492 times.
✗ Branch 133 → 136 not taken.
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 492 times.
✓ Branch 137 → 138 taken 1 time.
✓ Branch 137 → 145 taken 492 times.
493 } else if (interrupt.timedOut() || (executed && !exhausted)) {
233 1 summary.outcome = MailSearchSummary::Outcome::Limited;
234 1 summary.error = QStringLiteral("Search summary exceeded the worker time limit");
235
6/12
✓ Branch 145 → 146 taken 492 times.
✗ Branch 145 → 149 not taken.
✓ Branch 146 → 147 taken 492 times.
✓ Branch 147 → 148 taken 492 times.
✗ Branch 148 → 149 not taken.
✓ Branch 148 → 150 taken 492 times.
✓ Branch 151 → 152 taken 492 times.
✗ Branch 151 → 153 not taken.
✗ Branch 153 → 154 not taken.
✓ Branch 153 → 175 taken 492 times.
✗ Branch 206 → 207 not taken.
✗ Branch 206 → 208 not taken.
492 } else if (!executed || q.lastError().isValid()) {
236 ✗ qCWarning(lcCache) << "Search summary failed:" << q.lastError().text();
237 ✗ summary.outcome = MailSearchSummary::Outcome::Failed;
238 ✗ summary.error = q.lastError().text();
239 } else {
240 492 summary.outcome = MailSearchSummary::Outcome::Ready;
241 }
242 514 return summary;
243 516 }
244