Warning, file /frameworks/kdelibs4support/autotests/ksavefiletest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 Copyright 2006 Allen Winter <winter@kde.org> 0004 Copyright 2006 Jaison Lee <lee.jaison@gmail.com> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License version 2 as published by the Free Software Foundation. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "ksavefiletest.h" 0022 0023 #include "kbackup.h" // TODO split out into a separate test 0024 0025 #include <QDebug> 0026 #include <QTextStream> 0027 0028 #include <qstandardpaths.h> 0029 #include <qtemporaryfile.h> 0030 0031 #include <kdebug.h> 0032 #include <klocalizedstring.h> 0033 #include <klocale.h> 0034 #include <ktemporaryfile.h> 0035 #include <ktempdir.h> 0036 #include <ksavefile.h> 0037 0038 #include <qtest_kde.h> 0039 0040 QTEST_KDEMAIN_CORE(KSaveFileTest) 0041 0042 void KSaveFileTest::initTestCase() 0043 { 0044 tmp = tmpDir.path() + '/'; 0045 } 0046 0047 void KSaveFileTest::test_ksavefile() 0048 { 0049 QString targetFile; 0050 0051 { 0052 //This will be the file we eventually write to. Yes, I know you 0053 //should never remove the temporaryfile and then expect the filename 0054 //to continue to be unique, but this is a test for crying out loud. :) 0055 QTemporaryFile file(QDir::tempPath() + QLatin1String("/ksavefiletest_XXXXXX")); 0056 QVERIFY(file.open()); 0057 targetFile = file.fileName(); 0058 } 0059 0060 { 0061 //Test basic functionality 0062 KSaveFile saveFile; 0063 saveFile.setFileName(targetFile); 0064 QVERIFY(saveFile.open()); 0065 QVERIFY(!QFile::exists(targetFile)); 0066 0067 QTextStream ts(&saveFile); 0068 ts << "This is test data one.\n"; 0069 ts.flush(); 0070 QCOMPARE(saveFile.error(), QFile::NoError); 0071 QVERIFY(!QFile::exists(targetFile)); 0072 0073 QVERIFY(saveFile.finalize()); 0074 QVERIFY(QFile::exists(targetFile)); 0075 0076 QFile::remove(targetFile); 0077 QVERIFY(!QFile::exists(targetFile)); 0078 } 0079 0080 { 0081 //Make sure destructor does what it is supposed to do. 0082 { 0083 KSaveFile saveFile; 0084 saveFile.setFileName(targetFile); 0085 QVERIFY(saveFile.open()); 0086 QVERIFY(!QFile::exists(targetFile)); 0087 } 0088 0089 QVERIFY(QFile::exists(targetFile)); 0090 QFile::remove(targetFile); 0091 QVERIFY(!QFile::exists(targetFile)); 0092 } 0093 0094 { 0095 //Test some error conditions 0096 KSaveFile saveFile; 0097 QVERIFY(!saveFile.open()); //no filename 0098 saveFile.setFileName(targetFile); 0099 QVERIFY(saveFile.open()); 0100 QVERIFY(!QFile::exists(targetFile)); 0101 QVERIFY(!saveFile.open()); //already open 0102 0103 QVERIFY(saveFile.finalize()); 0104 QVERIFY(QFile::exists(targetFile)); 0105 QVERIFY(!saveFile.finalize()); //already finalized 0106 0107 QFile::remove(targetFile); 0108 QVERIFY(!QFile::exists(targetFile)); 0109 } 0110 0111 { 0112 //Do it again, aborting this time 0113 KSaveFile saveFile(targetFile); 0114 QVERIFY(saveFile.open()); 0115 QVERIFY(!QFile::exists(targetFile)); 0116 0117 QTextStream ts(&saveFile); 0118 ts << "This is test data two.\n"; 0119 ts.flush(); 0120 QCOMPARE(saveFile.error(), QFile::NoError); 0121 QVERIFY(!QFile::exists(targetFile)); 0122 0123 saveFile.abort(); 0124 QVERIFY(!QFile::exists(targetFile)); 0125 } 0126 0127 QFile file(targetFile); 0128 QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text)); 0129 QVERIFY(file.setPermissions(file.permissions() | QFile::ExeUser)); 0130 file.close(); 0131 0132 { 0133 //Test how it works when the file already exists 0134 //Also check for special permissions 0135 KSaveFile saveFile(targetFile); 0136 QVERIFY(saveFile.open()); 0137 0138 QVERIFY(QFile::exists(targetFile)); 0139 QFileInfo fi(targetFile); 0140 0141 #ifndef Q_OS_WIN 0142 // Windows: qt_ntfs_permission_lookup is not set by default in 0143 // qfsfileengine_win.cpp, could change in future Qt versions. 0144 QVERIFY(fi.permission(QFile::ExeUser)); 0145 #endif 0146 QVERIFY(fi.size() == 0); 0147 0148 QTextStream ts(&saveFile); 0149 ts << "This is test data three.\n"; 0150 ts.flush(); 0151 0152 fi.refresh(); 0153 QVERIFY(fi.size() == 0); 0154 QVERIFY(saveFile.finalize()); 0155 0156 fi.refresh(); 0157 QVERIFY(fi.size() != 0); 0158 #ifndef Q_OS_WIN 0159 QVERIFY(fi.permission(QFile::ExeUser)); 0160 #endif 0161 0162 QFile::remove(targetFile); 0163 } 0164 0165 { 0166 QFileInfo fi(targetFile); 0167 targetFile = fi.fileName(); 0168 QDir::setCurrent(fi.path()); 0169 0170 //one more time, this time with relative filenames 0171 KSaveFile saveFile(targetFile); 0172 QVERIFY(saveFile.open()); 0173 QVERIFY(!QFile::exists(targetFile)); 0174 0175 QTextStream ts(&saveFile); 0176 ts << "This is test data four.\n"; 0177 ts.flush(); 0178 QCOMPARE(saveFile.error(), QFile::NoError); 0179 QVERIFY(!QFile::exists(targetFile)); 0180 0181 QVERIFY(saveFile.finalize()); 0182 QVERIFY(QFile::exists(targetFile)); 0183 QFile::remove(targetFile); 0184 } 0185 } 0186 0187 void KSaveFileTest::transactionalWriteNoPermissionsOnDir_data() 0188 { 0189 QTest::addColumn<bool>("directWriteFallback"); 0190 0191 QTest::newRow("default") << false; 0192 QTest::newRow("directWriteFallback") << true; 0193 } 0194 0195 void KSaveFileTest::transactionalWriteNoPermissionsOnDir() 0196 { 0197 #ifdef Q_OS_UNIX 0198 QFETCH(bool, directWriteFallback); 0199 // Restore permissions so that the QTemporaryDir cleanup can happen 0200 class PermissionRestorer 0201 { 0202 QString m_path; 0203 public: 0204 PermissionRestorer(const QString &path) 0205 : m_path(path) 0206 {} 0207 0208 ~PermissionRestorer() 0209 { 0210 restore(); 0211 } 0212 void restore() 0213 { 0214 QFile file(m_path); 0215 file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)); 0216 } 0217 }; 0218 0219 KTempDir dir; 0220 QVERIFY(QFile(dir.name()).setPermissions(QFile::ReadOwner | QFile::ExeOwner)); 0221 PermissionRestorer permissionRestorer(dir.name()); 0222 0223 const QString targetFile = dir.name() + QString::fromLatin1("/outfile"); 0224 KSaveFile firstTry(targetFile); 0225 QVERIFY(!firstTry.open(QIODevice::WriteOnly)); 0226 QCOMPARE((int)firstTry.error(), (int)QFile::PermissionsError); // actually better than QSaveFile (limited because of QTemporaryFileEngine) 0227 QVERIFY(!firstTry.finalize()); 0228 0229 // Now make an existing writable file 0230 permissionRestorer.restore(); 0231 QFile f(targetFile); 0232 QVERIFY(f.open(QIODevice::WriteOnly)); 0233 QCOMPARE(f.write("Hello"), Q_INT64_C(5)); 0234 f.close(); 0235 0236 // Make the directory non-writable again 0237 QVERIFY(QFile(dir.name()).setPermissions(QFile::ReadOwner | QFile::ExeOwner)); 0238 0239 // And write to it again using KSaveFile; only works if directWriteFallback is enabled 0240 KSaveFile file(targetFile); 0241 file.setDirectWriteFallback(directWriteFallback); 0242 QCOMPARE(file.directWriteFallback(), directWriteFallback); 0243 if (directWriteFallback) { 0244 QVERIFY(file.open(QIODevice::WriteOnly)); 0245 QCOMPARE((int)file.error(), (int)QFile::NoError); 0246 QCOMPARE(file.write("World"), Q_INT64_C(5)); 0247 QVERIFY(file.finalize()); 0248 0249 QFile reader(targetFile); 0250 QVERIFY(reader.open(QIODevice::ReadOnly)); 0251 QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("World")); 0252 reader.close(); 0253 0254 QVERIFY(file.open(QIODevice::WriteOnly)); 0255 QCOMPARE((int)file.error(), (int)QFile::NoError); 0256 QCOMPARE(file.write("W"), Q_INT64_C(1)); 0257 QVERIFY(file.finalize()); 0258 0259 QVERIFY(reader.open(QIODevice::ReadOnly)); 0260 QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("W")); 0261 } else { 0262 QVERIFY(!file.open(QIODevice::WriteOnly)); 0263 QCOMPARE((int)file.error(), (int)QFile::PermissionsError); 0264 } 0265 #endif 0266 } 0267 0268 void KSaveFileTest::test_simpleBackupFile() 0269 { 0270 QTemporaryFile file; 0271 QVERIFY(file.open()); 0272 0273 QVERIFY(KBackup::simpleBackupFile(file.fileName())); 0274 QVERIFY(QFile::exists(file.fileName() + '~')); 0275 QFile::remove(file.fileName() + '~'); 0276 0277 QVERIFY(KBackup::simpleBackupFile(file.fileName(), tmp)); 0278 QFileInfo fi(file.fileName()); 0279 QVERIFY(QFile::exists(tmp + fi.fileName() + '~')); 0280 QFile::remove(tmp + fi.fileName() + '~'); 0281 } 0282 0283 void KSaveFileTest::test_numberedBackupFile() 0284 { 0285 // Test absolute pathname file 0286 { 0287 QTemporaryFile file; 0288 QVERIFY(file.open()); 0289 0290 for (int i = 1; i < 15; i++) { 0291 QVERIFY(KBackup::numberedBackupFile(file.fileName())); 0292 } 0293 0294 QString fileNameTemplate = file.fileName() + ".%1~"; 0295 for (int i = 1; i <= 10; i++) { 0296 QVERIFY(QFile::exists(fileNameTemplate.arg(i))); 0297 filesToRemove << fileNameTemplate.arg(i); 0298 } 0299 0300 QVERIFY(!QFile::exists(fileNameTemplate.arg(11))); 0301 QVERIFY(!QFile::exists(fileNameTemplate.arg(12))); 0302 QVERIFY(!QFile::exists(fileNameTemplate.arg(13))); 0303 QVERIFY(!QFile::exists(fileNameTemplate.arg(14))); 0304 } 0305 0306 // Test current directory 0307 { 0308 QTemporaryFile file; 0309 QVERIFY(file.open()); 0310 0311 QFileInfo fi(file.fileName()); 0312 QVERIFY(QDir::setCurrent(fi.absolutePath())); 0313 0314 for (int i = 1; i < 15; i++) { 0315 QVERIFY(KBackup::numberedBackupFile(fi.fileName())); 0316 } 0317 0318 QString fileNameTemplate = fi.fileName() + ".%1~"; 0319 for (int i = 1; i <= 10; i++) { 0320 QVERIFY(QFile::exists(fileNameTemplate.arg(i))); 0321 filesToRemove << fileNameTemplate.arg(i); 0322 } 0323 0324 QVERIFY(!QFile::exists(fileNameTemplate.arg(11))); 0325 QVERIFY(!QFile::exists(fileNameTemplate.arg(12))); 0326 QVERIFY(!QFile::exists(fileNameTemplate.arg(13))); 0327 QVERIFY(!QFile::exists(fileNameTemplate.arg(14))); 0328 } 0329 0330 // Test absolute pathname file w/new directory 0331 { 0332 QTemporaryFile file; 0333 QVERIFY(file.open()); 0334 0335 QFileInfo fi(file.fileName()); 0336 QVERIFY(QDir::setCurrent(fi.absolutePath())); 0337 0338 for (int i = 1; i < 15; i++) { 0339 QVERIFY(KBackup::numberedBackupFile(fi.fileName(), tmp)); 0340 } 0341 0342 QString fileNameTemplate = tmp + fi.fileName() + ".%1~"; 0343 for (int i = 1; i <= 10; i++) { 0344 QVERIFY(QFile::exists(fileNameTemplate.arg(i))); 0345 filesToRemove << fileNameTemplate.arg(i); 0346 } 0347 0348 QVERIFY(!QFile::exists(fileNameTemplate.arg(11))); 0349 QVERIFY(!QFile::exists(fileNameTemplate.arg(12))); 0350 QVERIFY(!QFile::exists(fileNameTemplate.arg(13))); 0351 QVERIFY(!QFile::exists(fileNameTemplate.arg(14))); 0352 } 0353 0354 // Test current directory w/new directory 0355 { 0356 QTemporaryFile file; 0357 QVERIFY(file.open()); 0358 0359 QFileInfo fi(file.fileName()); 0360 QVERIFY(QDir::setCurrent(fi.absolutePath())); 0361 0362 for (int i = 1; i < 15; i++) { 0363 QVERIFY(KBackup::numberedBackupFile(fi.fileName(), tmp)); 0364 } 0365 0366 QString fileNameTemplate = tmp + fi.fileName() + ".%1~"; 0367 for (int i = 1; i <= 10; i++) { 0368 QVERIFY(QFile::exists(fileNameTemplate.arg(i))); 0369 filesToRemove << fileNameTemplate.arg(i); 0370 } 0371 0372 QVERIFY(!QFile::exists(fileNameTemplate.arg(11))); 0373 QVERIFY(!QFile::exists(fileNameTemplate.arg(12))); 0374 QVERIFY(!QFile::exists(fileNameTemplate.arg(13))); 0375 QVERIFY(!QFile::exists(fileNameTemplate.arg(14))); 0376 } 0377 0378 } 0379 0380 void KSaveFileTest::test_rcsBackupFile() 0381 { 0382 QString cipath = QStandardPaths::findExecutable("ci"); 0383 if (cipath.isEmpty()) { 0384 QSKIP("ci not available"); 0385 } 0386 0387 { 0388 QTemporaryFile f; 0389 QVERIFY(f.open()); 0390 0391 QVERIFY(KBackup::rcsBackupFile(f.fileName())); 0392 QVERIFY(QFile::exists(f.fileName() + ",v")); 0393 QVERIFY(KBackup::rcsBackupFile(f.fileName())); 0394 QVERIFY(QFile::exists(f.fileName() + ",v")); 0395 0396 filesToRemove << f.fileName() + ",v"; 0397 } 0398 0399 { 0400 QTemporaryFile f; 0401 QVERIFY(f.open()); 0402 0403 QVERIFY(KBackup::rcsBackupFile(f.fileName())); 0404 QVERIFY(QFile::exists(f.fileName() + ",v")); 0405 0406 QTextStream out(&f); 0407 out << "Testing a change\n"; 0408 out.flush(); 0409 0410 QVERIFY(KBackup::rcsBackupFile(f.fileName())); 0411 0412 out << "Testing another change\n"; 0413 out.flush(); 0414 0415 QVERIFY(KBackup::rcsBackupFile(f.fileName())); 0416 filesToRemove << f.fileName() + ",v"; 0417 } 0418 0419 { 0420 QTemporaryFile f; 0421 QVERIFY(f.open()); 0422 0423 QFileInfo fi(f.fileName()); 0424 QVERIFY(QDir::setCurrent(fi.absolutePath())); 0425 0426 QVERIFY(KBackup::rcsBackupFile(fi.fileName())); 0427 QVERIFY(QFile::exists(f.fileName() + ",v")); 0428 QVERIFY(KBackup::rcsBackupFile(fi.fileName())); 0429 QVERIFY(QFile::exists(f.fileName() + ",v")); 0430 0431 filesToRemove << f.fileName() + ",v"; 0432 } 0433 0434 { 0435 QTemporaryFile f; 0436 QVERIFY(f.open()); 0437 0438 QFileInfo fi(f.fileName()); 0439 0440 QVERIFY(KBackup::rcsBackupFile(f.fileName(), tmp)); 0441 QVERIFY(QFile::exists(tmp + fi.fileName() + ",v")); 0442 QVERIFY(KBackup::rcsBackupFile(f.fileName(), tmp)); 0443 QVERIFY(QFile::exists(tmp + fi.fileName() + ",v")); 0444 0445 filesToRemove << tmp + fi.fileName() + ",v"; 0446 } 0447 0448 { 0449 QTemporaryFile f; 0450 QVERIFY(f.open()); 0451 0452 QFileInfo fi(f.fileName()); 0453 QVERIFY(QDir::setCurrent(fi.absolutePath())); 0454 0455 QVERIFY(KBackup::rcsBackupFile(fi.fileName(), tmp)); 0456 QVERIFY(QFile::exists(tmp + fi.fileName() + ",v")); 0457 QVERIFY(KBackup::rcsBackupFile(fi.fileName(), tmp)); 0458 QVERIFY(QFile::exists(tmp + fi.fileName() + ",v")); 0459 0460 filesToRemove << tmp + fi.fileName() + ",v"; 0461 } 0462 } 0463 0464 void KSaveFileTest::cleanupTestCase() 0465 { 0466 foreach (const QString &fileToRemove, filesToRemove) { 0467 QFile::remove(fileToRemove); 0468 } 0469 }