File indexing completed on 2024-12-01 03:42:31
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2001, 2003 Peter Kelly <pmk@post.com> 0004 SPDX-FileCopyrightText: 2003, 2004 Stephan Kulow <coolo@kde.org> 0005 SPDX-FileCopyrightText: 2004 Dirk Mueller <mueller@kde.org> 0006 SPDX-FileCopyrightText: 2006, 2007 Leo Savernik <l.savernik@aon.at> 0007 SPDX-FileCopyrightText: 2010 Milian Wolff <mail@milianw.de> 0008 SPDX-FileCopyrightText: 2013 Gerald Senarclens de Grancy <oss@senarclens.eu> 0009 0010 SPDX-License-Identifier: LGPL-2.0-or-later 0011 */ 0012 0013 // BEGIN Includes 0014 0015 #include "kateconfig.h" 0016 #include "katedocument.h" 0017 #include "kateglobal.h" 0018 #include "kateview.h" 0019 0020 #include <QCryptographicHash> 0021 #include <QDir> 0022 #include <QFileInfo> 0023 #include <QJSEngine> 0024 #include <QMainWindow> 0025 #include <QProcess> 0026 #include <QStandardPaths> 0027 #include <QTest> 0028 0029 #include <iostream> 0030 0031 #include "script_test_base.h" 0032 #include "testutils.h" 0033 0034 const QString testDataPath(QLatin1String(TEST_DATA_DIR)); 0035 0036 QtMessageHandler ScriptTestBase::m_msgHandler = nullptr; 0037 void noDebugMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) 0038 { 0039 switch (type) { 0040 case QtDebugMsg: 0041 break; 0042 default: 0043 ScriptTestBase::m_msgHandler(type, context, msg); 0044 } 0045 } 0046 0047 void ScriptTestBase::initTestCase() 0048 { 0049 KTextEditor::EditorPrivate::enableUnitTestMode(); 0050 m_msgHandler = qInstallMessageHandler(noDebugMessageOutput); 0051 m_toplevel = new QMainWindow(); 0052 m_document = new KTextEditor::DocumentPrivate(true, false, m_toplevel); 0053 m_view = static_cast<KTextEditor::ViewPrivate *>(m_document->widget()); 0054 m_view->config()->setValue(KateViewConfig::AutoBrackets, false); 0055 m_env = new TestScriptEnv(m_document, m_outputWasCustomised); 0056 } 0057 0058 void ScriptTestBase::cleanupTestCase() 0059 { 0060 qInstallMessageHandler(m_msgHandler); 0061 } 0062 0063 void ScriptTestBase::getTestData(const QString &script) 0064 { 0065 QTest::addColumn<QString>("testcase"); 0066 0067 // make sure the script files are valid 0068 if (!m_script_dir.isEmpty()) { 0069 QFile scriptFile(QLatin1String(JS_DATA_DIR) + m_script_dir + QLatin1Char('/') + script + QLatin1String(".js")); 0070 if (scriptFile.exists()) { 0071 QVERIFY(scriptFile.open(QFile::ReadOnly)); 0072 QJSValue result = m_env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); 0073 QVERIFY2(!result.isError(), (result.toString() + QLatin1String(" in file ") + scriptFile.fileName()).toUtf8().constData()); 0074 } 0075 } 0076 0077 const QDir testDir(testDataPath + m_section + QLatin1Char('/') + script + QLatin1Char('/')); 0078 if (!testDir.exists()) { 0079 QSKIP(qPrintable(QString(testDir.path() + QLatin1String(" does not exist"))), SkipAll); 0080 } 0081 const auto testList = testDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); 0082 for (const auto &info : testList) { 0083 QTest::newRow(info.baseName().toUtf8().constData()) << info.absoluteFilePath(); 0084 } 0085 } 0086 0087 /** 0088 * helper to compare files 0089 * @param refFile reference file 0090 * @param outFile output file 0091 */ 0092 inline bool filesEqual(const QString &refFile, const QString &outFile) 0093 { 0094 /** 0095 * quick compare, all fine, if no diffs! 0096 * use text mode + text streams to avoid unix/windows mismatches 0097 */ 0098 QFile ref(refFile); 0099 QFile out(outFile); 0100 ref.open(QIODevice::ReadOnly | QIODevice::Text); 0101 out.open(QIODevice::ReadOnly | QIODevice::Text); 0102 QTextStream refIn(&ref); 0103 QTextStream outIn(&out); 0104 const QString refContent = refIn.readAll(); 0105 const QString outContent = outIn.readAll(); 0106 const bool equalResults = refContent == outContent; 0107 if (equalResults) { 0108 return true; 0109 } 0110 0111 /** 0112 * elaborate diff output, if possible 0113 */ 0114 static const QString diffExecutable = QStandardPaths::findExecutable(QStringLiteral("diff")); 0115 if (!diffExecutable.isEmpty()) { 0116 QProcess proc; 0117 proc.setProcessChannelMode(QProcess::ForwardedChannels); 0118 proc.start(diffExecutable, {QStringLiteral("-u"), refFile, outFile}); 0119 proc.waitForFinished(); 0120 } 0121 0122 /** 0123 * else: trivial output of mismatching characters, e.g. for windows testing without diff 0124 */ 0125 else { 0126 qDebug() << "'diff' executable is not in the PATH, no difference output"; 0127 } 0128 0129 // there were diffs 0130 return false; 0131 } 0132 0133 void ScriptTestBase::runTest(const ExpectedFailures &failures) 0134 { 0135 if (!QFile::exists(testDataPath + m_section)) { 0136 QSKIP(qPrintable(QString(testDataPath + m_section + QLatin1String(" does not exist"))), SkipAll); 0137 } 0138 0139 QFETCH(QString, testcase); 0140 0141 m_toplevel->resize(800, 600); // restore size 0142 0143 // load page 0144 QUrl url; 0145 url.setScheme(QLatin1String("file")); 0146 url.setPath(testcase + QLatin1String("/origin")); 0147 m_document->openUrl(url); 0148 0149 // evaluate test-script 0150 QFile sourceFile(testcase + QLatin1String("/input.js")); 0151 if (!sourceFile.open(QFile::ReadOnly)) { 0152 QFAIL(qPrintable(QString::fromLatin1("Failed to open file: %1").arg(sourceFile.fileName()))); 0153 } 0154 0155 QTextStream stream(&sourceFile); 0156 QString code = stream.readAll(); 0157 sourceFile.close(); 0158 0159 // Execute script 0160 QJSValue result = m_env->engine()->evaluate(code, testcase + QLatin1String("/input.js"), 1); 0161 QVERIFY2(!result.isError(), result.toString().toUtf8().constData()); 0162 0163 const QString fileExpected = testcase + QLatin1String("/expected"); 0164 const QString fileActual = testcase + QLatin1String("/actual"); 0165 0166 url.setPath(fileActual); 0167 m_document->saveAs(url); 0168 m_document->closeUrl(); 0169 0170 for (const Failure &failure : failures) { 0171 QEXPECT_FAIL(failure.first, failure.second, Abort); 0172 } 0173 0174 // compare files, expected fail will invert this verify 0175 QVERIFY(filesEqual(fileExpected, fileActual)); 0176 } 0177 0178 #include "moc_script_test_base.cpp"