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% 55 / 0 / 55
Functions: 85.7% 6 / 0 / 7
Branches: 80.2% 93 / 0 / 116

app/core/CalendarFreeBusy.cpp
Line Branch Exec Source
1 #include "CalendarFreeBusy.h"
2
3 #include "service/CalDavClient.h"
4
5 #include <QLoggingCategory>
6 #include <QTimer>
7 #include <QUuid>
8 #include <memory>
9
10
4/7
✓ Branch 2 → 3 taken 4 times.
✓ Branch 2 → 8 taken 8 times.
✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 4 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
12 Q_LOGGING_CATEGORY(lcFreeBusy, "mailjd.calendar.freebusy")
11
12 23 QString CalendarFreeBusy::cacheKey(const QString &accountId, const QString &attendee, const QDateTime &from,
13 const QDateTime &to) {
14
6/6
✓ Branch 6 → 7 taken 23 times.
✓ Branch 7 → 8 taken 23 times.
✓ Branch 12 → 13 taken 23 times.
✓ Branch 13 → 14 taken 23 times.
✓ Branch 14 → 15 taken 23 times.
✓ Branch 15 → 16 taken 23 times.
46 return accountId + QLatin1Char('|') + attendee + QLatin1Char('|') + QString::number(from.toSecsSinceEpoch()) +
15
4/4
✓ Branch 2 → 3 taken 23 times.
✓ Branch 3 → 4 taken 23 times.
✓ Branch 16 → 17 taken 23 times.
✓ Branch 17 → 18 taken 23 times.
69 QLatin1Char('|') + QString::number(to.toSecsSinceEpoch());
16 }
17
18 12 void CalendarFreeBusy::request(const QString &accountId, const QString &outboxUrl, const QString &organizer,
19 const QStringList &attendees, const QDateTime &from, const QDateTime &to,
20 Done done) {
21
1/1
✓ Branch 2 → 3 taken 12 times.
12 const QDateTime now = m_clock();
22 12 QList<CalDavXml::FreeBusy> answers;
23 12 QStringList missing;
24
2/2
✓ Branch 35 → 5 taken 21 times.
✓ Branch 35 → 36 taken 12 times.
33 for (const QString &raw : attendees) {
25
2/2
✓ Branch 6 → 7 taken 21 times.
✓ Branch 7 → 8 taken 21 times.
21 const QString attendee = raw.trimmed().toLower();
26
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 21 times.
21 if (attendee.isEmpty()) continue;
27
1/1
✓ Branch 12 → 13 taken 21 times.
21 const auto cached = m_cache.constFind(cacheKey(accountId, attendee, from, to));
28
8/8
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 22 taken 19 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 22 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 26 taken 20 times.
✓ Branch 25 → 27 taken 1 time.
21 if (cached != m_cache.cend() && cached->fetched.secsTo(now) < CacheSeconds) answers.append(cached->answer);
29
1/1
✓ Branch 26 → 27 taken 20 times.
20 else missing.append(attendee);
30 21 }
31 20 const auto unknown = [](const QString &attendee) {
32 20 CalDavXml::FreeBusy entry;
33 20 entry.recipient = attendee;
34 20 return entry;
35 };
36
5/5
✓ Branch 37 → 38 taken 11 times.
✓ Branch 37 → 42 taken 1 time.
✓ Branch 39 → 40 taken 3 times.
✓ Branch 39 → 42 taken 8 times.
✓ Branch 40 → 41 taken 3 times.
12 CalDavClient *client = missing.isEmpty() || outboxUrl.isEmpty() ? nullptr : m_clientFor(accountId);
37
2/2
✓ Branch 43 → 44 taken 9 times.
✓ Branch 43 → 71 taken 3 times.
12 if (!client) {
38
5/5
✓ Branch 44 → 45 taken 9 times.
✓ Branch 45 → 46 taken 9 times.
✓ Branch 49 → 50 taken 16 times.
✓ Branch 53 → 47 taken 16 times.
✓ Branch 53 → 54 taken 9 times.
25 for (const QString &attendee : missing) answers.append(unknown(attendee));
39
8/8
✓ Branch 54 → 55 taken 9 times.
✓ Branch 58 → 59 taken 9 times.
✓ Branch 59 → 60 taken 9 times.
✓ Branch 61 → 62 taken 9 times.
✓ Branch 62 → 63 taken 9 times.
✓ Branch 64 → 65 taken 9 times.
✓ Branch 68 → 56 taken 9 times.
✓ Branch 68 → 69 taken 9 times.
18 qCInfo(lcFreeBusy) << "free/busy without a request; attendees" << answers.size() << "missing" << missing.size();
40
1/1
✓ Branch 69 → 70 taken 9 times.
9 done(answers);
41 9 return;
42 }
43
2/2
✓ Branch 71 → 72 taken 3 times.
✓ Branch 72 → 73 taken 3 times.
6 const QByteArray body = CalDavXml::freeBusyRequest(QUuid::createUuid().toString(QUuid::WithoutBraces), organizer,
44
1/1
✓ Branch 73 → 74 taken 3 times.
3 missing, from, to, now);
45
1/1
✓ Branch 75 → 76 taken 3 times.
3 const quint64 id = client->postFreeBusy(outboxUrl, body);
46 // Exactly one finish: the answer or the timeout, whichever comes first.
47
1/1
✓ Branch 76 → 77 taken 3 times.
3 auto finished = std::make_shared<bool>(false);
48
1/1
✓ Branch 77 → 78 taken 3 times.
3 auto connection = std::make_shared<QMetaObject::Connection>();
49 6 auto finish = [this, finished, connection, answers, missing, accountId, from, to, done, unknown,
50 now](const QByteArray *xml) {
51
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3 times.
3 if (*finished) return;
52 3 *finished = true;
53
1/1
✓ Branch 7 → 8 taken 3 times.
3 QObject::disconnect(*connection);
54 3 QList<CalDavXml::FreeBusy> all = answers;
55
2/2
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 1 time.
3 const QList<CalDavXml::FreeBusy> parsed = xml ? CalDavXml::parseFreeBusyResponse(*xml, from, to)
56
1/1
✓ Branch 10 → 12 taken 2 times.
3 : QList<CalDavXml::FreeBusy>{};
57
2/2
✓ Branch 37 → 14 taken 4 times.
✓ Branch 37 → 38 taken 3 times.
7 for (const QString &attendee : missing) {
58 4 CalDavXml::FreeBusy entry = unknown(attendee);
59 4 entry.noAnswer = xml == nullptr;
60
2/2
✓ Branch 24 → 18 taken 3 times.
✓ Branch 24 → 25 taken 4 times.
7 for (const CalDavXml::FreeBusy &candidate : parsed)
61
2/2
✓ Branch 20 → 21 taken 2 times.
✓ Branch 20 → 22 taken 1 time.
3 if (candidate.recipient == attendee) entry = candidate;
62
3/3
✓ Branch 25 → 26 taken 2 times.
✓ Branch 25 → 33 taken 2 times.
✓ Branch 29 → 30 taken 2 times.
6 if (entry.known) m_cache.insert(cacheKey(accountId, attendee, from, to), {entry, now});
63
1/1
✓ Branch 33 → 34 taken 4 times.
4 all.append(entry);
64 4 }
65
8/8
✓ Branch 38 → 39 taken 3 times.
✓ Branch 42 → 43 taken 3 times.
✓ Branch 43 → 44 taken 3 times.
✓ Branch 44 → 45 taken 3 times.
✓ Branch 45 → 46 taken 3 times.
✓ Branch 47 → 48 taken 3 times.
✓ Branch 51 → 40 taken 3 times.
✓ Branch 51 → 52 taken 3 times.
6 qCInfo(lcFreeBusy) << "free/busy answered" << (xml != nullptr) << "attendees" << all.size();
66
1/1
✓ Branch 52 → 53 taken 3 times.
3 done(all);
67
2/18
✓ Branch 28 → 29 taken 2 times.
✗ Branch 63 → 64 not taken.
✗ Branch 63 → 65 not taken.
✓ Branch 85 → 86 taken 3 times.
✗ Branch 138 → 139 not taken.
✗ Branch 138 → 140 not taken.
✗ Branch 141 → 142 not taken.
✗ Branch 141 → 143 not taken.
✗ Branch 144 → 145 not taken.
✗ Branch 144 → 146 not taken.
✗ Branch 147 → 148 not taken.
✗ Branch 147 → 149 not taken.
✗ Branch 150 → 151 not taken.
✗ Branch 150 → 152 not taken.
✗ Branch 153 → 154 not taken.
✗ Branch 153 → 155 not taken.
✗ Branch 156 → 157 not taken.
✗ Branch 156 → 158 not taken.
8 };
68
2/2
✓ Branch 87 → 88 taken 3 times.
✓ Branch 88 → 89 taken 3 times.
6 *connection = connect(client, &CalDavClient::resourceResponse, this, [id, finish](const DavResponse &response) {
69
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 if (response.request != id) return;
70
3/4
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 7 not taken.
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 7 taken 1 time.
3 const bool ok = response.status >= 200 && response.status < 300;
71
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 1 time.
3 finish(ok ? &response.body : nullptr);
72 3 });
73
2/2
✓ Branch 93 → 94 taken 3 times.
✓ Branch 94 → 95 taken 3 times.
3 QTimer::singleShot(TimeoutMs, this, [finish] { finish(nullptr); });
74 30 }
75