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: 98.5% 64 / 0 / 65
Functions: 100.0% 6 / 0 / 6
Branches: 81.3% 74 / 0 / 91

presentation/QuickRuleConflict.cpp
Line Branch Exec Source
1 // Rule conflicts of QuickRulesBackend (Sprint 95 C7/C8, Sprint 107
2 // S107.3.4): the held conflict with its three scripts, the whole-side
3 // resolution of the banner and the resolver's checked upload.
4 #include "QuickRulesBackend.h"
5
6 #include <QLoggingCategory>
7 #include <QPointer>
8
9 Q_DECLARE_LOGGING_CATEGORY(lcConflict)
10
11 8 void QuickRulesBackend::holdConflict(const QByteArray &mine, const QByteArray &base,
12 const SieveSession::SaveOutcome &outcome) {
13 8 m_conflictMine = mine;
14 8 m_conflictBase = base;
15 8 m_conflictTheirs = outcome.theirs;
16 8 m_conflictBlocks.clear();
17
2/2
✓ Branch 41 → 8 taken 8 times.
✓ Branch 41 → 42 taken 8 times.
16 for (const Sieve::MergeConflict &conflict : outcome.merge.conflicts)
18
1/1
✓ Branch 25 → 26 taken 8 times.
24 m_conflictBlocks.append(QVariantMap{{QStringLiteral("name"), conflict.name},
19
1/1
✓ Branch 16 → 17 taken 8 times.
16 {QStringLiteral("mine"), QString::fromUtf8(conflict.mine)},
20
3/5
✓ Branch 21 → 22 taken 8 times.
✓ Branch 29 → 30 taken 24 times.
✓ Branch 29 → 31 taken 8 times.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
48 {QStringLiteral("theirs"), QString::fromUtf8(conflict.theirs)}});
21
7/7
✓ Branch 42 → 43 taken 8 times.
✓ Branch 46 → 47 taken 8 times.
✓ Branch 47 → 48 taken 8 times.
✓ Branch 49 → 50 taken 8 times.
✓ Branch 50 → 51 taken 8 times.
✓ Branch 54 → 44 taken 8 times.
✓ Branch 54 → 55 taken 8 times.
16 qCInfo(lcConflict) << "rules conflict held:" << outcome.merge.conflicts.size() << "blocks";
22 8 emit conflictChanged();
23 40 }
24
25 51 void QuickRulesBackend::clearConflict() {
26
2/2
✓ Branch 3 → 4 taken 45 times.
✓ Branch 3 → 5 taken 6 times.
51 if (m_conflictMine.isNull())
27 45 return;
28 6 m_conflictMine.clear();
29 6 m_conflictBase.clear();
30 6 m_conflictTheirs.clear();
31 6 m_conflictBlocks.clear();
32 6 emit conflictChanged();
33 }
34
35 5 void QuickRulesBackend::resolveConflict(const QString &choice) {
36
1/1
✓ Branch 2 → 3 taken 5 times.
5 SieveSession *s = session();
37
3/6
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 5 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 5 times.
5 if (!s || m_conflictMine.isNull())
38 1 return;
39 5 const QByteArray mine = m_conflictMine;
40
1/1
✓ Branch 11 → 12 taken 5 times.
5 clearConflict();
41
2/2
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 20 taken 4 times.
5 if (choice == QLatin1String("theirs")) {
42
1/1
✓ Branch 15 → 16 taken 1 time.
1 s->load();
43
2/2
✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
1 emit toast(tr("Kept the rules from the server"), false);
44 1 return;
45 }
46 4 SieveSession::SaveOptions options;
47 4 options.keepMine = true;
48 4 options.reason = QStringLiteral("conflict");
49
1/1
✓ Branch 27 → 28 taken 4 times.
4 s->save(mine, options, [this](const SieveSession::SaveOutcome &outcome) {
50
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 8 taken 1 time.
4 if (outcome.ok()) {
51
2/2
✓ Branch 4 → 5 taken 3 times.
✓ Branch 5 → 6 taken 3 times.
3 emit toast(tr("Your version was saved"), false);
52 3 return;
53 }
54
4/4
✓ Branch 8 → 9 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
2 emit toast(outcomeMap(outcome).value(QStringLiteral("message")).toString(), false);
55 });
56 5 }
57
58 3 void QuickRulesBackend::resolveWith(const QByteArray &resolved, const QByteArray &theirs, ResolveCallback done) {
59
1/1
✓ Branch 2 → 3 taken 3 times.
3 SieveSession *s = session();
60
6/8
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 8 not taken.
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 8 taken 1 time.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 2 times.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 25 taken 2 times.
3 if (!s || m_conflictMine.isNull() || theirs != m_conflictTheirs) {
61
1/2
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 24 not taken.
1 if (done)
62
2/2
✓ Branch 14 → 15 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
2 done(false, QStringLiteral("stale"), tr("The rules changed meanwhile. Reload them and try again."), {});
63 1 return;
64 }
65 // The resolution was made against `theirs`: the upload expects exactly
66 // that server version; a newer one is merged onto it like any change
67 // made elsewhere and becomes a new conflict when it overlaps (D-9).
68 2 SieveSession::SaveOptions options;
69 2 options.reason = QStringLiteral("conflict");
70 2 options.expectedServer = theirs;
71 2 options.renderedFrom = theirs;
72
1/1
✓ Branch 33 → 34 taken 2 times.
2 QPointer<QuickRulesBackend> guard(this);
73
3/9
✓ Branch 37 → 38 taken 2 times.
✓ Branch 38 → 39 taken 2 times.
✓ Branch 39 → 40 taken 2 times.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
✗ Branch 68 → 69 not taken.
✗ Branch 68 → 70 not taken.
2 s->save(resolved, options, [this, guard, resolved, theirs, done](const SieveSession::SaveOutcome &outcome) {
74
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 if (!guard)
75 ✗ return;
76
1/1
✓ Branch 5 → 6 taken 2 times.
2 const QVariantMap result = outcomeMap(outcome);
77
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 13 taken 1 time.
2 if (outcome.ok()) {
78
1/1
✓ Branch 8 → 9 taken 1 time.
1 clearConflict();
79
2/2
✓ Branch 9 → 10 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
1 emit toast(tr("Your choices were saved"), false);
80
1/2
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 15 not taken.
1 } else if (outcome.kind == SieveSession::SaveOutcome::Kind::Conflict) {
81
1/1
✓ Branch 14 → 15 taken 1 time.
1 holdConflict(resolved, theirs, outcome);
82 }
83
8/8
✓ Branch 15 → 16 taken 2 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 20 → 21 taken 2 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 27 → 28 taken 2 times.
✓ Branch 36 → 17 taken 2 times.
✓ Branch 36 → 37 taken 2 times.
4 qCInfo(lcConflict) << "rules resolution uploaded:" << result.value(QStringLiteral("kind")).toString();
84
1/2
✓ Branch 38 → 39 taken 2 times.
✗ Branch 38 → 75 not taken.
2 if (done)
85
5/5
✓ Branch 49 → 50 taken 2 times.
✓ Branch 50 → 51 taken 2 times.
✓ Branch 55 → 56 taken 2 times.
✓ Branch 56 → 57 taken 2 times.
✓ Branch 58 → 59 taken 2 times.
6 done(outcome.ok(), result.value(QStringLiteral("kind")).toString(), result.value(QStringLiteral("message")).toString(),
86
2/2
✓ Branch 43 → 44 taken 2 times.
✓ Branch 44 → 45 taken 2 times.
6 result.value(QStringLiteral("errors")).toList());
87 2 });
88 2 }
89