From ecece11df3fabcfb1e1b22aa110781050428684f Mon Sep 17 00:00:00 2001 From: Martchus Date: Fri, 26 Apr 2024 23:04:47 +0200 Subject: [PATCH] Introduce basic test setup for models This test setup utilizes the "mocked" configuration so far only used for manual testing. This allows adding unit tests for models without having to run Syncthing itself. The test is pretty basic itself at this point. --- syncthingconnector/CMakeLists.txt | 34 +++++++++++++ syncthingconnector/syncthingconnection.cpp | 2 + syncthingmodel/CMakeLists.txt | 21 ++++++++ syncthingmodel/tests/models.cpp | 59 ++++++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 syncthingmodel/tests/models.cpp diff --git a/syncthingconnector/CMakeLists.txt b/syncthingconnector/CMakeLists.txt index d74dcb1..fe9bd88 100644 --- a/syncthingconnector/CMakeLists.txt +++ b/syncthingconnector/CMakeLists.txt @@ -150,5 +150,39 @@ if (META_MAIN_TEST_NAME) set_tests_properties("${META_MAIN_TEST_NAME}" PROPERTIES RESOURCE_LOCK "syncthingtestinstance") endif () +# add additional library with mocked SyncthingConnector class so models can be tested without running Syncthing itself +if (EXCLUDE_TESTS_FROM_ALL) + set(TESTS_EXCLUSION EXCLUDE_FROM_ALL) +else () + unset(TESTS_EXCLUSION) +endif () +add_library( + ${META_TARGET_NAME}_mocked + ${TESTS_EXCLUSION} + OBJECT + syncthingconnection.h + syncthingconnection.cpp + syncthingconnection_requests.cpp + syncthingconnectionmockhelpers.h + syncthingconnectionmockhelpers.cpp) +target_link_libraries( + ${META_TARGET_NAME}_mocked + PUBLIC ${META_ADDITIONAL_LINK_FLAGS} "${PUBLIC_LIBRARIES}" + PRIVATE "${PRIVATE_LIBRARIES}") +target_include_directories( + ${META_TARGET_NAME}_mocked + PUBLIC ${TARGET_INCLUDE_DIRECTORY_BUILD_INTERFACE} ${TARGET_GENERATED_INCLUDE_DIRECTORY} ${PUBLIC_INCLUDE_DIRS} + PRIVATE ${PRIVATE_INCLUDE_DIRS}) +target_compile_definitions( + ${META_TARGET_NAME}_mocked + PUBLIC ${META_PUBLIC_COMPILE_DEFINITIONS} ${META_PROJECT_VARNAME_UPPER}_MOCKED + ${META_PROJECT_VARNAME_UPPER}_CONNECTION_MOCKED SyncthingConnection=SyncthingConnectionMocked + PRIVATE "${META_PRIVATE_COMPILE_DEFINITIONS}") +target_compile_options( + ${META_TARGET_NAME}_mocked + PUBLIC "${META_PUBLIC_COMPILE_OPTIONS}" + PRIVATE "${META_PRIVATE_COMPILE_OPTIONS}") +set_target_properties(${META_TARGET_NAME}_mocked PROPERTIES CXX_STANDARD "${META_CXX_STANDARD}") + include(Doxygen) include(ConfigHeader) diff --git a/syncthingconnector/syncthingconnection.cpp b/syncthingconnector/syncthingconnection.cpp index 701132e..c7c3c76 100644 --- a/syncthingconnector/syncthingconnection.cpp +++ b/syncthingconnector/syncthingconnection.cpp @@ -39,6 +39,7 @@ using namespace CppUtilities::EscapeCodes; namespace Data { +#ifndef LIB_SYNCTHING_CONNECTOR_MOCKED /*! * \brief Returns the QNetworkAccessManager instance used by SyncthingConnection instances. */ @@ -47,6 +48,7 @@ QNetworkAccessManager &networkAccessManager() static auto networkAccessManager = new QNetworkAccessManager; return *networkAccessManager; } +#endif /*! * \class SyncthingConnection diff --git a/syncthingmodel/CMakeLists.txt b/syncthingmodel/CMakeLists.txt index 1076233..b966bac 100644 --- a/syncthingmodel/CMakeLists.txt +++ b/syncthingmodel/CMakeLists.txt @@ -7,6 +7,7 @@ set(META_APP_NAME "Data models of Syncthing Tray") set(META_APP_DESCRIPTION "Data models of Syncthing Tray") set(META_PROJECT_VARNAME_UPPER LIB_SYNCTHING_MODEL) set(META_PUBLIC_QT_MODULES Gui Widgets) +set(META_SRCDIR_REFS "${CMAKE_CURRENT_SOURCE_DIR}/../syncthingconnector") # add project files set(HEADER_FILES @@ -37,6 +38,9 @@ set(RES_FILES resources/${META_PROJECT_NAME}icons.qrc) set(TS_FILES translations/${META_PROJECT_NAME}_zh_CN.ts translations/${META_PROJECT_NAME}_cs_CZ.ts translations/${META_PROJECT_NAME}_de_DE.ts translations/${META_PROJECT_NAME}_en_US.ts) +set(QT_TESTS models) +set(QT_TEST_SRC_FILES_models syncthingicons.cpp syncthingmodel.cpp syncthingdirectorymodel.cpp) + # find c++utilities find_package(${PACKAGE_NAMESPACE_PREFIX}c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.0.0 REQUIRED) use_cpp_utilities() @@ -63,3 +67,20 @@ include(WindowsResources) include(LibraryTarget) include(Doxygen) include(ConfigHeader) + +# configure test target +include(TestUtilities) +list(APPEND QT_TEST_LIBRARIES ${LIB_SYNCTHING_CONNECTOR_LIB}_mocked ${CPP_UTILITIES_LIB}) +use_qt_module(LIBRARIES_VARIABLE "QT_TEST_LIBRARIES" PREFIX "${QT_PACKAGE_PREFIX}" MODULE "Test") +foreach (TEST ${QT_TESTS}) + configure_test_target( + TEST_NAME + "${TEST}_tests" + SRC_FILES + ${QT_TEST_SRC_FILES_${TEST}} + "tests/${TEST}.cpp" + LIBRARIES + "${QT_TEST_LIBRARIES}" + FULL_TEST_NAME_OUT_VAR + FULL_TEST_NAME_${TEST}) +endforeach () diff --git a/syncthingmodel/tests/models.cpp b/syncthingmodel/tests/models.cpp new file mode 100644 index 0000000..faa9958 --- /dev/null +++ b/syncthingmodel/tests/models.cpp @@ -0,0 +1,59 @@ +#include "../syncthingdirectorymodel.h" + +#include + +#include + +#include +#include + +#include + +class ModelTests : public QObject { + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void testDirectoryModel(); + +private: + QTimer m_timeout; + QEventLoop m_loop; + Data::SyncthingConnection m_connection; +}; + +void ModelTests::initTestCase() +{ + // setup timeout + m_timeout.setSingleShot(true); + m_timeout.setInterval(5000); + m_timeout.start(); + connect(&m_timeout, &QTimer::timeout, this, [this] { + m_loop.quit(); + QFAIL("Timeout exceeded when loading mocked config/status for test"); + }); + + // request config and status and wait until available + connect(&m_connection, &Data::SyncthingConnection::newConfigApplied, &m_loop, &QEventLoop::quit); + m_connection.requestConfigAndStatus(); + m_loop.exec(); + m_timeout.stop(); +} + +void ModelTests::cleanupTestCase() +{ +} + +void ModelTests::testDirectoryModel() +{ + auto model = Data::SyncthingDirectoryModel(m_connection); + QCOMPARE(model.rowCount(QModelIndex()), 3); + QCOMPARE(model.index(0, 0).data(), QStringLiteral("A folder")); + QCOMPARE(model.index(1, 0).data(), QStringLiteral("Yet another folder")); + QCOMPARE(model.index(2, 0).data(), QStringLiteral("A folder which is not shared")); +} + +QTEST_MAIN(ModelTests) +#include "models.moc"