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: 85.7% 6 / 0 / 7
Functions: 75.0% 3 / 0 / 4
Branches: 57.9% 11 / 0 / 19

app/core/CalendarAccountSync.h
Line Branch Exec Source
1 #pragma once
2
3 #include <QHash>
4 #include <QObject>
5 #include <QPointer>
6 #include <QSet>
7 #include <QStringList>
8 #include <QTimer>
9 #include <functional>
10
11 #include "data/CalendarModels.h"
12 #include "data/DavCredentials.h"
13
14 class CalDavClient;
15 class CalendarStore;
16 class CalendarSyncApply;
17 class CalendarSyncStatus;
18 struct DavCollectionChanges;
19
20 // One DAV account as configured for calendar sync.
21 struct CalendarSyncAccount {
22 2625 QString accountId, serverUrl, username;
23 1749 QStringList selectedCalendars, readOnlyCalendars;
24 874 bool requiresLocalAuthorization = false;
25
7/12
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 875 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 875 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 875 times.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 874 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 874 times.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 874 times.
875 bool operator==(const CalendarSyncAccount &) const = default;
26 };
27
28 // Sprint 96 S96.3.1/S96.3.3: what one account run does.
29 // - discover: PROPFIND the collections; collections whose CTag did not
30 // change are skipped (poll, manual, initial runs).
31 // - forcedPaths: synchronised regardless of the CTag — a push notice, a
32 // recovery ticket or a manual "sync this calendar" is never discarded by
33 // an unchanged cached CTag. A run without discovery syncs only these.
34 struct CalendarSyncRequest {
35 QString accountId;
36 bool discover = true;
37 QStringList forcedPaths;
38 unsigned reasons = 0; // DavSyncReason bits
39 };
40
41 struct CalendarSyncResult {
42 QString accountId;
43 unsigned reasons = 0;
44 bool completed = false; // credentials resolved and requests answered
45 QString errorKind; // CalendarSyncStatus kind of the first failure
46 QSet<QString> syncedPaths; // completely synchronised (or unchanged CTag)
47 QSet<QString> failedPaths; // requested, but not completely synchronised
48 int retryAfterSeconds = 0;
49 };
50
51 // Sprint 96: one account sync run, extracted from CalendarSyncCoordinator so
52 // several accounts can run concurrently and a run can be targeted. Owns its
53 // CalDavClient; every read result goes through CalendarSyncApply. Emits
54 // finished() exactly once (answered, credentials failure, 60 s timeout or
55 // cancel()).
56 class CalendarAccountSync final : public QObject {
57 ✗ Q_OBJECT
58 public:
59 using ClientFactory = std::function<CalDavClient *(const QString &serverUrl, const QString &username,
60 const QString &password)>;
61 using CredentialResolver = std::function<void(QObject *owner, const QString &accountId, const QString &serverUrl,
62 const QString &username, DavCredentials::PasswordCallback callback)>;
63 static constexpr int kMaxSyncPagesPerRun = 100;
64 static constexpr int kTimeoutMs = 60000;
65
66 struct Deps {
67 CalendarStore *store = nullptr;
68 CalendarSyncApply *apply = nullptr;
69 CalendarSyncStatus *status = nullptr;
70 ClientFactory makeClient;
71 CredentialResolver resolveCredentials;
72 QSet<QString> *queryOnlyCollections = nullptr; // shared by all runs
73 std::function<void(const QString &, const QString &, const QString &)> adoptServerColor;
74 std::function<bool()> configurationCurrent; // the account config is unchanged
75 // Test seam (F-54): a shorter budget lets tests prove the run's timer
76 // restarts on every answered request instead of running out.
77 int timeoutMs = kTimeoutMs;
78 };
79
80 CalendarAccountSync(const CalendarSyncAccount &account, const CalendarSyncRequest &request, Deps deps,
81 QObject *parent = nullptr);
82 void start();
83 void cancel();
84 const CalendarSyncRequest &request() const { return m_request; }
85
86 signals:
87 void storeChanged();
88 void statusMessage(const QString &message);
89 // Discovery result incl. push offers (CalendarInfo::push).
90 void collectionsDiscovered(const QString &accountId, const QList<CalendarInfo> &calendars);
91 void finished(const CalendarSyncResult &result);
92
93 private:
94 void onCredentials(QByteArray password, const QString &error);
95 void run(QByteArray password);
96 void onDiscovered(const QList<CalendarInfo> &calendars);
97 void onCollectionSynced(const QString &path, const DavCollectionChanges &changes);
98 void onCollectionRejected(const QString &path, bool invalidToken);
99 void onQueryResult(const QString &path, bool events, bool stored, bool complete);
100 void syncCollection(const QString &path);
101 void queryCollection(const QString &path);
102 void requestPage(const QString &path, const QString &token);
103 void fail(const QString &kind, const QString &detail);
104 void finish(bool completed);
105 bool current() const;
106 538 bool selected(const QString &path) const { return m_account.selectedCalendars.contains(path); }
107
108 CalendarSyncAccount m_account;
109 CalendarSyncRequest m_request;
110 Deps m_deps;
111 QPointer<CalDavClient> m_client;
112 QTimer m_timeout;
113 CalendarSyncResult m_result;
114 bool m_finished = false;
115 bool m_credentialsResolved = false;
116 QSet<QString> m_requested;
117 QHash<QString, QString> m_discoveredCtags;
118 QHash<QString, int> m_pages;
119 QSet<QString> m_tokenResets;
120 // calendar-query fallback: CTag and outstanding results per collection.
121 QHash<QString, QPair<QString, int>> m_queryPending;
122 };
123
124
4/7
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 5 times.
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 14 not taken.
✓ Branch 9 → 10 taken 5 times.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 14 → 15 not taken.
5 Q_DECLARE_METATYPE(CalendarSyncResult)
125