Compare commits
4 commits
6064be2b71
...
9d95d08ab7
Author | SHA1 | Date | |
---|---|---|---|
9d95d08ab7 | |||
fc5e4f19a8 | |||
7f5c9cfd49 | |||
![]() |
46b17dd5f5 |
14 changed files with 65 additions and 477 deletions
|
@ -134,8 +134,6 @@ jobs:
|
||||||
-GNinja -DCMAKE_BUILD_TYPE=Release \
|
-GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||||
-DENABLE_EXAMPLES=ON \
|
-DENABLE_EXAMPLES=ON \
|
||||||
-DENABLE_TESTS=ON \
|
-DENABLE_TESTS=ON \
|
||||||
-DMAX_LOG_LEVEL=0 \
|
|
||||||
-DTEST_MAX_LOG_LEVEL=0 \
|
|
||||||
-DCMAKE_CXX_FLAGS="-ftemplate-backtrace-limit=0"
|
-DCMAKE_CXX_FLAGS="-ftemplate-backtrace-limit=0"
|
||||||
cmake --build ${{ github.workspace }}/build_gcc --parallel `nproc`
|
cmake --build ${{ github.workspace }}/build_gcc --parallel `nproc`
|
||||||
|
|
||||||
|
@ -144,7 +142,7 @@ jobs:
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
cd ${{ github.workspace }}/build_gcc
|
cd ${{ github.workspace }}/build_gcc
|
||||||
./larra_xmpp_tests --log_level=0
|
./larra_xmpp_tests
|
||||||
|
|
||||||
- name: Clang build (only configuring)
|
- name: Clang build (only configuring)
|
||||||
id: clang_build
|
id: clang_build
|
||||||
|
@ -162,8 +160,6 @@ jobs:
|
||||||
-GNinja -DCMAKE_BUILD_TYPE=Release \
|
-GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||||
-DENABLE_EXAMPLES=ON \
|
-DENABLE_EXAMPLES=ON \
|
||||||
-DENABLE_TESTS=ON \
|
-DENABLE_TESTS=ON \
|
||||||
-DMAX_LOG_LEVEL=0 \
|
|
||||||
-DTEST_MAX_LOG_LEVEL=0 \
|
|
||||||
-DCMAKE_CXX_FLAGS="-stdlib=libc++ -I/home/LLVM-${LLVM_VER}/include/c++/v1 -fno-modules"
|
-DCMAKE_CXX_FLAGS="-stdlib=libc++ -I/home/LLVM-${LLVM_VER}/include/c++/v1 -fno-modules"
|
||||||
|
|
||||||
echo "::group::compile_commands.json content"
|
echo "::group::compile_commands.json content"
|
||||||
|
@ -204,4 +200,4 @@ jobs:
|
||||||
# export LLVM_VER=19.1.5
|
# export LLVM_VER=19.1.5
|
||||||
# export PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}"
|
# export PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}"
|
||||||
# cd ${{ github.workspace }}/build_clang
|
# cd ${{ github.workspace }}/build_clang
|
||||||
# ASAN_SYMBOLIZER_PATH=llvm-symbolizer ASAN_OPTIONS=detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=1:atexit=1:abort_on_error=1 ./larra_xmpp_tests --log_level=0
|
# ASAN_SYMBOLIZER_PATH=llvm-symbolizer ASAN_OPTIONS=detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=1:atexit=1:abort_on_error=1 ./larra_xmpp_tests
|
||||||
|
|
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
|
@ -9,10 +9,7 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug: connect",
|
"name": "Debug: connect",
|
||||||
"program": "${workspaceFolder}/build/examples/output/connect",
|
"program": "${workspaceFolder}/build/examples/output/connect",
|
||||||
"args": [
|
"args": [],
|
||||||
"--log_level=0"
|
|
||||||
// --gtest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS]
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"preLaunchTask": "GCC: Build"
|
"preLaunchTask": "GCC: Build"
|
||||||
},
|
},
|
||||||
|
@ -22,7 +19,6 @@
|
||||||
"name": "Debug: tests",
|
"name": "Debug: tests",
|
||||||
"program": "${workspaceFolder}/build/larra_xmpp_tests",
|
"program": "${workspaceFolder}/build/larra_xmpp_tests",
|
||||||
"args": [
|
"args": [
|
||||||
"--log_level=0"
|
|
||||||
// --gtest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS]
|
// --gtest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS]
|
||||||
// "--gtest_filter=Roster*"
|
// "--gtest_filter=Roster*"
|
||||||
],
|
],
|
||||||
|
|
13
.vscode/tasks.json
vendored
13
.vscode/tasks.json
vendored
|
@ -79,8 +79,8 @@
|
||||||
"command": [
|
"command": [
|
||||||
"cd ${workspaceFolder} &&",
|
"cd ${workspaceFolder} &&",
|
||||||
"mkdir -p build && cd build &&",
|
"mkdir -p build && cd build &&",
|
||||||
"cmake -Wno-dev ",
|
"cmake cmake -Wno-dev ",
|
||||||
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON -DMAX_LOG_LEVEL=0 -DTEST_MAX_LOG_LEVEL=0 .."
|
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON .."
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"env": {
|
||||||
|
@ -138,7 +138,6 @@
|
||||||
"mkdir -p build_clang && cd build_clang &&",
|
"mkdir -p build_clang && cd build_clang &&",
|
||||||
"cmake -Wno-dev ",
|
"cmake -Wno-dev ",
|
||||||
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ",
|
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ",
|
||||||
" -DMAX_LOG_LEVEL=0 -DTEST_MAX_LOG_LEVEL=0",
|
|
||||||
" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++\"",
|
" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++\"",
|
||||||
" -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++\" .."
|
" -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++\" .."
|
||||||
],
|
],
|
||||||
|
@ -161,7 +160,6 @@
|
||||||
"mkdir -p build_clang && cd build_clang &&",
|
"mkdir -p build_clang && cd build_clang &&",
|
||||||
"cmake -Wno-dev ",
|
"cmake -Wno-dev ",
|
||||||
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON",
|
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON",
|
||||||
" -DMAX_LOG_LEVEL=0 -DTEST_MAX_LOG_LEVEL=0",
|
|
||||||
//
|
//
|
||||||
// Uncomment for GCC standart library: libstdc++
|
// Uncomment for GCC standart library: libstdc++
|
||||||
//" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"",
|
//" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"",
|
||||||
|
@ -193,7 +191,7 @@
|
||||||
"command": [
|
"command": [
|
||||||
"cd ${workspaceFolder} &&",
|
"cd ${workspaceFolder} &&",
|
||||||
"mkdir -p build_clang && cd build_clang &&",
|
"mkdir -p build_clang && cd build_clang &&",
|
||||||
"ASAN_SYMBOLIZER_PATH=llvm-symbolizer ASAN_OPTIONS=detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=1:atexit=1:abort_on_error=1 ./larra_xmpp_tests --log_level=0 ; echo \"exit code: $?\"",
|
"ASAN_SYMBOLIZER_PATH=llvm-symbolizer ASAN_OPTIONS=detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=1:atexit=1:abort_on_error=1 ./larra_xmpp_tests ; echo \"exit code: $?\"",
|
||||||
],
|
],
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"clear": true
|
"clear": true
|
||||||
|
@ -213,7 +211,6 @@
|
||||||
"mkdir -p build_clang && cd build_clang &&",
|
"mkdir -p build_clang && cd build_clang &&",
|
||||||
"cmake -Wno-dev ",
|
"cmake -Wno-dev ",
|
||||||
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ",
|
" -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ",
|
||||||
" -DMAX_LOG_LEVEL=0 -DTEST_MAX_LOG_LEVEL=0",
|
|
||||||
" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\"",
|
" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\"",
|
||||||
" -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\" ..",
|
" -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\" ..",
|
||||||
],
|
],
|
||||||
|
@ -239,7 +236,7 @@
|
||||||
"command": [
|
"command": [
|
||||||
"cd ${workspaceFolder} &&",
|
"cd ${workspaceFolder} &&",
|
||||||
"mkdir -p build_clang && cd build_clang &&",
|
"mkdir -p build_clang && cd build_clang &&",
|
||||||
"MSAN_SYMBOLIZER_PATH=llvm-symbolizer MSAN_OPTIONS=abort_on_error=1 ./larra_xmpp_tests --log_level=0 ; echo \"exit code: $?\"",
|
"MSAN_SYMBOLIZER_PATH=llvm-symbolizer MSAN_OPTIONS=abort_on_error=1 ./larra_xmpp_tests ; echo \"exit code: $?\"",
|
||||||
],
|
],
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"clear": true
|
"clear": true
|
||||||
|
@ -273,7 +270,7 @@
|
||||||
"command": [
|
"command": [
|
||||||
"cd ${workspaceFolder} &&",
|
"cd ${workspaceFolder} &&",
|
||||||
"mkdir -p build_clang && cd build_clang &&",
|
"mkdir -p build_clang && cd build_clang &&",
|
||||||
"MSAN_SYMBOLIZER_PATH=llvm-symbolizer MSAN_OPTIONS=abort_on_error=1 ./larra_xmpp_tests --log_level=0 ; echo \"exit code: $?\"",
|
"MSAN_SYMBOLIZER_PATH=llvm-symbolizer MSAN_OPTIONS=abort_on_error=1 ./larra_xmpp_tests ; echo \"exit code: $?\"",
|
||||||
],
|
],
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"clear": true
|
"clear": true
|
||||||
|
|
|
@ -18,12 +18,10 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(FMT_MODULE OFF)
|
set(FMT_MODULE OFF)
|
||||||
set(UTEMPL_MODULE OFF)
|
set(UTEMPL_MODULE OFF)
|
||||||
set(CXX_EXTENSIONS NO)
|
set(CXX_EXTENSIONS NO)
|
||||||
set(BOOST_INCLUDE_LIBRARIES "pfr;asio;serialization;program_options")
|
set(BOOST_INCLUDE_LIBRARIES "pfr;asio;serialization")
|
||||||
option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON)
|
option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON)
|
||||||
option(UTEMPL_USE_LOCAL_PACKAGE "Use utempl local package" OFF)
|
option(UTEMPL_USE_LOCAL_PACKAGE "Use utempl local package" OFF)
|
||||||
option(BUILD_EXECUTABLE ON)
|
option(BUILD_EXECUTABLE ON)
|
||||||
set(MAX_LOG_LEVEL 2 CACHE STRING "Available log levels: 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=CRITICAL, 6=OFF")
|
|
||||||
set(TEST_MAX_LOG_LEVEL 2 CACHE STRING "Available log levels: 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=CRITICAL, 6=OFF")
|
|
||||||
set(UTEMPL_URL
|
set(UTEMPL_URL
|
||||||
"https://sha512sum.xyz/git/sha512sum/utempl"
|
"https://sha512sum.xyz/git/sha512sum/utempl"
|
||||||
CACHE STRING "utempl repository URL")
|
CACHE STRING "utempl repository URL")
|
||||||
|
@ -177,11 +175,11 @@ target_include_directories(larra_xmpp PUBLIC
|
||||||
|
|
||||||
if(TARGET Boost::pfr)
|
if(TARGET Boost::pfr)
|
||||||
target_link_libraries(larra_xmpp PUBLIC
|
target_link_libraries(larra_xmpp PUBLIC
|
||||||
Boost::asio Boost::serialization Boost::program_options utempl::utempl
|
Boost::asio Boost::serialization utempl::utempl
|
||||||
OpenSSL::SSL nameof::nameof fmt::fmt
|
OpenSSL::SSL nameof::nameof fmt::fmt
|
||||||
OpenSSL::Crypto spdlog xmlplusplus ${LIBXML2_LIBRARIES})
|
OpenSSL::Crypto spdlog xmlplusplus ${LIBXML2_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
find_package(Boost 1.85.0 COMPONENTS serialization program_options REQUIRED)
|
find_package(Boost 1.85.0 COMPONENTS serialization REQUIRED)
|
||||||
target_link_libraries(larra_xmpp PUBLIC
|
target_link_libraries(larra_xmpp PUBLIC
|
||||||
utempl::utempl ${Boost_LIBRARIES} OpenSSL::SSL
|
utempl::utempl ${Boost_LIBRARIES} OpenSSL::SSL
|
||||||
nameof::nameof fmt::fmt
|
nameof::nameof fmt::fmt
|
||||||
|
@ -261,7 +259,6 @@ if(ENABLE_TESTS)
|
||||||
target_sources(larra_xmpp_tests PUBLIC ${SOURCES})
|
target_sources(larra_xmpp_tests PUBLIC ${SOURCES})
|
||||||
target_link_libraries(larra_xmpp_tests GTest::gtest_main
|
target_link_libraries(larra_xmpp_tests GTest::gtest_main
|
||||||
larra_xmpp)
|
larra_xmpp)
|
||||||
target_compile_definitions(larra_xmpp_tests PRIVATE SPDLOG_ACTIVE_LEVEL=${TEST_MAX_LOG_LEVEL})
|
|
||||||
set_property(TARGET larra_xmpp_tests PROPERTY CXX_STANDARD 23)
|
set_property(TARGET larra_xmpp_tests PROPERTY CXX_STANDARD 23)
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
gtest_discover_tests(larra_xmpp_tests)
|
gtest_discover_tests(larra_xmpp_tests)
|
||||||
|
@ -273,7 +270,6 @@ if(ENABLE_EXAMPLES)
|
||||||
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SRC} NAME_WE)
|
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SRC} NAME_WE)
|
||||||
add_executable(${EXAMPLE_NAME} ${EXAMPLE_SRC})
|
add_executable(${EXAMPLE_NAME} ${EXAMPLE_SRC})
|
||||||
target_link_libraries(${EXAMPLE_NAME} larra_xmpp)
|
target_link_libraries(${EXAMPLE_NAME} larra_xmpp)
|
||||||
target_compile_definitions(${EXAMPLE_NAME} PRIVATE SPDLOG_ACTIVE_LEVEL=${TEST_MAX_LOG_LEVEL})
|
|
||||||
set_property(TARGET ${EXAMPLE_NAME} PROPERTY CXX_STANDARD 23)
|
set_property(TARGET ${EXAMPLE_NAME} PROPERTY CXX_STANDARD 23)
|
||||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES
|
set_target_properties(${EXAMPLE_NAME} PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/examples/output")
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/examples/output")
|
||||||
|
|
|
@ -3,28 +3,11 @@
|
||||||
|
|
||||||
#include <boost/asio/co_spawn.hpp>
|
#include <boost/asio/co_spawn.hpp>
|
||||||
#include <boost/asio/detached.hpp>
|
#include <boost/asio/detached.hpp>
|
||||||
#include <boost/program_options.hpp>
|
|
||||||
#include <larra/client/client.hpp>
|
#include <larra/client/client.hpp>
|
||||||
#include <larra/presence.hpp>
|
#include <larra/presence.hpp>
|
||||||
#include <larra/printer_stream.hpp>
|
#include <larra/printer_stream.hpp>
|
||||||
#include <print>
|
#include <print>
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
constexpr auto ToString(spdlog::level::level_enum e) {
|
|
||||||
switch (e) {
|
|
||||||
case spdlog::level::trace: return "TRACE";
|
|
||||||
case spdlog::level::debug: return "DEBUG";
|
|
||||||
case spdlog::level::info: return "INFO";
|
|
||||||
case spdlog::level::warn: return "WARNING";
|
|
||||||
case spdlog::level::err: return "ERROR";
|
|
||||||
case spdlog::level::critical: return "CRITICAL";
|
|
||||||
case spdlog::level::off: return "OFF";
|
|
||||||
default:
|
|
||||||
return "INVALID";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
namespace iq = larra::xmpp::iq;
|
namespace iq = larra::xmpp::iq;
|
||||||
|
|
||||||
auto Coroutine() -> boost::asio::awaitable<void> {
|
auto Coroutine() -> boost::asio::awaitable<void> {
|
||||||
|
@ -57,39 +40,8 @@ auto Coroutine() -> boost::asio::awaitable<void> {
|
||||||
SPDLOG_INFO("Done connecting client!");
|
SPDLOG_INFO("Done connecting client!");
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
auto main() -> int {
|
||||||
|
spdlog::set_level(spdlog::level::trace);
|
||||||
auto main(int argc, char** argv) -> int {
|
|
||||||
// Define options
|
|
||||||
po::options_description desc("Allowed options");
|
|
||||||
desc.add_options()("help,h", "Print help message")("log_level,l",
|
|
||||||
po::value<int>()->default_value(SPDLOG_LEVEL_INFO),
|
|
||||||
"Set log level: 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=CRITICAL, 6=OFF");
|
|
||||||
|
|
||||||
// Parse command-line arguments
|
|
||||||
po::variables_map vm;
|
|
||||||
try {
|
|
||||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
|
||||||
po::notify(vm);
|
|
||||||
|
|
||||||
if(vm["log_level"].as<int>() < spdlog::level::level_enum::trace || vm["log_level"].as<int>() > spdlog::level::level_enum::off) {
|
|
||||||
throw std::invalid_argument{
|
|
||||||
std::format("Invalid argument value for '--log_level' option. Check option description for more details")};
|
|
||||||
}
|
|
||||||
if(vm["log_level"].as<int>() < SPDLOG_ACTIVE_LEVEL) {
|
|
||||||
SPDLOG_WARN("Specified log_level '{}' is lower than max available one '{}'. Log level will be changed according to the maximum one",
|
|
||||||
vm["log_level"].as<int>(),
|
|
||||||
SPDLOG_ACTIVE_LEVEL);
|
|
||||||
}
|
|
||||||
} catch(const std::exception& e) {
|
|
||||||
SPDLOG_CRITICAL("Cmd parse error: {}", e.what());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cmd options handling
|
|
||||||
spdlog::set_level(static_cast<spdlog::level::level_enum>(vm["log_level"].as<int>()));
|
|
||||||
std::println("\nEnvironment setup:\n\tCurrently set log level: {}\n", ToString(spdlog::get_level()));
|
|
||||||
|
|
||||||
boost::asio::io_context io_context;
|
boost::asio::io_context io_context;
|
||||||
boost::asio::co_spawn(io_context, Coroutine(), boost::asio::detached);
|
boost::asio::co_spawn(io_context, Coroutine(), boost::asio::detached);
|
||||||
io_context.run();
|
io_context.run();
|
||||||
|
|
|
@ -84,12 +84,14 @@ struct Client {
|
||||||
|
|
||||||
auto set_bind_response = co_await connection.template Read<Iq<::iq::Bind>>();
|
auto set_bind_response = co_await connection.template Read<Iq<::iq::Bind>>();
|
||||||
std::visit(utempl::Overloaded(
|
std::visit(utempl::Overloaded(
|
||||||
|
[](auto error) {
|
||||||
|
throw "Error response on IQ: Set::Bind: ''"; // TODO(unknown): Add exact error parsing
|
||||||
|
},
|
||||||
[&](::iq::ResultBind r) {
|
[&](::iq::ResultBind r) {
|
||||||
jid.resource = std::move(r.payload.jid->resource);
|
jid.resource = std::move(r.payload.jid->resource);
|
||||||
SPDLOG_INFO("Allocated resource: {}", jid.resource);
|
SPDLOG_INFO("Allocated resource: {}", jid.resource);
|
||||||
},
|
}),
|
||||||
IqErrThrowVisitor{"Error response on IQ: Set::Bind"}),
|
set_bind_response);
|
||||||
std::move(set_bind_response));
|
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,12 +101,14 @@ struct Client {
|
||||||
|
|
||||||
const auto get_roster_response = co_await connection.template Read<Iq<::iq::Roster>>();
|
const auto get_roster_response = co_await connection.template Read<Iq<::iq::Roster>>();
|
||||||
std::visit(utempl::Overloaded(
|
std::visit(utempl::Overloaded(
|
||||||
|
[](auto error) {
|
||||||
|
throw "Error response on IQ: Get::Roster: ''"; // TODO(unknown): Add exact error parsing
|
||||||
|
},
|
||||||
[&](::iq::ResultRoster r) {
|
[&](::iq::ResultRoster r) {
|
||||||
roster = std::move(r.payload);
|
roster = std::move(r.payload);
|
||||||
SPDLOG_INFO("New roster: {}", ToString(roster));
|
SPDLOG_INFO("New roster: {}", ToString(roster));
|
||||||
},
|
}),
|
||||||
IqErrThrowVisitor{"Error response on IQ: Get::Roster"}),
|
get_roster_response);
|
||||||
std::move(get_roster_response));
|
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
[[nodiscard]] auto Roster() const -> const std::vector<iq::RosterItem>& {
|
[[nodiscard]] auto Roster() const -> const std::vector<iq::RosterItem>& {
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
#include <larra/jid.hpp>
|
#include <larra/jid.hpp>
|
||||||
#include <larra/serialization.hpp>
|
#include <larra/serialization.hpp>
|
||||||
#include <larra/stanza_error.hpp>
|
#include <larra/stream_error.hpp>
|
||||||
#include <larra/utils.hpp>
|
#include <larra/utils.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace larra::xmpp {
|
namespace larra::xmpp {
|
||||||
|
@ -118,41 +115,7 @@ using Error = BaseImplWithPayload<kErrorName, Payload>;
|
||||||
|
|
||||||
} // namespace iq
|
} // namespace iq
|
||||||
|
|
||||||
using IqError = iq::Error<stanza::error::StanzaError>;
|
|
||||||
|
|
||||||
template <typename Payload>
|
template <typename Payload>
|
||||||
using Iq = std::variant<iq::Get<Payload>, iq::Set<Payload>, iq::Result<Payload>, IqError>;
|
using Iq = std::variant<iq::Get<Payload>, iq::Set<Payload>, iq::Result<Payload>, iq::Error<Payload>>;
|
||||||
|
|
||||||
struct IqErrThrowVisitor {
|
|
||||||
constexpr IqErrThrowVisitor(std::string_view baseErrorMsg) : baseErrorMsg(baseErrorMsg) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Payload>
|
|
||||||
void operator()(const iq::Get<Payload>&) {
|
|
||||||
static constexpr std::string_view getErrorMsg = ": 'Get' is an invalid type for IQ result. Expected 'Result' or 'Error'";
|
|
||||||
|
|
||||||
auto finalErrorMsg = std::string(baseErrorMsg).append(getErrorMsg);
|
|
||||||
SPDLOG_ERROR(finalErrorMsg);
|
|
||||||
throw std::runtime_error{finalErrorMsg};
|
|
||||||
}
|
|
||||||
template <typename Payload>
|
|
||||||
void operator()(const iq::Set<Payload>&) {
|
|
||||||
static constexpr std::string_view getErrorMsg = ": 'Set' is an invalid type for IQ result. Expected 'Result' or 'Error'";
|
|
||||||
|
|
||||||
auto finalErrorMsg = std::string(baseErrorMsg).append(getErrorMsg);
|
|
||||||
SPDLOG_ERROR(finalErrorMsg);
|
|
||||||
throw std::runtime_error{finalErrorMsg};
|
|
||||||
}
|
|
||||||
void operator()(IqError err) {
|
|
||||||
SPDLOG_ERROR(baseErrorMsg);
|
|
||||||
std::visit(
|
|
||||||
[](auto exception) {
|
|
||||||
throw exception;
|
|
||||||
},
|
|
||||||
std::move(err.payload));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view baseErrorMsg;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace larra::xmpp
|
} // namespace larra::xmpp
|
||||||
|
|
|
@ -1,148 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <libxml++/libxml++.h>
|
|
||||||
|
|
||||||
#include <larra/utils.hpp>
|
|
||||||
#include <optional>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
namespace larra::xmpp::stanza::error {
|
|
||||||
|
|
||||||
struct StanzaBaseError : std::exception {};
|
|
||||||
|
|
||||||
// DO NOT MOVE TO ANOTHER NAMESPACE(where no heirs). VIA friend A FUNCTION IS ADDED THAT VIA ADL WILL BE SEARCHED FOR HEIRS
|
|
||||||
// C++20 modules very unstable in clangd :(
|
|
||||||
template <typename T>
|
|
||||||
struct StanzaErrorImpl : StanzaBaseError {
|
|
||||||
static constexpr auto kDefaultName = "error";
|
|
||||||
static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-stanzas";
|
|
||||||
static inline const auto kKebabCaseName = static_cast<std::string>(utils::ToKebabCaseName<T>());
|
|
||||||
|
|
||||||
static constexpr auto kErrorMessage = [] -> std::string_view {
|
|
||||||
static constexpr auto name = nameof::nameof_short_type<T>();
|
|
||||||
static constexpr auto str = [] {
|
|
||||||
return std::array{std::string_view{"Stanza IQ Error: "}, std::string_view{name}, std::string_view{"\0", 1}} | std::views::join;
|
|
||||||
};
|
|
||||||
static constexpr auto array = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
|
|
||||||
return {array.data(), array.size() - 1};
|
|
||||||
}();
|
|
||||||
|
|
||||||
std::optional<std::string> by{};
|
|
||||||
std::string type;
|
|
||||||
|
|
||||||
// TODO(unknown): Add "optional text children" support for stanza error. Check "XML Stanzas" -> "Syntax" for more details
|
|
||||||
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<T> {
|
|
||||||
if(not element) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto by = element->get_attribute("by");
|
|
||||||
auto type = element->get_attribute("type");
|
|
||||||
if(not type) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto node = element->get_first_child(kKebabCaseName);
|
|
||||||
if(not node) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
T obj;
|
|
||||||
obj.type = type->get_value();
|
|
||||||
if(by) {
|
|
||||||
obj.by = std::optional{by->get_value()};
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
static constexpr auto Parse(xmlpp::Element* element) -> T {
|
|
||||||
return TryParse(element).value();
|
|
||||||
}
|
|
||||||
friend constexpr auto operator<<(xmlpp::Element* element, const T& obj) -> void {
|
|
||||||
element->set_attribute("type", obj.type);
|
|
||||||
if(obj.by) {
|
|
||||||
element->set_attribute("by", *obj.by);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto node = element->add_child_element(kKebabCaseName);
|
|
||||||
node->set_namespace_declaration(kDefaultNamespace);
|
|
||||||
}
|
|
||||||
constexpr auto operator==(const StanzaErrorImpl<T>&) const -> bool {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
|
||||||
return kErrorMessage.data();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper class to prevent parsing response stream into an expected return type if its name is an 'error'
|
|
||||||
struct UnknownStanzaError : StanzaBaseError {
|
|
||||||
static constexpr auto kDefaultName = "stream:error";
|
|
||||||
static constexpr std::string_view kErrorMessage = "Unknown XMPP stream error";
|
|
||||||
|
|
||||||
static constexpr auto TryParse(xmlpp::Element* element) {
|
|
||||||
return std::optional{UnknownStanzaError{}};
|
|
||||||
}
|
|
||||||
static constexpr auto Parse(xmlpp::Element* element) {
|
|
||||||
return TryParse(element).value();
|
|
||||||
}
|
|
||||||
friend constexpr auto operator<<(xmlpp::Element* element, const UnknownStanzaError& obj) -> void {
|
|
||||||
throw std::runtime_error{std::format("'{}' must never be written into the real stream!", kErrorMessage)};
|
|
||||||
}
|
|
||||||
constexpr auto operator==(const UnknownStanzaError&) const -> bool {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
|
||||||
return kErrorMessage.data();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BadRequest : StanzaErrorImpl<BadRequest> {};
|
|
||||||
struct Conflict : StanzaErrorImpl<Conflict> {};
|
|
||||||
struct FeatureNotImplemented : StanzaErrorImpl<FeatureNotImplemented> {};
|
|
||||||
struct Forbidden : StanzaErrorImpl<Forbidden> {};
|
|
||||||
struct Gone : StanzaErrorImpl<Gone> {};
|
|
||||||
struct InternalServerError : StanzaErrorImpl<InternalServerError> {};
|
|
||||||
struct ItemNotFound : StanzaErrorImpl<ItemNotFound> {};
|
|
||||||
struct JidMalformed : StanzaErrorImpl<JidMalformed> {};
|
|
||||||
struct NotAcceptable : StanzaErrorImpl<NotAcceptable> {};
|
|
||||||
struct NotAllowed : StanzaErrorImpl<NotAllowed> {};
|
|
||||||
struct NotAuthorized : StanzaErrorImpl<NotAuthorized> {};
|
|
||||||
struct PolicyViolation : StanzaErrorImpl<PolicyViolation> {};
|
|
||||||
struct RecipientUnavailable : StanzaErrorImpl<RecipientUnavailable> {};
|
|
||||||
struct Redirect : StanzaErrorImpl<Redirect> {};
|
|
||||||
struct RegistrationRequired : StanzaErrorImpl<RegistrationRequired> {};
|
|
||||||
struct RemoteServerNotFound : StanzaErrorImpl<RemoteServerNotFound> {};
|
|
||||||
struct RemoteServerTimeout : StanzaErrorImpl<RemoteServerTimeout> {};
|
|
||||||
struct ResourceConstraint : StanzaErrorImpl<ResourceConstraint> {};
|
|
||||||
struct ServiceUnavailable : StanzaErrorImpl<ServiceUnavailable> {};
|
|
||||||
struct SubscriptionRequired : StanzaErrorImpl<SubscriptionRequired> {};
|
|
||||||
struct UndefinedCondition : StanzaErrorImpl<UndefinedCondition> {};
|
|
||||||
struct UnexpectedRequest : StanzaErrorImpl<UnexpectedRequest> {};
|
|
||||||
|
|
||||||
using StanzaError = std::variant<BadRequest,
|
|
||||||
Conflict,
|
|
||||||
FeatureNotImplemented,
|
|
||||||
Forbidden,
|
|
||||||
Gone,
|
|
||||||
InternalServerError,
|
|
||||||
ItemNotFound,
|
|
||||||
JidMalformed,
|
|
||||||
NotAcceptable,
|
|
||||||
NotAllowed,
|
|
||||||
NotAuthorized,
|
|
||||||
PolicyViolation,
|
|
||||||
RecipientUnavailable,
|
|
||||||
Redirect,
|
|
||||||
RegistrationRequired,
|
|
||||||
RemoteServerNotFound,
|
|
||||||
RemoteServerTimeout,
|
|
||||||
ResourceConstraint,
|
|
||||||
ServiceUnavailable,
|
|
||||||
SubscriptionRequired,
|
|
||||||
UndefinedCondition,
|
|
||||||
UnexpectedRequest,
|
|
||||||
UnknownStanzaError>;
|
|
||||||
|
|
||||||
static_assert(std::is_same_v<typename std::variant_alternative_t<std::variant_size_v<StanzaError> - 1, StanzaError>, UnknownStanzaError>,
|
|
||||||
"'UnknownStanzaError' must be at the end of 'StanzaError' variant");
|
|
||||||
|
|
||||||
} // namespace larra::xmpp::stanza::error
|
|
|
@ -2,10 +2,43 @@
|
||||||
#include <libxml++/libxml++.h>
|
#include <libxml++/libxml++.h>
|
||||||
|
|
||||||
#include <larra/utils.hpp>
|
#include <larra/utils.hpp>
|
||||||
|
#include <nameof.hpp>
|
||||||
|
#include <ranges>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace larra::xmpp {
|
namespace larra::xmpp {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
// std::isupper not declared as constexpr
|
||||||
|
constexpr auto IsUpper(char ch) -> bool {
|
||||||
|
return ch >= 'A' && ch <= 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto ToLower(char ch) -> char {
|
||||||
|
return (ch >= 'A' && ch <= 'Z') ? static_cast<char>(ch + ('a' - 'A')) : ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto ToKebabCaseName() -> std::string_view {
|
||||||
|
static constexpr auto rawStr = nameof::nameof_short_type<T>();
|
||||||
|
|
||||||
|
constexpr auto str = [] {
|
||||||
|
return rawStr //
|
||||||
|
| std::views::transform([](auto ch) {
|
||||||
|
return impl::IsUpper(ch) ? std::array<char, 2>{'-', impl::ToLower(ch)} : std::array<char, 2>{ch, '\0'};
|
||||||
|
}) //
|
||||||
|
| std::views::join //
|
||||||
|
| std::views::filter([](char ch) {
|
||||||
|
return ch != '\0';
|
||||||
|
}) //
|
||||||
|
| std::views::drop(1);
|
||||||
|
};
|
||||||
|
static constexpr auto arr = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
|
||||||
|
return {arr.data(), arr.size()};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
namespace error::stream {
|
namespace error::stream {
|
||||||
|
|
||||||
struct BaseError : std::exception {};
|
struct BaseError : std::exception {};
|
||||||
|
@ -15,7 +48,7 @@ struct BaseError : std::exception {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct ErrorImpl : BaseError {
|
struct ErrorImpl : BaseError {
|
||||||
static constexpr auto kDefaultName = "stream:error";
|
static constexpr auto kDefaultName = "stream:error";
|
||||||
static inline const auto kKebabCaseName = static_cast<std::string>(utils::ToKebabCaseName<T>());
|
static inline const auto kKebabCaseName = static_cast<std::string>(impl::ToKebabCaseName<T>());
|
||||||
|
|
||||||
static constexpr auto kErrorMessage = [] -> std::string_view {
|
static constexpr auto kErrorMessage = [] -> std::string_view {
|
||||||
static constexpr auto name = nameof::nameof_short_type<T>();
|
static constexpr auto name = nameof::nameof_short_type<T>();
|
||||||
|
@ -52,7 +85,7 @@ struct UnknownXmppError : BaseError {
|
||||||
return TryParse(element).value();
|
return TryParse(element).value();
|
||||||
}
|
}
|
||||||
friend constexpr auto operator<<(xmlpp::Element* element, const UnknownXmppError& obj) -> void {
|
friend constexpr auto operator<<(xmlpp::Element* element, const UnknownXmppError& obj) -> void {
|
||||||
throw std::runtime_error{std::format("'{}' must never be written into the real stream!", kErrorMessage)};
|
throw std::format("'{}' must never be written into the real stream!", kErrorMessage);
|
||||||
}
|
}
|
||||||
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
||||||
return kErrorMessage.data();
|
return kErrorMessage.data();
|
||||||
|
@ -112,8 +145,7 @@ using StreamError = std::variant<error::stream::BadFormat,
|
||||||
error::stream::UnsupportedVersion,
|
error::stream::UnsupportedVersion,
|
||||||
error::stream::UnknownXmppError>;
|
error::stream::UnknownXmppError>;
|
||||||
|
|
||||||
static_assert(
|
static_assert(!std::is_same_v<typename std::variant_alternative_t<std::variant_size_v<StreamError> - 1, StreamError>, StreamError>,
|
||||||
std::is_same_v<typename std::variant_alternative_t<std::variant_size_v<StreamError> - 1, StreamError>, error::stream::UnknownXmppError>,
|
"'UnknownXmppError' must be at the end of 'StreamError' variant");
|
||||||
"'UnknownXmppError' must be at the end of 'StreamError' variant");
|
|
||||||
|
|
||||||
} // namespace larra::xmpp
|
} // namespace larra::xmpp
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <boost/pfr.hpp>
|
#include <boost/pfr.hpp>
|
||||||
#include <nameof.hpp>
|
|
||||||
#include <ranges>
|
|
||||||
#include <utempl/utils.hpp>
|
#include <utempl/utils.hpp>
|
||||||
|
|
||||||
namespace larra::xmpp::utils {
|
namespace larra::xmpp::utils {
|
||||||
|
@ -311,31 +309,4 @@ auto AccumulateFieldLength(const T& obj) -> std::size_t {
|
||||||
return totalLength;
|
return totalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr auto ToKebabCaseName() -> std::string_view {
|
|
||||||
static constexpr auto rawStr = nameof::nameof_short_type<T>();
|
|
||||||
|
|
||||||
// std::isupper and std::tolower are not declared as constexpr
|
|
||||||
static constexpr auto isUpper = [](char ch) {
|
|
||||||
return ch >= 'A' && ch <= 'Z';
|
|
||||||
};
|
|
||||||
static constexpr auto toLower = [](char ch) {
|
|
||||||
return (ch >= 'A' && ch <= 'Z') ? static_cast<char>(ch + ('a' - 'A')) : ch;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto str = [] {
|
|
||||||
return rawStr //
|
|
||||||
| std::views::transform([](auto ch) {
|
|
||||||
return isUpper(ch) ? std::array<char, 2>{'-', toLower(ch)} : std::array<char, 2>{ch, '\0'};
|
|
||||||
}) //
|
|
||||||
| std::views::join //
|
|
||||||
| std::views::filter([](char ch) {
|
|
||||||
return ch != '\0';
|
|
||||||
}) //
|
|
||||||
| std::views::drop(1);
|
|
||||||
};
|
|
||||||
static constexpr auto arr = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
|
|
||||||
return {arr.data(), arr.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace larra::xmpp::utils
|
} // namespace larra::xmpp::utils
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace larra::xmpp::iq {
|
namespace larra::xmpp::iq {
|
||||||
auto operator<<(xmlpp::Element* element, const Bind& bind) -> void {
|
auto operator<<(xmlpp::Element* element, const Bind& bind) -> void {
|
||||||
element->set_namespace_declaration(Bind::kDefaultNamespace);
|
element->set_attribute("xmlns", Bind::kDefaultNamespace);
|
||||||
|
|
||||||
if(bind.jid) {
|
if(bind.jid) {
|
||||||
auto* jid_el = element->add_child_element("jid");
|
auto* jid_el = element->add_child_element("jid");
|
||||||
|
|
|
@ -21,7 +21,7 @@ auto RosterItem::Parse(xmlpp::Element* element) -> RosterItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator<<(xmlpp::Element* element, const Roster& self) -> void {
|
auto operator<<(xmlpp::Element* element, const Roster& self) -> void {
|
||||||
element->set_namespace_declaration(Roster::kDefaultNamespace);
|
element->set_attribute("xmlns", Roster::kDefaultNamespace);
|
||||||
S::Serialize(element, self);
|
S::Serialize(element, self);
|
||||||
}
|
}
|
||||||
auto Roster::Parse(xmlpp::Element* element) -> Roster {
|
auto Roster::Parse(xmlpp::Element* element) -> Roster {
|
||||||
|
|
112
tests/iq.cpp
112
tests/iq.cpp
|
@ -1,23 +1,10 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
#include <larra/iq.hpp>
|
#include <larra/iq.hpp>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static constexpr auto kForbiddenErrorData = R"(<?xml version="1.0" encoding="UTF-8"?>
|
static constexpr auto kExpectedData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<iq id=\"id\" type=\"get\"><some>37</some></iq>\n";
|
||||||
<iq id="42" to="name@server/res" type="error"><error type="auth"><forbidden xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error>
|
|
||||||
</iq>)";
|
|
||||||
|
|
||||||
static constexpr auto kExpectedSetData = R"(<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<iq id="id" type="set"><some>37</some></iq>
|
|
||||||
)";
|
|
||||||
|
|
||||||
static constexpr auto kExpectedData = R"(<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<iq id="id" type="get"><some>37</some></iq>
|
|
||||||
)";
|
|
||||||
|
|
||||||
struct SomeStruct {
|
struct SomeStruct {
|
||||||
int value;
|
int value;
|
||||||
constexpr auto operator==(const SomeStruct&) const -> bool = default;
|
constexpr auto operator==(const SomeStruct&) const -> bool = default;
|
||||||
|
@ -56,101 +43,4 @@ TEST(IQ, Parse) {
|
||||||
EXPECT_EQ(S::Parse(node), iq);
|
EXPECT_EQ(S::Parse(node), iq);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IQ, ParseForbiddenError) {
|
|
||||||
std::istringstream xml_stream(kForbiddenErrorData);
|
|
||||||
|
|
||||||
xmlpp::DomParser parser;
|
|
||||||
parser.parse_stream(xml_stream);
|
|
||||||
|
|
||||||
using S = Serialization<Iq<SomeStruct>>;
|
|
||||||
xmlpp::Document* doc = parser.get_document();
|
|
||||||
auto iqRes = S::Parse(doc->get_root_node());
|
|
||||||
|
|
||||||
ASSERT_TRUE(std::holds_alternative<IqError>(iqRes));
|
|
||||||
|
|
||||||
auto errorRes = std::get<IqError>(iqRes);
|
|
||||||
ASSERT_TRUE(std::holds_alternative<stanza::error::Forbidden>(errorRes.payload));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IQ, IqErrThrowVisitorThrow) {
|
|
||||||
std::istringstream xml_stream(kForbiddenErrorData);
|
|
||||||
|
|
||||||
xmlpp::DomParser parser;
|
|
||||||
parser.parse_stream(xml_stream);
|
|
||||||
|
|
||||||
using S = Serialization<Iq<SomeStruct>>;
|
|
||||||
xmlpp::Document* doc = parser.get_document();
|
|
||||||
auto iqRes = S::Parse(doc->get_root_node());
|
|
||||||
ASSERT_TRUE(std::holds_alternative<IqError>(iqRes));
|
|
||||||
|
|
||||||
static constexpr auto visitorErrMsg = "Test Error";
|
|
||||||
static constexpr auto throwErrMsg = "Stanza IQ Error: Forbidden";
|
|
||||||
try {
|
|
||||||
std::visit(utempl::Overloaded([](iq::Result<SomeStruct> r) {}, IqErrThrowVisitor{visitorErrMsg}), std::move(iqRes));
|
|
||||||
} catch(const stanza::error::StanzaBaseError& err) {
|
|
||||||
ASSERT_STREQ(throwErrMsg, err.what());
|
|
||||||
return;
|
|
||||||
} catch(const std::runtime_error& err) {
|
|
||||||
ASSERT_TRUE(false) << "Invalid throw type throw";
|
|
||||||
} catch(...) {
|
|
||||||
ASSERT_TRUE(false) << "Unexpected throw";
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_TRUE(false) << "Expected throwing an exception due to an error in output";
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IQ, IqErrThrowVisitorThrowGet) {
|
|
||||||
std::istringstream xml_stream(kExpectedData);
|
|
||||||
|
|
||||||
xmlpp::DomParser parser;
|
|
||||||
parser.parse_stream(xml_stream);
|
|
||||||
|
|
||||||
using S = Serialization<Iq<SomeStruct>>;
|
|
||||||
xmlpp::Document* doc = parser.get_document();
|
|
||||||
auto iqRes = S::Parse(doc->get_root_node());
|
|
||||||
ASSERT_TRUE(std::holds_alternative<iq::Get<SomeStruct>>(iqRes)) << "\tERROR: Unexpected parse result";
|
|
||||||
|
|
||||||
static constexpr auto visitorErrMsg = "Test Error";
|
|
||||||
static constexpr auto throwErrMsg = "Test Error: 'Get' is an invalid type for IQ result. Expected 'Result' or 'Error'";
|
|
||||||
try {
|
|
||||||
std::visit(utempl::Overloaded([](iq::Result<SomeStruct> r) {}, IqErrThrowVisitor{"Test Error"}), std::move(iqRes));
|
|
||||||
} catch(const stanza::error::StanzaBaseError& err) {
|
|
||||||
ASSERT_TRUE(false) << "\tERROR: Invalid throw type throw";
|
|
||||||
} catch(const std::runtime_error& err) {
|
|
||||||
ASSERT_STREQ(throwErrMsg, err.what());
|
|
||||||
return;
|
|
||||||
} catch(...) {
|
|
||||||
ASSERT_TRUE(false) << "\tERROR: Unexpected throw";
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_TRUE(false) << "\tERROR: Expected throwing an exception due to an error in output";
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IQ, IqErrThrowVisitorThrowSet) {
|
|
||||||
std::istringstream xml_stream(kExpectedSetData);
|
|
||||||
|
|
||||||
xmlpp::DomParser parser;
|
|
||||||
parser.parse_stream(xml_stream);
|
|
||||||
|
|
||||||
using S = Serialization<Iq<SomeStruct>>;
|
|
||||||
xmlpp::Document* doc = parser.get_document();
|
|
||||||
auto iqRes = S::Parse(doc->get_root_node());
|
|
||||||
ASSERT_TRUE(std::holds_alternative<iq::Set<SomeStruct>>(iqRes)) << "\tERROR: Unexpected parse result";
|
|
||||||
|
|
||||||
static constexpr auto visitorErrMsg = "Test Error";
|
|
||||||
static constexpr auto throwErrMsg = "Test Error: 'Set' is an invalid type for IQ result. Expected 'Result' or 'Error'";
|
|
||||||
try {
|
|
||||||
std::visit(utempl::Overloaded([](iq::Result<SomeStruct> r) {}, IqErrThrowVisitor{"Test Error"}), std::move(iqRes));
|
|
||||||
} catch(const stanza::error::StanzaBaseError& err) {
|
|
||||||
ASSERT_TRUE(false) << "\tERROR: Invalid throw type throw";
|
|
||||||
} catch(const std::runtime_error& err) {
|
|
||||||
ASSERT_STREQ(throwErrMsg, err.what());
|
|
||||||
return;
|
|
||||||
} catch(...) {
|
|
||||||
ASSERT_TRUE(false) << "\tERROR: Unexpected throw";
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_TRUE(false) << "\tERROR: Expected throwing an exception due to an error in output";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace larra::xmpp
|
} // namespace larra::xmpp
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
|
||||||
#include <exception>
|
|
||||||
#include <print>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
constexpr auto ToString(spdlog::level::level_enum e) {
|
|
||||||
switch (e) {
|
|
||||||
case spdlog::level::trace: return "TRACE";
|
|
||||||
case spdlog::level::debug: return "DEBUG";
|
|
||||||
case spdlog::level::info: return "INFO";
|
|
||||||
case spdlog::level::warn: return "WARNING";
|
|
||||||
case spdlog::level::err: return "ERROR";
|
|
||||||
case spdlog::level::critical: return "CRITICAL";
|
|
||||||
case spdlog::level::off: return "OFF";
|
|
||||||
default:
|
|
||||||
return "INVALID";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
|
||||||
|
|
||||||
auto main(int argc, char** argv) -> int {
|
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
|
||||||
|
|
||||||
// Define options
|
|
||||||
po::options_description desc("Allowed options");
|
|
||||||
desc.add_options()("help,h", "Print help message")("log_level,l",
|
|
||||||
po::value<int>()->default_value(SPDLOG_LEVEL_INFO),
|
|
||||||
"Set log level: 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=CRITICAL, 6=OFF");
|
|
||||||
|
|
||||||
// Parse command-line arguments
|
|
||||||
po::variables_map vm;
|
|
||||||
try {
|
|
||||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
|
||||||
po::notify(vm);
|
|
||||||
|
|
||||||
if(vm["log_level"].as<int>() < spdlog::level::level_enum::trace || vm["log_level"].as<int>() > spdlog::level::level_enum::off) {
|
|
||||||
throw std::invalid_argument{
|
|
||||||
std::format("Invalid argument value for '--log_level' option. Check option description for more details")};
|
|
||||||
}
|
|
||||||
if(vm["log_level"].as<int>() < SPDLOG_ACTIVE_LEVEL) {
|
|
||||||
SPDLOG_WARN("Specified log_level '{}' is lower than max available one '{}'. Log level will be changed according to the maximum one",
|
|
||||||
vm["log_level"].as<int>(),
|
|
||||||
SPDLOG_ACTIVE_LEVEL);
|
|
||||||
}
|
|
||||||
} catch(const std::exception& e) {
|
|
||||||
SPDLOG_CRITICAL("Cmd parse error: {}", e.what());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cmd options handling
|
|
||||||
spdlog::set_level(static_cast<spdlog::level::level_enum>(vm["log_level"].as<int>()));
|
|
||||||
std::println("\nEnvironment setup:\n\tCurrently set log level: {}\n", ToString(spdlog::get_level()));
|
|
||||||
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
Loading…
Reference in a new issue