diff --git a/.github/workflows/ci_macos.yaml b/.github/workflows/ci_macos.yaml index 6a3fafa73..25d3f4375 100644 --- a/.github/workflows/ci_macos.yaml +++ b/.github/workflows/ci_macos.yaml @@ -16,10 +16,10 @@ jobs: matrix: libt_version: ["2.0.6", "1.2.16"] qbt_gui: ["GUI=ON", "GUI=OFF"] - qt_version: ["5.15.2", "6.3.0"] + qt_version: ["5.15.2", "6.2.0"] exclude: - libt_version: "1.2.16" - qt_version: "6.3.0" + qt_version: "6.2.0" env: boost_path: "${{ github.workspace }}/../boost" @@ -87,10 +87,12 @@ jobs: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DBOOST_ROOT="${{ env.boost_path }}" \ -DOPENSSL_ROOT_DIR="${{ env.openssl_root }}" \ + -DTESTING=ON \ -DVERBOSE_CONFIGURE=ON \ -D${{ matrix.qbt_gui }} cmake --build build --target qbt_update_translations cmake --build build + cmake --build build --target check - name: Build qBittorrent (Qt6) if: ${{ startsWith(matrix.qt_version, 6) }} @@ -103,10 +105,12 @@ jobs: -DBOOST_ROOT="${{ env.boost_path }}" \ -DOPENSSL_ROOT_DIR="${{ env.openssl_root }}" \ -DQT6=ON \ + -DTESTING=ON \ -DVERBOSE_CONFIGURE=ON \ -D${{ matrix.qbt_gui }} cmake --build build --target qbt_update_translations cmake --build build + cmake --build build --target check - name: Prepare build artifacts run: | diff --git a/.github/workflows/ci_ubuntu.yaml b/.github/workflows/ci_ubuntu.yaml index 790ad2e95..b83ff8cb3 100644 --- a/.github/workflows/ci_ubuntu.yaml +++ b/.github/workflows/ci_ubuntu.yaml @@ -70,10 +70,12 @@ jobs: -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DCMAKE_INSTALL_PREFIX="/usr" \ + -DTESTING=ON \ -DVERBOSE_CONFIGURE=ON \ -D${{ matrix.qbt_gui }} cmake --build build --target qbt_update_translations cmake --build build + cmake --build build --target check DESTDIR="qbittorrent" cmake --install build - name: Build qBittorrent (Qt6) @@ -86,10 +88,12 @@ jobs: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DCMAKE_INSTALL_PREFIX="/usr" \ -DQT6=ON \ + -DTESTING=ON \ -DVERBOSE_CONFIGURE=ON \ -D${{ matrix.qbt_gui }} cmake --build build --target qbt_update_translations cmake --build build + cmake --build build --target check DESTDIR="qbittorrent" cmake --install build - name: Prepare build artifacts diff --git a/.github/workflows/ci_windows.yaml b/.github/workflows/ci_windows.yaml index a9d7c34f0..0ed2afa52 100644 --- a/.github/workflows/ci_windows.yaml +++ b/.github/workflows/ci_windows.yaml @@ -115,11 +115,13 @@ jobs: -DLibtorrentRasterbar_DIR="${{ env.libtorrent_path }}/lib/cmake/LibtorrentRasterbar" ` -DMSVC_RUNTIME_DYNAMIC=OFF ` -DQT6=ON ` + -DTESTING=ON ` -DVCPKG_TARGET_TRIPLET=x64-windows-static-release ` -DVERBOSE_CONFIGURE=ON ` --graphviz=build/target_graph.dot cmake --build build --target qbt_update_translations cmake --build build + cmake --build build --target check - name: Prepare build artifacts run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c6ffc889..12bf50d66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,11 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR) # Policies <= CMP0097 default to NEW -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) - project(qBittorrent DESCRIPTION "The qBittorrent BitTorrent client" HOMEPAGE_URL "https://www.qbittorrent.org/" LANGUAGES CXX ) -# use CONFIG mode first in find_package -set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) # version requirements - older versions may work, but you are on your own set(minBoostVersion 1.71) set(minQt5Version 5.15.2) @@ -19,37 +15,51 @@ set(minLibtorrent1Version 1.2.14) set(minLibtorrentVersion 2.0.4) set(minZlibVersion 1.2.11) -# features (some are platform-specific) include(CheckCXXSourceCompiles) # TODO: migrate to CheckSourceCompiles in CMake >= 3.19 +include(GNUInstallDirs) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) include(FeatureSummary) include(FeatureOptionsSetup) -feature_option(QT6 "Use Qt6" OFF) -feature_option(STACKTRACE "Enable stacktraces" ON) + +# features, list is loosely sorted by user's interests feature_option(GUI "Build GUI application" ON) -feature_option(WEBUI "Enables built-in HTTP server for headless use" ON) +feature_option(WEBUI "Enable built-in HTTP server for remote control" ON) +feature_option(QT6 "Build with Qt 6 instead of Qt 5" OFF) +feature_option(STACKTRACE "Enable stacktrace support" ON) +feature_option(TESTING "Build internal testing suite" OFF) feature_option(VERBOSE_CONFIGURE "Show information about PACKAGES_FOUND and PACKAGES_NOT_FOUND in the configure output (only useful for debugging the CMake build scripts)" OFF) + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") feature_option_dependent(DBUS - "Enables support for notifications and power-management features on Linux via D-Bus" + "Enable support for notifications and power-management features via D-Bus on Linux" ON "GUI" OFF ) feature_option_dependent(SYSTEMD - "Install systemd service file to a directory manually overridable with SYSTEMD_SERVICES_INSTALL_DIR" + "Install systemd service file. Target directory is overridable with `SYSTEMD_SERVICES_INSTALL_DIR` variable" OFF "NOT GUI" OFF ) elseif (MSVC) feature_option(MSVC_RUNTIME_DYNAMIC "Use MSVC dynamic runtime library (-MD) instead of static (-MT)" ON) endif() -include(GNUInstallDirs) -add_subdirectory(src) -add_subdirectory(dist) - if (VERBOSE_CONFIGURE) feature_summary(WHAT ALL) else() feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES) endif() +# go check the packages +include(CheckPackages) +# configure for specific platform +include(CommonConfig) + # Generate version header configure_file("src/base/version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/base/version.h" @ONLY) + +add_subdirectory(src) +add_subdirectory(dist) + +if (TESTING) + add_subdirectory(test) +endif() diff --git a/cmake/Modules/CheckPackages.cmake b/cmake/Modules/CheckPackages.cmake new file mode 100644 index 000000000..672cbd9d2 --- /dev/null +++ b/cmake/Modules/CheckPackages.cmake @@ -0,0 +1,67 @@ +# use CONFIG mode first in find_package +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) + +macro(find_libtorrent version) + if (UNIX AND (NOT APPLE) AND (NOT CYGWIN)) + find_package(LibtorrentRasterbar QUIET ${version} COMPONENTS torrent-rasterbar) + if (NOT LibtorrentRasterbar_FOUND) + include(FindPkgConfig) + pkg_check_modules(LibtorrentRasterbar IMPORTED_TARGET GLOBAL "libtorrent-rasterbar>=${version}") + if (NOT LibtorrentRasterbar_FOUND) + message( + FATAL_ERROR + "Package LibtorrentRasterbar >= ${version} not found" + " with CMake or pkg-config.\n- Set LibtorrentRasterbar_DIR to a directory containing" + " a LibtorrentRasterbarConfig.cmake file or add the installation prefix of LibtorrentRasterbar" + " to CMAKE_PREFIX_PATH.\n- Alternatively, make sure there is a valid libtorrent-rasterbar.pc" + " file in your system's pkg-config search paths (use the system environment variable PKG_CONFIG_PATH" + " to specify additional search paths if needed)." + ) + endif() + add_library(LibtorrentRasterbar::torrent-rasterbar ALIAS PkgConfig::LibtorrentRasterbar) + # force a fake package to show up in the feature summary + set_property(GLOBAL APPEND PROPERTY + PACKAGES_FOUND + "LibtorrentRasterbar via pkg-config (version >= ${version})" + ) + set_package_properties("LibtorrentRasterbar via pkg-config (version >= ${version})" + PROPERTIES + TYPE REQUIRED + ) + else() + set_package_properties(LibtorrentRasterbar PROPERTIES TYPE REQUIRED) + endif() + else() + find_package(LibtorrentRasterbar ${version} REQUIRED COMPONENTS torrent-rasterbar) + endif() +endmacro() + +find_libtorrent(${minLibtorrent1Version}) +if (LibtorrentRasterbar_FOUND AND (LibtorrentRasterbar_VERSION VERSION_GREATER_EQUAL 2.0)) + find_libtorrent(${minLibtorrentVersion}) +endif() + +# force variable type so that it always shows up in ccmake/cmake-gui frontends +set_property(CACHE LibtorrentRasterbar_DIR PROPERTY TYPE PATH) +find_package(Boost ${minBoostVersion} REQUIRED) +find_package(OpenSSL ${minOpenSSLVersion} REQUIRED) +find_package(ZLIB ${minZlibVersion} REQUIRED) +if (QT6) + find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools) + if (DBUS) + find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS DBus) + set_package_properties(Qt6DBus PROPERTIES + DESCRIPTION "Qt6 module for inter-process communication over the D-Bus protocol" + PURPOSE "Required by the DBUS feature" + ) + endif() +else() + find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools) + if (DBUS) + find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS DBus) + set_package_properties(Qt5DBus PROPERTIES + DESCRIPTION "Qt5 module for inter-process communication over the D-Bus protocol" + PURPOSE "Required by the DBUS feature" + ) + endif() +endif() diff --git a/cmake/Modules/CommonConfig.cmake b/cmake/Modules/CommonConfig.cmake new file mode 100644 index 000000000..8e7a4c074 --- /dev/null +++ b/cmake/Modules/CommonConfig.cmake @@ -0,0 +1,106 @@ +# Set platform variables and create some interface-only library targets +# that some or all other targets will link to, either directly or transitively, +# to consume common compile options/definitions + +# treat value specified by the CXX_STANDARD target property as a requirement by default +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTORCC_OPTIONS --compress 9 --threshold 5) + +add_library(qbt_common_cfg INTERFACE) + +# Full C++ 17 support is required +# See also https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html +# for a breakdown of the features that CMake recognizes for each C++ standard +target_compile_features(qbt_common_cfg INTERFACE + cxx_std_17 +) + +target_compile_definitions(qbt_common_cfg INTERFACE + QT_DISABLE_DEPRECATED_BEFORE=0x050f02 + QT_NO_CAST_FROM_ASCII + QT_NO_CAST_TO_ASCII + QT_NO_CAST_FROM_BYTEARRAY + QT_NO_NARROWING_CONVERSIONS_IN_CONNECT + QT_USE_QSTRINGBUILDER + QT_STRICT_ITERATORS + $<$>:QT_NO_DEBUG_OUTPUT> +) + +if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_compile_definitions(qbt_common_cfg INTERFACE + _DARWIN_FEATURE_64_BIT_INODE + ) +endif() + +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_compile_definitions(qbt_common_cfg INTERFACE + NTDDI_VERSION=0x06010000 + _WIN32_WINNT=0x0601 + _WIN32_IE=0x0601 + WIN32_LEAN_AND_MEAN + NOMINMAX + UNICODE + _UNICODE + ) +endif() + +if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")) + target_compile_options(qbt_common_cfg INTERFACE + -Wall + -Wextra + -Wcast-qual + -Wcast-align + -Winvalid-pch + -Woverloaded-virtual + -Wold-style-cast + -Wnon-virtual-dtor + -pedantic + -pedantic-errors + ) + + # Clang 11 still doesn't support -Wstrict-null-sentinel + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-Wstrict-null-sentinel SNS_SUPPORT) + if (SNS_SUPPORT) + target_compile_options(qbt_common_cfg INTERFACE -Wstrict-null-sentinel) + endif() +endif() + +if ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")) + target_compile_options(qbt_common_cfg INTERFACE + -Wno-range-loop-analysis + ) +endif() + +if (MINGW) + target_link_options(qbt_common_cfg INTERFACE $<$,$>:LINKER:--dynamicbase>) +endif() + +if (MSVC) + target_compile_options(qbt_common_cfg INTERFACE + /guard:cf + /utf-8 + # https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ + /Zc:__cplusplus + ) + target_link_options(qbt_common_cfg INTERFACE + /guard:cf + $<$>:/OPT:REF /OPT:ICF> + # suppress linking warning due to /INCREMENTAL and /OPT:ICF being both ON + $<$:/INCREMENTAL:NO> + ) + + if (MSVC_RUNTIME_DYNAMIC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() +endif() + +if (LibtorrentRasterbar_VERSION VERSION_GREATER_EQUAL ${minLibtorrentVersion}) + target_compile_definitions(qbt_common_cfg INTERFACE QBT_USES_LIBTORRENT2) +endif() diff --git a/cmake/Modules/MacroQbtCommonConfig.cmake b/cmake/Modules/MacroQbtCommonConfig.cmake deleted file mode 100644 index e703437f4..000000000 --- a/cmake/Modules/MacroQbtCommonConfig.cmake +++ /dev/null @@ -1,104 +0,0 @@ -# Set common variables and create some interface-only library targets -# that some or all other targets will link to, either directly or transitively, -# to consume common compile options/definitions - -macro(qbt_common_config) - # treat value specified by the CXX_STANDARD target property as a requirement by default - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) - - add_library(qbt_common_cfg INTERFACE) - - # Full C++ 17 support is required - # See also https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # for a breakdown of the features that CMake recognizes for each C++ standard - target_compile_features(qbt_common_cfg INTERFACE - cxx_std_17 - ) - - target_compile_definitions(qbt_common_cfg INTERFACE - QT_DISABLE_DEPRECATED_BEFORE=0x050f02 - QT_NO_CAST_FROM_ASCII - QT_NO_CAST_TO_ASCII - QT_NO_CAST_FROM_BYTEARRAY - QT_NO_NARROWING_CONVERSIONS_IN_CONNECT - QT_USE_QSTRINGBUILDER - QT_STRICT_ITERATORS - $<$>:QT_NO_DEBUG_OUTPUT> - ) - - if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_compile_definitions(qbt_common_cfg INTERFACE - _DARWIN_FEATURE_64_BIT_INODE - ) - endif() - - if (CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_compile_definitions(qbt_common_cfg INTERFACE - NTDDI_VERSION=0x06010000 - _WIN32_WINNT=0x0601 - _WIN32_IE=0x0601 - WIN32_LEAN_AND_MEAN - NOMINMAX - UNICODE - _UNICODE - ) - endif() - - if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")) - target_compile_options(qbt_common_cfg INTERFACE - -Wall - -Wextra - -Wcast-qual - -Wcast-align - -Winvalid-pch - -Woverloaded-virtual - -Wold-style-cast - -Wnon-virtual-dtor - -pedantic - -pedantic-errors - ) - - # Clang 11 still doesn't support -Wstrict-null-sentinel - include(CheckCXXCompilerFlag) - check_cxx_compiler_flag(-Wstrict-null-sentinel SNS_SUPPORT) - if (SNS_SUPPORT) - target_compile_options(qbt_common_cfg INTERFACE -Wstrict-null-sentinel) - endif() - endif() - - if ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")) - target_compile_options(qbt_common_cfg INTERFACE - -Wno-range-loop-analysis - ) - endif() - - if (MINGW) - target_link_options(qbt_common_cfg INTERFACE $<$,$>:LINKER:--dynamicbase>) - endif() - - if (MSVC_RUNTIME_DYNAMIC) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") - else() - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - endif() - - if (MSVC) - target_compile_options(qbt_common_cfg INTERFACE - /guard:cf - /utf-8 - # https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - /Zc:__cplusplus - ) - target_link_options(qbt_common_cfg INTERFACE - /guard:cf - $<$>:/OPT:REF /OPT:ICF> - # suppress linking warning due to /INCREMENTAL and /OPT:ICF being both ON - $<$:/INCREMENTAL:NO> - ) - endif() - - if (LibtorrentRasterbar_VERSION VERSION_GREATER_EQUAL ${minLibtorrentVersion}) - target_compile_definitions(qbt_common_cfg INTERFACE QBT_USES_LIBTORRENT2) - endif() -endmacro(qbt_common_config) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ded8c5442..4dde49de7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,97 +1,12 @@ -macro(find_libtorrent version) - if (UNIX AND (NOT APPLE) AND (NOT CYGWIN)) - find_package(LibtorrentRasterbar QUIET ${version} COMPONENTS torrent-rasterbar) - if (NOT LibtorrentRasterbar_FOUND) - include(FindPkgConfig) - pkg_check_modules(LibtorrentRasterbar IMPORTED_TARGET GLOBAL "libtorrent-rasterbar>=${version}") - if (NOT LibtorrentRasterbar_FOUND) - message( - FATAL_ERROR - "Package LibtorrentRasterbar >= ${version} not found" - " with CMake or pkg-config.\n- Set LibtorrentRasterbar_DIR to a directory containing" - " a LibtorrentRasterbarConfig.cmake file or add the installation prefix of LibtorrentRasterbar" - " to CMAKE_PREFIX_PATH.\n- Alternatively, make sure there is a valid libtorrent-rasterbar.pc" - " file in your system's pkg-config search paths (use the system environment variable PKG_CONFIG_PATH" - " to specify additional search paths if needed)." - ) - endif() - add_library(LibtorrentRasterbar::torrent-rasterbar ALIAS PkgConfig::LibtorrentRasterbar) - # force a fake package to show up in the feature summary - set_property(GLOBAL APPEND PROPERTY - PACKAGES_FOUND - "LibtorrentRasterbar via pkg-config (version >= ${version})" - ) - set_package_properties("LibtorrentRasterbar via pkg-config (version >= ${version})" - PROPERTIES - TYPE REQUIRED - ) - else() - set_package_properties(LibtorrentRasterbar PROPERTIES TYPE REQUIRED) - endif() - else() - find_package(LibtorrentRasterbar ${version} REQUIRED COMPONENTS torrent-rasterbar) - endif() -endmacro() - -find_libtorrent(${minLibtorrent1Version}) -if (LibtorrentRasterbar_FOUND AND (LibtorrentRasterbar_VERSION VERSION_GREATER_EQUAL 2.0)) - find_libtorrent(${minLibtorrentVersion}) -endif() - -# force variable type so that it always shows up in ccmake/cmake-gui frontends -set_property(CACHE LibtorrentRasterbar_DIR PROPERTY TYPE PATH) -find_package(Boost ${minBoostVersion} REQUIRED) -find_package(OpenSSL ${minOpenSSLVersion} REQUIRED) -find_package(ZLIB ${minZlibVersion} REQUIRED) -if (QT6) - find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools) - if (DBUS) - find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS DBus) - set_package_properties(Qt6DBus PROPERTIES - DESCRIPTION "Qt6 module for inter-process communication over the D-Bus protocol" - PURPOSE "Required by the DBUS feature" - ) - endif() -else() - find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS Core Network Sql Xml LinguistTools) - if (DBUS) - find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS DBus) - set_package_properties(Qt5DBus PROPERTIES - DESCRIPTION "Qt5 module for inter-process communication over the D-Bus protocol" - PURPOSE "Required by the DBUS feature" - ) - endif() -endif() - -# automatically call Qt moc and rcc as needed for all targets by default -set(CMAKE_AUTORCC_OPTIONS --compress 9 --threshold 5) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -# create interface-only target libraries with common compile options/definitions to link to -include(MacroQbtCommonConfig) -qbt_common_config() - -# include directories - ideally, would be done per target instead of global directory scope include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_subdirectory(app) add_subdirectory(base) if (GUI) - if (QT6) - find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Widgets Svg) - else() - find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS Widgets Svg) - if (CMAKE_SYSTEM_NAME STREQUAL "Windows") - find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS WinExtras) - endif() - endif() - add_subdirectory(gui) endif() if (WEBUI) add_subdirectory(webui) endif() - -add_subdirectory(app) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 05546614f..9f2798636 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1,3 +1,11 @@ +if (QT6) + find_package(Qt6 ${minQt6Version} REQUIRED COMPONENTS Widgets Svg) +else() + find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS Widgets Svg) + if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + find_package(Qt5 ${minQt5Version} REQUIRED COMPONENTS WinExtras) + endif() +endif() # CMAKE_AUTO_UI causes unnecessary rebuilds qt_wrap_ui(UI_HEADERS diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..de3a36511 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,19 @@ +if (QT6) + find_package(Qt6 REQUIRED COMPONENTS Test) +else() + find_package(Qt5 REQUIRED COMPONENTS Test) +endif() + +enable_testing(true) +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure) + +include_directories("../src") + +file(GLOB testFiles "${CMAKE_CURRENT_SOURCE_DIR}/test*.cpp") +foreach(testFile ${testFiles}) + get_filename_component(testFilename "${testFile}" NAME_WLE) + + add_executable("${testFilename}" "${testFile}") + target_link_libraries("${testFilename}" PRIVATE Qt::Test qbt_base) + add_test(NAME "${testFilename}" COMMAND "${testFilename}") +endforeach() diff --git a/test/Readme.md b/test/Readme.md new file mode 100644 index 000000000..2e7573de6 --- /dev/null +++ b/test/Readme.md @@ -0,0 +1,4 @@ +# Test suite + +To run tests, add `-DTESTING=ON` argument when invoking cmake, then build the app as usual. \ +After building, run `cmake --build --target check` where `` is your cmake build directory. diff --git a/test/testutilsgzip.cpp b/test/testutilsgzip.cpp new file mode 100644 index 000000000..c46cc1fa1 --- /dev/null +++ b/test/testutilsgzip.cpp @@ -0,0 +1,70 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2022 Mike Tzou (Chocobo1) + * + * 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 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include + +#include "base/global.h" +#include "base/utils/gzip.h" + +class TestUtilsGzip final : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(TestUtilsGzip) + +public: + TestUtilsGzip() = default; + +private slots: + void testCompress() const + { + // compressed data is not reproducible, see: https://stackoverflow.com/questions/30150972/are-there-test-vectors-available-for-gzip + const QByteArray data = QByteArrayLiteral("abc"); + + bool ok = false; + const QByteArray compressedData = Utils::Gzip::compress(data, 6, &ok); + QVERIFY(ok); + } + + void testDecompress() const + { + const QByteArray data = QByteArrayLiteral("abc"); + + bool ok = false; + const QByteArray compressedData = Utils::Gzip::compress(data, 6, &ok); + QVERIFY(ok); + QVERIFY(compressedData != data); + + ok = false; + const QByteArray decompressedData = Utils::Gzip::decompress(compressedData, &ok); + QVERIFY(ok); + QCOMPARE(decompressedData, data); + } +}; + +QTEST_APPLESS_MAIN(TestUtilsGzip) +#include "testutilsgzip.moc"