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: 94.1% 80 / 0 / 85
Functions: 100.0% 4 / 0 / 4
Branches: 87.0% 87 / 0 / 100

data/RelationPath.cpp
Line Branch Exec Source
1 #include "RelationPath.h"
2
3 #include "RelationVocabulary.h"
4
5 #include <QCoreApplication>
6 #include <QHash>
7 #include <QSet>
8 #include <map>
9
10 namespace RelationPath {
11
12 namespace {
13
14 95 int weightOf(const RelationGraph::StoredEdge &e) {
15
2/2
✓ Branch 4 → 5 taken 31 times.
✓ Branch 4 → 6 taken 64 times.
95 if (e.role == QLatin1String("via"))
16 31 return 1;
17
2/4
✓ Branch 7 → 8 taken 48 times.
✓ Branch 7 → 9 taken 16 times.
✗ Branch 7 → 10 not taken.
✗ Branch 7 → 11 not taken.
64 switch (RelationVocabulary::categoryOf(e.type)) {
18 48 case RelationVocabulary::Category::Family:
19 case RelationVocabulary::Category::Friends:
20 48 return 2;
21 16 case RelationVocabulary::Category::Work:
22 16 return 3;
23 ✗ case RelationVocabulary::Category::Other:
24 ✗ break;
25 }
26 ✗ return 4;
27 }
28
29 7 QString tr(const char *text) { return QCoreApplication::translate("RelationPath", text); }
30
31 } // namespace
32
33 11 Path find(const RelationGraph::Input &input, qint64 from, qint64 to, int maxHops) {
34 11 Path path;
35
2/4
✓ Branch 2 → 3 taken 11 times.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11 times.
11 if (from <= 0 || to <= 0)
36 ✗ return path;
37
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 10 times.
11 if (from == to) {
38 1 path.found = true;
39
1/1
✓ Branch 6 → 7 taken 1 time.
1 path.cards = {from};
40 1 return path;
41 }
42 // S106-275: only people of the graph carry a path — an edge to a card the
43 // graph does not hold (another kind, another scope) has no one to name.
44 10 QSet<qint64> people;
45
3/3
✓ Branch 12 → 13 taken 98 times.
✓ Branch 15 → 11 taken 98 times.
✓ Branch 15 → 16 taken 10 times.
108 for (const RelationGraph::Person &person : input.people) people.insert(person.cardId);
46 10 QHash<qint64, QList<int>> adjacency;
47
2/2
✓ Branch 34 → 17 taken 87 times.
✓ Branch 34 → 35 taken 10 times.
97 for (int i = 0; i < input.edges.size(); ++i) {
48 87 const RelationGraph::StoredEdge &e = input.edges.at(i);
49
6/8
✓ Branch 18 → 19 taken 87 times.
✗ Branch 18 → 24 not taken.
✓ Branch 19 → 20 taken 87 times.
✗ Branch 19 → 24 not taken.
✓ Branch 21 → 22 taken 86 times.
✓ Branch 21 → 24 taken 1 time.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 28 taken 85 times.
173 if (e.toCardId <= 0 || e.fromCardId == e.toCardId || !people.contains(e.fromCardId) ||
50
2/2
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 25 taken 85 times.
86 !people.contains(e.toCardId))
51 2 continue;
52
2/2
✓ Branch 28 → 29 taken 85 times.
✓ Branch 29 → 30 taken 85 times.
85 adjacency[e.fromCardId].append(i);
53
2/2
✓ Branch 30 → 31 taken 85 times.
✓ Branch 31 → 32 taken 85 times.
85 adjacency[e.toCardId].append(i);
54 }
55 // (cost, hops, card) ordered: deterministic Dijkstra.
56 10 std::map<std::tuple<int, int, qint64>, bool> queue;
57 10 QHash<qint64, int> cost;
58 10 QHash<qint64, int> hops;
59 10 QHash<qint64, int> via; // card → edge index that reached it
60 10 QSet<qint64> done;
61
1/1
✓ Branch 37 → 38 taken 10 times.
10 cost.insert(from, 0);
62
1/1
✓ Branch 38 → 39 taken 10 times.
10 hops.insert(from, 0);
63
1/1
✓ Branch 40 → 41 taken 10 times.
10 queue[{0, 0, from}] = true;
64 10 int visited = 0;
65
5/6
✓ Branch 93 → 94 taken 49 times.
✓ Branch 93 → 96 taken 4 times.
✓ Branch 94 → 95 taken 49 times.
✗ Branch 94 → 96 not taken.
✓ Branch 97 → 42 taken 49 times.
✓ Branch 97 → 98 taken 4 times.
53 while (!queue.empty() && visited < RelationGraph::MaxVisited) {
66 49 const auto [c, h, card] = queue.begin()->first;
67
1/1
✓ Branch 48 → 49 taken 49 times.
49 queue.erase(queue.begin());
68
1/2
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 49 times.
49 if (done.contains(card))
69 2 continue;
70
1/1
✓ Branch 52 → 53 taken 49 times.
49 done.insert(card);
71 49 ++visited;
72
2/2
✓ Branch 53 → 54 taken 6 times.
✓ Branch 53 → 55 taken 43 times.
49 if (card == to)
73 6 break;
74
2/2
✓ Branch 55 → 56 taken 2 times.
✓ Branch 55 → 57 taken 41 times.
43 if (h >= maxHops)
75 2 continue;
76 41 QList<int> edges = adjacency.value(card);
77
3/3
✓ Branch 58 → 59 taken 41 times.
✓ Branch 59 → 60 taken 41 times.
✓ Branch 60 → 61 taken 41 times.
41 std::sort(edges.begin(), edges.end());
78
4/4
✓ Branch 61 → 62 taken 41 times.
✓ Branch 62 → 63 taken 41 times.
✓ Branch 88 → 64 taken 95 times.
✓ Branch 88 → 89 taken 41 times.
136 for (int index : edges) {
79 95 const RelationGraph::StoredEdge &e = input.edges.at(index);
80
2/2
✓ Branch 66 → 67 taken 44 times.
✓ Branch 66 → 68 taken 51 times.
95 const qint64 next = e.fromCardId == card ? e.toCardId : e.fromCardId;
81
1/1
✓ Branch 69 → 70 taken 95 times.
95 const int nextCost = c + weightOf(e);
82
8/8
✓ Branch 71 → 72 taken 60 times.
✓ Branch 71 → 76 taken 35 times.
✓ Branch 73 → 74 taken 5 times.
✓ Branch 73 → 77 taken 55 times.
✓ Branch 75 → 76 taken 4 times.
✓ Branch 75 → 77 taken 1 time.
✓ Branch 78 → 79 taken 39 times.
✓ Branch 78 → 80 taken 56 times.
95 if (done.contains(next) || (cost.contains(next) && cost.value(next) <= nextCost))
83 39 continue;
84
1/1
✓ Branch 80 → 81 taken 56 times.
56 cost.insert(next, nextCost);
85
1/1
✓ Branch 81 → 82 taken 56 times.
56 hops.insert(next, h + 1);
86
1/1
✓ Branch 82 → 83 taken 56 times.
56 via.insert(next, index);
87
1/1
✓ Branch 84 → 85 taken 56 times.
56 queue[{nextCost, h + 1, next}] = true;
88 }
89 41 }
90
2/2
✓ Branch 99 → 100 taken 4 times.
✓ Branch 99 → 101 taken 6 times.
10 if (!done.contains(to))
91 4 return path;
92 6 path.found = true;
93
2/2
✓ Branch 110 → 102 taken 19 times.
✓ Branch 110 → 111 taken 6 times.
25 for (qint64 card = to; card != from;) {
94 19 const RelationGraph::StoredEdge &e = input.edges.at(via.value(card));
95
1/1
✓ Branch 104 → 105 taken 19 times.
19 path.cards.prepend(card);
96
1/1
✓ Branch 105 → 106 taken 19 times.
19 path.steps.prepend(e);
97
1/2
✓ Branch 106 → 107 taken 19 times.
✗ Branch 106 → 108 not taken.
19 card = e.fromCardId == card ? e.toCardId : e.fromCardId;
98 }
99
1/1
✓ Branch 111 → 112 taken 6 times.
6 path.cards.prepend(from);
100 6 return path;
101 10 }
102
103 3 QString sentence(const Path &path, const QStringList &names) {
104
4/8
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 8 not taken.
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 8 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 3 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 3 times.
3 if (!path.found || path.cards.size() < 2 || names.size() != path.cards.size())
105 ✗ return {};
106 3 const QString target = names.last();
107
2/2
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 21 taken 2 times.
3 if (path.cards.size() == 2)
108
2/2
✓ Branch 16 → 17 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
2 return tr("You know %1 directly.").arg(target);
109 // Walk backwards: target through n-1, whom you know through n-2, …
110
2/2
✓ Branch 21 → 22 taken 2 times.
✓ Branch 24 → 25 taken 2 times.
2 QString text = tr("You know %1 through %2").arg(target, names.at(names.size() - 2));
111
2/2
✓ Branch 36 → 28 taken 4 times.
✓ Branch 36 → 37 taken 2 times.
6 for (int i = int(names.size()) - 3; i >= 1; --i)
112
3/3
✓ Branch 28 → 29 taken 4 times.
✓ Branch 31 → 32 taken 4 times.
✓ Branch 32 → 33 taken 4 times.
8 text += tr(", whom you know through %1").arg(names.at(i));
113
1/1
✓ Branch 39 → 40 taken 2 times.
2 return text + QLatin1Char('.');
114 3 }
115
116 } // namespace RelationPath
117