用于单元测试的模拟 AsyncReadStream 增强

问题描述 投票:0回答:1

我面临着一种情况,我们在代表 HTTP 会话的类内部使用

http::async_read(...)
http::async_write(...)
。但是,如果我们想对此类进行单元测试,我们不希望打开网络连接,而是使用端口和套接字来侦听并相应地通过
acceptor
接受第一个调用。

相反,我希望通过另一个

socket
“伪造”
AsyncReadStream
的行为。我已经考虑过自己编写,但这似乎是一项艰巨的任务,而且搜索并没有显示出太多帮助。

为了进行单元测试,可以简单地流式传输

AsyncReadStream
请求并随后将响应放入其中的
HTTP
示例是什么?如果没有,是否有某种模板,我可以用它来编写一个具有非常少的“假”功能的准系统?

c++ sockets asynchronous boost googletest
1个回答
0
投票

对 AsyncReadStream/AsyncWriteStream 概念进行建模几乎是微不足道的

唯一的复杂性是使用 CompletionToken 模式启动异步操作:

例如:

住在Coliru

#include <boost/asio.hpp>
#include <iostream>
#include <fmt/ranges.h>
namespace asio = boost::asio;
using namespace std::literals;

struct MockStream {
    using error_code    = boost::system::error_code;
    using executor_type = asio::any_io_executor;
    MockStream(asio::any_io_executor ex) : _ex(std::move(ex)) {}
    executor_type get_executor() const { return _ex; }

    template <typename Token> auto async_write_some(asio::const_buffer buf, Token&& token) {
        return asio::async_initiate<Token, void(error_code, size_t)>( //
            [fallback = _ex](auto h, auto buf) {
                auto ex = asio::get_associated_executor(h, fallback);
                asio::dispatch(ex, [=, h = std::move(h)]() mutable {
                    fmt::print("Simulated write of {} completed\n", buf.size());
                    std::move(h)({}, asio::buffer_size(buf));
                });
            },
            token, buf);
    }

    template <typename Token> auto async_read_some(asio::mutable_buffer buf, Token&& token) {
        return asio::async_initiate<Token, void(error_code, size_t)>( //
            [fallback = _ex, ch = mock_data++](auto h, auto buf) {
                auto ex = asio::get_associated_executor(h, fallback);

                std::fill(asio::buffers_begin(buf), asio::buffers_end(buf), ch);

                asio::dispatch(ex, [=, h = std::move(h)]() mutable {
                    fmt::print("Simulated read of {} completed\n", buf.size());
                    std::move(h)({}, asio::buffer_size(buf));
                });
            },
            token, buf);
    }

    asio::any_io_executor _ex;
    char                  mock_data = 'a';
};

int main() {
    asio::io_context ioc;

    MockStream stream(make_strand(ioc));

    asio::async_write(stream, asio::buffer("Hello world"sv), [](auto ec, size_t n) {
        fmt::print("Write completed with {} and {} bytes written\n", ec.message(), n);
    });

    std::array<char, 10> buf;
    asio::async_read(stream, asio::buffer(buf), [&buf](auto ec, size_t n) {
        fmt::print("Read completed with {} and {} bytes read: {}\n", ec.message(), n, buf);
    });

    asio::streambuf sbuf;
    asio::async_read_until(stream, sbuf, "d", [&sbuf](auto ec, size_t n) {
        fmt::print("Read-until completed with {} and {} bytes read\n", ec.message(), n);
        std::cout << "Streambuf: " << &sbuf << std::endl;
    });

    ioc.run();
}

印刷

Simulated write of 11 completed
Write completed with Success and 11 bytes written
Simulated read of 10 completed
Read completed with Success and 10 bytes read: ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']
Simulated read of 512 completed
Simulated read of 512 completed
Simulated read of 512 completed
Read-until completed with Success and 1025 bytes read
Streambuf: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

链接

这里有类似的实现:

© www.soinside.com 2019 - 2024. All rights reserved.