File indexing completed on 2024-04-28 04:01:09

0001 /*
0002     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #include "test-config.h"
0008 
0009 #include <KSyntaxHighlighting/AbstractHighlighter>
0010 #include <KSyntaxHighlighting/Definition>
0011 #include <KSyntaxHighlighting/Format>
0012 #include <KSyntaxHighlighting/Repository>
0013 #include <KSyntaxHighlighting/State>
0014 
0015 #include <QDir>
0016 #include <QObject>
0017 #include <QTest>
0018 
0019 using namespace KSyntaxHighlighting;
0020 
0021 class NullHighlighter : public AbstractHighlighter
0022 {
0023 public:
0024     /**
0025      * Read in the given file and cache it for the highlighting benchmarking
0026      * @param inFileName file to read
0027      */
0028     NullHighlighter(const QString &inFileName)
0029     {
0030         QFile f(inFileName);
0031         if (!f.open(QFile::ReadOnly)) {
0032             qWarning() << "Failed to open input file" << inFileName << ":" << f.errorString();
0033             return;
0034         }
0035 
0036         QTextStream in(&f);
0037         while (!in.atEnd()) {
0038             m_fileContents.append(in.readLine());
0039         }
0040     }
0041 
0042     /**
0043      * highlight the in-memory stored file
0044      * @return number of highlighted lines
0045      */
0046     int highlightFile()
0047     {
0048         State state;
0049         for (const auto &line : std::as_const(m_fileContents)) {
0050             state = highlightLine(line, state);
0051         }
0052         return m_fileContents.size();
0053     }
0054 
0055 protected:
0056     void applyFormat(int, int, const Format &) override
0057     {
0058     }
0059     QStringList m_fileContents;
0060 };
0061 
0062 class HighlighterBenchmark : public QObject
0063 {
0064     Q_OBJECT
0065 public:
0066     explicit HighlighterBenchmark(QObject *parent = nullptr)
0067         : QObject(parent)
0068     {
0069     }
0070 
0071 private:
0072     Repository m_repo;
0073 
0074 private Q_SLOTS:
0075     void initTestCase()
0076     {
0077         initRepositorySearchPaths(m_repo);
0078     }
0079 
0080     void cleanupTestCase()
0081     {
0082     }
0083 
0084     void benchmarkHighlight_data()
0085     {
0086         QTest::addColumn<QString>("inFile");
0087         QTest::addColumn<QString>("syntax");
0088 
0089         const QDir dir(QStringLiteral(TESTSRCDIR "/input"));
0090         for (const auto &fileName : dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Hidden, QDir::Name)) {
0091             if (fileName == QLatin1String(".clang-format")) {
0092                 continue;
0093             }
0094 
0095             const auto inFile = dir.absoluteFilePath(fileName);
0096             if (inFile.endsWith(QLatin1String(".syntax"))) {
0097                 continue;
0098             }
0099 
0100             QString syntax;
0101             QFile syntaxOverride(inFile + QStringLiteral(".syntax"));
0102             if (syntaxOverride.exists() && syntaxOverride.open(QFile::ReadOnly)) {
0103                 syntax = QString::fromUtf8(syntaxOverride.readAll()).trimmed();
0104             }
0105 
0106             QTest::newRow(fileName.toUtf8().constData()) << inFile << syntax;
0107         }
0108     }
0109 
0110     void benchmarkHighlight()
0111     {
0112         QFETCH(QString, inFile);
0113         QFETCH(QString, syntax);
0114 
0115         NullHighlighter highlighter(inFile);
0116         auto def = m_repo.definitionForFileName(inFile);
0117         if (!syntax.isEmpty()) {
0118             def = m_repo.definitionForName(syntax);
0119         }
0120         QVERIFY(def.isValid());
0121         highlighter.setDefinition(def);
0122 
0123         // trigger loading of definition per benchmarking loop
0124         QVERIFY(!def.formats().isEmpty());
0125 
0126         // benchmark the highlighting
0127         // try to highlight ~ 20000 lines per file
0128         // bail out, if file is empty, else we are stuck
0129         for (int i = 0; i <= 20000;) {
0130             int lines = highlighter.highlightFile();
0131             if (lines <= 0) {
0132                 break;
0133             }
0134             i += lines;
0135         }
0136     }
0137 };
0138 
0139 QTEST_GUILESS_MAIN(HighlighterBenchmark)
0140 
0141 #include "highlighter_benchmark.moc"