diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bbedbe88..bfbbdc4c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,6 +35,7 @@ set(test_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/InputCompletion.cpp ${CMAKE_CURRENT_LIST_DIR}/src/XDGDesktopFile.cpp ${CMAKE_CURRENT_LIST_DIR}/src/XDGHelper.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/XDGDirectory.cpp ${CMAKE_CURRENT_LIST_DIR}/src/Selection.cpp ${CMAKE_CURRENT_LIST_DIR}/src/NotebookTab.cpp ${CMAKE_CURRENT_LIST_DIR}/src/SplitInput.cpp diff --git a/tests/src/Test.cpp b/tests/src/Test.cpp index 5f245f5d..db63b2d9 100644 --- a/tests/src/Test.cpp +++ b/tests/src/Test.cpp @@ -40,3 +40,10 @@ void PrintTo(const QString &str, std::ostream *os) { ::testing::internal::UniversalPrint(str.toStdU16String(), os); } + +std::unique_lock environmentLock() +{ + static std::mutex m; + + return std::unique_lock(m); +} diff --git a/tests/src/Test.hpp b/tests/src/Test.hpp index a44e244a..74528aa8 100644 --- a/tests/src/Test.hpp +++ b/tests/src/Test.hpp @@ -3,6 +3,7 @@ #include // IWYU pragma: export #include // IWYU pragma: export +#include #include class QString; @@ -20,3 +21,7 @@ void PrintTo(const QByteArray &bytes, std::ostream *os); void PrintTo(QStringView str, std::ostream *os); void PrintTo(const QString &str, std::ostream *os); // NOLINTEND(readability-identifier-naming) + +/// Use this lock when your test relies on certain environment variables being set. +/// It essentially helps ensure tests that rely on the same process environment variables cannot run in parallel +std::unique_lock environmentLock(); diff --git a/tests/src/XDGDirectory.cpp b/tests/src/XDGDirectory.cpp new file mode 100644 index 00000000..2a780ec5 --- /dev/null +++ b/tests/src/XDGDirectory.cpp @@ -0,0 +1,144 @@ +#include "util/XDGDirectory.hpp" + +#include "Test.hpp" +#include "util/CombinePath.hpp" + +#include +#include +#include + +#if defined(Q_OS_UNIX) and !defined(Q_OS_DARWIN) + +using namespace chatterino; + +namespace { + +class TempEnv +{ +public: + TempEnv(const char *key_, const QString &value_) + : key(key_) + , value(value_) + , prevValue(qEnvironmentVariable(this->key)) + { + if (!this->value.isNull()) + { + qDebug() << "Setting" << qPrintable(this->key) << "from" + << this->prevValue << "to" << this->value; + qputenv(this->key, this->value.toLocal8Bit()); + } + else + { + qDebug() << "Unsetting" << qPrintable(this->key) + << "- old value was" << this->prevValue; + qunsetenv(this->key); + } + } + + TempEnv(const TempEnv &) = delete; + TempEnv(TempEnv &&) = delete; + TempEnv &operator=(const TempEnv &) = delete; + TempEnv &operator=(TempEnv &&) = delete; + + ~TempEnv() + { + if (!this->prevValue.isNull()) + { + qDebug() << "Reverting" << qPrintable(this->key) << "to" + << this->prevValue; + qputenv(this->key, this->prevValue.toLocal8Bit()); + } + else + { + qDebug() << "Unsetting" << qPrintable(this->key) << "to" + << this->prevValue; + qunsetenv(this->key); + } + } + + const QString &getValue() const + { + return this->value; + } + +private: + const char *key; + QString value; + QString prevValue; +}; + +} // namespace + +/// Test the returned directories from XDGDirectoryType::Config when no extra environment variables are set +TEST(XDGDirectory, ConfigDefault) +{ + QTemporaryDir tmp; + auto lock = environmentLock(); + + TempEnv home("HOME", combinePath(tmp.path(), "home")); + TempEnv dataHome("XDG_CONFIG_HOME", {}); + TempEnv dataDirs("XDG_CONFIG_DIRS", {}); + + auto actual = getXDGDirectories(XDGDirectoryType::Config); + + ASSERT_EQ(actual.at(0), combinePath(home.getValue(), ".config/")); + ASSERT_EQ(actual.at(1), "/etc/xdg"); + + ASSERT_EQ(actual.length(), 2); +} + +TEST(XDGDirectory, ConfigCustom) +{ + auto lock = environmentLock(); + + TempEnv dataHome("XDG_CONFIG_HOME", "/tmp/home-data"); + TempEnv dataDirs("XDG_CONFIG_DIRS", "/tmp/sys-data-1:/tmp/sys-data-2"); + + auto actual = getXDGDirectories(XDGDirectoryType::Config); + + ASSERT_EQ(actual.at(0), "/tmp/home-data"); + ASSERT_EQ(actual.at(1), "/tmp/sys-data-1"); + ASSERT_EQ(actual.at(2), "/tmp/sys-data-2"); + + ASSERT_EQ(actual.length(), 3); +} + +/// Test the returned directories from XDGDirectoryType::Data when no extra environment variables are set +TEST(XDGDirectory, DataDefault) +{ + QTemporaryDir tmp; + auto lock = environmentLock(); + + TempEnv home("HOME", combinePath(tmp.path(), "home")); + TempEnv dataHome("XDG_DATA_HOME", {}); + TempEnv dataDirs("XDG_DATA_DIRS", {}); + + auto actual = getXDGDirectories(XDGDirectoryType::Data); + + ASSERT_EQ(actual.at(0), combinePath(home.getValue(), ".local/share/")); + ASSERT_EQ(actual.at(1), "/usr/local/share/"); + ASSERT_EQ(actual.at(2), "/usr/share/"); + + ASSERT_EQ(actual.length(), 3); +} + +/// Test the returned directories from XDGDirectoryType::Data when user custom-configured environment variables are set +TEST(XDGDirectory, DataCustom) +{ + auto lock = environmentLock(); + + TempEnv dataHome("XDG_DATA_HOME", "/tmp/home-share"); + TempEnv dataDirs("XDG_DATA_DIRS", + "/tmp/sys-share-1:/tmp/sys-share-2:/tmp/sys-share-3"); + + auto actual = getXDGDirectories(XDGDirectoryType::Data); + + ASSERT_EQ(actual.at(0), "/tmp/home-share"); + ASSERT_EQ(actual.at(1), "/tmp/sys-share-1"); + ASSERT_EQ(actual.at(2), "/tmp/sys-share-2"); + ASSERT_EQ(actual.at(3), "/tmp/sys-share-3"); + + ASSERT_EQ(actual.length(), 4); +} + +#endif