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.5% 207 / 0 / 219
Functions: 100.0% 18 / 0 / 18
Branches: 90.5% 344 / 0 / 380

data/SieveRuleRender.cpp
Line Branch Exec Source
1 // Rendering half of the rule codec (SieveRuleCodec.h): Rule/Vacation ->
2 // Sieve bytes in the script's style, and the extensions each one needs.
3 #include "SieveRuleCodec.h"
4
5 #include <QCryptographicHash>
6
7 namespace Sieve {
8
9 namespace {
10
11 // S106-102: every string is written with the script's line end, so a
12 // dirty re-render of a CRLF script keeps the match text of its conditions.
13 753 QByteArray quoted(const QString &value, const Style &style) {
14 753 return stringLiteral(value, style.lineEnd);
15 }
16
17 677 QByteArray markerLine(const QString &name, const Style &style) {
18 677 QString clean = name;
19
1/1
✓ Branch 7 → 8 taken 677 times.
677 clean.replace(QLatin1Char('\r'), QLatin1Char(' '));
20
1/1
✓ Branch 12 → 13 taken 677 times.
677 clean.replace(QLatin1Char('\n'), QLatin1Char(' '));
21
4/4
✓ Branch 13 → 14 taken 677 times.
✓ Branch 14 → 15 taken 677 times.
✓ Branch 15 → 16 taken 677 times.
✓ Branch 16 → 17 taken 677 times.
1354 return "# rule:[" + clean.toUtf8() + "]" + style.lineEnd;
22 677 }
23
24 865 QByteArray renderCondition(const Condition &condition, const Style &style) {
25 865 QByteArray out;
26
2/2
✓ Branch 2 → 3 taken 20 times.
✓ Branch 2 → 4 taken 845 times.
865 if (condition.negated)
27
1/1
✓ Branch 3 → 4 taken 20 times.
20 out += "not ";
28
4/5
✓ Branch 4 → 5 taken 196 times.
✓ Branch 4 → 7 taken 623 times.
✓ Branch 4 → 9 taken 38 times.
✓ Branch 4 → 11 taken 8 times.
✗ Branch 4 → 13 not taken.
865 switch (condition.kind) {
29
1/1
✓ Branch 5 → 6 taken 196 times.
196 case Condition::Kind::Address: out += "address"; break;
30
1/1
✓ Branch 7 → 8 taken 623 times.
623 case Condition::Kind::Header: out += "header"; break;
31
1/1
✓ Branch 9 → 10 taken 38 times.
38 case Condition::Kind::Size: out += "size"; break;
32
1/1
✓ Branch 11 → 12 taken 8 times.
8 case Condition::Kind::Body: out += "body"; break;
33 }
34
2/2
✓ Branch 13 → 14 taken 38 times.
✓ Branch 13 → 39 taken 827 times.
865 if (condition.kind == Condition::Kind::Size) {
35
3/3
✓ Branch 14 → 15 taken 28 times.
✓ Branch 14 → 16 taken 10 times.
✓ Branch 17 → 18 taken 38 times.
38 out += condition.sizeOver ? " :over " : " :under ";
36 38 const quint64 size = condition.sizeLimit;
37
3/4
✓ Branch 18 → 19 taken 38 times.
✗ Branch 18 → 26 not taken.
✓ Branch 19 → 20 taken 22 times.
✓ Branch 19 → 26 taken 16 times.
38 if (size > 0 && size % (1024ULL * 1024) == 0)
38
3/3
✓ Branch 20 → 21 taken 22 times.
✓ Branch 21 → 22 taken 22 times.
✓ Branch 22 → 23 taken 22 times.
22 out += QByteArray::number(size / (1024ULL * 1024)) + "M";
39
2/4
✓ Branch 26 → 27 taken 16 times.
✗ Branch 26 → 34 not taken.
✓ Branch 27 → 28 taken 16 times.
✗ Branch 27 → 34 not taken.
16 else if (size > 0 && size % 1024ULL == 0)
40
3/3
✓ Branch 28 → 29 taken 16 times.
✓ Branch 29 → 30 taken 16 times.
✓ Branch 30 → 31 taken 16 times.
16 out += QByteArray::number(size / 1024ULL) + "K";
41 else
42 ✗ out += QByteArray::number(size);
43 38 return out;
44 }
45
2/2
✓ Branch 40 → 41 taken 15 times.
✓ Branch 40 → 47 taken 812 times.
827 if (!condition.comparator.isEmpty())
46
3/3
✓ Branch 41 → 42 taken 15 times.
✓ Branch 42 → 43 taken 15 times.
✓ Branch 43 → 44 taken 15 times.
15 out += " :comparator " + quoted(condition.comparator, style);
47
6/6
✓ Branch 47 → 48 taken 196 times.
✓ Branch 47 → 52 taken 631 times.
✓ Branch 50 → 51 taken 9 times.
✓ Branch 50 → 52 taken 187 times.
✓ Branch 53 → 54 taken 9 times.
✓ Branch 53 → 60 taken 818 times.
827 if (condition.kind == Condition::Kind::Address && condition.addressPart != QLatin1String("all"))
48
3/3
✓ Branch 54 → 55 taken 9 times.
✓ Branch 55 → 56 taken 9 times.
✓ Branch 56 → 57 taken 9 times.
9 out += " :" + condition.addressPart.toLatin1();
49
3/3
✓ Branch 60 → 61 taken 827 times.
✓ Branch 61 → 62 taken 827 times.
✓ Branch 62 → 63 taken 827 times.
827 out += " :" + condition.matchType.toLatin1();
50
2/2
✓ Branch 65 → 66 taken 819 times.
✓ Branch 65 → 72 taken 8 times.
827 if (condition.kind != Condition::Kind::Body)
51
3/3
✓ Branch 66 → 67 taken 819 times.
✓ Branch 67 → 68 taken 819 times.
✓ Branch 68 → 69 taken 819 times.
819 out += " " + stringListLiteral(condition.headers, style.lineEnd);
52
3/3
✓ Branch 72 → 73 taken 827 times.
✓ Branch 73 → 74 taken 827 times.
✓ Branch 74 → 75 taken 827 times.
827 out += " " + stringListLiteral(condition.values, style.lineEnd);
53 827 return out;
54 ✗ }
55
56 701 QByteArray renderTest(const Rule &rule, const Style &style) {
57
2/2
✓ Branch 3 → 4 taken 32 times.
✓ Branch 3 → 6 taken 669 times.
701 if (rule.conditions.isEmpty())
58
1/1
✓ Branch 4 → 5 taken 32 times.
32 return "true";
59
6/6
✓ Branch 7 → 8 taken 487 times.
✓ Branch 7 → 10 taken 182 times.
✓ Branch 8 → 9 taken 392 times.
✓ Branch 8 → 10 taken 95 times.
✓ Branch 11 → 12 taken 392 times.
✓ Branch 11 → 15 taken 277 times.
669 if (rule.conditions.size() == 1 && !rule.explicitList)
60
1/1
✓ Branch 13 → 14 taken 392 times.
392 return renderCondition(rule.conditions.first(), style);
61
3/3
✓ Branch 15 → 16 taken 255 times.
✓ Branch 15 → 17 taken 22 times.
✓ Branch 18 → 19 taken 277 times.
277 QByteArray out = rule.matchAll ? "allof (" : "anyof (";
62
2/2
✓ Branch 28 → 20 taken 473 times.
✓ Branch 28 → 29 taken 277 times.
750 for (int i = 0; i < rule.conditions.size(); ++i) {
63
2/2
✓ Branch 20 → 21 taken 196 times.
✓ Branch 20 → 22 taken 277 times.
473 if (i > 0)
64
1/1
✓ Branch 21 → 22 taken 196 times.
196 out += ", ";
65
2/2
✓ Branch 23 → 24 taken 473 times.
✓ Branch 24 → 25 taken 473 times.
473 out += renderCondition(rule.conditions.at(i), style);
66 }
67
1/1
✓ Branch 29 → 30 taken 277 times.
277 out += ")";
68 277 return out;
69 277 }
70
71 767 QByteArray renderAction(const Action &action, const Style &style) {
72
8/9
✓ Branch 2 → 3 taken 599 times.
✓ Branch 2 → 26 taken 12 times.
✓ Branch 2 → 42 taken 61 times.
✓ Branch 2 → 49 taken 24 times.
✓ Branch 2 → 56 taken 8 times.
✓ Branch 2 → 63 taken 36 times.
✓ Branch 2 → 64 taken 10 times.
✓ Branch 2 → 65 taken 17 times.
✗ Branch 2 → 72 not taken.
767 switch (action.kind) {
73 599 case Action::Kind::FileInto: {
74
1/1
✓ Branch 3 → 4 taken 599 times.
599 QByteArray out = "fileinto";
75
2/2
✓ Branch 4 → 5 taken 12 times.
✓ Branch 4 → 6 taken 587 times.
599 if (action.copy)
76
1/1
✓ Branch 5 → 6 taken 12 times.
12 out += " :copy";
77
2/2
✓ Branch 6 → 7 taken 8 times.
✓ Branch 6 → 8 taken 591 times.
599 if (action.create)
78
1/1
✓ Branch 7 → 8 taken 8 times.
8 out += " :create";
79
2/2
✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 16 taken 595 times.
599 if (!action.specialUse.isEmpty())
80
3/3
✓ Branch 10 → 11 taken 4 times.
✓ Branch 11 → 12 taken 4 times.
✓ Branch 12 → 13 taken 4 times.
4 out += " :specialuse " + quoted(action.specialUse, style);
81
4/4
✓ Branch 16 → 17 taken 599 times.
✓ Branch 17 → 18 taken 599 times.
✓ Branch 18 → 19 taken 599 times.
✓ Branch 19 → 20 taken 599 times.
599 return out + " " + quoted(action.target, style) + ";";
82 599 }
83 12 case Action::Kind::Redirect:
84
4/5
✓ Branch 27 → 28 taken 12 times.
✗ Branch 27 → 29 not taken.
✓ Branch 30 → 31 taken 12 times.
✓ Branch 31 → 32 taken 12 times.
✓ Branch 32 → 33 taken 12 times.
24 return QByteArray("redirect") + (action.copy ? " :copy" : "") + " " +
85
3/3
✓ Branch 26 → 27 taken 12 times.
✓ Branch 33 → 34 taken 12 times.
✓ Branch 34 → 35 taken 12 times.
36 quoted(action.target, style) + ";";
86
3/3
✓ Branch 42 → 43 taken 61 times.
✓ Branch 43 → 44 taken 61 times.
✓ Branch 44 → 45 taken 61 times.
61 case Action::Kind::AddFlag: return "addflag " + stringListLiteral(action.flags, style.lineEnd) + ";";
87
3/3
✓ Branch 49 → 50 taken 24 times.
✓ Branch 50 → 51 taken 24 times.
✓ Branch 51 → 52 taken 24 times.
24 case Action::Kind::SetFlag: return "setflag " + stringListLiteral(action.flags, style.lineEnd) + ";";
88 8 case Action::Kind::RemoveFlag:
89
3/3
✓ Branch 56 → 57 taken 8 times.
✓ Branch 57 → 58 taken 8 times.
✓ Branch 58 → 59 taken 8 times.
8 return "removeflag " + stringListLiteral(action.flags, style.lineEnd) + ";";
90 36 case Action::Kind::Keep: return "keep;";
91 10 case Action::Kind::Discard: return "discard;";
92
3/3
✓ Branch 65 → 66 taken 17 times.
✓ Branch 66 → 67 taken 17 times.
✓ Branch 67 → 68 taken 17 times.
17 case Action::Kind::Reject: return "reject " + stringLiteral(action.target, style.lineEnd) + ";";
93 }
94 ✗ return {};
95 }
96
97 // `braceOnOwnLine` is forced for the disabled form: its test is a comment
98 // up to the end of the line, so a "{" on that line would be commented out.
99 738 QByteArray renderBlockBody(const QList<QByteArray> &commands, const Style &style,
100 bool braceOnOwnLine) {
101
2/2
✓ Branch 2 → 3 taken 679 times.
✓ Branch 2 → 4 taken 59 times.
738 QByteArray out = braceOnOwnLine ? style.lineEnd + "{" : QByteArray(" {");
102
1/1
✓ Branch 5 → 6 taken 738 times.
738 out += style.lineEnd;
103
2/2
✓ Branch 16 → 8 taken 1253 times.
✓ Branch 16 → 17 taken 738 times.
1991 for (const QByteArray &command : commands)
104
3/3
✓ Branch 9 → 10 taken 1253 times.
✓ Branch 10 → 11 taken 1253 times.
✓ Branch 11 → 12 taken 1253 times.
1253 out += style.indent + command + style.lineEnd;
105
2/2
✓ Branch 17 → 18 taken 738 times.
✓ Branch 18 → 19 taken 738 times.
738 out += "}" + style.lineEnd;
106 738 return out;
107 ✗ }
108
109 738 QByteArray renderIfHeader(const QByteArray &test, bool enabled) {
110
2/2
✓ Branch 2 → 3 taken 562 times.
✓ Branch 2 → 5 taken 176 times.
738 if (enabled)
111
1/1
✓ Branch 3 → 4 taken 562 times.
562 return "if " + test;
112 // Roundcube's disabled form keeps the test as a comment (D-3). S106-089:
113 // a test that spans lines (a multi-line string) continues on "# " lines,
114 // so every line of it stays commented out (decoded by disabledTest()).
115
1/1
✓ Branch 5 → 6 taken 176 times.
176 QByteArray out = "if false # ";
116
2/2
✓ Branch 19 → 7 taken 7777 times.
✓ Branch 19 → 20 taken 176 times.
7953 for (int i = 0; i < test.size(); ++i) {
117
1/1
✓ Branch 8 → 9 taken 7777 times.
7777 out += test.at(i);
118
6/6
✓ Branch 10 → 11 taken 4 times.
✓ Branch 10 → 14 taken 7773 times.
✓ Branch 12 → 13 taken 3 times.
✓ Branch 12 → 14 taken 1 time.
✓ Branch 15 → 16 taken 3 times.
✓ Branch 15 → 17 taken 7774 times.
7777 if (test.at(i) == '\n' && i + 1 < test.size())
119
1/1
✓ Branch 16 → 17 taken 3 times.
3 out += "# ";
120 }
121 176 return out;
122 176 }
123
124 24 QByteArray dateTest(const QString &zone, const char *relation, const QDate &day,
125 const Style &style) {
126 24 QByteArray out = "currentdate";
127
2/2
✓ Branch 4 → 5 taken 19 times.
✓ Branch 4 → 11 taken 5 times.
24 if (!zone.isEmpty())
128
3/3
✓ Branch 5 → 6 taken 19 times.
✓ Branch 6 → 7 taken 19 times.
✓ Branch 7 → 8 taken 19 times.
19 out += " :zone " + quoted(zone, style);
129
3/3
✓ Branch 13 → 14 taken 24 times.
✓ Branch 14 → 15 taken 24 times.
✓ Branch 15 → 16 taken 24 times.
48 out += QByteArray(" :value \"") + relation + "\" \"date\" " +
130
4/4
✓ Branch 11 → 12 taken 24 times.
✓ Branch 12 → 13 taken 24 times.
✓ Branch 16 → 17 taken 24 times.
✓ Branch 17 → 18 taken 24 times.
72 quoted(day.toString(Qt::ISODate), style);
131 24 return out;
132 ✗ }
133
134 37 QByteArray vacationTest(const Vacation &vacation, const Style &style) {
135 37 QList<QByteArray> tests;
136
3/3
✓ Branch 2 → 3 taken 37 times.
✓ Branch 3 → 4 taken 12 times.
✓ Branch 3 → 8 taken 25 times.
37 if (vacation.firstDay.isValid())
137
2/2
✓ Branch 4 → 5 taken 12 times.
✓ Branch 5 → 6 taken 12 times.
12 tests.append(dateTest(vacation.zone, "ge", vacation.firstDay, style));
138
3/3
✓ Branch 8 → 9 taken 37 times.
✓ Branch 9 → 10 taken 12 times.
✓ Branch 9 → 14 taken 25 times.
37 if (vacation.lastDay.isValid())
139
2/2
✓ Branch 10 → 11 taken 12 times.
✓ Branch 11 → 12 taken 12 times.
12 tests.append(dateTest(vacation.zone, "le", vacation.lastDay, style));
140
2/2
✓ Branch 15 → 16 taken 24 times.
✓ Branch 15 → 18 taken 13 times.
37 if (tests.isEmpty())
141
1/1
✓ Branch 16 → 17 taken 24 times.
24 return "true";
142
2/2
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 22 taken 11 times.
13 if (tests.size() == 1)
143
1/1
✓ Branch 20 → 21 taken 2 times.
2 return tests.first();
144
4/4
✓ Branch 24 → 25 taken 11 times.
✓ Branch 25 → 26 taken 11 times.
✓ Branch 26 → 27 taken 11 times.
✓ Branch 27 → 28 taken 11 times.
11 return "allof (" + tests.at(0) + ", " + tests.at(1) + ")";
145 37 }
146
147 1953 void appendUnique(QStringList *list, const QString &value) {
148
2/2
✓ Branch 3 → 4 taken 1941 times.
✓ Branch 3 → 5 taken 12 times.
1953 if (!list->contains(value))
149 1941 list->append(value);
150 1953 }
151
152 } // namespace
153
154 701 QByteArray renderRule(const Rule &rule, const Style &style) {
155 701 QList<QByteArray> commands;
156
2/2
✓ Branch 10 → 4 taken 767 times.
✓ Branch 10 → 11 taken 701 times.
1468 for (const Action &action : rule.actions)
157
2/2
✓ Branch 5 → 6 taken 767 times.
✓ Branch 6 → 7 taken 767 times.
767 commands.append(renderAction(action, style));
158
2/2
✓ Branch 11 → 12 taken 449 times.
✓ Branch 11 → 16 taken 252 times.
701 if (rule.stop)
159
2/2
✓ Branch 12 → 13 taken 449 times.
✓ Branch 13 → 14 taken 449 times.
449 commands.append("stop;");
160 701 QByteArray out;
161
2/2
✓ Branch 17 → 18 taken 640 times.
✓ Branch 17 → 22 taken 61 times.
701 if (!rule.name.isEmpty())
162
2/2
✓ Branch 18 → 19 taken 640 times.
✓ Branch 19 → 20 taken 640 times.
640 out += markerLine(rule.name, style);
163
3/3
✓ Branch 22 → 23 taken 701 times.
✓ Branch 23 → 24 taken 701 times.
✓ Branch 24 → 25 taken 701 times.
701 out += renderIfHeader(renderTest(rule, style), rule.enabled);
164
6/6
✓ Branch 27 → 28 taken 86 times.
✓ Branch 27 → 29 taken 615 times.
✓ Branch 28 → 29 taken 28 times.
✓ Branch 28 → 30 taken 58 times.
✓ Branch 31 → 32 taken 701 times.
✓ Branch 32 → 33 taken 701 times.
701 out += renderBlockBody(commands, style, style.braceOnOwnLine || !rule.enabled);
165 701 return out;
166 701 }
167
168 37 QByteArray renderVacation(const Vacation &vacation, const QString &name, const Style &style) {
169 // S106-094: days 0 = ":days" was not given (the server default applies).
170
1/1
✓ Branch 2 → 3 taken 37 times.
37 QByteArray command = "vacation";
171
2/2
✓ Branch 3 → 4 taken 36 times.
✓ Branch 3 → 10 taken 1 time.
37 if (vacation.days > 0)
172
3/3
✓ Branch 4 → 5 taken 36 times.
✓ Branch 5 → 6 taken 36 times.
✓ Branch 6 → 7 taken 36 times.
36 command += " :days " + QByteArray::number(vacation.days);
173
2/2
✓ Branch 11 → 12 taken 35 times.
✓ Branch 11 → 18 taken 2 times.
37 if (!vacation.subject.isEmpty())
174
3/3
✓ Branch 12 → 13 taken 35 times.
✓ Branch 13 → 14 taken 35 times.
✓ Branch 14 → 15 taken 35 times.
35 command += " :subject " + quoted(vacation.subject, style);
175
2/2
✓ Branch 19 → 20 taken 9 times.
✓ Branch 19 → 26 taken 28 times.
37 if (!vacation.from.isEmpty())
176
3/3
✓ Branch 20 → 21 taken 9 times.
✓ Branch 21 → 22 taken 9 times.
✓ Branch 22 → 23 taken 9 times.
9 command += " :from " + quoted(vacation.from, style);
177
2/2
✓ Branch 27 → 28 taken 31 times.
✓ Branch 27 → 49 taken 6 times.
37 if (!vacation.addresses.isEmpty()) {
178
1/1
✓ Branch 28 → 29 taken 31 times.
31 QByteArray list = "[";
179
2/2
✓ Branch 41 → 30 taken 36 times.
✓ Branch 41 → 42 taken 31 times.
67 for (int i = 0; i < vacation.addresses.size(); ++i)
180
5/5
✓ Branch 31 → 32 taken 36 times.
✓ Branch 32 → 33 taken 5 times.
✓ Branch 32 → 34 taken 31 times.
✓ Branch 35 → 36 taken 36 times.
✓ Branch 36 → 37 taken 36 times.
36 list += (i > 0 ? ", " : "") + quoted(vacation.addresses.at(i), style);
181
3/3
✓ Branch 42 → 43 taken 31 times.
✓ Branch 43 → 44 taken 31 times.
✓ Branch 44 → 45 taken 31 times.
31 command += " :addresses " + list + "]";
182 31 }
183 37 QString message = vacation.message;
184
8/8
✓ Branch 52 → 53 taken 37 times.
✓ Branch 53 → 54 taken 7 times.
✓ Branch 53 → 59 taken 30 times.
✓ Branch 56 → 57 taken 7 times.
✓ Branch 57 → 58 taken 2 times.
✓ Branch 57 → 59 taken 5 times.
✓ Branch 60 → 61 taken 2 times.
✓ Branch 60 → 65 taken 35 times.
37 if (message.contains(QLatin1Char('\n')) && !message.endsWith(QLatin1Char('\n')))
185
1/1
✓ Branch 63 → 64 taken 2 times.
2 message += QLatin1Char('\n');
186
4/4
✓ Branch 65 → 66 taken 37 times.
✓ Branch 66 → 67 taken 37 times.
✓ Branch 67 → 68 taken 37 times.
✓ Branch 68 → 69 taken 37 times.
37 command += " " + stringLiteral(message, style.lineEnd) + ";";
187
5/7
✓ Branch 73 → 74 taken 1 time.
✓ Branch 73 → 77 taken 36 times.
✓ Branch 78 → 79 taken 37 times.
✓ Branch 80 → 81 taken 1 time.
✓ Branch 80 → 82 taken 36 times.
✗ Branch 154 → 155 not taken.
✗ Branch 154 → 156 not taken.
38 QByteArray out = markerLine(name.isEmpty() ? QStringLiteral("Out of office") : name, style);
188
3/3
✓ Branch 82 → 83 taken 37 times.
✓ Branch 83 → 84 taken 37 times.
✓ Branch 84 → 85 taken 37 times.
37 out += renderIfHeader(vacationTest(vacation, style), vacation.enabled);
189
7/10
✓ Branch 87 → 88 taken 1 time.
✓ Branch 87 → 89 taken 36 times.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 90 taken 1 time.
✓ Branch 93 → 94 taken 37 times.
✓ Branch 94 → 95 taken 37 times.
✓ Branch 98 → 99 taken 37 times.
✓ Branch 98 → 100 taken 37 times.
✗ Branch 170 → 171 not taken.
✗ Branch 170 → 172 not taken.
111 out += renderBlockBody({command}, style, style.braceOnOwnLine || !vacation.enabled);
190 37 return out;
191 74 }
192
193 1804 QStringList extensionsFor(const Rule &rule) {
194 1804 QStringList extensions;
195
2/2
✓ Branch 45 → 4 taken 2051 times.
✓ Branch 45 → 46 taken 1804 times.
3855 for (const Condition &condition : rule.conditions) {
196
2/2
✓ Branch 7 → 8 taken 12 times.
✓ Branch 7 → 15 taken 2039 times.
2051 if (condition.matchType == QLatin1String("regex"))
197
1/1
✓ Branch 11 → 12 taken 12 times.
12 appendUnique(&extensions, QStringLiteral("regex"));
198
2/2
✓ Branch 15 → 16 taken 10 times.
✓ Branch 15 → 23 taken 2041 times.
2051 if (condition.kind == Condition::Kind::Body)
199
1/1
✓ Branch 19 → 20 taken 10 times.
10 appendUnique(&extensions, QStringLiteral("body"));
200 2051 if (!condition.comparator.isEmpty() &&
201
4/4
✓ Branch 24 → 25 taken 14 times.
✓ Branch 24 → 32 taken 2037 times.
✓ Branch 27 → 28 taken 10 times.
✓ Branch 27 → 32 taken 4 times.
2061 condition.comparator != QLatin1String("i;ascii-casemap") &&
202
4/4
✓ Branch 30 → 31 taken 6 times.
✓ Branch 30 → 32 taken 4 times.
✓ Branch 33 → 34 taken 6 times.
✓ Branch 33 → 43 taken 2045 times.
2061 condition.comparator != QLatin1String("i;octet"))
203
2/2
✓ Branch 37 → 38 taken 6 times.
✓ Branch 38 → 39 taken 6 times.
12 appendUnique(&extensions, QStringLiteral("comparator-") + condition.comparator);
204 }
205
2/2
✓ Branch 99 → 48 taken 1957 times.
✓ Branch 99 → 100 taken 1804 times.
3761 for (const Action &action : rule.actions) {
206
4/4
✓ Branch 49 → 50 taken 1682 times.
✓ Branch 49 → 74 taken 169 times.
✓ Branch 49 → 81 taken 23 times.
✓ Branch 49 → 88 taken 83 times.
1957 switch (action.kind) {
207 1682 case Action::Kind::FileInto:
208
1/1
✓ Branch 53 → 54 taken 1682 times.
1682 appendUnique(&extensions, QStringLiteral("fileinto"));
209
2/2
✓ Branch 56 → 57 taken 8 times.
✓ Branch 56 → 64 taken 1674 times.
1682 if (action.create)
210
1/1
✓ Branch 60 → 61 taken 8 times.
8 appendUnique(&extensions, QStringLiteral("mailbox"));
211
2/2
✓ Branch 65 → 66 taken 6 times.
✓ Branch 65 → 73 taken 1676 times.
1682 if (!action.specialUse.isEmpty())
212
1/1
✓ Branch 69 → 70 taken 6 times.
6 appendUnique(&extensions, QStringLiteral("special-use"));
213 1682 break;
214 169 case Action::Kind::AddFlag:
215 case Action::Kind::SetFlag:
216 case Action::Kind::RemoveFlag:
217
1/1
✓ Branch 77 → 78 taken 169 times.
169 appendUnique(&extensions, QStringLiteral("imap4flags"));
218 169 break;
219 23 case Action::Kind::Reject:
220
1/1
✓ Branch 84 → 85 taken 23 times.
23 appendUnique(&extensions, QStringLiteral("reject"));
221 23 break;
222 83 default:
223 83 break;
224 }
225
2/2
✓ Branch 89 → 90 taken 37 times.
✓ Branch 89 → 97 taken 1920 times.
1957 if (action.copy)
226
1/1
✓ Branch 93 → 94 taken 37 times.
37 appendUnique(&extensions, QStringLiteral("copy"));
227 }
228 1804 return extensions;
229 ✗ }
230
231 22 QStringList extensionsFor(const Vacation &vacation) {
232
2/4
✓ Branch 7 → 8 taken 22 times.
✓ Branch 7 → 9 taken 22 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
44 QStringList extensions{QStringLiteral("vacation")};
233
2/3
✓ Branch 11 → 12 taken 22 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 20 taken 22 times.
22 if (vacation.subject.contains(QLatin1String("${")))
234 ✗ extensions.append(QStringLiteral("variables"));
235
8/8
✓ Branch 20 → 21 taken 22 times.
✓ Branch 21 → 22 taken 10 times.
✓ Branch 21 → 24 taken 12 times.
✓ Branch 22 → 23 taken 10 times.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 25 taken 9 times.
✓ Branch 26 → 27 taken 13 times.
✓ Branch 26 → 40 taken 9 times.
22 if (vacation.firstDay.isValid() || vacation.lastDay.isValid()) {
236
1/1
✓ Branch 30 → 31 taken 13 times.
13 extensions.append(QStringLiteral("date"));
237
1/1
✓ Branch 36 → 37 taken 13 times.
13 extensions.append(QStringLiteral("relational"));
238 }
239 22 return extensions;
240 44 }
241
242 namespace {
243
244 230382 bool representable(const QStringList &values) {
245
2/2
✓ Branch 10 → 4 taken 166320 times.
✓ Branch 10 → 11 taken 230380 times.
396700 for (const QString &value : values)
246
3/3
✓ Branch 5 → 6 taken 166320 times.
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 8 taken 166318 times.
166320 if (!representableString(value))
247 2 return false;
248 230380 return true;
249 }
250
251 } // namespace
252
253 72131 bool representable(const Rule &rule) {
254
2/2
✓ Branch 17 → 4 taken 76428 times.
✓ Branch 17 → 18 taken 72129 times.
148557 for (const Condition &condition : rule.conditions)
255
7/8
✓ Branch 5 → 6 taken 76428 times.
✓ Branch 6 → 7 taken 76428 times.
✗ Branch 6 → 11 not taken.
✓ Branch 7 → 8 taken 76428 times.
✓ Branch 8 → 9 taken 76426 times.
✓ Branch 8 → 11 taken 2 times.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 15 taken 76426 times.
152854 if (!representable(condition.headers) || !representable(condition.values) ||
256
2/3
✓ Branch 9 → 10 taken 76426 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 76426 times.
76426 !representableString(condition.comparator))
257 2 return false;
258
2/2
✓ Branch 33 → 20 taken 77288 times.
✓ Branch 33 → 34 taken 72129 times.
149417 for (const Action &action : rule.actions)
259
5/8
✓ Branch 21 → 22 taken 77288 times.
✓ Branch 22 → 23 taken 77288 times.
✗ Branch 22 → 27 not taken.
✓ Branch 23 → 24 taken 77288 times.
✓ Branch 24 → 25 taken 77288 times.
✗ Branch 24 → 27 not taken.
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 31 taken 77288 times.
154576 if (!representableString(action.target) || !representable(action.flags) ||
260
2/3
✓ Branch 25 → 26 taken 77288 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 77288 times.
77288 !representableString(action.specialUse))
261 ✗ return false;
262 72129 return true;
263 }
264
265 238 bool representable(const Vacation &vacation) {
266
1/2
✓ Branch 5 → 6 taken 238 times.
✗ Branch 5 → 13 not taken.
476 return representableString(vacation.subject) && representableString(vacation.message) &&
267
3/6
✓ Branch 3 → 4 taken 238 times.
✗ Branch 3 → 13 not taken.
✓ Branch 7 → 8 taken 238 times.
✗ Branch 7 → 13 not taken.
✓ Branch 9 → 10 taken 238 times.
✗ Branch 9 → 13 not taken.
714 representableString(vacation.from) && representable(vacation.addresses) &&
268
1/2
✓ Branch 11 → 12 taken 238 times.
✗ Branch 11 → 13 not taken.
476 representableString(vacation.zone);
269 }
270
271 20004 QString Block::hash() const {
272 20004 QByteArray bytes = original;
273
3/6
✓ Branch 3 → 4 taken 20004 times.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 20004 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 17 taken 20004 times.
20004 if (dirty || bytes.isEmpty()) {
274 ✗ const Style style;
275 ✗ bytes = kind == BlockKind::Vacation ? renderVacation(vacation, name, style)
276 ✗ : renderRule(rule, style);
277 ✗ }
278
3/3
✓ Branch 18 → 19 taken 20004 times.
✓ Branch 19 → 20 taken 20004 times.
✓ Branch 20 → 21 taken 20004 times.
40008 return QString::fromLatin1(QCryptographicHash::hash(bytes, QCryptographicHash::Sha256).toHex());
279 20004 }
280
281 } // namespace Sieve
282