1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2026 Project Tick
// SPDX-FileContributor: Project Tick Team
#include <QTest>
#include <logs/LogEventParser.hpp>
using projt::logs::LogEventParser;
class LogEventParserTest : public QObject
{
Q_OBJECT
private slots:
void parseLog4jComplete()
{
LogEventParser parser;
const QString xml =
"<log4j:Event logger=\"Test.Logger\" timestamp=\"1700000000\" level=\"WARN\" thread=\"Main\">"
"<log4j:Message>Hello World</log4j:Message>"
"</log4j:Event>";
parser.pushLine(xml);
auto item = parser.popNext();
QVERIFY(item.has_value());
QVERIFY(std::holds_alternative<LogEventParser::LogRecord>(item.value()));
auto entry = std::get<LogEventParser::LogRecord>(item.value());
QCOMPARE(entry.logger, QStringLiteral("Test.Logger"));
QCOMPARE(entry.levelText, QStringLiteral("WARN"));
QCOMPARE(entry.level, MessageLevel::Warning);
QCOMPARE(entry.thread, QStringLiteral("Main"));
QCOMPARE(entry.message, QStringLiteral("Hello World"));
QCOMPARE(entry.timestamp.toSecsSinceEpoch(), 1700000000LL);
}
void parseLog4jMissingLogger()
{
LogEventParser parser;
const QString xml = "<log4j:Event timestamp=\"1700000000\" level=\"INFO\" thread=\"Main\">"
"<log4j:Message>Missing logger</log4j:Message>"
"</log4j:Event>";
parser.pushLine(xml);
auto item = parser.popNext();
QVERIFY(!item.has_value());
auto err = parser.lastError();
QVERIFY(err.has_value());
QVERIFY(err->message.contains(QStringLiteral("missing logger"), Qt::CaseInsensitive));
}
void parseLog4jPendingChunk()
{
LogEventParser parser;
const QString partial =
"<log4j:Event logger=\"Test.Logger\" timestamp=\"1700000000\" level=\"INFO\" thread=\"Main\">"
"<log4j:Message>Partial";
const QString remainder = "</log4j:Message></log4j:Event>";
parser.pushLine(partial);
auto first = parser.popNext();
QVERIFY(first.has_value());
QVERIFY(std::holds_alternative<LogEventParser::PendingChunk>(first.value()));
parser.pushLine(remainder);
auto second = parser.popNext();
QVERIFY(second.has_value());
QVERIFY(std::holds_alternative<LogEventParser::LogRecord>(second.value()));
auto entry = std::get<LogEventParser::LogRecord>(second.value());
QCOMPARE(entry.message, QStringLiteral("Partial"));
}
void parseLog4jLeadingWhitespace()
{
LogEventParser parser;
const QString xml =
" <log4j:Event logger=\"Test.Logger\" timestamp=\"1700000000\" level=\"INFO\" thread=\"Main\">"
"<log4j:Message>Whitespace</log4j:Message>"
"</log4j:Event>";
parser.pushLine(xml);
auto item = parser.popNext();
QVERIFY(item.has_value());
QVERIFY(std::holds_alternative<LogEventParser::LogRecord>(item.value()));
}
void guessLevelFromLine_data()
{
QTest::addColumn<QString>("line");
QTest::addColumn<int>("fallback");
QTest::addColumn<int>("expected");
QTest::newRow("header-info") << "[12:34:56] [Server thread/INFO] Hello"
<< static_cast<int>(MessageLevel::Unknown) << static_cast<int>(MessageLevel::Info);
QTest::newRow("bracket-severe") << "[SEVERE] Something bad" << static_cast<int>(MessageLevel::Unknown)
<< static_cast<int>(MessageLevel::Error);
QTest::newRow("warning-tag") << "[WARNING] Potential issue" << static_cast<int>(MessageLevel::Unknown)
<< static_cast<int>(MessageLevel::Warning);
QTest::newRow("fatal-overwrite") << "overwriting existing" << static_cast<int>(MessageLevel::Unknown)
<< static_cast<int>(MessageLevel::Fatal);
QTest::newRow("fallback-preserved")
<< "overwriting existing" << static_cast<int>(MessageLevel::Info) << static_cast<int>(MessageLevel::Info);
}
void guessLevelFromLine()
{
QFETCH(QString, line);
QFETCH(int, fallback);
QFETCH(int, expected);
auto result = LogEventParser::guessLevelFromLine(line, static_cast<MessageLevel::Enum>(fallback));
QCOMPARE(static_cast<int>(result), expected);
}
};
QTEST_GUILESS_MAIN(LogEventParserTest)
#include "LogEventParser_test.moc"
|