presentation/AccountConnectionTest.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "AccountConnectionTest.h" | ||
| 2 | |||
| 3 | #include "data/AccountConfig.h" | ||
| 4 | #include "data/CredentialStore.h" | ||
| 5 | #include "service/ImapService.h" | ||
| 6 | |||
| 7 | #include <QMetaMethod> | ||
| 8 | #include <QSslSocket> | ||
| 9 | #include <QTimer> | ||
| 10 | |||
| 11 | |||
| 12 | // ─── SMTP probe ─── | ||
| 13 | |||
| 14 | // String-connect bridge for the test seam: adapts any object exposing | ||
| 15 | // failed(QString) into the completion lambda. | ||
| 16 | class SmtpForwarder : public QObject { | ||
| 17 | Q_OBJECT | ||
| 18 | public: | ||
| 19 | 3 | explicit SmtpForwarder(QObject *parent, | |
| 20 | std::function<void(const QString &)> callback) | ||
| 21 | 3 | : QObject(parent), m_callback(std::move(callback)) {} | |
| 22 | public slots: | ||
| 23 | 3 | void forward(const QString &error) { | |
| 24 |
1/2✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 5 not taken.
|
3 | if (m_callback) m_callback(error); |
| 25 | 3 | deleteLater(); | |
| 26 | 3 | } | |
| 27 | private: | ||
| 28 | std::function<void(const QString &)> m_callback; | ||
| 29 | }; | ||
| 30 | |||
| 31 | |||
| 32 | |||
| 33 | // Bounded SMTP reachability check: TCP (+TLS for "ssl") to the outgoing | ||
| 34 | // server and wait for the 220 greeting. This proves the host answers and | ||
| 35 | // speaks SMTP - the predecessor wizard deliberately tested nothing more, | ||
| 36 | // and a full dialog would need a message to send. | ||
| 37 | class SmtpConnectionProbe final : public QObject { | ||
| 38 | ✗ | Q_OBJECT | |
| 39 | public: | ||
| 40 | 1 | SmtpConnectionProbe(const QString &host, quint16 port, | |
| 41 | const QString &security, QObject *parent) | ||
| 42 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 6 → 7 taken 1 time.
|
1 | : QObject(parent), m_host(host), m_port(port), m_security(security) { |
| 43 |
1/1✓ Branch 7 → 8 taken 1 time.
|
1 | connect(&m_socket, &QSslSocket::readyRead, this, &SmtpConnectionProbe::readGreeting); |
| 44 | 1 | connect(&m_socket, &QSslSocket::errorOccurred, this, | |
| 45 |
1/3✗ Branch 2 → 3 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 9 → 10 taken 1 time.
|
1 | [this](QAbstractSocket::SocketError) { emit failed(m_socket.errorString()); }); |
| 46 |
1/1✓ Branch 11 → 12 taken 1 time.
|
1 | connect(&m_socket, &QSslSocket::sslErrors, this, [this](const QList<QSslError> &errors) { |
| 47 | // The account form's test path accepts the configured server's | ||
| 48 | // certificate chain like the send path's default validation would; | ||
| 49 | // only explicit handshake failures fail the probe. | ||
| 50 | ✗ | for (const auto &error : errors) | |
| 51 | ✗ | if (error.error() != QSslError::NoError) { | |
| 52 | ✗ | emit failed(error.errorString()); | |
| 53 | ✗ | return; | |
| 54 | } | ||
| 55 | }); | ||
| 56 | 1 | } | |
| 57 | public slots: | ||
| 58 | // S106-226: a slot — AccountConnectionTest starts the probe through a | ||
| 59 | // queued meta-call, which a plain member never received. | ||
| 60 | 1 | void start() { | |
| 61 | 1 | m_deadline.setSingleShot(true); | |
| 62 | 1 | connect(&m_deadline, &QTimer::timeout, this, | |
| 63 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 3 → 4 taken 1 time.
|
1 | [this] { emit failed(tr("The SMTP server did not answer in time.")); }); |
| 64 | 1 | m_deadline.start(10000); | |
| 65 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 12 taken 1 time.
|
1 | if (m_security == QLatin1String("ssl")) |
| 66 | ✗ | m_socket.connectToHostEncrypted(m_host, m_port); | |
| 67 | else | ||
| 68 |
1/1✓ Branch 13 → 14 taken 1 time.
|
1 | m_socket.connectToHost(m_host, m_port); |
| 69 | 1 | } | |
| 70 | signals: | ||
| 71 | void failed(const QString &error); | ||
| 72 | private: | ||
| 73 | 1 | void readGreeting() { | |
| 74 |
2/3✓ Branch 2 → 3 taken 1 time.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
|
1 | if (!m_socket.canReadLine()) return; |
| 75 |
1/1✓ Branch 5 → 6 taken 1 time.
|
1 | const QByteArray line = m_socket.readLine(256); |
| 76 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 20 taken 1 time.
|
1 | if (!line.startsWith("220")) { |
| 77 | ✗ | emit failed(tr("The SMTP server rejected the connection: %1") | |
| 78 | ✗ | .arg(QString::fromUtf8(line).trimmed())); | |
| 79 | ✗ | return; | |
| 80 | } | ||
| 81 |
1/1✓ Branch 20 → 21 taken 1 time.
|
1 | m_socket.write("QUIT\r\n"); |
| 82 |
1/1✓ Branch 21 → 22 taken 1 time.
|
1 | m_socket.disconnectFromHost(); |
| 83 |
1/1✓ Branch 22 → 23 taken 1 time.
|
1 | m_deadline.stop(); |
| 84 |
1/1✓ Branch 24 → 25 taken 1 time.
|
1 | emit failed(QString()); // empty error = success |
| 85 | 1 | } | |
| 86 | QSslSocket m_socket; | ||
| 87 | QString m_host; | ||
| 88 | quint16 m_port = 0; | ||
| 89 | QString m_security; | ||
| 90 | QTimer m_deadline; | ||
| 91 | }; | ||
| 92 | |||
| 93 | 804 | AccountConnectionTest::AccountConnectionTest(QObject *parent) | |
| 94 | 1608 | : QObject(parent) { | |
| 95 | 804 | m_probeFactory = [](const ImapConfig &config) { | |
| 96 | ✗ | auto *probe = new ImapService; | |
| 97 | ✗ | probe->connectToServer(config); | |
| 98 | ✗ | return probe; | |
| 99 | 804 | }; | |
| 100 | 805 | m_smtpProbeFactory = [](const QString &host, quint16 port, | |
| 101 | const QString &security) { | ||
| 102 |
2/5✓ Branch 3 → 4 taken 1 time.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 1 time.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
|
2 | return static_cast<QObject *>(new SmtpConnectionProbe(host, port, security, nullptr)); |
| 103 | 804 | }; | |
| 104 | 804 | m_secretReader = [](QObject *owner, const QString &accountId, | |
| 105 | std::function<void(bool, const QByteArray &)> callback) { | ||
| 106 | ✗ | auto *store = new CredentialStore(owner); | |
| 107 | ✗ | store->readPassword(QStringLiteral("imap"), accountId, | |
| 108 | ✗ | [store, callback = std::move(callback)]( | |
| 109 | bool success, const QByteArray &password) { | ||
| 110 | ✗ | store->deleteLater(); | |
| 111 | ✗ | callback(success, password); | |
| 112 | ✗ | }); | |
| 113 | 804 | }; | |
| 114 | 804 | } | |
| 115 | |||
| 116 | 804 | AccountConnectionTest::~AccountConnectionTest() { ++m_generation; } | |
| 117 | |||
| 118 | 3 | void AccountConnectionTest::cancel() { | |
| 119 | 3 | ++m_generation; | |
| 120 |
2/2✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 6 taken 1 time.
|
3 | if (m_run) m_run->deleteLater(); |
| 121 | 3 | m_run = nullptr; | |
| 122 |
1/1✓ Branch 11 → 12 taken 3 times.
|
6 | finish(QStringLiteral("idle"), QString()); |
| 123 | 3 | } | |
| 124 | |||
| 125 | 29 | void AccountConnectionTest::finish(const QString &state, const QString &message) { | |
| 126 |
5/6✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 7 taken 28 times.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 28 times.
|
29 | if (m_state == state && m_message == message) return; |
| 127 | 28 | m_state = state; | |
| 128 | 28 | m_message = message; | |
| 129 | 28 | emit stateChanged(); | |
| 130 | } | ||
| 131 | |||
| 132 | 17 | void AccountConnectionTest::start(const QVariantMap &fields) { | |
| 133 | // One probe at a time: a second press while testing joins nothing. | ||
| 134 |
2/2✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 16 times.
|
31 | if (m_state == QStringLiteral("testing")) return; |
| 135 | |||
| 136 |
1/1✓ Branch 14 → 15 taken 16 times.
|
32 | const auto portValue = fields.value(QStringLiteral("imapPort"), 993); |
| 137 | 16 | bool portOk = false; | |
| 138 |
1/1✓ Branch 18 → 19 taken 16 times.
|
16 | const double port = portValue.toDouble(&portOk); |
| 139 |
11/29✓ Branch 23 → 24 taken 16 times.
✓ Branch 24 → 25 taken 16 times.
✓ Branch 25 → 26 taken 16 times.
✓ Branch 36 → 37 taken 14 times.
✗ Branch 36 → 41 not taken.
✓ Branch 57 → 58 taken 16 times.
✗ Branch 57 → 59 not taken.
✓ Branch 59 → 60 taken 16 times.
✗ Branch 59 → 61 not taken.
✓ Branch 61 → 62 taken 16 times.
✗ Branch 61 → 63 not taken.
✓ Branch 63 → 64 taken 16 times.
✗ Branch 63 → 65 not taken.
✓ Branch 65 → 66 taken 16 times.
✗ Branch 65 → 67 not taken.
✓ Branch 67 → 68 taken 3 times.
✓ Branch 67 → 77 taken 13 times.
✗ Branch 195 → 196 not taken.
✗ Branch 195 → 197 not taken.
✗ Branch 199 → 200 not taken.
✗ Branch 199 → 201 not taken.
✗ Branch 203 → 204 not taken.
✗ Branch 203 → 205 not taken.
✗ Branch 207 → 208 not taken.
✗ Branch 207 → 209 not taken.
✗ Branch 211 → 212 not taken.
✗ Branch 211 → 213 not taken.
✗ Branch 215 → 216 not taken.
✗ Branch 215 → 217 not taken.
|
62 | if (fields.value(QStringLiteral("imapHost")).toString().trimmed().isEmpty() || |
| 140 |
14/27✓ Branch 32 → 33 taken 14 times.
✓ Branch 33 → 34 taken 14 times.
✓ Branch 34 → 35 taken 14 times.
✓ Branch 45 → 46 taken 14 times.
✓ Branch 45 → 47 taken 2 times.
✓ Branch 47 → 48 taken 14 times.
✓ Branch 47 → 49 taken 2 times.
✓ Branch 49 → 50 taken 14 times.
✓ Branch 49 → 51 taken 2 times.
✓ Branch 51 → 52 taken 14 times.
✓ Branch 51 → 53 taken 2 times.
✓ Branch 53 → 54 taken 14 times.
✓ Branch 53 → 55 taken 2 times.
✓ Branch 55 → 56 taken 16 times.
✗ Branch 55 → 57 not taken.
✗ Branch 171 → 172 not taken.
✗ Branch 171 → 173 not taken.
✗ Branch 175 → 176 not taken.
✗ Branch 175 → 177 not taken.
✗ Branch 179 → 180 not taken.
✗ Branch 179 → 181 not taken.
✗ Branch 183 → 184 not taken.
✗ Branch 183 → 185 not taken.
✗ Branch 187 → 188 not taken.
✗ Branch 187 → 189 not taken.
✗ Branch 191 → 192 not taken.
✗ Branch 191 → 193 not taken.
|
44 | fields.value(QStringLiteral("imapUsername")).toString().trimmed().isEmpty() || |
| 141 |
8/10✓ Branch 27 → 28 taken 14 times.
✓ Branch 27 → 41 taken 2 times.
✓ Branch 37 → 38 taken 14 times.
✗ Branch 37 → 41 not taken.
✓ Branch 38 → 39 taken 13 times.
✓ Branch 38 → 41 taken 1 time.
✓ Branch 39 → 40 taken 13 times.
✗ Branch 39 → 41 not taken.
✓ Branch 43 → 44 taken 14 times.
✓ Branch 43 → 45 taken 2 times.
|
59 | !portOk || port < 1 || port > 65535 || |
| 142 |
1/2✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 13 times.
|
13 | std::floor(port) != port) { |
| 143 |
1/1✓ Branch 72 → 73 taken 3 times.
|
3 | finish(QStringLiteral("failed"), |
| 144 |
1/1✓ Branch 68 → 69 taken 3 times.
|
6 | tr("Enter server, username and a whole port between 1 and 65535.")); |
| 145 | 3 | return; | |
| 146 | } | ||
| 147 | |||
| 148 | 13 | ++m_generation; | |
| 149 | 13 | const quint64 generation = m_generation; | |
| 150 |
4/7✓ Branch 77 → 78 taken 13 times.
✓ Branch 78 → 79 taken 13 times.
✓ Branch 79 → 80 taken 13 times.
✗ Branch 80 → 81 not taken.
✓ Branch 80 → 82 taken 13 times.
✗ Branch 228 → 229 not taken.
✗ Branch 228 → 230 not taken.
|
13 | m_run = new QObject(this); |
| 151 |
1/1✓ Branch 82 → 83 taken 13 times.
|
13 | emit stateChanged(); |
| 152 |
2/2✓ Branch 83 → 84 taken 13 times.
✓ Branch 87 → 88 taken 13 times.
|
26 | finish(QStringLiteral("testing"), tr("Testing connection…")); |
| 153 |
1/1✓ Branch 91 → 92 taken 13 times.
|
13 | QPointer<AccountConnectionTest> guard(this); |
| 154 | 13 | QPointer<QObject> run(m_run); | |
| 155 | |||
| 156 |
2/2✓ Branch 97 → 98 taken 13 times.
✓ Branch 98 → 99 taken 13 times.
|
26 | const QString accountId = fields.value(QStringLiteral("id")).toString(); |
| 157 | const QString enteredPassword = | ||
| 158 |
2/2✓ Branch 107 → 108 taken 13 times.
✓ Branch 108 → 109 taken 13 times.
|
26 | fields.value(QStringLiteral("imapPassword")).toString(); |
| 159 | |||
| 160 | 13 | const auto beginProbe = [guard, run, generation, | |
| 161 | fields](const QByteArray &password) { | ||
| 162 |
4/8✓ Branch 3 → 4 taken 13 times.
✗ Branch 3 → 9 not taken.
✓ Branch 5 → 6 taken 13 times.
✗ Branch 5 → 9 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 13 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 13 times.
|
15 | if (!guard || !run || !guard->runCurrent(generation)) return; |
| 163 |
2/2✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 30 taken 11 times.
|
13 | if (password.isEmpty()) { |
| 164 |
1/1✓ Branch 17 → 18 taken 2 times.
|
2 | guard->m_run->deleteLater(); |
| 165 |
1/1✓ Branch 19 → 20 taken 2 times.
|
2 | guard->m_run = nullptr; |
| 166 |
1/1✓ Branch 25 → 26 taken 2 times.
|
4 | guard->finish(QStringLiteral("failed"), |
| 167 |
1/1✓ Branch 21 → 22 taken 2 times.
|
4 | tr("Enter the IMAP password to test the connection.")); |
| 168 | 2 | return; | |
| 169 | } | ||
| 170 |
1/1✓ Branch 30 → 31 taken 11 times.
|
11 | ImapConfig config; |
| 171 |
3/3✓ Branch 35 → 36 taken 11 times.
✓ Branch 36 → 37 taken 11 times.
✓ Branch 37 → 38 taken 11 times.
|
22 | config.host = fields.value(QStringLiteral("imapHost")).toString().trimmed(); |
| 172 | 11 | config.port = static_cast<quint16>( | |
| 173 |
2/2✓ Branch 49 → 50 taken 11 times.
✓ Branch 50 → 51 taken 11 times.
|
22 | fields.value(QStringLiteral("imapPort"), 993).toInt()); |
| 174 |
1/1✓ Branch 62 → 63 taken 11 times.
|
44 | config.security = fields.value(QStringLiteral("imapSecurity"), |
| 175 |
1/1✓ Branch 63 → 64 taken 11 times.
|
33 | QStringLiteral("ssl")).toString(); |
| 176 | config.username = | ||
| 177 |
3/3✓ Branch 76 → 77 taken 11 times.
✓ Branch 77 → 78 taken 11 times.
✓ Branch 78 → 79 taken 11 times.
|
22 | fields.value(QStringLiteral("imapUsername")).toString().trimmed(); |
| 178 | 11 | config.password = password; | |
| 179 | |||
| 180 |
1/1✓ Branch 88 → 89 taken 11 times.
|
11 | ImapService *probe = guard->m_probeFactory(config); |
| 181 |
1/2✗ Branch 89 → 90 not taken.
✓ Branch 89 → 105 taken 11 times.
|
11 | if (!probe) { |
| 182 | ✗ | guard->m_run->deleteLater(); | |
| 183 | ✗ | guard->m_run = nullptr; | |
| 184 | ✗ | guard->finish(QStringLiteral("failed"), | |
| 185 | ✗ | tr("The connection test could not be started.")); | |
| 186 | ✗ | return; | |
| 187 | } | ||
| 188 |
1/1✓ Branch 107 → 108 taken 11 times.
|
11 | probe->setParent(guard->m_run); |
| 189 | 35 | const auto completed = [guard, run, generation]() { | |
| 190 |
3/4✓ Branch 3 → 4 taken 13 times.
✗ Branch 3 → 12 not taken.
✓ Branch 6 → 7 taken 12 times.
✓ Branch 6 → 12 taken 1 time.
|
25 | return guard && guard->runCurrent(generation) && |
| 191 |
5/8✓ Branch 8 → 9 taken 12 times.
✓ Branch 9 → 10 taken 12 times.
✓ Branch 10 → 11 taken 12 times.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 12 times.
✓ Branch 13 → 15 taken 1 time.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
|
25 | !run->property("finished").toBool(); |
| 192 | 11 | }; | |
| 193 |
3/3✓ Branch 114 → 115 taken 11 times.
✓ Branch 115 → 116 taken 11 times.
✓ Branch 116 → 117 taken 11 times.
|
22 | const bool hasSmtp = !fields.value(QStringLiteral("smtpHost")).toString().trimmed().isEmpty(); |
| 194 |
1/1✓ Branch 129 → 130 taken 11 times.
|
11 | connect(probe, &ImapService::stateChanged, run, |
| 195 |
0/6✗ Branch 253 → 254 not taken.
✗ Branch 253 → 255 not taken.
✗ Branch 256 → 257 not taken.
✗ Branch 256 → 258 not taken.
✗ Branch 259 → 260 not taken.
✗ Branch 259 → 261 not taken.
|
22 | [guard, run, generation, completed, hasSmtp, fields](ImapService::State state) { |
| 196 |
2/3✓ Branch 2 → 3 taken 6 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6 times.
|
9 | if (!completed()) return; |
| 197 |
2/2✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 5 times.
|
6 | if (state != ImapService::State::Authenticated) return; |
| 198 |
2/2✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 27 taken 3 times.
|
5 | if (!hasSmtp) { |
| 199 |
1/1✓ Branch 10 → 11 taken 2 times.
|
2 | run->setProperty("finished", true); |
| 200 |
1/1✓ Branch 14 → 15 taken 2 times.
|
2 | guard->m_run->deleteLater(); |
| 201 |
1/1✓ Branch 16 → 17 taken 2 times.
|
2 | guard->m_run = nullptr; |
| 202 |
1/1✓ Branch 22 → 23 taken 2 times.
|
4 | guard->finish(QStringLiteral("success"), |
| 203 |
1/1✓ Branch 18 → 19 taken 2 times.
|
4 | tr("Connection successful. The account can be saved.")); |
| 204 | 2 | return; | |
| 205 | } | ||
| 206 | // Q07 SMTP reachability: the outgoing server gets its own | ||
| 207 | // bounded probe; the combined message names both results. | ||
| 208 |
3/3✓ Branch 31 → 32 taken 3 times.
✓ Branch 32 → 33 taken 3 times.
✓ Branch 33 → 34 taken 3 times.
|
6 | const QString host = fields.value(QStringLiteral("smtpHost")).toString().trimmed(); |
| 209 | 3 | bool portOk = false; | |
| 210 |
2/2✓ Branch 43 → 44 taken 3 times.
✓ Branch 44 → 45 taken 3 times.
|
6 | const int port = fields.value(QStringLiteral("smtpPort"), 587).toInt(&portOk); |
| 211 |
1/1✓ Branch 56 → 57 taken 3 times.
|
12 | const QString security = fields.value(QStringLiteral("smtpSecurity"), |
| 212 |
1/1✓ Branch 57 → 58 taken 3 times.
|
9 | QStringLiteral("starttls")).toString(); |
| 213 |
3/6✓ Branch 64 → 65 taken 3 times.
✗ Branch 64 → 67 not taken.
✓ Branch 65 → 66 taken 3 times.
✗ Branch 65 → 67 not taken.
✗ Branch 66 → 67 not taken.
✓ Branch 66 → 86 taken 3 times.
|
3 | if (!portOk || port < 1 || port > 65535) { |
| 214 | ✗ | run->setProperty("finished", true); | |
| 215 | ✗ | guard->m_run->deleteLater(); | |
| 216 | ✗ | guard->m_run = nullptr; | |
| 217 | ✗ | guard->finish(QStringLiteral("success"), | |
| 218 | ✗ | tr("IMAP connected; enter a whole SMTP port to test the outgoing server.")); | |
| 219 | ✗ | return; | |
| 220 | } | ||
| 221 |
1/1✓ Branch 87 → 88 taken 3 times.
|
3 | QObject *smtpProbe = guard->m_smtpProbeFactory(host, static_cast<quint16>(port), security); |
| 222 |
1/2✗ Branch 88 → 89 not taken.
✓ Branch 88 → 108 taken 3 times.
|
3 | if (!smtpProbe) { |
| 223 | ✗ | run->setProperty("finished", true); | |
| 224 | ✗ | guard->m_run->deleteLater(); | |
| 225 | ✗ | guard->m_run = nullptr; | |
| 226 | ✗ | guard->finish(QStringLiteral("success"), | |
| 227 | ✗ | tr("IMAP connected. The SMTP test could not be started.")); | |
| 228 | ✗ | return; | |
| 229 | } | ||
| 230 |
1/1✓ Branch 109 → 110 taken 3 times.
|
3 | smtpProbe->setParent(run); |
| 231 | 12 | const auto smtpDone = [guard, run, generation, completed](const QString &error) { | |
| 232 |
3/6✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 3 times.
|
3 | if (!guard || !completed()) return; |
| 233 |
1/1✓ Branch 12 → 13 taken 3 times.
|
3 | run->setProperty("finished", true); |
| 234 | 3 | guard->m_run->deleteLater(); | |
| 235 | 3 | guard->m_run = nullptr; | |
| 236 |
2/2✓ Branch 20 → 21 taken 2 times.
✓ Branch 20 → 31 taken 1 time.
|
3 | if (error.isEmpty()) |
| 237 |
1/1✓ Branch 26 → 27 taken 2 times.
|
4 | guard->finish(QStringLiteral("success"), |
| 238 |
1/1✓ Branch 22 → 23 taken 2 times.
|
4 | tr("IMAP and SMTP connections successful. The account can be saved.")); |
| 239 | else | ||
| 240 |
1/1✓ Branch 38 → 39 taken 1 time.
|
2 | guard->finish(QStringLiteral("failed"), |
| 241 |
2/2✓ Branch 32 → 33 taken 1 time.
✓ Branch 34 → 35 taken 1 time.
|
3 | tr("IMAP connected, but the SMTP test failed: %1").arg(error)); |
| 242 | 3 | }; | |
| 243 | // Both the production probe and test seam objects carry a | ||
| 244 | // failed(QString) signal and an invokable start(); the | ||
| 245 | // new-style connect matches by signature through the | ||
| 246 | // normalized signal string. | ||
| 247 |
3/6✓ Branch 113 → 114 taken 3 times.
✓ Branch 115 → 116 taken 3 times.
✗ Branch 116 → 117 not taken.
✓ Branch 116 → 118 taken 3 times.
✗ Branch 242 → 243 not taken.
✗ Branch 242 → 244 not taken.
|
3 | auto *adapter = new QObject(run); |
| 248 | // A dedicated forwarding QObject gives string-connect a real | ||
| 249 | // receiver with a slot. | ||
| 250 |
4/7✓ Branch 118 → 119 taken 3 times.
✓ Branch 119 → 120 taken 3 times.
✓ Branch 120 → 121 taken 3 times.
✗ Branch 122 → 123 not taken.
✓ Branch 122 → 124 taken 3 times.
✗ Branch 248 → 249 not taken.
✗ Branch 248 → 250 not taken.
|
3 | auto *forward = new SmtpForwarder(adapter, smtpDone); |
| 251 |
3/3✓ Branch 124 → 125 taken 3 times.
✓ Branch 125 → 126 taken 3 times.
✓ Branch 126 → 127 taken 3 times.
|
3 | QObject::connect(smtpProbe, SIGNAL(failed(QString)), |
| 252 | forward, SLOT(forward(QString)), | ||
| 253 | Qt::DirectConnection); | ||
| 254 |
2/3✓ Branch 128 → 129 taken 3 times.
✗ Branch 129 → 130 not taken.
✓ Branch 129 → 149 taken 3 times.
|
3 | if (!QMetaObject::invokeMethod(smtpProbe, "start", Qt::QueuedConnection)) { |
| 255 | ✗ | run->setProperty("finished", true); | |
| 256 | ✗ | guard->m_run->deleteLater(); | |
| 257 | ✗ | guard->m_run = nullptr; | |
| 258 | ✗ | guard->finish(QStringLiteral("success"), | |
| 259 | ✗ | tr("IMAP connected. The SMTP test could not be started.")); | |
| 260 | } | ||
| 261 |
2/4✓ Branch 152 → 153 taken 3 times.
✗ Branch 152 → 154 not taken.
✓ Branch 156 → 157 taken 3 times.
✗ Branch 156 → 159 not taken.
|
3 | }); |
| 262 |
1/1✓ Branch 136 → 137 taken 11 times.
|
11 | connect(probe, &ImapService::errorOccurred, run, |
| 263 |
0/4✗ Branch 266 → 267 not taken.
✗ Branch 266 → 268 not taken.
✗ Branch 269 → 270 not taken.
✗ Branch 269 → 271 not taken.
|
22 | [guard, run, generation, completed](const QString &error) { |
| 264 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
|
2 | if (!completed()) return; |
| 265 |
1/1✓ Branch 7 → 8 taken 1 time.
|
1 | run->setProperty("finished", true); |
| 266 | 1 | guard->m_run->deleteLater(); | |
| 267 | 1 | guard->m_run = nullptr; | |
| 268 |
1/1✓ Branch 21 → 22 taken 1 time.
|
2 | guard->finish(QStringLiteral("failed"), |
| 269 |
2/2✓ Branch 15 → 16 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
|
3 | tr("Connection test failed: %1").arg(error)); |
| 270 | }); | ||
| 271 |
1/5✓ Branch 144 → 145 taken 11 times.
✗ Branch 276 → 277 not taken.
✗ Branch 276 → 278 not taken.
✗ Branch 279 → 280 not taken.
✗ Branch 279 → 281 not taken.
|
11 | QTimer::singleShot(guard->m_timeoutMs, run, [guard, run, generation, completed] { |
| 272 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
|
2 | if (!completed()) return; |
| 273 |
1/1✓ Branch 7 → 8 taken 2 times.
|
2 | run->setProperty("finished", true); |
| 274 | 2 | guard->m_run->deleteLater(); | |
| 275 | 2 | guard->m_run = nullptr; | |
| 276 |
1/1✓ Branch 19 → 20 taken 2 times.
|
4 | guard->finish(QStringLiteral("failed"), |
| 277 |
1/1✓ Branch 15 → 16 taken 2 times.
|
4 | tr("Connection test timed out.")); |
| 278 | }); | ||
| 279 |
1/2✓ Branch 149 → 150 taken 11 times.
✗ Branch 149 → 152 not taken.
|
24 | }; |
| 280 | |||
| 281 |
6/6✓ Branch 117 → 118 taken 3 times.
✓ Branch 117 → 120 taken 10 times.
✓ Branch 119 → 120 taken 1 time.
✓ Branch 119 → 121 taken 2 times.
✓ Branch 122 → 123 taken 11 times.
✓ Branch 122 → 127 taken 2 times.
|
13 | if (!enteredPassword.isEmpty() || accountId.isEmpty()) { |
| 282 |
2/2✓ Branch 123 → 124 taken 11 times.
✓ Branch 124 → 125 taken 11 times.
|
11 | beginProbe(enteredPassword.toUtf8()); |
| 283 | 11 | return; | |
| 284 | } | ||
| 285 | // Empty password on a saved account: test with the stored secret. | ||
| 286 |
1/1✓ Branch 132 → 133 taken 2 times.
|
2 | m_secretReader(m_run, accountId, |
| 287 |
1/7✓ Branch 130 → 131 taken 2 times.
✗ Branch 271 → 272 not taken.
✗ Branch 271 → 273 not taken.
✗ Branch 274 → 275 not taken.
✗ Branch 274 → 276 not taken.
✗ Branch 277 → 278 not taken.
✗ Branch 277 → 279 not taken.
|
4 | [beginProbe, guard, run, generation](bool, const QByteArray &secret) { |
| 288 |
4/8✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 9 not taken.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 9 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 2 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 2 times.
|
2 | if (!guard || !run || !guard->runCurrent(generation)) return; |
| 289 | 2 | beginProbe(secret); | |
| 290 | }); | ||
| 291 | 71 | } | |
| 292 | #include "AccountConnectionTest.moc" | ||
| 293 |