File indexing completed on 2024-04-28 03:53:14
0001 /* This file is part of the KDE libraries 0002 SPDX-FileCopyrightText: 2010 Canonical Ltd 0003 SPDX-FileContributor: Aurélien Gâteau <aurelien.gateau@canonical.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 #include "test_kconf_update.h" 0008 0009 #include <memory> 0010 0011 // Qt 0012 #include <QDir> 0013 #include <QFile> 0014 #include <QProcess> 0015 #include <qglobal.h> 0016 #include <qstandardpaths.h> 0017 #include <qtemporaryfile.h> 0018 #include <qtest.h> 0019 #include <qtestcase.h> 0020 0021 QTEST_GUILESS_MAIN(TestKConfUpdate) 0022 0023 void TestKConfUpdate::initTestCase() 0024 { 0025 QStandardPaths::setTestModeEnabled(true); 0026 0027 // Ensure it all works with spaces in paths (as happens more commonly on OSX where it's ~/Library/Application Support/) 0028 qputenv("XDG_DATA_HOME", "/tmp/a b"); 0029 } 0030 0031 static void writeFile(const QString &path, const QString &content) 0032 { 0033 QFile file(path); 0034 if (!file.open(QIODevice::WriteOnly)) { 0035 qFatal("Could not write to '%s'", qPrintable(path)); 0036 } 0037 file.write(content.toUtf8()); 0038 } 0039 0040 static QString readFile(const QString &path) 0041 { 0042 QFile file(path); 0043 if (!file.open(QIODevice::ReadOnly)) { 0044 qFatal("Could not read '%s'", qPrintable(path)); 0045 } 0046 QString ret = QString::fromUtf8(file.readAll()); 0047 #ifdef Q_OS_WIN 0048 // KConfig always writes files with the native line ending, the test comparison uses \n 0049 ret.replace(QLatin1String{"\r\n"}, QLatin1String{"\n"}); 0050 #endif 0051 return ret; 0052 } 0053 0054 static std::unique_ptr<QTemporaryFile> writeUpdFile(const QString &content) 0055 { 0056 std::unique_ptr<QTemporaryFile> file{new QTemporaryFile(QDir::tempPath() + QLatin1String("/test_kconf_update_XXXXXX.upd"))}; 0057 bool ok = file->open(); 0058 Q_UNUSED(ok) // silence warnings 0059 Q_ASSERT(ok); 0060 file->write(content.toUtf8()); 0061 file->flush(); 0062 return file; 0063 } 0064 0065 static void runKConfUpdate(const QString &updPath, const QString &expectedKConfOutputString) 0066 { 0067 const QString kconfUpdateExecutable = QFINDTESTDATA("kconf_update"); 0068 QVERIFY(QFile::exists(kconfUpdateExecutable)); 0069 QProcess p; 0070 p.start(kconfUpdateExecutable, QStringList{QStringLiteral("--testmode"), QStringLiteral("--debug"), updPath}); 0071 QVERIFY(p.waitForFinished()); 0072 QCOMPARE(p.exitCode(), 0); 0073 if (!expectedKConfOutputString.isEmpty()) { 0074 const QString out = QString::fromLocal8Bit(p.readAllStandardError()); 0075 QVERIFY2(out.contains(expectedKConfOutputString), 0076 qPrintable(QLatin1String("The string \"%1\" was not contained in putput \"%2\"").arg(expectedKConfOutputString, out))); 0077 } 0078 } 0079 0080 void TestKConfUpdate::testScript_data() 0081 { 0082 QTest::addColumn<QString>("updContent"); 0083 QTest::addColumn<QString>("updScript"); 0084 QTest::addColumn<QString>("oldConfContent"); 0085 QTest::addColumn<QString>("expectedNewConfContent"); 0086 QTest::addColumn<QString>("expectedKConfOutputString"); 0087 0088 #ifdef Q_OS_FREEBSD 0089 // https://stackoverflow.com/a/69955786 0090 const QString sedCommand = QStringLiteral("sed -i '' "); 0091 #else 0092 const QString sedCommand = QStringLiteral("sed -i "); 0093 #endif 0094 const QString updVersionIdPrefix = QLatin1String("Version=6\nId=%1\n").arg(QLatin1String{QTest::currentDataTag()}); 0095 const QString confPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String{"/testrc"}; 0096 const QString scriptContent = sedCommand + QLatin1String("'s/firstVal=abc/firstVal=xyz/' %1").arg(confPath); 0097 0098 QTest::newRow("should reject script due to version missmatch") 0099 << QStringLiteral("Version=5\nId=12345") << scriptContent << QString() << QString() << QStringLiteral("defined Version=5 but Version=6 was expected"); 0100 0101 const QString updContent = updVersionIdPrefix + QLatin1String("Script=test.sh,sh\n"); 0102 const QString configIn = QStringLiteral("[grp]\nfirstVal=abc\nsecondVal=xyz\n"); 0103 const QString configOut = QStringLiteral("[grp]\nfirstVal=xyz\nsecondVal=xyz\n"); 0104 0105 QTest::newRow("should run command and modify file") << updContent << scriptContent << configIn << configOut << QString(); 0106 0107 const QString argScriptContent = sedCommand + QLatin1String("\"s/secondVal=$1/secondVal=abc/\" %1").arg(confPath); 0108 QTest::newRow("should run command with argument and modify file") << QStringLiteral("ScriptArguments=xyz\n") + updContent << argScriptContent << configIn 0109 << QStringLiteral("[grp]\nfirstVal=abc\nsecondVal=abc\n") << QString(); 0110 0111 QTest::newRow("should run command with arguments and modify file") 0112 << QStringLiteral("ScriptArguments=xyz abc\n") + updContent << sedCommand + QLatin1String("\"s/secondVal=$1/secondVal=$2/\" %1").arg(confPath) 0113 << configIn << QStringLiteral("[grp]\nfirstVal=abc\nsecondVal=abc\n") << QString(); 0114 } 0115 0116 void TestKConfUpdate::testScript() 0117 { 0118 if (QStandardPaths::findExecutable(QStringLiteral("sh")).isEmpty()) { 0119 QSKIP("Could not find sh executable, cannot run test"); 0120 return; 0121 } 0122 0123 QFETCH(QString, updContent); 0124 QFETCH(QString, updScript); 0125 QFETCH(QString, oldConfContent); 0126 QFETCH(QString, expectedNewConfContent); 0127 QFETCH(QString, expectedKConfOutputString); 0128 0129 std::unique_ptr<QTemporaryFile> updFile(writeUpdFile(updContent)); 0130 0131 const QString scriptDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String{"/kconf_update"}; 0132 QVERIFY(QDir().mkpath(scriptDir)); 0133 const QString scriptPath = scriptDir + QLatin1String{"/test.sh"}; 0134 writeFile(scriptPath, updScript); 0135 QCOMPARE(readFile(scriptPath), updScript); 0136 0137 const QString confPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String{"/testrc"}; 0138 writeFile(confPath, oldConfContent); 0139 QCOMPARE(readFile(confPath), oldConfContent); 0140 0141 runKConfUpdate(updFile->fileName(), expectedKConfOutputString); 0142 0143 QCOMPARE(readFile(confPath), expectedNewConfContent); 0144 } 0145 0146 #include "moc_test_kconf_update.cpp"