mirror of
https://github.com/boostorg/redis.git
synced 2026-01-30 20:12:42 +00:00
Compare commits
57 Commits
boost-1.85
...
boost-1.87
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8df535f50e | ||
|
|
26197e8300 | ||
|
|
f592073330 | ||
|
|
32bc39a63a | ||
|
|
ca2c4efa35 | ||
|
|
7f9ac6f0fc | ||
|
|
d68c4583ed | ||
|
|
943cf0d740 | ||
|
|
53cabf0745 | ||
|
|
c309c5776b | ||
|
|
a535862d51 | ||
|
|
dfecf0bd0a | ||
|
|
ce4e5cbffa | ||
|
|
c370e930c5 | ||
|
|
e30bb373aa | ||
|
|
b8a52e5e61 | ||
|
|
302d50e262 | ||
|
|
86015cbdde | ||
|
|
84ead6a3e4 | ||
|
|
dbfb72d853 | ||
|
|
9039c3cd90 | ||
|
|
abde1afcb0 | ||
|
|
e8dd4d69eb | ||
|
|
a4d2bb983d | ||
|
|
30ba3c3eb6 | ||
|
|
90f3d6cd92 | ||
|
|
ef6dea1666 | ||
|
|
90b001a54e | ||
|
|
ec1ca876eb | ||
|
|
1b90346b7c | ||
|
|
8f46d1eaa9 | ||
|
|
a4e9a60f34 | ||
|
|
e9b16a3140 | ||
|
|
ced4f9bd02 | ||
|
|
43878d68a3 | ||
|
|
29892f2837 | ||
|
|
b71dff6dd0 | ||
|
|
a9204fcc91 | ||
|
|
1788ebc80b | ||
|
|
5656571aa4 | ||
|
|
aa6622ffa2 | ||
|
|
f459d5d89b | ||
|
|
35276b6acb | ||
|
|
122ffb20b2 | ||
|
|
1f4b709b21 | ||
|
|
7d52065a87 | ||
|
|
f0d92c16a5 | ||
|
|
1df18258d8 | ||
|
|
71c60a5a89 | ||
|
|
098fbd68d2 | ||
|
|
4f2b12adbc | ||
|
|
e7cec45cb2 | ||
|
|
b19067cfed | ||
|
|
0af1c2e73d | ||
|
|
da48368d53 | ||
|
|
5c46b62958 | ||
|
|
6cde6eab44 |
63
.github/workflows/ci.yml
vendored
63
.github/workflows/ci.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 4
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Boost
|
||||
run: python3 tools/ci.py setup-boost --source-dir=$(pwd)
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
OPENSSL_ROOT: "C:\\Program Files\\OpenSSL"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup user-config.jam
|
||||
run: cp tools/user-config.jam "${HOMEDRIVE}${HOMEPATH}/"
|
||||
@@ -134,7 +134,6 @@ jobs:
|
||||
- toolset: gcc-11
|
||||
install: g++-11
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '17'
|
||||
build-type: 'Debug'
|
||||
ldflags: ''
|
||||
@@ -142,7 +141,6 @@ jobs:
|
||||
- toolset: gcc-11
|
||||
install: g++-11
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '20'
|
||||
build-type: 'Release'
|
||||
ldflags: ''
|
||||
@@ -150,7 +148,6 @@ jobs:
|
||||
- toolset: clang-11
|
||||
install: clang-11
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '17'
|
||||
build-type: 'Debug'
|
||||
ldflags: ''
|
||||
@@ -158,7 +155,6 @@ jobs:
|
||||
- toolset: clang-11
|
||||
install: clang-11
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '20'
|
||||
build-type: 'Debug'
|
||||
ldflags: ''
|
||||
@@ -166,7 +162,6 @@ jobs:
|
||||
- toolset: clang-13
|
||||
install: clang-13
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '17'
|
||||
build-type: 'Release'
|
||||
ldflags: ''
|
||||
@@ -174,7 +169,6 @@ jobs:
|
||||
- toolset: clang-13
|
||||
install: clang-13
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '20'
|
||||
build-type: 'Release'
|
||||
ldflags: ''
|
||||
@@ -182,7 +176,6 @@ jobs:
|
||||
- toolset: clang-14
|
||||
install: 'clang-14 libc++-14-dev libc++abi-14-dev'
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '17'
|
||||
build-type: 'Debug'
|
||||
cxxflags: '-stdlib=libc++'
|
||||
@@ -191,83 +184,83 @@ jobs:
|
||||
- toolset: clang-14
|
||||
install: 'clang-14 libc++-14-dev libc++abi-14-dev'
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:22.04
|
||||
cxxstd: '20'
|
||||
build-type: 'Release'
|
||||
cxxflags: '-stdlib=libc++'
|
||||
ldflags: '-lc++'
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{matrix.container}}
|
||||
env:
|
||||
CXXFLAGS: ${{matrix.cxxflags}} -Wall -Wextra
|
||||
LDFLAGS: ${{matrix.ldflags}}
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 4
|
||||
BOOST_REDIS_TEST_SERVER: redis
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up the required containers
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install sudo python3 git g++ libssl-dev protobuf-compiler redis-server
|
||||
|
||||
docker compose -f tools/docker-compose.yml up -d --wait || (docker compose logs; exit 1)
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install cmake protobuf-compiler redis-server python3 ${{ matrix.install }}
|
||||
docker exec builder apt-get update
|
||||
docker exec builder apt-get -y --no-install-recommends install \
|
||||
git \
|
||||
g++ \
|
||||
libssl-dev \
|
||||
make \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
protobuf-compiler \
|
||||
python3 \
|
||||
${{ matrix.install }}
|
||||
|
||||
- name: Setup Boost
|
||||
run: ./tools/ci.py setup-boost --source-dir=$(pwd)
|
||||
run: docker exec builder /boost-redis/tools/ci.py setup-boost --source-dir=/boost-redis
|
||||
|
||||
- name: Build a Boost distribution using B2
|
||||
run: |
|
||||
./tools/ci.py build-b2-distro \
|
||||
docker exec builder /boost-redis/tools/ci.py build-b2-distro \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Build a Boost distribution using CMake
|
||||
run: |
|
||||
./tools/ci.py build-cmake-distro \
|
||||
docker exec builder /boost-redis/tools/ci.py build-cmake-distro \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Build the project tests
|
||||
run: |
|
||||
./tools/ci.py build-cmake-standalone-tests \
|
||||
docker exec builder /boost-redis/tools/ci.py build-cmake-standalone-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Run the project tests
|
||||
run: |
|
||||
./tools/ci.py run-cmake-standalone-tests \
|
||||
docker exec builder /boost-redis/tools/ci.py run-cmake-standalone-tests \
|
||||
--build-type ${{ matrix.build-type }}
|
||||
|
||||
- name: Run add_subdirectory tests
|
||||
run: |
|
||||
./tools/ci.py run-cmake-add-subdirectory-tests \
|
||||
docker exec builder /boost-redis/tools/ci.py run-cmake-add-subdirectory-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Run find_package tests with the built cmake distribution
|
||||
run: |
|
||||
./tools/ci.py run-cmake-find-package-tests \
|
||||
docker exec builder /boost-redis/tools/ci.py run-cmake-find-package-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
|
||||
- name: Run find_package tests with the built b2 distribution
|
||||
run: |
|
||||
./tools/ci.py run-cmake-b2-find-package-tests \
|
||||
docker exec builder /boost-redis/tools/ci.py run-cmake-b2-find-package-tests \
|
||||
--build-type ${{ matrix.build-type }} \
|
||||
--cxxstd ${{ matrix.cxxstd }} \
|
||||
--toolset ${{ matrix.toolset }}
|
||||
@@ -296,7 +289,7 @@ jobs:
|
||||
container: ${{matrix.container}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
|
||||
51
.github/workflows/coverage.yml
vendored
51
.github/workflows/coverage.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: Coverage
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CXX: g++-11
|
||||
CXXFLAGS: -g -O0 -std=c++20 --coverage -fkeep-inline-functions -fkeep-static-functions
|
||||
LDFLAGS: --coverage
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 4
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get --no-install-recommends -y install cmake lcov g++-11 redis-server python3 libgd-perl
|
||||
|
||||
- name: Setup Boost
|
||||
run: ./tools/ci.py setup-boost --source-dir=$(pwd)
|
||||
|
||||
- name: Build Boost
|
||||
run: ./tools/ci.py build-b2-distro --toolset=gcc-11
|
||||
|
||||
# Having our library there confuses the coverage reports
|
||||
- name: Remove Boost.Redis from the b2 distro
|
||||
run: rm -rf ~/boost-b2-distro/include/boost/redis
|
||||
|
||||
- name: Run CMake
|
||||
run: cmake -DCMAKE_PREFIX_PATH=$HOME/boost-b2-distro --preset coverage .
|
||||
|
||||
- name: Build
|
||||
run: cmake --build --preset coverage
|
||||
|
||||
- name: Test
|
||||
run: ctest --preset coverage
|
||||
|
||||
- name: Make the coverage file
|
||||
run: cmake --build --preset coverage --target coverage
|
||||
|
||||
- name: Upload to codecov
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -f ./build/coverage/coverage.info
|
||||
@@ -38,7 +38,6 @@ if (BOOST_REDIS_MAIN_PROJECT)
|
||||
align
|
||||
context
|
||||
core
|
||||
coroutine
|
||||
static_assert
|
||||
pool
|
||||
date_time
|
||||
|
||||
30
README.md
30
README.md
@@ -9,7 +9,7 @@ The requirements for using Boost.Redis are:
|
||||
* Boost. The library is included in Boost distributions starting with 1.84.
|
||||
* C++17 or higher.
|
||||
* Redis 6 or higher (must support RESP3).
|
||||
* Gcc (10, 11, 12), Clang (11, 13, 14) and Visual Studio (16 2019, 17 2022).
|
||||
* Gcc (11, 12), Clang (11, 13, 14) and Visual Studio (16 2019, 17 2022).
|
||||
* Have basic-level knowledge about [Redis](https://redis.io/docs/)
|
||||
and [Boost.Asio](https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio/overview.html).
|
||||
|
||||
@@ -676,16 +676,34 @@ https://lists.boost.org/Archives/boost/2023/01/253944.php.
|
||||
|
||||
## Changelog
|
||||
|
||||
### Boost 1.87
|
||||
|
||||
* (Issue [205](https://github.com/boostorg/redis/issues/205))
|
||||
Improves reaction time to disconnection by using `wait_for_one_error`
|
||||
instead of `wait_for_all`. The function `connection::async_run` was
|
||||
also changed to return EOF to the user when that error is received
|
||||
from the server. That is a breaking change.
|
||||
|
||||
* (Issue [210](https://github.com/boostorg/redis/issues/210))
|
||||
Fixes the adapter of empty nested reposponses.
|
||||
|
||||
* (Issues [211](https://github.com/boostorg/redis/issues/211) and [212](https://github.com/boostorg/redis/issues/212))
|
||||
Fixes the reconnect loop that would hang under certain conditions,
|
||||
see the linked issues for more details.
|
||||
|
||||
* (Issue [219](https://github.com/boostorg/redis/issues/219))
|
||||
Changes the default log level from `disabled` to `debug`.
|
||||
|
||||
### Boost 1.85
|
||||
|
||||
* ([Issue 170](https://github.com/boostorg/redis/issues/170))
|
||||
* (Issue [170](https://github.com/boostorg/redis/issues/170))
|
||||
Under load and on low-latency networks it is possible to start
|
||||
receiving responses before the write operation completed and while
|
||||
the request is still marked as staged and not written. This messes
|
||||
up with the heuristics that classifies responses as unsolicied or
|
||||
not.
|
||||
|
||||
* ([Issue 168](https://github.com/boostorg/redis/issues/168)).
|
||||
* (Issue [168](https://github.com/boostorg/redis/issues/168)).
|
||||
Provides a way of passing a custom SSL context to the connection.
|
||||
The design here differs from that of Boost.Beast and Boost.MySql
|
||||
since in Boost.Redis the connection owns the context instead of only
|
||||
@@ -693,16 +711,16 @@ https://lists.boost.org/Archives/boost/2023/01/253944.php.
|
||||
apps need only one connection for their entire application, which
|
||||
makes the overhead of one ssl-context per connection negligible.
|
||||
|
||||
* ([Issue 181](https://github.com/boostorg/redis/issues/181)).
|
||||
* (Issue [181](https://github.com/boostorg/redis/issues/181)).
|
||||
See a detailed description of this bug in
|
||||
[this](https://github.com/boostorg/redis/issues/181#issuecomment-1913346983)
|
||||
comment.
|
||||
|
||||
* ([Issue 182](https://github.com/boostorg/redis/issues/182)).
|
||||
* (Issue [182](https://github.com/boostorg/redis/issues/182)).
|
||||
Sets `"default"` as the default value of `config::username`. This
|
||||
makes it simpler to use the `requirepass` configuration in Redis.
|
||||
|
||||
* ([Issue 189](https://github.com/boostorg/redis/issues/189)).
|
||||
* (Issue [189](https://github.com/boostorg/redis/issues/189)).
|
||||
Fixes narrowing convertion by using `std::size_t` instead of
|
||||
`std::uint64_t` for the sizes of bulks and aggregates. The code
|
||||
relies now on `std::from_chars` returning an error if a value
|
||||
|
||||
28
build.jam
Normal file
28
build.jam
Normal file
@@ -0,0 +1,28 @@
|
||||
# Copyright René Ferdinand Rivera Morell 2024
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt 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/core//boost_core
|
||||
/boost/mp11//boost_mp11
|
||||
/boost/system//boost_system
|
||||
/boost/throw_exception//boost_throw_exception ;
|
||||
|
||||
project /boost/redis
|
||||
: common-requirements
|
||||
<include>include
|
||||
;
|
||||
|
||||
explicit
|
||||
[ alias boost_redis : : : : <library>$(boost_dependencies) ]
|
||||
[ alias all : boost_redis test ]
|
||||
;
|
||||
|
||||
call-if : boost-library redis
|
||||
;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -102,8 +102,12 @@ private:
|
||||
std::variant>,
|
||||
std::tuple_size<Tuple>::value>;
|
||||
|
||||
// Tuple element we are currently on.
|
||||
std::size_t i_ = 0;
|
||||
|
||||
// Nested aggregate element counter.
|
||||
std::size_t aggregate_size_ = 0;
|
||||
|
||||
adapters_array_type adapters_;
|
||||
result<Tuple>* res_ = nullptr;
|
||||
|
||||
@@ -117,36 +121,35 @@ public:
|
||||
}
|
||||
|
||||
template <class String>
|
||||
void count(resp3::basic_node<String> const& nd)
|
||||
void count(resp3::basic_node<String> const& elem)
|
||||
{
|
||||
if (nd.depth == 1) {
|
||||
if (is_aggregate(nd.data_type))
|
||||
aggregate_size_ = element_multiplicity(nd.data_type) * nd.aggregate_size;
|
||||
else
|
||||
++i_;
|
||||
|
||||
return;
|
||||
if (elem.depth == 1 && is_aggregate(elem.data_type)) {
|
||||
aggregate_size_ = element_multiplicity(elem.data_type) * elem.aggregate_size;
|
||||
}
|
||||
|
||||
if (--aggregate_size_ == 0)
|
||||
++i_;
|
||||
if (aggregate_size_ == 0) {
|
||||
i_ += 1;
|
||||
} else {
|
||||
aggregate_size_ -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <class String>
|
||||
void operator()(resp3::basic_node<String> const& nd, system::error_code& ec)
|
||||
void operator()(resp3::basic_node<String> const& elem, system::error_code& ec)
|
||||
{
|
||||
using std::visit;
|
||||
|
||||
if (nd.depth == 0) {
|
||||
auto const real_aggr_size = nd.aggregate_size * element_multiplicity(nd.data_type);
|
||||
if (elem.depth == 0) {
|
||||
auto const multiplicity = element_multiplicity(elem.data_type);
|
||||
auto const real_aggr_size = elem.aggregate_size * multiplicity;
|
||||
if (real_aggr_size != std::tuple_size<Tuple>::value)
|
||||
ec = redis::error::incompatible_size;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
visit([&](auto& arg){arg(nd, ec);}, adapters_[i_]);
|
||||
count(nd);
|
||||
visit([&](auto& arg){arg(elem, ec);}, adapters_[i_]);
|
||||
count(elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -113,7 +113,7 @@ struct exec_op {
|
||||
asio::coroutine coro{};
|
||||
|
||||
template <class Self>
|
||||
void operator()(Self& self , system::error_code ec = {}, std::size_t = 0)
|
||||
void operator()(Self& self , system::error_code = {}, std::size_t = 0)
|
||||
{
|
||||
BOOST_ASIO_CORO_REENTER (coro)
|
||||
{
|
||||
@@ -317,7 +317,7 @@ struct reader_op {
|
||||
if (ec == asio::error::eof) {
|
||||
logger_.trace("reader-op: EOF received. Exiting ...");
|
||||
conn_->cancel(operation::run);
|
||||
return self.complete({}); // EOFINAE: EOF is not an error.
|
||||
return self.complete(ec);
|
||||
}
|
||||
|
||||
// The connection is not viable after an error.
|
||||
@@ -705,7 +705,7 @@ private:
|
||||
template <class, class> friend struct writer_op;
|
||||
template <class, class> friend struct run_op;
|
||||
template <class> friend struct exec_op;
|
||||
template <class, class, class> friend struct run_all_op;
|
||||
template <class, class, class> friend struct runner_op;
|
||||
|
||||
void cancel_push_requests()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -12,9 +12,8 @@
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/experimental/parallel_group.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/cancel_after.hpp>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
@@ -30,65 +29,29 @@ struct connect_op {
|
||||
|
||||
template <class Self>
|
||||
void operator()( Self& self
|
||||
, std::array<std::size_t, 2> const& order = {}
|
||||
, system::error_code const& ec1 = {}
|
||||
, asio::ip::tcp::endpoint const& ep= {}
|
||||
, system::error_code const& ec2 = {})
|
||||
, system::error_code const& ec = {}
|
||||
, asio::ip::tcp::endpoint const& ep= {})
|
||||
{
|
||||
BOOST_ASIO_CORO_REENTER (coro)
|
||||
{
|
||||
ctor_->timer_.expires_after(ctor_->timeout_);
|
||||
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
asio::experimental::make_parallel_group(
|
||||
[this](auto token)
|
||||
{
|
||||
auto f = [](system::error_code const&, auto const&) { return true; };
|
||||
return asio::async_connect(*stream, *res_, f, token);
|
||||
},
|
||||
[this](auto token) { return ctor_->timer_.async_wait(token);}
|
||||
).async_wait(
|
||||
asio::experimental::wait_for_one(),
|
||||
std::move(self));
|
||||
asio::async_connect(*stream, *res_,
|
||||
[](system::error_code const&, auto const&) { return true; },
|
||||
asio::cancel_after(ctor_->timeout_, std::move(self)));
|
||||
|
||||
if (is_cancelled(self)) {
|
||||
self.complete(asio::error::operation_aborted);
|
||||
return;
|
||||
}
|
||||
ctor_->endpoint_ = ep;
|
||||
|
||||
switch (order[0]) {
|
||||
case 0: {
|
||||
ctor_->endpoint_ = ep;
|
||||
self.complete(ec1);
|
||||
} break;
|
||||
case 1:
|
||||
{
|
||||
if (ec2) {
|
||||
self.complete(ec2);
|
||||
} else {
|
||||
self.complete(error::connect_timeout);
|
||||
}
|
||||
} break;
|
||||
|
||||
default: BOOST_ASSERT(false);
|
||||
if (ec == asio::error::operation_aborted) {
|
||||
self.complete(redis::error::connect_timeout);
|
||||
} else {
|
||||
self.complete(ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class Executor>
|
||||
class connector {
|
||||
public:
|
||||
using timer_type =
|
||||
asio::basic_waitable_timer<
|
||||
std::chrono::steady_clock,
|
||||
asio::wait_traits<std::chrono::steady_clock>,
|
||||
Executor>;
|
||||
|
||||
connector(Executor ex)
|
||||
: timer_{ex}
|
||||
{}
|
||||
|
||||
void set_config(config const& cfg)
|
||||
{ timeout_ = cfg.connect_timeout; }
|
||||
|
||||
@@ -102,20 +65,7 @@ public:
|
||||
return asio::async_compose
|
||||
< CompletionToken
|
||||
, void(system::error_code)
|
||||
>(connect_op<connector, Stream>{this, &stream, &res}, token, timer_);
|
||||
}
|
||||
|
||||
std::size_t cancel(operation op)
|
||||
{
|
||||
switch (op) {
|
||||
case operation::connect:
|
||||
case operation::all:
|
||||
timer_.cancel();
|
||||
break;
|
||||
default: /* ignore */;
|
||||
}
|
||||
|
||||
return 0;
|
||||
>(connect_op<connector, Stream>{this, &stream, &res}, token);
|
||||
}
|
||||
|
||||
auto const& endpoint() const noexcept { return endpoint_;}
|
||||
@@ -123,7 +73,6 @@ public:
|
||||
private:
|
||||
template <class, class> friend struct connect_op;
|
||||
|
||||
timer_type timer_;
|
||||
std::chrono::steady_clock::duration timeout_ = std::chrono::seconds{2};
|
||||
asio::ip::tcp::endpoint endpoint_;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -12,9 +12,8 @@
|
||||
#include <boost/redis/error.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/experimental/parallel_group.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/cancel_after.hpp>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
@@ -28,51 +27,23 @@ struct resolve_op {
|
||||
|
||||
template <class Self>
|
||||
void operator()( Self& self
|
||||
, std::array<std::size_t, 2> order = {}
|
||||
, system::error_code ec1 = {}
|
||||
, asio::ip::tcp::resolver::results_type res = {}
|
||||
, system::error_code ec2 = {})
|
||||
, system::error_code ec = {}
|
||||
, asio::ip::tcp::resolver::results_type res = {})
|
||||
{
|
||||
BOOST_ASIO_CORO_REENTER (coro)
|
||||
{
|
||||
resv_->timer_.expires_after(resv_->timeout_);
|
||||
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
asio::experimental::make_parallel_group(
|
||||
[this](auto token)
|
||||
{
|
||||
return resv_->resv_.async_resolve(resv_->addr_.host, resv_->addr_.port, token);
|
||||
},
|
||||
[this](auto token) { return resv_->timer_.async_wait(token);}
|
||||
).async_wait(
|
||||
asio::experimental::wait_for_one(),
|
||||
std::move(self));
|
||||
resv_->resv_.async_resolve(
|
||||
resv_->addr_.host,
|
||||
resv_->addr_.port,
|
||||
asio::cancel_after(resv_->timeout_, std::move(self)));
|
||||
|
||||
if (is_cancelled(self)) {
|
||||
self.complete(asio::error::operation_aborted);
|
||||
return;
|
||||
}
|
||||
resv_->results_ = res;
|
||||
|
||||
switch (order[0]) {
|
||||
case 0: {
|
||||
// Resolver completed first.
|
||||
resv_->results_ = res;
|
||||
self.complete(ec1);
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
if (ec2) {
|
||||
// Timer completed first with error, perhaps a
|
||||
// cancellation going on.
|
||||
self.complete(ec2);
|
||||
} else {
|
||||
// Timer completed first without an error, this is a
|
||||
// resolve timeout.
|
||||
self.complete(error::resolve_timeout);
|
||||
}
|
||||
} break;
|
||||
|
||||
default: BOOST_ASSERT(false);
|
||||
if (ec == asio::error::operation_aborted) {
|
||||
self.complete(error::resolve_timeout);
|
||||
} else {
|
||||
self.complete(ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,13 +52,7 @@ struct resolve_op {
|
||||
template <class Executor>
|
||||
class resolver {
|
||||
public:
|
||||
using timer_type =
|
||||
asio::basic_waitable_timer<
|
||||
std::chrono::steady_clock,
|
||||
asio::wait_traits<std::chrono::steady_clock>,
|
||||
Executor>;
|
||||
|
||||
resolver(Executor ex) : resv_{ex} , timer_{ex} {}
|
||||
resolver(Executor ex) : resv_{ex} {}
|
||||
|
||||
template <class CompletionToken>
|
||||
auto async_resolve(CompletionToken&& token)
|
||||
@@ -104,7 +69,6 @@ public:
|
||||
case operation::resolve:
|
||||
case operation::all:
|
||||
resv_.cancel();
|
||||
timer_.cancel();
|
||||
break;
|
||||
default: /* ignore */;
|
||||
}
|
||||
@@ -126,7 +90,6 @@ private:
|
||||
template <class> friend struct resolve_op;
|
||||
|
||||
resolver_type resv_;
|
||||
timer_type timer_;
|
||||
address addr_;
|
||||
std::chrono::steady_clock::duration timeout_;
|
||||
asio::ip::tcp::resolver::results_type results_;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -18,11 +18,11 @@
|
||||
#include <boost/redis/detail/resolver.hpp>
|
||||
#include <boost/redis/detail/handshaker.hpp>
|
||||
#include <boost/asio/compose.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/experimental/parallel_group.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/prepend.hpp>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
@@ -87,13 +87,54 @@ public:
|
||||
{
|
||||
BOOST_ASIO_CORO_REENTER (coro_)
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
runner_->resv_.async_resolve(
|
||||
asio::prepend(std::move(self), std::array<std::size_t, 3> {}));
|
||||
|
||||
logger_.on_resolve(ec0, runner_->resv_.results());
|
||||
|
||||
if (ec0 || redis::detail::is_cancelled(self)) {
|
||||
self.complete(!!ec0 ? ec0 : asio::error::operation_aborted);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
runner_->ctor_.async_connect(
|
||||
conn_->next_layer().next_layer(),
|
||||
runner_->resv_.results(),
|
||||
asio::prepend(std::move(self), std::array<std::size_t, 3> {}));
|
||||
|
||||
logger_.on_connect(ec0, runner_->ctor_.endpoint());
|
||||
|
||||
if (ec0 || redis::detail::is_cancelled(self)) {
|
||||
self.complete(!!ec0 ? ec0 : asio::error::operation_aborted);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn_->use_ssl()) {
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
runner_->hsher_.async_handshake(
|
||||
conn_->next_layer(),
|
||||
asio::prepend(std::move(self),
|
||||
std::array<std::size_t, 3> {}));
|
||||
|
||||
logger_.on_ssl_handshake(ec0);
|
||||
if (ec0 || redis::detail::is_cancelled(self)) {
|
||||
self.complete(!!ec0 ? ec0 : asio::error::operation_aborted);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Oder is important here because async_run might
|
||||
// trigger an async_write before the async_hello thereby
|
||||
// causing authentication problems.
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
asio::experimental::make_parallel_group(
|
||||
[this](auto token) { return runner_->async_run_all(*conn_, logger_, token); },
|
||||
[this](auto token) { return runner_->async_hello(*conn_, logger_, token); },
|
||||
[this](auto token) { return runner_->health_checker_.async_check_health(*conn_, logger_, token); },
|
||||
[this](auto token) { return runner_->async_hello(*conn_, logger_, token); }
|
||||
[this](auto token) { return conn_->async_run_lean(runner_->cfg_, logger_, token); }
|
||||
).async_wait(
|
||||
asio::experimental::wait_for_all(),
|
||||
asio::experimental::wait_for_one_error(),
|
||||
std::move(self));
|
||||
|
||||
logger_.on_runner(ec0, ec1, ec2);
|
||||
@@ -103,59 +144,17 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (ec0 == error::connect_timeout || ec0 == error::resolve_timeout) {
|
||||
if (order[0] == 0 && !!ec0) {
|
||||
self.complete(ec0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (order[0] == 2 && !!ec2) {
|
||||
self.complete(ec2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (order[0] == 1 && ec1 == error::pong_timeout) {
|
||||
self.complete(ec1);
|
||||
return;
|
||||
}
|
||||
|
||||
self.complete(ec0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class Runner, class Connection, class Logger>
|
||||
struct run_all_op {
|
||||
Runner* runner_ = nullptr;
|
||||
Connection* conn_ = nullptr;
|
||||
Logger logger_;
|
||||
asio::coroutine coro_{};
|
||||
|
||||
template <class Self>
|
||||
void operator()(Self& self, system::error_code ec = {}, std::size_t = 0)
|
||||
{
|
||||
BOOST_ASIO_CORO_REENTER (coro_)
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
runner_->resv_.async_resolve(std::move(self));
|
||||
logger_.on_resolve(ec, runner_->resv_.results());
|
||||
BOOST_REDIS_CHECK_OP0(conn_->cancel(operation::run);)
|
||||
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
runner_->ctor_.async_connect(conn_->next_layer().next_layer(), runner_->resv_.results(), std::move(self));
|
||||
logger_.on_connect(ec, runner_->ctor_.endpoint());
|
||||
BOOST_REDIS_CHECK_OP0(conn_->cancel(operation::run);)
|
||||
|
||||
if (conn_->use_ssl()) {
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
runner_->hsher_.async_handshake(conn_->next_layer(), std::move(self));
|
||||
logger_.on_ssl_handshake(ec);
|
||||
BOOST_REDIS_CHECK_OP0(conn_->cancel(operation::run);)
|
||||
}
|
||||
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
conn_->async_run_lean(runner_->cfg_, logger_, std::move(self));
|
||||
BOOST_REDIS_CHECK_OP0(;)
|
||||
self.complete(ec);
|
||||
self.complete(ec2);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -165,7 +164,6 @@ class runner {
|
||||
public:
|
||||
runner(Executor ex, config cfg)
|
||||
: resv_{ex}
|
||||
, ctor_{ex}
|
||||
, hsher_{ex}
|
||||
, health_checker_{ex}
|
||||
, cfg_{cfg}
|
||||
@@ -174,7 +172,6 @@ public:
|
||||
std::size_t cancel(operation op)
|
||||
{
|
||||
resv_.cancel(op);
|
||||
ctor_.cancel(op);
|
||||
hsher_.cancel(op);
|
||||
health_checker_.cancel(op);
|
||||
return 0U;
|
||||
@@ -202,24 +199,12 @@ public:
|
||||
|
||||
private:
|
||||
using resolver_type = resolver<Executor>;
|
||||
using connector_type = connector<Executor>;
|
||||
using handshaker_type = detail::handshaker<Executor>;
|
||||
using health_checker_type = health_checker<Executor>;
|
||||
using timer_type = typename connector_type::timer_type;
|
||||
|
||||
template <class, class, class> friend struct run_all_op;
|
||||
template <class, class, class> friend class runner_op;
|
||||
template <class, class, class> friend struct hello_op;
|
||||
|
||||
template <class Connection, class Logger, class CompletionToken>
|
||||
auto async_run_all(Connection& conn, Logger l, CompletionToken token)
|
||||
{
|
||||
return asio::async_compose
|
||||
< CompletionToken
|
||||
, void(system::error_code)
|
||||
>(run_all_op<runner, Connection, Logger>{this, &conn, l}, token, conn);
|
||||
}
|
||||
|
||||
template <class Connection, class Logger, class CompletionToken>
|
||||
auto async_hello(Connection& conn, Logger l, CompletionToken token)
|
||||
{
|
||||
@@ -255,7 +240,7 @@ private:
|
||||
}
|
||||
|
||||
resolver_type resv_;
|
||||
connector_type ctor_;
|
||||
connector ctor_;
|
||||
handshaker_type hsher_;
|
||||
health_checker_type health_checker_;
|
||||
request hello_req_;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -156,19 +156,19 @@ logger::on_hello(
|
||||
|
||||
void
|
||||
logger::on_runner(
|
||||
system::error_code const& run_all_ec,
|
||||
system::error_code const& health_check_ec,
|
||||
system::error_code const& hello_ec)
|
||||
system::error_code const& hello,
|
||||
system::error_code const& check_health,
|
||||
system::error_code const& run)
|
||||
{
|
||||
if (level_ < level::info)
|
||||
return;
|
||||
|
||||
write_prefix();
|
||||
|
||||
std::clog << "runner-op: "
|
||||
<< run_all_ec.message() << " (async_run_all), "
|
||||
<< health_check_ec.message() << " (async_health_check) "
|
||||
<< hello_ec.message() << " (async_hello).";
|
||||
std::clog << "hello: "
|
||||
<< hello.message() << " (async_hello), "
|
||||
<< check_health.message() << " (async_check_health) "
|
||||
<< run.message() << " (async_run_lean).";
|
||||
|
||||
std::clog << std::endl;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
*
|
||||
* @param l Log level.
|
||||
*/
|
||||
logger(level l = level::disabled)
|
||||
logger(level l = level::debug)
|
||||
: level_{l}
|
||||
{}
|
||||
|
||||
@@ -143,15 +143,15 @@ public:
|
||||
/** @brief Called when the runner operation completes.
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* @param run_all_ec Error code returned by the run_all operation.
|
||||
* @param health_check_ec Error code returned by the health checker operation.
|
||||
* @param hello_ec Error code returned by the health checker operation.
|
||||
* @param health_check_ec Error code returned by the health checker operation.
|
||||
* @param run_all_ec Error code returned by the run_all operation.
|
||||
*/
|
||||
void
|
||||
on_runner(
|
||||
system::error_code const& run_all_ec,
|
||||
system::error_code const& health_check_ec,
|
||||
system::error_code const& hello_ec);
|
||||
system::error_code const& hello,
|
||||
system::error_code const& health_check,
|
||||
system::error_code const& run);
|
||||
|
||||
void
|
||||
on_check_health(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
|
||||
12
test/Jamfile
12
test/Jamfile
@@ -1,12 +1,14 @@
|
||||
|
||||
import ../config/checks/config : requires ;
|
||||
import-search /boost/config/checks ;
|
||||
import config : requires ;
|
||||
import ac ;
|
||||
|
||||
# Configure openssl if it hasn't been done yet
|
||||
using openssl ;
|
||||
|
||||
# Use these requirements as both regular and usage requirements across all tests
|
||||
local requirements =
|
||||
local requirements =
|
||||
<library>/boost/redis//boost_redis
|
||||
<define>BOOST_ASIO_NO_DEPRECATED=1
|
||||
<define>BOOST_ASIO_DISABLE_BOOST_ARRAY=1
|
||||
<define>BOOST_ASIO_DISABLE_BOOST_BIND=1
|
||||
@@ -14,7 +16,6 @@ local requirements =
|
||||
<define>BOOST_ASIO_DISABLE_BOOST_REGEX=1
|
||||
<toolset>msvc:<cxxflags>"/bigobj"
|
||||
<target-os>windows:<define>_WIN32_WINNT=0x0601
|
||||
<include>../include
|
||||
[ requires
|
||||
cxx14_constexpr
|
||||
cxx14_generic_lambdas
|
||||
@@ -30,6 +31,7 @@ local requirements =
|
||||
]
|
||||
[ ac.check-library /openssl//ssl : <library>/openssl//ssl/<link>shared : <build>no ]
|
||||
[ ac.check-library /openssl//crypto : <library>/openssl//crypto/<link>shared : <build>no ]
|
||||
<library>/boost/test//boost_unit_test_framework
|
||||
;
|
||||
|
||||
|
||||
@@ -44,7 +46,7 @@ lib redis_test_common
|
||||
|
||||
# B2 runs tests in parallel, and some tests rely on having exclusive
|
||||
# access to a Redis server, so we only run the ones that don't require a DB server.
|
||||
local tests =
|
||||
local tests =
|
||||
test_low_level_sync_sans_io
|
||||
test_low_level
|
||||
test_request
|
||||
@@ -54,7 +56,7 @@ local tests =
|
||||
# Build and run the tests
|
||||
for local test in $(tests)
|
||||
{
|
||||
run
|
||||
run
|
||||
$(test).cpp
|
||||
redis_test_common/<link>static
|
||||
: target-name $(test)
|
||||
|
||||
@@ -29,7 +29,7 @@ run(
|
||||
conn->async_run(cfg, {l}, run_callback{conn, op, ec});
|
||||
}
|
||||
|
||||
std::string safe_getenv(const char* name, const char* default_value)
|
||||
static std::string safe_getenv(const char* name, const char* default_value)
|
||||
{
|
||||
// MSVC doesn't like getenv
|
||||
#ifdef BOOST_MSVC
|
||||
@@ -43,10 +43,15 @@ std::string safe_getenv(const char* name, const char* default_value)
|
||||
return res ? res : default_value;
|
||||
}
|
||||
|
||||
std::string get_server_hostname()
|
||||
{
|
||||
return safe_getenv("BOOST_REDIS_TEST_SERVER", "localhost");
|
||||
}
|
||||
|
||||
boost::redis::config make_test_config()
|
||||
{
|
||||
boost::redis::config cfg;
|
||||
cfg.addr.host = safe_getenv("BOOST_REDIS_TEST_SERVER", "localhost");
|
||||
cfg.addr.host = get_server_hostname();
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ auto start(boost::asio::awaitable<void> op) -> int;
|
||||
#endif // BOOST_ASIO_HAS_CO_AWAIT
|
||||
|
||||
boost::redis::config make_test_config();
|
||||
std::string get_server_hostname();
|
||||
|
||||
void
|
||||
run(
|
||||
|
||||
@@ -152,6 +152,9 @@ BOOST_AUTO_TEST_CASE(correct_database)
|
||||
auto const pos = value.find("db=");
|
||||
auto const index_str = value.substr(pos + 3, 1);
|
||||
auto const index = std::stoi(index_str);
|
||||
|
||||
// This check might fail if more than one client is connected to
|
||||
// redis when the CLIENT LIST command is run.
|
||||
BOOST_CHECK_EQUAL(cfg.database_index.value(), index);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <boost/system/errc.hpp>
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/co_spawn.hpp>
|
||||
#include <boost/asio/experimental/as_tuple.hpp>
|
||||
#include <boost/asio/as_tuple.hpp>
|
||||
#define BOOST_TEST_MODULE conn-push
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#include <iostream>
|
||||
@@ -21,7 +21,7 @@ namespace redis = boost::redis;
|
||||
using boost::redis::operation;
|
||||
using connection = boost::redis::connection;
|
||||
using error_code = boost::system::error_code;
|
||||
using net::experimental::as_tuple;
|
||||
using net::as_tuple;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
@@ -218,7 +218,7 @@ BOOST_AUTO_TEST_CASE(test_push_adapter)
|
||||
|
||||
auto cfg = make_test_config();
|
||||
conn->async_run(cfg, {}, [](auto ec){
|
||||
BOOST_CHECK_EQUAL(ec, boost::redis::error::incompatible_size);
|
||||
BOOST_CHECK_EQUAL(ec, redis::error::incompatible_size);
|
||||
});
|
||||
|
||||
ioc.run();
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
#ifdef BOOST_ASIO_HAS_CO_AWAIT
|
||||
#include <boost/asio/experimental/awaitable_operators.hpp>
|
||||
#include <boost/asio/experimental/as_tuple.hpp>
|
||||
#include <boost/asio/as_tuple.hpp>
|
||||
|
||||
namespace net = boost::asio;
|
||||
|
||||
using boost::redis::operation;
|
||||
using boost::redis::connection;
|
||||
using boost::system::error_code;
|
||||
using net::experimental::as_tuple;
|
||||
using net::as_tuple;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
* accompanying file LICENSE.txt)
|
||||
*/
|
||||
|
||||
#include <boost/asio/ssl/host_name_verification.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/redis/connection.hpp>
|
||||
#define BOOST_TEST_MODULE conn-tls
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#include <iostream>
|
||||
#include "common.hpp"
|
||||
|
||||
namespace net = boost::asio;
|
||||
@@ -16,24 +17,49 @@ using connection = boost::redis::connection;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::config;
|
||||
using boost::redis::operation;
|
||||
using boost::system::error_code;
|
||||
|
||||
bool verify_certificate(bool, net::ssl::verify_context&)
|
||||
{
|
||||
std::cout << "set_verify_callback" << std::endl;
|
||||
return true;
|
||||
}
|
||||
// CA certificate that signed the test server's certificate.
|
||||
// This is a self-signed CA created for testing purposes.
|
||||
// This must match tools/tls/ca.crt contents
|
||||
static constexpr const char* ca_certificate = R"%(-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
2XVYrfsnPHX0CsPDIy7L
|
||||
-----END CERTIFICATE-----)%";
|
||||
|
||||
config make_tls_config()
|
||||
static config make_tls_config()
|
||||
{
|
||||
config cfg;
|
||||
cfg.use_ssl = true;
|
||||
cfg.username = "aedis";
|
||||
cfg.password = "aedis";
|
||||
cfg.addr.host = "db.occase.de";
|
||||
cfg.addr.host = get_server_hostname();
|
||||
cfg.addr.port = "6380";
|
||||
//cfg.health_check_interval = std::chrono::seconds{0};
|
||||
return cfg;
|
||||
}
|
||||
|
||||
@@ -49,11 +75,13 @@ BOOST_AUTO_TEST_CASE(ping_internal_ssl_context)
|
||||
|
||||
net::io_context ioc;
|
||||
connection conn{ioc};
|
||||
conn.next_layer().set_verify_mode(net::ssl::verify_peer);
|
||||
conn.next_layer().set_verify_callback(verify_certificate);
|
||||
|
||||
conn.async_exec(req, resp, [&](auto ec, auto) {
|
||||
BOOST_TEST(!ec);
|
||||
// The custom server uses a certificate signed by a CA
|
||||
// that is not trusted by default - skip verification.
|
||||
conn.next_layer().set_verify_mode(net::ssl::verify_none);
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, auto) {
|
||||
BOOST_TEST(ec == std::error_code());
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
@@ -76,12 +104,17 @@ BOOST_AUTO_TEST_CASE(ping_custom_ssl_context)
|
||||
|
||||
net::io_context ioc;
|
||||
net::ssl::context ctx{boost::asio::ssl::context::tls_client};
|
||||
|
||||
// Configure the SSL context to trust the CA that signed the server's certificate.
|
||||
// The test certificate uses "redis" as its common name, regardless of the actual server's hostname
|
||||
ctx.add_certificate_authority(net::const_buffer(ca_certificate, std::strlen(ca_certificate)));
|
||||
ctx.set_verify_mode(net::ssl::verify_peer);
|
||||
ctx.set_verify_callback(net::ssl::host_name_verification("redis"));
|
||||
|
||||
connection conn{ioc, std::move(ctx)};
|
||||
conn.next_layer().set_verify_mode(net::ssl::verify_peer);
|
||||
conn.next_layer().set_verify_callback(verify_certificate);
|
||||
|
||||
conn.async_exec(req, resp, [&](auto ec, auto) {
|
||||
BOOST_TEST(!ec);
|
||||
BOOST_TEST(ec == std::error_code());
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
@@ -91,38 +124,3 @@ BOOST_AUTO_TEST_CASE(ping_custom_ssl_context)
|
||||
|
||||
BOOST_CHECK_EQUAL(in, std::get<0>(resp).value());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(acl_does_not_allow_select)
|
||||
{
|
||||
auto cfg = make_tls_config();
|
||||
cfg.database_index = 22;
|
||||
cfg.reconnect_wait_interval = std::chrono::seconds::zero();
|
||||
|
||||
std::string const in = "Kabuf";
|
||||
|
||||
request req;
|
||||
req.push("PING", in);
|
||||
|
||||
response<std::string> resp;
|
||||
|
||||
net::io_context ioc;
|
||||
connection conn{ioc};
|
||||
conn.next_layer().set_verify_mode(net::ssl::verify_peer);
|
||||
conn.next_layer().set_verify_callback(verify_certificate);
|
||||
|
||||
conn.async_exec(req, resp, [&](auto, auto) {
|
||||
// TODO: We should not need this cancel here because
|
||||
// reconnect was disabled.
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
|
||||
error_code ec2;
|
||||
conn.async_run(cfg, {}, [&](auto ec) {
|
||||
ec2 = ec;
|
||||
});
|
||||
|
||||
ioc.run();
|
||||
|
||||
BOOST_TEST(!!ec2);
|
||||
}
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
using boost::redis::request;
|
||||
using boost::redis::config;
|
||||
using boost::redis::detail::push_hello;
|
||||
using boost::redis::response;
|
||||
using boost::redis::adapter::adapt2;
|
||||
using boost::redis::adapter::result;
|
||||
using boost::redis::resp3::detail::deserialize;
|
||||
using boost::redis::ignore_t;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(low_level_sync_sans_io)
|
||||
{
|
||||
@@ -88,3 +90,113 @@ BOOST_AUTO_TEST_CASE(config_to_hello_cmd_auth)
|
||||
std::string_view const expected = "*5\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$3\r\nfoo\r\n$3\r\nbar\r\n";
|
||||
BOOST_CHECK_EQUAL(req.payload(), expected);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(issue_210_empty_set)
|
||||
{
|
||||
try {
|
||||
result<
|
||||
std::tuple<
|
||||
result<int>,
|
||||
result<std::vector<std::string>>,
|
||||
result<std::string>,
|
||||
result<int>
|
||||
>
|
||||
> resp;
|
||||
|
||||
char const* wire = "*4\r\n:1\r\n~0\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n";
|
||||
|
||||
deserialize(wire, adapt2(resp));
|
||||
|
||||
BOOST_CHECK_EQUAL(std::get<0>(resp.value()).value(), 1);
|
||||
BOOST_CHECK(std::get<1>(resp.value()).value().empty());
|
||||
BOOST_CHECK_EQUAL(std::get<2>(resp.value()).value(), "this_should_not_be_in_set");
|
||||
BOOST_CHECK_EQUAL(std::get<3>(resp.value()).value(), 2);
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_one)
|
||||
{
|
||||
try {
|
||||
result<
|
||||
std::tuple<
|
||||
result<int>,
|
||||
result<std::vector<std::string>>,
|
||||
result<std::string>,
|
||||
result<int>
|
||||
>
|
||||
> resp;
|
||||
|
||||
char const* wire = "*4\r\n:1\r\n~1\r\n$3\r\nfoo\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n";
|
||||
|
||||
deserialize(wire, adapt2(resp));
|
||||
|
||||
BOOST_CHECK_EQUAL(std::get<0>(resp.value()).value(), 1);
|
||||
BOOST_CHECK_EQUAL(std::get<1>(resp.value()).value().size(), 1);
|
||||
BOOST_CHECK_EQUAL(std::get<1>(resp.value()).value().at(0), std::string{"foo"});
|
||||
BOOST_CHECK_EQUAL(std::get<2>(resp.value()).value(), "this_should_not_be_in_set");
|
||||
BOOST_CHECK_EQUAL(std::get<3>(resp.value()).value(), 2);
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_two)
|
||||
{
|
||||
try {
|
||||
result<
|
||||
std::tuple<
|
||||
result<int>,
|
||||
result<std::vector<std::string>>,
|
||||
result<std::string>,
|
||||
result<int>
|
||||
>
|
||||
> resp;
|
||||
|
||||
char const* wire = "*4\r\n:1\r\n~2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n";
|
||||
|
||||
deserialize(wire, adapt2(resp));
|
||||
|
||||
BOOST_CHECK_EQUAL(std::get<0>(resp.value()).value(), 1);
|
||||
BOOST_CHECK_EQUAL(std::get<1>(resp.value()).value().at(0), std::string{"foo"});
|
||||
BOOST_CHECK_EQUAL(std::get<1>(resp.value()).value().at(1), std::string{"bar"});
|
||||
BOOST_CHECK_EQUAL(std::get<2>(resp.value()).value(), "this_should_not_be_in_set");
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(issue_210_no_nested)
|
||||
{
|
||||
try {
|
||||
result<
|
||||
std::tuple<
|
||||
result<int>,
|
||||
result<std::string>,
|
||||
result<std::string>,
|
||||
result<std::string>
|
||||
>
|
||||
> resp;
|
||||
|
||||
char const* wire = "*4\r\n:1\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$25\r\nthis_should_not_be_in_set\r\n";
|
||||
|
||||
deserialize(wire, adapt2(resp));
|
||||
|
||||
BOOST_CHECK_EQUAL(std::get<0>(resp.value()).value(), 1);
|
||||
BOOST_CHECK_EQUAL(std::get<1>(resp.value()).value(), std::string{"foo"});
|
||||
BOOST_CHECK_EQUAL(std::get<2>(resp.value()).value(), std::string{"bar"});
|
||||
BOOST_CHECK_EQUAL(std::get<3>(resp.value()).value(), "this_should_not_be_in_set");
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
24
tools/docker-compose.yml
Normal file
24
tools/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
command: [
|
||||
"redis-server",
|
||||
"--tls-port", "6380",
|
||||
"--tls-cert-file", "/tls/server.crt",
|
||||
"--tls-key-file", "/tls/server-key.key",
|
||||
"--tls-ca-cert-file", "/tls/ca.crt",
|
||||
"--tls-auth-clients", "no",
|
||||
]
|
||||
volumes:
|
||||
- ./tls:/tls
|
||||
ports:
|
||||
- 6379:6379
|
||||
- 6380:6380
|
||||
builder:
|
||||
image: ubuntu:22.04
|
||||
container_name: builder
|
||||
tty: true
|
||||
environment:
|
||||
- BOOST_REDIS_TEST_SERVER=redis
|
||||
volumes:
|
||||
- ../:/boost-redis
|
||||
31
tools/tls/ca.crt
Executable file
31
tools/tls/ca.crt
Executable file
@@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
2XVYrfsnPHX0CsPDIy7L
|
||||
-----END CERTIFICATE-----
|
||||
51
tools/tls/ca.key
Executable file
51
tools/tls/ca.key
Executable file
@@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
tools/tls/server-key.key
Executable file
27
tools/tls/server-key.key
Executable file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAxDwCrIWM9cqHpT/2MKnQ2DsdChUOkKkwsw8HA/eSrLm+LqGl
|
||||
IFcj19j9PP68O5Nd1N4W1SFHz2HiaZarTtqCBo+laaXaxoAjOA7BiPP6Rce8t+gb
|
||||
mJ4EvjwEn+vIg6eyM8fFRyoqUSIh5ybJ7Cq7Un0lUDqhbt7VrvBWZQcyh6z9F1Z1
|
||||
NXiexKdYH/ewpGrA2FeM9lv3zVUiJKO0mM2t86u/TPw9zsgc3sQAwd1I+dZv+jbA
|
||||
qfjzrfNIk0htRKgMKTuIOwZlFW+WLhqx9dDfMrAD30vSv0jXyPa1tYo46hBIwefr
|
||||
0PcLpw3HNwgrizDOShhS9V2pTtO9gVM+Xxwn/wIDAQABAoIBAA50zU2gWQ4SaYPG
|
||||
/n//Qp9rW2xOuM/3ZtsKFF46cte+p0AQMHX9dWqFVcKUkZFh/ducsNnqpbulXmSg
|
||||
8OXSOxn4oxrxWPien/mVPLS2JI3XdROnScEogvjwuvZ9DDyGsh4WbXYcqRlpBk5d
|
||||
ESsQytP83C7Y4uOkDuHgWrz+lr5f4tbwxEvSI4AQ0ucksV/BNupwGaz0VTOqWTuN
|
||||
cZSRILcDnkldFXprX//QFUxGYh3sLQpigja9v2ES72yEuS3VDaZvc/2CQL51vYn/
|
||||
wfnKSUPSiX1p/wtwJXwTUzFIKYsfi/b3TqWCt+ajqSY4hUqHn/xf+m27sTV2thbC
|
||||
w3Hh8yECgYEA+4bvSk8uRFy1Yg+G36sSKp/tBAmrGE3vFfhePTC7XFsUQstQE9pP
|
||||
1IZJY+SxKfj8snben6MtSjNu0ntte55Jnhq0M2UsmsEzR0rN43P1u8iJAUe1vp4t
|
||||
vptJCUDDj+8WppzzyzbRESoFYfJ5o9JMu0h12Sx/U1bgnp75NhRi2y0CgYEAx7lb
|
||||
wT6a/FSgkisvrOTY+bY9xsz7aqH+fz2FdZpoJlIofbofmwdNGU2oXdo4S71ITB4y
|
||||
xLLOuyUhz2okBu+iwJbZEmX1CALe/GV1UYAlNcFVmggGQM44G0mh1chgR6qIbCOB
|
||||
7yPwPkmERVqGtV+MxPR8ku7u73b/3sDLmVTUm1sCgYB46RR+lDGZizdmPDCJtKK2
|
||||
+snk9wDYXh5gYVRr9dEbRG0o7rM/1+IoN6Vv7696jcZrw9igxMAwuyi65bprglvB
|
||||
NPUK/8fBXL5ZtwviGww1iODTTLWBPGihB+TEHe3kcvpgfXJ0bZVyutB7lSQELEPW
|
||||
g66jB1DtrwWrOqBx7rrWwQKBgQCMqdqanoovfzbb23inb0H1lUmrE0FbV55TZTPy
|
||||
oP4LRz/nVMffuuOtF4mmGAQgK76YhYhCCqEZI0zNtTaMgAgDVfqqP460xrjf0GEx
|
||||
Nmx+kJzGcDJfQB458cD+PTK6JrwQVW20zH3ukH6NDfXkFdih+oMmRQuZMhmBfA2o
|
||||
/xsCEwKBgQDTbsTzHrBSvQtxEB8QYFnEBeRcvNHrtvVrWGJnYPbmvAAxJgzC83tr
|
||||
u8ST6sPUTe7rpdxQUzwxThkkbovsPqC+40wwclOMltZSyVwNlREYUl8iQUZKX0ZM
|
||||
0sdNP0Z/UMCDa08yz18qbMtehQrIS2o6lwzIgM/NS2IlkmN7Hbx5Mw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
23
tools/tls/server.crt
Executable file
23
tools/tls/server.crt
Executable file
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID3DCCAcQCFENgZw0c9P89NpIf0+jFhIYpQzi3MA0GCSqGSIb3DQEBCwUAMDUx
|
||||
EzARBgNVBAoMClJlZGlzIFRlc3QxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhv
|
||||
cml0eTAeFw0yNDAzMzExNDI1MzlaFw0yNDA0MzAxNDI1MzlaMCAxDjAMBgNVBAoM
|
||||
BXJlZGlzMQ4wDAYDVQQDDAVyZWRpczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||
AQoCggEBAMQ8AqyFjPXKh6U/9jCp0Ng7HQoVDpCpMLMPBwP3kqy5vi6hpSBXI9fY
|
||||
/Tz+vDuTXdTeFtUhR89h4mmWq07aggaPpWml2saAIzgOwYjz+kXHvLfoG5ieBL48
|
||||
BJ/ryIOnsjPHxUcqKlEiIecmyewqu1J9JVA6oW7e1a7wVmUHMoes/RdWdTV4nsSn
|
||||
WB/3sKRqwNhXjPZb981VIiSjtJjNrfOrv0z8Pc7IHN7EAMHdSPnWb/o2wKn4863z
|
||||
SJNIbUSoDCk7iDsGZRVvli4asfXQ3zKwA99L0r9I18j2tbWKOOoQSMHn69D3C6cN
|
||||
xzcIK4swzkoYUvVdqU7TvYFTPl8cJ/8CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||
le50e2bw+Vc0kN9PUs13p/2JAEy1LlS1ehyBx+O1kFnkQRk6YMNOFDcrL9+65pWq
|
||||
La1Me+OozgUuBErhbI7eElFwb5CJ1Jzm2UGmV7+9AcC0eU4qdY0tR/gOpPtaKVly
|
||||
+Sqq44P2lZSBssjr1KLuk/pEGd4Q//G8EB31TumLRTL+fbzSqQ+m/5mukMdCSUpd
|
||||
lxeCzr1n0p9/29eZ2+qX7moQUvZ9nsHwtKyxMsuDSJTiHysC5TfGWrbstpFULM7M
|
||||
bqKZiA+WLtDCvh8xa49+AeDbbZSQahEVm09I9ww3XBFCQNTfgmnscMvscpgR5xqj
|
||||
A3AceHjhO7T8oAdNF8UoHprIpLl7tw/RZwqYeLq1IabwUN+t+Patt4HZIRgWeiKc
|
||||
IlzPICI8n3OhHBRTl0GhPL6G85Z56WhI6wxbTm9HmVRYK1RFbPpIxQ7Mi+BQG5wC
|
||||
oXwAAQeDyF0au9zByTU6bjYqXMGgaBRVzSh1VaQ675yqT3+CJFAMPqkGdTmgwOBy
|
||||
Ge7T697+gMR37/xPqY7TnDucJ2x33dVmIVkwpNapZjM+TThFYihV0Dl9wxCr/Kuz
|
||||
MTIXvzC6bEEu24FsAWttt9vPV+yrIpidLZ0AKo6zYO6azU2Uui9whDps6Rzi1g6f
|
||||
WVot3B9KCQTPtc80ayJiQQEnR1n13wlfInaD8cxqoic=
|
||||
-----END CERTIFICATE-----
|
||||
Reference in New Issue
Block a user