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: 100.0% 52 / 0 / 52
Functions: 100.0% 4 / 0 / 4
Branches: 86.0% 86 / 0 / 100

data/SendChecks.cpp
Line Branch Exec Source
1 #include "SendChecks.h"
2
3 #include "IdentityChoice.h"
4
5 #include <QRegularExpression>
6
7 namespace SendChecks {
8
9 65 QStringList defaultAttachmentWords() {
10 65 return {QStringLiteral("attached"), QStringLiteral("attachment"), QStringLiteral("attachments"),
11 65 QStringLiteral("enclosed"), QStringLiteral("see the file"), QStringLiteral("anbei"),
12 65 QStringLiteral("Anhang"), QStringLiteral("angehängt"), QStringLiteral("im Anhang"),
13
2/4
✓ Branch 37 → 38 taken 715 times.
✓ Branch 37 → 39 taken 65 times.
✗ Branch 53 → 54 not taken.
✗ Branch 53 → 55 not taken.
845 QStringLiteral("beigefügt"), QStringLiteral("Anlage")};
14 780 }
15
16 53 QString attachmentMention(const QString &text, const QStringList &words) {
17
2/2
✓ Branch 55 → 4 taken 521 times.
✓ Branch 55 → 56 taken 43 times.
564 for (const QString &word : words) {
18
1/1
✓ Branch 5 → 6 taken 521 times.
521 const QString trimmed = word.trimmed();
19
3/6
✓ Branch 7 → 8 taken 521 times.
✗ Branch 7 → 10 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 521 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 521 times.
521 if (trimmed.isEmpty() || trimmed.size() > 100) continue;
20 // Whole words: no letter directly before or after the phrase.
21
2/2
✓ Branch 18 → 19 taken 521 times.
✓ Branch 22 → 23 taken 521 times.
1563 const QRegularExpression pattern(QStringLiteral("(?<![\\p{L}\\p{N}])") + QRegularExpression::escape(trimmed) +
22
1/1
✓ Branch 23 → 24 taken 521 times.
1563 QStringLiteral("(?![\\p{L}\\p{N}])"),
23
1/1
✓ Branch 24 → 25 taken 521 times.
1042 QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption);
24
1/1
✓ Branch 33 → 34 taken 521 times.
521 const auto match = pattern.match(text);
25
4/4
✓ Branch 34 → 35 taken 521 times.
✓ Branch 35 → 36 taken 10 times.
✓ Branch 35 → 38 taken 511 times.
✓ Branch 36 → 37 taken 10 times.
521 if (match.hasMatch()) return match.captured();
26 541 }
27 43 return {};
28 }
29
30 namespace {
31 80 QString domainOf(const QString &address) {
32 80 const qsizetype at = address.lastIndexOf(QLatin1Char('@'));
33
4/8
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 80 times.
✓ Branch 7 → 8 taken 80 times.
✓ Branch 8 → 9 taken 80 times.
✓ Branch 10 → 11 taken 80 times.
✗ Branch 10 → 12 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
160 return at < 0 ? QString() : address.mid(at + 1).toLower();
34 }
35 } // namespace
36
37 59 QList<Finding> check(const Input &input) {
38 59 QList<Finding> findings;
39
9/10
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 11 taken 50 times.
✓ Branch 5 → 6 taken 9 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 8 times.
✓ Branch 7 → 11 taken 1 time.
✓ Branch 9 → 10 taken 3 times.
✓ Branch 9 → 11 taken 5 times.
✓ Branch 12 → 13 taken 3 times.
✓ Branch 12 → 16 taken 56 times.
59 if (input.to.isEmpty() && input.cc.isEmpty() && input.bcc.isEmpty() && input.invalidRecipients.isEmpty())
40
1/1
✓ Branch 13 → 14 taken 3 times.
3 findings.append({Kind::NoRecipient, {}, {}, 0, true});
41
2/2
✓ Branch 24 → 18 taken 16 times.
✓ Branch 24 → 25 taken 59 times.
75 for (const QString &address : input.invalidRecipients)
42 16 findings.append({Kind::InvalidRecipient, address, {}, 0, true});
43
4/4
✓ Branch 25 → 26 taken 59 times.
✓ Branch 28 → 29 taken 8 times.
✓ Branch 28 → 32 taken 51 times.
✓ Branch 29 → 30 taken 8 times.
59 if (input.subject.trimmed().isEmpty()) findings.append({Kind::EmptySubject, {}, {}, 0, false});
44
2/2
✓ Branch 32 → 33 taken 45 times.
✓ Branch 32 → 47 taken 14 times.
59 if (input.attachmentCount == 0) {
45 const QString word = attachmentMention(
46
4/4
✓ Branch 34 → 35 taken 14 times.
✓ Branch 34 → 36 taken 31 times.
✓ Branch 35 → 37 taken 14 times.
✓ Branch 37 → 38 taken 45 times.
45 input.newText, input.attachmentWords.isEmpty() ? defaultAttachmentWords() : input.attachmentWords);
47
2/2
✓ Branch 40 → 41 taken 4 times.
✓ Branch 40 → 45 taken 41 times.
49 if (!word.isEmpty()) findings.append({Kind::ForgottenAttachment, word, {}, 0, false});
48 45 }
49
2/2
✓ Branch 55 → 49 taken 1 time.
✓ Branch 55 → 56 taken 59 times.
60 for (const QString &file : input.filesOverLimit) findings.append({Kind::FileTooLarge, file, {}, 0, true});
50
5/6
✓ Branch 57 → 58 taken 55 times.
✓ Branch 57 → 60 taken 4 times.
✓ Branch 58 → 59 taken 55 times.
✗ Branch 58 → 60 not taken.
✓ Branch 61 → 62 taken 55 times.
✓ Branch 61 → 81 taken 4 times.
59 if (input.bcc.isEmpty() && !input.invitation) {
51 55 int external = 0;
52
2/2
✓ Branch 76 → 64 taken 110 times.
✓ Branch 76 → 77 taken 55 times.
165 for (const QStringList *field : {&input.to, &input.cc})
53
2/2
✓ Branch 74 → 66 taken 80 times.
✓ Branch 74 → 75 taken 110 times.
190 for (const QString &address : *field)
54
3/3
✓ Branch 67 → 68 taken 80 times.
✓ Branch 70 → 71 taken 35 times.
✓ Branch 70 → 72 taken 45 times.
80 if (!input.ownDomains.contains(domainOf(address))) ++external;
55
2/2
✓ Branch 77 → 78 taken 1 time.
✓ Branch 77 → 81 taken 54 times.
55 if (external >= input.manyRecipientsThreshold)
56
1/1
✓ Branch 78 → 79 taken 1 time.
1 findings.append({Kind::ManyWithoutBcc, {}, {}, external, false});
57 }
58
5/6
✓ Branch 82 → 83 taken 4 times.
✓ Branch 82 → 86 taken 55 times.
✓ Branch 84 → 85 taken 4 times.
✗ Branch 84 → 86 not taken.
✓ Branch 87 → 88 taken 4 times.
✓ Branch 87 → 102 taken 55 times.
59 if (!input.originalSentTo.isEmpty() && !input.identityAddress.isEmpty()) {
59
2/2
✓ Branch 88 → 89 taken 4 times.
✓ Branch 89 → 90 taken 4 times.
4 const QString original = IdentityChoice::withoutPlusTag(input.originalSentTo.toLower());
60
3/3
✓ Branch 91 → 92 taken 4 times.
✓ Branch 94 → 95 taken 1 time.
✓ Branch 94 → 100 taken 3 times.
4 if (original != input.identityAddress.toLower())
61 1 findings.append({Kind::IdentityDiffers, input.originalSentTo, input.identityAddress, 0, false});
62 4 }
63
2/2
✓ Branch 110 → 104 taken 1 time.
✓ Branch 110 → 111 taken 59 times.
60 for (const QString &placeholder : input.placeholders)
64 1 findings.append({Kind::Placeholder, placeholder, {}, 0, false});
65
5/6
✓ Branch 111 → 112 taken 1 time.
✓ Branch 111 → 115 taken 58 times.
✓ Branch 113 → 114 taken 1 time.
✗ Branch 113 → 115 not taken.
✓ Branch 116 → 117 taken 1 time.
✓ Branch 116 → 121 taken 58 times.
60 if (input.invitation && !input.bcc.isEmpty()) findings.append({Kind::InvitationBcc, {}, {}, int(input.bcc.size()), true});
66
3/4
✓ Branch 121 → 122 taken 1 time.
✓ Branch 121 → 126 taken 58 times.
✓ Branch 122 → 123 taken 1 time.
✗ Branch 122 → 126 not taken.
59 if (input.serverScheduledInvitation && input.invitationLosesContent)
67
1/1
✓ Branch 123 → 124 taken 1 time.
1 findings.append({Kind::ServerInvitationLoses, {}, {}, 0, false});
68
3/3
✓ Branch 126 → 127 taken 1 time.
✓ Branch 126 → 130 taken 58 times.
✓ Branch 127 → 128 taken 1 time.
59 if (input.replyWithoutQuote) findings.append({Kind::QuoteUnavailable, {}, {}, 0, false});
69 59 return findings;
70 24 }
71
72 } // namespace SendChecks
73