File indexing completed on 2025-02-02 14:22:23
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 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0038 in.setCodec("UTF-8"); 0039 #endif 0040 while (!in.atEnd()) { 0041 m_fileContents.append(in.readLine()); 0042 } 0043 } 0044 0045 /** 0046 * highlight the in-memory stored file 0047 * @return number of highlighted lines 0048 */ 0049 int highlightFile() 0050 { 0051 State state; 0052 for (const auto &line : std::as_const(m_fileContents)) { 0053 state = highlightLine(line, state); 0054 } 0055 return m_fileContents.size(); 0056 } 0057 0058 protected: 0059 void applyFormat(int, int, const Format &) override 0060 { 0061 } 0062 QStringList m_fileContents; 0063 }; 0064 0065 class HighlighterBenchmark : public QObject 0066 { 0067 Q_OBJECT 0068 public: 0069 explicit HighlighterBenchmark(QObject *parent = nullptr) 0070 : QObject(parent) 0071 { 0072 } 0073 0074 private: 0075 Repository m_repo; 0076 0077 private Q_SLOTS: 0078 void initTestCase() 0079 { 0080 initRepositorySearchPaths(m_repo); 0081 } 0082 0083 void cleanupTestCase() 0084 { 0085 } 0086 0087 void benchmarkHighlight_data() 0088 { 0089 QTest::addColumn<QString>("inFile"); 0090 QTest::addColumn<QString>("syntax"); 0091 0092 const QDir dir(QStringLiteral(TESTSRCDIR "/input")); 0093 for (const auto &fileName : dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Hidden, QDir::Name)) { 0094 if (fileName == QLatin1String(".clang-format")) { 0095 continue; 0096 } 0097 0098 const auto inFile = dir.absoluteFilePath(fileName); 0099 if (inFile.endsWith(QLatin1String(".syntax"))) { 0100 continue; 0101 } 0102 0103 QString syntax; 0104 QFile syntaxOverride(inFile + QStringLiteral(".syntax")); 0105 if (syntaxOverride.exists() && syntaxOverride.open(QFile::ReadOnly)) { 0106 syntax = QString::fromUtf8(syntaxOverride.readAll()).trimmed(); 0107 } 0108 0109 QTest::newRow(fileName.toUtf8().constData()) << inFile << syntax; 0110 } 0111 } 0112 0113 void benchmarkHighlight() 0114 { 0115 QFETCH(QString, inFile); 0116 QFETCH(QString, syntax); 0117 0118 NullHighlighter highlighter(inFile); 0119 auto def = m_repo.definitionForFileName(inFile); 0120 if (!syntax.isEmpty()) { 0121 def = m_repo.definitionForName(syntax); 0122 } 0123 QVERIFY(def.isValid()); 0124 highlighter.setDefinition(def); 0125 0126 // trigger loading of definition per benchmarking loop 0127 QVERIFY(!def.formats().isEmpty()); 0128 0129 // benchmark the highlighting 0130 // try to highlight ~ 20000 lines per file 0131 // bail out, if file is empty, else we are stuck 0132 for (int i = 0; i <= 20000;) { 0133 int lines = highlighter.highlightFile(); 0134 if (lines <= 0) { 0135 break; 0136 } 0137 i += lines; 0138 } 0139 } 0140 }; 0141 0142 QTEST_GUILESS_MAIN(HighlighterBenchmark) 0143 0144 #include "highlighter_benchmark.moc"