File indexing completed on 2024-04-21 05:46:12

0001 /*
0002     SPDX-FileCopyrightText: 2007 Nicolas Ternisien <nicolas.ternisien@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QList>
0008 #include <QSignalSpy>
0009 #include <QStringList>
0010 #include <QTest>
0011 #include <QThread>
0012 
0013 #include "testUtil.h"
0014 
0015 #include "analyzer.h"
0016 #include "globals.h"
0017 
0018 #include "logFile.h"
0019 #include "logLevel.h"
0020 #include "logViewModel.h"
0021 #include "logViewWidget.h"
0022 
0023 #include "ksystemlogConfig.h"
0024 
0025 #include "ksystemlog_debug.h"
0026 
0027 class SystemAnalyzerTest : public QObject
0028 {
0029     Q_OBJECT
0030 
0031 private Q_SLOTS:
0032 
0033     void initTestCase();
0034 
0035     void testMultipleLines();
0036     void testOneLine();
0037     void testTwoLines();
0038     void testStrangeLines();
0039 
0040     void testDeleteProcessIdentifier();
0041     void testMaxLines();
0042     void testRemoveDuplicates();
0043 
0044 private:
0045     void compareWithMinTime(const QList<LogLine *> &lines, const QDateTime &minTime);
0046 
0047 private:
0048     TestUtil testUtil;
0049 };
0050 
0051 void SystemAnalyzerTest::initTestCase()
0052 {
0053     testUtil.registerLogModeFactories();
0054 }
0055 
0056 void SystemAnalyzerTest::testOneLine()
0057 {
0058     LogViewModel *model = nullptr;
0059 
0060     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0061     QVERIFY(systemAnalyzer);
0062     QVERIFY(model);
0063 
0064     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/default/one-line.log"));
0065 
0066     systemAnalyzer->setLogFiles(logFiles);
0067 
0068     systemAnalyzer->watchLogFiles(true);
0069 
0070     QCOMPARE(model->itemCount(), 1);
0071     QCOMPARE(model->isEmpty(), false);
0072 
0073     QList<LogLine *> const logLines = model->logLines();
0074 
0075     QStringList const items = QStringList() << QStringLiteral("localhost") << QStringLiteral("kernel")
0076                                             << QStringLiteral("[11663.656000] eth1: no IPv6 routers present");
0077 
0078     const int year = QDate::currentDate().year();
0079     testUtil.testLine(logLines.at(0),
0080                       logFiles.at(0).url().toLocalFile(),
0081                       logFiles.at(0).defaultLogLevel(),
0082                       QDateTime(QDate(year, 8, 21), QTime(22, 52, 44)),
0083                       items
0084 
0085     );
0086 
0087     testUtil.destroyReader(systemAnalyzer);
0088 }
0089 
0090 void SystemAnalyzerTest::testTwoLines()
0091 {
0092     LogViewModel *model = nullptr;
0093 
0094     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0095     QVERIFY(systemAnalyzer);
0096     QVERIFY(model);
0097 
0098     // Specifical configuration
0099     KSystemLogConfig::setMaxLines(1000);
0100 
0101     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/default/two-lines.log"));
0102 
0103     systemAnalyzer->setLogFiles(logFiles);
0104 
0105     systemAnalyzer->watchLogFiles(true);
0106 
0107     QCOMPARE(model->itemCount(), 2);
0108     QCOMPARE(model->isEmpty(), false);
0109 
0110     testUtil.destroyReader(systemAnalyzer);
0111 }
0112 
0113 void SystemAnalyzerTest::testMultipleLines()
0114 {
0115     LogViewModel *model = nullptr;
0116 
0117     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0118     QVERIFY(systemAnalyzer);
0119     QVERIFY(model);
0120 
0121     // Specifical configuration
0122     KSystemLogConfig::setMaxLines(1000);
0123 
0124     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/system/system.log"));
0125     LogFile const logFile = logFiles.at(0);
0126 
0127     systemAnalyzer->setLogFiles(logFiles);
0128 
0129     QSignalSpy stateSpy(systemAnalyzer, &Analyzer::logUpdated);
0130     QList<QVariant> arguments;
0131 
0132     // Each watching relaunch a reading
0133     systemAnalyzer->watchLogFiles(true);
0134 
0135     // Assert that the model has been updated
0136     QCOMPARE(model->itemCount(), 24);
0137 
0138     // Assert that the logUpdated signal emits the right count
0139     QCOMPARE(stateSpy.count(), 1);
0140     arguments = stateSpy.takeFirst();
0141     QCOMPARE(arguments.at(0).toInt(), 24);
0142 
0143     // Each watching relaunch a reading
0144     systemAnalyzer->watchLogFiles(true);
0145 
0146     // Assert that the model has been updated
0147     QCOMPARE(model->itemCount(), 48);
0148 
0149     // Assert that the logUpdated signal emits the right count
0150     QCOMPARE(stateSpy.count(), 1);
0151     arguments = stateSpy.takeFirst();
0152     QCOMPARE(arguments.at(0).toInt(), 24);
0153 
0154     QStringList addedLines;
0155     addedLines << QStringLiteral("Aug 18 17:04:28 localhost test: Test line 1");
0156     addedLines << QStringLiteral("Aug 18 17:04:30 localhost test: Test line 2");
0157 
0158     testUtil.addLogLines(logFile.url().toLocalFile(), addedLines);
0159 
0160     // Assert that the model has been updated
0161     QCOMPARE(model->itemCount(), 50);
0162 
0163     // Assert that the logUpdated signal emits the right count
0164     QCOMPARE(stateSpy.count(), 1);
0165     arguments = stateSpy.takeFirst();
0166     QCOMPARE(arguments.at(0).toInt(), 2);
0167 
0168     testUtil.destroyReader(systemAnalyzer);
0169 }
0170 
0171 void SystemAnalyzerTest::testStrangeLines()
0172 {
0173     LogViewModel *model = nullptr;
0174 
0175     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0176     QVERIFY(systemAnalyzer);
0177     QVERIFY(model);
0178 
0179     // Specifical configuration
0180     KSystemLogConfig::setMaxLines(1000);
0181     KSystemLogConfig::setDeleteProcessIdentifier(false);
0182 
0183     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/system/strange-lines.log"));
0184 
0185     systemAnalyzer->setLogFiles(logFiles);
0186 
0187     systemAnalyzer->watchLogFiles(true);
0188 
0189     QCOMPARE(model->itemCount(), 8);
0190 
0191     // i18n("undefined")
0192     QString const undefined = QLatin1String("");
0193 
0194     QStringList items;
0195 
0196     QSKIP("This test/code is broken");
0197     const int year = QDate::currentDate().year();
0198 
0199     // Classical log line
0200     items = QStringList() << QStringLiteral("localhost") << QStringLiteral("kernel") << QStringLiteral("Kernel panic");
0201     testUtil.testLine(model->logLines().at(0),
0202                       logFiles.at(0).url().toLocalFile(),
0203                       logFiles.at(0).defaultLogLevel(),
0204                       QDateTime(QDate(year, 8, 10), QTime(17, 04, 28)),
0205                       items);
0206 
0207     //-- MARK -- log line
0208     items = QStringList() << QStringLiteral("localhost") << QStringLiteral("syslog") << QStringLiteral("-- MARK --");
0209     testUtil.testLine(model->logLines().at(1),
0210                       logFiles.at(0).url().toLocalFile(),
0211                       logFiles.at(0).defaultLogLevel(),
0212                       QDateTime(QDate(year, 8, 11), QTime(13, 49, 38)),
0213                       items);
0214 
0215     // Last message repeated n time log line
0216     items = QStringList() << QStringLiteral("localhost") << QStringLiteral("syslog") << QStringLiteral("last message repeated 4 times");
0217     testUtil.testLine(model->logLines().at(2),
0218                       logFiles.at(0).url().toLocalFile(),
0219                       logFiles.at(0).defaultLogLevel(),
0220                       QDateTime(QDate(year, 8, 12), QTime(18, 10, 32)),
0221                       items);
0222 
0223     //"Aug 13 17:04:28 testprocess: Say ouhou  " -> No host name
0224     items = QStringList() << undefined << QStringLiteral("testprocess") << QStringLiteral("Say ouhou  ");
0225     testUtil.testLine(model->logLines().at(3),
0226                       logFiles.at(0).url().toLocalFile(),
0227                       logFiles.at(0).defaultLogLevel(),
0228                       QDateTime(QDate(year, 8, 13), QTime(17, 04, 28)),
0229                       items);
0230 
0231     //"Aug 14 17:04:28 localhost kernel say ouhou" -> No process name and not a syslog message
0232     items = QStringList() << QStringLiteral("localhost") << undefined << QStringLiteral("kernel say ouhou");
0233     testUtil.testLine(model->logLines().at(4),
0234                       logFiles.at(0).url().toLocalFile(),
0235                       logFiles.at(0).defaultLogLevel(),
0236                       QDateTime(QDate(year, 8, 14), QTime(17, 04, 28)),
0237                       items);
0238 
0239     //"Aug 15 22:39:01 localhost /USR/SBIN/CRON[9433]: (root) CMD (  [ -d /var/lib/php5 ] && find
0240     /// var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -r -0 rm)" -> Long log line
0241     items = QStringList() << QStringLiteral("localhost") << QStringLiteral("/USR/SBIN/CRON[9433]")
0242                           << QStringLiteral(
0243                                  "(root) CMD (  [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin "
0244                                  "+$(/usr/lib/php5/maxlifetime) -print0 | xargs -r -0 rm)");
0245     testUtil.testLine(model->logLines().at(5),
0246                       logFiles.at(0).url().toLocalFile(),
0247                       logFiles.at(0).defaultLogLevel(),
0248                       QDateTime(QDate(year, 8, 15), QTime(22, 39, 01)),
0249                       items);
0250 
0251     //"blablalbla" -> Invalid line
0252     items = QStringList() << undefined << undefined << QLatin1String("");
0253     QCOMPARE(model->logLines().at(6)->logItems(), items);
0254 
0255     //"" -> Empty line
0256     items = QStringList() << undefined << undefined << QStringLiteral("blablalbla");
0257     QCOMPARE(model->logLines().at(7)->logItems(), items);
0258 
0259     testUtil.destroyReader(systemAnalyzer);
0260 }
0261 
0262 void SystemAnalyzerTest::testDeleteProcessIdentifier()
0263 {
0264     LogViewModel *model = nullptr;
0265 
0266     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0267     QVERIFY(systemAnalyzer);
0268     QVERIFY(model);
0269 
0270     // Specifical configuration
0271     KSystemLogConfig::setMaxLines(1000);
0272     KSystemLogConfig::setDeleteProcessIdentifier(true);
0273 
0274     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/system/delete-process-identifier.log"));
0275 
0276     systemAnalyzer->setLogFiles(logFiles);
0277 
0278     systemAnalyzer->watchLogFiles(true);
0279 
0280     QCOMPARE(model->itemCount(), 2);
0281 
0282     QStringList items;
0283 
0284     // Cron log line
0285     items = QStringList() << QStringLiteral("localhost") << QStringLiteral("/USR/SBIN/CRON") << QStringLiteral("Hello");
0286     QCOMPARE(model->logLines().at(0)->logItems(), items);
0287 
0288     //"f" process
0289     items = QStringList() << QStringLiteral("localhost") << QStringLiteral("f") << QStringLiteral("Ola");
0290     QCOMPARE(model->logLines().at(1)->logItems(), items);
0291 
0292     testUtil.destroyReader(systemAnalyzer);
0293 }
0294 
0295 void SystemAnalyzerTest::testMaxLines()
0296 {
0297     LogViewModel *model = nullptr;
0298 
0299     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0300     QVERIFY(systemAnalyzer);
0301     QVERIFY(model);
0302 
0303     // Specifical configuration
0304     KSystemLogConfig::setMaxLines(5);
0305 
0306     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/system/max-lines.log"));
0307     LogFile const logFile = logFiles.at(0);
0308 
0309     systemAnalyzer->setLogFiles(logFiles);
0310 
0311     systemAnalyzer->watchLogFiles(true);
0312 
0313     QCOMPARE(model->itemCount(), 5);
0314 
0315     // Asserts that there is no line before the oldest one's time
0316     compareWithMinTime(model->logLines(), QDateTime(QDate(2007, 8, 18), QTime(11, 0, 0)));
0317 
0318     QStringList addedLines;
0319 
0320     addedLines << QStringLiteral("Aug 18 10:00:00 localhost test: Line 8");
0321     testUtil.addLogLines(logFile.url().toLocalFile(), addedLines);
0322 
0323     QCOMPARE(model->itemCount(), 5);
0324     compareWithMinTime(model->logLines(), QDateTime(QDate(2007, 8, 18), QTime(11, 0, 0)));
0325 
0326     // Specifical configuration
0327     KSystemLogConfig::setMaxLines(6);
0328 
0329     addedLines.clear();
0330     addedLines << QStringLiteral("Aug 18 10:00:00 localhost test: Line 9");
0331     addedLines << QStringLiteral("Aug 18 19:00:00 localhost test: Line 10");
0332     testUtil.addLogLines(logFile.url().toLocalFile(), addedLines);
0333 
0334     QCOMPARE(model->itemCount(), 6);
0335     compareWithMinTime(model->logLines(), QDateTime(QDate(2007, 8, 18), QTime(11, 0, 0)));
0336 
0337     addedLines.clear();
0338     addedLines << QStringLiteral("Aug 18 20:00:00 localhost test: Line 11");
0339     addedLines << QStringLiteral("Aug 18 21:00:00 localhost test: Line 12");
0340     testUtil.addLogLines(logFile.url().toLocalFile(), addedLines);
0341 
0342     QCOMPARE(model->itemCount(), 6);
0343     compareWithMinTime(model->logLines(), QDateTime(QDate(2007, 8, 18), QTime(13, 0, 0)));
0344 
0345     testUtil.destroyReader(systemAnalyzer);
0346 }
0347 
0348 void SystemAnalyzerTest::compareWithMinTime(const QList<LogLine *> &logLines, const QDateTime &minTime)
0349 {
0350     qCDebug(KSYSTEMLOG) << "Min time : " << minTime.toString();
0351 
0352     for (LogLine *logLine : logLines) {
0353         if (logLine->time() < minTime) {
0354             QFAIL(QString::fromLatin1("The line '%1' has a lesser time than the required min time (%2)")
0355                       .arg(logLine->logItems().join(QLatin1Char(' ')), logLine->time().toString())
0356                       .toUtf8()
0357                       .constData());
0358         }
0359     }
0360 }
0361 
0362 void SystemAnalyzerTest::testRemoveDuplicates()
0363 {
0364     LogViewModel *model = nullptr;
0365 
0366     Analyzer *systemAnalyzer = testUtil.createAnalyzer(QStringLiteral("systemLogMode"), &model);
0367     QVERIFY(systemAnalyzer);
0368     QVERIFY(model);
0369 
0370     // Specifical configuration
0371     KSystemLogConfig::setMaxLines(1000);
0372     KSystemLogConfig::setDeleteDuplicatedLines(true);
0373 
0374     QVector<LogFile> const logFiles = testUtil.createLogFiles(QStringLiteral(":/testFiles/system/duplicate-lines.log"));
0375 
0376     systemAnalyzer->setLogFiles(logFiles);
0377 
0378     systemAnalyzer->watchLogFiles(true);
0379 
0380     QCOMPARE(model->itemCount(), 5);
0381 }
0382 
0383 QTEST_MAIN(SystemAnalyzerTest)
0384 
0385 #include "systemAnalyzerTest.moc"