mirror of
https://github.com/boostorg/mqtt5.git
synced 2025-06-25 04:01:33 +02:00
Add Jamfile, make CMake scripts Boost compliant
Summary: related to T15996 Reviewers: ivica, korina Reviewed By: ivica Subscribers: iljazovic, miljen Differential Revision: https://repo.mireo.local/D33480
This commit is contained in:
297
.github/workflows/ci.yml
vendored
297
.github/workflows/ci.yml
vendored
@ -9,121 +9,11 @@ name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
BOOST_VERSION: 1.82.0
|
||||
BOOST_DIR_VER_NAME: 1_82_0
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: "${{ matrix.toolset }} std=c++${{ matrix.cxxstd }}"
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# internal compiler error
|
||||
# - toolset: msvc-14.2 win64
|
||||
# os: windows-2019
|
||||
# architecture: x64
|
||||
# generator: "Visual Studio 16 2019"
|
||||
# cxxstd: 17
|
||||
# build-type: 'Debug'
|
||||
# cxxflags: ''
|
||||
# ldflags: '/machine:x64'
|
||||
|
||||
- toolset: msvc-14.3 win32
|
||||
os: windows-2022
|
||||
architecture: Win32
|
||||
generator: Visual Studio 17 2022
|
||||
cxxstd: 20
|
||||
build-type: 'Debug'
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: msvc-14.3 win64
|
||||
os: windows-2022
|
||||
architecture: x64
|
||||
generator: Visual Studio 17 2022
|
||||
cxxstd: 20
|
||||
build-type: 'Debug'
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CXXFLAGS: ${{ matrix.cxxflags }} /D_WIN32_WINNT=0x0601 /DWIN32_LEAN_AND_MEAN=1 /DNOMINMAX=1 /D_FILE_OFFSET_BITS=64 /DBOOST_ALL_NO_LIB /EHsc /bigobj
|
||||
LDFLAGS: ${{ matrix.ldflags }}
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 4
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup OpenSSL
|
||||
env:
|
||||
OPENSSL_ROOT: "C:\\OpenSSL"
|
||||
run: |
|
||||
if "${{ matrix.architecture }}" == "x64" (
|
||||
choco install --no-progress -y openssl --x64
|
||||
)
|
||||
if "${{ matrix.architecture }}" == "Win32" (
|
||||
set openssl_install_dir="C:\\Program Files (x86)\\OpenSSL-Win32"
|
||||
choco install --no-progress -y openssl --forcex86 --version 1.1.1.2100
|
||||
)
|
||||
if "${{ matrix.architecture }}" == "x64" (
|
||||
if exist "C:\Program Files\OpenSSL\" (
|
||||
set openssl_install_dir="C:\\Program Files\\OpenSSL"
|
||||
) else (
|
||||
set openssl_install_dir="C:\\Program Files\\OpenSSL-Win64"
|
||||
)
|
||||
)
|
||||
mklink /D %OPENSSL_ROOT% %openssl_install_dir%
|
||||
refreshenv
|
||||
set
|
||||
|
||||
- name: Setup Cmake
|
||||
run: |
|
||||
choco install cmake
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
curl -o boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz https://archives.boost.io/release/${{ env.BOOST_VERSION }}/source/boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
||||
tar -xf boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
||||
mkdir ${{ github.workspace }}\\boost_${{ env.BOOST_DIR_VER_NAME }}
|
||||
move boost_${{ env.BOOST_DIR_VER_NAME }}\\boost ${{ github.workspace }}\\boost_${{ env.BOOST_DIR_VER_NAME }}
|
||||
del boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
||||
|
||||
- name: Setup library
|
||||
run: |
|
||||
cmake -S . -B build -DBoost_INCLUDE_DIR="${{ github.workspace }}\\boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --install build
|
||||
|
||||
- name: Build examples
|
||||
run: |
|
||||
cmake -S example -B example\\build -A ${{ matrix.architecture }} ^
|
||||
-DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" ^
|
||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" ^
|
||||
-DBoost_INCLUDE_DIR="${{ github.workspace }}\\boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build example\\build -j 4
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cmake -S test -B test\\build -A ${{ matrix.architecture }} ^
|
||||
-DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" ^
|
||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" ^
|
||||
-DBoost_INCLUDE_DIR="${{ github.workspace }}\\boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build test\\build -j 4
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
.\\test\\build\\${{ matrix.build-type }}\\mqtt-test.exe
|
||||
|
||||
posix:
|
||||
name: "${{ matrix.toolset }} std=c++${{ matrix.cxxstd }} ${{ matrix.container }}"
|
||||
# TODO: windows builds
|
||||
|
||||
posix-cmake:
|
||||
name: "CMake ${{ matrix.toolset }} std=c++${{ matrix.cxxstd }} ${{ matrix.cxxflags }}"
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
@ -132,8 +22,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: g++-9
|
||||
compiler: g++-9
|
||||
- toolset: gcc-9
|
||||
install: g++-9
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -142,8 +31,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: g++-10
|
||||
compiler: g++-10
|
||||
- toolset: gcc-10
|
||||
install: g++-10
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -152,8 +40,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: g++-12
|
||||
compiler: g++-12
|
||||
- toolset: gcc-12
|
||||
install: g++-12
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -162,8 +49,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: g++-13
|
||||
compiler: g++-13
|
||||
- toolset: gcc-13
|
||||
install: g++-13
|
||||
os: ubuntu-24.04
|
||||
container: ubuntu:24.04
|
||||
@ -172,8 +58,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: g++-14 -fsanitize=address,undefined
|
||||
compiler: g++-14
|
||||
- toolset: gcc-14
|
||||
install: g++-14
|
||||
os: ubuntu-24.04
|
||||
container: ubuntu:24.04
|
||||
@ -182,8 +67,7 @@ jobs:
|
||||
cxxflags: '-fsanitize=address,undefined -fno-sanitize-recover=all'
|
||||
ldflags: '-fsanitize=address,undefined'
|
||||
|
||||
- toolset: clang++-12
|
||||
compiler: clang++-12
|
||||
- toolset: clang-12
|
||||
install: clang++-12
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -192,8 +76,7 @@ jobs:
|
||||
cxxflags: '-fdeclspec'
|
||||
ldflags: ''
|
||||
|
||||
- toolset: clang++-13
|
||||
compiler: clang++-13
|
||||
- toolset: clang-13
|
||||
install: clang++-13
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -202,8 +85,7 @@ jobs:
|
||||
cxxflags: '-fdeclspec'
|
||||
ldflags: ''
|
||||
|
||||
- toolset: clang++-14-libc++-14
|
||||
compiler: clang++-14
|
||||
- toolset: clang-14
|
||||
install: 'clang++-14 libc++-14-dev libc++abi-14-dev'
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -212,8 +94,7 @@ jobs:
|
||||
cxxflags: '-stdlib=libc++'
|
||||
ldflags: '-lc++'
|
||||
|
||||
- toolset: clang++-15
|
||||
compiler: clang++-15
|
||||
- toolset: clang-15
|
||||
install: clang++-15
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
@ -222,8 +103,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: clang++-16
|
||||
compiler: clang++-16
|
||||
- toolset: clang-16
|
||||
install: clang++-16
|
||||
os: ubuntu-24.04
|
||||
container: ubuntu:24.04
|
||||
@ -232,8 +112,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: clang++-17
|
||||
compiler: clang++-17
|
||||
- toolset: clang-17
|
||||
install: clang++-17
|
||||
os: ubuntu-24.04
|
||||
container: ubuntu:24.04
|
||||
@ -242,8 +121,7 @@ jobs:
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: clang++-18 -fsanitize=address,undefined
|
||||
compiler: clang++-18
|
||||
- toolset: clang-18
|
||||
install: clang++-18
|
||||
os: ubuntu-24.04
|
||||
container: ubuntu:24.04
|
||||
@ -267,40 +145,131 @@ jobs:
|
||||
if: matrix.container
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install sudo wget tar cmake openssl libssl-dev pkg-config
|
||||
apt-get -y install --no-install-recommends \
|
||||
sudo git g++ cmake make openssl libssl-dev ca-certificates pkg-config python3
|
||||
|
||||
- name: Install compiler
|
||||
- name: Install toolset
|
||||
run: sudo apt-get install -y ${{ matrix.install }}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
wget https://archives.boost.io/release/${{ env.BOOST_VERSION }}/source/boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
||||
tar xzf boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
||||
mkdir /usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}
|
||||
mv boost_${{ env.BOOST_DIR_VER_NAME }}/boost /usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}
|
||||
rm boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
||||
python3 tools/ci.py setup-boost \
|
||||
--source-dir=$(pwd)
|
||||
|
||||
- name: Setup library
|
||||
run: |
|
||||
cmake -S . -B build -DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" \
|
||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
sudo cmake --install build
|
||||
- name: Build a Boost distribution using B2
|
||||
run : |
|
||||
python3 tools/ci.py build-b2-distro \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Build examples
|
||||
- name: Build a Boost distribution using CMake
|
||||
run: |
|
||||
cmake -S example -B example/build \
|
||||
-DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" \
|
||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" \
|
||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build example/build -j 4
|
||||
python3 tools/ci.py build-cmake-distro \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Build standalone examples using CMake
|
||||
run: |
|
||||
python3 tools/ci.py build-cmake-standalone-examples \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Build standalone tests using CMake
|
||||
run: |
|
||||
python3 tools/ci.py build-cmake-standalone-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Run standalone tests
|
||||
run: |
|
||||
python3 tools/ci.py run-cmake-standalone-tests \
|
||||
--build-type ${{ matrix.build-type }}
|
||||
|
||||
- name: Run CMake find_package test with B2 distribution
|
||||
run: |
|
||||
python3 tools/ci.py run-cmake-b2-find-package-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Run CMake find_package test with CMake distribution
|
||||
run : |
|
||||
python3 tools/ci.py run-cmake-find-package-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Run CMake add_subdirectory test with CMake distribution
|
||||
run: |
|
||||
python3 tools/ci.py run-cmake-add-subdirectory-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
posix-b2:
|
||||
name: "B2 ${{ matrix.toolset }} std=c++${{ matrix.cxxstd }} ${{ matrix.cxxflags }}"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-11
|
||||
install: g++-11
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
build-type: 'debug,release'
|
||||
cxxstd: "17,20"
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
- toolset: clang-14
|
||||
install: clang-14
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
build-type: 'debug,release'
|
||||
cxxstd: "17,20"
|
||||
cxxflags: ''
|
||||
ldflags: ''
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
env:
|
||||
CXXFLAGS: ${{ matrix.cxxflags }} -Wall -Wextra
|
||||
LDFLAGS: ${{ matrix.ldflags }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install --no-install-recommends \
|
||||
sudo git g++ ca-certificates pkg-config python3
|
||||
|
||||
- name: Install toolset
|
||||
run: sudo apt-get install -y ${{ matrix.install }}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
python3 tools/ci.py setup-boost \
|
||||
--source-dir=$(pwd)
|
||||
|
||||
- name: Build a Boost distribution using B2
|
||||
run : |
|
||||
python3 tools/ci.py build-b2-distro \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Build tests
|
||||
- name: Build and run tests using B2
|
||||
run: |
|
||||
cmake -S test -B test/build \
|
||||
-DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" \
|
||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" \
|
||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build test/build -j 4
|
||||
|
||||
- name: Run tests
|
||||
run: ./test/build/mqtt-test
|
||||
python3 tools/ci.py run-b2-tests \
|
||||
--toolset ${{ matrix.toolset }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--variant ${{ matrix.build-type }}
|
||||
|
110
CMakeLists.txt
110
CMakeLists.txt
@ -1,50 +1,80 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
project(async-mqtt5 VERSION 1.0.2 LANGUAGES CXX)
|
||||
cmake_minimum_required(VERSION 3.8...3.20)
|
||||
|
||||
project(boost_mqtt5 VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
include(cmake/project-is-top-level.cmake)
|
||||
include(cmake/variables.cmake)
|
||||
|
||||
add_library(async_mqtt5 INTERFACE)
|
||||
add_library(Async::MQTT5 ALIAS async_mqtt5)
|
||||
|
||||
set_property(
|
||||
TARGET async_mqtt5 PROPERTY
|
||||
EXPORT_NAME MQTT5
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
async_mqtt5 ${warning_guard}
|
||||
INTERFACE
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
)
|
||||
|
||||
target_compile_features(async_mqtt5 INTERFACE cxx_std_17)
|
||||
|
||||
find_package(Boost 1.82 REQUIRED)
|
||||
target_link_libraries(async_mqtt5
|
||||
INTERFACE
|
||||
Boost::headers
|
||||
)
|
||||
|
||||
if(NOT CMAKE_SKIP_INSTALL_RULES)
|
||||
include(cmake/install-rules.cmake)
|
||||
# Determine if this is the superproject or called from add_subdirectory.
|
||||
if(NOT DEFINED BOOST_MQTT5_MAIN_PROJECT)
|
||||
set(BOOST_MQTT5_MAIN_PROJECT OFF)
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
set(BOOST_MQTT5_MAIN_PROJECT ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
option(BUILD_EXAMPLES "Build examples tree." "${async-mqtt5_DEVELOPER_MODE}")
|
||||
add_library(boost_mqtt5 INTERFACE)
|
||||
add_library(Boost::mqtt5 ALIAS boost_mqtt5)
|
||||
|
||||
# If non-Boost dependencies are not found, we just bail out.
|
||||
find_package(Threads)
|
||||
if(NOT Threads_FOUND)
|
||||
message(STATUS "Boost.MQTT5 has been disabled, because the required package Threads hasn't been found")
|
||||
return()
|
||||
endif()
|
||||
|
||||
target_include_directories(boost_mqtt5 INTERFACE include)
|
||||
target_compile_features(boost_mqtt5 INTERFACE cxx_std_17)
|
||||
|
||||
if(BOOST_MQTT5_MAIN_PROJECT)
|
||||
find_package(Boost 1.82 REQUIRED)
|
||||
if (NOT Boost_FOUND)
|
||||
message(STATUS "Cannot find Boost!")
|
||||
return()
|
||||
endif()
|
||||
target_link_libraries(boost_mqtt5 INTERFACE Boost::headers Threads::Threads)
|
||||
else()
|
||||
target_link_libraries(
|
||||
boost_mqtt5
|
||||
INTERFACE
|
||||
Boost::asio
|
||||
Boost::assert
|
||||
# Boost::beast # Optional, only used for MQTT connections over WebSocket.
|
||||
Boost::container
|
||||
Boost::core
|
||||
Boost::endian
|
||||
Boost::fusion
|
||||
Boost::optional
|
||||
Boost::random
|
||||
Boost::range
|
||||
Boost::smart_ptr
|
||||
Boost::spirit
|
||||
Boost::system
|
||||
Boost::type_traits
|
||||
Threads::Threads
|
||||
)
|
||||
endif()
|
||||
|
||||
option(BOOST_MQTT5_PUBLIC_BROKER_TESTS OFF "Whether to run tests requiring a public MQTT broker")
|
||||
mark_as_advanced(BOOST_MQTT5_PUBLIC_BROKER_TESTS)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
# Custom target tests; required by the Boost superproject
|
||||
if(NOT TARGET tests)
|
||||
add_custom_target(tests)
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(BOOST_MQTT5_MAIN_PROJECT)
|
||||
option(BUILD_EXAMPLES "Whether to build examples")
|
||||
if(BUILD_EXAMPLES)
|
||||
add_subdirectory(example)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT async-mqtt5_DEVELOPER_MODE)
|
||||
return()
|
||||
elseif(NOT PROJECT_IS_TOP_LEVEL)
|
||||
message(
|
||||
AUTHOR_WARNING
|
||||
"Developer mode is intended for developers of async-mqtt5"
|
||||
)
|
||||
endif()
|
||||
|
||||
include(cmake/dev-mode.cmake)
|
||||
|
37
build.jam
Normal file
37
build.jam
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
require-b2 5.2 ;
|
||||
|
||||
constant boost_dependencies :
|
||||
/boost/asio//boost_asio
|
||||
/boost/assert//boost_assert
|
||||
/boost/container//boost_container
|
||||
/boost/core//boost_core
|
||||
/boost/endian//boost_endian
|
||||
/boost/fusion//boost_fusion
|
||||
/boost/optional//boost_optional
|
||||
/boost/random//boost_random
|
||||
/boost/range//boost_range
|
||||
/boost/smart_ptr//boost_smart_ptr
|
||||
/boost/spirit//boost_spirit
|
||||
/boost/system//boost_system
|
||||
/boost/type_traits//boost_type_traits
|
||||
;
|
||||
|
||||
project /boost/mqtt5
|
||||
: common-requirements
|
||||
<include>include
|
||||
;
|
||||
|
||||
explicit
|
||||
[ alias boost_mqtt5 : : : : <library>$(boost_dependencies) ]
|
||||
[ alias all : boost_mqtt5 test ]
|
||||
;
|
||||
|
||||
call-if : boost-library mqtt5
|
||||
;
|
@ -1,4 +0,0 @@
|
||||
include(CTest)
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
@ -1,4 +0,0 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Boost 1.82)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/async-mqtt5Targets.cmake")
|
@ -1,66 +0,0 @@
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
set(
|
||||
CMAKE_INSTALL_INCLUDEDIR "/async-mqtt5-${PROJECT_VERSION}"
|
||||
CACHE STRING ""
|
||||
)
|
||||
set_property(CACHE CMAKE_INSTALL_INCLUDEDIR PROPERTY TYPE PATH)
|
||||
endif()
|
||||
|
||||
# Project is configured with no languages, so tell GNUInstallDirs the lib dir
|
||||
set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "")
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# find_package(<package>) call for consumers to find this project
|
||||
set(package async-mqtt5)
|
||||
|
||||
install(
|
||||
DIRECTORY include/
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT async-mqtt5_Development
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS async_mqtt5
|
||||
EXPORT async-mqtt5Targets
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${package}ConfigVersion.cmake"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
ARCH_INDEPENDENT
|
||||
)
|
||||
|
||||
# Allow package maintainers to freely override the path for the configs
|
||||
set(
|
||||
async-mqtt5_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}"
|
||||
CACHE STRING "CMake package config location relative to the install prefix"
|
||||
)
|
||||
set_property(CACHE async-mqtt5_INSTALL_CMAKEDIR PROPERTY TYPE PATH)
|
||||
mark_as_advanced(async-mqtt5_INSTALL_CMAKEDIR)
|
||||
|
||||
install(
|
||||
FILES cmake/install-config.cmake
|
||||
DESTINATION "${async-mqtt5_INSTALL_CMAKEDIR}"
|
||||
RENAME "${package}Config.cmake"
|
||||
COMPONENT async-mqtt5_Development
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake"
|
||||
DESTINATION "${async-mqtt5_INSTALL_CMAKEDIR}"
|
||||
COMPONENT async-mqtt5_Development
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT async-mqtt5Targets
|
||||
NAMESPACE Async::
|
||||
DESTINATION "${async-mqtt5_INSTALL_CMAKEDIR}"
|
||||
COMPONENT async-mqtt5_Development
|
||||
)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
include(CPack)
|
||||
endif()
|
@ -1,28 +0,0 @@
|
||||
# ---- Developer mode ----
|
||||
|
||||
# Developer mode enables targets and code paths in the CMake scripts that are
|
||||
# only relevant for the developer(s) of async-mqtt5
|
||||
# Targets necessary to build the project must be provided unconditionally, so
|
||||
# consumers can trivially build and package the project
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
option(async-mqtt5_DEVELOPER_MODE "Enable developer mode" OFF)
|
||||
endif()
|
||||
|
||||
# ---- Warning guard ----
|
||||
|
||||
# target_include_directories with the SYSTEM modifier will request the compiler
|
||||
# to omit warnings from the provided paths, if the compiler supports that
|
||||
# This is to provide a user experience similar to find_package when
|
||||
# add_subdirectory or FetchContent is used to consume this project
|
||||
set(warning_guard "")
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
option(
|
||||
async-mqtt5_INCLUDES_WITH_SYSTEM
|
||||
"Use SYSTEM modifier for async-mqtt5's includes, disabling warnings"
|
||||
ON
|
||||
)
|
||||
mark_as_advanced(async-mqtt5_INCLUDES_WITH_SYSTEM)
|
||||
if(async-mqtt5_INCLUDES_WITH_SYSTEM)
|
||||
set(warning_guard SYSTEM)
|
||||
endif()
|
||||
endif()
|
@ -1,16 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
project(async-mqtt5-examples CXX)
|
||||
cmake_minimum_required(VERSION 3.8...3.20)
|
||||
|
||||
include(../cmake/project-is-top-level.cmake)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
find_package(async-mqtt5 REQUIRED)
|
||||
endif()
|
||||
project(async-mqtt5-examples LANGUAGES CXX)
|
||||
|
||||
function(add_example name)
|
||||
add_executable("${name}" ${ARGN})
|
||||
target_link_libraries("${name}" PRIVATE Async::MQTT5)
|
||||
target_link_libraries("${name}" PRIVATE Boost::mqtt5)
|
||||
string(FIND "${example_name}" "tls" found_tls)
|
||||
if(found_tls GREATER -1)
|
||||
target_link_libraries("${name}" PRIVATE OpenSSL::SSL)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
@ -20,9 +20,7 @@
|
||||
#include <boost/asio/require.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
|
||||
namespace boost::mqtt5::detail {
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <boost/mqtt5/types.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/smart_ptr/allocate_unique.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
@ -109,13 +110,13 @@ public:
|
||||
}
|
||||
|
||||
qos_e qos() const {
|
||||
assert(control_code() == control_code_e::publish);
|
||||
BOOST_ASSERT(control_code() == control_code_e::publish);
|
||||
auto byte = (uint8_t(*(_packet->data())) & 0b00000110) >> 1;
|
||||
return qos_e(byte);
|
||||
}
|
||||
|
||||
control_packet& set_dup() {
|
||||
assert(control_code() == control_code_e::publish);
|
||||
BOOST_ASSERT(control_code() == control_code_e::publish);
|
||||
auto& byte = *(_packet->data());
|
||||
byte |= 0b00001000;
|
||||
return *this;
|
||||
|
@ -1,3 +1,10 @@
|
||||
//
|
||||
// Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MQTT5_SHUTDOWN_HPP
|
||||
#define BOOST_MQTT5_SHUTDOWN_HPP
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/asio/completion_condition.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/prepend.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <chrono>
|
||||
@ -148,7 +149,7 @@ public:
|
||||
return complete(ec, 0, {}, {});
|
||||
|
||||
_data_span.expand_suffix(bytes_read);
|
||||
assert(_data_span.size());
|
||||
BOOST_ASSERT(_data_span.size());
|
||||
|
||||
auto control_byte = uint8_t(*_data_span.first());
|
||||
|
||||
@ -187,7 +188,7 @@ private:
|
||||
auto negotiated_ka = _svc.negotiated_keep_alive();
|
||||
return negotiated_ka ?
|
||||
std::chrono::milliseconds(3 * negotiated_ka * 1000 / 2) :
|
||||
duration(std::numeric_limits<duration::rep>::max());
|
||||
duration((std::numeric_limits<duration::rep>::max)());
|
||||
}
|
||||
|
||||
static bool valid_header(uint8_t control_byte) {
|
||||
|
@ -277,7 +277,7 @@ private:
|
||||
_replies(_executor),
|
||||
_async_sender(*this),
|
||||
_active_span(_read_buff.cend(), _read_buff.cend()),
|
||||
_rec_channel(_executor, std::numeric_limits<size_t>::max()),
|
||||
_rec_channel(_executor, (std::numeric_limits<size_t>::max)()),
|
||||
_ping_timer(_executor),
|
||||
_sentry_timer(_executor)
|
||||
{
|
||||
@ -297,7 +297,7 @@ public:
|
||||
_replies(ex),
|
||||
_async_sender(*this),
|
||||
_active_span(_read_buff.cend(), _read_buff.cend()),
|
||||
_rec_channel(ex, std::numeric_limits<size_t>::max()),
|
||||
_rec_channel(ex, (std::numeric_limits<size_t>::max)()),
|
||||
_ping_timer(ex),
|
||||
_sentry_timer(ex)
|
||||
{}
|
||||
|
@ -96,7 +96,7 @@ private:
|
||||
auto negotiated_ka = _svc_ptr->negotiated_keep_alive();
|
||||
return negotiated_ka ?
|
||||
std::chrono::seconds(negotiated_ka) :
|
||||
duration(std::numeric_limits<duration::rep>::max());
|
||||
duration((std::numeric_limits<duration::rep>::max)());
|
||||
}
|
||||
|
||||
void complete() {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/prepend.hpp>
|
||||
#include <boost/asio/recycling_allocator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@ -146,7 +147,7 @@ private:
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
|
||||
perform();
|
||||
|
@ -222,7 +222,7 @@ private:
|
||||
|
||||
std::clog << property_name(prop) << ":";
|
||||
std::clog << "[";
|
||||
for (auto i = 0; i < val.size(); i++) {
|
||||
for (size_t i = 0; i < val.size(); i++) {
|
||||
if constexpr (detail::is_pair<decltype(val[i])>)
|
||||
std::clog << "(" << val[i].first << "," << val[i].second << ")";
|
||||
else
|
||||
|
@ -11,5 +11,10 @@
|
||||
"Concurrent",
|
||||
"IO"
|
||||
],
|
||||
"maintainers": [
|
||||
"Ivica Siladić",
|
||||
"Bruno Iljazović",
|
||||
"Korina Šimičević"
|
||||
],
|
||||
"cxxstd": "17"
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
project(async-mqtt5-tests CXX)
|
||||
|
||||
include(../cmake/project-is-top-level.cmake)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
find_package(async-mqtt5 REQUIRED)
|
||||
enable_testing()
|
||||
endif()
|
||||
project(boost_mqtt5_tests CXX)
|
||||
|
||||
file(GLOB integration_tests "integration/*.cpp")
|
||||
file(GLOB unit_tests "unit/*.cpp")
|
||||
@ -17,7 +15,31 @@ add_executable(mqtt-test src/run_tests.cpp ${integration_tests} ${unit_tests})
|
||||
target_include_directories(mqtt-test PRIVATE include)
|
||||
target_compile_definitions(mqtt-test PRIVATE BOOST_TEST_NO_MAIN=1)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(mqtt-test PRIVATE Async::MQTT5 OpenSSL::SSL)
|
||||
if(BOOST_MQTT5_MAIN_PROJECT)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_compile_definitions(mqtt-test PRIVATE BOOST_MQTT5_EXTRA_DEPS=1)
|
||||
|
||||
target_link_libraries(
|
||||
mqtt-test PRIVATE
|
||||
Boost::mqtt5
|
||||
OpenSSL::SSL
|
||||
)
|
||||
else()
|
||||
target_link_libraries(
|
||||
mqtt-test PRIVATE
|
||||
Boost::mqtt5
|
||||
Boost::included_unit_test_framework
|
||||
)
|
||||
|
||||
# Follow the Boost convention: don't build test targets by default,
|
||||
# and only when explicitly requested by building target tests
|
||||
set_target_properties(mqtt-test PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
add_dependencies(tests mqtt-test)
|
||||
endif()
|
||||
|
||||
include(CTest)
|
||||
add_test(NAME mqtt-test COMMAND mqtt-test)
|
||||
|
||||
if (BOOST_MQTT5_PUBLIC_BROKER_TESTS)
|
||||
set_property(TEST mqtt-test PROPERTY ENVIRONMENT "BOOST_MQTT5_PUBLIC_BROKER_TESTS=1")
|
||||
endif()
|
||||
|
28
test/Jamfile
Normal file
28
test/Jamfile
Normal file
@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
import-search /boost/config/checks ;
|
||||
import ac ;
|
||||
|
||||
# Use these requirements as both regular and usage requirements across all tests
|
||||
local requirements =
|
||||
<library>/boost/mqtt5//boost_mqtt5
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<define>BOOST_ASIO_NO_DEPRECATED=1
|
||||
<define>BOOST_TEST_NO_MAIN=1
|
||||
<toolset>msvc:<cxxflags>"/bigobj"
|
||||
<target-os>windows:<define>_WIN32_WINNT=0x0601
|
||||
<library>/boost/test//included
|
||||
;
|
||||
|
||||
run
|
||||
src/run_tests.cpp
|
||||
[ glob "unit/*.cpp" ]
|
||||
: requirements $(requirements)
|
||||
<include>include
|
||||
: target-name boost_mqtt5_tests
|
||||
;
|
19
test/cmake_b2_test/CMakeLists.txt
Normal file
19
test/cmake_b2_test/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.8...3.20)
|
||||
|
||||
project(cmake_b2_test LANGUAGES CXX)
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS headers)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_executable(main ../src/quick.cpp)
|
||||
target_link_libraries(main PRIVATE Boost::headers Threads::Threads)
|
||||
|
||||
include(CTest)
|
||||
add_test(main main)
|
18
test/cmake_install_test/CMakeLists.txt
Normal file
18
test/cmake_install_test/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.8...3.20)
|
||||
|
||||
project(cmake_install_test LANGUAGES CXX)
|
||||
|
||||
find_package(boost_mqtt5 REQUIRED)
|
||||
|
||||
add_executable(main ../src/quick.cpp)
|
||||
target_link_libraries(main Boost::mqtt5)
|
||||
|
||||
include(CTest)
|
||||
add_test(main main)
|
98
test/cmake_subdir_test/CMakeLists.txt
Normal file
98
test/cmake_subdir_test/CMakeLists.txt
Normal file
@ -0,0 +1,98 @@
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.8...3.20)
|
||||
|
||||
project(cmake_subdir_test LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(../../../mqtt5 boostorg/mqtt5)
|
||||
|
||||
# `boostdep --brief mqtt5`
|
||||
set(deps
|
||||
# Primary dependencies
|
||||
|
||||
asio
|
||||
assert
|
||||
# beast # Optional dependency, boostdep finds it because of websocket.hpp
|
||||
container
|
||||
core
|
||||
endian
|
||||
fusion
|
||||
optional
|
||||
random
|
||||
range
|
||||
smart_ptr
|
||||
spirit
|
||||
system
|
||||
type_traits
|
||||
|
||||
# Secondary dependencies
|
||||
|
||||
align
|
||||
config
|
||||
context
|
||||
date_time
|
||||
throw_exception
|
||||
bind
|
||||
container_hash
|
||||
intrusive
|
||||
# logic # Beast dependency
|
||||
mp11
|
||||
preprocessor
|
||||
static_assert
|
||||
# static_string # Beast dependency
|
||||
type_index
|
||||
winapi
|
||||
move
|
||||
function_types
|
||||
functional
|
||||
mpl
|
||||
tuple
|
||||
typeof
|
||||
utility
|
||||
array
|
||||
dynamic_bitset
|
||||
integer
|
||||
io
|
||||
concept_check
|
||||
conversion
|
||||
detail
|
||||
iterator
|
||||
regex
|
||||
"function"
|
||||
phoenix
|
||||
pool
|
||||
proto
|
||||
thread
|
||||
unordered
|
||||
variant
|
||||
variant2
|
||||
describe
|
||||
predef
|
||||
algorithm
|
||||
lexical_cast
|
||||
numeric/conversion
|
||||
tokenizer
|
||||
atomic
|
||||
chrono
|
||||
exception
|
||||
ratio
|
||||
)
|
||||
|
||||
foreach(dep IN LISTS deps)
|
||||
add_subdirectory(../../../${dep} boostorg/${dep} EXCLUDE_FROM_ALL)
|
||||
endforeach()
|
||||
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory(../../../test boostorg/test EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
add_executable(main ../src/quick.cpp)
|
||||
target_link_libraries(main Boost::mqtt5)
|
||||
|
||||
include(CTest)
|
||||
add_test(main main)
|
34
test/include/test_common/extra_deps.hpp
Normal file
34
test/include/test_common/extra_deps.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MQTT5_TEST_EXTRA_DEPS_HPP
|
||||
#define BOOST_MQTT5_TEST_EXTRA_DEPS_HPP
|
||||
|
||||
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
||||
|
||||
namespace boost::mqtt5 {
|
||||
|
||||
template <typename StreamBase>
|
||||
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
|
||||
static constexpr auto client = asio::ssl::stream_base::client;
|
||||
static constexpr auto server = asio::ssl::stream_base::server;
|
||||
};
|
||||
|
||||
template <typename StreamBase>
|
||||
void assign_tls_sni(
|
||||
const authority_path& ap,
|
||||
asio::ssl::context& /* ctx */,
|
||||
asio::ssl::stream<StreamBase>& stream
|
||||
) {
|
||||
SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str());
|
||||
}
|
||||
|
||||
} // end namespace boost::mqtt5
|
||||
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
#endif // BOOST_MQTT5_TEST_EXTRA_DEPS_HPP
|
40
test/include/test_common/preconditions.hpp
Normal file
40
test/include/test_common/preconditions.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MQTT5_TEST_PRECONDITIONS_HPP
|
||||
#define BOOST_MQTT5_TEST_PRECONDITIONS_HPP
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace boost::mqtt5::test {
|
||||
|
||||
static std::string safe_getenv(const char* name) {
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // MSVC doesn't like getenv
|
||||
#endif
|
||||
const char* res = std::getenv(name);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
return res ? res : "";
|
||||
}
|
||||
|
||||
struct env_condition {
|
||||
std::string env;
|
||||
boost::test_tools::assertion_result operator()(boost::unit_test::test_unit_id) {
|
||||
return !safe_getenv(env.c_str()).empty();
|
||||
}
|
||||
};
|
||||
static const env_condition public_broker_cond =
|
||||
env_condition { "BOOST_MQTT5_PUBLIC_BROKER_TESTS" };
|
||||
|
||||
} // end namespace boost::mqtt5::test
|
||||
|
||||
#endif // BOOST_MQTT5_TEST_PRECONDITIONS_HPP
|
@ -65,7 +65,7 @@ public:
|
||||
pending_read& operator=(const pending_read&) = delete;
|
||||
|
||||
size_t consume(const std::vector<uint8_t>& data) {
|
||||
size_t num_bytes = std::min(_buffer_size, data.size());
|
||||
size_t num_bytes = (std::min)(_buffer_size, data.size());
|
||||
if (num_bytes == 0)
|
||||
return 0;
|
||||
std::memcpy(_buffer_data, data.data(), num_bytes);
|
||||
@ -169,11 +169,11 @@ public:
|
||||
);
|
||||
BOOST_TEST(buffers_size == expected.size());
|
||||
|
||||
size_t num_packets = std::min(buffers_size, expected.size());
|
||||
size_t num_packets = (std::min)(buffers_size, expected.size());
|
||||
auto it = asio::buffer_sequence_begin(buffers);
|
||||
for (size_t i = 0; i < num_packets; ++i, ++it) {
|
||||
BOOST_TEST(it->size() == expected[i].size());
|
||||
size_t len = std::min(it->size(), expected[i].size());
|
||||
size_t len = (std::min)(it->size(), expected[i].size());
|
||||
if (memcmp(it->data(), expected[i].data(), len))
|
||||
BOOST_TEST_MESSAGE(
|
||||
concat_strings(
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <variant>
|
||||
#include <variant> // std::monostate
|
||||
|
||||
namespace boost::mqtt5::test {
|
||||
|
||||
|
@ -11,39 +11,21 @@
|
||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
||||
#include <boost/mqtt5.hpp>
|
||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
||||
|
||||
#include <boost/asio/as_tuple.hpp>
|
||||
#include <boost/asio/co_spawn.hpp>
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace boost::mqtt5 {
|
||||
#include "test_common/extra_deps.hpp"
|
||||
#include "test_common/preconditions.hpp"
|
||||
|
||||
template <typename StreamBase>
|
||||
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
|
||||
static constexpr auto client = asio::ssl::stream_base::client;
|
||||
static constexpr auto server = asio::ssl::stream_base::server;
|
||||
};
|
||||
|
||||
template <typename StreamBase>
|
||||
void assign_tls_sni(
|
||||
const authority_path& ap,
|
||||
asio::ssl::context& /* ctx */,
|
||||
asio::ssl::stream<StreamBase>& stream
|
||||
) {
|
||||
SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str());
|
||||
}
|
||||
|
||||
} // end namespace boost::mqtt5
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(client/*, *boost::unit_test::disabled()*/)
|
||||
BOOST_AUTO_TEST_SUITE(client,
|
||||
* boost::unit_test::precondition(boost::mqtt5::test::public_broker_cond))
|
||||
|
||||
using namespace boost::mqtt5;
|
||||
namespace asio = boost::asio;
|
||||
@ -139,6 +121,8 @@ BOOST_AUTO_TEST_CASE(tcp_client_check) {
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
|
||||
asio::io_context ioc;
|
||||
|
||||
@ -242,7 +226,8 @@ BOOST_AUTO_TEST_CASE(websocket_tls_client_check) {
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
#endif
|
||||
#endif // BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/type_traits/remove_cv_ref.hpp>
|
||||
@ -23,6 +22,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "test_common/extra_deps.hpp"
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/packet_util.hpp"
|
||||
#include "test_common/test_authenticators.hpp"
|
||||
@ -32,7 +32,7 @@
|
||||
using namespace boost::mqtt5;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(client_functions/*, *boost::unit_test::disabled()*/)
|
||||
BOOST_AUTO_TEST_SUITE(client_functions)
|
||||
|
||||
struct shared_test_data {
|
||||
error_code success {};
|
||||
@ -83,18 +83,6 @@ BOOST_AUTO_TEST_CASE(create_client_with_execution_context) {
|
||||
BOOST_CHECK(c.get_executor() == ioc.get_executor());
|
||||
}
|
||||
|
||||
void assign_tls_context() {
|
||||
// Tests if the tls_context function compiles
|
||||
|
||||
asio::io_context ioc;
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> tls_client(ioc.get_executor(), std::move(ctx));
|
||||
tls_client.tls_context();
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(assign_credentials, shared_test_data) {
|
||||
std::string client_id = "client_id";
|
||||
std::string username = "username";
|
||||
@ -118,23 +106,6 @@ BOOST_FIXTURE_TEST_CASE(assign_credentials, shared_test_data) {
|
||||
);
|
||||
}
|
||||
|
||||
void assign_credentials_tls_client() {
|
||||
// Tests if the assign credentials function compiles
|
||||
|
||||
std::string client_id = "client_id";
|
||||
std::string username = "username";
|
||||
std::string password = "password";
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.credentials(client_id, username, password);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(assign_will, shared_test_data) {
|
||||
will w("topic", "message");
|
||||
std::optional<will> will_opt { std::move(w) };
|
||||
@ -168,19 +139,6 @@ void assign_authenticator() {
|
||||
c.authenticator(test::test_authenticator());
|
||||
}
|
||||
|
||||
void assign_authenticator_tls_client() {
|
||||
// Tests if the authenticator function compiles
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.authenticator(test::test_authenticator());
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(assign_keep_alive, shared_test_data) {
|
||||
uint16_t keep_alive = 120;
|
||||
|
||||
@ -272,38 +230,6 @@ BOOST_FIXTURE_TEST_CASE(connect_property, shared_connect_prop_test_data) {
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(connect_properties_tls_client, shared_connect_prop_test_data) {
|
||||
// Tests if the connect_properties function compiles
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.connect_properties(cprops);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(connect_property_tls_client, shared_connect_prop_test_data) {
|
||||
// Tests if the connect_property functions compile
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.connect_property(prop::session_expiry_interval, session_expiry_interval);
|
||||
ts.connect_property(prop::receive_maximum, receive_maximum);
|
||||
ts.connect_property(prop::maximum_packet_size, maximum_packet_size);
|
||||
ts.connect_property(prop::topic_alias_maximum, topic_alias_maximum);
|
||||
ts.connect_property(prop::request_response_information, request_response_information);
|
||||
ts.connect_property(prop::request_problem_information, request_problem_information);
|
||||
ts.connect_property(prop::user_property, user_properties);
|
||||
}
|
||||
|
||||
struct shared_connack_prop_test_data {
|
||||
error_code success {};
|
||||
|
||||
@ -382,7 +308,7 @@ void run_test_with_post_fun(
|
||||
timer.async_wait(
|
||||
[&c, fun = std::forward<TestingClientFun>(client_fun)](error_code) {
|
||||
fun(c);
|
||||
c.cancel();
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
@ -440,6 +366,82 @@ BOOST_FIXTURE_TEST_CASE(connack_property, shared_connack_prop_test_data) {
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
void assign_credentials_tls_client() {
|
||||
// Tests if the assign credentials function compiles
|
||||
|
||||
std::string client_id = "client_id";
|
||||
std::string username = "username";
|
||||
std::string password = "password";
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.credentials(client_id, username, password);
|
||||
}
|
||||
|
||||
void assign_tls_context() {
|
||||
// Tests if the tls_context function compiles
|
||||
|
||||
asio::io_context ioc;
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> tls_client(ioc.get_executor(), std::move(ctx));
|
||||
tls_client.tls_context();
|
||||
}
|
||||
|
||||
void assign_authenticator_tls_client() {
|
||||
// Tests if the authenticator function compiles
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.authenticator(test::test_authenticator());
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(connect_properties_tls_client, shared_connect_prop_test_data) {
|
||||
// Tests if the connect_properties function compiles
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.connect_properties(cprops);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(connect_property_tls_client, shared_connect_prop_test_data) {
|
||||
// Tests if the connect_property functions compile
|
||||
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
mqtt_client<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>, asio::ssl::context
|
||||
> ts(ioc.get_executor(), std::move(ctx));
|
||||
|
||||
ts.connect_property(prop::session_expiry_interval, session_expiry_interval);
|
||||
ts.connect_property(prop::receive_maximum, receive_maximum);
|
||||
ts.connect_property(prop::maximum_packet_size, maximum_packet_size);
|
||||
ts.connect_property(prop::topic_alias_maximum, topic_alias_maximum);
|
||||
ts.connect_property(prop::request_response_information, request_response_information);
|
||||
ts.connect_property(prop::request_problem_information, request_problem_information);
|
||||
ts.connect_property(prop::user_property, user_properties);
|
||||
}
|
||||
|
||||
void connack_property_with_tls_client() {
|
||||
// Tests if the connack_properties & connack_property functions compile
|
||||
|
||||
@ -457,5 +459,6 @@ void connack_property_with_tls_client() {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
@ -11,7 +11,6 @@
|
||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
||||
#include <boost/mqtt5.hpp>
|
||||
#include <boost/mqtt5/websocket.hpp>
|
||||
|
||||
#include <boost/asio/as_tuple.hpp>
|
||||
#include <boost/asio/co_spawn.hpp>
|
||||
@ -20,14 +19,15 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/beast/websocket/stream.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "test_common/preconditions.hpp"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(mqtt_features/*, *boost::unit_test::disabled()*/)
|
||||
BOOST_AUTO_TEST_SUITE(mqtt_features,
|
||||
* boost::unit_test::precondition(boost::mqtt5::test::public_broker_cond))
|
||||
|
||||
using namespace boost::mqtt5;
|
||||
namespace asio = boost::asio;
|
||||
@ -36,9 +36,9 @@ constexpr auto use_nothrow_awaitable = asio::as_tuple(asio::use_awaitable);
|
||||
|
||||
constexpr auto test_duration = std::chrono::seconds(5);
|
||||
|
||||
using stream_type = boost::beast::websocket::stream<asio::ip::tcp::socket>;
|
||||
using stream_type = asio::ip::tcp::socket;
|
||||
|
||||
constexpr auto broker = "broker.hivemq.com/mqtt";
|
||||
constexpr auto broker = "broker.hivemq.com";
|
||||
constexpr auto connect_wait_dur = std::chrono::milliseconds(200);
|
||||
constexpr auto topic = "async-mqtt5/test";
|
||||
constexpr auto share_topic = "$share/sharename/async-mqtt5/test";
|
||||
@ -64,7 +64,7 @@ asio::awaitable<void> test_manual_use_topic_alias() {
|
||||
auto ex = co_await asio::this_coro::executor;
|
||||
|
||||
mqtt_client<stream_type> client(ex);
|
||||
client.brokers(broker, 8000)
|
||||
client.brokers(broker, 1883)
|
||||
.connect_property(prop::topic_alias_maximum, uint16_t(10))
|
||||
.async_run(asio::detached);
|
||||
|
||||
@ -96,7 +96,7 @@ asio::awaitable<void> test_subscription_identifiers() {
|
||||
auto ex = co_await asio::this_coro::executor;
|
||||
|
||||
mqtt_client<stream_type> client(ex);
|
||||
client.brokers(broker, 8000)
|
||||
client.brokers(broker, 1883)
|
||||
.async_run(asio::detached);
|
||||
|
||||
publish_props pprops;
|
||||
@ -137,7 +137,7 @@ asio::awaitable<void> test_shared_subscription() {
|
||||
auto ex = co_await asio::this_coro::executor;
|
||||
|
||||
mqtt_client<stream_type> client(ex);
|
||||
client.brokers(broker, 8000)
|
||||
client.brokers(broker, 1883)
|
||||
.async_run(asio::detached);
|
||||
|
||||
subscribe_options sub_opts = { .no_local = no_local_e::no };
|
||||
@ -172,7 +172,7 @@ asio::awaitable<void> test_user_property() {
|
||||
auto ex = co_await asio::this_coro::executor;
|
||||
|
||||
mqtt_client<stream_type> client(ex);
|
||||
client.brokers(broker, 8000)
|
||||
client.brokers(broker, 1883)
|
||||
.async_run(asio::detached);
|
||||
|
||||
publish_props pprops;
|
||||
|
@ -59,7 +59,7 @@ std::string connack_with_keep_alive(uint16_t keep_alive) {
|
||||
void run_test(
|
||||
test::msg_exchange broker_side,
|
||||
std::chrono::milliseconds cancel_timeout,
|
||||
uint16_t keep_alive = std::numeric_limits<uint16_t>::max()
|
||||
uint16_t keep_alive = (std::numeric_limits<uint16_t>::max)()
|
||||
) {
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
|
@ -93,7 +93,7 @@ void run_test(test::msg_exchange broker_side) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_TEST(!ec);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||
BOOST_TEST(rcs[0] == reason_codes::granted_qos_0);
|
||||
|
||||
c.cancel();
|
||||
@ -106,7 +106,7 @@ void run_test(test::msg_exchange broker_side) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_TEST(!ec);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||
BOOST_TEST(rcs[0] == reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
@ -423,7 +423,7 @@ void run_cancellation_test(test::msg_exchange broker_side) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_TEST(ec == asio::error::operation_aborted);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||
BOOST_TEST(rcs[0] == reason_codes::empty);
|
||||
|
||||
c.cancel();
|
||||
@ -439,7 +439,7 @@ void run_cancellation_test(test::msg_exchange broker_side) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_TEST(ec == asio::error::operation_aborted);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||
BOOST_TEST(rcs[0] == reason_codes::empty);
|
||||
|
||||
c.cancel();
|
||||
|
17
test/src/quick.cpp
Normal file
17
test/src/quick.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include <boost/asio/system_executor.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
int main() {
|
||||
boost::asio::system_executor sys;
|
||||
boost::mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(sys);
|
||||
return 0;
|
||||
}
|
@ -5,43 +5,23 @@
|
||||
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/asio/awaitable.hpp>
|
||||
#include <boost/asio/use_awaitable.hpp>
|
||||
|
||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
||||
#include <boost/mqtt5.hpp>
|
||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
||||
|
||||
#include <boost/asio/awaitable.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/beast/websocket/stream.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <variant> // std::monostate
|
||||
#include <vector>
|
||||
|
||||
namespace boost::mqtt5 {
|
||||
#include "test_common/extra_deps.hpp"
|
||||
|
||||
namespace asio = boost::asio;
|
||||
|
||||
template <typename StreamBase>
|
||||
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
|
||||
static constexpr auto client = asio::ssl::stream_base::client;
|
||||
static constexpr auto server = asio::ssl::stream_base::server;
|
||||
};
|
||||
|
||||
template <typename StreamBase>
|
||||
void assign_tls_sni(
|
||||
const authority_path& /* ap */,
|
||||
asio::ssl::context& /* ctx */,
|
||||
asio::ssl::stream<StreamBase>& /* stream */
|
||||
) {}
|
||||
|
||||
namespace test {
|
||||
namespace boost::mqtt5::test {
|
||||
|
||||
// the following code needs to compile
|
||||
|
||||
@ -83,11 +63,13 @@ asio::awaitable<void> test_default_completion_tokens_impl(
|
||||
auto dc_props = disconnect_props {};
|
||||
co_await c.async_disconnect();
|
||||
co_await c.async_disconnect(disconnect_rc_e::normal_disconnection, dc_props);
|
||||
co_return;
|
||||
}
|
||||
|
||||
asio::awaitable<void> test_default_completion_tokens() {
|
||||
co_await test_default_completion_tokens_impl<asio::ip::tcp::socket>();
|
||||
|
||||
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||
co_await test_default_completion_tokens_impl<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>,
|
||||
asio::ssl::context
|
||||
@ -105,10 +87,9 @@ asio::awaitable<void> test_default_completion_tokens() {
|
||||
asio::ssl::context(asio::ssl::context::tls_client),
|
||||
logger(log_level::debug)
|
||||
);
|
||||
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||
}
|
||||
|
||||
} // end namespace test
|
||||
|
||||
} // end namespace boost::mqtt5
|
||||
} // end namespace boost::mqtt5::test
|
||||
|
||||
#endif // BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
@ -8,15 +8,12 @@
|
||||
#include <boost/mqtt5/logger.hpp>
|
||||
#include <boost/mqtt5/logger_traits.hpp>
|
||||
#include <boost/mqtt5/mqtt_client.hpp>
|
||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
||||
|
||||
#include <boost/mqtt5/detail/log_invoke.hpp>
|
||||
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/beast/websocket/stream.hpp>
|
||||
#include <boost/test/tools/output_test_stream.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
@ -25,33 +22,15 @@
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_common/extra_deps.hpp"
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/preconditions.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace boost::mqtt5;
|
||||
namespace asio = boost::asio;
|
||||
|
||||
namespace boost::mqtt5 {
|
||||
|
||||
template <typename StreamBase>
|
||||
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
|
||||
static constexpr auto client = asio::ssl::stream_base::client;
|
||||
static constexpr auto server = asio::ssl::stream_base::server;
|
||||
};
|
||||
|
||||
template <typename StreamBase>
|
||||
void assign_tls_sni(
|
||||
const authority_path& ap,
|
||||
asio::ssl::context& /* ctx */,
|
||||
asio::ssl::stream<StreamBase>& stream
|
||||
) {
|
||||
SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str());
|
||||
}
|
||||
|
||||
} // end namespace boost::mqtt5
|
||||
|
||||
|
||||
void logger_test() {
|
||||
BOOST_STATIC_ASSERT(has_at_resolve<logger>);
|
||||
BOOST_STATIC_ASSERT(has_at_tcp_connect<logger>);
|
||||
@ -61,13 +40,6 @@ void logger_test() {
|
||||
BOOST_STATIC_ASSERT(has_at_disconnect<logger>);
|
||||
}
|
||||
|
||||
using stream_type = boost::beast::websocket::stream<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>
|
||||
>;
|
||||
using context_type = asio::ssl::context;
|
||||
using logger_type = logger;
|
||||
using client_type = mqtt_client<stream_type, context_type, logger_type>;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(logger_tests)
|
||||
|
||||
class clog_redirect {
|
||||
@ -90,61 +62,6 @@ bool contains(const std::string& str, const std::string& substr) {
|
||||
return str.find(substr) != std::string::npos;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(successful_connect_debug) {
|
||||
boost::test_tools::output_test_stream output;
|
||||
|
||||
{
|
||||
clog_redirect guard(output.rdbuf());
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context tls_context(asio::ssl::context::tls_client);
|
||||
client_type c(
|
||||
ioc, std::move(tls_context), logger(log_level::debug)
|
||||
);
|
||||
|
||||
c.brokers("broker.hivemq.com/mqtt", 8884)
|
||||
.async_run(asio::detached);
|
||||
|
||||
c.async_disconnect([](error_code) {});
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
std::string log = output.rdbuf()->str();
|
||||
BOOST_TEST_MESSAGE(log);
|
||||
BOOST_TEST_WARN(contains(log, "resolve"));
|
||||
BOOST_TEST_WARN(contains(log, "TCP connect"));
|
||||
BOOST_TEST_WARN(contains(log, "TLS handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "WebSocket handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "connack"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(successful_connect_warning) {
|
||||
boost::test_tools::output_test_stream output;
|
||||
|
||||
{
|
||||
clog_redirect guard(output.rdbuf());
|
||||
|
||||
asio::io_context ioc;
|
||||
asio::ssl::context tls_context(asio::ssl::context::tls_client);
|
||||
client_type c(
|
||||
ioc, std::move(tls_context), logger(log_level::warning)
|
||||
);
|
||||
|
||||
c.brokers("broker.hivemq.com/mqtt", 8884)
|
||||
.async_run(asio::detached);
|
||||
|
||||
c.async_disconnect([](error_code) {});
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
// If connection is successful, nothing should be printed.
|
||||
// However if the Broker is down or overloaded, this will cause logs to be printed.
|
||||
// We should not fail the test because of it.
|
||||
BOOST_TEST_WARN(output.is_empty());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(disconnect) {
|
||||
using test::after;
|
||||
using namespace std::chrono_literals;
|
||||
@ -194,4 +111,72 @@ BOOST_AUTO_TEST_CASE(disconnect) {
|
||||
BOOST_TEST(contains(log, "disconnect"));
|
||||
}
|
||||
|
||||
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||
using stream_type = boost::beast::websocket::stream<
|
||||
asio::ssl::stream<asio::ip::tcp::socket>
|
||||
>;
|
||||
using context_type = asio::ssl::context;
|
||||
using logger_type = logger;
|
||||
using client_type = mqtt_client<stream_type, context_type, logger_type>;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(successful_connect_debug,
|
||||
* boost::unit_test::precondition(test::public_broker_cond))
|
||||
{
|
||||
boost::test_tools::output_test_stream output;
|
||||
|
||||
{
|
||||
clog_redirect guard(output.rdbuf());
|
||||
asio::io_context ioc;
|
||||
|
||||
asio::ssl::context tls_context(asio::ssl::context::tls_client);
|
||||
client_type c(
|
||||
ioc, std::move(tls_context), logger(log_level::debug)
|
||||
);
|
||||
|
||||
c.brokers("broker.hivemq.com/mqtt", 8884)
|
||||
.async_run(asio::detached);
|
||||
|
||||
c.async_disconnect([](error_code) {});
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
std::string log = output.rdbuf()->str();
|
||||
BOOST_TEST_MESSAGE(log);
|
||||
BOOST_TEST_WARN(contains(log, "resolve"));
|
||||
BOOST_TEST_WARN(contains(log, "TCP connect"));
|
||||
BOOST_TEST_WARN(contains(log, "TLS handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "WebSocket handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "connack"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(successful_connect_warning,
|
||||
* boost::unit_test::precondition(test::public_broker_cond))
|
||||
{
|
||||
boost::test_tools::output_test_stream output;
|
||||
|
||||
{
|
||||
clog_redirect guard(output.rdbuf());
|
||||
|
||||
asio::io_context ioc;
|
||||
asio::ssl::context tls_context(asio::ssl::context::tls_client);
|
||||
client_type c(
|
||||
ioc, std::move(tls_context), logger(log_level::warning)
|
||||
);
|
||||
|
||||
c.brokers("broker.hivemq.com/mqtt", 8884)
|
||||
.async_run(asio::detached);
|
||||
|
||||
c.async_disconnect([](error_code) {});
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
// If connection is successful, nothing should be printed.
|
||||
// However if the Broker is down or overloaded, this will cause logs to be printed.
|
||||
// We should not fail the test because of it.
|
||||
BOOST_TEST_WARN(output.is_empty());
|
||||
}
|
||||
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(test_connect) {
|
||||
BOOST_TEST(*cprops_[prop::topic_alias_maximum] == topic_alias_max);
|
||||
BOOST_TEST(*cprops_[prop::request_response_information] == request_response_information);
|
||||
BOOST_TEST(*cprops_[prop::request_problem_information] == request_problem_information);
|
||||
BOOST_TEST_REQUIRE(cprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(cprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(cprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(cprops_[prop::user_property][0].second == user_property_2);
|
||||
BOOST_TEST(*cprops_[prop::authentication_method] == auth_method);
|
||||
@ -125,7 +125,7 @@ BOOST_AUTO_TEST_CASE(test_connect) {
|
||||
BOOST_TEST(*(will)[prop::content_type] == will_content_type);
|
||||
BOOST_TEST(*(will)[prop::response_topic] == will_response_topic);
|
||||
BOOST_TEST(*(will)[prop::correlation_data] == will_correlation_data);
|
||||
BOOST_TEST_REQUIRE((will)[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE((will)[prop::user_property].size() == 1u);
|
||||
BOOST_TEST((will)[prop::user_property][0].first == will_user_property_1);
|
||||
BOOST_TEST((will)[prop::user_property][0].second == will_user_property_2);
|
||||
}
|
||||
@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE(test_connack) {
|
||||
BOOST_TEST(*cprops_[prop::assigned_client_identifier] == assigned_client_id);
|
||||
BOOST_TEST(*cprops_[prop::topic_alias_maximum] == topic_alias_max);
|
||||
BOOST_TEST(*cprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(cprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(cprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(cprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(cprops_[prop::user_property][0].second == user_property_2);
|
||||
BOOST_TEST(*cprops_[prop::wildcard_subscription_available] == wildcard_sub);
|
||||
@ -261,10 +261,10 @@ BOOST_AUTO_TEST_CASE(test_publish) {
|
||||
BOOST_TEST(*pprops_[prop::topic_alias] == topic_alias);
|
||||
BOOST_TEST(*pprops_[prop::response_topic] == response_topic);
|
||||
BOOST_TEST(*pprops_[prop::correlation_data] == correlation_data);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].first == publish_prop_1);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].second == publish_prop_2);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::subscription_identifier].size() == 1);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::subscription_identifier].size() == 1u);
|
||||
BOOST_TEST(pprops_[prop::subscription_identifier][0] == subscription_identifier);
|
||||
BOOST_TEST(*pprops_[prop::content_type] == content_type);
|
||||
}
|
||||
@ -327,7 +327,7 @@ BOOST_AUTO_TEST_CASE(test_puback) {
|
||||
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(reason_code_ == reason_code);
|
||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(test_pubrec) {
|
||||
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(reason_code_ == reason_code);
|
||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -399,7 +399,7 @@ BOOST_AUTO_TEST_CASE(test_pubrel) {
|
||||
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(reason_code_ == reason_code);
|
||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -435,7 +435,7 @@ BOOST_AUTO_TEST_CASE(test_pubcomp) {
|
||||
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(reason_code_ == reason_code);
|
||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(pprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -489,7 +489,7 @@ BOOST_AUTO_TEST_CASE(test_subscribe) {
|
||||
|
||||
sprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(*sprops_[prop::subscription_identifier] == sub_id);
|
||||
BOOST_TEST_REQUIRE(sprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(sprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(sprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(sprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -525,7 +525,7 @@ BOOST_AUTO_TEST_CASE(test_suback) {
|
||||
|
||||
sprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(*sprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(sprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(sprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(sprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(sprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -558,7 +558,7 @@ BOOST_AUTO_TEST_CASE(test_unsubscribe) {
|
||||
BOOST_TEST(topics_ == topics);
|
||||
|
||||
uprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST_REQUIRE(uprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(uprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(uprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(uprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -594,7 +594,7 @@ BOOST_AUTO_TEST_CASE(test_unsuback) {
|
||||
|
||||
uprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(*uprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(uprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(uprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(uprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(uprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -631,7 +631,7 @@ BOOST_AUTO_TEST_CASE(test_disconnect) {
|
||||
dprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||
BOOST_TEST(*dprops_[prop::session_expiry_interval] == session_expiry_interval);
|
||||
BOOST_TEST(*dprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(dprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(dprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(dprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(dprops_[prop::user_property][0].second == user_property_2);
|
||||
BOOST_TEST(*dprops_[prop::server_reference] == server_reference);
|
||||
@ -671,7 +671,7 @@ BOOST_AUTO_TEST_CASE(test_auth) {
|
||||
BOOST_TEST(*aprops_[prop::authentication_method] == authentication_method);
|
||||
BOOST_TEST(*aprops_[prop::authentication_data] == authentication_data);
|
||||
BOOST_TEST(*aprops_[prop::reason_string] == reason_string);
|
||||
BOOST_TEST_REQUIRE(aprops_[prop::user_property].size() == 1);
|
||||
BOOST_TEST_REQUIRE(aprops_[prop::user_property].size() == 1u);
|
||||
BOOST_TEST(aprops_[prop::user_property][0].first == user_property_1);
|
||||
BOOST_TEST(aprops_[prop::user_property][0].second == user_property_2);
|
||||
}
|
||||
@ -730,7 +730,7 @@ BOOST_AUTO_TEST_CASE(empty_user_property) {
|
||||
const auto& [topic_, packet_id_, flags, pprops_, payload_] = *rv;
|
||||
|
||||
auto user_props_ = pprops_[prop::user_property];
|
||||
BOOST_TEST_REQUIRE(user_props_.size() == 1);
|
||||
BOOST_TEST_REQUIRE(user_props_.size() == 1u);
|
||||
BOOST_TEST(user_props_[0].first == "");
|
||||
BOOST_TEST(user_props_[0].second == "");
|
||||
}
|
||||
@ -753,7 +753,7 @@ BOOST_AUTO_TEST_CASE(deserialize_user_property) {
|
||||
|
||||
const auto& [reason_code_, pprops_] = *rv;
|
||||
auto user_props_ = pprops_[prop::user_property];
|
||||
BOOST_TEST_REQUIRE(user_props_.size() == 1);
|
||||
BOOST_TEST_REQUIRE(user_props_.size() == 1u);
|
||||
BOOST_TEST(user_props_[0].first == "key");
|
||||
BOOST_TEST(user_props_[0].second == "val");
|
||||
}
|
||||
@ -776,7 +776,7 @@ BOOST_AUTO_TEST_CASE(deserialize_empty_user_property) {
|
||||
|
||||
const auto& [reason_code_, pprops_] = *rv;
|
||||
auto user_props_ = pprops_[prop::user_property];
|
||||
BOOST_TEST_REQUIRE(user_props_.size() == 1);
|
||||
BOOST_TEST_REQUIRE(user_props_.size() == 1u);
|
||||
BOOST_TEST(user_props_[0].first == "");
|
||||
BOOST_TEST(user_props_[0].second == "");
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(pid_overrun) {
|
||||
auto handler = [&handlers_called](error_code ec, std::vector<reason_code> rcs, suback_props) {
|
||||
++handlers_called;
|
||||
BOOST_TEST(ec == client::error::pid_overrun);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||
BOOST_TEST(rcs[0] == reason_codes::empty);
|
||||
};
|
||||
|
||||
@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(large_subscription_id) {
|
||||
cprops[prop::subscription_identifier_available] = uint8_t(1);
|
||||
|
||||
subscribe_props sprops;
|
||||
sprops[prop::subscription_identifier] = std::numeric_limits<int32_t>::max();
|
||||
sprops[prop::subscription_identifier] = (std::numeric_limits<int32_t>::max)();
|
||||
|
||||
run_test(client::error::malformed_packet, "topic", sprops, cprops);
|
||||
}
|
||||
|
@ -12,9 +12,7 @@
|
||||
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/system_executor.hpp>
|
||||
#include <boost/beast/websocket/stream.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/type_traits/remove_cv_ref.hpp>
|
||||
|
||||
@ -22,6 +20,8 @@
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_common/extra_deps.hpp"
|
||||
|
||||
using namespace boost::mqtt5;
|
||||
|
||||
struct good_authenticator {
|
||||
@ -62,48 +62,15 @@ BOOST_STATIC_ASSERT(detail::is_authenticator<good_authenticator>);
|
||||
BOOST_STATIC_ASSERT(!detail::is_authenticator<bad_authenticator>);
|
||||
|
||||
namespace asio = boost::asio;
|
||||
namespace beast = boost::beast;
|
||||
|
||||
using tcp_layer = asio::ip::tcp::socket;
|
||||
using tls_layer = asio::ssl::stream<asio::ip::tcp::socket>;
|
||||
using websocket_tcp_layer = beast::websocket::stream<tcp_layer>;
|
||||
using websocket_tls_layer = beast::websocket::stream<tls_layer>;
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT(!detail::has_next_layer<tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<websocket_tls_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_layer<tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_tls_layer<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_layer<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_tls_layer<websocket_tls_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_handshake<tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_tls_handshake<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_handshake<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_handshake<websocket_tls_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(!detail::has_ws_handshake<tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_ws_handshake<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_ws_handshake<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_ws_handshake<websocket_tls_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(!detail::has_next_layer<tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<websocket_tls_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<tcp_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<tls_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<websocket_tcp_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<websocket_tls_layer>, tls_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<tcp_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<tls_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<websocket_tcp_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<websocket_tls_layer>, tcp_layer>);
|
||||
|
||||
void tcp_layers_test() {
|
||||
asio::system_executor ex;
|
||||
@ -116,6 +83,34 @@ void tcp_layers_test() {
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<boost::remove_cv_ref_t<decltype(llayer)>, tcp_layer>);
|
||||
}
|
||||
|
||||
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||
|
||||
namespace beast = boost::beast;
|
||||
using tls_layer = asio::ssl::stream<asio::ip::tcp::socket>;
|
||||
using websocket_tcp_layer = beast::websocket::stream<tcp_layer>;
|
||||
using websocket_tls_layer = beast::websocket::stream<tls_layer>;
|
||||
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_tls_layer<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_tls_handshake<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_ws_handshake<tls_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<tls_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<tls_layer>, tcp_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_layer<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_handshake<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_ws_handshake<websocket_tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<websocket_tcp_layer>, tcp_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<websocket_tcp_layer>, tcp_layer>);
|
||||
|
||||
BOOST_STATIC_ASSERT(detail::has_next_layer<websocket_tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_tls_layer<websocket_tls_layer>);
|
||||
BOOST_STATIC_ASSERT(!detail::has_tls_handshake<websocket_tls_layer>);
|
||||
BOOST_STATIC_ASSERT(detail::has_ws_handshake<websocket_tls_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::next_layer_type<websocket_tls_layer>, tls_layer>);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<detail::lowest_layer_type<websocket_tls_layer>, tcp_layer>);
|
||||
|
||||
void tls_layers_test() {
|
||||
asio::system_executor ex;
|
||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
||||
@ -150,3 +145,5 @@ void websocket_tls_layers_test() {
|
||||
detail::lowest_layer_type<websocket_tls_layer>& llayer = detail::lowest_layer(layer);
|
||||
BOOST_STATIC_ASSERT(std::is_same_v<boost::remove_cv_ref_t<decltype(llayer)>, tcp_layer>);
|
||||
}
|
||||
|
||||
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||
|
@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(pid_overrun) {
|
||||
auto handler = [&handlers_called](error_code ec, std::vector<reason_code> rcs, unsuback_props) {
|
||||
++handlers_called;
|
||||
BOOST_TEST(ec == client::error::pid_overrun);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
||||
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||
BOOST_TEST(rcs[0] == reason_codes::empty);
|
||||
};
|
||||
|
||||
|
398
tools/ci.py
Normal file
398
tools/ci.py
Normal file
@ -0,0 +1,398 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Contains commands that are invoked by the CI scripts.
|
||||
# Having this as a Python file makes it platform-independent.
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Union
|
||||
import subprocess
|
||||
import os
|
||||
import stat
|
||||
from shutil import rmtree, copytree, ignore_patterns
|
||||
import argparse
|
||||
|
||||
|
||||
# Variables
|
||||
_is_windows = os.name == 'nt'
|
||||
_home = Path(os.path.expanduser('~'))
|
||||
_boost_root = _home.joinpath('boost-root')
|
||||
_b2_distro = _home.joinpath('boost-b2-distro')
|
||||
_cmake_distro = _home.joinpath('boost-cmake-distro')
|
||||
_b2_command = str(_boost_root.joinpath('b2'))
|
||||
|
||||
|
||||
# Utilities
|
||||
def _run(args: List[str]) -> None:
|
||||
print('+ ', args, flush=True)
|
||||
subprocess.run(args, check=True)
|
||||
|
||||
|
||||
def _mkdir_and_cd(path: Path) -> None:
|
||||
os.makedirs(str(path), exist_ok=True)
|
||||
os.chdir(str(path))
|
||||
|
||||
|
||||
def _remove_readonly(func, path, _):
|
||||
os.chmod(path, stat.S_IWRITE)
|
||||
func(path)
|
||||
|
||||
|
||||
# Parses a string into a boolean (for command-line parsing)
|
||||
def _str2bool(v: Union[bool, str]) -> bool:
|
||||
if isinstance(v, bool):
|
||||
return v
|
||||
elif v == '1':
|
||||
return True
|
||||
elif v == '0':
|
||||
return False
|
||||
else:
|
||||
raise argparse.ArgumentTypeError('Boolean value expected.')
|
||||
|
||||
|
||||
# Transforms a b2-like toolset into a compiler command suitable
|
||||
# to be passed to CMAKE_CXX_COMPILER
|
||||
def _compiler_from_toolset(toolset: str) -> str:
|
||||
if toolset.startswith('gcc'):
|
||||
return toolset.replace('gcc', 'g++')
|
||||
elif toolset.startswith('clang'):
|
||||
return toolset.replace('clang', 'clang++')
|
||||
elif toolset.startswith('msvc'):
|
||||
return 'cl'
|
||||
else:
|
||||
return toolset
|
||||
|
||||
|
||||
# If we're on the master branch, we should use the Boost superproject master branch.
|
||||
# Otherwise, use the superproject develop branch.
|
||||
def _deduce_boost_branch() -> str:
|
||||
# Are we in GitHub Actions?
|
||||
if os.environ.get('GITHUB_ACTIONS') is not None:
|
||||
ci = 'GitHub Actions'
|
||||
ref = os.environ.get('GITHUB_BASE_REF', '') or os.environ.get('GITHUB_REF', '')
|
||||
res = 'master' if ref == 'master' or ref.endswith('/master') else 'develop'
|
||||
elif os.environ.get('DRONE') is not None:
|
||||
ref = os.environ.get('DRONE_BRANCH', '')
|
||||
ci = 'Drone'
|
||||
res = 'master' if ref == 'master' else 'develop'
|
||||
else:
|
||||
ci = 'Unknown'
|
||||
ref = ''
|
||||
res = 'develop'
|
||||
|
||||
print('+ Found CI {}, ref={}, deduced branch {}'.format(ci, ref, res))
|
||||
|
||||
return res
|
||||
|
||||
|
||||
# Gets Boost (develop or master, depending on the CI branch we're operating on),
|
||||
# with the required dependencies, and leaves it at _boost_root. Places our library,
|
||||
# located under source_dir, under $BOOST_ROOT/libs. Also runs the bootstrap script so b2 is usable.
|
||||
def _setup_boost(
|
||||
source_dir: Path
|
||||
) -> None:
|
||||
assert source_dir.is_absolute()
|
||||
assert not _boost_root.exists()
|
||||
lib_dir = _boost_root.joinpath('libs', 'mqtt5')
|
||||
branch = _deduce_boost_branch()
|
||||
|
||||
# Clone Boost
|
||||
_run(['git', 'clone', '-b', branch, '--depth', '1', 'https://github.com/boostorg/boost.git', str(_boost_root)])
|
||||
os.chdir(str(_boost_root))
|
||||
|
||||
# Put our library inside boost root
|
||||
if lib_dir.exists():
|
||||
rmtree(str(lib_dir), onerror=_remove_readonly)
|
||||
copytree(
|
||||
str(source_dir),
|
||||
str(lib_dir),
|
||||
ignore=ignore_patterns('__build*__', '.git')
|
||||
)
|
||||
|
||||
# Install Boost dependencies
|
||||
_run(["git", "config", "submodule.fetchJobs", "8"])
|
||||
_run(["git", "submodule", "update", "-q", "--init", "tools/boostdep"])
|
||||
_run(["python3", "tools/boostdep/depinst/depinst.py", "--include", "example", "mqtt5"])
|
||||
|
||||
# Bootstrap
|
||||
if _is_windows:
|
||||
_run(['cmd', '/q', '/c', 'bootstrap.bat'])
|
||||
else:
|
||||
_run(['bash', 'bootstrap.sh'])
|
||||
_run([_b2_command, 'headers', '-d0'])
|
||||
|
||||
|
||||
# Builds a Boost distribution using ./b2 install, and places it into _b2_distro.
|
||||
# This emulates a regular Boost distribution, like the ones in releases
|
||||
def _build_b2_distro(
|
||||
toolset: str
|
||||
):
|
||||
os.chdir(str(_boost_root))
|
||||
_run([
|
||||
_b2_command,
|
||||
'--prefix={}'.format(_b2_distro),
|
||||
'--with-system',
|
||||
'toolset={}'.format(toolset),
|
||||
'-d0',
|
||||
'install'
|
||||
])
|
||||
|
||||
|
||||
# Builds a Boost distribution using cmake, and places it into _cmake_distro.
|
||||
# It includes only our library and any dependency.
|
||||
def _build_cmake_distro(
|
||||
generator: str,
|
||||
build_type: str,
|
||||
cxxstd: str,
|
||||
toolset: str,
|
||||
):
|
||||
_mkdir_and_cd(_boost_root.joinpath('__build_cmake_test__'))
|
||||
_run([
|
||||
'cmake',
|
||||
'-G',
|
||||
generator,
|
||||
'-DBUILD_TESTING=ON',
|
||||
'-DCMAKE_CXX_COMPILER={}'.format(_compiler_from_toolset(toolset)),
|
||||
'-DCMAKE_BUILD_TYPE={}'.format(build_type),
|
||||
'-DCMAKE_CXX_STANDARD={}'.format(cxxstd),
|
||||
'-DBOOST_INCLUDE_LIBRARIES=mqtt5',
|
||||
'-DCMAKE_INSTALL_PREFIX={}'.format(_cmake_distro),
|
||||
'-DBoost_VERBOSE=ON',
|
||||
'-DCMAKE_INSTALL_MESSAGE=NEVER',
|
||||
'..'
|
||||
])
|
||||
_run(['cmake', '--build', '.', '--target', 'tests', '--config', build_type])
|
||||
_run(['ctest', '--output-on-failure', '--build-config', build_type])
|
||||
_run(['cmake', '--build', '.', '--target', 'install', '--config', build_type])
|
||||
|
||||
|
||||
# Builds our examples
|
||||
def _build_cmake_standalone_examples(
|
||||
generator: str,
|
||||
build_type: str,
|
||||
cxxstd: str,
|
||||
toolset: str
|
||||
):
|
||||
_mkdir_and_cd(_boost_root.joinpath('libs', 'mqtt5', '__build_standalone_examples__'))
|
||||
_run([
|
||||
'cmake',
|
||||
'-DBUILD_EXAMPLES=ON',
|
||||
'-DBoost_INCLUDE_DIR={}'.format(_boost_root),
|
||||
'-DCMAKE_CXX_COMPILER={}'.format(_compiler_from_toolset(toolset)),
|
||||
'-DCMAKE_PREFIX_PATH={}'.format(_b2_distro),
|
||||
'-DCMAKE_BUILD_TYPE={}'.format(build_type),
|
||||
'-DCMAKE_CXX_STANDARD={}'.format(cxxstd),
|
||||
'-G',
|
||||
generator,
|
||||
'..'
|
||||
])
|
||||
_run(['cmake', '--build', '.'])
|
||||
|
||||
|
||||
# Builds our CMake tests as a standalone project
|
||||
# (BOOST_MQTT5_MAIN_PROJECT is ON) and we find_package Boost.
|
||||
# This ensures that all our test suite is run.
|
||||
def _build_cmake_standalone_tests(
|
||||
generator: str,
|
||||
build_type: str,
|
||||
cxxstd: str,
|
||||
toolset: str
|
||||
):
|
||||
_mkdir_and_cd(_boost_root.joinpath('libs', 'mqtt5', '__build_standalone_tests__'))
|
||||
_run([
|
||||
'cmake',
|
||||
'-DBUILD_TESTING=ON',
|
||||
'-DBoost_INCLUDE_DIR={}'.format(_boost_root),
|
||||
'-DCMAKE_CXX_COMPILER={}'.format(_compiler_from_toolset(toolset)),
|
||||
'-DCMAKE_PREFIX_PATH={}'.format(_b2_distro),
|
||||
'-DCMAKE_BUILD_TYPE={}'.format(build_type),
|
||||
'-DCMAKE_CXX_STANDARD={}'.format(cxxstd),
|
||||
'-DBOOST_MQTT5_PUBLIC_BROKER_TESTS=ON',
|
||||
'-G',
|
||||
generator,
|
||||
'..'
|
||||
])
|
||||
_run(['cmake', '--build', '.'])
|
||||
|
||||
|
||||
# Runs the tests built in the previous step
|
||||
def _run_cmake_standalone_tests(
|
||||
build_type: str
|
||||
):
|
||||
os.chdir(str(_boost_root.joinpath('libs', 'mqtt5', '__build_standalone_tests__', 'test')))
|
||||
_run([
|
||||
'ctest',
|
||||
'--output-on-failure',
|
||||
'--build-config', build_type,
|
||||
'--no-tests=error'
|
||||
])
|
||||
|
||||
|
||||
# Tests that the library can be consumed using add_subdirectory()
|
||||
def _run_cmake_add_subdirectory_tests(
|
||||
generator: str,
|
||||
build_type: str,
|
||||
cxxstd: str,
|
||||
toolset: str
|
||||
):
|
||||
test_folder = _boost_root.joinpath('libs', 'mqtt5', 'test', 'cmake_subdir_test', '__build')
|
||||
_mkdir_and_cd(test_folder)
|
||||
_run([
|
||||
'cmake',
|
||||
'-G',
|
||||
generator,
|
||||
'-DCMAKE_CXX_COMPILER={}'.format(_compiler_from_toolset(toolset)),
|
||||
'-DBUILD_TESTING=ON',
|
||||
'-DCMAKE_BUILD_TYPE={}'.format(build_type),
|
||||
'-DCMAKE_CXX_STANDARD={}'.format(cxxstd),
|
||||
'..'
|
||||
])
|
||||
_run(['cmake', '--build', '.', '--config', build_type])
|
||||
_run(['ctest', '--output-on-failure', '--build-config', build_type, '--no-tests=error'])
|
||||
|
||||
|
||||
# Tests that the library can be consumed using find_package on a distro built by cmake
|
||||
def _run_cmake_find_package_tests(
|
||||
generator: str,
|
||||
build_type: str,
|
||||
cxxstd: str,
|
||||
toolset: str
|
||||
):
|
||||
_mkdir_and_cd(_boost_root.joinpath('libs', 'mqtt5', 'test', 'cmake_install_test', '__build'))
|
||||
_run([
|
||||
'cmake',
|
||||
'-G',
|
||||
generator,
|
||||
'-DCMAKE_CXX_COMPILER={}'.format(_compiler_from_toolset(toolset)),
|
||||
'-DBUILD_TESTING=ON',
|
||||
'-DCMAKE_BUILD_TYPE={}'.format(build_type),
|
||||
'-DCMAKE_CXX_STANDARD={}'.format(cxxstd),
|
||||
'-DCMAKE_PREFIX_PATH={}'.format(_cmake_distro),
|
||||
'..'
|
||||
])
|
||||
_run(['cmake', '--build', '.', '--config', build_type])
|
||||
_run(['ctest', '--output-on-failure', '--build-config', build_type, '--no-tests=error'])
|
||||
|
||||
|
||||
# Tests that the library can be consumed using find_package on a distro built by b2
|
||||
def _run_cmake_b2_find_package_tests(
|
||||
generator: str,
|
||||
build_type: str,
|
||||
cxxstd: str,
|
||||
toolset: str
|
||||
):
|
||||
_mkdir_and_cd(_boost_root.joinpath('libs', 'mqtt5', 'test', 'cmake_b2_test', '__build'))
|
||||
_run([
|
||||
'cmake',
|
||||
'-G',
|
||||
generator,
|
||||
'-DCMAKE_CXX_COMPILER={}'.format(_compiler_from_toolset(toolset)),
|
||||
'-DBUILD_TESTING=ON',
|
||||
'-DCMAKE_PREFIX_PATH={}'.format(_b2_distro),
|
||||
'-DCMAKE_BUILD_TYPE={}'.format(build_type),
|
||||
'-DCMAKE_CXX_STANDARD={}'.format(cxxstd),
|
||||
'..'
|
||||
])
|
||||
_run(['cmake', '--build', '.', '--config', build_type])
|
||||
_run(['ctest', '--output-on-failure', '--build-config', build_type, '--no-tests=error'])
|
||||
|
||||
|
||||
# Builds and runs the library tests using b2
|
||||
def _run_b2_tests(
|
||||
variant: str,
|
||||
cxxstd: str,
|
||||
toolset: str
|
||||
):
|
||||
os.chdir(str(_boost_root))
|
||||
_run([
|
||||
_b2_command,
|
||||
'--abbreviate-paths',
|
||||
'toolset={}'.format(toolset),
|
||||
'cxxstd={}'.format(cxxstd),
|
||||
'variant={}'.format(variant),
|
||||
'-j4',
|
||||
'libs/mqtt5/test'
|
||||
])
|
||||
|
||||
|
||||
def main():
|
||||
# Command line parsing
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
subp = subparsers.add_parser('setup-boost')
|
||||
subp.add_argument('--source-dir', type=Path, required=True)
|
||||
subp.set_defaults(func=_setup_boost)
|
||||
|
||||
subp = subparsers.add_parser('build-b2-distro')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_build_b2_distro)
|
||||
|
||||
subp = subparsers.add_parser('build-cmake-distro')
|
||||
subp.add_argument('--generator', default='Unix Makefiles')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.add_argument('--cxxstd', default='20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_build_cmake_distro)
|
||||
|
||||
subp = subparsers.add_parser('build-cmake-standalone-examples')
|
||||
subp.add_argument('--generator', default='Unix Makefiles')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.add_argument('--cxxstd', default='20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_build_cmake_standalone_examples)
|
||||
|
||||
subp = subparsers.add_parser('build-cmake-standalone-tests')
|
||||
subp.add_argument('--generator', default='Unix Makefiles')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.add_argument('--cxxstd', default='20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_build_cmake_standalone_tests)
|
||||
|
||||
subp = subparsers.add_parser('run-cmake-standalone-tests')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.set_defaults(func=_run_cmake_standalone_tests)
|
||||
|
||||
subp = subparsers.add_parser('run-cmake-add-subdirectory-tests')
|
||||
subp.add_argument('--generator', default='Unix Makefiles')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.add_argument('--cxxstd', default='20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_run_cmake_add_subdirectory_tests)
|
||||
|
||||
subp = subparsers.add_parser('run-cmake-find-package-tests')
|
||||
subp.add_argument('--generator', default='Unix Makefiles')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.add_argument('--cxxstd', default='20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_run_cmake_find_package_tests)
|
||||
|
||||
subp = subparsers.add_parser('run-cmake-b2-find-package-tests')
|
||||
subp.add_argument('--generator', default='Unix Makefiles')
|
||||
subp.add_argument('--build-type', default='Debug')
|
||||
subp.add_argument('--cxxstd', default='20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_run_cmake_b2_find_package_tests)
|
||||
|
||||
subp = subparsers.add_parser('run-b2-tests')
|
||||
subp.add_argument('--variant', default='debug,release')
|
||||
subp.add_argument('--cxxstd', default='17,20')
|
||||
subp.add_argument('--toolset', default='gcc')
|
||||
subp.set_defaults(func=_run_b2_tests)
|
||||
|
||||
# Actually parse the arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
# Invoke the relevant function (as defined by the func default), with
|
||||
# the command-line arguments the user passed us (we need to get rid
|
||||
# of the func property to match function signatures)
|
||||
# This approach is recommended by Python's argparse docs
|
||||
args.func(**{k: v for k, v in vars(args).items() if k != 'func'})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Reference in New Issue
Block a user