File indexing completed on 2025-03-23 06:53:30
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"