From 108e4efc8ad280142653d2f6ce3a7e3a630ee2f2 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Fri, 19 Oct 2018 20:10:37 +0200 Subject: [PATCH] Fix tests on Windows --- tests/CMakeLists.txt | 2 +- tests/TestCli.cpp | 24 ++++++++-------- tests/TestCli.h | 9 +++--- tests/gui/CMakeLists.txt | 2 +- tests/gui/TestGui.cpp | 6 ++-- tests/gui/TestGui.h | 4 +-- tests/util/TemporaryFile.cpp | 55 ++++++++++++++++++++++++++++++++++++ tests/util/TemporaryFile.h | 50 ++++++++++++++++++++++++++++++++ 8 files changed, 130 insertions(+), 22 deletions(-) create mode 100644 tests/util/TemporaryFile.cpp create mode 100644 tests/util/TemporaryFile.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 562b45e4d..fc2df2f62 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -95,7 +95,7 @@ set(TEST_LIBRARIES ${ZLIB_LIBRARIES} ) -set(testsupport_SOURCES TestGlobal.h modeltest.cpp FailDevice.cpp stub/TestClock.cpp) +set(testsupport_SOURCES TestGlobal.h modeltest.cpp FailDevice.cpp stub/TestClock.cpp util/TemporaryFile.cpp) add_library(testsupport STATIC ${testsupport_SOURCES}) target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test) diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp index 02bc0ba3f..fd51aa2e4 100644 --- a/tests/TestCli.cpp +++ b/tests/TestCli.cpp @@ -71,22 +71,22 @@ void TestCli::initTestCase() void TestCli::init() { - m_dbFile.reset(new QTemporaryFile()); + m_dbFile.reset(new TemporaryFile()); m_dbFile->open(); m_dbFile->write(m_dbData); - m_dbFile->flush(); + m_dbFile->close(); - m_stdinFile.reset(new QTemporaryFile()); + m_stdinFile.reset(new TemporaryFile()); m_stdinFile->open(); m_stdinHandle = fdopen(m_stdinFile->handle(), "r+"); Utils::STDIN = m_stdinHandle; - m_stdoutFile.reset(new QTemporaryFile()); + m_stdoutFile.reset(new TemporaryFile()); m_stdoutFile->open(); m_stdoutHandle = fdopen(m_stdoutFile->handle(), "r+"); Utils::STDOUT = m_stdoutHandle; - m_stderrFile.reset(new QTemporaryFile()); + m_stderrFile.reset(new TemporaryFile()); m_stderrFile->open(); m_stderrHandle = fdopen(m_stderrFile->handle(), "r+"); Utils::STDERR = m_stderrHandle; @@ -147,6 +147,7 @@ void TestCli::testAdd() Utils::setNextPassword("a"); addCmd.execute({"add", "-u", "newuser", "--url", "https://example.com/", "-g", "-l", "20", m_dbFile->fileName(), "/newuser-entry"}); + m_stderrFile->reset(); auto db = readTestDatabase(); auto* entry = db->rootGroup()->findEntryByPath("/newuser-entry"); @@ -220,7 +221,7 @@ void TestCli::testDiceware() passphrase = m_stdoutFile->readLine(); QCOMPARE(passphrase.split(" ").size(), 10); - QTemporaryFile wordFile; + TemporaryFile wordFile; wordFile.open(); for (int i = 0; i < 4500; ++i) { wordFile.write(QString("word" + QString::number(i) + "\n").toLatin1()); @@ -548,7 +549,7 @@ void TestCli::testLocate() entry->setUuid(QUuid::createUuid()); entry->setTitle("New Entry"); group->addEntry(entry); - QTemporaryFile tmpFile; + TemporaryFile tmpFile; tmpFile.open(); Kdbx4Writer writer; writer.writeDatabase(&tmpFile, db.data()); @@ -581,13 +582,13 @@ void TestCli::testMerge() // load test database and save a copy auto db = readTestDatabase(); QVERIFY(db); - QTemporaryFile targetFile1; + TemporaryFile targetFile1; targetFile1.open(); writer.writeDatabase(&targetFile1, db.data()); targetFile1.close(); // save another copy with a different password - QTemporaryFile targetFile2; + TemporaryFile targetFile2; targetFile2.open(); auto oldKey = db->key(); auto key = QSharedPointer::create(); @@ -605,7 +606,7 @@ void TestCli::testMerge() auto* group = db->rootGroup()->findGroupByPath("/Internet/"); QVERIFY(group); group->addEntry(entry); - QTemporaryFile sourceFile; + TemporaryFile sourceFile; sourceFile.open(); writer.writeDatabase(&sourceFile, db.data()); sourceFile.close(); @@ -615,6 +616,7 @@ void TestCli::testMerge() mergeCmd.execute({"merge", "-s", targetFile1.fileName(), sourceFile.fileName()}); m_stdoutFile->seek(pos); m_stdoutFile->readLine(); + m_stderrFile->reset(); QCOMPARE(m_stdoutFile->readAll(), QByteArray("Successfully merged the database files.\n")); QFile readBack(targetFile1.fileName()); @@ -660,7 +662,7 @@ void TestCli::testRemove() // load test database and save a copy with disabled recycle bin auto db = readTestDatabase(); QVERIFY(db); - QTemporaryFile fileCopy; + TemporaryFile fileCopy; fileCopy.open(); db->metadata()->setRecycleBinEnabled(false); writer.writeDatabase(&fileCopy, db.data()); diff --git a/tests/TestCli.h b/tests/TestCli.h index 532d84a79..691269840 100644 --- a/tests/TestCli.h +++ b/tests/TestCli.h @@ -19,6 +19,7 @@ #define KEEPASSXC_TESTCLI_H #include "core/Database.h" +#include "util/TemporaryFile.h" #include #include @@ -57,10 +58,10 @@ private slots: private: QByteArray m_dbData; - QScopedPointer m_dbFile; - QScopedPointer m_stdoutFile; - QScopedPointer m_stderrFile; - QScopedPointer m_stdinFile; + QScopedPointer m_dbFile; + QScopedPointer m_stdoutFile; + QScopedPointer m_stderrFile; + QScopedPointer m_stdinFile; FILE* m_stdoutHandle = stdout; FILE* m_stderrHandle = stderr; FILE* m_stdinHandle = stdin; diff --git a/tests/gui/CMakeLists.txt b/tests/gui/CMakeLists.txt index a6e876f47..8542e58cb 100644 --- a/tests/gui/CMakeLists.txt +++ b/tests/gui/CMakeLists.txt @@ -15,6 +15,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) -add_unit_test(NAME testgui SOURCES TestGui.cpp LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testgui SOURCES TestGui.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES}) add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES}) diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index ee53eb777..450f09474 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -102,7 +102,7 @@ void TestGui::initTestCase() // Every test starts with opening the temp database void TestGui::init() { - m_dbFile.reset(new QTemporaryFile()); + m_dbFile.reset(new TemporaryFile()); // Write the temp storage to a temp database file for use in our tests QVERIFY(m_dbFile->open()); QCOMPARE(m_dbFile->write(m_dbData), static_cast((m_dbData.size()))); @@ -289,7 +289,7 @@ void TestGui::createDatabaseCallback() QCOMPARE(fileCombo->currentText(), QString("%1/%2").arg(QString(KEEPASSX_TEST_DATA_DIR), "FileKeyHashed.key")); // save database to temporary file - QTemporaryFile tmpFile; + TemporaryFile tmpFile; QVERIFY(tmpFile.open()); tmpFile.close(); fileDialog()->setNextFileName(tmpFile.fileName()); @@ -1071,7 +1071,7 @@ void TestGui::testSaveAs() m_db->metadata()->setName("testSaveAs"); // open temporary file so it creates a filename - QTemporaryFile tmpFile; + TemporaryFile tmpFile; QVERIFY(tmpFile.open()); QString tmpFileName = tmpFile.fileName(); tmpFile.remove(); diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index 5e0b441b1..4df606f4a 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -20,12 +20,12 @@ #define KEEPASSX_TESTGUI_H #include "gui/MainWindow.h" +#include "util/TemporaryFile.h" #include #include #include #include -#include class Database; class DatabaseTabWidget; @@ -90,7 +90,7 @@ private: QPointer m_dbWidget; QPointer m_db; QByteArray m_dbData; - QScopedPointer m_dbFile; + QScopedPointer m_dbFile; QString m_dbFileName; QString m_dbFilePath; }; diff --git a/tests/util/TemporaryFile.cpp b/tests/util/TemporaryFile.cpp new file mode 100644 index 000000000..476313b02 --- /dev/null +++ b/tests/util/TemporaryFile.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TemporaryFile.h" + +#ifdef Q_OS_WIN + +TemporaryFile::TemporaryFile() + : TemporaryFile(nullptr) +{ +} + +TemporaryFile::TemporaryFile(const QString& templateName) + : TemporaryFile(templateName, nullptr) +{ +} + +TemporaryFile::TemporaryFile(QObject* parent) + : QFile(parent) +{ + QTemporaryFile tmp; + tmp.open(); + QFile::setFileName(tmp.fileName()); + tmp.close(); +} + +TemporaryFile::TemporaryFile(const QString& templateName, QObject* parent) + : QFile(parent) +{ + QTemporaryFile tmp(templateName); + tmp.open(); + QFile::setFileName(tmp.fileName()); + tmp.close(); +} + +bool TemporaryFile::open() +{ + return QFile::open(QIODevice::ReadWrite); +} + +#endif diff --git a/tests/util/TemporaryFile.h b/tests/util/TemporaryFile.h new file mode 100644 index 000000000..4e39a9ae7 --- /dev/null +++ b/tests/util/TemporaryFile.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_TEMPORARYFILE_H +#define KEEPASSXC_TEMPORARYFILE_H + +#include + +#ifdef Q_OS_WIN +/** + * QTemporaryFile does not actually close a file when close() is + * called, which causes the file to be locked on Windows. + * This class extends a QFile with the extra functionality + * of a QTemporaryFile to circumvent this problem. + */ +class TemporaryFile : public QFile +#else +class TemporaryFile : public QTemporaryFile +#endif +{ + Q_OBJECT + +#ifdef Q_OS_WIN +public: + TemporaryFile(); + explicit TemporaryFile(const QString& templateName); + explicit TemporaryFile(QObject* parent); + TemporaryFile(const QString& templateName, QObject* parent); + ~TemporaryFile() override = default; + + using QFile::open; + bool open(); +#endif +}; + +#endif //KEEPASSXC_TEMPORARYFILE_H