forked from boostorg/mqtt5
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]
|
on: [push, pull_request]
|
||||||
|
|
||||||
env:
|
|
||||||
BOOST_VERSION: 1.82.0
|
|
||||||
BOOST_DIR_VER_NAME: 1_82_0
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows:
|
# TODO: windows builds
|
||||||
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 }}"
|
|
||||||
|
|
||||||
|
posix-cmake:
|
||||||
|
name: "CMake ${{ matrix.toolset }} std=c++${{ matrix.cxxstd }} ${{ matrix.cxxflags }}"
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -132,8 +22,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- toolset: g++-9
|
- toolset: gcc-9
|
||||||
compiler: g++-9
|
|
||||||
install: g++-9
|
install: g++-9
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -142,8 +31,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: g++-10
|
- toolset: gcc-10
|
||||||
compiler: g++-10
|
|
||||||
install: g++-10
|
install: g++-10
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -152,8 +40,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: g++-12
|
- toolset: gcc-12
|
||||||
compiler: g++-12
|
|
||||||
install: g++-12
|
install: g++-12
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -162,8 +49,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: g++-13
|
- toolset: gcc-13
|
||||||
compiler: g++-13
|
|
||||||
install: g++-13
|
install: g++-13
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
container: ubuntu:24.04
|
container: ubuntu:24.04
|
||||||
@ -172,8 +58,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: g++-14 -fsanitize=address,undefined
|
- toolset: gcc-14
|
||||||
compiler: g++-14
|
|
||||||
install: g++-14
|
install: g++-14
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
container: ubuntu:24.04
|
container: ubuntu:24.04
|
||||||
@ -182,8 +67,7 @@ jobs:
|
|||||||
cxxflags: '-fsanitize=address,undefined -fno-sanitize-recover=all'
|
cxxflags: '-fsanitize=address,undefined -fno-sanitize-recover=all'
|
||||||
ldflags: '-fsanitize=address,undefined'
|
ldflags: '-fsanitize=address,undefined'
|
||||||
|
|
||||||
- toolset: clang++-12
|
- toolset: clang-12
|
||||||
compiler: clang++-12
|
|
||||||
install: clang++-12
|
install: clang++-12
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -192,8 +76,7 @@ jobs:
|
|||||||
cxxflags: '-fdeclspec'
|
cxxflags: '-fdeclspec'
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: clang++-13
|
- toolset: clang-13
|
||||||
compiler: clang++-13
|
|
||||||
install: clang++-13
|
install: clang++-13
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -202,8 +85,7 @@ jobs:
|
|||||||
cxxflags: '-fdeclspec'
|
cxxflags: '-fdeclspec'
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: clang++-14-libc++-14
|
- toolset: clang-14
|
||||||
compiler: clang++-14
|
|
||||||
install: 'clang++-14 libc++-14-dev libc++abi-14-dev'
|
install: 'clang++-14 libc++-14-dev libc++abi-14-dev'
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -212,8 +94,7 @@ jobs:
|
|||||||
cxxflags: '-stdlib=libc++'
|
cxxflags: '-stdlib=libc++'
|
||||||
ldflags: '-lc++'
|
ldflags: '-lc++'
|
||||||
|
|
||||||
- toolset: clang++-15
|
- toolset: clang-15
|
||||||
compiler: clang++-15
|
|
||||||
install: clang++-15
|
install: clang++-15
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
container: ubuntu:22.04
|
container: ubuntu:22.04
|
||||||
@ -222,8 +103,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: clang++-16
|
- toolset: clang-16
|
||||||
compiler: clang++-16
|
|
||||||
install: clang++-16
|
install: clang++-16
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
container: ubuntu:24.04
|
container: ubuntu:24.04
|
||||||
@ -232,8 +112,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: clang++-17
|
- toolset: clang-17
|
||||||
compiler: clang++-17
|
|
||||||
install: clang++-17
|
install: clang++-17
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
container: ubuntu:24.04
|
container: ubuntu:24.04
|
||||||
@ -242,8 +121,7 @@ jobs:
|
|||||||
cxxflags: ''
|
cxxflags: ''
|
||||||
ldflags: ''
|
ldflags: ''
|
||||||
|
|
||||||
- toolset: clang++-18 -fsanitize=address,undefined
|
- toolset: clang-18
|
||||||
compiler: clang++-18
|
|
||||||
install: clang++-18
|
install: clang++-18
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
container: ubuntu:24.04
|
container: ubuntu:24.04
|
||||||
@ -267,40 +145,131 @@ jobs:
|
|||||||
if: matrix.container
|
if: matrix.container
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
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 }}
|
run: sudo apt-get install -y ${{ matrix.install }}
|
||||||
|
|
||||||
- name: Setup Boost
|
- name: Setup Boost
|
||||||
run: |
|
run: |
|
||||||
wget https://archives.boost.io/release/${{ env.BOOST_VERSION }}/source/boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
python3 tools/ci.py setup-boost \
|
||||||
tar xzf boost_${{ env.BOOST_DIR_VER_NAME }}.tar.gz
|
--source-dir=$(pwd)
|
||||||
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
|
|
||||||
|
|
||||||
- name: Setup library
|
- name: Build a Boost distribution using B2
|
||||||
run: |
|
run : |
|
||||||
cmake -S . -B build -DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" \
|
python3 tools/ci.py build-b2-distro \
|
||||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
--toolset ${{ matrix.toolset }}
|
||||||
sudo cmake --install build
|
|
||||||
|
|
||||||
- name: Build examples
|
- name: Build a Boost distribution using CMake
|
||||||
run: |
|
run: |
|
||||||
cmake -S example -B example/build \
|
python3 tools/ci.py build-cmake-distro \
|
||||||
-DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" \
|
--build-type ${{ matrix.build-type }} \
|
||||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" \
|
--cxxstd ${{ matrix.cxxstd }} \
|
||||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
--toolset ${{ matrix.toolset }}
|
||||||
cmake --build example/build -j 4
|
|
||||||
|
- 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: |
|
run: |
|
||||||
cmake -S test -B test/build \
|
python3 tools/ci.py run-b2-tests \
|
||||||
-DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" \
|
--toolset ${{ matrix.toolset }} \
|
||||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" \
|
--cxxstd ${{ matrix.cxxstd }} \
|
||||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
--variant ${{ matrix.build-type }}
|
||||||
cmake --build test/build -j 4
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: ./test/build/mqtt-test
|
|
||||||
|
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/project-is-top-level.cmake)
|
||||||
include(cmake/variables.cmake)
|
|
||||||
|
|
||||||
add_library(async_mqtt5 INTERFACE)
|
# Determine if this is the superproject or called from add_subdirectory.
|
||||||
add_library(Async::MQTT5 ALIAS async_mqtt5)
|
if(NOT DEFINED BOOST_MQTT5_MAIN_PROJECT)
|
||||||
|
set(BOOST_MQTT5_MAIN_PROJECT OFF)
|
||||||
set_property(
|
if(PROJECT_IS_TOP_LEVEL)
|
||||||
TARGET async_mqtt5 PROPERTY
|
set(BOOST_MQTT5_MAIN_PROJECT ON)
|
||||||
EXPORT_NAME MQTT5
|
endif()
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(PROJECT_IS_TOP_LEVEL)
|
add_library(boost_mqtt5 INTERFACE)
|
||||||
option(BUILD_EXAMPLES "Build examples tree." "${async-mqtt5_DEVELOPER_MODE}")
|
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)
|
if(BUILD_EXAMPLES)
|
||||||
add_subdirectory(example)
|
add_subdirectory(example)
|
||||||
endif()
|
endif()
|
||||||
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)
|
project(async-mqtt5-examples LANGUAGES CXX)
|
||||||
|
|
||||||
if(PROJECT_IS_TOP_LEVEL)
|
|
||||||
find_package(async-mqtt5 REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
function(add_example name)
|
function(add_example name)
|
||||||
add_executable("${name}" ${ARGN})
|
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)
|
string(FIND "${example_name}" "tls" found_tls)
|
||||||
if(found_tls GREATER -1)
|
if(found_tls GREATER -1)
|
||||||
target_link_libraries("${name}" PRIVATE OpenSSL::SSL)
|
target_link_libraries("${name}" PRIVATE OpenSSL::SSL)
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/thread_pool.hpp>
|
#include <boost/asio/thread_pool.hpp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/asio/thread_pool.hpp>
|
#include <boost/asio/thread_pool.hpp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -20,9 +20,7 @@
|
|||||||
#include <boost/asio/require.hpp>
|
#include <boost/asio/require.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace boost::mqtt5::detail {
|
namespace boost::mqtt5::detail {
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <boost/mqtt5/types.hpp>
|
#include <boost/mqtt5/types.hpp>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/smart_ptr/allocate_unique.hpp>
|
#include <boost/smart_ptr/allocate_unique.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -109,13 +110,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
qos_e qos() const {
|
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;
|
auto byte = (uint8_t(*(_packet->data())) & 0b00000110) >> 1;
|
||||||
return qos_e(byte);
|
return qos_e(byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
control_packet& set_dup() {
|
control_packet& set_dup() {
|
||||||
assert(control_code() == control_code_e::publish);
|
BOOST_ASSERT(control_code() == control_code_e::publish);
|
||||||
auto& byte = *(_packet->data());
|
auto& byte = *(_packet->data());
|
||||||
byte |= 0b00001000;
|
byte |= 0b00001000;
|
||||||
return *this;
|
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
|
#ifndef BOOST_MQTT5_SHUTDOWN_HPP
|
||||||
#define BOOST_MQTT5_SHUTDOWN_HPP
|
#define BOOST_MQTT5_SHUTDOWN_HPP
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/asio/completion_condition.hpp>
|
#include <boost/asio/completion_condition.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/asio/prepend.hpp>
|
#include <boost/asio/prepend.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@ -148,7 +149,7 @@ public:
|
|||||||
return complete(ec, 0, {}, {});
|
return complete(ec, 0, {}, {});
|
||||||
|
|
||||||
_data_span.expand_suffix(bytes_read);
|
_data_span.expand_suffix(bytes_read);
|
||||||
assert(_data_span.size());
|
BOOST_ASSERT(_data_span.size());
|
||||||
|
|
||||||
auto control_byte = uint8_t(*_data_span.first());
|
auto control_byte = uint8_t(*_data_span.first());
|
||||||
|
|
||||||
@ -187,7 +188,7 @@ private:
|
|||||||
auto negotiated_ka = _svc.negotiated_keep_alive();
|
auto negotiated_ka = _svc.negotiated_keep_alive();
|
||||||
return negotiated_ka ?
|
return negotiated_ka ?
|
||||||
std::chrono::milliseconds(3 * negotiated_ka * 1000 / 2) :
|
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) {
|
static bool valid_header(uint8_t control_byte) {
|
||||||
|
@ -277,7 +277,7 @@ private:
|
|||||||
_replies(_executor),
|
_replies(_executor),
|
||||||
_async_sender(*this),
|
_async_sender(*this),
|
||||||
_active_span(_read_buff.cend(), _read_buff.cend()),
|
_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),
|
_ping_timer(_executor),
|
||||||
_sentry_timer(_executor)
|
_sentry_timer(_executor)
|
||||||
{
|
{
|
||||||
@ -297,7 +297,7 @@ public:
|
|||||||
_replies(ex),
|
_replies(ex),
|
||||||
_async_sender(*this),
|
_async_sender(*this),
|
||||||
_active_span(_read_buff.cend(), _read_buff.cend()),
|
_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),
|
_ping_timer(ex),
|
||||||
_sentry_timer(ex)
|
_sentry_timer(ex)
|
||||||
{}
|
{}
|
||||||
|
@ -96,7 +96,7 @@ private:
|
|||||||
auto negotiated_ka = _svc_ptr->negotiated_keep_alive();
|
auto negotiated_ka = _svc_ptr->negotiated_keep_alive();
|
||||||
return negotiated_ka ?
|
return negotiated_ka ?
|
||||||
std::chrono::seconds(negotiated_ka) :
|
std::chrono::seconds(negotiated_ka) :
|
||||||
duration(std::numeric_limits<duration::rep>::max());
|
duration((std::numeric_limits<duration::rep>::max)());
|
||||||
}
|
}
|
||||||
|
|
||||||
void complete() {
|
void complete() {
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/asio/error.hpp>
|
#include <boost/asio/error.hpp>
|
||||||
#include <boost/asio/prepend.hpp>
|
#include <boost/asio/prepend.hpp>
|
||||||
#include <boost/asio/recycling_allocator.hpp>
|
#include <boost/asio/recycling_allocator.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -146,7 +147,7 @@ private:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
perform();
|
perform();
|
||||||
|
@ -222,7 +222,7 @@ private:
|
|||||||
|
|
||||||
std::clog << property_name(prop) << ":";
|
std::clog << property_name(prop) << ":";
|
||||||
std::clog << "[";
|
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])>)
|
if constexpr (detail::is_pair<decltype(val[i])>)
|
||||||
std::clog << "(" << val[i].first << "," << val[i].second << ")";
|
std::clog << "(" << val[i].first << "," << val[i].second << ")";
|
||||||
else
|
else
|
||||||
|
@ -11,5 +11,10 @@
|
|||||||
"Concurrent",
|
"Concurrent",
|
||||||
"IO"
|
"IO"
|
||||||
],
|
],
|
||||||
|
"maintainers": [
|
||||||
|
"Ivica Siladić",
|
||||||
|
"Bruno Iljazović",
|
||||||
|
"Korina Šimičević"
|
||||||
|
],
|
||||||
"cxxstd": "17"
|
"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)
|
project(boost_mqtt5_tests CXX)
|
||||||
|
|
||||||
include(../cmake/project-is-top-level.cmake)
|
|
||||||
|
|
||||||
if(PROJECT_IS_TOP_LEVEL)
|
|
||||||
find_package(async-mqtt5 REQUIRED)
|
|
||||||
enable_testing()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(GLOB integration_tests "integration/*.cpp")
|
file(GLOB integration_tests "integration/*.cpp")
|
||||||
file(GLOB unit_tests "unit/*.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_include_directories(mqtt-test PRIVATE include)
|
||||||
target_compile_definitions(mqtt-test PRIVATE BOOST_TEST_NO_MAIN=1)
|
target_compile_definitions(mqtt-test PRIVATE BOOST_TEST_NO_MAIN=1)
|
||||||
|
|
||||||
find_package(OpenSSL REQUIRED)
|
if(BOOST_MQTT5_MAIN_PROJECT)
|
||||||
target_link_libraries(mqtt-test PRIVATE Async::MQTT5 OpenSSL::SSL)
|
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)
|
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;
|
pending_read& operator=(const pending_read&) = delete;
|
||||||
|
|
||||||
size_t consume(const std::vector<uint8_t>& data) {
|
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)
|
if (num_bytes == 0)
|
||||||
return 0;
|
return 0;
|
||||||
std::memcpy(_buffer_data, data.data(), num_bytes);
|
std::memcpy(_buffer_data, data.data(), num_bytes);
|
||||||
@ -169,11 +169,11 @@ public:
|
|||||||
);
|
);
|
||||||
BOOST_TEST(buffers_size == expected.size());
|
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);
|
auto it = asio::buffer_sequence_begin(buffers);
|
||||||
for (size_t i = 0; i < num_packets; ++i, ++it) {
|
for (size_t i = 0; i < num_packets; ++i, ++it) {
|
||||||
BOOST_TEST(it->size() == expected[i].size());
|
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))
|
if (memcmp(it->data(), expected[i].data(), len))
|
||||||
BOOST_TEST_MESSAGE(
|
BOOST_TEST_MESSAGE(
|
||||||
concat_strings(
|
concat_strings(
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <variant>
|
#include <variant> // std::monostate
|
||||||
|
|
||||||
namespace boost::mqtt5::test {
|
namespace boost::mqtt5::test {
|
||||||
|
|
||||||
|
@ -11,39 +11,21 @@
|
|||||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||||
|
|
||||||
#include <boost/mqtt5.hpp>
|
#include <boost/mqtt5.hpp>
|
||||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
|
||||||
|
|
||||||
#include <boost/asio/as_tuple.hpp>
|
#include <boost/asio/as_tuple.hpp>
|
||||||
#include <boost/asio/co_spawn.hpp>
|
#include <boost/asio/co_spawn.hpp>
|
||||||
#include <boost/asio/detached.hpp>
|
#include <boost/asio/detached.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/ssl.hpp>
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
#include <boost/asio/steady_timer.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
namespace boost::mqtt5 {
|
#include "test_common/extra_deps.hpp"
|
||||||
|
#include "test_common/preconditions.hpp"
|
||||||
|
|
||||||
template <typename StreamBase>
|
BOOST_AUTO_TEST_SUITE(client,
|
||||||
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
|
* boost::unit_test::precondition(boost::mqtt5::test::public_broker_cond))
|
||||||
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()*/)
|
|
||||||
|
|
||||||
using namespace boost::mqtt5;
|
using namespace boost::mqtt5;
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
@ -139,6 +121,8 @@ BOOST_AUTO_TEST_CASE(tcp_client_check) {
|
|||||||
ioc.run();
|
ioc.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
|
BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
|
||||||
asio::io_context ioc;
|
asio::io_context ioc;
|
||||||
|
|
||||||
@ -242,7 +226,8 @@ BOOST_AUTO_TEST_CASE(websocket_tls_client_check) {
|
|||||||
|
|
||||||
ioc.run();
|
ioc.run();
|
||||||
}
|
}
|
||||||
|
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
#endif
|
#endif // BOOST_ASIO_HAS_CO_AWAIT
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <boost/asio/detached.hpp>
|
#include <boost/asio/detached.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
#include <boost/asio/steady_timer.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/type_traits/remove_cv_ref.hpp>
|
#include <boost/type_traits/remove_cv_ref.hpp>
|
||||||
@ -23,6 +22,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "test_common/extra_deps.hpp"
|
||||||
#include "test_common/message_exchange.hpp"
|
#include "test_common/message_exchange.hpp"
|
||||||
#include "test_common/packet_util.hpp"
|
#include "test_common/packet_util.hpp"
|
||||||
#include "test_common/test_authenticators.hpp"
|
#include "test_common/test_authenticators.hpp"
|
||||||
@ -32,7 +32,7 @@
|
|||||||
using namespace boost::mqtt5;
|
using namespace boost::mqtt5;
|
||||||
using namespace std::chrono_literals;
|
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 {
|
struct shared_test_data {
|
||||||
error_code success {};
|
error_code success {};
|
||||||
@ -83,18 +83,6 @@ BOOST_AUTO_TEST_CASE(create_client_with_execution_context) {
|
|||||||
BOOST_CHECK(c.get_executor() == ioc.get_executor());
|
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) {
|
BOOST_FIXTURE_TEST_CASE(assign_credentials, shared_test_data) {
|
||||||
std::string client_id = "client_id";
|
std::string client_id = "client_id";
|
||||||
std::string username = "username";
|
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) {
|
BOOST_FIXTURE_TEST_CASE(assign_will, shared_test_data) {
|
||||||
will w("topic", "message");
|
will w("topic", "message");
|
||||||
std::optional<will> will_opt { std::move(w) };
|
std::optional<will> will_opt { std::move(w) };
|
||||||
@ -168,19 +139,6 @@ void assign_authenticator() {
|
|||||||
c.authenticator(test::test_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) {
|
BOOST_FIXTURE_TEST_CASE(assign_keep_alive, shared_test_data) {
|
||||||
uint16_t keep_alive = 120;
|
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 {
|
struct shared_connack_prop_test_data {
|
||||||
error_code success {};
|
error_code success {};
|
||||||
|
|
||||||
@ -382,7 +308,7 @@ void run_test_with_post_fun(
|
|||||||
timer.async_wait(
|
timer.async_wait(
|
||||||
[&c, fun = std::forward<TestingClientFun>(client_fun)](error_code) {
|
[&c, fun = std::forward<TestingClientFun>(client_fun)](error_code) {
|
||||||
fun(c);
|
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() {
|
void connack_property_with_tls_client() {
|
||||||
// Tests if the connack_properties & connack_property functions compile
|
// Tests if the connack_properties & connack_property functions compile
|
||||||
|
|
||||||
@ -457,5 +459,6 @@ void connack_property_with_tls_client() {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END();
|
BOOST_AUTO_TEST_SUITE_END();
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||||
|
|
||||||
#include <boost/mqtt5.hpp>
|
#include <boost/mqtt5.hpp>
|
||||||
#include <boost/mqtt5/websocket.hpp>
|
|
||||||
|
|
||||||
#include <boost/asio/as_tuple.hpp>
|
#include <boost/asio/as_tuple.hpp>
|
||||||
#include <boost/asio/co_spawn.hpp>
|
#include <boost/asio/co_spawn.hpp>
|
||||||
@ -20,14 +19,15 @@
|
|||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/steady_timer.hpp>
|
#include <boost/asio/steady_timer.hpp>
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#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;
|
using namespace boost::mqtt5;
|
||||||
namespace asio = boost::asio;
|
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);
|
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 connect_wait_dur = std::chrono::milliseconds(200);
|
||||||
constexpr auto topic = "async-mqtt5/test";
|
constexpr auto topic = "async-mqtt5/test";
|
||||||
constexpr auto share_topic = "$share/sharename/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;
|
auto ex = co_await asio::this_coro::executor;
|
||||||
|
|
||||||
mqtt_client<stream_type> client(ex);
|
mqtt_client<stream_type> client(ex);
|
||||||
client.brokers(broker, 8000)
|
client.brokers(broker, 1883)
|
||||||
.connect_property(prop::topic_alias_maximum, uint16_t(10))
|
.connect_property(prop::topic_alias_maximum, uint16_t(10))
|
||||||
.async_run(asio::detached);
|
.async_run(asio::detached);
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ asio::awaitable<void> test_subscription_identifiers() {
|
|||||||
auto ex = co_await asio::this_coro::executor;
|
auto ex = co_await asio::this_coro::executor;
|
||||||
|
|
||||||
mqtt_client<stream_type> client(ex);
|
mqtt_client<stream_type> client(ex);
|
||||||
client.brokers(broker, 8000)
|
client.brokers(broker, 1883)
|
||||||
.async_run(asio::detached);
|
.async_run(asio::detached);
|
||||||
|
|
||||||
publish_props pprops;
|
publish_props pprops;
|
||||||
@ -137,7 +137,7 @@ asio::awaitable<void> test_shared_subscription() {
|
|||||||
auto ex = co_await asio::this_coro::executor;
|
auto ex = co_await asio::this_coro::executor;
|
||||||
|
|
||||||
mqtt_client<stream_type> client(ex);
|
mqtt_client<stream_type> client(ex);
|
||||||
client.brokers(broker, 8000)
|
client.brokers(broker, 1883)
|
||||||
.async_run(asio::detached);
|
.async_run(asio::detached);
|
||||||
|
|
||||||
subscribe_options sub_opts = { .no_local = no_local_e::no };
|
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;
|
auto ex = co_await asio::this_coro::executor;
|
||||||
|
|
||||||
mqtt_client<stream_type> client(ex);
|
mqtt_client<stream_type> client(ex);
|
||||||
client.brokers(broker, 8000)
|
client.brokers(broker, 1883)
|
||||||
.async_run(asio::detached);
|
.async_run(asio::detached);
|
||||||
|
|
||||||
publish_props pprops;
|
publish_props pprops;
|
||||||
|
@ -59,7 +59,7 @@ std::string connack_with_keep_alive(uint16_t keep_alive) {
|
|||||||
void run_test(
|
void run_test(
|
||||||
test::msg_exchange broker_side,
|
test::msg_exchange broker_side,
|
||||||
std::chrono::milliseconds cancel_timeout,
|
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;
|
asio::io_context ioc;
|
||||||
auto executor = ioc.get_executor();
|
auto executor = ioc.get_executor();
|
||||||
|
@ -93,7 +93,7 @@ void run_test(test::msg_exchange broker_side) {
|
|||||||
++handlers_called;
|
++handlers_called;
|
||||||
|
|
||||||
BOOST_TEST(!ec);
|
BOOST_TEST(!ec);
|
||||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||||
BOOST_TEST(rcs[0] == reason_codes::granted_qos_0);
|
BOOST_TEST(rcs[0] == reason_codes::granted_qos_0);
|
||||||
|
|
||||||
c.cancel();
|
c.cancel();
|
||||||
@ -106,7 +106,7 @@ void run_test(test::msg_exchange broker_side) {
|
|||||||
++handlers_called;
|
++handlers_called;
|
||||||
|
|
||||||
BOOST_TEST(!ec);
|
BOOST_TEST(!ec);
|
||||||
BOOST_TEST_REQUIRE(rcs.size() == 1);
|
BOOST_TEST_REQUIRE(rcs.size() == 1u);
|
||||||
BOOST_TEST(rcs[0] == reason_codes::success);
|
BOOST_TEST(rcs[0] == reason_codes::success);
|
||||||
|
|
||||||
c.cancel();
|
c.cancel();
|
||||||
@ -423,7 +423,7 @@ void run_cancellation_test(test::msg_exchange broker_side) {
|
|||||||
++handlers_called;
|
++handlers_called;
|
||||||
|
|
||||||
BOOST_TEST(ec == asio::error::operation_aborted);
|
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);
|
BOOST_TEST(rcs[0] == reason_codes::empty);
|
||||||
|
|
||||||
c.cancel();
|
c.cancel();
|
||||||
@ -439,7 +439,7 @@ void run_cancellation_test(test::msg_exchange broker_side) {
|
|||||||
++handlers_called;
|
++handlers_called;
|
||||||
|
|
||||||
BOOST_TEST(ec == asio::error::operation_aborted);
|
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);
|
BOOST_TEST(rcs[0] == reason_codes::empty);
|
||||||
|
|
||||||
c.cancel();
|
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)
|
// (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>
|
#include <boost/asio/use_awaitable.hpp>
|
||||||
|
|
||||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||||
|
|
||||||
#include <boost/mqtt5.hpp>
|
#include <boost/mqtt5.hpp>
|
||||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
|
||||||
|
|
||||||
#include <boost/asio/awaitable.hpp>
|
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl.hpp>
|
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant> // std::monostate
|
#include <variant> // std::monostate
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace boost::mqtt5 {
|
#include "test_common/extra_deps.hpp"
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace boost::mqtt5::test {
|
||||||
|
|
||||||
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 {
|
|
||||||
|
|
||||||
// the following code needs to compile
|
// the following code needs to compile
|
||||||
|
|
||||||
@ -83,11 +63,13 @@ asio::awaitable<void> test_default_completion_tokens_impl(
|
|||||||
auto dc_props = disconnect_props {};
|
auto dc_props = disconnect_props {};
|
||||||
co_await c.async_disconnect();
|
co_await c.async_disconnect();
|
||||||
co_await c.async_disconnect(disconnect_rc_e::normal_disconnection, dc_props);
|
co_await c.async_disconnect(disconnect_rc_e::normal_disconnection, dc_props);
|
||||||
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::awaitable<void> test_default_completion_tokens() {
|
asio::awaitable<void> test_default_completion_tokens() {
|
||||||
co_await test_default_completion_tokens_impl<asio::ip::tcp::socket>();
|
co_await test_default_completion_tokens_impl<asio::ip::tcp::socket>();
|
||||||
|
|
||||||
|
#ifdef BOOST_MQTT5_EXTRA_DEPS
|
||||||
co_await test_default_completion_tokens_impl<
|
co_await test_default_completion_tokens_impl<
|
||||||
asio::ssl::stream<asio::ip::tcp::socket>,
|
asio::ssl::stream<asio::ip::tcp::socket>,
|
||||||
asio::ssl::context
|
asio::ssl::context
|
||||||
@ -105,10 +87,9 @@ asio::awaitable<void> test_default_completion_tokens() {
|
|||||||
asio::ssl::context(asio::ssl::context::tls_client),
|
asio::ssl::context(asio::ssl::context::tls_client),
|
||||||
logger(log_level::debug)
|
logger(log_level::debug)
|
||||||
);
|
);
|
||||||
|
#endif // BOOST_MQTT5_EXTRA_DEPS
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace test
|
} // end namespace boost::mqtt5::test
|
||||||
|
|
||||||
} // end namespace boost::mqtt5
|
|
||||||
|
|
||||||
#endif // BOOST_ASIO_HAS_CO_AWAIT
|
#endif // BOOST_ASIO_HAS_CO_AWAIT
|
||||||
|
@ -8,15 +8,12 @@
|
|||||||
#include <boost/mqtt5/logger.hpp>
|
#include <boost/mqtt5/logger.hpp>
|
||||||
#include <boost/mqtt5/logger_traits.hpp>
|
#include <boost/mqtt5/logger_traits.hpp>
|
||||||
#include <boost/mqtt5/mqtt_client.hpp>
|
#include <boost/mqtt5/mqtt_client.hpp>
|
||||||
#include <boost/mqtt5/websocket_ssl.hpp>
|
|
||||||
|
|
||||||
#include <boost/mqtt5/detail/log_invoke.hpp>
|
#include <boost/mqtt5/detail/log_invoke.hpp>
|
||||||
|
|
||||||
#include <boost/asio/detached.hpp>
|
#include <boost/asio/detached.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/ip/tcp.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/tools/output_test_stream.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@ -25,33 +22,15 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "test_common/extra_deps.hpp"
|
||||||
#include "test_common/message_exchange.hpp"
|
#include "test_common/message_exchange.hpp"
|
||||||
|
#include "test_common/preconditions.hpp"
|
||||||
#include "test_common/test_service.hpp"
|
#include "test_common/test_service.hpp"
|
||||||
#include "test_common/test_stream.hpp"
|
#include "test_common/test_stream.hpp"
|
||||||
|
|
||||||
using namespace boost::mqtt5;
|
using namespace boost::mqtt5;
|
||||||
namespace asio = boost::asio;
|
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() {
|
void logger_test() {
|
||||||
BOOST_STATIC_ASSERT(has_at_resolve<logger>);
|
BOOST_STATIC_ASSERT(has_at_resolve<logger>);
|
||||||
BOOST_STATIC_ASSERT(has_at_tcp_connect<logger>);
|
BOOST_STATIC_ASSERT(has_at_tcp_connect<logger>);
|
||||||
@ -61,13 +40,6 @@ void logger_test() {
|
|||||||
BOOST_STATIC_ASSERT(has_at_disconnect<logger>);
|
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)
|
BOOST_AUTO_TEST_SUITE(logger_tests)
|
||||||
|
|
||||||
class clog_redirect {
|
class clog_redirect {
|
||||||
@ -90,61 +62,6 @@ bool contains(const std::string& str, const std::string& substr) {
|
|||||||
return str.find(substr) != std::string::npos;
|
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) {
|
BOOST_AUTO_TEST_CASE(disconnect) {
|
||||||
using test::after;
|
using test::after;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
@ -194,4 +111,72 @@ BOOST_AUTO_TEST_CASE(disconnect) {
|
|||||||
BOOST_TEST(contains(log, "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();
|
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::topic_alias_maximum] == topic_alias_max);
|
||||||
BOOST_TEST(*cprops_[prop::request_response_information] == request_response_information);
|
BOOST_TEST(*cprops_[prop::request_response_information] == request_response_information);
|
||||||
BOOST_TEST(*cprops_[prop::request_problem_information] == request_problem_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].first == user_property_1);
|
||||||
BOOST_TEST(cprops_[prop::user_property][0].second == user_property_2);
|
BOOST_TEST(cprops_[prop::user_property][0].second == user_property_2);
|
||||||
BOOST_TEST(*cprops_[prop::authentication_method] == auth_method);
|
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::content_type] == will_content_type);
|
||||||
BOOST_TEST(*(will)[prop::response_topic] == will_response_topic);
|
BOOST_TEST(*(will)[prop::response_topic] == will_response_topic);
|
||||||
BOOST_TEST(*(will)[prop::correlation_data] == will_correlation_data);
|
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].first == will_user_property_1);
|
||||||
BOOST_TEST((will)[prop::user_property][0].second == will_user_property_2);
|
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::assigned_client_identifier] == assigned_client_id);
|
||||||
BOOST_TEST(*cprops_[prop::topic_alias_maximum] == topic_alias_max);
|
BOOST_TEST(*cprops_[prop::topic_alias_maximum] == topic_alias_max);
|
||||||
BOOST_TEST(*cprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(cprops_[prop::user_property][0].second == user_property_2);
|
BOOST_TEST(cprops_[prop::user_property][0].second == user_property_2);
|
||||||
BOOST_TEST(*cprops_[prop::wildcard_subscription_available] == wildcard_sub);
|
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::topic_alias] == topic_alias);
|
||||||
BOOST_TEST(*pprops_[prop::response_topic] == response_topic);
|
BOOST_TEST(*pprops_[prop::response_topic] == response_topic);
|
||||||
BOOST_TEST(*pprops_[prop::correlation_data] == correlation_data);
|
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].first == publish_prop_1);
|
||||||
BOOST_TEST(pprops_[prop::user_property][0].second == publish_prop_2);
|
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::subscription_identifier][0] == subscription_identifier);
|
||||||
BOOST_TEST(*pprops_[prop::content_type] == content_type);
|
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; });
|
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||||
BOOST_TEST(reason_code_ == reason_code);
|
BOOST_TEST(reason_code_ == reason_code);
|
||||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||||
BOOST_TEST(reason_code_ == reason_code);
|
BOOST_TEST(reason_code_ == reason_code);
|
||||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||||
BOOST_TEST(reason_code_ == reason_code);
|
BOOST_TEST(reason_code_ == reason_code);
|
||||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
pprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
||||||
BOOST_TEST(reason_code_ == reason_code);
|
BOOST_TEST(reason_code_ == reason_code);
|
||||||
BOOST_TEST(*pprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(pprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
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(*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].first == user_property_1);
|
||||||
BOOST_TEST(sprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
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(*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].first == user_property_1);
|
||||||
BOOST_TEST(sprops_[prop::user_property][0].second == user_property_2);
|
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);
|
BOOST_TEST(topics_ == topics);
|
||||||
|
|
||||||
uprops_.visit([](const auto& p, const auto&) { (void)p; BOOST_TEST_REQUIRE(p); return true; });
|
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].first == user_property_1);
|
||||||
BOOST_TEST(uprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
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(*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].first == user_property_1);
|
||||||
BOOST_TEST(uprops_[prop::user_property][0].second == user_property_2);
|
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; });
|
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::session_expiry_interval] == session_expiry_interval);
|
||||||
BOOST_TEST(*dprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(dprops_[prop::user_property][0].second == user_property_2);
|
BOOST_TEST(dprops_[prop::user_property][0].second == user_property_2);
|
||||||
BOOST_TEST(*dprops_[prop::server_reference] == server_reference);
|
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_method] == authentication_method);
|
||||||
BOOST_TEST(*aprops_[prop::authentication_data] == authentication_data);
|
BOOST_TEST(*aprops_[prop::authentication_data] == authentication_data);
|
||||||
BOOST_TEST(*aprops_[prop::reason_string] == reason_string);
|
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].first == user_property_1);
|
||||||
BOOST_TEST(aprops_[prop::user_property][0].second == user_property_2);
|
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;
|
const auto& [topic_, packet_id_, flags, pprops_, payload_] = *rv;
|
||||||
|
|
||||||
auto user_props_ = pprops_[prop::user_property];
|
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].first == "");
|
||||||
BOOST_TEST(user_props_[0].second == "");
|
BOOST_TEST(user_props_[0].second == "");
|
||||||
}
|
}
|
||||||
@ -753,7 +753,7 @@ BOOST_AUTO_TEST_CASE(deserialize_user_property) {
|
|||||||
|
|
||||||
const auto& [reason_code_, pprops_] = *rv;
|
const auto& [reason_code_, pprops_] = *rv;
|
||||||
auto user_props_ = pprops_[prop::user_property];
|
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].first == "key");
|
||||||
BOOST_TEST(user_props_[0].second == "val");
|
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;
|
const auto& [reason_code_, pprops_] = *rv;
|
||||||
auto user_props_ = pprops_[prop::user_property];
|
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].first == "");
|
||||||
BOOST_TEST(user_props_[0].second == "");
|
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) {
|
auto handler = [&handlers_called](error_code ec, std::vector<reason_code> rcs, suback_props) {
|
||||||
++handlers_called;
|
++handlers_called;
|
||||||
BOOST_TEST(ec == client::error::pid_overrun);
|
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);
|
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);
|
cprops[prop::subscription_identifier_available] = uint8_t(1);
|
||||||
|
|
||||||
subscribe_props sprops;
|
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);
|
run_test(client::error::malformed_packet, "topic", sprops, cprops);
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/ssl/stream.hpp>
|
|
||||||
#include <boost/asio/system_executor.hpp>
|
#include <boost/asio/system_executor.hpp>
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/type_traits/remove_cv_ref.hpp>
|
#include <boost/type_traits/remove_cv_ref.hpp>
|
||||||
|
|
||||||
@ -22,6 +20,8 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "test_common/extra_deps.hpp"
|
||||||
|
|
||||||
using namespace boost::mqtt5;
|
using namespace boost::mqtt5;
|
||||||
|
|
||||||
struct good_authenticator {
|
struct good_authenticator {
|
||||||
@ -62,48 +62,15 @@ BOOST_STATIC_ASSERT(detail::is_authenticator<good_authenticator>);
|
|||||||
BOOST_STATIC_ASSERT(!detail::is_authenticator<bad_authenticator>);
|
BOOST_STATIC_ASSERT(!detail::is_authenticator<bad_authenticator>);
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
namespace beast = boost::beast;
|
|
||||||
|
|
||||||
using tcp_layer = asio::ip::tcp::socket;
|
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<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<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<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<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<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<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() {
|
void tcp_layers_test() {
|
||||||
asio::system_executor ex;
|
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>);
|
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() {
|
void tls_layers_test() {
|
||||||
asio::system_executor ex;
|
asio::system_executor ex;
|
||||||
asio::ssl::context ctx(asio::ssl::context::tls_client);
|
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);
|
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>);
|
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) {
|
auto handler = [&handlers_called](error_code ec, std::vector<reason_code> rcs, unsuback_props) {
|
||||||
++handlers_called;
|
++handlers_called;
|
||||||
BOOST_TEST(ec == client::error::pid_overrun);
|
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);
|
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