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: 90.4% 66 / 0 / 73
Functions: 100.0% 7 / 0 / 7
Branches: 81.1% 103 / 0 / 127

data/VCardExportFilter.cpp
Line Branch Exec Source
1 #include "VCardExportFilter.h"
2
3 #include <algorithm>
4
5 #include "VCardCodec.h"
6
7 #include <QSet>
8
9 namespace VCardExportFilter {
10
11 namespace {
12
13 const QSet<QString> kPersonal{
14 QStringLiteral("RELATED"), QStringLiteral("X-ABRELATEDNAMES"), QStringLiteral("NOTE"),
15 QStringLiteral("CATEGORIES"), QStringLiteral("INTEREST"), QStringLiteral("HOBBY"),
16 QStringLiteral("EXPERTISE"), QStringLiteral("X-ABDATE"), QStringLiteral("BIRTHPLACE"),
17 QStringLiteral("GEO"), QStringLiteral("X-EVOLUTION-SPOUSE"), QStringLiteral("X-EVOLUTION-MANAGER"),
18 QStringLiteral("X-EVOLUTION-ASSISTANT"), QStringLiteral("X-KADDRESSBOOK-X-SPOUSESNAME"),
19 QStringLiteral("X-KADDRESSBOOK-X-MANAGERSNAME"), QStringLiteral("X-KADDRESSBOOK-X-ASSISTANTSNAME"),
20 };
21
22 2203 bool personal(const ICal::Property &property, bool groupCard) {
23
1/1
✓ Branch 2 → 3 taken 2203 times.
2203 const QString name = VCardCodec::baseName(property);
24
7/7
✓ Branch 4 → 5 taken 1531 times.
✓ Branch 4 → 8 taken 672 times.
✓ Branch 6 → 7 taken 1531 times.
✓ Branch 7 → 8 taken 25 times.
✓ Branch 7 → 9 taken 1506 times.
✓ Branch 10 → 11 taken 697 times.
✓ Branch 10 → 12 taken 1506 times.
2203 if (kPersonal.contains(name) || name.startsWith(QLatin1String("X-MAILJD-")))
25 697 return true;
26
8/8
✓ Branch 12 → 13 taken 45 times.
✓ Branch 12 → 20 taken 1461 times.
✓ Branch 15 → 16 taken 41 times.
✓ Branch 15 → 19 taken 4 times.
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 20 taken 39 times.
✓ Branch 21 → 22 taken 6 times.
✓ Branch 21 → 23 taken 1500 times.
1506 if (groupCard && (name == QLatin1String("MEMBER") || name == QLatin1String("X-ADDRESSBOOKSERVER-MEMBER")))
27 6 return true;
28
8/13
✓ Branch 25 → 26 taken 30 times.
✓ Branch 25 → 32 taken 1470 times.
✓ Branch 29 → 30 taken 30 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 30 times.
✓ Branch 34 → 35 taken 30 times.
✓ Branch 34 → 36 taken 1470 times.
✓ Branch 36 → 37 taken 30 times.
✓ Branch 36 → 38 taken 1470 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
1530 return name == QLatin1String("ADR") && property.hasParameter(QStringLiteral("GEO"));
29 2203 }
30
31 232 bool isGroupCard(const ICal::Component &card) {
32
2/2
✓ Branch 29 → 4 taken 2841 times.
✓ Branch 29 → 30 taken 225 times.
3066 for (const ICal::Property &property : card.properties) {
33
1/1
✓ Branch 5 → 6 taken 2841 times.
2841 const QString name = VCardCodec::baseName(property);
34
6/6
✓ Branch 8 → 9 taken 2834 times.
✓ Branch 8 → 12 taken 7 times.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 17 taken 2832 times.
✓ Branch 15 → 16 taken 7 times.
✓ Branch 15 → 17 taken 2 times.
2850 if ((name == QLatin1String("KIND") || name == QLatin1String("X-ADDRESSBOOKSERVER-KIND")) &&
35
5/7
✓ Branch 12 → 13 taken 9 times.
✓ Branch 18 → 19 taken 9 times.
✓ Branch 18 → 20 taken 2832 times.
✓ Branch 20 → 21 taken 7 times.
✓ Branch 20 → 22 taken 2834 times.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 35 not taken.
2850 property.value.trimmed().compare(QLatin1String("group"), Qt::CaseInsensitive) == 0)
36 7 return true;
37 2841 }
38 225 return false;
39 }
40
41 } // namespace
42
43 namespace {
44
45 // S106-163: nested cards (a 2.1 AGENT) are checked and filtered like the
46 // card itself; they used to pass the D-22 filter verbatim.
47 140 bool containsPersonal(const ICal::Component &card) {
48 140 const bool group = isGroupCard(card);
49
2/2
✓ Branch 11 → 5 taken 926 times.
✓ Branch 11 → 12 taken 88 times.
1014 for (const ICal::Property &property : card.properties)
50
3/3
✓ Branch 6 → 7 taken 926 times.
✓ Branch 7 → 8 taken 52 times.
✓ Branch 7 → 9 taken 874 times.
926 if (personal(property, group))
51 52 return true;
52 88 return std::any_of(card.components.cbegin(), card.components.cend(), containsPersonal);
53 }
54
55 92 void filterCard(ICal::Component *card) {
56
1/1
✓ Branch 2 → 3 taken 92 times.
92 const bool group = isGroupCard(*card);
57 92 QSet<QString> droppedGroups;
58 92 QList<ICal::Property> kept;
59
4/4
✓ Branch 4 → 5 taken 92 times.
✓ Branch 5 → 6 taken 92 times.
✓ Branch 53 → 7 taken 1279 times.
✓ Branch 53 → 54 taken 92 times.
1371 for (ICal::Property property : card->properties) {
60
13/20
✓ Branch 10 → 11 taken 1279 times.
✓ Branch 12 → 13 taken 14 times.
✓ Branch 12 → 19 taken 1265 times.
✓ Branch 16 → 17 taken 14 times.
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 12 times.
✓ Branch 20 → 21 taken 14 times.
✓ Branch 20 → 22 taken 1265 times.
✓ Branch 22 → 23 taken 14 times.
✓ Branch 22 → 24 taken 1265 times.
✓ Branch 24 → 25 taken 1279 times.
✗ Branch 24 → 26 not taken.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 35 taken 1277 times.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
✗ Branch 95 → 96 not taken.
✗ Branch 95 → 97 not taken.
✗ Branch 99 → 100 not taken.
✗ Branch 99 → 101 not taken.
1293 if (VCardCodec::baseName(property) == QLatin1String("ADR") && property.hasParameter(QStringLiteral("GEO"))) {
61 // The address stays, only its pinned position goes.
62
1/1
✓ Branch 30 → 31 taken 2 times.
2 property.removeParameter(QStringLiteral("GEO"));
63
1/1
✓ Branch 33 → 34 taken 2 times.
2 kept.append(property);
64 2 continue;
65 }
66
3/3
✓ Branch 35 → 36 taken 1277 times.
✓ Branch 36 → 37 taken 651 times.
✓ Branch 36 → 46 taken 626 times.
1277 if (personal(property, group)) {
67
3/3
✓ Branch 37 → 38 taken 651 times.
✓ Branch 39 → 40 taken 35 times.
✓ Branch 39 → 44 taken 616 times.
651 if (const QString g = VCardCodec::groupOf(property); !g.isEmpty())
68
2/2
✓ Branch 40 → 41 taken 35 times.
✓ Branch 41 → 42 taken 35 times.
651 droppedGroups.insert(g.toUpper());
69 651 continue;
70 651 }
71
1/1
✓ Branch 46 → 47 taken 626 times.
626 kept.append(property);
72 1279 }
73 // Labels (X-ABLabel and other X-AB companions) of removed values go too.
74
1/1
✓ Branch 54 → 55 taken 92 times.
92 card->properties.clear();
75
4/4
✓ Branch 55 → 56 taken 92 times.
✓ Branch 56 → 57 taken 92 times.
✓ Branch 79 → 58 taken 628 times.
✓ Branch 79 → 80 taken 92 times.
720 for (const ICal::Property &property : kept) {
76
2/2
✓ Branch 59 → 60 taken 628 times.
✓ Branch 60 → 61 taken 628 times.
628 const QString g = VCardCodec::groupOf(property).toUpper();
77
6/6
✓ Branch 63 → 64 taken 49 times.
✓ Branch 63 → 67 taken 579 times.
✓ Branch 65 → 66 taken 35 times.
✓ Branch 65 → 67 taken 14 times.
✓ Branch 68 → 69 taken 35 times.
✓ Branch 68 → 70 taken 593 times.
628 if (!g.isEmpty() && droppedGroups.contains(g))
78 35 continue;
79
1/1
✓ Branch 70 → 71 taken 593 times.
593 card->properties.append(property);
80 628 }
81
4/4
✓ Branch 80 → 81 taken 92 times.
✓ Branch 81 → 82 taken 92 times.
✓ Branch 87 → 83 taken 2 times.
✓ Branch 87 → 88 taken 92 times.
94 for (ICal::Component &child : card->components)
82
1/1
✓ Branch 84 → 85 taken 2 times.
2 filterCard(&child);
83 92 }
84
85 } // namespace
86
87 140 bool hasPersonalDetails(const QString &raw) {
88 140 ICal::Component card;
89 140 QString error;
90 140 int skipped = 0;
91
2/3
✓ Branch 2 → 3 taken 140 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 140 times.
140 if (!VCardCodec::parseTree(raw, &card, &error, &skipped))
92 ✗ return false;
93 // Unreadable lines may hold anything: the export sheet asks (S106-163).
94
5/5
✓ Branch 5 → 6 taken 138 times.
✓ Branch 5 → 8 taken 2 times.
✓ Branch 6 → 7 taken 138 times.
✓ Branch 7 → 8 taken 52 times.
✓ Branch 7 → 9 taken 86 times.
140 return skipped > 0 || containsPersonal(card);
95 140 }
96
97 90 QString withoutPersonalDetails(const QString &raw) {
98 90 ICal::Component card;
99 90 QString error;
100 90 int skipped = 0;
101
2/3
✓ Branch 2 → 3 taken 90 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 90 times.
90 if (!VCardCodec::parseTree(raw, &card, &error, &skipped))
102 ✗ return raw;
103 // A card with unreadable lines is exported filtered without them — the
104 // private direction — instead of verbatim with them (S106-163).
105
1/1
✓ Branch 5 → 6 taken 90 times.
90 filterCard(&card);
106
1/1
✓ Branch 6 → 7 taken 90 times.
90 return ICal::serialize(card);
107 90 }
108
109 82 QString filterAll(const QString &vcf, bool includePersonal) {
110
1/2
✓ Branch 2 → 3 taken 82 times.
✗ Branch 2 → 4 not taken.
82 if (includePersonal)
111 82 return vcf;
112 ✗ QString out;
113 ✗ for (const QString &card : VCardCodec::splitCards(vcf))
114 ✗ out += withoutPersonalDetails(card);
115 ✗ return out;
116 ✗ }
117
118 } // namespace VCardExportFilter
119