File indexing completed on 2024-05-12 05:46:50
0001 /* This file is part of the KDE libraries 0002 Copyright 2010 Canonical Ltd 0003 Author: Aurélien Gâteau <aurelien.gateau@canonical.com> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License (LGPL) as published by the Free Software Foundation; 0008 either version 2 of the License, or (at your option) any later 0009 version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 #include "test_kconf_update.h" 0022 0023 // Qt 0024 #include <QFile> 0025 #include <QDir> 0026 #include <QSharedPointer> 0027 #include <QProcess> 0028 #include <qtemporaryfile.h> 0029 #include <qstandardpaths.h> 0030 #include "config-kconf.h" 0031 0032 #include <qtest.h> 0033 0034 QTEST_GUILESS_MAIN(TestKConfUpdate) 0035 0036 void TestKConfUpdate::initTestCase() 0037 { 0038 QStandardPaths::setTestModeEnabled(true); 0039 0040 // Ensure it all works with spaces in paths (as happens more commonly on OSX where it's ~/Library/Application Support/) 0041 qputenv("XDG_DATA_HOME", "/tmp/a b"); 0042 } 0043 0044 static void writeFile(const QString &path, const QString &content) 0045 { 0046 QFile file(path); 0047 if (!file.open(QIODevice::WriteOnly)) { 0048 qFatal("Could not write to '%s'", qPrintable(path)); 0049 } 0050 file.write(content.toUtf8()); 0051 } 0052 0053 static QString readFile(const QString &path) 0054 { 0055 QFile file(path); 0056 if (!file.open(QIODevice::ReadOnly)) { 0057 qFatal("Could not read '%s'", qPrintable(path)); 0058 } 0059 QString ret = QString::fromUtf8(file.readAll()); 0060 #ifdef Q_OS_WIN 0061 // KConfig always writes files with the native line ending, the test comparison uses \n 0062 ret.replace("\r\n", "\n"); 0063 #endif 0064 return ret; 0065 } 0066 0067 static QTemporaryFile *writeUpdFile(const QString &content) 0068 { 0069 QTemporaryFile *file = new QTemporaryFile(QDir::tempPath() + QLatin1String("/test_kconf_update_XXXXXX.upd")); 0070 bool ok = file->open(); 0071 Q_UNUSED(ok) // silence warnings 0072 Q_ASSERT(ok); 0073 file->write(content.toUtf8()); 0074 file->flush(); 0075 return file; 0076 } 0077 0078 static void runKConfUpdate(const QString &updPath) 0079 { 0080 QVERIFY(QFile::exists(KCONF_UPDATE_EXECUTABLE)); 0081 QCOMPARE(0, QProcess::execute(KCONF_UPDATE_EXECUTABLE, QStringList() << "--testmode" << "--debug" << updPath)); 0082 } 0083 0084 void TestKConfUpdate::test_data() 0085 { 0086 QTest::addColumn<QString>("updContent"); 0087 QTest::addColumn<QString>("oldConfName"); 0088 QTest::addColumn<QString>("oldConfContent"); 0089 QTest::addColumn<QString>("newConfName"); 0090 QTest::addColumn<QString>("expectedNewConfContent"); 0091 QTest::addColumn<QString>("expectedOldConfContent"); 0092 QTest::addColumn<bool>("useVersion5"); 0093 QTest::addColumn<bool>("shouldUpdateWork"); 0094 0095 QTest::newRow("moveKeysSameFile") 0096 << 0097 "File=testrc\n" 0098 "Group=group\n" 0099 "Key=old,new\n" 0100 "Options=overwrite\n" 0101 << 0102 "testrc" 0103 << 0104 "[group]\n" 0105 "old=value\n" 0106 << 0107 "testrc" 0108 << 0109 "[$Version]\n" 0110 "update_info=%1\n" 0111 "\n" 0112 "[group]\n" 0113 "new=value\n" 0114 << 0115 "" 0116 << true 0117 << true 0118 ; 0119 QTest::newRow("moveKeysOtherFile") 0120 << 0121 "File=oldrc,newrc\n" 0122 "Group=group1,group2\n" 0123 "Key=old,new\n" 0124 "Options=overwrite\n" 0125 << 0126 "oldrc" 0127 << 0128 "[group1]\n" 0129 "old=value\n" 0130 "[stay]\n" 0131 "foo=bar\n" 0132 << 0133 "newrc" 0134 << 0135 "[$Version]\n" 0136 "update_info=%1\n" 0137 "\n" 0138 "[group2]\n" 0139 "new=value\n" 0140 << 0141 "[$Version]\n" 0142 "update_info=%1\n" 0143 "\n" 0144 "[stay]\n" 0145 "foo=bar\n" 0146 << true 0147 << true 0148 ; 0149 QTest::newRow("allKeys") 0150 << 0151 "File=testrc\n" 0152 "Group=group1,group2\n" 0153 "AllKeys\n" 0154 << 0155 "testrc" 0156 << 0157 "[group1]\n" 0158 "key1=value1\n" 0159 "key2=value2\n" 0160 "\n" 0161 "[stay]\n" 0162 "foo=bar\n" 0163 << 0164 "testrc" 0165 << 0166 "[$Version]\n" 0167 "update_info=%1\n" 0168 "\n" 0169 "[group2]\n" 0170 "key1=value1\n" 0171 "key2=value2\n" 0172 "\n" 0173 "[stay]\n" 0174 "foo=bar\n" 0175 << 0176 "" 0177 << true 0178 << true 0179 ; 0180 QTest::newRow("allKeysSubGroup") 0181 << 0182 "File=testrc\n" 0183 "Group=[group][sub1],[group][sub2]\n" 0184 "AllKeys\n" 0185 << 0186 "testrc" 0187 << 0188 "[group][sub1]\n" 0189 "key1=value1\n" 0190 "key2=value2\n" 0191 "\n" 0192 "[group][sub1][subsub]\n" 0193 "key3=value3\n" 0194 "key4=value4\n" 0195 "\n" 0196 "[stay]\n" 0197 "foo=bar\n" 0198 << 0199 "testrc" 0200 << 0201 "[$Version]\n" 0202 "update_info=%1\n" 0203 "\n" 0204 "[group][sub2]\n" 0205 "key1=value1\n" 0206 "key2=value2\n" 0207 "\n" 0208 "[group][sub2][subsub]\n" 0209 "key3=value3\n" 0210 "key4=value4\n" 0211 "\n" 0212 "[stay]\n" 0213 "foo=bar\n" 0214 << 0215 "" 0216 << true 0217 << true 0218 ; 0219 QTest::newRow("removeGroup") 0220 << 0221 "File=testrc\n" 0222 "RemoveGroup=remove\n" 0223 << 0224 "testrc" 0225 << 0226 "[keep]\n" 0227 "key=value\n" 0228 "" 0229 "[remove]\n" 0230 "key=value\n" 0231 << 0232 "testrc" 0233 << 0234 "[$Version]\n" 0235 "update_info=%1\n" 0236 "\n" 0237 "[keep]\n" 0238 "key=value\n" 0239 << 0240 "" 0241 << true 0242 << true 0243 ; 0244 QTest::newRow("moveKeysSameFileDontExist") 0245 << 0246 "File=testrc\n" 0247 "Group=group,group2\n" 0248 "Key=key1\n" 0249 "Key=key2\n" 0250 << 0251 "testrc" 0252 << 0253 "[group]\n" 0254 "key1=value1\n" 0255 "key3=value3\n" 0256 << 0257 "testrc" 0258 << 0259 "[$Version]\n" 0260 "update_info=%1\n" 0261 "\n" 0262 "[group]\n" 0263 "key3=value3\n" 0264 "\n" 0265 "[group2]\n" 0266 "key1=value1\n" 0267 << 0268 "" 0269 << true 0270 << true 0271 ; 0272 QTest::newRow("DontMigrateWhenFileDoesntHaveVersion") 0273 << 0274 "File=testrc\n" 0275 "Group=group\n" 0276 "Key=old,new\n" 0277 "Options=overwrite\n" 0278 << 0279 "testrc" 0280 << 0281 "[group]\n" 0282 "old=value\n" 0283 << 0284 "testrc" 0285 << 0286 "[group]\n" 0287 "old=value\n" 0288 << 0289 "" 0290 << false 0291 << false 0292 ; 0293 0294 QTest::newRow("DontMigrateWhenUpdateCantDoItMissingFilename") 0295 << 0296 "Group=group\n" 0297 "Key=old,new\n" 0298 "Options=overwrite\n" 0299 << 0300 "testrc" 0301 << 0302 "[group]\n" 0303 "old=value\n" 0304 << 0305 "testrc" 0306 << 0307 "[group]\n" 0308 "old=value\n" 0309 << 0310 "" 0311 << true 0312 << false 0313 ; 0314 } 0315 0316 void TestKConfUpdate::test() 0317 { 0318 QFETCH(QString, updContent); 0319 QFETCH(QString, oldConfName); 0320 QFETCH(QString, oldConfContent); 0321 QFETCH(QString, newConfName); 0322 QFETCH(QString, expectedNewConfContent); 0323 QFETCH(QString, expectedOldConfContent); 0324 QFETCH(bool, useVersion5); 0325 QFETCH(bool, shouldUpdateWork); 0326 0327 // Prepend Version and the Id= field to the upd content 0328 const QString header = QStringLiteral("Id=%1\n").arg(QTest::currentDataTag()); 0329 updContent = header + updContent; 0330 if (useVersion5) 0331 updContent.prepend("Version=5\n"); 0332 0333 const QString configDir = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); 0334 QVERIFY(QDir().mkpath(configDir)); 0335 QString oldConfPath = configDir + QLatin1Char('/') + oldConfName; 0336 QString newConfPath = configDir + QLatin1Char('/') + newConfName; 0337 0338 QFile::remove(oldConfPath); 0339 QFile::remove(newConfPath); 0340 0341 writeFile(oldConfPath, oldConfContent); 0342 QCOMPARE(readFile(oldConfPath), oldConfContent); 0343 QSharedPointer<QTemporaryFile> updFile(writeUpdFile(updContent)); 0344 runKConfUpdate(updFile->fileName()); 0345 0346 QString updateInfo = QStringLiteral("%1:%2") 0347 .arg(updFile->fileName().section('/', -1)) 0348 .arg(QTest::currentDataTag()); 0349 0350 QString newConfContentAfter = readFile(newConfPath); 0351 if (shouldUpdateWork) { 0352 expectedNewConfContent = expectedNewConfContent.arg(updateInfo); 0353 } 0354 QCOMPARE(newConfContentAfter, expectedNewConfContent); 0355 0356 if (oldConfName != newConfName) { 0357 QString oldConfContentAfter = readFile(oldConfPath); 0358 if (shouldUpdateWork) { 0359 expectedOldConfContent = expectedOldConfContent.arg(updateInfo); 0360 } 0361 QCOMPARE(oldConfContentAfter, expectedOldConfContent); 0362 } 0363 } 0364 0365 void TestKConfUpdate::testScript_data() 0366 { 0367 #ifdef Q_OS_WIN 0368 // add sh.exe and sed.exe to PATH on Windows 0369 // uncomment and adapt path to run all tests 0370 // qputenv("PATH", qgetenv("PATH") + ";C:\\kde\\msys\\bin"); 0371 #endif 0372 0373 QTest::addColumn<QString>("updContent"); 0374 QTest::addColumn<QString>("updScript"); 0375 QTest::addColumn<QString>("oldConfContent"); 0376 QTest::addColumn<QString>("expectedNewConfContent"); 0377 0378 QTest::newRow("delete-key") 0379 << 0380 "File=testrc\n" 0381 "Group=group\n" 0382 "Script=test.sh,sh\n" 0383 << 0384 "echo '# DELETE deprecated'\n" 0385 << 0386 "[group]\n" 0387 "deprecated=foo\n" 0388 "valid=bar\n" 0389 << 0390 "[$Version]\n" 0391 "update_info=%1\n" 0392 "\n" 0393 "[group]\n" 0394 "valid=bar\n" 0395 ; 0396 0397 QTest::newRow("delete-key2") 0398 << 0399 "File=testrc\n" 0400 "Script=test.sh,sh\n" 0401 << 0402 "echo '# DELETE [group]deprecated'\n" 0403 "echo '# DELETE [group][sub]deprecated2'\n" 0404 << 0405 "[group]\n" 0406 "deprecated=foo\n" 0407 "valid=bar\n" 0408 "\n" 0409 "[group][sub]\n" 0410 "deprecated2=foo\n" 0411 "valid2=bar\n" 0412 << 0413 "[$Version]\n" 0414 "update_info=%1\n" 0415 "\n" 0416 "[group]\n" 0417 "valid=bar\n" 0418 "\n" 0419 "[group][sub]\n" 0420 "valid2=bar\n" 0421 ; 0422 0423 QTest::newRow("delete-group") 0424 << 0425 "File=testrc\n" 0426 "Script=test.sh,sh\n" 0427 << 0428 "echo '# DELETEGROUP [group1]'\n" 0429 "echo '# DELETEGROUP [group2][sub]'\n" 0430 << 0431 "[group1]\n" 0432 "key=value\n" 0433 "\n" 0434 "[group2]\n" 0435 "valid=bar\n" 0436 "\n" 0437 "[group2][sub]\n" 0438 "key=value\n" 0439 << 0440 "[$Version]\n" 0441 "update_info=%1\n" 0442 "\n" 0443 "[group2]\n" 0444 "valid=bar\n" 0445 ; 0446 0447 QTest::newRow("delete-group2") 0448 << 0449 "File=testrc\n" 0450 "Group=group\n" 0451 "Script=test.sh,sh\n" 0452 << 0453 "echo '# DELETEGROUP'\n" 0454 << 0455 "[group]\n" 0456 "key=value\n" 0457 "\n" 0458 "[group2]\n" 0459 "valid=bar\n" 0460 << 0461 "[$Version]\n" 0462 "update_info=%1\n" 0463 "\n" 0464 "[group2]\n" 0465 "valid=bar\n" 0466 ; 0467 0468 QTest::newRow("new-key") 0469 << 0470 "File=testrc\n" 0471 "Script=test.sh,sh\n" 0472 << 0473 "echo '[group]'\n" 0474 "echo 'new=value'\n" 0475 << 0476 "[group]\n" 0477 "valid=bar\n" 0478 << 0479 "[$Version]\n" 0480 "update_info=%1\n" 0481 "\n" 0482 "[group]\n" 0483 "new=value\n" 0484 "valid=bar\n" 0485 ; 0486 0487 QTest::newRow("modify-key-no-overwrite") 0488 << 0489 "File=testrc\n" 0490 "Script=test.sh,sh\n" 0491 << 0492 "echo '[group]'\n" 0493 "echo 'existing=new'\n" 0494 << 0495 "[group]\n" 0496 "existing=old\n" 0497 << 0498 "[$Version]\n" 0499 "update_info=%1\n" 0500 "\n" 0501 "[group]\n" 0502 "existing=old\n" 0503 ; 0504 0505 QTest::newRow("modify-key-overwrite") 0506 << 0507 "File=testrc\n" 0508 "Options=overwrite\n" 0509 "Script=test.sh,sh\n" 0510 << 0511 "echo '[group]'\n" 0512 "echo 'existing=new'\n" 0513 << 0514 "[group]\n" 0515 "existing=old\n" 0516 << 0517 "[$Version]\n" 0518 "update_info=%1\n" 0519 "\n" 0520 "[group]\n" 0521 "existing=new\n" 0522 ; 0523 0524 QTest::newRow("new-key-in-subgroup") 0525 << 0526 "File=testrc\n" 0527 "Script=test.sh,sh\n" 0528 << 0529 "echo '[group][sub]'\n" 0530 "echo 'new=value2'\n" 0531 << 0532 "[group][sub]\n" 0533 "existing=foo\n" 0534 << 0535 "[$Version]\n" 0536 "update_info=%1\n" 0537 "\n" 0538 "[group][sub]\n" 0539 "existing=foo\n" 0540 "new=value2\n" 0541 ; 0542 0543 QTest::newRow("new-key-in-subgroup2") 0544 << 0545 "File=testrc\n" 0546 "Script=test.sh,sh\n" 0547 << 0548 "echo '[group][sub]'\n" 0549 "echo 'new=value3'\n" 0550 << 0551 "[group][sub]\n" 0552 "existing=foo\n" 0553 << 0554 "[$Version]\n" 0555 "update_info=%1\n" 0556 "\n" 0557 "[group][sub]\n" 0558 "existing=foo\n" 0559 "new=value3\n" 0560 ; 0561 0562 if (QStandardPaths::findExecutable(QStringLiteral("sed")).isEmpty()) { 0563 qWarning("sed executable not found, cannot run all tests!"); 0564 } else { 0565 QTest::newRow("filter") 0566 << 0567 "File=testrc\n" 0568 "Script=test.sh,sh\n" 0569 << 0570 "echo '# DELETE [group]changed'\n" 0571 "sed s/value/VALUE/\n" 0572 << 0573 "[group]\n" 0574 "changed=value\n" 0575 "unchanged=value\n" 0576 << 0577 "[$Version]\n" 0578 "update_info=%1\n" 0579 "\n" 0580 "[group]\n" 0581 "changed=VALUE\n" 0582 "unchanged=value\n" 0583 ; 0584 0585 QTest::newRow("filter-subgroup") 0586 << 0587 "File=testrc\n" 0588 "Script=test.sh,sh\n" 0589 << 0590 "echo '# DELETE [group][sub]changed'\n" 0591 "sed s/value/VALUE/\n" 0592 << 0593 "[group]\n" 0594 "unchanged=value\n" 0595 "\n" 0596 "[group][sub]\n" 0597 "changed=value\n" 0598 "unchanged=value\n" 0599 << 0600 "[$Version]\n" 0601 "update_info=%1\n" 0602 "\n" 0603 "[group]\n" 0604 "unchanged=value\n" 0605 "\n" 0606 "[group][sub]\n" 0607 "changed=VALUE\n" 0608 "unchanged=value\n" 0609 ; 0610 } 0611 } 0612 0613 void TestKConfUpdate::testScript() 0614 { 0615 if (QStandardPaths::findExecutable(QStringLiteral("sh")).isEmpty()) { 0616 QSKIP("Could not find sh executable, cannot run test"); 0617 return; 0618 } 0619 0620 QFETCH(QString, updContent); 0621 QFETCH(QString, updScript); 0622 QFETCH(QString, oldConfContent); 0623 QFETCH(QString, expectedNewConfContent); 0624 0625 // Prepend the Version and Id= field to the upd content 0626 updContent = QStringLiteral("Version=5\nId=%1\n").arg(QTest::currentDataTag()) + updContent; 0627 0628 QSharedPointer<QTemporaryFile> updFile(writeUpdFile(updContent)); 0629 0630 const QString scriptDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kconf_update"; 0631 QVERIFY(QDir().mkpath(scriptDir)); 0632 QString scriptPath = scriptDir + "/test.sh"; 0633 writeFile(scriptPath, updScript); 0634 QCOMPARE(readFile(scriptPath), updScript); 0635 0636 QString confPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + "testrc"; 0637 writeFile(confPath, oldConfContent); 0638 QCOMPARE(readFile(confPath), oldConfContent); 0639 0640 runKConfUpdate(updFile->fileName()); 0641 0642 QString updateInfo = QStringLiteral("%1:%2") 0643 .arg(updFile->fileName().section('/', -1)) 0644 .arg(QTest::currentDataTag()); 0645 QString newConfContent = readFile(confPath); 0646 expectedNewConfContent = expectedNewConfContent.arg(updateInfo); 0647 QCOMPARE(newConfContent, expectedNewConfContent); 0648 } 0649 0650