service/ImapServiceContract.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Test/diagnostic state contract of ImapService (Sprint 92 S92.0.2): the | ||
| 2 | // accessors and protocol steps whose state is owned by an internal unit | ||
| 3 | // since the Sprint 92 extraction. They forward to the owning unit so the | ||
| 4 | // tests keep one stable surface; no product code calls them. | ||
| 5 | |||
| 6 | #include "ImapService.h" | ||
| 7 | #include "ImapCommandTable.h" | ||
| 8 | #include "ImapConnectionSetup.h" | ||
| 9 | #include "ImapLineReader.h" | ||
| 10 | #include "ImapPushSession.h" | ||
| 11 | #include "ImapBodyFetch.h" | ||
| 12 | #include "ImapMutationCommands.h" | ||
| 13 | #include "ImapAppendStream.h" | ||
| 14 | |||
| 15 | 344 | QMap<QString, QString> ImapService::pendingCommands() const { | |
| 16 | 344 | QMap<QString, QString> types; | |
| 17 |
4/4✓ Branch 4 → 5 taken 344 times.
✓ Branch 12 → 13 taken 619 times.
✓ Branch 14 → 6 taken 275 times.
✓ Branch 14 → 15 taken 344 times.
|
619 | for (auto it = m_commands->records().cbegin(); it != m_commands->records().cend(); ++it) |
| 18 |
1/1✓ Branch 8 → 9 taken 275 times.
|
275 | types.insert(it.key(), it->type); |
| 19 | 344 | return types; | |
| 20 | ✗ | } | |
| 21 | 135 | ImapPendingCommand &ImapService::injectPendingCommand(const QString &tag, const QString &type) { | |
| 22 | 135 | ImapPendingCommand record; | |
| 23 | 135 | record.type = type; | |
| 24 |
1/1✓ Branch 6 → 7 taken 135 times.
|
135 | m_commands->records().insert(tag, std::move(record)); |
| 25 |
1/1✓ Branch 9 → 10 taken 135 times.
|
270 | return m_commands->records()[tag]; |
| 26 | 135 | } | |
| 27 | ✗ | ImapPendingCommand *ImapService::pendingRecord(const QString &tag) { | |
| 28 | ✗ | auto it = m_commands->records().find(tag); | |
| 29 | ✗ | return it == m_commands->records().end() ? nullptr : &*it; | |
| 30 | } | ||
| 31 | 2 | void ImapService::sendRecordedCommand(const QString &type, const QString &command, | |
| 32 | const ImapPendingCommand &record) { | ||
| 33 |
2/2✓ Branch 3 → 4 taken 2 times.
✓ Branch 4 → 5 taken 2 times.
|
2 | m_commands->sendCommand(type, command, record); |
| 34 | 2 | } | |
| 35 | 4 | void ImapService::removePendingCommand(const QString &tag) { m_commands->records().remove(tag); } | |
| 36 | 66 | void ImapService::clearPendingCommands() { m_commands->records().clear(); } | |
| 37 | 5 | QMap<QString, QElapsedTimer> ImapService::commandTimers() const { | |
| 38 | 5 | QMap<QString, QElapsedTimer> timers; | |
| 39 |
4/4✓ Branch 4 → 5 taken 5 times.
✓ Branch 16 → 17 taken 7 times.
✓ Branch 18 → 6 taken 2 times.
✓ Branch 18 → 19 taken 5 times.
|
7 | for (auto it = m_commands->records().cbegin(); it != m_commands->records().cend(); ++it) { |
| 40 |
1/2✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 13 not taken.
|
2 | if (it->timer) |
| 41 |
1/1✓ Branch 12 → 13 taken 2 times.
|
2 | timers.insert(it.key(), *it->timer); |
| 42 | } | ||
| 43 | 5 | return timers; | |
| 44 | ✗ | } | |
| 45 | 3 | void ImapService::injectCommandTimer(const QString &tag, const QElapsedTimer &timer) { | |
| 46 |
1/1✓ Branch 4 → 5 taken 3 times.
|
3 | auto it = m_commands->records().find(tag); |
| 47 |
2/3✓ Branch 7 → 8 taken 3 times.
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 12 not taken.
|
3 | if (it != m_commands->records().end()) |
| 48 | 3 | it->timer = timer; | |
| 49 | 3 | } | |
| 50 | 2 | QString ImapService::pendingSelectFolder() const { | |
| 51 |
1/1✓ Branch 6 → 7 taken 2 times.
|
4 | const auto *select = m_commands->recordOfType(QStringLiteral("SELECT")); |
| 52 |
1/2✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 11 not taken.
|
2 | return select ? select->selectFolder : QString(); |
| 53 | } | ||
| 54 | 7 | QString ImapService::pendingStatusFolder() const { | |
| 55 |
1/1✓ Branch 6 → 7 taken 7 times.
|
14 | const auto *status = m_commands->recordOfType(QStringLiteral("STATUS")); |
| 56 |
2/2✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 11 taken 3 times.
|
7 | return status ? status->statusFolder : QString(); |
| 57 | } | ||
| 58 | 6 | std::optional<StatusResult> ImapService::pendingStatusResult() const { | |
| 59 |
1/1✓ Branch 6 → 7 taken 6 times.
|
12 | const auto *status = m_commands->recordOfType(QStringLiteral("STATUS")); |
| 60 |
2/2✓ Branch 9 → 10 taken 3 times.
✓ Branch 9 → 11 taken 3 times.
|
6 | return status ? status->status : std::nullopt; |
| 61 | } | ||
| 62 | 3 | qint64 ImapService::statusRequestStartedNs() const { | |
| 63 |
1/1✓ Branch 6 → 7 taken 3 times.
|
6 | const auto *status = m_commands->recordOfType(QStringLiteral("STATUS")); |
| 64 |
2/2✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 2 times.
|
3 | return status ? status->statusStartedNs : 0; |
| 65 | } | ||
| 66 | 102 | QQueue<std::function<void()>> &ImapService::deferredCommands() { | |
| 67 | 102 | return m_commands->deferredCommands(); | |
| 68 | } | ||
| 69 | 52 | QQueue<std::function<void()>> &ImapService::serializedCommands() { | |
| 70 | 52 | return m_commands->serializedCommands(); | |
| 71 | } | ||
| 72 | 7 | QTimer *ImapService::commandTimeoutTimer() const { return m_commands->commandTimeoutTimer(); } | |
| 73 | 5 | QTimer *ImapService::commandDeadlineTimer() const { return m_commands->commandDeadlineTimer(); } | |
| 74 | 2 | qint64 &ImapService::commandResponseBytes() { return m_commands->commandResponseBytes(); } | |
| 75 | 1 | qint64 &ImapService::commandLiteralCount() { return m_commands->commandLiteralCount(); } | |
| 76 | 1 | qint64 &ImapService::commandResultItems() { return m_commands->commandResultItems(); } | |
| 77 | |||
| 78 | 3 | void ImapService::sendCommand(const QString &type, const QString &command) { | |
| 79 |
1/1✓ Branch 3 → 4 taken 3 times.
|
3 | m_commands->sendCommand(type, command); |
| 80 | 3 | } | |
| 81 | 6 | bool ImapService::hasStatefulCommandInFlight() const { | |
| 82 | 6 | return m_commands->hasStatefulCommandInFlight(); | |
| 83 | } | ||
| 84 | 4 | bool ImapService::hasTimeoutTrackedCommandInFlight() const { | |
| 85 | 4 | return m_commands->hasTimeoutTrackedCommandInFlight(); | |
| 86 | } | ||
| 87 | 1 | void ImapService::enqueueSerializedCommand(std::function<void()> command) { | |
| 88 |
1/1✓ Branch 5 → 6 taken 1 time.
|
1 | m_commands->enqueueSerializedCommand(std::move(command)); |
| 89 | 1 | } | |
| 90 | 7 | void ImapService::runNextSerializedCommand() { m_commands->runNextSerializedCommand(); } | |
| 91 | 2 | void ImapService::refreshCommandTimeout() { m_commands->refreshCommandTimeout(); } | |
| 92 | 2 | void ImapService::refreshCommandDeadline() { m_commands->refreshCommandDeadline(); } | |
| 93 | 1 | bool ImapService::accountCommandResponseBytes(qint64 bytes) { | |
| 94 | 1 | return m_commands->accountCommandResponseBytes(bytes); | |
| 95 | } | ||
| 96 | 1 | bool ImapService::accountCommandLiteral() { return m_commands->accountCommandLiteral(); } | |
| 97 | 1 | bool ImapService::accountCommandResultItems(qint64 items) { | |
| 98 | 1 | return m_commands->accountCommandResultItems(items); | |
| 99 | } | ||
| 100 | 2 | void ImapService::onCommandTimeout() { m_commands->onCommandTimeout(); } | |
| 101 | 2 | void ImapService::onCommandDeadline() { m_commands->onCommandDeadline(); } | |
| 102 | |||
| 103 | 36 | QByteArray &ImapService::readBuffer() { return m_reader->readBuffer(); } | |
| 104 | 4 | qint64 &ImapService::literalBytesRemaining() { return m_reader->literalBytesRemaining(); } | |
| 105 | 2 | QString &ImapService::literalLine() { return m_reader->literalLine(); } | |
| 106 | 15 | QByteArray &ImapService::literalData() { return m_reader->literalData(); } | |
| 107 | 7 | std::unique_ptr<QTemporaryFile> &ImapService::bodySpool() { return m_reader->bodySpool(); } | |
| 108 | 4 | qint64 &ImapService::bodySpoolThreshold() { return m_reader->bodySpoolThreshold(); } | |
| 109 | 30 | void ImapService::onReadyRead() { m_reader->onReadyRead(); } | |
| 110 | 15 | void ImapService::processLine(const QString &line) { m_reader->processLine(line); } | |
| 111 | 8 | void ImapService::completeLiteral() { m_reader->completeLiteral(); } | |
| 112 | |||
| 113 | 28 | ImapConfig &ImapService::config() { return m_setup->config(); } | |
| 114 | 14 | ImapService::SetupPhase &ImapService::setupPhase() { return m_setup->setupPhase(); } | |
| 115 | 13 | QStringList &ImapService::pendingCapabilities() { return m_setup->pendingCapabilities(); } | |
| 116 | 1 | bool &ImapService::mutableKeepAliveTuned() { return m_setup->keepAliveTuned(); } | |
| 117 | 3 | QTimer *ImapService::setupTimeoutTimer() const { return m_setup->setupTimer(); } | |
| 118 | ✗ | void ImapService::onConnected() { m_setup->onConnected(); } | |
| 119 | 1 | void ImapService::onEncrypted() { m_setup->onEncrypted(); } | |
| 120 | 1 | void ImapService::tuneKeepAlive() { m_setup->tuneKeepAlive(); } | |
| 121 | 1 | bool ImapService::beginLogin() { return m_setup->beginLogin(); } | |
| 122 | |||
| 123 | 13 | bool &ImapService::autoIdle() { return m_push->autoIdle(); } | |
| 124 | 54 | bool &ImapService::mutableIdling() { return m_push->isIdling(); } | |
| 125 | 4 | bool &ImapService::idleStartPending() { return m_push->idleStartPending(); } | |
| 126 | 17 | QString &ImapService::idleTag() { return m_push->idleTag(); } | |
| 127 | 18 | bool &ImapService::mutableNotifying() { return m_push->isNotifying(); } | |
| 128 | 2 | QString &ImapService::notifyTag() { return m_push->notifyTag(); } | |
| 129 | 2 | QStringList &ImapService::notifyFolders() { return m_push->notifyFolders(); } | |
| 130 | 19 | QTimer *ImapService::idleRenewWatchdog() const { return m_push->idleRenewWatchdog(); } | |
| 131 | 14 | QTimer *ImapService::livenessProbeWatchdog() const { return m_push->livenessProbeWatchdog(); } | |
| 132 | 23 | QString &ImapService::probeTag() { return m_push->probeTag(); } | |
| 133 | 12 | QString &ImapService::lastProbeReason() { return m_push->lastProbeReason(); } | |
| 134 | 9 | void ImapService::restartPush() { m_push->restartPush(); } | |
| 135 | 1 | void ImapService::onIdleRenew() { m_push->onIdleRenew(); } | |
| 136 | 3 | void ImapService::onLivenessProbeTimeout() { m_push->onLivenessProbeTimeout(); } | |
| 137 | 1 | void ImapService::onIdleRenewWatchdogTimeout() { m_push->onIdleRenewWatchdogTimeout(); } | |
| 138 | |||
| 139 | 16 | qint64 &ImapService::activeBodyFetchUid() { return m_body->activeBodyFetchUid(); } | |
| 140 | 7 | quint64 &ImapService::activeBodyRequestId() { return m_body->activeBodyRequestId(); } | |
| 141 | 5 | QString &ImapService::activeBodyRequestFolder() { return m_body->activeBodyRequestFolder(); } | |
| 142 | 8 | qint64 &ImapService::activeBodyFetchLimit() { return m_body->activeBodyFetchLimit(); } | |
| 143 | 8 | qint64 &ImapService::activeBodyFetchRequestBytes() { | |
| 144 | 8 | return m_body->activeBodyFetchRequestBytes(); | |
| 145 | } | ||
| 146 | 2 | bool &ImapService::bodyFetchRequiresSelect() { return m_body->bodyFetchRequiresSelect(); } | |
| 147 | 1 | void ImapService::fetchBodyWithLimits(quint64 requestId, qint64 uid, qint64 acceptedBytes, | |
| 148 | qint64 requestedBytes) { | ||
| 149 | 1 | m_body->fetchBodyWithLimits(requestId, uid, acceptedBytes, requestedBytes); | |
| 150 | 1 | } | |
| 151 | 3 | void ImapService::completeBodyRequest(BodyOutcome outcome, QByteArray bytes, | |
| 152 | const QString &error, qint64 maxBytes) { | ||
| 153 |
1/1✓ Branch 5 → 6 taken 3 times.
|
3 | m_body->completeBodyRequest(outcome, std::move(bytes), error, maxBytes); |
| 154 | 3 | } | |
| 155 | 4 | QString ImapService::buildFetchBodyCommand(qint64 uid, qint64 maxBytes) { | |
| 156 | 4 | return ImapBodyFetch::buildFetchBodyCommand(uid, maxBytes); | |
| 157 | } | ||
| 158 | |||
| 159 | namespace { | ||
| 160 | // The in-flight record of the MOVE/COPY family (at most one: serialized). | ||
| 161 | 12 | const ImapPendingCommand *moveRecord(ImapCommandTable &commands) { | |
| 162 | 49 | for (const QString &type : {QStringLiteral("MOVE"), QStringLiteral("COPY"), | |
| 163 | 12 | QStringLiteral("STORE_DELETE"), QStringLiteral("EXPUNGE_MOVE"), | |
| 164 |
2/2✓ Branch 29 → 25 taken 32 times.
✓ Branch 29 → 30 taken 5 times.
|
193 | QStringLiteral("COPY_ONLY")}) { |
| 165 |
3/3✓ Branch 25 → 26 taken 32 times.
✓ Branch 26 → 27 taken 7 times.
✓ Branch 26 → 28 taken 25 times.
|
32 | if (const auto *record = commands.recordOfType(type)) |
| 166 | 7 | return record; | |
| 167 | 72 | } | |
| 168 | 5 | return nullptr; | |
| 169 | } | ||
| 170 | } // namespace | ||
| 171 | |||
| 172 | 2 | QString ImapService::pendingMoveTarget() const { | |
| 173 | 2 | const auto *move = moveRecord(*m_commands); | |
| 174 |
2/2✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 1 time.
|
2 | return move ? move->moveTarget : QString(); |
| 175 | } | ||
| 176 | 8 | QList<qint64> ImapService::pendingMoveUids() const { | |
| 177 | 8 | const auto *move = moveRecord(*m_commands); | |
| 178 |
2/2✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 6 taken 3 times.
|
8 | return move ? move->moveUids : QList<qint64>(); |
| 179 | } | ||
| 180 | 2 | QList<qint64> ImapService::pendingMoveMutationTokens() const { | |
| 181 | 2 | const auto *move = moveRecord(*m_commands); | |
| 182 |
2/2✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 1 time.
|
2 | return move ? move->mutationTokens : QList<qint64>(); |
| 183 | } | ||
| 184 | ✗ | qint64 ImapService::pendingStoreMutationToken() const { | |
| 185 | ✗ | const auto *store = m_commands->recordOfType(QStringLiteral("STORE")); | |
| 186 | ✗ | return store ? store->storeToken : 0; | |
| 187 | } | ||
| 188 | 1 | QSet<qint64> &ImapService::knownMutationTokens() { return m_mutations->knownMutationTokens(); } | |
| 189 | |||
| 190 | 11 | QByteArray ImapService::pendingAppendData() const { | |
| 191 |
1/1✓ Branch 6 → 7 taken 11 times.
|
22 | const auto *append = m_commands->recordOfType(QStringLiteral("APPEND")); |
| 192 |
2/2✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 11 taken 7 times.
|
11 | return append ? append->appendData : QByteArray(); |
| 193 | } | ||
| 194 | 7 | QString ImapService::pendingAppendFolder() const { | |
| 195 |
1/1✓ Branch 6 → 7 taken 7 times.
|
14 | const auto *append = m_commands->recordOfType(QStringLiteral("APPEND")); |
| 196 |
2/2✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 5 times.
|
7 | return append ? append->appendFolder : QString(); |
| 197 | } | ||
| 198 | 3 | quint64 ImapService::pendingAppendRequestId() const { | |
| 199 |
1/1✓ Branch 6 → 7 taken 3 times.
|
6 | const auto *append = m_commands->recordOfType(QStringLiteral("APPEND")); |
| 200 |
2/2✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 1 time.
|
3 | return append ? append->appendRequestId : 0; |
| 201 | } | ||
| 202 | 1 | qint64 ImapService::pendingAppendMutationToken() const { | |
| 203 |
1/1✓ Branch 6 → 7 taken 1 time.
|
2 | const auto *append = m_commands->recordOfType(QStringLiteral("APPEND")); |
| 204 |
1/2✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 1 time.
|
1 | return append ? append->appendToken : 0; |
| 205 | } | ||
| 206 | 1 | quint64 &ImapService::nextAppendRequestId() { return m_append->nextAppendRequestId(); } | |
| 207 | 125 | void ImapService::noteRoundTrip(qint64 elapsedMs) { m_push->noteRoundTrip(elapsedMs); } | |
| 208 | 11 | int ImapService::probeWatchdogMs() const { return m_push->probeWatchdogMs(); } | |
| 209 | 2 | qint64 ImapService::quietMs() const { return m_reader->quietMs(); } | |
| 210 | 13 | qint64 &ImapService::lastReceiveMs() { return m_reader->lastReceiveMs(); } | |
| 211 |