From 66a8dda244152a6aef48461f83481faf87167210 Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 2 Aug 2023 17:35:41 +0200 Subject: [PATCH] Improve test setup * Improve code for reading environment variables * Make tests work when the temp directory is not `/tmp` because e.g. `TEMP` has been set or tests are executed under Windows --- cli/tests/application.cpp | 24 ++++++---- syncthingconnector/tests/connectiontests.cpp | 9 ++-- testhelper/helper.h | 14 ++++++ testhelper/syncthingtestinstance.cpp | 48 ++++++++++++-------- 4 files changed, 65 insertions(+), 30 deletions(-) diff --git a/cli/tests/application.cpp b/cli/tests/application.cpp index af6baee..a4959a9 100644 --- a/cli/tests/application.cpp +++ b/cli/tests/application.cpp @@ -1,3 +1,4 @@ +#include "../../testhelper/helper.h" #include "../../testhelper/syncthingtestinstance.h" #include @@ -94,14 +95,21 @@ void ApplicationTests::test() setenv("ENABLE_ESCAPE_CODES", "0", true); // load expected status - const auto expectedStatusData(readFile(testFilePath("expected-status.txt"), 4000)); - const auto expectedStatusLines(splitString>(expectedStatusData, "\n")); - vector expectedStatusPatterns; - expectedStatusPatterns.reserve(expectedStatusLines.size()); - for (const auto &line : expectedStatusLines) { - expectedStatusPatterns.emplace_back(line); - } - CPPUNIT_ASSERT(!expectedStatusPatterns.empty()); + const auto expectedStatusData = [] { + auto data = readFile(testFilePath("expected-status.txt"), 4000); + findAndReplace(data, "/tmp/", tempDirectory()); + return data; + }(); + const auto expectedStatusLines = splitString>(expectedStatusData, "\n"); + const auto expectedStatusPatterns = [&] { + auto regex = std::vector(); + regex.reserve(expectedStatusLines.size()); + for (const auto &line : expectedStatusLines) { + regex.emplace_back(line); + } + CPPUNIT_ASSERT(!regex.empty()); + return regex; + }(); // wait till Syncthing GUI becomes available { diff --git a/syncthingconnector/tests/connectiontests.cpp b/syncthingconnector/tests/connectiontests.cpp index bae12fb..1f8ad79 100644 --- a/syncthingconnector/tests/connectiontests.cpp +++ b/syncthingconnector/tests/connectiontests.cpp @@ -4,6 +4,8 @@ #include "../../testhelper/helper.h" #include "../../testhelper/syncthingtestinstance.h" +#include + #include #include @@ -472,10 +474,11 @@ void ConnectionTests::checkDirectories() const const auto &dirInfo = m_connection.dirInfo(); CPPUNIT_ASSERT_EQUAL_MESSAGE("2 dirs present", 2_st, dirInfo.size()); const SyncthingDir &dir1 = dirInfo.front(); + const auto tempDir = QtUtilities::fromNativeFileName(tempDirectory()); CPPUNIT_ASSERT_EQUAL(QStringLiteral("test1"), dir1.id); CPPUNIT_ASSERT_EQUAL(QStringLiteral(""), dir1.label); CPPUNIT_ASSERT_EQUAL(QStringLiteral("test1"), dir1.displayName()); - CPPUNIT_ASSERT_EQUAL(QStringLiteral("/tmp/some/path/1/"), dir1.path); + CPPUNIT_ASSERT_EQUAL(tempDir + QStringLiteral("some/path/1/"), dir1.path); CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir1.statusString()); CPPUNIT_ASSERT_EQUAL(SyncthingDirType::SendReceive, dir1.dirType); CPPUNIT_ASSERT(!dir1.paused); @@ -494,8 +497,8 @@ void ConnectionTests::checkDirectories() const CPPUNIT_ASSERT_EQUAL(QStringLiteral("test2"), dir2.id); CPPUNIT_ASSERT_EQUAL(QStringLiteral("Test dir 2"), dir2.label); CPPUNIT_ASSERT_EQUAL(QStringLiteral("Test dir 2"), dir2.displayName()); - CPPUNIT_ASSERT_EQUAL(QStringLiteral("/tmp/some/path/2/"), dir2.path); - CPPUNIT_ASSERT_EQUAL(QStringLiteral("/tmp/some/path/2"), dir2.pathWithoutTrailingSlash().toString()); + CPPUNIT_ASSERT_EQUAL(tempDir + QStringLiteral("some/path/2/"), dir2.path); + CPPUNIT_ASSERT_EQUAL(tempDir + QStringLiteral("some/path/2"), dir2.pathWithoutTrailingSlash().toString()); CPPUNIT_ASSERT_EQUAL(QStringLiteral("paused"), dir2.statusString()); CPPUNIT_ASSERT_EQUAL(SyncthingDirType::SendReceive, dir2.dirType); CPPUNIT_ASSERT(dir2.paused); diff --git a/testhelper/helper.h b/testhelper/helper.h index 3afe3c4..c81482f 100644 --- a/testhelper/helper.h +++ b/testhelper/helper.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -54,6 +55,19 @@ namespace CppUtilities { extern SYNCTHINGTESTHELPER_EXPORT double timeoutFactor; +/*! + * \brief Returns the temp directory using "/" consistently and ensuring a trailing "/" is always present. + */ +inline std::string tempDirectory() +{ + auto dir = std::filesystem::temp_directory_path().make_preferred().string(); + findAndReplace(dir, "\\", "/"); + if (!dir.empty() && (dir.back() != '/' || dir.back() != '\\')) { + dir += '/'; + } + return dir; +} + /*! * \brief Waits for the \a duration specified in ms while keeping the event loop running. */ diff --git a/testhelper/syncthingtestinstance.cpp b/testhelper/syncthingtestinstance.cpp index 4f4f394..16acc83 100644 --- a/testhelper/syncthingtestinstance.cpp +++ b/testhelper/syncthingtestinstance.cpp @@ -1,9 +1,13 @@ #include "./syncthingtestinstance.h" #include "./helper.h" +#include +#include + #include #include #include +#include #include #include @@ -40,10 +44,9 @@ void SyncthingTestInstance::start() cerr << "\n - Setup configuration for Syncthing tests ..." << endl; // set timeout factor for helper - const QByteArray timeoutFactorEnv(qgetenv("SYNCTHING_TEST_TIMEOUT_FACTOR")); - if (!timeoutFactorEnv.isEmpty()) { + if (const auto timeoutFactorEnv = qgetenv("SYNCTHING_TEST_TIMEOUT_FACTOR"); !timeoutFactorEnv.isEmpty()) { try { - timeoutFactor = stringToNumber(string(timeoutFactorEnv.data())); + timeoutFactor = stringToNumber(timeoutFactorEnv.data()); cerr << " - Using timeout factor " << timeoutFactor << endl; } catch (const ConversionException &) { cerr << " - Specified SYNCTHING_TEST_TIMEOUT_FACTOR \"" << timeoutFactorEnv.data() @@ -55,49 +58,56 @@ void SyncthingTestInstance::start() } // setup st config - const string configFilePath = workingCopyPath("testconfig/config.xml"); - if (configFilePath.empty()) { + const auto tempDir = tempDirectory(); + const auto relativeConfigFilePath = "testconfig/config.xml"s; + const auto configFilePathTemplate = testFilePath(relativeConfigFilePath); + const auto configFilePath = workingCopyPath(relativeConfigFilePath, WorkingCopyMode::NoCopy); + if (configFilePathTemplate.empty() || configFilePath.empty()) { throw runtime_error("Unable to setup Syncthing config directory."); } - const QFileInfo configFile(QString::fromLocal8Bit(configFilePath.data())); + auto configFile = readFile(configFilePathTemplate); + findAndReplace(configFile, "/tmp/", tempDir); + writeFile(configFilePath, configFile); + // clean config dir - const QDir configDir(configFile.dir()); - for (QFileInfo &configEntry : configDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)) { + const auto configFilePathFileInfo = QFileInfo(QtUtilities::fromNativeFileName(configFilePath)); + const auto configDir = QDir(configFilePathFileInfo.dir()); + for (const auto &configEntry : configDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)) { if (configEntry.isDir()) { QDir(configEntry.absoluteFilePath()).removeRecursively(); - } else if (configEntry.fileName() != QStringLiteral("config.xml")) { + } else if (configEntry.fileName() != QLatin1String("config.xml")) { QFile::remove(configEntry.absoluteFilePath()); } } // ensure dirs exist - const QDir parentDir(QStringLiteral("/tmp/some/path")); + const auto parentDir = QDir(QtUtilities::fromNativeFileName(tempDir) + QStringLiteral("some/path")); parentDir.mkpath(QStringLiteral("1")); parentDir.mkpath(QStringLiteral("2")); // determine st path - const QByteArray syncthingPathFromEnv(qgetenv("SYNCTHING_PATH")); - const QString syncthingPath(syncthingPathFromEnv.isEmpty() ? QStringLiteral("syncthing") : QString::fromLocal8Bit(syncthingPathFromEnv)); + auto syncthingPath = qEnvironmentVariable("SYNCTHING_PATH"); + if (syncthingPath.isEmpty()) { + syncthingPath = QStringLiteral("syncthing"); + } // determine st port - const int syncthingPortFromEnv(qEnvironmentVariableIntValue("SYNCTHING_PORT")); + const auto syncthingPortFromEnv = qEnvironmentVariableIntValue("SYNCTHING_PORT"); m_syncthingPort = !syncthingPortFromEnv ? QStringLiteral("4001") : QString::number(syncthingPortFromEnv); // start st // clang-format off - const QStringList args{ + const auto args = QStringList{ QStringLiteral("-gui-address=http://127.0.0.1:") + m_syncthingPort, QStringLiteral("-gui-apikey=") + m_apiKey, - QStringLiteral("-home=") + configFile.absolutePath(), + QStringLiteral("-home=") + configFilePathFileInfo.absolutePath(), QStringLiteral("-no-browser"), QStringLiteral("-verbose"), }; - cerr << "\n - Launching Syncthing: " - << syncthingPath.toStdString() - << ' ' << args.join(QChar(' ')).toStdString() << endl; + // clang-format on + cerr << "\n - Launching Syncthing: " << syncthingPath.toStdString() << ' ' << args.join(QChar(' ')).toStdString() << endl; m_processSupposedToRun = true; m_syncthingProcess.start(syncthingPath, args); - // clang-format on } /*!