<|start_filename|>test/beast/http/buffer_body.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/http/buffer_body.hpp>

#include <boost/beast/core/flat_buffer.hpp>
#include <boost/beast/core/ostream.hpp>
#include <boost/beast/http/parser.hpp>
#include <boost/beast/http/read.hpp>

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>

namespace boost {
namespace beast {
namespace http {

class buffer_body_test : public beast::unit_test::suite
{
public:
    void
    testIssue1717()
    {
        net::io_context ioc;
        test::stream ts{ioc};
        ostream(ts.buffer()) <<
            "HTTP/1.1 200 OK\r\n"
            "Content-Length:3\r\n"
            "\r\n"
            "1.0";
        error_code ec;
        flat_buffer fb;
        response_parser<buffer_body> p;
        char buf[256];
        p.get().body().data = buf;
        p.get().body().size = sizeof(buf);
        read_header(ts, fb, p, ec);
        auto const bytes_transferred =
            read(ts, fb, p, ec);
        boost::ignore_unused(bytes_transferred);
        BEAST_EXPECTS(! ec, ec.message());

        // VFALCO What should the read algorithms return?
        //BEAST_EXPECT(bytes_transferred == 3);
    }

    void
    run() override
    {
        testIssue1717();
    }
};

BEAST_DEFINE_TESTSUITE(beast,http,buffer_body);

} // http
} // beast
} // boost


<|start_filename|>test/doc/websocket_7_teardown.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL> dot <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#include <boost/config.hpp>

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4459) // declaration hides global declaration
#endif

#include <boost/beast/_experimental/unit_test/suite.hpp>

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

namespace {

#include "websocket_common.ipp"

//[code_websocket_7_1

struct custom_stream;

void
teardown(
    role_type role,
    custom_stream& stream,
    error_code& ec);

template<class TeardownHandler>
void
async_teardown(
    role_type role,
    custom_stream& stream,
    TeardownHandler&& handler);

//]

void
teardown(
    role_type,
    custom_stream&,
    error_code&)
{
}

//[code_websocket_7_2

template <class NextLayer>
struct custom_wrapper
{
    NextLayer next_layer;

    template<class... Args>
    explicit
    custom_wrapper(Args&&... args)
        : next_layer(std::forward<Args>(args)...)
    {
    }

    friend
    void
    teardown(
        role_type role,
        custom_wrapper& stream,
        error_code& ec)
    {
        using boost::beast::websocket::teardown;
        teardown(role, stream.next_layer, ec);
    }

    template<class TeardownHandler>
    friend
    void
    async_teardown(
        role_type role,
        custom_wrapper& stream,
        TeardownHandler&& handler)
    {
        using boost::beast::websocket::async_teardown;
        async_teardown(role, stream.next_layer, std::forward<TeardownHandler>(handler));
    }
};

//]

void
snippets()
{
    //stream<tcp_stream> ws(ioc);

    {
    //[code_websocket_7_3

    //]
    }
}

struct websocket_7_test
    : public boost::beast::unit_test::suite
{
    void
    run() override
    {
        BEAST_EXPECT(&snippets);
        BEAST_EXPECT(static_cast<void(*)(
            role_type, custom_stream&, error_code&)>(
                &teardown));
    }
};

BEAST_DEFINE_TESTSUITE(beast,doc,websocket_7);

} // (anon)

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif


<|start_filename|>.dockers/windows-vs-32/Dockerfile<|end_filename|>
# escape=`

# Use the latest Windows Server Core image with .NET Framework 4.8.
FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019

# Restore the default Windows shell for correct batch processing.
SHELL ["cmd", "/S", "/C"]

# Download the Build Tools bootstrapper.
ADD https://aka.ms/vs/16/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe

RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache `
    --installPath C:\BuildTools `
    --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended `
 || IF "%ERRORLEVEL%"=="3010" EXIT 0

# --------------
# Boost Section
# --------------

WORKDIR C:\
RUN powershell -Command iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
RUN powershell -Command Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
RUN choco install -y git.install
RUN choco install -y python --version 3.8.3

# chocolaty install of openssl 1.1.1
# RUN choco install -y openssl --x86 --version 1.1.1.700
# RUN mklink /D "OpenSSL" "Program Files (x86)\\OpenSSL-Win32"

# scoop install of openssl 1.0.2u
# RUN powershell -Command scoop install openssl@1.0.2u -a 32bit -g
# RUN mklink /D "OpenSSL" "ProgramData\\scoop\\apps\\openssl\\current"

# scoop install of openssl 1.1.1g
RUN powershell -Command scoop install openssl@1.1.1g -a 32bit -g
RUN mklink /D "OpenSSL" "ProgramData\\scoop\\apps\\openssl\\current"

RUN mkdir C:\devel

WORKDIR C:\devel
RUN git.exe clone -b develop https://github.com/boostorg/boost.git

WORKDIR C:\devel\boost
RUN git.exe submodule update --init --recursive
COPY . C:\devel\boost\libs\beast\
COPY ".dockers\\windows-vs-32\\user-config.jam" C:\devel\boost\
COPY ".dockers\\windows-vs-32\\tests.bat" C:\devel\boost\

RUN C:\\BuildTools\\VC\\Auxiliary\\Build\\vcvars32.bat && bootstrap.bat
RUN C:\\BuildTools\\VC\\Auxiliary\\Build\\vcvars32.bat && b2 variant=release cxxstd=latest headers

# Choose one of the following two lines. The second will succeed regardless of the test results, if you'd prefer the build to complete.
# RUN C:\\BuildTools\\VC\\Auxiliary\\Build\\vcvars32.bat && set OPENSSL_ROOT=C:/OpenSSL&& tests.bat
RUN C:\\BuildTools\\VC\\Auxiliary\\Build\\vcvars32.bat && set OPENSSL_ROOT=C:/OpenSSL&& tests.bat || ver>nul

ENTRYPOINT ["C:\\BuildTools\\VC\\Auxiliary\\Build\\vcvars32.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]


<|start_filename|>test/doc/websocket_3_decorator.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#include <boost/config.hpp>

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4459) // declaration hides global declaration
#endif

#include <boost/beast/_experimental/unit_test/suite.hpp>

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

namespace {

#include "websocket_common.ipp"

//[code_websocket_3_1

void set_user_agent(request_type& req)
{
    // Set the User-Agent on the request
    req.set(http::field::user_agent, "My User Agent");
}

//]

void
snippets()
{
    {
    //[code_websocket_3_2

        stream<tcp_stream> ws(ioc);

        // The function `set_user_agent` will be invoked with
        // every upgrade request before it is sent by the stream.

        ws.set_option(stream_base::decorator(&set_user_agent));

    //]
    }

    stream<tcp_stream> ws(ioc);
    
    {
    //[code_websocket_3_3

        struct set_server
        {
            void operator()(response_type& res)
            {
                // Set the Server field on the response
                res.set(http::field::user_agent, "My Server");
            }
        };

        ws.set_option(stream_base::decorator(set_server{}));

    //]
    }

    {
    //[code_websocket_3_4

        ws.set_option(stream_base::decorator(
            [](response_type& res)
            {
                // Set the Server field on the response
                res.set(http::field::user_agent, "My Server");
            }));

    //]
    }

    {
    //[code_websocket_3_5

        struct set_message_fields
        {
            void operator()(request_type& req)
            {
                // Set the User-Agent on the request
                req.set(http::field::user_agent, "My User Agent");
            }

            void operator()(response_type& res)
            {
                // Set the Server field on the response
                res.set(http::field::user_agent, "My Server");
            }
        };

        ws.set_option(stream_base::decorator(set_message_fields{}));

    //]
    }

    {
    //[code_websocket_3_6
    
        struct set_auth
        {
            std::unique_ptr<std::string> key;

            void operator()(request_type& req)
            {
                // Set the authorization field
                req.set(http::field::authorization, *key);
            }
        };

        // The stream takes ownership of the decorator object
        ws.set_option(stream_base::decorator(
            set_auth{boost::make_unique<std::string>("Basic QWxhZGRpbjpPcGVuU2VzYW1l")}));
    
    //]
    }
}

struct websocket_3_test
    : public boost::beast::unit_test::suite
{
    void
    run() override
    {
        BEAST_EXPECT(&snippets);
    }
};

BEAST_DEFINE_TESTSUITE(beast,doc,websocket_3);

} // (anon)

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif


<|start_filename|>test/doc/core_4_layers.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#include "snippets.hpp"

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/websocket.hpp>
#include <cstdlib>
#include <utility>

namespace boost {
namespace beast {

void
core_4_layers_snippets()
{
    #include "snippets.ipp"
    {
    //[code_core_4_layers_1

        net::ssl::stream<net::ip::tcp::socket> ss(ioc, ctx);

    //]
    }
    {
    //[code_core_4_layers_2

        websocket::stream<net::ip::tcp::socket> ws(ioc);

    //]
    }
    //[code_core_4_layers_3

        websocket::stream<net::ssl::stream<net::ip::tcp::socket>> ws(ioc, ctx);

    //]
}

//[code_core_4_layers_4

// Set non-blocking mode on a stack of stream
// layers with a regular socket at the lowest layer.
template <class Stream>
void set_non_blocking (Stream& stream)
{
    error_code ec;
    // A compile error here means your lowest layer is not the right type!
    get_lowest_layer(stream).non_blocking(true, ec);
    if(ec)
        throw system_error{ec};
}

//]

//[code_core_4_layers_5

// A layered stream which counts the bytes read and bytes written on the next layer
template <class NextLayer>
class counted_stream
{
    NextLayer next_layer_;              // Reads and writes are passed through to this
    std::size_t bytes_read_ = 0;        // Holds the total bytes read
    std::size_t bytes_written_ = 0;     // Holds the total bytes written

    // This is the "initiation" object passed to async_initiate to start the operation
    struct run_read_op
    {
        template<
            class ReadHandler,
            class MutableBufferSequence>
        void
        operator()(
            ReadHandler&& handler,
            counted_stream* stream,
            MutableBufferSequence const& buffers)
        {
            using handler_type = typename std::decay<ReadHandler>::type;

            // async_base handles all of the composed operation boilerplate for us
            using base = async_base<
                handler_type, beast::executor_type<NextLayer>>;

            // Our composed operation is implemented as a completion handler object
            struct op : base
            {
                counted_stream& stream_;

                op( counted_stream& stream,
                    handler_type&& handler,
                    MutableBufferSequence const& buffers)
                    : base(std::move(handler), stream.get_executor())
                    , stream_(stream)
                {
                    // Start the asynchronous operation
                    stream_.next_layer().async_read_some(buffers, std::move(*this));
                }

                void operator()(error_code ec, std::size_t bytes_transferred)
                {
                    // Count the bytes transferred towards the total
                    stream_.bytes_read_ += bytes_transferred;

                    this->complete_now(ec, bytes_transferred);
                }
            };

            op(*stream, std::forward<ReadHandler>(handler), buffers);
        }
    };

    // This is the "initiation" object passed to async_initiate to start the operation
    struct run_write_op
    {
        template<
            class WriteHandler,
            class ConstBufferSequence>
        void
        operator()(
            WriteHandler&& handler,
            counted_stream* stream,
            ConstBufferSequence const& buffers)
        {
            using handler_type = typename std::decay<WriteHandler>::type;

            // async_base handles all of the composed operation boilerplate for us
            using base = async_base<
                handler_type, beast::executor_type<NextLayer>>;

            // Our composed operation is implemented as a completion handler object
            struct op : base
            {
                counted_stream& stream_;

                op( counted_stream& stream,
                    handler_type&& handler,
                    ConstBufferSequence const& buffers)
                    : base(std::move(handler), stream.get_executor())
                    , stream_(stream)
                {
                    // Start the asynchronous operation
                    stream_.next_layer().async_write_some(buffers, std::move(*this));
                }

                void operator()(error_code ec, std::size_t bytes_transferred)
                {
                    // Count the bytes transferred towards the total
                    stream_.bytes_written_ += bytes_transferred;

                    this->complete_now(ec, bytes_transferred);
                }
            };

            op(*stream, std::forward<WriteHandler>(handler), buffers);
        }
    };

public:
    /// The type of executor used by this stream
    using executor_type = beast::executor_type<NextLayer>;

    /// Constructor
    template <class... Args>
    explicit
    counted_stream(Args&&... args)
        : next_layer_(std::forward<Args>(args)...)
    {
    }

    /// Returns an instance of the executor used to submit completion handlers
    executor_type get_executor() noexcept
    {
        return next_layer_.get_executor();
    }

    /// Returns a reference to the next layer
    NextLayer& next_layer() noexcept
    {
        return next_layer_;
    }

    /// Returns a reference to the next layer
    NextLayer const& next_layer() const noexcept
    {
        return next_layer_;
    }

    /// Returns the total number of bytes read since the stream was constructed
    std::size_t bytes_read() const noexcept
    {
        return bytes_read_;
    }

    /// Returns the total number of bytes written since the stream was constructed
    std::size_t bytes_written() const noexcept
    {
        return bytes_written_;
    }

    /// Read some data from the stream
    template <class MutableBufferSequence>
    std::size_t read_some(MutableBufferSequence const& buffers)
    {
        auto const bytes_transferred = next_layer_.read_some(buffers);
        bytes_read_ += bytes_transferred;
        return bytes_transferred;
    }

    /// Read some data from the stream
    template <class MutableBufferSequence>
    std::size_t read_some(MutableBufferSequence const& buffers, error_code& ec)
    {
        auto const bytes_transferred = next_layer_.read_some(buffers, ec);
        bytes_read_ += bytes_transferred;
        return bytes_transferred;
    }

    /// Write some data to the stream
    template <class ConstBufferSequence>
    std::size_t write_some(ConstBufferSequence const& buffers)
    {
        auto const bytes_transferred = next_layer_.write_some(buffers);
        bytes_written_ += bytes_transferred;
        return bytes_transferred;
    }

    /// Write some data to the stream
    template <class ConstBufferSequence>
    std::size_t write_some(ConstBufferSequence const& buffers, error_code& ec)
    {
        auto const bytes_transferred = next_layer_.write_some(buffers, ec);
        bytes_written_ += bytes_transferred;
        return bytes_transferred;
    }

    /// Read some data from the stream asynchronously
    template<
        class MutableBufferSequence,
        class ReadHandler =
            net::default_completion_token_t<executor_type>>
    BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
    async_read_some(
        MutableBufferSequence const& buffers,
        ReadHandler&& handler =
            net::default_completion_token_t<executor_type>{})
    {
        return net::async_initiate<
            ReadHandler,
            void(error_code, std::size_t)>(
                run_read_op{},
                handler,
                this,
                buffers);
    }

    /// Write some data to the stream asynchronously
    template<
        class ConstBufferSequence,
        class WriteHandler =
            net::default_completion_token_t<executor_type>>
    BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
    async_write_some(
        ConstBufferSequence const& buffers,
        WriteHandler&& handler =
            net::default_completion_token_t<
                executor_type>{})
    {
        return net::async_initiate<
            WriteHandler,
            void(error_code, std::size_t)>(
                run_write_op{},
                handler,
                this,
                buffers);
    }
};
//]

template class counted_stream<test::stream>;

BOOST_STATIC_ASSERT(is_sync_read_stream<counted_stream<test::stream>>::value);
BOOST_STATIC_ASSERT(is_sync_write_stream<counted_stream<test::stream>>::value);
BOOST_STATIC_ASSERT(is_async_read_stream<counted_stream<test::stream>>::value);
BOOST_STATIC_ASSERT(is_async_write_stream<counted_stream<test::stream>>::value);

struct core_4_layers_test
    : public beast::unit_test::suite
{
    struct handler
    {
        void operator()(error_code, std::size_t)
        {
        }
    };

    void
    run() override
    {
        BEAST_EXPECT(&core_4_layers_snippets);
        BEAST_EXPECT(&set_non_blocking<net::ip::tcp::socket>);
    }
};

BEAST_DEFINE_TESTSUITE(beast,doc,core_4_layers);

} // beast
} // boost


<|start_filename|>test/beast/core/detect_ssl.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/core/detect_ssl.hpp>

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/beast/_experimental/test/handler.hpp>
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/core/exchange.hpp>
#if BOOST_ASIO_HAS_CO_AWAIT
#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/use_awaitable.hpp>
#endif
namespace boost {
namespace beast {

class detect_ssl_test : public unit_test::suite
{
public:
    void
    testDetect()
    {
        auto const yes =
            [](int n, string_view s)
            {
                BEAST_EXPECT(detail::is_tls_client_hello(
                    net::const_buffer(s.data(), n)));
            };

        auto const no =
            [](int n, string_view s)
            {
                BEAST_EXPECT(! detail::is_tls_client_hello(
                    net::const_buffer(s.data(), n)));
            };

        auto const maybe =
            [](int n, string_view s)
            {
                BEAST_EXPECT(boost::indeterminate(
                    detail::is_tls_client_hello(
                        net::const_buffer(s.data(), n))));
            };

        maybe(  0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00");
        no   (  1, "\x01\x00\x00\x00\x00\x00\x00\x00\x00");
        maybe(  1, "\x16\x00\x00\x00\x00\x00\x00\x00\x00");
        maybe(  4, "\x16\x00\x00\x00\x00\x00\x00\x00\x00");
        no   (  5, "\x16\x00\x00\x00\x00\x00\x00\x00\x00");
        maybe(  5, "\x16\x00\x00\x01\x00\x00\x00\x00\x00");
        no   (  8, "\x16\x00\x00\x01\x00\x00\x00\x00\x00");
        maybe(  8, "\x16\x00\x00\x01\x00\x01\x00\x00\x00");
        no   (  9, "\x16\x00\x00\x01\x00\x01\x01\x00\x00");
        yes  (  9, "\x16\x00\x00\x01\x00\x01\x00\x00\x00");
    }

    void
    testRead()
    {
        net::io_context ioc;

        // true

        {
            error_code ec;
            flat_buffer b;
            test::stream s1(ioc);
            s1.append({"\x16\x00\x00\x01\x00\x01\x00\x00\x00", 9});
            auto result = detect_ssl(s1, b, ec);
            BEAST_EXPECT(result == true);
            BEAST_EXPECTS(! ec, ec.message());
        }

        // true

        {
            error_code ec;
            flat_buffer b;
            test::stream s1(ioc);
            auto s2 = test::connect(s1);
            s1.append({"\x16\x00\x00\x01\x00\x01\x00\x00\x00", 9});
            s2.close();
            auto result = detect_ssl(s1, b, ec);
            BEAST_EXPECT(result == true);
            BEAST_EXPECTS(! ec, ec.message());
        }

        // false

        {
            error_code ec;
            flat_buffer b;
            test::stream s1(ioc);
            s1.append({"\x16\x00\x00\x01\x00\x01\x01\x00\x00", 9});
            auto result = detect_ssl(s1, b, ec);
            BEAST_EXPECT(result == false);
            BEAST_EXPECTS(! ec, ec.message());
        }

        // eof
        {
            error_code ec;
            flat_buffer b;
            test::stream s1(ioc);
            auto s2 = test::connect(s1);
            s1.append({"\x16\x00\x00\x01\x00", 5});
            s2.close();
            auto result = detect_ssl(s1, b, ec);
            BEAST_EXPECT(result == false);
            BEAST_EXPECT(ec);
        }
    }

    void
    testAsyncRead()
    {
        net::io_context ioc;

        // true

        {
            flat_buffer b;
            test::stream s1(ioc);
            s1.append({"\x16\x00\x00\x01\x00\x01\x00\x00\x00", 9});
            async_detect_ssl(s1, b, test::success_handler());
            test::run(ioc);
        }

        // true

        {
            flat_buffer b;
            test::stream s1(ioc);
            auto s2 = test::connect(s1);
            s1.append({"\x16\x00\x00\x01\x00\x01\x00\x00\x00", 9});
            s2.close();
            async_detect_ssl(s1, b, test::success_handler());
            test::run(ioc);
        }

        // false

        {
            flat_buffer b;
            test::stream s1(ioc);
            s1.append({"\x16\x00\x00\x01\x00\x01\x01\x00\x00", 9});
            async_detect_ssl(s1, b, test::success_handler());
            test::run(ioc);
        }

        // eof
        {
            flat_buffer b;
            test::stream s1(ioc);
            auto s2 = test::connect(s1);
            s1.append({"\x16\x00\x00\x01\x00", 5});
            s2.close();
            async_detect_ssl(s1, b,
                test::fail_handler(net::error::eof));
            test::run(ioc);
        }
    }

#if BOOST_ASIO_HAS_CO_AWAIT
    void testAwaitableCompiles(test::stream& stream, flat_buffer& b)
    {
        static_assert(
            std::is_same_v<
                net::awaitable<bool>, decltype(
                async_detect_ssl(stream, b, net::use_awaitable))>);
    }
#endif

    void
    run() override
    {
        testDetect();
        testRead();
        testAsyncRead();
#if BOOST_ASIO_HAS_CO_AWAIT
        boost::ignore_unused(&detect_ssl_test::testAwaitableCompiles);
#endif
    }
};

BEAST_DEFINE_TESTSUITE(beast,core,detect_ssl);

} // beast
} // boost


<|start_filename|>test/beast/core/test_buffer.hpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> dot <EMAIL> at g<EMAIL> dot <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#ifndef BOOST_BEAST_TEST_BUFFER_HPP
#define BOOST_BEAST_TEST_BUFFER_HPP

#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/assert.hpp>
#include <algorithm>
#include <string>
#include <type_traits>

namespace boost {
namespace beast {

/** A MutableBufferSequence for tests, where length is always 3.
*/
class buffers_triple
{
    net::mutable_buffer b_[3];

public:
    using value_type = net::mutable_buffer;
    using const_iterator = net::mutable_buffer const*;

    buffers_triple(
        buffers_triple const&) = default;

    buffers_triple& operator=(
        buffers_triple const&) = default;

    buffers_triple(char* data, std::size_t size)
    {
        b_[0] = {data, size/6};
        data += b_[0].size();
        size -= b_[0].size();
            
        b_[1] = {data, 2*size/5};
        data += b_[1].size();
        size -= b_[1].size();

        b_[2] = {data, size};

        BOOST_ASSERT(b_[0].size() > 0);
        BOOST_ASSERT(b_[1].size() > 0);
        BOOST_ASSERT(b_[2].size() > 0);
    }

    bool
    operator==(buffers_triple const& rhs) const noexcept
    {
        return
            b_[0].data() == rhs.b_[0].data() &&
            b_[0].size() == rhs.b_[0].size() &&
            b_[1].data() == rhs.b_[1].data() &&
            b_[1].size() == rhs.b_[1].size() &&
            b_[2].data() == rhs.b_[2].data() &&
            b_[2].size() == rhs.b_[2].size();
    }

    bool
    operator!=(buffers_triple const& rhs) const noexcept
    {
        return !(*this == rhs);
    }

    const_iterator
    begin() const noexcept
    {
        return &b_[0];
    }

    const_iterator
    end() const noexcept
    {
        return &b_[3];
    }
};

template<class ConstBufferSequence>
std::size_t
buffers_length(
    ConstBufferSequence const& buffers)
{
    return std::distance(
        net::buffer_sequence_begin(buffers),
        net::buffer_sequence_end(buffers));
}

//------------------------------------------------------------------------------

namespace detail {

template<class MutableBufferSequence>
void test_mutable_buffers(
    MutableBufferSequence const&,
    net::const_buffer)
{
}

template<class MutableBufferSequence>
void test_mutable_buffers(
    MutableBufferSequence const& b,
    net::mutable_buffer)
{
    string_view src = "Hello, world!";
    BOOST_ASSERT(buffer_bytes(b) <= src.size());
    if(src.size() > buffer_bytes(b))
        src = {src.data(), buffer_bytes(b)};
    net::buffer_copy(b, net::const_buffer(
        src.data(), src.size()));
    BEAST_EXPECT(beast::buffers_to_string(b) == src);
}

} // detail

/** Test an instance of a constant or mutable buffer sequence.
*/
template<class ConstBufferSequence>
void
test_buffer_sequence(
    ConstBufferSequence const& buffers)
{
    BOOST_STATIC_ASSERT(
        net::is_const_buffer_sequence<
            ConstBufferSequence>::value);

    using iterator = decltype(
        net::buffer_sequence_begin(buffers));
    BEAST_EXPECT(sizeof(iterator) > 0);

    auto const size = buffer_bytes(buffers);
    BEAST_EXPECT(size > 0 );

    // begin, end
    auto const length = std::distance(
        net::buffer_sequence_begin(buffers),
        net::buffer_sequence_end(buffers));
    BEAST_EXPECT(length > 0);
    BEAST_EXPECT(
        net::buffer_sequence_begin(buffers) !=
        net::buffer_sequence_end(buffers));

    // copy construction
    ConstBufferSequence b1(buffers);
    BEAST_EXPECT(buffer_bytes(b1) == size);

    // copy assignment
    ConstBufferSequence b2(buffers);
    b2 = b1;
    BEAST_EXPECT(buffer_bytes(b2) == size);

    // iterators
    {
        iterator it1{};
        iterator it2{};
        iterator it3 =
            net::buffer_sequence_begin(buffers);
        iterator it4 =
            net::buffer_sequence_end(buffers);
        BEAST_EXPECT(it1 == it2);
        BEAST_EXPECT(it1 != it3);
        BEAST_EXPECT(it3 != it1);
        BEAST_EXPECT(it1 != it4);
        BEAST_EXPECT(it4 != it1);
    }

    // bidirectional
    {
        auto const first =
            net::buffer_sequence_begin(buffers);
        auto const last =
            net::buffer_sequence_end(buffers);
        std::size_t n, m;
        iterator it;

        // pre-increment
        m = 0;
        n = length;
        for(it = first; n--; ++it)
            m += buffer_bytes(*it);
        BEAST_EXPECT(it == last);
        BEAST_EXPECT(m == size);

        // post-increment
        m = 0;
        n = length;
        for(it = first; n--;)
            m += buffer_bytes(*it++);
        BEAST_EXPECT(it == last);
        BEAST_EXPECT(m == size);

        // pre-decrement
        m = 0;
        n = length;
        for(it = last; n--;)
            m += buffer_bytes(*--it);
        BEAST_EXPECT(it == first);
        BEAST_EXPECT(m == size);

        // post-decrement
        m = 0;
        n = length;
        for(it = last; n--;)
        {
            it--;
            m += buffer_bytes(*it);
        }
        BEAST_EXPECT(it == first);
        BEAST_EXPECT(m == size);
    }

    detail::test_mutable_buffers(buffers,
        buffers_type<ConstBufferSequence>{});
}

//------------------------------------------------------------------------------

/** Metafunction to determine if a type meets the requirements of MutableDynamicBuffer_v0
*/
/* @{ */
// VFALCO This trait needs tests
template<class T, class = void>
struct is_mutable_dynamic_buffer
    : std::false_type
{
};

template<class T>
struct is_mutable_dynamic_buffer<T, detail::void_t<decltype(
    std::declval<typename T::const_buffers_type&>() =
        std::declval<T const&>().data(),
    std::declval<typename T::const_buffers_type&>() =
        std::declval<T&>().cdata(),
    std::declval<typename T::mutable_buffers_type&>() =
        std::declval<T&>().data()
    ) > > : net::is_dynamic_buffer_v1<T>
{
};
/** @} */

namespace detail {

template<class MutableBufferSequence>
void
buffers_fill(
    MutableBufferSequence const& buffers,
    char c)
{
    auto const end =
        net::buffer_sequence_end(buffers);
    for(auto it = net::buffer_sequence_begin(buffers);
        it != end; ++it)
    {
        net::mutable_buffer b(*it);
        std::fill(
            static_cast<char*>(b.data()),
            static_cast<char*>(b.data()) + b.size(), c);
    }
}

template<class MutableDynamicBuffer_v0>
void
test_mutable_dynamic_buffer(
    MutableDynamicBuffer_v0 const&,
    std::false_type)
{
}

template<class MutableDynamicBuffer_v0>
void
test_mutable_dynamic_buffer(
    MutableDynamicBuffer_v0 const& b0,
    std::true_type)
{
    BOOST_STATIC_ASSERT(
        net::is_mutable_buffer_sequence<typename
            MutableDynamicBuffer_v0::mutable_buffers_type>::value);

    BOOST_STATIC_ASSERT(
        std::is_convertible<
            typename MutableDynamicBuffer_v0::mutable_buffers_type,
            typename MutableDynamicBuffer_v0::const_buffers_type>::value);

    string_view src = "Hello, world!";
    if(src.size() > b0.max_size())
        src = {src.data(), b0.max_size()};

    // modify readable bytes
    {
        MutableDynamicBuffer_v0 b(b0);
        auto const mb = b.prepare(src.size());
        BEAST_EXPECT(buffer_bytes(mb) == src.size());
        buffers_fill(mb, '*');
        b.commit(src.size());
        BEAST_EXPECT(b.size() == src.size());
        BEAST_EXPECT(
            beast::buffers_to_string(b.data()) ==
            std::string(src.size(), '*'));
        BEAST_EXPECT(
            beast::buffers_to_string(b.cdata()) ==
            std::string(src.size(), '*'));
        auto const n = net::buffer_copy(
            b.data(), net::const_buffer(
                src.data(), src.size()));
        BEAST_EXPECT(n == src.size());
        BEAST_EXPECT(
            beast::buffers_to_string(b.data()) == src);
        BEAST_EXPECT(
            beast::buffers_to_string(b.cdata()) == src);
    }

    // mutable to const sequence conversion
    {
        MutableDynamicBuffer_v0 b(b0);
        b.commit(net::buffer_copy(
            b.prepare(src.size()),
            net::const_buffer(src.data(), src.size())));
        auto mb = b.data();
        auto cb = static_cast<
            MutableDynamicBuffer_v0 const&>(b).data();
        auto cbc = b.cdata();
        BEAST_EXPECT(
            beast::buffers_to_string(b.data()) == src);
        BEAST_EXPECT(
            beast::buffers_to_string(b.cdata()) == src);
        beast::test_buffer_sequence(cb);
        beast::test_buffer_sequence(cbc);
        beast::test_buffer_sequence(mb);
        {
            decltype(mb)  mb2(mb);
            mb = mb2;
            decltype(cb)  cb2(cb);
            cb = cb2;
            decltype(cbc) cbc2(cbc);
            cbc = cbc2;
        }
        {
            decltype(cb)  cb2(mb);
            decltype(cbc) cbc2(mb);
            cb2 = mb;
            cbc2 = mb;
        }
    }
}

} // detail

/** Test an instance of a dynamic buffer or mutable dynamic buffer.
*/
template<class DynamicBuffer_v0>
void
test_dynamic_buffer(
    DynamicBuffer_v0 const& b0)
{
    BOOST_STATIC_ASSERT(
        net::is_dynamic_buffer_v1<DynamicBuffer_v0>::value);

    BOOST_STATIC_ASSERT(
        net::is_const_buffer_sequence<typename
            DynamicBuffer_v0::const_buffers_type>::value);

    BOOST_STATIC_ASSERT(
        net::is_mutable_buffer_sequence<typename
            DynamicBuffer_v0::mutable_buffers_type>::value);

    BEAST_EXPECT(b0.size() == 0);
    BEAST_EXPECT(buffer_bytes(b0.data()) == 0);

    // members
    {
        string_view src = "Hello, world!";

        DynamicBuffer_v0 b1(b0);
        auto const mb = b1.prepare(src.size());
        b1.commit(net::buffer_copy(mb,
            net::const_buffer(src.data(), src.size())));

        // copy constructor
        {
            DynamicBuffer_v0 b2(b1);
            BEAST_EXPECT(b2.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b1.data()) ==
                buffers_to_string(b2.data()));

            // https://github.com/boostorg/beast/issues/1621
            b2.consume(1);
            DynamicBuffer_v0 b3(b2);
            BEAST_EXPECT(b3.size() == b2.size());
            BEAST_EXPECT(
                buffers_to_string(b2.data()) ==
                buffers_to_string(b3.data()));
        }

        // move constructor
        {
            DynamicBuffer_v0 b2(b1);
            DynamicBuffer_v0 b3(std::move(b2));
            BEAST_EXPECT(b3.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b3.data()) ==
                buffers_to_string(b1.data()));
        }

        // copy assignment
        {
            DynamicBuffer_v0 b2(b0);
            b2 = b1;
            BEAST_EXPECT(b2.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b1.data()) ==
                buffers_to_string(b2.data()));

            // self assignment
            b2 = *&b2;
            BEAST_EXPECT(b2.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b2.data()) ==
                buffers_to_string(b1.data()));

            // https://github.com/boostorg/beast/issues/1621
            b2.consume(1);
            DynamicBuffer_v0 b3(b2);
            BEAST_EXPECT(b3.size() == b2.size());
            BEAST_EXPECT(
                buffers_to_string(b2.data()) ==
                buffers_to_string(b3.data()));

        }

        // move assignment
        {
            DynamicBuffer_v0 b2(b1);
            DynamicBuffer_v0 b3(b0);
            b3 = std::move(b2);
            BEAST_EXPECT(b3.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b3.data()) ==
                buffers_to_string(b1.data()));

            // self move
            b3 = std::move(b3);
            BEAST_EXPECT(b3.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b3.data()) ==
                buffers_to_string(b1.data()));
        }

        // swap
        {
            DynamicBuffer_v0 b2(b1);
            DynamicBuffer_v0 b3(b0);
            BEAST_EXPECT(b2.size() == b1.size());
            BEAST_EXPECT(b3.size() == b0.size());
            using std::swap;
            swap(b2, b3);
            BEAST_EXPECT(b2.size() == b0.size());
            BEAST_EXPECT(b3.size() == b1.size());
            BEAST_EXPECT(
                buffers_to_string(b3.data()) ==
                buffers_to_string(b1.data()));
        }
    }

    // n == 0
    {
        DynamicBuffer_v0 b(b0);
        b.commit(1);
        BEAST_EXPECT(b.size() == 0);
        BEAST_EXPECT(buffer_bytes(b.prepare(0)) == 0);
        b.commit(0);
        BEAST_EXPECT(b.size() == 0);
        b.commit(1);
        BEAST_EXPECT(b.size() == 0);
        b.commit(b.max_size() + 1);
        BEAST_EXPECT(b.size() == 0);
        b.consume(0);
        BEAST_EXPECT(b.size() == 0);
        b.consume(1);
        BEAST_EXPECT(b.size() == 0);
        b.consume(b.max_size() + 1);
        BEAST_EXPECT(b.size() == 0);
    }

    // max_size
    {
        DynamicBuffer_v0 b(b0);
        if(BEAST_EXPECT(
            b.max_size() + 1 > b.max_size()))
        {
            try
            {
                b.prepare(b.max_size() + 1);
                BEAST_FAIL();
            }
            catch(std::length_error const&)
            {
                BEAST_PASS();
            }
            catch(...)
            {
                BEAST_FAIL();
            }
        }
    }

    // setup source buffer
    char buf[13];
    unsigned char k0 = 0;
    string_view src(buf, sizeof(buf));
    if(src.size() > b0.max_size())
        src = {src.data(), b0.max_size()};
    BEAST_EXPECT(b0.max_size() >= src.size());
    BEAST_EXPECT(b0.size() == 0);
    BEAST_EXPECT(buffer_bytes(b0.data()) == 0);
    auto const make_new_src =
        [&buf, &k0, &src]
        {
            auto k = k0++;
            for(std::size_t i = 0; i < src.size(); ++i)
                buf[i] = k++;
        };

    // readable / writable buffer sequence tests
    {
        make_new_src();
        DynamicBuffer_v0 b(b0);
        auto const& bc(b);
        auto const mb = b.prepare(src.size());
        BEAST_EXPECT(buffer_bytes(mb) == src.size());
        beast::test_buffer_sequence(mb);
        b.commit(net::buffer_copy(mb,
            net::const_buffer(src.data(), src.size())));
        BEAST_EXPECT(
            buffer_bytes(bc.data()) == src.size());
        beast::test_buffer_sequence(bc.data());
    }

    // h = in size
    // i = prepare size
    // j = commit size
    // k = consume size
    for(std::size_t h = 1; h <= src.size(); ++h)
    {
        string_view in(src.data(), h);
        for(std::size_t i = 1; i <= in.size(); ++i) {
        for(std::size_t j = 1; j <= i + 1; ++j) {
        for(std::size_t k = 1; k <= in.size(); ++k) {
        {
            make_new_src();

            DynamicBuffer_v0 b(b0);
            auto const& bc(b);
            net::const_buffer cb(in.data(), in.size());
            while(cb.size() > 0)
            {
                auto const mb = b.prepare(
                    std::min<std::size_t>(i,
                        b.max_size() - b.size()));
                auto const n = net::buffer_copy(mb,
                    net::const_buffer(cb.data(),
                        std::min<std::size_t>(j, cb.size())));
                b.commit(n);
                cb += n;
            }
            BEAST_EXPECT(b.size() == in.size());
            BEAST_EXPECT(
                buffer_bytes(bc.data()) == in.size());
            BEAST_EXPECT(beast::buffers_to_string(
                bc.data()) == in);
            while(b.size() > 0)
                b.consume(k);
            BEAST_EXPECT(buffer_bytes(bc.data()) == 0);
        }
        } } }
    }

    // MutableDynamicBuffer_v0 refinement
    detail::test_mutable_dynamic_buffer(b0,
        is_mutable_dynamic_buffer<DynamicBuffer_v0>{});
}

} // beast
} // boost

#endif


<|start_filename|>test/doc/websocket_2_handshaking.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at g<EMAIL> dot <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#include <boost/config.hpp>

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4459) // declaration hides global declaration
#endif

#include <boost/beast/_experimental/unit_test/suite.hpp>

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

namespace {

#include "websocket_common.ipp"

void
snippets()
{
    {
    //[code_websocket_2_1

        stream<tcp_stream> ws(ioc);
        net::ip::tcp::resolver resolver(ioc);
        get_lowest_layer(ws).connect(resolver.resolve("www.example.com", "ws"));

        // Do the websocket handshake in the client role, on the connected stream.
        // The implementation only uses the Host parameter to set the HTTP "Host" field,
        // it does not perform any DNS lookup. That must be done first, as shown above.

        ws.handshake(
            "www.example.com",  // The Host field
            "/"                 // The request-target
        );

    //]
    }

    {

    stream<tcp_stream> ws(ioc);

    {
    //[code_websocket_2_2

        // This variable will receive the HTTP response from the server
        response_type res;

        // Perform the websocket handshake in the client role.
        // On success, `res` will hold the complete HTTP response received.

        ws.handshake(
            res,                // Receives the HTTP response
            "www.example.com",  // The Host field
            "/"                 // The request-target
        );

    //]
    }

    //--------------------------------------------------------------------------

    {
    //[code_websocket_2_3

        // Perform the websocket handshake in the server role.
        // The stream must already be connected to the peer.

        ws.accept();

    //]
    }

    {
    //[code_websocket_2_4

        // This buffer will hold the HTTP request as raw characters
        std::string s;

        // Read into our buffer until we reach the end of the HTTP request.
        // No parsing takes place here, we are just accumulating data.

        net::read_until(sock, net::dynamic_buffer(s), "\r\n\r\n");

        // Now accept the connection, using the buffered data.
        ws.accept(net::buffer(s));

    //]
    }

    }

    {
    //[code_websocket_2_5

        // This buffer is required for reading HTTP messages
        flat_buffer buffer;

        // Read the HTTP request ourselves
        http::request<http::string_body> req;
        http::read(sock, buffer, req);

        // See if its a WebSocket upgrade request
        if(websocket::is_upgrade(req))
        {
            // Construct the stream, transferring ownership of the socket
            stream<tcp_stream> ws(std::move(sock));

            // Clients SHOULD NOT begin sending WebSocket
            // frames until the server has provided a response.
            BOOST_ASSERT(buffer.size() == 0);

            // Accept the upgrade request
            ws.accept(req);
        }
        else
        {
            // Its not a WebSocket upgrade, so
            // handle it like a normal HTTP request.
        }

    //]
    }

    {
        //[code_websocket_2_6

        // a function to select the most preferred protocol from a comma-separated list
        auto select_protocol = [](string_view offered_tokens) -> std::string
        {
            // tokenize the Sec-Websocket-Protocol header offered by the client
            http::token_list offered( offered_tokens );

            // an array of protocols supported by this server
            // in descending order of preference
            static const std::array<string_view, 3>
                supported = {
                "v3.my.chat",
                "v2.my.chat",
                "v1.my.chat"
            };

            std::string result;

            for (auto proto : supported)
            {
                auto iter = std::find(offered.begin(), offered.end(), proto);
                if (iter != offered.end())
                {
                    // we found a supported protocol in the list offered by the client
                    result.assign(proto.begin(), proto.end());
                    break;
                }
            }

            return result;
        };


        // This buffer is required for reading HTTP messages
        flat_buffer buffer;

        // Read the HTTP request ourselves
        http::request<http::string_body> req;
        http::read(sock, buffer, req);

        // See if it's a WebSocket upgrade request
        if(websocket::is_upgrade(req))
        {
            // we store the selected protocol in a std::string here because
            // we intend to capture it in the decorator's lambda below
            std::string protocol =
                select_protocol(
                    req[http::field::sec_websocket_protocol]);

            if (protocol.empty())
            {
                // none of our supported protocols were offered
                http::response<http::string_body> res;
                res.result(http::status::bad_request);
                res.body() = "No valid sub-protocol was offered."
                              " This server implements"
                              " v3.my.chat,"
                              " v2.my.chat"
                              " and v1.my.chat";
                http::write(sock, res);
            }
            else
            {
                // Construct the stream, transferring ownership of the socket
                stream<tcp_stream> ws(std::move(sock));

                ws.set_option(
                    stream_base::decorator(
                        [protocol](http::response_header<> &hdr) {
                            hdr.set(
                                http::field::sec_websocket_protocol,
                                protocol);
                        }));

                // Accept the upgrade request
                ws.accept(req);
            }
        }
        else
        {
            // Its not a WebSocket upgrade, so
            // handle it like a normal HTTP request.
        }

        //]
    }

}

struct websocket_2_test
    : public boost::beast::unit_test::suite
{
    void
    run() override
    {
        BEAST_EXPECT(&snippets);
    }
};

BEAST_DEFINE_TESTSUITE(beast,doc,websocket_2);

} // (anon)

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif


<|start_filename|>.dockers/windows-vs-32/tests.bat<|end_filename|>

set PROCESSORS=%NUMBER_OF_PROCESSORS%

REM Optionally throttle cpus:
REM if %PROCESSORS% GTR 2 set PROCESSORS=2

b2 --user-config=user-config.jam ^
  asio.mode=dflt,nodep,nots,ts,nodep-nots,nodep-ts ^
  variant=release ^
  cxxstd=2a,17,14,11 ^
  -j%PROCESSORS% ^
  -q ^
  libs/beast/test libs/beast/example


<|start_filename|>test/doc/websocket.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#include <boost/config.hpp>

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4459) // declaration hides global declaration
#endif

#include <boost/beast/_experimental/unit_test/suite.hpp>

//[code_websocket_1a

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

//]

namespace {

#include "websocket_common.ipp"

void
snippets()
{
    {
    //[code_websocket_1f

        // This newly constructed WebSocket stream will use the specified
        // I/O context and have support for the permessage-deflate extension.

        stream<tcp_stream> ws(ioc);

    //]
    }

    {
    //[code_websocket_2f

        // The `tcp_stream` will be constructed with a new
        // strand which uses the specified I/O context.

        stream<tcp_stream> ws(net::make_strand(ioc));

    //]
    }

    {
    //[code_websocket_3f

        // Ownership of the `tcp_stream` is transferred to the websocket stream

        stream<tcp_stream> ws(std::move(sock));

    //]
    }
    
    {
        stream<tcp_stream> ws(ioc);
    //[code_websocket_4f

        // Calls `close` on the underlying `beast::tcp_stream`
        ws.next_layer().close();

    //]
    }

    {
    //[code_websocket_5f

        // The WebSocket stream will use SSL and a new strand
        stream<ssl_stream<tcp_stream>> wss(net::make_strand(ioc), ctx);

    //]

    //[code_websocket_6f

        // Perform the SSL handshake in the client role
        wss.next_layer().handshake(net::ssl::stream_base::client);

    //]

    //[code_websocket_7f

        // Cancel all pending I/O on the underlying `tcp_stream`
        get_lowest_layer(wss).cancel();

    //]
    }
}

struct doc_websocket_test
    : public boost::beast::unit_test::suite
{
    void
    run() override
    {
        BEAST_EXPECT(&snippets);
    }
};

BEAST_DEFINE_TESTSUITE(beast,doc,doc_websocket);

} // (anon)

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif


<|start_filename|>test/beast/websocket/read3.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/websocket/stream.hpp>

#include "test.hpp"

#include <boost/asio/buffer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/write.hpp>

namespace boost {
namespace beast {
namespace websocket {

class read3_test : public websocket_test_suite
{
public:
    void
    testSuspend()
    {
        // suspend on read block
        doFailLoop([&](test::fail_count& fc)
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc, fc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            std::size_t count = 0;
            ws.async_close({},
                [&](error_code ec)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 1);
                });
            while(! ws.impl_->rd_block.is_locked())
                ioc.run_one();
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    if(ec != net::error::operation_aborted)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 2);
                });
            ioc.run();
            BEAST_EXPECT(count == 2);
        });

        // suspend on release read block
        doFailLoop([&](test::fail_count& fc)
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc, fc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            std::size_t count = 0;
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    if(ec != net::error::operation_aborted)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 2);
                });
            BOOST_ASSERT(ws.impl_->rd_block.is_locked());
            ws.async_close({},
                [&](error_code ec)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 1);
                });
            ioc.run();
            BEAST_EXPECT(count == 2);
        });

        // suspend on write pong
        doFailLoop([&](test::fail_count& fc)
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc, fc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            // insert a ping
            ws.next_layer().append(string_view(
                "\x89\x00", 2));
            std::size_t count = 0;
            std::string const s = "Hello, world";
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(buffers_to_string(b.data()) == s);
                    ++count;
                });
            BEAST_EXPECT(ws.impl_->rd_block.is_locked());
            ws.async_write(net::buffer(s),
                [&](error_code ec, std::size_t n)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(n == s.size());
                    ++count;
                });
            BEAST_EXPECT(ws.impl_->wr_block.is_locked());
            ioc.run();
            BEAST_EXPECT(count == 2);
        });

        // Ignore ping when closing
        doFailLoop([&](test::fail_count& fc)
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc, fc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            std::size_t count = 0;
            // insert fragmented message with
            // a ping in between the frames.
            ws.next_layer().append(string_view(
                "\x01\x01*"
                "\x89\x00"
                "\x80\x01*", 8));
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(buffers_to_string(b.data()) == "**");
                    BEAST_EXPECT(++count == 1);
                    b.consume(b.size());
                    ws.async_read(b,
                        [&](error_code ec, std::size_t)
                        {
                            if(ec != net::error::operation_aborted)
                                BOOST_THROW_EXCEPTION(
                                    system_error{ec});
                            BEAST_EXPECT(++count == 3);
                        });
                });
            BEAST_EXPECT(ws.impl_->rd_block.is_locked());
            ws.async_close({},
                [&](error_code ec)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 2);
                });
            BEAST_EXPECT(ws.impl_->wr_block.is_locked());
            ioc.run();
            BEAST_EXPECT(count == 3);
        });

        // See if we are already closing
        doFailLoop([&](test::fail_count& fc)
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc, fc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            std::size_t count = 0;
            // insert fragmented message with
            // a close in between the frames.
            ws.next_layer().append(string_view(
                "\x01\x01*"
                "\x88\x00"
                "\x80\x01*", 8));
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    if(ec != net::error::operation_aborted)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 2);
                });
            BEAST_EXPECT(ws.impl_->rd_block.is_locked());
            ws.async_close({},
                [&](error_code ec)
                {
                    if(ec)
                        BOOST_THROW_EXCEPTION(
                            system_error{ec});
                    BEAST_EXPECT(++count == 1);
                });
            BEAST_EXPECT(ws.impl_->wr_block.is_locked());
            ioc.run();
            BEAST_EXPECT(count == 2);
        });
    }

    void
    testParseFrame()
    {
        auto const bad =
            [&](string_view s)
            {
                echo_server es{log};
                net::io_context ioc;
                stream<test::stream> ws{ioc};
                ws.next_layer().connect(es.stream());
                ws.handshake("localhost", "/");
                ws.next_layer().append(s);
                error_code ec;
                multi_buffer b;
                ws.read(b, ec);
                BEAST_EXPECT(ec);
            };

        // chopped frame header
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            ws.next_layer().append(
                "\x81\x7e\x01");
            std::size_t count = 0;
            std::string const s(257, '*');
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    ++count;
                    BEAST_EXPECTS(! ec, ec.message());
                    BEAST_EXPECT(buffers_to_string(b.data()) == s);
                });
            ioc.run_one();
            es.stream().write_some(
                net::buffer("\x01" + s));
            ioc.run();
            BEAST_EXPECT(count == 1);
        }

        // new data frame when continuation expected
        bad("\x01\x01*" "\x81\x01*");

        // reserved bits not cleared
        bad("\xb1\x01*");
        bad("\xc1\x01*");
        bad("\xd1\x01*");

        // continuation without an active message
        bad("\x80\x01*");

        // reserved bits not cleared (cont)
        bad("\x01\x01*" "\xb0\x01*");
        bad("\x01\x01*" "\xc0\x01*");
        bad("\x01\x01*" "\xd0\x01*");

        // reserved opcode
        bad("\x83\x01*");

        // fragmented control message
        bad("\x09\x01*");

        // invalid length for control message
        bad("\x89\x7e\x01\x01");

        // reserved bits not cleared (control)
        bad("\xb9\x01*");
        bad("\xc9\x01*");
        bad("\xd9\x01*");

        // unmasked frame from client
        {
            echo_server es{log, kind::async_client};
            net::io_context ioc;
            stream<test::stream> ws{ioc};
            ws.next_layer().connect(es.stream());
            es.async_handshake();
            ws.accept();
            ws.next_layer().append(
                "\x81\x01*");
            error_code ec;
            multi_buffer b;
            ws.read(b, ec);
            BEAST_EXPECT(ec);
        }

        // masked frame from server
        bad("\x81\x80\xff\xff\xff\xff");

        // chopped control frame payload
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            ws.next_layer().append(
                "\x89\x02*");
            std::size_t count = 0;
            multi_buffer b;
            ws.async_read(b,
                [&](error_code ec, std::size_t)
                {
                    ++count;
                    BEAST_EXPECTS(! ec, ec.message());
                    BEAST_EXPECT(buffers_to_string(b.data()) == "**");
                });
            ioc.run_one();
            es.stream().write_some(
                net::buffer(
                    "*" "\x81\x02**"));
            ioc.run();
            BEAST_EXPECT(count == 1);
        }

        // length not canonical
        bad(string_view("\x81\x7e\x00\x7d", 4));
        bad(string_view("\x81\x7f\x00\x00\x00\x00\x00\x00\xff\xff", 10));
    }

    void
    testIssue802()
    {
        for(std::size_t i = 0; i < 100; ++i)
        {
            echo_server es{log, kind::async};
            net::io_context ioc;
            stream<test::stream> ws{ioc};
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            // too-big message frame indicates payload of 2^64-1
            net::write(ws.next_layer(), sbuf(
                "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"));
            multi_buffer b;
            error_code ec;
            ws.read(b, ec);
            BEAST_EXPECT(ec == error::closed);
            BEAST_EXPECT(ws.reason().code == 1009);
        }
    }

    void
    testIssue807()
    {
        echo_server es{log};
        net::io_context ioc;
        stream<test::stream> ws{ioc};
        ws.next_layer().connect(es.stream());
        ws.handshake("localhost", "/");
        ws.write(sbuf("Hello, world!"));
        char buf[4];
        net::mutable_buffer b{buf, 0};
        auto const n = ws.read_some(b);
        BEAST_EXPECT(n == 0);
    }

    /*
        When the internal read buffer contains a control frame and
        stream::async_read_some is called, it is possible for the control
        callback to be invoked on the caller's stack instead of through
        the executor associated with the final completion handler.
    */
    void
    testIssue954()
    {
        echo_server es{log};
        multi_buffer b;
        net::io_context ioc;
        stream<test::stream> ws{ioc};
        ws.next_layer().connect(es.stream());
        ws.handshake("localhost", "/");
        // message followed by ping
        ws.next_layer().append({
            "\x81\x00"
            "\x89\x00",
            4});
        bool called_cb = false;
        bool called_handler = false;
        ws.control_callback(
            [&called_cb](frame_type, string_view)
            {
                called_cb = true;
            });
        ws.async_read(b,
            [&](error_code, std::size_t)
            {
                called_handler = true;
            });
        BEAST_EXPECT(! called_cb);
        BEAST_EXPECT(! called_handler);
        ioc.run();
        BEAST_EXPECT(! called_cb);
        BEAST_EXPECT(called_handler);
        ws.async_read(b,
            [&](error_code, std::size_t)
            {
            });
        BEAST_EXPECT(! called_cb);
    }

    /*  Bishop Fox Hybrid Assessment issue 1

        Happens with permessage-deflate enabled and a
        compressed frame with the FIN bit set ends with an
        invalid prefix.
    */
    void
    testIssueBF1()
    {
        permessage_deflate pmd;
        pmd.client_enable = true;
        pmd.server_enable = true;

        // read
#if 0
        {
            echo_server es{log};
            net::io_context ioc;
            stream<test::stream> ws{ioc};
            ws.set_option(pmd);
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            // invalid 1-byte deflate block in frame
            net::write(ws.next_layer(), sbuf(
                "\xc1\x81\x3a\xa1\x74\x3b\x49"));
        }
#endif
        {
            net::io_context ioc;
            stream<test::stream> wsc{ioc};
            stream<test::stream> wss{ioc};
            wsc.set_option(pmd);
            wss.set_option(pmd);
            wsc.next_layer().connect(wss.next_layer());
            wsc.async_handshake(
                "localhost", "/", [](error_code){});
            wss.async_accept([](error_code){});
            ioc.run();
            ioc.restart();
            BEAST_EXPECT(wsc.is_open());
            BEAST_EXPECT(wss.is_open());
            // invalid 1-byte deflate block in frame
            net::write(wsc.next_layer(), sbuf(
                "\xc1\x81\x3a\xa1\x74\x3b\x49"));
            error_code ec;
            multi_buffer b;
            wss.read(b, ec);
            BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
        }

        // async read
#if 0
        {
            echo_server es{log, kind::async};
            net::io_context ioc;
            stream<test::stream> ws{ioc};
            ws.set_option(pmd);
            ws.next_layer().connect(es.stream());
            ws.handshake("localhost", "/");
            // invalid 1-byte deflate block in frame
            net::write(ws.next_layer(), sbuf(
                "\xc1\x81\x3a\xa1\x74\x3b\x49"));
        }
#endif
        {
            net::io_context ioc;
            stream<test::stream> wsc{ioc};
            stream<test::stream> wss{ioc};
            wsc.set_option(pmd);
            wss.set_option(pmd);
            wsc.next_layer().connect(wss.next_layer());
            wsc.async_handshake(
                "localhost", "/", [](error_code){});
            wss.async_accept([](error_code){});
            ioc.run();
            ioc.restart();
            BEAST_EXPECT(wsc.is_open());
            BEAST_EXPECT(wss.is_open());
            // invalid 1-byte deflate block in frame
            net::write(wsc.next_layer(), sbuf(
                "\xc1\x81\x3a\xa1\x74\x3b\x49"));
            error_code ec;
            flat_buffer b;
            wss.async_read(b,
                [&ec](error_code ec_, std::size_t){ ec = ec_; });
            ioc.run();
            BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
        }
    }

    /*  Bishop Fox Hybrid Assessment issue 2

        Happens with permessage-deflate enabled,
        and a deflate block with the BFINAL bit set
        is encountered in a compressed payload.
    */
    void
    testIssueBF2()
    {
        permessage_deflate pmd;
        pmd.client_enable = true;
        pmd.server_enable = true;

        // read
        {
            net::io_context ioc;
            stream<test::stream> wsc{ioc};
            stream<test::stream> wss{ioc};
            wsc.set_option(pmd);
            wss.set_option(pmd);
            wsc.next_layer().connect(wss.next_layer());
            wsc.async_handshake(
                "localhost", "/", [](error_code){});
            wss.async_accept([](error_code){});
            ioc.run();
            ioc.restart();
            BEAST_EXPECT(wsc.is_open());
            BEAST_EXPECT(wss.is_open());
            // contains a deflate block with BFINAL set
            net::write(wsc.next_layer(), sbuf(
                "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e"
                "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e"
                "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b"
                "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
                "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4"
                "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e"
                "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
                "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e"
                "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e"));
            error_code ec;
            flat_buffer b;
            wss.read(b, ec);
            BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
        }

        // async read
        {
            net::io_context ioc;
            stream<test::stream> wsc{ioc};
            stream<test::stream> wss{ioc};
            wsc.set_option(pmd);
            wss.set_option(pmd);
            wsc.next_layer().connect(wss.next_layer());
            wsc.async_handshake(
                "localhost", "/", [](error_code){});
            wss.async_accept([](error_code){});
            ioc.run();
            ioc.restart();
            BEAST_EXPECT(wsc.is_open());
            BEAST_EXPECT(wss.is_open());
            // contains a deflate block with BFINAL set
            net::write(wsc.next_layer(), sbuf(
                "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e"
                "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e"
                "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b"
                "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
                "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4"
                "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e"
                "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
                "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e"
                "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
                "\xcc\x3e\xd1\xe4\xcc\x3e"));
            error_code ec;
            flat_buffer b;
            wss.async_read(b,
                [&ec](error_code ec_, std::size_t){ ec = ec_; });
            ioc.run();
            BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
        }
    }

    /*
     * Tests when a deflate block spans multiple multi_byte character arrays.
     */
    void
    testIssue1630()
    {
        permessage_deflate pmd;
        pmd.client_enable = true;
        pmd.server_enable = true;

        net::io_context ioc;
        stream<test::stream> wsc{ioc};
        stream<test::stream> wss{ioc};
        wsc.set_option(pmd);
        wss.set_option(pmd);
        wsc.next_layer().connect(wss.next_layer());
        wsc.async_handshake(
            "localhost", "/", [](error_code){});
        wss.async_accept([](error_code){});
        ioc.run();
        ioc.restart();
        BEAST_EXPECT(wsc.is_open());
        BEAST_EXPECT(wss.is_open());

        const asio::const_buffer packets[] = {
            sbuf(
                // websocket bytes
                "\xc1\x2d"

                //deflated payload
                "\xaa\x56\xca\x4b\x4d\xcf\x2f\xc9\x4c\x2c\x49"
                "\x4d\x09\xc9\xcc\x4d\xcd\x2f\x2d\x51\xb2\x32"
                "\x35\x30\x30\xd0\x51\x2a\xa9\x2c\x48\x55\xb2"
                "\x52\x2a\x4f\xcd\x49\xce\xcf\x4d\x55\xaa\x05"
                "\x00"
            ),
            // packet 2
            sbuf(
                "\xc1\x7e\x0b\x89"
                "\xd4\x5a\xdb\x8e\xdb\x48\x92\xfd\x15\xa1\x1e"
                "\x17\x5b\xae\xbc\x5f\xb8\xf0\x43\x49\xa5\xc2"
                "\xf6\xa2\xdd\x30\xfa\x36\x98\xd9\x19\x34\xf2"
                "\x12\x29\xb1\x74\x2d\x92\x52\x5d\x0c\xff\xfb"
                "\x1c\x4a\xb6\xdb\xa2\xc7\xd3\xe8\x92\x5f\x06"
                "\x7e\x28\x93\x99\xc9\xc8\x8c\x38\x11\xe7\x04"
                "\xa9\x77\x17\x71\x93\x9f\x2e\xaa\x77\x17\x7b"
                "\x6a\xda\x7a\xb3\xbe\xa8\xc4\xa7\x59\x69\xb3"
                "\x5e\x53\xc2\x43\x2e\xfe\xfb\x62\x4b\xd4\xfc"
                "\xf6\xe1\x06\xa6\xb5\x17\xd5\xff\xbf\xbb\xa8"
                "\x33\x66\x69\x9a\x46\xca\x21\xa4\xac\xcd\xf8"
                "\xd6\x14\xaf\xb8\x4f\x79\x62\xb3\x1c\x3b\x3d"
                "\xe1\x1e\x8b\x33\xb5\xa9\xa9\xb7\xdd\xe1\xf9"
                "\xef\x3e\x3e\x3e\xac\xdb\x07\x6a\x30\xdc\xe6"
                "\x2d\x2e\xf7\xaf\xd9\xdf\x9b\xbf\xaf\x37\xaf"
                "\x2f\x47\xd2\x09\xa5\xad\x36\x52\x7d\xfe\xdf"
                "\xef\x7e\x18\x7d\xf7\x56\x8d\xd8\xab\xc3\xbf"
                "\x7e\x6e\xfb\xfa\xd7\x37\xc4\x44\x14\x26\x58"
                "\x91\xb2\x30\x2c\x6a\x92\x32\x58\xed\x42\x0c"
                "\x2c\x59\x8a\xb1\x9f\xd7\xbd\x66\xa3\xc3\x82"
                "\xf0\xba\x4e\x74\xb9\xac\x3b\x3a\x5e\xad\xda"
                "\x3a\x5f\xb6\xb4\x0a\xeb\xae\x4e\xd5\xe8\x2f"
                "\x6f\x7e\x1a\xfd\xd7\x71\x64\xd6\x6c\x76\xdb"
                "\x6a\xfc\xcb\x0f\x37\xdf\x4f\x47\x61\x97\xeb"
                "\xcd\x68\x5f\x67\xda\xf4\xa3\xab\xd7\xc7\x1b"
                "\xdc\x70\x2e\x46\xbf\xdc\xbc\xbd\xfa\xf9\xfb"
                "\x9f\xae\x7e\xfc\xf9\xed\xd5\x4f\xd7\xbf\xbe"
                "\xbd\x1d\x71\xce\x8f\xe6\xd2\xeb\x0f\x7b\xd6"
                "\xea\x15\x37\xf2\x95\x32\xaf\x38\x37\x47\x03"
                "\xf4\xd8\xad\xc2\xb6\xe2\xa3\x5d\xb3\xae\x6a"
                "\xea\x4a\xb5\x0d\x4d\x58\xb5\x55\xd3\x6d\x2f"
                "\xe7\xb9\xc1\x78\xd5\xb6\x4d\xba\x3c\xd8\xba"
                "\x5c\xd2\x9e\x96\xc7\x95\x4d\x97\xb0\xee\x60"
                "\xfb\xeb\x8f\xc7\x53\x0e\x8f\xc7\x56\x36\xdb"
                "\x5d\x7b\xa5\x1c\xe2\x7f\x25\x4e\x06\xd9\xe8"
                "\xed\xe4\xcd\x2f\x57\xfd\xc8\xf1\x7e\x59\x75"
                "\xc7\x25\xab\x7a\x8d\x68\xad\xe8\x35\x67\xff"
                "\xb3\x6b\xa9\x5e\xc7\xb0\xce\x85\xd2\x6b\x7e"
                "\x9c\x98\x70\x59\x67\xe0\xab\x12\x23\xde\x7b"
                "\x60\x24\x18\x97\xc2\x18\x25\xd9\xe9\x6e\x3e"
                "\x38\x09\x21\x1f\xcd\x37\x6d\xf7\xe5\x72\x71"
                "\xb2\x5c\xf8\x2f\x96\x3b\xad\x06\xcb\x7b\x07"
                "\x5c\xae\x76\x8f\xc7\xab\x96\x3a\x44\x2a\x00"
                "\x96\xfb\x8f\x51\xad\x73\x75\xf0\xda\x87\x90"
                "\xaf\x3f\x1f\xec\x01\xb0\x2b\x4d\x98\x55\x7f"
                "\x91\xe3\xd5\xef\xf7\xb6\x0f\xb9\xfa\xbf\xc9"
                "\xf7\xe5\x6f\xbf\x88\xe4\x36\xfc\xfb\xbf\xbe"
                "\xf9\xa1\xb9\x7e\x93\xfe\xf7\xe9\xbb\x0f\xbe"
                "\xa9\xd7\x33\x6a\xb6\x4d\xbd\x46\x5c\xe6\xe1"
                "\x52\x68\x33\xba\xbe\xa9\xac\xa8\xa6\x93\x4a"
                "\x89\x8a\x4d\x2a\xc9\xaa\xa9\xad\x1c\xaf\x8c"
                "\xad\xae\x27\x15\x9f\x56\xb7\xaa\x62\xbc\x9f"
                "\xa3\x58\x35\xbe\xae\xa4\xab\xb8\xae\xac\xab"
                "\xec\x4d\x25\x54\x75\x73\x53\xe9\x49\x7f\x67"
                "\xcc\xab\x9b\xdb\xca\x4c\x2b\x31\xae\x24\xee"
                "\x4f\xfb\xfb\x52\x1f\xb1\x76\x80\xdd\x57\xb1"
                "\xe6\xe1\x22\x86\x20\x08\xfb\x47\x80\x3b\x78"
                "\x0d\x39\xfe\x4c\x27\x00\x14\xa3\x79\x87\xa8"
                "\x5f\x5d\x3d\x3c\x3c\xbc\x7a\xa0\x88\x69\xaf"
                "\x36\xcd\xec\x8a\x1e\xb7\xd4\x00\x02\xeb\xae"
                "\xbd\xfa\x1d\x92\x57\x21\xb6\x48\x98\x75\xbe"
                "\xec\xe1\xf1\xe7\xf1\x88\xed\xfe\xfa\xd6\x5d"
                "\x79\xf6\x09\x73\x1f\x81\x8a\x43\x34\x94\xff"
                "\xd5\x88\xb0\xa3\xdd\x72\x0b\xf4\x9d\x0e\xe2"
                "\x34\x25\xf6\x0f\x9c\x6d\x36\xb3\xcb\x86\x56"
                "\xf1\x8b\x91\x94\x56\xa3\x52\x37\x5f\xdc\x07"
                "\x20\x16\xff\xf2\xe6\x68\xbb\xac\xff\x53\x10"
                "\xfe\xa9\x1c\xfd\x87\x23\x1c\x04\xd0\xd0\xbe"
                "\x3e\x92\x0f\x7f\xff\xfe\x1f\x20\x84\x03\xb1"
                "\xfc\xf8\x26\x4a\xad\xb2\x92\x96\x9c\x0d\x14"
                "\x6d\xe1\x41\x48\x23\xbc\x29\x4a\xd8\xa0\x55"
                "\xc2\xd2\x75\x58\xf5\x5c\xd2\x51\xdb\xfd\xb8"
                "\xd9\xac\x78\x4f\x55\xa1\x41\x35\xaf\xb7\x28"
                "\xea\x3d\xdb\x1c\x1f\xf6\xf6\xda\x07\x6e\x98"
                "\xd6\x4c\xa9\x98\x5d\xe4\x31\x07\xe5\xb8\x35"
                "\xcc\x5a\xb2\x9a\x97\x88\x95\xf0\x28\x88\xa0"
                "\x03\x1f\x5e\xa8\xc5\x83\x6c\x1f\x1e\x14\x17"
                "\x01\x03\x5d\x03\x70\xf4\x9c\xf7\x8f\x93\xcd"
                "\x62\xa7\x1d\x62\x7c\x42\x95\xef\x4f\x36\x70"
                "\xe4\xc9\x8f\x5b\x50\xc9\x0a\xc5\x48\x27\x6e"
                "\x9d\xd1\xc1\x11\x27\x2a\xdc\x32\xe2\x9a\x7b"
                "\x7b\xb0\xf4\xd9\x16\x9e\x42\xfd\x1c\xb5\xdf"
                "\xdc\xcf\xfe\xec\x0e\x7e\xb7\xe8\x6c\xe4\x89"
                "\x31\xee\x75\x24\x09\x6b\x8a\x60\x8c\x65\xa5"
                "\x8b\x2f\x52\x65\x7e\x6a\x71\xbe\xb2\xdd\x7e"
                "\x3d\x8b\x0f\xdb\x97\x5b\x14\x64\x43\x20\xc9"
                "\x02\xf7\x4a\x38\xa1\x09\x8c\x2c\xa4\x73\x41"
                "\x30\x11\x92\x33\xa7\x16\x1f\x9f\x77\x6c\xbe"
                "\xb7\xba\xac\x4f\x4c\xbe\xbb\x58\xd4\xeb\xfe"
                "\x79\x87\x32\xde\xc7\xb4\xa9\x37\xcd\x71\x09"
                "\xcc\xaf\x73\x68\xf2\xe1\x41\xb8\x9e\xc4\x20"
                "\xd4\x6d\x9a\x4e\xb9\x1f\x73\x91\x6f\xf9\xd4"
                "\xfa\xb1\xb3\x53\x75\xe3\xfc\x58\xc8\x6b\xcc"
                "\xa3\x75\x88\x4b\xec\xb3\xea\x9a\x1d\x7d\x84"
                "\xd7\x9b\x9f\x59\x26\x15\x95\x4b\x91\x9b\x42"
                "\xe4\x88\x22\xb6\x18\x12\xe5\x92\x99\x96\xe5"
                "\x33\x78\x1d\xb6\xd1\x3b\xeb\xe3\xd9\x1b\x0a"
                "\x90\x4d\xef\xff\xa4\x6b\xa4\xcd\x3a\xc9\x10"
                "\xe0\x0d\x66\x45\xb1\xc5\x15\x0a\x0e\x7f\x1c"
                "\x15\x16\xf4\xa9\x6b\xb6\xcb\xfc\x3c\x7f\x7e"
                "\x6e\x82\x7b\x79\x30\x4a\x61\x52\x10\x03\xd4"
                "\x11\x13\x32\x8a\x2b\x0b\x81\xa6\x2d\x67\x64"
                "\x6c\xa4\x01\xe0\x9c\x7a\x5e\x6d\xd6\x4f\x33"
                "\x7b\x86\x45\x29\xb3\x13\xdc\x05\x0f\x9f\x96"
                "\x60\x88\xbc\x0c\x39\x51\x04\xe8\x45\x31\x7c"
                "\x60\x71\xbf\x17\xcb\xd9\x4c\x3f\xab\xfb\xf8"
                "\x72\x93\x54\x10\x45\x98\xd3\x46\x91\xe3\xc5"
                "\x67\xe3\x78\x72\xd1\xb3\xe2\xb9\x04\xf2\x4e"
                "\x4d\x2e\x6a\x73\x37\x33\xe6\x69\x7f\x77\x7f"
                "\x86\x49\x99\x62\xcc\x49\x3a\x29\x54\x91\x92"
                "\x21\x9f\x19\x59\x11\x93\xb5\x70\x36\xf9\x53"
                "\x93\xcf\x49\x3c\x74\xeb\x55\x9a\xe9\x97\x62"
                "\xdc\x8e\xbd\x4c\xc0\x8b\x08\xd7\x65\x12\x88"
                "\x29\x76\x33\xf6\x88\xa7\xb9\xe5\x66\x32\x66"
                "\xe6\xeb\x18\x2f\x36\x1a\x53\x5c\x2e\xdc\xbb"
                "\x88\x24\x8c\x56\x81\x83\x94\x00\xf4\x82\xc8"
                "\xd1\x7d\x6b\x8c\x67\x16\xb1\x53\x6f\x6d\xd4"
                "\x2c\x3b\x16\x89\x39\xe1\xc9\x9b\xbe\x80\x1b"
                "\x00\xe2\xd4\x33\x65\x66\xee\xb6\xcf\x0f\x4e"
                "\x29\xf3\x52\xd7\xe4\x6b\xe7\x39\xbf\xa1\xa8"
                "\x8c\x33\xe4\x99\xb8\x71\xc5\x0a\xeb\x43\x36"
                "\x13\x19\xb4\xfb\xba\x6b\x28\x18\x99\x8d\x28"
                "\x49\xea\x4c\x5a\x0b\xa9\x4a\x22\x1e\x5d\xc9"
                "\xdc\x07\x55\xbe\xb9\x6b\xa2\x96\x46\x72\xa6"
                "\x85\x8e\x46\x64\x50\x18\x2a\x30\x17\xe8\x57"
                "\x94\xc9\x3c\x85\x01\x01\x2d\x5a\x24\xd1\xd3"
                "\xc2\xad\xd9\xfc\x0c\x9c\x22\x1a\x21\xe4\x10"
                "\xbd\x96\xde\x71\x27\x8b\x62\x20\x40\x27\x72"
                "\xee\xb7\x30\x30\xa9\xbb\xd6\x7b\xbf\x8f\xfb"
                "\xae\x9c\x51\xff\x59\x30\x3e\x5a\x9f\x35\x22"
                "\xae\x72\x62\x9e\x64\xe6\x1c\x65\xd5\x19\xc1"
                "\xe3\xa0\xc8\xb5\x6e\xb3\x69\x45\x3b\x67\x67"
                "\x70\x5c\x4a\xbd\x28\xc8\x92\x2b\x9e\x2c\x7a"
                "\x41\x69\xa8\x38\xc4\x4f\x4a\x6e\x75\x1e\x42"
                "\x4e\x37\xdb\xc7\xed\xfe\xa9\x7e\xf4\x67\x98"
                "\x54\x85\x83\x20\x14\x05\x1c\x0e\x96\xad\x0b"
                "\x8a\xf3\x62\xb2\xd3\x01\x95\x5d\x0e\x68\x35"
                "\xd7\xb6\x5d\x28\xf5\x94\xd5\x4b\x41\x7e\x33"
                "\x9e\x06\xba\x4d\xd7\xb6\x8c\x7b\x01\x33\x65"
                "\x13\x7d\x3b\x09\xce\x84\x58\x8c\xbe\xfd\x77"
                "\xf9\x0f\x81\xa3\x9d\xb4\x5c\x1a\x28\x0c\xaf"
                "\x28\x16\x8d\x7a\xec\x3c\x01\x7f\x42\x90\xfa"
                "\xd6\x20\x2f\x59\xd9\xac\x10\x74\x4b\xc9\x2b"
                "\x23\xb4\x48\xd2\xfb\xc4\xa3\xe1\xca\xcb\xa1"
                "\xc4\x29\x6c\x7f\xcf\x3b\x7b\x87\x04\x7c\x79"
                "\x30\xb4\x06\xcb\xe5\x98\xb3\x43\xa5\x8b\x05"
                "\xa7\xcb\x7d\xa3\x20\x20\x06\xa0\xa9\x6c\x3e"
                "\x35\x69\x15\x28\xc1\x77\x35\x70\xf7\x72\x93"
                "\x28\x10\xc6\x6b\x21\x58\xce\x64\x7d\xca\x3c"
                "\x6b\x6b\x74\xb4\x89\xf3\x64\x24\x1b\x80\x9c"
                "\xb4\xcf\x77\x4f\x51\x24\x75\x06\xe5\x20\xa1"
                "\x24\x8b\xde\xb8\xa0\x21\x7f\x0b\xca\x88\xa3"
                "\x24\xc8\x69\xb2\xc9\x17\xaf\x06\x54\xce\xc0"
                "\x87\x8b\x8d\xe8\x16\xf9\x1c\x94\x33\xa3\xbd"
                "\x88\x92\x41\xb7\xa5\x22\x7d\x48\x06\x7a\x5c"
                "\xf3\x04\xe6\x30\x43\xc5\xcc\x96\x9d\xae\xe7"
                "\xa1\xd6\x85\x2f\xcf\x08\x26\x2a\x07\xa0\xe9"
                "\xa3\x57\xc5\x3a\x5c\xf9\x08\xa7\x92\x56\x88"
                "\xa7\x31\x76\xc0\xac\x82\x4c\x57\x5a\xb5\x62"
                "\xcf\x2f\xcd\xac\x08\xed\x2d\x85\xe7\xf6\x7a"
                "\x72\xdd\x87\x6e\x22\xd9\x58\x4b\x3b\x9e\x5e"
                "\x6b\xe5\xc6\x53\xff\xf5\xcc\xf2\x94\x1c\x73"
                "\xc8\x78\xe6\x25\xa9\xa0\x50\xce\x0b\x17\x89"
                "\x07\x12\x51\xf0\x03\xec\xbe\xad\x7a\xcc\x26"
                "\x07\xcd\x0c\xe3\x09\x6c\x0e\xba\x42\x95\x8d"
                "\x29\x12\x1a\x24\xc1\x58\x11\x03\xf5\x58\x3f"
                "\x85\xc7\x4d\xb1\x07\x8f\xbd\x58\xe5\x14\x70"
                "\xab\xe3\x26\xf6\x2f\x0f\xa3\x89\x46\x8b\xec"
                "\x3c\xf4\x0d\x2a\x2e\x2b\x03\xc8\x41\x68\x3e"
                "\xee\xfd\x2a\xcf\xdb\xc5\xcb\x4d\x32\x74\xc4"
                "\xc9\x68\xcb\xd0\x2a\x33\x1e\x20\x8a\x93\xb1"
                "\xc5\xea\xc8\x8c\x09\x65\x78\xc8\xa7\xe2\xb6"
                "\xe9\x7e\xbe\xdb\xbd\xb8\xb0\x2a\x88\xa7\x5b"
                "\x75\x7d\x33\xd5\x37\x19\x9a\x65\x2c\x99\x74"
                "\xe3\x34\x1d\x5f\xc7\x89\x98\x18\x16\xbe\x1e"
                "\x7e\x21\x2c\xb7\x05\x8d\x23\x68\x2e\xa0\xfe"
                "\x18\x0a\x0c\xd1\x4f\x5e\xa3\xf0\x45\xff\xcd"
                "\xd5\x03\x11\x4b\xa0\x18\x86\x36\xd6\x2a\xab"
                "\x60\x11\xea\x26\x65\x05\x3f\x81\xce\xf5\xc0"
                "\x33\xcd\x12\xcd\xe5\xc2\xb9\xfb\xa7\xfa\x0c"
                "\x62\x25\xa9\x24\x1a\x13\x69\x8d\xcb\x21\x43"
                "\x60\x43\xc4\x43\xcb\x3b\xef\x91\x99\x21\x0f"
                "\x4d\xf2\x9d\x70\x7b\x12\x67\x55\xb9\x82\x63"
                "\xf1\x04\x77\xa2\x39\xf5\x26\x66\x54\x20\x97"
                "\x24\x8f\x92\x52\x89\xce\x9e\x9a\x5c\xd7\x4a"
                "\x2f\x96\x4d\x58\x75\x2f\x8d\xbf\x80\xc1\x88"
                "\xfe\x54\x66\x81\x7e\xe8\x5a\x8c\xf3\x4d\x0c"
                "\x13\x48\xf9\x9b\x71\x30\xec\x76\xf2\x6f\x9a"
                "\x47\x42\xb0\x45\xd1\xce\x41\x8d\x17\xe1\x0c"
                "\xaa\x15\x49\x13\x15\xd3\x11\xac\xf7\xcd\xe3"
                "\xcf\xd0\xbd\x5b\x6d\xa1\xdf\x93\x46\x00\x7c"
                "\x28\x9c\x02\xaa\x80\x40\x4b\xaf\x50\xec\x07"
                "\x9e\x69\xd5\xbc\xbd\xdb\xda\x99\x3f\xa7\xfe"
                "\xa3\x6b\x04\xc8\x23\xe3\x4c\x5a\x2b\x50\x6f"
                "\xb2\x08\x05\x98\x4b\xac\x48\x32\x03\x61\x25"
                "\xd9\x66\xe1\x54\x36\xfb\xbb\x33\x84\x15\x13"
                "\x25\x2a\xc1\x55\xce\x90\x55\x46\x95\x08\x75"
                "\xac\x4c\x42\x5b\x17\xb9\x14\x76\x60\x72\x89"
                "\xe6\x71\x1e\x9a\xe6\xa9\x9c\xa1\x91\x21\x8d"
                "\x20\x87\x99\xd5\xc6\x27\x05\x69\xee\x93\x83"
                "\x2c\xe7\xb0\xcb\x89\xcb\x61\xc9\x11\x8f\xbb"
                "\x0d\x7f\x94\xf3\x66\x25\x5f\x6e\xd2\x16\x43"
                "\x82\xc9\xe8\x98\x8f\x32\x17\x54\xb8\x52\x28"
                "\x5b\xe5\x0b\xca\x1e\x94\xd3\xe0\x1d\x49\x9c"
                "\x2f\x56\x1b\x41\xeb\xd9\x19\xb1\x24\x88\x90"
                "\x92\xb8\x62\x89\x60\xd4\x48\x95\x99\x77\x49"
                "\x40\x27\x08\x19\xfd\x50\x24\xdf\xab\xf5\xec"
                "\x7e\x1d\x9e\x66\x74\x46\x5f\x2e\x1d\x8a\x93"
                "\x83\x5c\x40\xf4\x54\x41\x17\x58\x38\xb2\x59"
                "\x05\x10\xab\x4b\x5c\x0c\xa8\xfc\xfe\xa1\x9d"
                "\xdf\xdd\x6f\x1f\xdb\xc5\x19\x26\xb5\x46\x4a"
                "\x90\x02\x91\x27\x4a\x56\xb3\x90\x82\x70\x96"
                "\x34\x7a\x0f\x2a\x5a\x0c\x14\x4b\x11\x4d\x6a"
                "\xbc\x9c\x69\x7d\x86\x60\xa1\xc8\xc1\xfa\xa6"
                "\x7f\x9b\x16\x13\x9a\x0e\x83\x5e\x24\x59\x2f"
                "\xac\x8a\x68\x77\xfd\xa0\x62\xdd\x89\x6d\xbd"
                "\x60\x1d\xd9\xbb\x33\xd2\x32\x40\x05\x9a\xfe"
                "\x2d\xa8\x43\xd7\xe8\x11\x41\xed\x83\xd0\xc1"
                "\x16\x01\x0c\xbb\x32\xf0\xab\xdc\xb7\x16\x5a"
                "\xe0\x41\x9d\xa1\x77\x21\x3d\x95\x44\x65\x87"
                "\x9e\xb0\x31\xa0\xde\x59\x1b\x12\x72\x25\xa1"
                "\x5a\x7b\x2e\x07\xc5\xa7\xf8\xc5\x96\xa7\xd6"
                "\xdd\xdb\xcd\x19\x4c\x60\x81\x14\x99\x90\xfd"
                "\xa5\x7f\x7f\x84\x4e\x27\x6b\x86\x8c\x81\x34"
                "\xb0\x28\xda\x83\xb4\x94\x4f\xbe\x70\x7e\x9f"
                "\xf7\xea\x8c\x1c\xd1\xc1\xa3\x9d\x82\xce\x4d"
                "\xe0\x58\x1c\x58\x3a\xce\x73\x16\xae\x6f\x97"
                "\x55\x09\x83\x50\xba\xa5\x5c\x74\x7c\x2f\x50"
                "\x12\xcf\xa0\x58\x0f\x42\x47\x6e\xa2\x8e\x73"
                "\xc6\x7d\x12\x3c\x28\x17\x4c\x80\xf4\x81\x86"
                "\x18\x9e\x92\xb9\x36\x85\xc5\x92\x67\x1b\xce"
                "\xf0\x6c\xdf\x2f\xf9\xe0\x55\xcc\x85\x65\xe5"
                "\x72\x71\x56\x94\xe2\xb3\x4d\x21\x1b\x68\xfc"
                "\x53\x9b\x3c\x3e\xec\xed\xbe\xcc\xeb\xd4\x9d"
                "\x61\x32\x6a\x30\xad\xb7\xc5\x17\x65\x05\x79"
                "\x6f\x38\x0a\x81\x4a\xde\xeb\xe8\x85\x92\x83"
                "\xf7\x65\xeb\xf6\xfe\x49\x75\xbb\xe7\x17\xcb"
                "\x3a\x06\x76\x1e\x4f\xc1\x20\x29\x38\x39\x9e"
                "\x4c\x7a\x3a\x17\x60\x4f\xe2\xd7\x5a\xdc\x9a"
                "\xf4\x75\x5a\xef\x9b\x0f\x85\x02\x49\xde\x80"
                "\x12\xc8\xf9\x48\x2c\x6a\x8f\x52\x96\xb2\x06"
                "\x00\xbf\x79\xbf\x6c\xd1\x43\x42\xab\x25\xd5"
                "\x7f\x9d\x50\x46\x73\x21\x0d\x49\x9d\x6c\xf4"
                "\x68\xf2\x06\xfd\xf2\x03\xbc\xb6\x5c\x47\x3b"
                "\x13\x67\x50\x2c\x54\x2b\xa1\x19\x85\xb6\xd2"
                "\x09\x0a\x3f\x87\x5e\x63\x99\xe0\xac\xe3\xe4"
                "\x86\xed\xf2\x5e\xb3\x25\x37\x8b\x8d\x6f\xcf"
                "\x78\x29\x8c\xd3\xf5\xe2\x05\x9a\x35\x14\xc8"
                "\x7b\x54\x62\xc8\xe6\xec\x82\x30\xa4\x8d\xf4"
                "\x83\xd7\x25\x89\x9a\xb6\xd3\x72\xc5\xba\x33"
                "\x8a\xa4\x64\x60\x73\x74\x11\x94\xd0\xb8\x40"
                "\x51\x58\x69\x23\x57\x04\xda\x29\xe0\x77\x36"
                "\x40\xdc\x02\x4d\xdc\xbc\x7f\x63\xf4\x67\x31"
                "\x7e\x98\x92\x36\x4d\xae\xd7\xb3\xfe\x63\xd3"
                "\x27\x54\x95\xb0\x6c\x69\xb0\xbe\x6e\x7f\xfb"
                "\x6c\xf2\x61\xc6\x7b\x3c\x75\x17\xfb\x5f\x47"
                "\xc4\x7e\xd5\xbb\xcf\x16\xb0\xcf\x77\xd2\x7f"
                "\x55\xda\xc5\x65\xdd\xce\x87\xd3\xf8\x60\x5a"
                "\x4b\xed\x71\xe0\x42\xab\x83\xae\x61\x21\x78"
                "\x70\xa2\x76\xc5\x23\x0e\x68\x1b\x7d\x08\xa0"
                "\x61\x50\xc7\x1f\x7c\x5d\xfb\xa3\x0f\x66\x16"
                "\x09\x0c\xa5\xa4\xa2\xce\x8c\x65\x23\x79\x36"
                "\xa5\x58\x10\x93\x64\x42\xb9\x03\x29\x6c\xb6"
                "\x1f\x7e\x2c\xf2\xee\x62\x45\xb9\x0e\x38\xff"
                "\xec\xb8\xb9\x5d\x7b\x48\x9d\x7a\xb6\x0e\x4b"
                "\xb8\xe3\x8b\x81\xe3\x29\x7e\xeb\x3e\xfe\x7c"
                "\x45\xb2\xcf\x67\x53\x9e\x1d\x52\xb0\x9d\xc7"
                "\x5d\xb3\xbe\x78\xff\xfe\xd3\x6f\x56\x56\xed"
                "\xec\xe2\xfd\x3f\x01"
            ),

            // packet 3
            sbuf(
                "\xc1\x7e\x02\x73"
                "\xec\x9a\xc1\x6e\xdc\x20\x10\x86\x5f\x25\xf2"
                "\x7d\x24\x98\x1d\x83\xc9\xa9\xaf\x02\x36\x3e"
                "\x45\x4d\xd4\x34\x95\x7a\xc8\xbb\xf7\xf7\xaa"
                "\xf2\x42\xb5\xad\x41\xe9\x4a\xdd\x6a\x6e\x7b"
                "\xd8\xf9\xc7\x06\xcc\xfc\x03\xdf\x1f\xa9\x96"
                "\xb7\x97\xed\x5e\x76\xb8\x09\xd2\xf2\x0c\x1f"
                "\xd7\x4c\xb4\x8c\x1f\x20\x5a\xf6\x8b\xfe\x22"
                "\xf6\x56\x94\x4b\x13\xe1\x52\x3c\xc7\xad\xe1"
                "\x93\x33\x6f\x10\xae\x0c\xde\x47\xa0\x9a\x7f"
                "\xf2\xbe\xff\x25\xbe\xbe\x5e\x45\x5a\x36\x02"
                "\x03\x5b\xc9\xb7\xbb\xbc\xf0\xc7\xe3\x63\x0a"
                "\xf0\x27\x0c\x6d\x18\x31\x32\x0f\xf3\x56\x52"
                "\x1f\x31\xd7\x5f\xb0\x51\xc3\x4e\xa2\x14\x85"
                "\x4f\xdb\xe8\x10\x9c\x18\x3e\x06\x5e\xaf\xc7"
                "\x6d\x0b\xfb\x71\xc9\x6b\x7c\x7b\xfa\xfa\x10"
                "\x56\xb4\x53\x30\xfe\x24\x56\x98\xb0\x2b\x19"
                "\x0a\x1c\x3c\xa1\xa8\x6e\x95\x34\xe0\x9b\x2a"
                "\x65\x60\x9a\x27\x58\x2e\x6b\xa7\xbe\xf4\x45"
                "\x5c\x95\x7e\x46\x23\xc5\x61\x74\xe4\xc3\x12"
                "\x09\x2e\xc7\x11\xf6\xc0\x4c\x0b\x7a\x58\x9f"
                "\xd2\x82\xdf\x4b\x29\x33\xf9\x33\x04\xc0\xa6"
                "\x33\xfd\x25\xae\x4a\xcf\xe1\x34\x39\xc3\x33"
                "\xa1\x95\x74\x84\x36\xdc\x52\xb2\x21\x51\xf0"
                "\xd6\xc2\x46\xe7\x6c\xf3\x5c\xc8\x9c\xb0\x84"
                "\x9d\x4c\xa3\xe3\xbe\xf4\x45\x5c\x95\xde\xa5"
                "\x1c\xcd\x8a\x21\xb7\x12\x13\x89\x99\x84\x42"
                "\x9e\x22\x39\x98\x1b\x19\x67\x4e\x4b\xf0\x95"
                "\x8c\x20\x51\x40\x47\xdf\x9b\x7e\x8f\xab\xd2"
                "\x8f\x28\x50\xc6\x4c\x4c\xc9\xb1\x25\x81\x99"
                "\xa1\xed\x66\x84\x5c\xe4\x24\x78\x10\x4e\x59"
                "\x4a\x19\xd4\x35\x73\x82\xdd\xea\x9c\xfb\x22"
                "\xae\x7e\x7b\x37\xa1\x13\xf2\x91\x4c\x90\x13"
                "\xd6\x9f\x77\x14\xd3\x6c\xb0\x14\x04\xb6\x0e"
                "\x7b\x97\x49\xb5\x0c\xa3\x8f\x32\xe2\x7b\xdf"
                "\xfe\x12\x57\xa5\x4f\x92\x38\x25\x83\xa5\x0e"
                "\x1b\x47\x02\x37\x49\xe8\xeb\x85\x22\x2c\x50"
                "\xf2\x28\xf9\x6b\x0e\x85\x0c\xf6\x24\xf6\x58"
                "\xaa\x63\x5f\xf6\x4b\x58\x95\xdc\x66\xb1\x71"
                "\x11\x64\x83\x7d\x20\x58\x87\x89\xe2\xcc\x81"
                "\xe0\x5d\xe3\x92\x45\xd8\x2c\x5c\x81\x6c\xed"
                "\x10\xdb\xb5\x9a\xf2\x57\x01\xb2\xdf\x54\x91"
                "\x9b\x92\x72\xed\x08\x5a\x3f\xe2\x76\x07\x45"
                "\xac\xa0\xd6\xb6\x02\xf6\xfc\xf9\xe9\xfb\x5d"
                "\x16\xb1\xa1\xf4\xf6\xac\xd4\x9a\x52\x6b\x4a"
                "\xad\x29\xb5\xa6\xd4\x9a\x52\x6b\x4a\xad\x29"
                "\xb5\xa6\xd4\x9a\x52\x6b\x4a\xad\x29\xb5\xa6"
                "\xd4\x9a\x52\x6b\x4a\xad\x29\xb5\xa6\xd4\x9a"
                "\x52\x6b\x4a\xad\x29\xb5\xa6\xd4\x9a\x52\x6b"
                "\x4a\xad\x29\xb5\xa6\xd4\x9a\x52\x6b\xff\x27"
                "\xb5\x66\xab\xb5\x7f\x7e\xad\x96\x1b\xe2\xa1"
                "\xe3\x7e\x63\x1b\xb0\x9f\x36\xf8\x98\x79\x18"
                "\x3a\x3e\x92\x5d\xb8\x05\x27\x28\x84\x0f\x4f"
                "\xab\x77\xe1\x16\x50\xa0\x10\x3e\xec\xd6\x2e"
                "\xc2\x0d\xfc\xc5\xd0\xd1\x06\xec\xc2\x2d\x54"
                "\x4d\x21\x7c\x78\xbc\xb0\x0b\xb7\x40\x0b\x85"
                "\xf0\xe1\x89\xe0\x2e\xdc\x02\xe2\x14\xc2\x87"
                "\xe7\xe9\xef\xcd\xf0\xe5\x2f\x14\xe2\x0f\x00"
            ),

            // packet 4
            sbuf(
                "\xc1\x45"
                "\xec\xda\x31\x0d\x00\x00\x00\xc3\x20\xff\xae"
                "\x67\xa1\xf7\x82\x0e\x68\x0b\x91\x1a\x53\x63"
                "\x6a\x4c\x8d\xa9\x31\x35\xa6\xc6\xd4\x98\x1a"
                "\x53\x63\x6a\x4c\x8d\xa9\x31\x35\xa6\xc6\xd4"
                "\x98\x1a\x53\x63\x6a\x4c\x8d\xa9\x31\x35\xa6"
                "\xc6\xd4\x98\x1a\x53\x63\x6a\x4c\x8d\xa9\xf1"
                "\xa7\x1a\x0f"
            ),
        };

        for (auto const packet : packets) {
            net::write(wss.next_layer(), packet);
            multi_buffer buffer;
            error_code ec;
            wsc.async_read(buffer, [&ec](error_code ec_, std::size_t) { ec = ec_; });
            ioc.run();
            ioc.restart();
            BEAST_EXPECTS(!ec, ec.message());
        }
    }

    void
    testMoveOnly()
    {
        net::io_context ioc;
        stream<test::stream> ws{ioc};
        ws.async_read_some(
            net::mutable_buffer{},
            move_only_handler{});
    }

    struct copyable_handler
    {
        template<class... Args>
        void
        operator()(Args&&...) const
        {
        }
    };

    void
    testAsioHandlerInvoke()
    {
        // make sure things compile, also can set a
        // breakpoint in asio_handler_invoke to make sure
        // it is instantiated.
        {
            net::io_context ioc;
            net::strand<
                net::io_context::executor_type> s(
                    ioc.get_executor());
            stream<test::stream> ws{ioc};
            flat_buffer b;
            ws.async_read(b, net::bind_executor(
            s, copyable_handler{}));
        }
    }

    void
    run() override
    {
        testParseFrame();
        testIssue802();
        testIssue807();
        testIssue954();
        testIssue1630();
        testIssueBF1();
        testIssueBF2();
        testMoveOnly();
        testAsioHandlerInvoke();
    }
};

BEAST_DEFINE_TESTSUITE(beast,websocket,read3);

} // websocket
} // beast
} // boost


<|start_filename|>test/beast/core/stream_tests.hpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> dot <EMAIL> at g<EMAIL> dot <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#ifndef BOOST_BEAST_STREAM_TESTS_HPP
#define BOOST_BEAST_STREAM_TESTS_HPP

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/use_future.hpp>

namespace boost {
namespace beast {

template<class SyncReadStream>
void
test_sync_read_stream()
{
    BOOST_ASSERT(is_sync_read_stream<SyncReadStream>::value);
    BEAST_EXPECT(static_cast<
        std::size_t(SyncReadStream::*)(net::mutable_buffer const&)>(
        &SyncReadStream::template read_some<net::mutable_buffer>));
    BEAST_EXPECT(static_cast<
        std::size_t(SyncReadStream::*)(net::mutable_buffer const&, error_code&)>(
        &SyncReadStream::template read_some<net::mutable_buffer>));
}

template<class SyncWriteStream>
void
test_sync_write_stream()
{
    BOOST_ASSERT(is_sync_write_stream<SyncWriteStream>::value);
    BEAST_EXPECT(static_cast<
        std::size_t(SyncWriteStream::*)(net::const_buffer const&)>(
        &SyncWriteStream::template write_some<net::const_buffer>));
    BEAST_EXPECT(static_cast<
        std::size_t(SyncWriteStream::*)(net::const_buffer const&, error_code&)>(
        &SyncWriteStream::template write_some<net::const_buffer>));
}

template<class SyncReadStream>
void
test_sync_stream()
{
    test_sync_read_stream<SyncReadStream>();
    test_sync_write_stream<SyncReadStream>();
}

template<class AsyncReadStream>
void
test_async_read_stream()
{
    struct handler
    {
        void operator()(error_code, std::size_t)
        {
        }
    };

    BOOST_ASSERT(is_async_read_stream<AsyncReadStream>::value);
    BEAST_EXPECT(&AsyncReadStream::get_executor);

    // VFALCO These stopped working because of enable_if as the last parameter
    //BEAST_EXPECT((&AsyncReadStream::template async_read_some<net::mutable_buffer, handler>));
    //BEAST_EXPECT((&AsyncReadStream::template async_read_some<net::mutable_buffer, net::use_future_t<>>));
    //BEAST_EXPECT((&AsyncReadStream::template async_read_some<net::mutable_buffer, net::yield_context>));
}

template<class AsyncWriteStream>
void
test_async_write_stream()
{
    struct handler
    {
        void operator()(error_code, std::size_t)
        {
        }
    };

    BOOST_ASSERT(is_async_write_stream<AsyncWriteStream>::value);
    BEAST_EXPECT(&AsyncWriteStream::get_executor);
    // VFALCO These stopped working because of enable_if as the last parameter
    //BEAST_EXPECT((&AsyncWriteStream::template async_write_some<net::const_buffer, handler>));
    //BEAST_EXPECT((&AsyncWriteStream::template async_write_some<net::const_buffer, net::use_future_t<>>));
    //BEAST_EXPECT((&AsyncWriteStream::template async_write_some<net::const_buffer, net::yield_context>));
}

template<class AsyncStream>
void
test_async_stream()
{
    test_async_read_stream<AsyncStream>();
    test_async_write_stream<AsyncStream>();
}

} // beast
} // boost

#endif


<|start_filename|>test/doc/websocket_5_control_frames.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#include <boost/config.hpp>

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4459) // declaration hides global declaration
#endif

#include <boost/beast/_experimental/unit_test/suite.hpp>

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

namespace {

#include "websocket_common.ipp"

void
snippets()
{
    stream<tcp_stream> ws(ioc);

    {
    //[code_websocket_5_1

        ws.control_callback(
            [](frame_type kind, string_view payload)
            {
                // Do something with the payload
                boost::ignore_unused(kind, payload);
            });

    //]
    }

    {
    //[code_websocket_5_2
        
        ws.close(close_code::normal);

    //]
    }
    
    {
    //[code_websocket_5_3

        ws.auto_fragment(true);
        ws.write_buffer_bytes(16384);

    //]
    }
}

struct websocket_5_test
    : public boost::beast::unit_test::suite
{
    void
    run() override
    {
        BEAST_EXPECT(&snippets);
    }
};

BEAST_DEFINE_TESTSUITE(beast,doc,websocket_5);

} // (anon)

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif


<|start_filename|>test/beast/core/_detail_tuple.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at g<EMAIL> dot <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/core/detail/tuple.hpp>

#include <boost/beast/_experimental/unit_test/suite.hpp>

namespace boost {
namespace beast {
namespace detail {

class tuple_test : public beast::unit_test::suite
{
public:
    void
    run()
    {
        struct explicit_constructible
        {
            explicit_constructible(std::nullptr_t)
                : i_(0)
            {
            }

            explicit explicit_constructible(int i)
                : i_(i)
            {
            }

            int i_;
        };

        tuple<explicit_constructible, int> t{nullptr, 42};
        BEAST_EXPECT(detail::get<1>(t) == 42);
        BEAST_EXPECT(detail::get<0>(t).i_ == 0);

        t = tuple<explicit_constructible, int>{explicit_constructible(42), 43};
        BEAST_EXPECT(detail::get<1>(t) == 43);
        BEAST_EXPECT(detail::get<0>(t).i_ == 42);
    }
};

BEAST_DEFINE_TESTSUITE(beast,core,tuple);

} // detail
} // beast
} // boost


<|start_filename|>test/beast/core/make_strand.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/core/net::make_strand.hpp>

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/asio/executor.hpp>
#include <boost/asio/io_context.hpp>

namespace boost {
namespace beast {

class make_strand_test : public beast::unit_test::suite
{
public:
    void
    testFunction()
    {
        net::io_context ioc;
        net::make_strand(ioc);
        net::make_strand(ioc.get_executor());
        net::make_strand(net::make_strand(ioc));

        net::any_io_executor ex(ioc.get_executor());
        net::make_strand(ex);

        // this *should-not* compile
        //net::make_strand(ex.context());
    }

    void
    run() override
    {
        testFunction();
        pass();
    }
};

BEAST_DEFINE_TESTSUITE(beast,core,net::make_strand);

} // beast
} // boost


<|start_filename|>test/beast/_experimental/stream.cpp<|end_filename|>
﻿//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/_experimental/test/stream.hpp>

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/handler.hpp>

#include <boost/asio/ssl/stream.hpp>
#if defined(BOOST_ASIO_HAS_CO_AWAIT)
#include <boost/asio/use_awaitable.hpp>
#endif

#define DEF boost::asio::use_future_t
namespace boost {
namespace beast {

class stream_test
    : public unit_test::suite
{
public:
    void
    testTestStream()
    {
        char buf[1] = {};
        net::mutable_buffer m0;
        net::mutable_buffer m1(buf, sizeof(buf));

        {
            net::io_context ioc;

            {
                test::stream ts(ioc);
            }
            {
                test::stream ts(ioc);
                ts.close();
            }
            {
                test::stream t1(ioc);
                auto t2 = connect(t1);
            }
            {
                test::stream t1(ioc);
                auto t2 = connect(t1);
                t2.close();
            }
        }
        {
            // abandon
            net::io_context ioc;
            test::stream ts(ioc);
            ts.async_read_some(m1,
                [](error_code, std::size_t)
                {
                    BEAST_FAIL();
                });
        }
        //---
        {
            net::io_context ioc;
            {
                test::stream ts(ioc);
                ts.async_read_some(m1,
                    test::fail_handler(
                        net::error::operation_aborted));
            }
            test::run(ioc);
        }
        {
            net::io_context ioc;
            test::stream ts(ioc);
            ts.async_read_some(m1,
                test::fail_handler(
                    net::error::operation_aborted));
            ts.close(); 
            test::run(ioc);
        }
        {
            net::io_context ioc;
            test::stream t1(ioc);
            auto t2 = connect(t1);
            t1.async_read_some(m1,
                test::fail_handler(
                    net::error::eof));
            t2.close();
            test::run(ioc);
        }
        {
            net::io_context ioc;
            test::stream t1(ioc);
            auto t2 = connect(t1);
            t1.async_read_some(m1,
                test::fail_handler(
                    net::error::operation_aborted));
            t1.close();
            test::run(ioc);
        }
    }

    void
    testSharedAbandon()
    {
        struct handler
        {
            std::shared_ptr<test::stream> ts_;

            void
            operator()(error_code, std::size_t)
            {
            }
        };

        char buf[1] = {};
        net::mutable_buffer m1(buf, sizeof(buf));

        std::weak_ptr<test::stream> wp;

        {
            net::io_context ioc;
            {
                auto sp = std::make_shared<test::stream>(ioc);

                sp->async_read_some(m1, handler{sp});
                wp = sp;
            }
        }
        BEAST_EXPECT(! wp.lock());
    }

    void
    testLifetimeViolation()
    {
        // This should assert
        std::shared_ptr<test::stream> sp;
        {
            net::io_context ioc;
            sp = std::make_shared<test::stream>(ioc);
        }
        sp.reset();
    }

    void
    testAsioSSLCompat()
    {
        BOOST_STATIC_ASSERT(
            std::is_same<
                boost::asio::ssl::stream<test::stream>::
                    lowest_layer_type,
                test::stream>::value);
    }

#if defined(BOOST_ASIO_HAS_CO_AWAIT)
    net::awaitable<void>
    testRebind(net::mutable_buffer& b)
    {
        auto ex = co_await net::this_coro::executor;
        auto s1 = test::stream(ex);
        auto s2 = net::use_awaitable.as_default_on(std::move(s1));
#ifdef BOOST_ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS
        auto bt = co_await s2.async_read_some(b);
        bt = co_await s2.async_write_some(b);
#else
        auto bt = co_await s2.async_read_some(b,
            net::use_awaitable);
        bt = co_await s2.async_write_some(b,
            net::use_awaitable);
#endif
    }
#endif

    void
    run() override
    {
        testTestStream();
        testSharedAbandon();
        //testLifetimeViolation();
        boost::ignore_unused(&stream_test::testAsioSSLCompat);
#if defined(BOOST_ASIO_HAS_CO_AWAIT)
    boost::ignore_unused(&stream_test::testRebind);
#endif
    }
};

BEAST_DEFINE_TESTSUITE(beast,test,stream);

} // beast
} // boost


<|start_filename|>.dockers/centos-7/Dockerfile<|end_filename|>
FROM centos:7

RUN yum update -y
RUN yum install -y epel-release
RUN yum -y groupinstall "Development Tools"
RUN yum install -y cmake openssl-devel clang libcxx-devel libcxxabi-devel bzip2-devel which zlib-devel

WORKDIR /devel
RUN git clone -b develop https://github.com/boostorg/boost.git
COPY .dockers/centos-7/user-config.jam /devel/boost/
COPY .dockers/centos-7/tests.sh /devel/boost/

WORKDIR /devel/boost
RUN git submodule update --init --recursive
COPY . /devel/boost/libs/beast/

RUN ./bootstrap.sh
RUN ./b2 toolset=gcc variant=release cxxstd=latest headers
RUN ./tests.sh || true


<|start_filename|>meta/libraries.json<|end_filename|>
{
    "key": "beast",
    "name": "Beast",
    "authors": [
        "<NAME>"
    ],
    "description": "Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio",
    "category": [
        "Concurrent",
        "IO"
    ],
    "maintainers": [
        "<NAME> <<EMAIL>>"
    ],
    "cxxstd": "11"
}


<|start_filename|>.dockers/ubuntu-20/Dockerfile<|end_filename|>
FROM ubuntu:20.04

RUN apt-get update
RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata
RUN apt-get install -y build-essential
RUN apt-get install -y git cmake libssl-dev clang libc++-10-dev libc++abi-10-dev libbz2-dev zlib1g-dev mlocate

WORKDIR /devel
RUN git clone -b develop https://github.com/boostorg/boost.git
COPY .dockers/ubuntu-20/user-config.jam /devel/boost/
COPY .dockers/ubuntu-20/tests.sh /devel/boost/

WORKDIR /devel/boost
RUN git submodule update --init --recursive
COPY . /devel/boost/libs/beast/

RUN ./bootstrap.sh
RUN ./b2 toolset=gcc variant=release cxxstd=latest headers
RUN ./tests.sh || true


<|start_filename|>test/beast/core/flat_stream.cpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> at <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

// Test that header file is self-contained.
#include <boost/beast/core/flat_stream.hpp>

#include "stream_tests.hpp"

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/beast/core/role.hpp>
#include <initializer_list>
#include <vector>
#if BOOST_ASIO_HAS_CO_AWAIT
#include <boost/asio/use_awaitable.hpp>
#endif

namespace boost {
namespace beast {

class flat_stream_test : public unit_test::suite
{
public:
    void
    testMembers()
    {
        net::io_context ioc;

        test_sync_stream<flat_stream<test::stream>>();

        test_async_stream<flat_stream<test::stream>>();

        // read/write

        {
            error_code ec;
            flat_stream<test::stream> s(ioc);
            {
                // VFALCO Hack to make test stream code = eof
                test::stream ts(ioc);
                s.next_layer().connect(ts);
            }
            char buf[1];
            net::mutable_buffer m1 = net::buffer(buf);

            BEAST_EXPECT(s.read_some(net::mutable_buffer{}) == 0);
            BEAST_EXPECT(s.read_some(net::mutable_buffer{}, ec) == 0);
            BEAST_EXPECTS(! ec, ec.message());

            try
            {
                s.read_some(m1);
                BEAST_FAIL();
            }
            catch(std::exception const&)
            {
                BEAST_PASS();
            }
            catch(...)
            {
                BEAST_FAIL();
            }

            BEAST_EXPECT(s.write_some(net::const_buffer{}) == 0);
            BEAST_EXPECT(s.write_some(net::const_buffer{}, ec) == 0);
            BEAST_EXPECTS(! ec, ec.message());

            try
            {
                s.write_some(m1);
                BEAST_FAIL();
            }
            catch(std::exception const&)
            {
                BEAST_PASS();
            }
            catch(...)
            {
                BEAST_FAIL();
            }

            bool invoked;

            invoked = false;
            s.async_read_some(net::mutable_buffer{},
                [&](error_code ec, std::size_t)
                {
                    invoked = true;
                    BEAST_EXPECTS(! ec, ec.message());
                });
            ioc.run();
            ioc.restart();
            BEAST_EXPECT(invoked);

            invoked = false;
            s.async_write_some(net::const_buffer{},
                [&](error_code ec, std::size_t)
                {
                    invoked = true;
                    BEAST_EXPECTS(! ec, ec.message());
                });
            ioc.run();
            ioc.restart();
            BEAST_EXPECT(invoked);
        }

        // stack_write_some

        {
            char b[detail::flat_stream_base::max_size];
            std::array<net::const_buffer, 3> bs;
            bs[0] = net::const_buffer(b, 100);
            bs[1] = net::const_buffer(b + 100, 200);
            bs[2] = net::const_buffer(b + 100 + 200, 300);
            BEAST_EXPECT(buffer_bytes(bs) <=
                detail::flat_stream_base::max_stack);
            flat_stream<test::stream> s(ioc);
            error_code ec;
            s.write_some(bs, ec);
        }

        // write_some

        {
            char b[detail::flat_stream_base::max_size];
            std::array<net::const_buffer, 2> bs;
            bs[0] = net::const_buffer(b,
                detail::flat_stream_base::max_stack);
            bs[1] = net::const_buffer(b + bs[0].size(), 1024);
            BEAST_EXPECT(buffer_bytes(bs) <=
                detail::flat_stream_base::max_size);
            flat_stream<test::stream> s(ioc);
            error_code ec;
            s.write_some(bs, ec);
        }

        // async_write_some

        {
            char b[detail::flat_stream_base::max_size];
            std::array<net::const_buffer, 2> bs;
            bs[0] = net::const_buffer(b,
                detail::flat_stream_base::max_stack);
            bs[1] = net::const_buffer(b + bs[0].size(), 1024);
            BEAST_EXPECT(buffer_bytes(bs) <=
                detail::flat_stream_base::max_size);
            flat_stream<test::stream> s(ioc);
            s.async_write_some(bs,
                [](error_code, std::size_t)
                {
                });
        }

        // teardown

        {
            test::stream ts(ioc);
            flat_stream<test::stream> s(ioc);
            ts.connect(s.next_layer());
            error_code ec;
            teardown(role_type::client, s, ec);
        }

        {
            test::stream ts(ioc);
            flat_stream<test::stream> s(ioc);
            ts.connect(s.next_layer());
            async_teardown(role_type::client, s,
                [](error_code)
                {
                });
        }
    }

    void
    testSplit()
    {
        auto const check =
            [&](
                std::initializer_list<int> v0,
                std::size_t limit,
                unsigned long count,
                bool copy)
            {
                std::vector<net::const_buffer> v;
                v.reserve(v0.size());
                for(auto const n : v0)
                    v.emplace_back("", n);
                auto const result =
                    boost::beast::detail::flat_stream_base::flatten(v, limit);
                BEAST_EXPECT(result.size == count);
                BEAST_EXPECT(result.flatten == copy);
                return result;
            };
        check({},           1,    0, false);
        check({1,2},        1,    1, false);
        check({1,2},        2,    1, false);
        check({1,2},        3,    3, true);
        check({1,2},        4,    3, true);
        check({1,2,3},      1,    1, false);
        check({1,2,3},      2,    1, false);
        check({1,2,3},      3,    3, true);
        check({1,2,3},      4,    3, true);
        check({1,2,3},      7,    6, true);
        check({1,2,3,4},    3,    3, true);
    }

#if BOOST_ASIO_HAS_CO_AWAIT
    void testAwaitableCompiles(
        flat_stream<test::stream>& stream,
        net::mutable_buffer rxbuf,
        net::const_buffer txbuf)
    {
        static_assert(std::is_same_v<
            net::awaitable<std::size_t>, decltype(
            stream.async_read_some(rxbuf, net::use_awaitable))>);

        static_assert(std::is_same_v<
            net::awaitable<std::size_t>, decltype(
            stream.async_write_some(txbuf, net::use_awaitable))>);
    }
#endif

    void
    run() override
    {
        testMembers();
        testSplit();
#if BOOST_ASIO_HAS_CO_AWAIT
    boost::ignore_unused(&flat_stream_test::testAwaitableCompiles);
#endif
    }
};

BEAST_DEFINE_TESTSUITE(beast,core,flat_stream);

} // beast
} // boost


<|start_filename|>test/beast/core/file_test.hpp<|end_filename|>
//
// Copyright (c) 2016-2019 <NAME> (<EMAIL> dot <EMAIL> at g<EMAIL> dot <EMAIL>)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//

#ifndef BOOST_BEAST_FILE_TEST_HPP
#define BOOST_BEAST_FILE_TEST_HPP

#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/file_base.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <cstdio>
#include <string>
#include <type_traits>

namespace boost {
namespace beast {

template<class File, bool append_unicode_suffix = false>
void
test_file()
{
    BOOST_STATIC_ASSERT(
        is_file<File>::value);
    BOOST_STATIC_ASSERT(
        ! std::is_copy_constructible<File>::value);
    BOOST_STATIC_ASSERT(
        ! std::is_copy_assignable<File>::value);

    namespace fs = boost::filesystem;

    static constexpr
#ifdef _WIN32
    boost::winapi::WCHAR_ unicode_suffix[] = { 0xd83e, 0xdd84, 0x0000 }; // UTF-16-LE unicorn
#else
    char                  unicode_suffix[] = { '\xf0', '\x9f', '\xa6', '\x84', '\x00' }; // UTF-8 unicorn
#endif

    class temp_path
    {
        fs::path path_;
        std::vector<char> utf8_str_;

    public:
        temp_path()
            : path_(fs::unique_path())
        {
            if (append_unicode_suffix)
                path_ += unicode_suffix;
#ifdef _WIN32
            constexpr auto cp = boost::winapi::CP_UTF8_;
            constexpr auto flags = boost::winapi::WC_ERR_INVALID_CHARS_;
            auto sz = boost::winapi::WideCharToMultiByte(
                cp, flags, path_.c_str(), -1, nullptr, 0,
                nullptr, nullptr);
            BEAST_EXPECT(sz != 0);
            utf8_str_.resize(sz);
            auto ret = boost::winapi::WideCharToMultiByte(
                cp, flags, path_.c_str(), -1,
                utf8_str_.data(), sz,
                nullptr, nullptr);
            BEAST_EXPECT(ret == sz);
#endif
        }

        operator fs::path const&()
        {
            return path_;
        }

        operator char const*()
        {
#ifdef _WIN32
            return utf8_str_.data();
#else
            return path_.c_str();
#endif
        }
    };

    auto const create =
        [](fs::path const& path)
        {
            BEAST_EXPECT(! fs::exists(path));
            fs::ofstream out(path);
            BEAST_EXPECT(out.is_open());
        };

    auto const remove =
        [](fs::path const& path)
        {
            fs::remove(path);
            BEAST_EXPECT(! fs::exists(path));
        };

    temp_path path;

    // bad file descriptor
    {
        File f;
        char buf[1];
        BEAST_EXPECT(! f.is_open());
        BEAST_EXPECT(! fs::exists(path));
        {
            error_code ec;
            f.size(ec);
            BEAST_EXPECT(ec == errc::bad_file_descriptor);
        }
        {
            error_code ec;
            f.pos(ec);
            BEAST_EXPECT(ec == errc::bad_file_descriptor);
        }
        {
            error_code ec;
            f.seek(0, ec);
            BEAST_EXPECT(ec == errc::bad_file_descriptor);
        }
        {
            error_code ec;
            f.read(buf, 0, ec);
            BEAST_EXPECT(ec == errc::bad_file_descriptor);
        }
        {
            error_code ec;
            f.write(buf, 0, ec);
            BEAST_EXPECT(ec == errc::bad_file_descriptor);
        }
    }

    // file_mode::read
    {
        {
            File f;
            error_code ec;
            create(path);
            f.open(path, file_mode::read, ec);
            BEAST_EXPECT(! ec);
        }
        remove(path);
    }
    
    // file_mode::scan
    {
        {
            File f;
            error_code ec;
            create(path);
            f.open(path, file_mode::scan, ec);
            BEAST_EXPECT(! ec);
        }
        remove(path);
    }
    
    // file_mode::write
    {
        {
            File f;
            error_code ec;
            BEAST_EXPECT(! fs::exists(path));
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(fs::exists(path));
        }
        {
            File f;
            error_code ec;
            BEAST_EXPECT(fs::exists(path));
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(fs::exists(path));
        }
        remove(path);
    }
    
    // file_mode::write_new
    {
        {
            File f;
            error_code ec;
            BEAST_EXPECT(! fs::exists(path));
            f.open(path, file_mode::write_new, ec);
            BEAST_EXPECTS(! ec, ec.message());
            BEAST_EXPECT(fs::exists(path));
        }
        {
            File f;
            error_code ec;
            BEAST_EXPECT(fs::exists(path));
            f.open(path, file_mode::write_new, ec);
            BEAST_EXPECT(ec);
        }
        remove(path);
    }
    
    // file_mode::write_existing
    {
        {
            File f;
            error_code ec;
            BEAST_EXPECT(! fs::exists(path));
            f.open(path, file_mode::write_existing, ec);
            BEAST_EXPECT(ec);
            BEAST_EXPECT(! fs::exists(path));
        }
        {
            File f;
            error_code ec;
            create(path);
            BEAST_EXPECT(fs::exists(path));
            f.open(path, file_mode::write_existing, ec);
            BEAST_EXPECT(! ec);
        }
        remove(path);
    }
    
    // file_mode::append
    {
        {
            File f;
            error_code ec;
            BEAST_EXPECT(! fs::exists(path));
            f.open(path, file_mode::append, ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(fs::exists(path));
        }
        {
            File f;
            error_code ec;
            BEAST_EXPECT(fs::exists(path));
            f.open(path, file_mode::append, ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(fs::exists(path));
        }
        remove(path);
    }
        
    // file_mode::append_existing
    {
        {
            File f;
            error_code ec;
            BEAST_EXPECT(! fs::exists(path));
            f.open(path, file_mode::append_existing, ec);
            BEAST_EXPECT(ec);
            BEAST_EXPECT(! fs::exists(path));
        }
        remove(path);
        {
            File f;
            error_code ec;
            create(path);
            BEAST_EXPECT(fs::exists(path));
            f.open(path, file_mode::append_existing, ec);
            BEAST_EXPECT(! ec);
        }
        remove(path);
    }

    // special members
    {
        {
            File f1;
            error_code ec;
            f1.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(f1.is_open());

            // move constructor
            File f2(std::move(f1));
            BEAST_EXPECT(! f1.is_open());
            BEAST_EXPECT(f2.is_open());

            // move assignment
            File f3;
            f3 = std::move(f2);
            BEAST_EXPECT(! f2.is_open());
            BEAST_EXPECT(f3.is_open());
        }
        remove(path);
    }

    // re-open
    {
        {
            File f;
            error_code ec;
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
        }
        remove(path);
    }

    // re-assign
    {
        temp_path path2;
        {
            error_code ec;

            File f1;
            f1.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);

            File f2;
            f2.open(path2, file_mode::write, ec);
            BEAST_EXPECT(! ec);

            f2 = std::move(f1);
            BEAST_EXPECT(! f1.is_open());
            BEAST_EXPECT(f2.is_open());
        }
        remove(path);
        remove(path2);
    }

    // self-move
    {
        {
            File f;
            error_code ec;
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
            f = std::move(f);
            BEAST_EXPECT(f.is_open());
        }
        remove(path);
    }

    // native_handle
    {
        {
            File f;
            auto none = f.native_handle();
            error_code ec;
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);
            auto fd = f.native_handle();
            BEAST_EXPECT(fd != none);
            f.native_handle(none);
            BEAST_EXPECT(! f.is_open());
        }
        remove(path);
    }

    // read and write
    {
        string_view const s = "Hello, world!";

        // write
        {
            File f;
            error_code ec;
            f.open(path, file_mode::write, ec);
            BEAST_EXPECT(! ec);

            f.write(s.data(), s.size(), ec);
            BEAST_EXPECT(! ec);

            auto size = f.size(ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(size == s.size());

            auto pos = f.pos(ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(pos == size);

            f.close(ec);
            BEAST_EXPECT(! ec);
        }

        // read
        {
            File f;
            error_code ec;
            f.open(path, file_mode::read, ec);
            BEAST_EXPECT(! ec);

            std::string buf;
            buf.resize(s.size());
            f.read(&buf[0], buf.size(), ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(buf == s);

            f.seek(1, ec);
            BEAST_EXPECT(! ec);
            buf.resize(3);
            f.read(&buf[0], buf.size(), ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(buf == "ell");

            auto pos = f.pos(ec);
            BEAST_EXPECT(! ec);
            BEAST_EXPECT(pos == 4);
        }
        remove(path);
    }

    BEAST_EXPECT(! fs::exists(path));
}

} // beast
} // boost

#endif
