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: 89.2% 99 / 0 / 111
Functions: 87.5% 14 / 0 / 16
Branches: 66.9% 174 / 0 / 260

presentation/AccountServiceCheck.cpp
Line Branch Exec Source
1 #include "AccountServiceCheck.h"
2 #include "app/core/AccountSession.h"
3 #include "data/AccountConfig.h"
4 #include "data/CredentialStore.h"
5 #include <QUuid>
6
7 namespace {
8 1 QVariantMap missingPassword(const QString &service) {
9 1 Diagnosis diagnosis;
10 1 diagnosis.kind = QStringLiteral("auth");
11 1 diagnosis.service = service;
12 1 diagnosis.field = QStringLiteral("password");
13 1 diagnosis.action = QStringLiteral("retry");
14
1/1
✓ Branch 21 → 22 taken 1 time.
1 diagnosis.actionLabel = AccountServiceCheck::tr("Enter the password");
15
3/3
✓ Branch 24 → 25 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
2 diagnosis.message = AccountServiceCheck::tr("Enter the password to check the %1.").arg(ConnectionDiagnosis::serviceWord(service));
16
1/1
✓ Branch 32 → 33 taken 1 time.
2 return diagnosis.toMap();
17 1 }
18 } // namespace
19
20 1591 AccountServiceCheck::AccountServiceCheck(AccountSession *accounts, QObject *parent)
21
1/1
✓ Branch 4 → 5 taken 1591 times.
1591 : QObject(parent), m_accounts(accounts) {
22 3182 m_secretReader = [this](QObject *owner, const QString &service, const QString &accountId,
23 std::function<void(QByteArray)> done) {
24 ✗ const auto config = m_accounts ? m_accounts->configuration(accountId) : std::nullopt;
25 ✗ if (!config) { done({}); return; }
26 ✗ const QString name = service == QLatin1String("smtp") ? AccountConfigLoader::smtpCredentialName(*config)
27 ✗ : AccountConfigLoader::imapCredentialName(*config);
28 ✗ auto *store = new CredentialStore(owner);
29 ✗ store->readPassword(service, name, [store, done](bool success, const QByteArray &password) {
30 ✗ store->deleteLater();
31 ✗ done(success ? password : QByteArray());
32 ✗ });
33
0/2
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 33 not taken.
1591 };
34 1591 }
35
36 17 MailLoginProbe::Request AccountServiceCheck::request(const QString &service, const QByteArray &password) const {
37
6/6
✓ Branch 4 → 5 taken 9 times.
✓ Branch 4 → 8 taken 8 times.
✓ Branch 11 → 12 taken 8 times.
✓ Branch 11 → 13 taken 9 times.
✓ Branch 13 → 14 taken 9 times.
✓ Branch 13 → 15 taken 8 times.
34 const QString prefix = service == QLatin1String("smtp") ? QStringLiteral("smtp") : QStringLiteral("imap");
38
4/4
✓ Branch 19 → 20 taken 17 times.
✓ Branch 20 → 21 taken 17 times.
✓ Branch 21 → 22 taken 17 times.
✓ Branch 22 → 23 taken 17 times.
34 QString username = m_fields.value(prefix + QStringLiteral("Username")).toString().trimmed();
39
18/28
✓ Branch 31 → 32 taken 9 times.
✓ Branch 31 → 42 taken 8 times.
✓ Branch 37 → 38 taken 9 times.
✓ Branch 38 → 39 taken 9 times.
✓ Branch 40 → 41 taken 8 times.
✓ Branch 40 → 42 taken 1 time.
✓ Branch 43 → 44 taken 9 times.
✓ Branch 43 → 45 taken 8 times.
✓ Branch 45 → 46 taken 9 times.
✓ Branch 45 → 47 taken 8 times.
✓ Branch 47 → 48 taken 9 times.
✓ Branch 47 → 49 taken 8 times.
✓ Branch 49 → 50 taken 9 times.
✓ Branch 49 → 51 taken 8 times.
✓ Branch 51 → 52 taken 9 times.
✓ Branch 51 → 53 taken 8 times.
✓ Branch 53 → 54 taken 8 times.
✓ Branch 53 → 69 taken 9 times.
✗ Branch 145 → 146 not taken.
✗ Branch 145 → 147 not taken.
✗ Branch 149 → 150 not taken.
✗ Branch 149 → 151 not taken.
✗ Branch 153 → 154 not taken.
✗ Branch 153 → 155 not taken.
✗ Branch 157 → 158 not taken.
✗ Branch 157 → 159 not taken.
✗ Branch 161 → 162 not taken.
✗ Branch 161 → 163 not taken.
26 if (service == QLatin1String("smtp") && m_fields.value(QStringLiteral("smtpLogin")).toString() == QLatin1String("imap"))
40
3/3
✓ Branch 58 → 59 taken 8 times.
✓ Branch 59 → 60 taken 8 times.
✓ Branch 60 → 61 taken 8 times.
16 username = m_fields.value(QStringLiteral("imapUsername")).toString().trimmed();
41
3/3
✓ Branch 74 → 75 taken 17 times.
✓ Branch 75 → 76 taken 17 times.
✓ Branch 76 → 77 taken 17 times.
34 return {service, m_fields.value(prefix + QStringLiteral("Host")).toString().trimmed(),
42
3/3
✓ Branch 82 → 83 taken 17 times.
✓ Branch 83 → 84 taken 17 times.
✓ Branch 84 → 85 taken 17 times.
34 quint16(m_fields.value(prefix + QStringLiteral("Port")).toInt()),
43
2/2
✓ Branch 89 → 90 taken 17 times.
✓ Branch 90 → 91 taken 17 times.
34 m_fields.value(prefix + QStringLiteral("Security")).toString(), username, password,
44
2/2
✓ Branch 98 → 99 taken 17 times.
✓ Branch 99 → 100 taken 17 times.
51 m_fields.value(QStringLiteral("email")).toString().trimmed()};
45 102 }
46
47 11 QString AccountServiceCheck::check(const QVariantMap &fields) {
48 11 cancel();
49 11 m_fields = fields;
50
2/2
✓ Branch 4 → 5 taken 11 times.
✓ Branch 5 → 6 taken 11 times.
11 m_requestId = QUuid::createUuid().toString(QUuid::WithoutBraces);
51 11 m_incoming.clear();
52 11 m_outgoing.clear();
53
3/6
✓ Branch 11 → 12 taken 11 times.
✓ Branch 12 → 13 taken 11 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 11 times.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 34 not taken.
11 m_run = new QObject(this);
54
4/4
✓ Branch 19 → 20 taken 11 times.
✓ Branch 20 → 21 taken 11 times.
✓ Branch 25 → 26 taken 10 times.
✓ Branch 25 → 27 taken 1 time.
22 if (fields.value(QStringLiteral("checkIncoming"), true).toBool()) runIncoming();
55 1 else runOutgoing();
56 11 return m_requestId;
57 }
58
59 39 void AccountServiceCheck::cancel() {
60
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 39 times.
39 if (m_probe) m_probe->cancel();
61
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 10 taken 38 times.
39 if (m_run) m_run->deleteLater();
62 39 m_run = nullptr;
63
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 15 taken 38 times.
39 if (!m_step.isEmpty()) {
64 1 m_step.clear();
65 1 emit changed();
66 }
67 39 }
68
69 19 void AccountServiceCheck::readPassword(const QString &service, std::function<void(QByteArray)> done) {
70
4/4
✓ Branch 4 → 5 taken 9 times.
✓ Branch 4 → 15 taken 10 times.
✓ Branch 13 → 14 taken 8 times.
✓ Branch 13 → 15 taken 1 time.
28 const bool shared = service == QLatin1String("smtp") &&
71
12/22
✓ Branch 10 → 11 taken 9 times.
✓ Branch 11 → 12 taken 9 times.
✓ Branch 16 → 17 taken 9 times.
✓ Branch 16 → 18 taken 10 times.
✓ Branch 18 → 19 taken 9 times.
✓ Branch 18 → 20 taken 10 times.
✓ Branch 20 → 21 taken 9 times.
✓ Branch 20 → 22 taken 10 times.
✓ Branch 22 → 23 taken 9 times.
✓ Branch 22 → 24 taken 10 times.
✓ Branch 24 → 25 taken 9 times.
✓ Branch 24 → 26 taken 10 times.
✗ Branch 96 → 97 not taken.
✗ Branch 96 → 98 not taken.
✗ Branch 100 → 101 not taken.
✗ Branch 100 → 102 not taken.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 106 not taken.
✗ Branch 108 → 109 not taken.
✗ Branch 108 → 110 not taken.
✗ Branch 112 → 113 not taken.
✗ Branch 112 → 114 not taken.
37 m_fields.value(QStringLiteral("smtpLogin")).toString() == QLatin1String("imap");
72
2/2
✓ Branch 29 → 30 taken 10 times.
✓ Branch 29 → 33 taken 1 time.
29 const QString field = shared || service == QLatin1String("imap") ? QStringLiteral("imapPassword")
73
6/6
✓ Branch 26 → 27 taken 11 times.
✓ Branch 26 → 30 taken 8 times.
✓ Branch 36 → 37 taken 1 time.
✓ Branch 36 → 38 taken 18 times.
✓ Branch 38 → 39 taken 18 times.
✓ Branch 38 → 40 taken 1 time.
38 : QStringLiteral("smtpPassword");
74
3/3
✓ Branch 41 → 42 taken 19 times.
✓ Branch 42 → 43 taken 19 times.
✓ Branch 43 → 44 taken 19 times.
19 const QByteArray typed = m_fields.value(field).toString().toUtf8();
75
2/2
✓ Branch 51 → 52 taken 19 times.
✓ Branch 52 → 53 taken 19 times.
38 const QString id = m_fields.value(QStringLiteral("id")).toString();
76
6/7
✓ Branch 58 → 59 taken 2 times.
✓ Branch 58 → 61 taken 17 times.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 2 times.
✓ Branch 63 → 64 taken 17 times.
✓ Branch 63 → 68 taken 2 times.
✓ Branch 65 → 66 taken 17 times.
19 if (!typed.isEmpty() || id.isEmpty()) { done(typed); return; }
77
3/7
✗ Branch 70 → 71 not taken.
✓ Branch 70 → 74 taken 2 times.
✓ Branch 76 → 77 taken 2 times.
✗ Branch 78 → 79 not taken.
✓ Branch 78 → 80 taken 2 times.
✗ Branch 144 → 145 not taken.
✗ Branch 144 → 146 not taken.
2 m_secretReader(m_run, shared ? QStringLiteral("imap") : service, id, std::move(done));
78 53 }
79
80 10 void AccountServiceCheck::runIncoming() {
81 10 m_step = QStringLiteral("imap");
82
1/1
✓ Branch 8 → 9 taken 10 times.
10 emit changed();
83 10 QPointer<QObject> run(m_run);
84
2/2
✓ Branch 11 → 12 taken 10 times.
✓ Branch 15 → 16 taken 10 times.
20 readPassword(QStringLiteral("imap"), [this, run](QByteArray password) {
85
5/6
✓ Branch 3 → 4 taken 10 times.
✗ Branch 3 → 6 not taken.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 9 times.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 9 times.
10 if (!run || run != m_run) return; // S106-228: an older run's late answer
86
2/2
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 22 taken 8 times.
9 if (password.isEmpty()) {
87
1/1
✓ Branch 15 → 16 taken 1 time.
1 m_incoming = missingPassword(QStringLiteral("imap"));
88 1 runOutgoing();
89 1 return;
90 }
91
3/6
✓ Branch 24 → 25 taken 8 times.
✓ Branch 25 → 26 taken 8 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 8 times.
✗ Branch 55 → 56 not taken.
✗ Branch 55 → 57 not taken.
8 m_probe = new MailLoginProbe(m_run);
92
1/2
✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 31 not taken.
8 if (m_customSsl) m_probe->setSslConfiguration(m_ssl);
93
1/1
✓ Branch 34 → 35 taken 8 times.
8 connect(m_probe, &MailLoginProbe::finished, m_run, [this, run](const Diagnosis &diagnosis) {
94
3/6
✓ Branch 3 → 4 taken 8 times.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 8 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 8 times.
8 if (!run || run != m_run) return;
95
1/1
✓ Branch 10 → 11 taken 8 times.
8 m_incoming = diagnosis.toMap();
96 8 runOutgoing();
97 });
98
2/2
✓ Branch 41 → 42 taken 8 times.
✓ Branch 42 → 43 taken 8 times.
16 m_probe->start(request(QStringLiteral("imap"), password));
99 });
100 10 }
101
102 10 void AccountServiceCheck::runOutgoing() {
103
5/5
✓ Branch 6 → 7 taken 10 times.
✓ Branch 7 → 8 taken 10 times.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 15 taken 9 times.
✓ Branch 13 → 14 taken 1 time.
20 if (!m_fields.value(QStringLiteral("checkOutgoing"), true).toBool()) { complete(); return; }
104 9 m_step = QStringLiteral("smtp");
105
1/1
✓ Branch 21 → 22 taken 9 times.
9 emit changed();
106 9 QPointer<QObject> run(m_run);
107
2/2
✓ Branch 24 → 25 taken 9 times.
✓ Branch 28 → 29 taken 9 times.
18 readPassword(QStringLiteral("smtp"), [this, run](QByteArray password) {
108
3/6
✓ Branch 3 → 4 taken 9 times.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 9 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 9 times.
9 if (!run || run != m_run) return;
109
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 22 taken 9 times.
9 if (password.isEmpty()) {
110 ✗ m_outgoing = missingPassword(QStringLiteral("smtp"));
111 ✗ complete();
112 ✗ return;
113 }
114
3/6
✓ Branch 24 → 25 taken 9 times.
✓ Branch 25 → 26 taken 9 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 9 times.
✗ Branch 55 → 56 not taken.
✗ Branch 55 → 57 not taken.
9 m_probe = new MailLoginProbe(m_run);
115
1/2
✓ Branch 28 → 29 taken 9 times.
✗ Branch 28 → 31 not taken.
9 if (m_customSsl) m_probe->setSslConfiguration(m_ssl);
116
1/1
✓ Branch 34 → 35 taken 9 times.
9 connect(m_probe, &MailLoginProbe::finished, m_run, [this, run](const Diagnosis &diagnosis) {
117
3/6
✓ Branch 3 → 4 taken 9 times.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 9 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 9 times.
9 if (!run || run != m_run) return;
118
1/1
✓ Branch 10 → 11 taken 9 times.
9 m_outgoing = diagnosis.toMap();
119 9 complete();
120 });
121
2/2
✓ Branch 41 → 42 taken 9 times.
✓ Branch 42 → 43 taken 9 times.
18 m_probe->start(request(QStringLiteral("smtp"), password));
122 });
123 9 }
124
125 10 void AccountServiceCheck::complete() {
126 18 const auto passed = [](const QVariantMap &result) {
127
17/27
✓ Branch 2 → 3 taken 18 times.
✓ Branch 3 → 4 taken 17 times.
✓ Branch 3 → 13 taken 1 time.
✓ Branch 9 → 10 taken 17 times.
✓ Branch 10 → 11 taken 17 times.
✓ Branch 12 → 13 taken 12 times.
✓ Branch 12 → 14 taken 5 times.
✓ Branch 16 → 17 taken 17 times.
✓ Branch 16 → 18 taken 1 time.
✓ Branch 18 → 19 taken 17 times.
✓ Branch 18 → 20 taken 1 time.
✓ Branch 20 → 21 taken 17 times.
✓ Branch 20 → 22 taken 1 time.
✓ Branch 22 → 23 taken 17 times.
✓ Branch 22 → 24 taken 1 time.
✓ Branch 24 → 25 taken 17 times.
✓ Branch 24 → 26 taken 1 time.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 34 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 38 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 42 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
35 return result.isEmpty() || result.value(QStringLiteral("kind")).toString() == QLatin1String("ok");
128 };
129
6/6
✓ Branch 5 → 6 taken 10 times.
✓ Branch 6 → 7 taken 8 times.
✓ Branch 6 → 10 taken 2 times.
✓ Branch 7 → 8 taken 8 times.
✓ Branch 8 → 9 taken 5 times.
✓ Branch 8 → 10 taken 3 times.
20 const QVariantMap result{{QStringLiteral("ok"), passed(m_incoming) && passed(m_outgoing)},
130
2/4
✓ Branch 22 → 23 taken 30 times.
✓ Branch 22 → 24 taken 10 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
60 {QStringLiteral("incoming"), m_incoming}, {QStringLiteral("outgoing"), m_outgoing}};
131 10 const QString id = m_requestId;
132 10 m_step.clear();
133
2/3
✓ Branch 33 → 34 taken 10 times.
✗ Branch 33 → 36 not taken.
✓ Branch 35 → 36 taken 10 times.
10 if (m_run) m_run->deleteLater();
134
1/1
✓ Branch 36 → 37 taken 10 times.
10 m_run = nullptr;
135
1/1
✓ Branch 37 → 38 taken 10 times.
10 emit changed();
136
1/1
✓ Branch 38 → 39 taken 10 times.
10 emit finished(id, result);
137 50 }
138