diff --git a/src/beast/.gitignore b/src/beast/.gitignore index e51312d94c..99f984bdaa 100644 --- a/src/beast/.gitignore +++ b/src/beast/.gitignore @@ -1,30 +1,2 @@ -docs/ -._* -*.mode1v3 -*.pbxuser -*.perspectivev3 -*.user -*.ncb -*.suo -*.obj -*.ilk -*.pch -*.pdb -*.dep -*.idb -*.manifest -*.manifest.res -*.o -*.opensdf -*.d -*.sdf -xcuserdata -contents.xcworkspacedata -.DS_Store -.svn -profile bin/ -node_modules/ -cov-int/ -nohup.out -venv/ +bin64/ diff --git a/src/beast/.travis.yml b/src/beast/.travis.yml index 380cb741c9..57c16c5dde 100644 --- a/src/beast/.travis.yml +++ b/src/beast/.travis.yml @@ -2,6 +2,7 @@ language: cpp env: global: + - LLVM_VERSION=3.8.0 # Maintenance note: to move to a new version # of boost, update both BOOST_ROOT and BOOST_URL. # Note that for simplicity, BOOST_ROOT's final @@ -27,57 +28,50 @@ packages: &gcc5_pkgs - autotools-dev - libc6-dbg -packages: &clang38_pkgs - - clang-3.8 - - g++-5 - - python-software-properties - - libssl-dev - - libffi-dev - - libstdc++6 - - binutils-gold - # Provides a backtrace if the unittests crash - - gdb - # Needed for installing valgrind - - subversion - - automake - - autotools-dev - - libc6-dbg - matrix: include: - # GCC/Coverage + # GCC/Coverage/Autobahn - compiler: gcc - env: GCC_VER=5 VARIANT=coverage ADDRESS_MODEL=64 + env: + - GCC_VER=5 + - VARIANT=coverage + - ADDRESS_MODEL=64 + - BUILD_SYSTEM=cmake + - PATH=$PWD/cmake/bin:$PATH addons: &ao_gcc5 apt: sources: ['ubuntu-toolchain-r-test'] packages: *gcc5_pkgs - # # GCC/Debug - # - compiler: gcc - # env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=64 - # addons: *ao_gcc5 - # branches: # NOTE: this does NOT work, though it SHOULD - # - master - # - develop - # Clang/UndefinedBehaviourSanitizer - compiler: clang - env: GCC_VER=5 VARIANT=usan CLANG_VER=3.8 ADDRESS_MODEL=64 UBSAN_OPTIONS='print_stacktrace=1' - addons: &ao_clang38 - apt: - sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8'] - packages: *clang38_pkgs + env: + - GCC_VER=5 + - VARIANT=usan + - CLANG_VER=3.8 + - ADDRESS_MODEL=64 + - UBSAN_OPTIONS='print_stacktrace=1' + - BUILD_SYSTEM=cmake + - PATH=$PWD/cmake/bin:$PATH + - PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH + addons: *ao_gcc5 # Clang/AddressSanitizer - compiler: clang - env: GCC_VER=5 VARIANT=asan CLANG_VER=3.8 ADDRESS_MODEL=64 - addons: *ao_clang38 + env: + - GCC_VER=5 + - VARIANT=asan + - CLANG_VER=3.8 + - ADDRESS_MODEL=64 + - PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH + addons: *ao_gcc5 cache: directories: - $BOOST_ROOT - $VALGRIND_ROOT + - llvm-$LLVM_VERSION + - cmake before_install: - scripts/install-dependencies.sh diff --git a/src/beast/CHANGELOG b/src/beast/CHANGELOG deleted file mode 100644 index 0eacc6feff..0000000000 --- a/src/beast/CHANGELOG +++ /dev/null @@ -1,21 +0,0 @@ -1.0.0-b6 - -* Use SFINAE on return values -* Use beast::error_code instead of nested types -* Tidy up use of GENERATING_DOCS -* Remove obsolete RFC2616 functions -* Add message swap members and free functions -* Add HTTP field value parser containers: ext_list, param_list, token_list -* Fixes for some corner cases in basic_parser_v1 -* Configurable limits on headers and body sizes in basic_parser_v1 - -API Changes: - -* ci_equal is moved to beast::http namespace, in rfc7230.hpp - -* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See: - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers - -* basic_parser_v1 adheres to rfc7230 as strictly as possible - --------------------------------------------------------------------------------- diff --git a/src/beast/CHANGELOG.md b/src/beast/CHANGELOG.md new file mode 100644 index 0000000000..d82c196bcd --- /dev/null +++ b/src/beast/CHANGELOG.md @@ -0,0 +1,86 @@ +1.0.0-b13 + +* dstream improvements +* Remove bin and bin64 directories +* Tidy up .vcxproj file groupings + +-------------------------------------------------------------------------------- + +1.0.0-b12 + +* Use -p to print suites from unit test main. +* BEAST_EXPECTS to add a reason string to test failures +* Fix unit test runner to output all case names +* Update README for build requirements +* Rename to CHANGELOG.md + +-------------------------------------------------------------------------------- + +1.0.0-b11 + +* Set URI in generated WebSocket Upgrade requests +* Rename echo server class and file names +* Rename to DynamicBuffer in some code and documentation +* Fix integer warnings in Windows builds +* Add 32 and 64 bit Windows build support +* Update README for build instructions and more +* Add repository and documention banners + +-------------------------------------------------------------------------------- + +1.0.0-b10 + +* Fix compilation warnings +* Add websocketpp comparison to HTML documentation + +-------------------------------------------------------------------------------- + +1.0.0-b9 + +* Fix CMakeLists.txt + +-------------------------------------------------------------------------------- + +1.0.0-b8 + +* Fix include in example code +* Fix basic_headers rfc2616 Section 4.2 compliance + +-------------------------------------------------------------------------------- + +1.0.0-b7 + +* Fix prepare by calling init. prepare() can throw depending on the + implementation of Writer. Publicly provided beast::http writers never throw. +* Fixes to example HTTP server +* Fully qualify ambiguous calls to read and parse +* Remove deprecated http::stream wrapper +* Example HTTP server now calculates the MIME-type +* Fixes and documentation for teardown and use with SSL: +* Add example code to rfc7230 javadocs +* Remove extraneous header file +* Add skip_body parser option + +-------------------------------------------------------------------------------- + +1.0.0-b6 + +* Use SFINAE on return values +* Use beast::error_code instead of nested types +* Tidy up use of GENERATING_DOCS +* Remove obsolete RFC2616 functions +* Add message swap members and free functions +* Add HTTP field value parser containers: ext_list, param_list, token_list +* Fixes for some corner cases in basic_parser_v1 +* Configurable limits on headers and body sizes in basic_parser_v1 + +API Changes: + +* ci_equal is moved to beast::http namespace, in rfc7230.hpp + +* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See: + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers + +* basic_parser_v1 adheres to rfc7230 as strictly as possible + +-------------------------------------------------------------------------------- diff --git a/src/beast/CMakeLists.txt b/src/beast/CMakeLists.txt index 956f713311..20530bbb25 100644 --- a/src/beast/CMakeLists.txt +++ b/src/beast/CMakeLists.txt @@ -7,7 +7,7 @@ project (Beast) set_property (GLOBAL PROPERTY USE_FOLDERS ON) if (WIN32) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /bigobj /D _WIN32_WINNT=0x0601 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") else() set(Boost_USE_STATIC_LIBS ON) @@ -20,10 +20,29 @@ else() find_package(Threads) set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall -Wpedantic") + "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wpedantic") endif() -message ("cxx Flags: " ${CMAKE_CXX_FLAGS}) +if ("${VARIANT}" STREQUAL "coverage") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") + set(CMAKE_BUILD_TYPE RELWITHDEBINFO) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov") +elseif ("${VARIANT}" STREQUAL "asan") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") + set(CMAKE_BUILD_TYPE RELWITHDEBINFO) +elseif ("${VARIANT}" STREQUAL "usan") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-omit-frame-pointer") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") + set(CMAKE_BUILD_TYPE RELWITHDEBINFO) +elseif ("${VARIANT}" STREQUAL "debug") + set(CMAKE_BUILD_TYPE DEBUG) +elseif ("${VARIANT}" STREQUAL "release") + set(CMAKE_BUILD_TYPE RELEASE) +endif() function(DoGroupSources curdir rootdir folder) file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*) @@ -51,6 +70,9 @@ include_directories (include) file(GLOB_RECURSE BEAST_INCLUDES ${PROJECT_SOURCE_DIR}/include/beast/*.hpp ${PROJECT_SOURCE_DIR}/include/beast/*.ipp +) + +file(GLOB_RECURSE EXTRAS_INCLUDES ${PROJECT_SOURCE_DIR}/extras/beast/*.hpp ${PROJECT_SOURCE_DIR}/extras/beast/*.ipp ) @@ -60,5 +82,3 @@ add_subdirectory (test) add_subdirectory (test/core) add_subdirectory (test/http) add_subdirectory (test/websocket) - -#enable_testing() diff --git a/src/beast/Jamroot b/src/beast/Jamroot index f0f9f097c3..78951028dd 100644 --- a/src/beast/Jamroot +++ b/src/beast/Jamroot @@ -100,6 +100,7 @@ project beast clang:-std=c++11 msvc:_SCL_SECURE_NO_WARNINGS=1 msvc:_CRT_SECURE_NO_WARNINGS=1 + msvc:-bigobj LINUX:_XOPEN_SOURCE=600 LINUX:_GNU_SOURCE=1 SOLARIS:_XOPEN_SOURCE=500 diff --git a/src/beast/README.md b/src/beast/README.md index a94495cd9f..70c0e0209f 100644 --- a/src/beast/README.md +++ b/src/beast/README.md @@ -1,4 +1,5 @@ -# Beast +Beast [![Join the chat at https://gitter.im/vinniefalco/Beast](https://badges.gitter.im/vinniefalco/Beast.svg)](https://gitter.im/vinniefalco/Beast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status] (https://travis-ci.org/vinniefalco/Beast.svg?branch=master)](https://travis-ci.org/vinniefalco/Beast) [![codecov] @@ -7,23 +8,151 @@ (https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/) [![License] (https://img.shields.io/badge/license-boost-brightgreen.svg)](LICENSE_1_0.txt) -Beast provides implementations of the HTTP and WebSocket protocols -built on top of Boost.Asio and other parts of boost. +# HTTP and WebSocket implementations built on Boost.Asio -Requirements: +--- -* Boost -* C++11 or greater -* OpenSSL (optional) +## CppCon 2016 -This software is currently in beta: interfaces are subject to change. For -recent changes see [CHANGELOG](CHANGELOG). +I will be giving a lightning talk on Beast at CppCon 2016 in Bellevue, +Washington from September 18 to September 22. If you'd like to meet me +and hear the talk or ask questions about Beast feel free to approach +me in person or send me an email at vinnie.falco@gmail.com to schedule +some time. + +About CppCon 2016: +http://cppcon.org + +--- + +## Contents + +- [Introduction](#introduction) +- [Description](#description) +- [Requirements](#requirements) +- [Building](#building) +- [Usage](#usage) +- [Licence](#licence) +- [Contact](#contact) + +## Introduction + +Beast is a header-only, cross-platform C++ library built on Boost.Asio and +Boost, containing two modules implementing widely used network protocols. +Beast.HTTP offers a universal model for describing, sending, and receiving +HTTP messages while Beast.WebSocket provides a complete implementation of +the WebSocket protocol. Their design achieves these goals: + +* **Symmetry.** Interfaces are role-agnostic; the same interfaces can be +used to build clients, servers, or both. + +* **Ease of Use.** HTTP messages are modeled using simple, readily +accessible objects. Functions and classes used to send and receive HTTP +or WebSocket messages are designed to resemble Boost.Asio as closely as +possible. Users familiar with Boost.Asio will be immediately comfortable +using this library. + +* **Flexibility.** Interfaces do not mandate specific implementation +strategies; important decisions such as buffer or thread management are +left to users of the library. + +* **Performance.** The implementation performs competitively, making it a +realistic choice for building high performance network servers. + +* **Scalability.** Development of network applications that scale to thousands +of concurrent connections is possible with the implementation. + +* **Basis for further abstraction.** The interfaces facilitate the +development of other libraries that provide higher levels of abstraction. + +Beast is used in [rippled](https://github.com/ripple/rippled), an +open source server application that implements a decentralized +cryptocurrency system. + +## Description + +This software is currently in beta: interfaces may change. +For recent changes see the [CHANGELOG](CHANGELOG.md). The library has been submitted to the [Boost Library Incubator](http://rrsd.com/blincubator.com/bi_library/beast-2/?gform_post_id=1579) +* [Project Site](http://vinniefalco.github.io/) +* [Repository](https://github.com/vinniefalco/Beast) +* [Project Documentation](http://vinniefalco.github.io/beast/) +* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html) + +## Requirements + +* Boost 1.58 or higher +* C++11 or greater +* OpenSSL (optional) + +## Building + +Beast is header-only so there are no libraries to build or link with. +To use Beast in your project, simply copy the Beast sources to your +project's source tree (alternatively, bring Beast into your Git repository +using the `git subtree` or `git submodule` commands). Then, edit your + build scripts to add the `include/` directory to the list of paths checked + by the C++ compiler when searching for includes. Beast `#include` lines + will look like this: +``` +#include +#include +``` + +To link your program successfully, you'll need to add the Boost.System +library to link with. If you use coroutines you'll also need the +Boost.Coroutine library. Please visit the Boost documentation for +instructions on how to do this for your particular build system. + +For the examples and tests, Beast provides build scripts for Boost.Build (bjam) +and CMake. Developers using Microsoft Visual Studio can generate Visual Studio +project files by executing these commands from the root of the repository: + + +``` +cd bin +cmake .. # for 32-bit Windows build + +cd ../bin64 +cmake .. # for Linux/Mac builds, OR +cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds +``` + +To build with Boost.Build, it is necessary to have the bjam executable +in your path. And bjam needs to know how to find the Boost sources. The +easiest way to do this is make sure that the version of bjam in your path +is the one at the root of the Boost source tree, which is built when +running `bootstrap.sh` (or `bootstrap.bat` on Windows). + +Once bjam is in your path, simply run bjam in the root of the Beast +repository to automatically build the required Boost libraries if they +are not already built, build the examples, then build and run the unit +tests. + +The files in the repository are laid out thusly: + +``` +./ + bin/ Holds executables and project files + bin64/ Holds 64-bit Windows executables and project files + include/ Add this to your compiler includes + beast/ + extras/ Additional APIs, may change + examples/ Self contained example programs + test/ Unit tests and benchmarks +``` + + +## Usage + +These examples are complete, self-contained programs that you can build +and run yourself (they are in the `examples` directory). + Example WebSocket program: ```C++ -#include +#include #include #include #include @@ -34,13 +163,13 @@ int main() // Normal boost::asio setup std::string const host = "echo.websocket.org"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - boost::asio::ip::tcp::socket sock(ios); + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; boost::asio::connect(sock, r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"})); // WebSocket connect and send message using beast - beast::websocket::stream ws(sock); + beast::websocket::stream ws{sock}; ws.handshake(host, "/"); ws.write(boost::asio::buffer("Hello, world!")); @@ -65,8 +194,8 @@ int main() // Normal boost::asio setup std::string const host = "boost.org"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - boost::asio::ip::tcp::socket sock(ios); + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; boost::asio::connect(sock, r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); @@ -88,12 +217,13 @@ int main() } ``` -Links: +## License -* [Home](http://vinniefalco.github.io/) -* [Repository](https://github.com/vinniefalco/Beast) -* [Documentation](http://vinniefalco.github.io/beast/) -* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html) +Distributed under the Boost Software License, Version 1.0. +(See accompanying file [LICENSE_1_0.txt](LICENSE_1_0.txt) or copy at +http://www.boost.org/LICENSE_1_0.txt) + +## Contact Please report issues or questions here: https://github.com/vinniefalco/Beast/issues diff --git a/src/beast/doc/Jamfile b/src/beast/doc/Jamfile index 48e72a0abc..35e113110e 100644 --- a/src/beast/doc/Jamfile +++ b/src/beast/doc/Jamfile @@ -15,7 +15,7 @@ using boostbook ; using quickbook ; using doxygen ; -xml beast_boostbook : beast.qbk ; +xml beast_boostbook : master.qbk ; path-constant out : . ; @@ -56,8 +56,8 @@ boostbook doc chapter.autolabel=0 boost.image.src=images/beast.png boost.image.alt="Beast Logo" - boost.image.w=1007 - boost.image.h=107 + boost.image.w=2400 + boost.image.h=80 boost.root=$(broot) chapter.autolabel=0 chunk.first.sections=1 # Chunk the first top-level section? diff --git a/src/beast/doc/design.qbk b/src/beast/doc/design.qbk index ff109d7623..b656209055 100644 --- a/src/beast/doc/design.qbk +++ b/src/beast/doc/design.qbk @@ -8,9 +8,9 @@ [section:design Design choices] The implementations are driven by business needs of cryptocurrency server -applications ([@https://ripple.com Ripple] written in C++. These -needs were not met by existing solutions so new code was written. The new -code tries to avoid design flaws encountered in the already-existing software +applications (e.g. [@https://ripple.com Ripple]) written in C++. These +needs were not met by existing solutions so Beast was written from scratch +as a solution. Beast's design philosophy avoid flaws exhibited by other libraries: * Don't sacrifice performance. @@ -44,11 +44,13 @@ to address those issues. in production. That would give some evidence that the design works in practice."" ][ - Beast.HTTP and Beast.WebSocket will be used in [*rippled], an - asynchronous peer to peer server that implements the - [*Ripple Consensus Protocol]. These servers are deployed in multiple - production environments, with banks in many countries running client - applications that connect to [*rippled]. + Beast.HTTP and Beast.WebSocket are production ready and currently + running on public servers receiving traffic and handling millions of + dollars worth of financial transactions daily. The servers run [*rippled], + open source software ([@https://github.com/ripple/rippled repository]) + implementing the + [@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]], + technology provided by [@http://ripple.com Ripple]. ]] ] @@ -171,26 +173,453 @@ start. Other design goals: [section:websocket WebSocket] [variablelist + +[[ + How does this compare to [@https://www.zaphoyd.com/websocketpp websocketpp], + an alternate header-only WebSocket implementation? +][ + [variablelist + + [[1. Synchronous Interface][ + + Beast offers full support for WebSockets using a synchronous interface. It + uses the same style of interfaces found in Boost.Asio: versions that throw + exceptions, or versions that return the error code in a reference parameter: + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]] + [websocketpp] + ][ + [``` + template + void + read(opcode& op, DynamicBuffer& dynabuf) + ```] + [ + // + ] + ]]]] + + [[2. Connection Model][ + + websocketpp supports multiple transports by utilizing a trait, the `config::transport_type` + ([@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio transport example]) + To get an idea of the complexity involved with implementing a transport, + compare the asio transport to the + [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 `iostream` transport] + (a layer that allows websocket communication over a std iostream). + + In contrast, Beast abstracts the transport by defining just one [*`NextLayer`] + template argument The type requirements for [*`NextLayer`] are + already familiar to users as they are documented in Asio: + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html SyncReadStream], + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html SyncWriteStream], + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html AsyncReadStream], and + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html AsyncWriteStream]. + The type requirements for instantiating `beast::websocket::stream` versus + `websocketpp::connection` with user defined types are vastly reduced + (18 functions versus 2). Note that websocketpp connections are passed by + `shared_ptr`. Beast does not use `shared_ptr` anywhere in its public interface. + A `beast::websocket::stream` is constructible and movable in a manner identical + `to a boost::asio::ip::tcp::socket`. Callers can put such objects in a + `shared_ptr` if they want to, but there is no requirement to do so. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]] + ][ + [``` + template + class stream + { + NextLayer next_layer_; + ... + } + ```] + [``` + template + class connection + : public config::transport_type::transport_con_type + , public config::connection_base + { + public: + typedef lib::shared_ptr ptr; + ... + } + ```] + ]]]] + + [[3. Client and Server Role][ + + websocketpp provides multi-role support through a hierarchy of + different classes. A `beast::websocket::stream` is role-agnostic, it + offers member functions to perform both client and server handshakes + in the same class. The same types are used for client and server + streams. + + [table + [ + [Beast] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp], + [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 also]] + ][ + [ + // + ] + [``` + template + class client : public endpoint,config>; + template + class server : public endpoint,config>; + ```] + ]]]] + + [[4. Thread Safety][ + + websocketpp uses mutexes to protect shared data from concurrent + access. In contrast, Beast does not use mutexes anywhere in its + implementation. Instead, it follows the Asio pattern. Calls to + asynchronous initiation functions use the same method to invoke + intermediate handlers as the method used to invoke the final handler, + through the + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asio_handler_invoke.html asio_handler_invoke] mechanism. + + The only requirement in Beast is that calls to asynchronous initiation + functions are made from the same implicit or explicit strand. For + example, if the `io_service` associated with a `beast::websocket::stream` + is single threaded, this counts as an implicit strand and no performance + costs associated with mutexes are incurred. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]] + ][ + [``` + template + friend + void asio_handler_invoke(Function&& f, read_frame_op* op) + { + return boost_asio_handler_invoke_helpers::invoke(f, op->d_->h); + } + ```] + [``` + mutex_type m_read_mutex; + ```] + ]]]] + + [[5. Callback Model][ + + websocketpp requires a one-time call to set the handler for each event + in its interface (for example, upon message receipt). The handler is + represented by a `std::function equivalent`. Its important to recognize + that the websocketpp interface performs type-erasure on this handler. + + In comparison, Beast handlers are specified in a manner identical to + Boost.Asio. They are function objects which can be copied or moved but + most importantly they are not type erased. The compiler can see + through the type directly to the implementation, permitting + optimization. Furthermore, Beast follows the Asio rules for treatment + of handlers. It respects any allocation, continuation, or invocation + customizations associated with the handler through the use of argument + dependent lookup overloads of functions such as `asio_handler_allocate`. + + The Beast completion handler is provided at the call site. For each + call to an asynchronous initiation function, it is guaranteed that + there will be exactly one final call to the handler. This functions + exactly the same way as the asynchronous initiation functions found in + Boost.Asio, allowing the composition of higher level abstractions. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp], + [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 also]] + ][ + [``` + template + typename async_completion::result_type + async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler); + ```] + [``` + typedef lib::function message_handler; + void set_message_handler(message_handler h); + ```] + ]]]] + + [[6. Extensible Asynchronous Model][ + + Beast fully supports the + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf Extensible Asynchronous Model] + developed by Christopher Kohlhoff, author of Boost.Asio (see Section 8). + + Beast websocket asynchronous interfaces may be used seamlessly with + `std::future` stackful/stackless coroutines, or user defined customizations. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]] + [websocketpp] + ][ + [``` + beast::async_completion completion(handler); + read_op{ + completion.handler, *this, op, streambuf}; + return completion.result.get(); + ```] + [ + // + ] + ]]]] + + [[7. Message Buffering][ + + websocketpp defines a message buffer, passed in arguments by + `shared_ptr`, and an associated message manager which permits + aggregation and memory reuse of memory. The implementation of + `websocketpp::message` uses a `std::string` to hold the payload. If an + incoming message is broken up into multiple frames, the string may be + reallocated for each continuation frame. The std::string always uses + the standard allocator, it is not possible to customize the choice of + allocator. + + Beast allows callers to specify the object for receiving the message + or frame data, which is of any type meeting the requirements of + [@http://vinniefalco.github.io/beast/beast/types/DynamicBuffer.html [*DynamicBuffer]] + (modeled after `boost::asio::streambuf`). + + Beast comes with the class `beast::basic_streambuf`, an efficient + implementation of the [*DynamicBuffer] concept which makes use of multiple + allocated octet arrays. If an incoming message is broken up into + multiple pieces, no reallocation occurs. Instead, new allocations are + appended to the sequence when existing allocations are filled. Beast + does not impose any particular memory management model on callers. The + `basic_streambuf` provided by beast supports standard allocators through + a template argument. Use the [*DynamicBuffer] that comes with beast, + customize the allocator if you desire, or provide your own type that + meets the + [@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/basic_streambuf.hpp#L21 concept requirements]. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]] + ][ + [``` + template + read(opcode& op, DynamicBuffer& dynabuf); + ```] + [``` + template class con_msg_manager> + class message { + public: + typedef lib::shared_ptr ptr; + ... + std::string m_payload; + ... + }; + ```] + ]]]] + + [[8. Sending Messages][ + + When sending a message, websocketpp requires that the payload is + packaged in a `websocketpp::message` object using `std::string` as the + storage, or it requires a copy of the caller provided buffer by + constructing a new message object. Messages are placed onto an + outgoing queue. An asynchronous write operation runs in the background + to clear the queue. No user facing handler can be registered to be + notified when messages or frames have completed sending. + + Beast doesn't allocate or make copies of buffers when sending data. The + caller's buffers are sent in-place. You can use any object meeting the + requirements of + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence], + permitting efficient scatter-gather I/O. + + The [*ConstBufferSequence] interface allows callers to send data from + memory-mapped regions (not possible in websocketpp). Callers can also + use the same buffers to send data to multiple streams, for example + broadcasting common subscription data to many clients at once. For + each call to `async_write` the completion handler is called once when + the data finishes sending, in a manner identical to `boost::asio::async_write`. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]] + ][ + [``` + template + void + write(ConstBufferSequence const& buffers); + ```] + [``` + lib::error_code send(std::string const & payload, + frame::opcode::value op = frame::opcode::text); + ... + lib::error_code send(message_ptr msg); + ```] + ]]]] + + [[9. Streaming Messages][ + + websocketpp requires that the entire message fit into memory, and that + the size is known ahead of time. + + Beast allows callers to compose messages in individual frames. This is + useful when the size of the data is not known ahead of time or if it + is not desired to buffer the entire message in memory at once before + sending it. For example, sending periodic output of a database query + running on a coroutine. Or sending the contents of a file in pieces, + without bringing it all into memory. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]] + [websocketpp] + ][ + [``` + template + void + write_frame(bool fin, + ConstBufferSequence const& buffers); + ```] + [ + // + ] + ]]]] + + [[10. Flow Control][ + + The websocketpp read implementation continuously reads asynchronously + from the network and buffers message data. To prevent unbounded growth + and leverage TCP/IP's flow control mechanism, callers can periodically + turn this 'read pump' off and back on. + + In contrast a `beast::websocket::stream` does not independently begin + background activity, nor does it buffer messages. It receives data only + when there is a call to an asynchronous initiation function (for + example `beast::websocket::stream::async_read`) with an associated handler. + Applications do not need to implement explicit logic to regulate the + flow of data. Instead, they follow the traditional model of issuing a + read, receiving a read completion, processing the message, then + issuing a new read and repeating the process. + + [table + [ + [Beast] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]] + ][ + [ + // + ] + [``` + lib::error_code pause_reading(); + lib::error_code resume_reading(); + ```] + ]]]] + + [[11. Connection Establishment][ + + websocketpp offers the `endpoint` class which can handle binding and + listening to a port, and spawning connection objects. + + Beast does not reinvent the wheel here, callers use the interfaces + already in `boost::asio` for receiving incoming connections resolving + host names, or establishing outgoing connections. After the socket (or + `boost::asio::ssl::stream`) is connected, the `beast::websocket::stream` + is constructed around it and the WebSocket handshake can be performed. + + Beast users are free to implement their own "connection manager", but + there is no requirement to do so. + + [table + [ + [[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/async_connect.html Beast], + [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]] + ][ + [``` + #include + ```] + [``` + template + class endpoint : public config::socket_type; + ```] + ]]]] + + [[12. WebSocket Handshaking][ + + Callers invoke `beast::websocket::accept` to perform the WebSocket + handshake, but there is no requirement to use this function. Advanced + users can perform the WebSocket handshake themselves. Beast WebSocket + provides the tools for composing the request or response, and the + Beast HTTP interface provides the container and algorithms for sending + and receiving HTTP/1 messages including the necessary HTTP Upgrade + request for establishing the WebSocket session. + + Beast allows the caller to pass the incoming HTTP Upgrade request for + the cases where the caller has already received an HTTP message. + This flexibility permits novel and robust implementations. For example, + a listening socket that can handshake in multiple protocols on the + same port. + + Sometimes callers want to read some bytes on the socket before reading + the WebSocket HTTP Upgrade request. Beast allows these already-received + bytes to be supplied to an overload of the accepting function to permit + sophisticated features. For example, a listening socket that can + accept both regular WebSocket and Secure WebSocket (SSL) connections. + + [table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast], + [@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 also]] + [websocketpp] + ][ + [``` + template + void + accept(ConstBufferSequence const& buffers); + + template + void + accept(http::request_v1 const& request); + ```] + [ + // + ] + ]]]] + + ] +]] + [[ What about message compression? ][ - The feature is not currently present in the library, but the choice - of type requirements for buffers passed to the read functions have been - made with compression in mind. There is the plan to add this feature; - however, we feel that even without compression users can begin taking - advantage of the WebSocket protocol immediately with this library. + The author is currently porting ZLib 1.2.8 to modern, header-only C++11 + that does not use macros or try to support ancient architectures. This + deflate implementation will be available as its own individually + usable interface, and also will be used to power Beast WebSocket's + permessage-deflate implementation, due Q4 of 2016. + + However, Beast currently has sufficient functionality that users can + begin taking advantage of the WebSocket protocol using this library + immediately. ]] [[ Where is the TLS/SSL interface? ][ - The `websocket::stream` just wraps the socket or stream that you - provide (for example, a `boost::asio::ip::tcp::socket` or a - `boost::asio::ssl::stream`). You establish your TLS connection - using the interface on `ssl::stream` like shown in all of the Asio - examples, they construct your `websocket::stream` around it. - It works perfectly fine - Beast.WebSocket doesn't try to reinvent the - wheel or put a fresh coat of interface paint on the `ssl::stream`. + The `websocket::stream` wraps the socket or stream that you provide + (for example, a `boost::asio::ip::tcp::socket` or a + `boost::asio::ssl::stream`). You establish your TLS connection using the + interface on `ssl::stream` like shown in all of the Asio examples, they + construct your `websocket::stream` around it. It works perfectly fine; + Beast.WebSocket doesn't try to reinvent the wheel or put a fresh coat of + interface paint on the `ssl::stream`. The WebSocket implementation [*does] provides support for shutting down the TLS connection through the use of the ADL compile-time virtual functions @@ -200,14 +629,11 @@ start. Other design goals: for TLS streams. Callers may provide their own overloads of these functions for user-defined next layer types. ]] + ] [endsect] - - - - [endsect] diff --git a/src/beast/doc/http.qbk b/src/beast/doc/http.qbk index 6089102ac9..81b89f4840 100644 --- a/src/beast/doc/http.qbk +++ b/src/beast/doc/http.qbk @@ -92,19 +92,20 @@ and its customization points in more depth, for advanced applications. [heading Declarations] To do anything, a message must be declared. The message class template -requires at mininum, a value indicating whether the message is a request +requires at minimum, a value indicating whether the message is a request (versus a response), and a `Body` type. The choice of `Body` determines the kind of container used to represent the message body. Here we will -declare a request that has a `std::string` for the body container: +declare a HTTP/1 request that has a `std::string` for the body container: ``` - http::message req; + http::message_v1 req; ``` Two type aliases are provided for notational convenience when declaring -messages. These two statements declare a request and a response respectively: +HTTP/1 messages. These two statements declare a request and a response +respectively: ``` - http::request req; - http::response resp; + http::request_v1 req; + http::response_v1 resp; ``` [heading Members] @@ -113,14 +114,14 @@ Message objects are default constructible, with public access to data members. Request and response objects have some common members, and some members unique to the message type. These statements set all the members in each message: ``` - http::request req; - req.method = http::method_t::http_get; + http::request_v1 req; + req.method = "GET"; req.url = "/index.html"; req.version = 11; // HTTP/1.1 req.headers.insert("User-Agent", "hello_world"); req.body = ""; - http::response resp; + http::response_v1 resp; resp.status = 404; resp.reason = "Not Found"; resp.version = 10; // HTTP/1.0 @@ -128,17 +129,6 @@ to the message type. These statements set all the members in each message: resp.body = "The requested resource was not found."; ``` -The following statements achieve the same effects as the statements above: -``` - http::request req({http::method_t::http_get, "/index.html", 11}); - req.headers.insert("User-Agent", "hello_world"); - req.body = ""; - - http::response resp({404, "Not Found", 10}); - resp.headers.insert("Server", "Beast.HTTP"); - resp.body = "The requested resource was not found."; -``` - [heading Headers] The `message::headers` member is a container for setting the field/value @@ -146,7 +136,7 @@ pairs in the message. These statements change the values of the headers in the message passed: ``` template - void set_fields(http::request& req) + void set_fields(http::request_v1& req) { if(! req.exists("User-Agent")) req.insert("User-Agent", "myWebClient"); @@ -168,7 +158,10 @@ following types, provided by the library, are suitable choices for the * [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body. Used in GET requests where there is no message body. Example: ``` - http::request req({http::method_t::http_get, "/index.html", 11}); + http::request_v1 req; + req.version = 11; + req.method = "GET"; + req.url = "/index.html"; ``` * [link beast.ref.http__string_body [*`string_body`:]] A body with a @@ -177,7 +170,7 @@ or response with simple text in the message body (such as an error message). Has the same insertion complexity of `std::string`. This is the type of body used in the examples: ``` - http::response resp; + http::response_v1 resp; static_assert(std::is_same::value); resp.body = "Here is the data you requested"; ``` @@ -197,7 +190,10 @@ functions: ``` void send_request(boost::asio::ip::tcp::socket& sock) { - http::request req({http::method_t::http_get, "/index.html", 11}); + http::request req; + req.version = 11; + req.method = "GET"; + req.url = "/index.html"; ... http::write(sock, req); // Throws exception on error ... @@ -213,7 +209,7 @@ An asynchronous interface is available: ``` void handle_write(boost::system::error_code); ... - http::request req; + http::request_v1 req; ... http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1)); ``` @@ -222,13 +218,13 @@ When the implementation reads messages from a socket, it can read bytes lying after the end of the message if they are present (the alternative is to read a single byte at a time which is unsuitable for performance reasons). To store and re-use these extra bytes on subsequent messages, the read interface -requires an additional paramter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]] +requires an additional parameter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]] object. This example reads a message from the socket, with the extra bytes stored in the streambuf parameter for use in a subsequent call to read: ``` boost::asio::streambuf sb; ... - http::response resp; + http::response_v1 resp; http::read(sock, sb, resp); // Throws exception on error ... // Alternatively @@ -245,7 +241,7 @@ called: void handle_read(boost::system::error_code); ... boost::asio::streambuf sb; - http::response resp; + http::response_v1 resp; ... http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1)); ``` @@ -257,7 +253,7 @@ An alternative to using a `boost::asio::streambuf` is to use a void handle_read(boost::system::error_code); ... beast::streambuf sb; - http::response resp; + http::response_v1 resp; http::read(sock, sb, resp); ``` diff --git a/src/beast/doc/images/beast.png b/src/beast/doc/images/beast.png index 3444d5814c..604a6d9bea 100644 Binary files a/src/beast/doc/images/beast.png and b/src/beast/doc/images/beast.png differ diff --git a/src/beast/doc/images/beast.psd b/src/beast/doc/images/beast.psd index 81096530f5..772a1ceee4 100644 Binary files a/src/beast/doc/images/beast.psd and b/src/beast/doc/images/beast.psd differ diff --git a/src/beast/doc/images/readme.png b/src/beast/doc/images/readme.png new file mode 100644 index 0000000000..44b53c2e6c Binary files /dev/null and b/src/beast/doc/images/readme.png differ diff --git a/src/beast/doc/makeqbk.sh b/src/beast/doc/makeqbk.sh index 584cb8a93a..f215ce4d1c 100644 --- a/src/beast/doc/makeqbk.sh +++ b/src/beast/doc/makeqbk.sh @@ -6,7 +6,7 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) mkdir -p ../bin/doc/xml -doxygen beast.dox +doxygen source.dox cd ../bin/doc/xml xsltproc combine.xslt index.xml > all.xml cd ../../../doc diff --git a/src/beast/doc/beast.qbk b/src/beast/doc/master.qbk similarity index 91% rename from src/beast/doc/beast.qbk rename to src/beast/doc/master.qbk index f9d8b89ad0..0023e72a8a 100644 --- a/src/beast/doc/beast.qbk +++ b/src/beast/doc/master.qbk @@ -39,11 +39,11 @@ [section:intro Introduction] -Beast is a cross-platform C++ library built on Boost.Asio and Boost, containing -two modules implementing widely used network protocols. Beast.HTTP offers a -universal model for describing, sending, and receiving HTTP messages while -Beast.WebSocket provides a complete implementation of the WebSocket protocol. -Their design achieves these goals: +Beast is a header-only, cross-platform C++ library built on Boost.Asio and +Boost, containing two modules implementing widely used network protocols. +Beast.HTTP offers a universal model for describing, sending, and receiving +HTTP messages while Beast.WebSocket provides a complete implementation of +the WebSocket protocol. Their design achieves these goals: * [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be used to build clients, servers, or both. @@ -106,8 +106,8 @@ int main() // Normal boost::asio setup std::string const host = "boost.org"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - boost::asio::ip::tcp::socket sock(ios); + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; boost::asio::connect(sock, r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); @@ -131,7 +131,7 @@ int main() Establish a WebSocket connection, send a message and receive the reply: ``` -#include +#include #include #include #include @@ -142,13 +142,13 @@ int main() // Normal boost::asio setup std::string const host = "echo.websocket.org"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - boost::asio::ip::tcp::socket sock(ios); + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; boost::asio::connect(sock, r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"})); // WebSocket connect and send message using beast - beast::websocket::stream ws(sock); + beast::websocket::stream ws{sock}; ws.handshake(host, "/"); ws.write(boost::asio::buffer("Hello, world!")); diff --git a/src/beast/doc/quickref.xml b/src/beast/doc/quickref.xml index d025b35676..729a0ad5fb 100644 --- a/src/beast/doc/quickref.xml +++ b/src/beast/doc/quickref.xml @@ -43,6 +43,7 @@ body_max_size headers_max_size + skip_body Type Traits @@ -85,6 +86,7 @@ ping_data stream reason_string + teardown_tag Options diff --git a/src/beast/doc/reference.xsl b/src/beast/doc/reference.xsl index 3a82f1e589..4c37e30653 100644 --- a/src/beast/doc/reference.xsl +++ b/src/beast/doc/reference.xsl @@ -5,7 +5,7 @@ Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.beast.org/LICENSE_1_0.txt) + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) --> diff --git a/src/beast/doc/beast.dox b/src/beast/doc/source.dox similarity index 100% rename from src/beast/doc/beast.dox rename to src/beast/doc/source.dox diff --git a/src/beast/doc/websocket.qbk b/src/beast/doc/websocket.qbk index da2808cc0b..ff9c235e83 100644 --- a/src/beast/doc/websocket.qbk +++ b/src/beast/doc/websocket.qbk @@ -66,7 +66,7 @@ both Boost.Asio and the WebSocket protocol specification described in -[section:creating Creating the socket] +[section:creation Creation] The interface to Beast's WebSocket implementation is a single template class [link beast.ref.websocket__stream `beast::websocket::stream`] which @@ -75,24 +75,40 @@ of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous operations are performed, or [link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous operations are performed, or both. Arguments supplied during construction are -passed to next layer's constructor. Here we declare two websockets which have -ownership of the next layer: +passed to next layer's constructor. Here we declare a websocket stream over +a TCP/IP socket with ownership of the socket: ``` boost::asio::io_service ios; beast::websocket::stream ws(ios); - -boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); -beast::websocket::stream< - boost::asio::ssl::stream> wss(ios, ctx); ``` +[heading Using SSL] + +To use WebSockets over SSL, choose an SSL stream for the next layer template +argument when constructing the stream. +``` +#include +#include +#include + +boost::asio::io_service ios; +boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); +beast::websocket::stream ws(ios, ctx); +``` + +[note + When creating websocket stream objects using SSL, it is necessary + to include the file ``. +] + +[heading Non-owning references] + For servers that can handshake in multiple protocols, it may be desired to wrap an object that already exists. This socket can be moved in: ``` boost::asio::ip::tcp::socket&& sock; ... - beast::websocket::stream< - boost::asio::ip::tcp::socket> ws(std::move(sock)); + beast::websocket::stream ws(std::move(sock)); ``` Or, the wrapper can be constructed with a non-owning reference. In @@ -108,8 +124,7 @@ The layer being wrapped can be accessed through the websocket's "next layer", permitting callers to interact directly with its interface. ``` boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); - beast::websocket::stream< - boost::asio::ssl::stream> ws(ios, ctx); + beast::websocket::stream> ws(ios, ctx); ... ws.next_layer().shutdown(); // ssl::stream shutdown ``` diff --git a/src/beast/examples/CMakeLists.txt b/src/beast/examples/CMakeLists.txt index 5b3d09721e..d4815e907f 100644 --- a/src/beast/examples/CMakeLists.txt +++ b/src/beast/examples/CMakeLists.txt @@ -1,49 +1,52 @@ # Part of Beast -GroupSources(extras/beast beast) +GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(examples "/") add_executable (http-crawl ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} urls_large_data.hpp urls_large_data.cpp http_crawl.cpp ) if (NOT WIN32) - target_link_libraries(http-crawl ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(http-crawl ${Boost_LIBRARIES} Threads::Threads) endif() add_executable (http-server ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} file_body.hpp + mime_type.hpp http_async_server.hpp - http_stream.hpp - http_stream.ipp http_sync_server.hpp http_server.cpp ) if (NOT WIN32) - target_link_libraries(http-server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(http-server ${Boost_LIBRARIES} Threads::Threads) endif() add_executable (http-example ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} http_example.cpp ) if (NOT WIN32) - target_link_libraries(http-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(http-example ${Boost_LIBRARIES} Threads::Threads) endif() add_executable (websocket-example ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} websocket_example.cpp ) if (NOT WIN32) - target_link_libraries(websocket-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(websocket-example ${Boost_LIBRARIES} Threads::Threads) endif() diff --git a/src/beast/examples/file_body.hpp b/src/beast/examples/file_body.hpp index 300444ac3a..6df8dc86d3 100644 --- a/src/beast/examples/file_body.hpp +++ b/src/beast/examples/file_body.hpp @@ -23,7 +23,7 @@ struct file_body class writer { - std::uint64_t size_; + std::uint64_t size_ = 0; std::uint64_t offset_ = 0; std::string const& path_; FILE* file_ = nullptr; diff --git a/src/beast/examples/http_async_server.hpp b/src/beast/examples/http_async_server.hpp index bcb088d160..44b808121a 100644 --- a/src/beast/examples/http_async_server.hpp +++ b/src/beast/examples/http_async_server.hpp @@ -9,10 +9,13 @@ #define BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED #include "file_body.hpp" -#include "http_stream.hpp" +#include "mime_type.hpp" +#include #include +#include #include +#include #include #include #include @@ -32,17 +35,19 @@ class http_async_server using req_type = request_v1; using resp_type = response_v1; + std::mutex m_; + bool log_ = true; boost::asio::io_service ios_; - socket_type sock_; boost::asio::ip::tcp::acceptor acceptor_; + socket_type sock_; std::string root_; std::vector thread_; public: http_async_server(endpoint_type const& ep, - int threads, std::string const& root) - : sock_(ios_) - , acceptor_(ios_) + std::size_t threads, std::string const& root) + : acceptor_(ios_) + , sock_(ios_) , root_(root) { acceptor_.open(ep.protocol()); @@ -53,7 +58,7 @@ public: std::bind(&http_async_server::on_accept, this, beast::asio::placeholders::error)); thread_.reserve(threads); - for(int i = 0; i < threads; ++i) + for(std::size_t i = 0; i < threads; ++i) thread_.emplace_back( [&] { ios_.run(); }); } @@ -67,13 +72,124 @@ public: t.join(); } + template + void + log(Args const&... args) + { + if(log_) + { + std::lock_guard lock(m_); + log_args(args...); + } + } + private: + template + class write_op + { + using alloc_type = + handler_alloc; + + struct data + { + Stream& s; + message_v1 m; + Handler h; + bool cont; + + template + data(DeducedHandler&& h_, Stream& s_, + message_v1&& m_) + : s(s_) + , m(std::move(m_)) + , h(std::forward(h_)) + , cont(boost_asio_handler_cont_helpers:: + is_continuation(h)) + { + } + }; + + std::shared_ptr d_; + + public: + write_op(write_op&&) = default; + write_op(write_op const&) = default; + + template + write_op(DeducedHandler&& h, Stream& s, Args&&... args) + : d_(std::allocate_shared(alloc_type{h}, + std::forward(h), s, + std::forward(args)...)) + { + (*this)(error_code{}, false); + } + + void + operator()(error_code ec, bool again = true) + { + auto& d = *d_; + d.cont = d.cont || again; + if(! again) + { + beast::http::async_write(d.s, d.m, std::move(*this)); + return; + } + d.h(ec); + } + + friend + void* asio_handler_allocate( + std::size_t size, write_op* op) + { + return boost_asio_handler_alloc_helpers:: + allocate(size, op->d_->h); + } + + friend + void asio_handler_deallocate( + void* p, std::size_t size, write_op* op) + { + return boost_asio_handler_alloc_helpers:: + deallocate(p, size, op->d_->h); + } + + friend + bool asio_handler_is_continuation(write_op* op) + { + return op->d_->cont; + } + + template + friend + void asio_handler_invoke(Function&& f, write_op* op) + { + return boost_asio_handler_invoke_helpers:: + invoke(f, op->d_->h); + } + }; + + template + static + void + async_write(Stream& stream, message_v1< + isRequest, Body, Headers>&& msg, + DeducedHandler&& handler) + { + write_op::type, + isRequest, Body, Headers>{std::forward( + handler), stream, std::move(msg)}; + } + class peer : public std::enable_shared_from_this { int id_; - stream stream_; + streambuf sb_; + socket_type sock_; + http_async_server& server_; boost::asio::io_service::strand strand_; - std::string root_; req_type req_; public: @@ -82,16 +198,22 @@ private: peer& operator=(peer&&) = delete; peer& operator=(peer const&) = delete; - explicit - peer(socket_type&& sock, std::string const& root) - : stream_(std::move(sock)) - , strand_(stream_.get_io_service()) - , root_(root) + peer(socket_type&& sock, http_async_server& server) + : sock_(std::move(sock)) + , server_(server) + , strand_(sock_.get_io_service()) { static int n = 0; id_ = ++n; } + void + fail(error_code ec, std::string what) + { + if(ec != boost::asio::error::operation_aborted) + server_.log("#", id_, " ", what, ": ", ec.message(), "\n"); + } + void run() { do_read(); @@ -99,43 +221,58 @@ private: void do_read() { - stream_.async_read(req_, strand_.wrap( + async_read(sock_, sb_, req_, strand_.wrap( std::bind(&peer::on_read, shared_from_this(), asio::placeholders::error))); } - void on_read(error_code ec) + void on_read(error_code const& ec) { if(ec) return fail(ec, "read"); - do_read(); auto path = req_.url; if(path == "/") path = "/index.html"; - path = root_ + path; + path = server_.root_ + path; if(! boost::filesystem::exists(path)) { - response_v1 resp; - resp.status = 404; - resp.reason = "Not Found"; - resp.version = req_.version; - resp.headers.replace("Server", "http_async_server"); - resp.body = "The file '" + path + "' was not found"; - prepare(resp); - stream_.async_write(std::move(resp), + response_v1 res; + res.status = 404; + res.reason = "Not Found"; + res.version = req_.version; + res.headers.insert("Server", "http_async_server"); + res.headers.insert("Content-Type", "text/html"); + res.body = "The file '" + path + "' was not found"; + prepare(res); + async_write(sock_, std::move(res), std::bind(&peer::on_write, shared_from_this(), asio::placeholders::error)); return; } - resp_type resp; - resp.status = 200; - resp.reason = "OK"; - resp.version = req_.version; - resp.headers.replace("Server", "http_async_server"); - resp.headers.replace("Content-Type", "text/html"); - resp.body = path; - prepare(resp); - stream_.async_write(std::move(resp), + resp_type res; + res.status = 200; + res.reason = "OK"; + res.version = req_.version; + res.headers.insert("Server", "http_async_server"); + res.headers.insert("Content-Type", mime_type(path)); + res.body = path; + try + { + prepare(res); + } + catch(std::exception const& e) + { + res = {}; + res.status = 500; + res.reason = "Internal Error"; + res.version = req_.version; + res.headers.insert("Server", "http_async_server"); + res.headers.insert("Content-Type", "text/html"); + res.body = + std::string{"An internal error occurred"} + e.what(); + prepare(res); + } + async_write(sock_, std::move(res), std::bind(&peer::on_write, shared_from_this(), asio::placeholders::error)); } @@ -144,36 +281,27 @@ private: { if(ec) fail(ec, "write"); - } - - private: - void - fail(error_code ec, std::string what) - { - if(ec != boost::asio::error::operation_aborted) - { - std::cerr << - "#" << std::to_string(id_) << " " << - what << ": " << ec.message() << std::endl; - } + do_read(); } }; void - fail(error_code ec, std::string what) + log_args() { - std::cerr << - what << ": " << ec.message() << std::endl; + } + + template + void + log_args(Arg const& arg, Args const&... args) + { + std::cerr << arg; + log_args(args...); } void - maybe_throw(error_code ec, std::string what) + fail(error_code ec, std::string what) { - if(ec) - { - fail(ec, what); - throw ec; - } + log(what, ": ", ec.message(), "\n"); } void @@ -181,12 +309,13 @@ private: { if(! acceptor_.is_open()) return; - maybe_throw(ec, "accept"); + if(ec) + return fail(ec, "accept"); socket_type sock(std::move(sock_)); acceptor_.async_accept(sock_, std::bind(&http_async_server::on_accept, this, asio::placeholders::error)); - std::make_shared(std::move(sock), root_)->run(); + std::make_shared(std::move(sock), *this)->run(); } }; diff --git a/src/beast/examples/http_crawl.cpp b/src/beast/examples/http_crawl.cpp index b995c2011b..9948851fbd 100644 --- a/src/beast/examples/http_crawl.cpp +++ b/src/beast/examples/http_crawl.cpp @@ -5,9 +5,10 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include "http_stream.hpp" #include "urls_large_data.hpp" +#include +#include #include #include @@ -31,9 +32,9 @@ int main(int, char const*[]) ip::tcp::resolver r(ios); auto it = r.resolve( ip::tcp::resolver::query{host, "http"}); - stream hs(ios); - connect(hs.lowest_layer(), it); - auto ep = hs.lowest_layer().remote_endpoint(); + ip::tcp::socket sock(ios); + connect(sock, it); + auto ep = sock.remote_endpoint(); request_v1 req; req.method = "GET"; req.url = "/"; @@ -42,10 +43,11 @@ int main(int, char const*[]) std::string(":") + std::to_string(ep.port())); req.headers.insert("User-Agent", "beast/http"); prepare(req); - hs.write(req); - response_v1 resp; - hs.read(resp); - std::cout << resp; + write(sock, req); + response_v1 res; + streambuf sb; + beast::http::read(sock, sb, res); + std::cout << res; } catch(boost::system::system_error const& ec) { diff --git a/src/beast/examples/http_example.cpp b/src/beast/examples/http_example.cpp index a7869c6c75..55d74a829c 100644 --- a/src/beast/examples/http_example.cpp +++ b/src/beast/examples/http_example.cpp @@ -15,8 +15,8 @@ int main() // Normal boost::asio setup std::string const host = "boost.org"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - boost::asio::ip::tcp::socket sock(ios); + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; boost::asio::connect(sock, r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); diff --git a/src/beast/examples/http_server.cpp b/src/beast/examples/http_server.cpp index 32d1b13b7e..246508a8e0 100644 --- a/src/beast/examples/http_server.cpp +++ b/src/beast/examples/http_server.cpp @@ -57,8 +57,13 @@ int main(int ac, char const* av[]) endpoint_type ep{address_type::from_string(ip), port}; if(sync) + { http_sync_server server(ep, root); + beast::test::sig_wait(); + } else + { http_async_server server(ep, threads, root); - beast::test::sig_wait(); + beast::test::sig_wait(); + } } diff --git a/src/beast/examples/http_stream.hpp b/src/beast/examples/http_stream.hpp deleted file mode 100644 index eb07f63786..0000000000 --- a/src/beast/examples/http_stream.hpp +++ /dev/null @@ -1,480 +0,0 @@ -// -// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// 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) -// - -#ifndef BEAST_HTTP_STREAM_H_INCLUDED -#define BEAST_HTTP_STREAM_H_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace beast { -namespace http { - -namespace detail { - -class stream_base -{ -protected: - struct op - : boost::intrusive::list_base_hook< - boost::intrusive::link_mode< - boost::intrusive::normal_link>> - { - virtual ~op() = default; - virtual void operator()() = 0; - virtual void cancel() = 0; - }; - - using op_list = typename boost::intrusive::make_list< - op, boost::intrusive::constant_time_size>::type; - - op_list wr_q_; - bool wr_active_ = false; -}; - -} // detail - -/** Provides message-oriented functionality using HTTP. - - The stream class template provides asynchronous and blocking - message-oriented functionality necessary for clients and servers - to utilize the HTTP protocol. - - @par Thread Safety - @e Distinct @e objects: Safe.@n - @e Shared @e objects: Unsafe. The application must ensure that - all asynchronous operations are performed within the same - implicit or explicit strand. - - @par Example - - To use the class template with an `ip::tcp::socket`, you would write: - - @code - http::stream hs(io_service); - @endcode - Alternatively, you can write: - @code - ip::tcp::socket sock(io_service); - http::stream hs(sock); - @endcode - - @note A stream object must not be destroyed while there are - pending asynchronous operations associated with it. - - @par Concepts - AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template> -class stream : public detail::stream_base -{ - NextLayer next_layer_; - basic_streambuf rd_buf_; - -public: - /// The type of the next layer. - using next_layer_type = - typename std::remove_reference::type; - - /// The type of the lowest layer. - using lowest_layer_type = - typename next_layer_type::lowest_layer_type; - - /// The type of endpoint of the lowest layer. - using endpoint_type = - typename lowest_layer_type::endpoint_type; - - /// The protocol of the next layer. - using protocol_type = - typename lowest_layer_type::protocol_type; - - /// The type of resolver of the next layer. - using resolver_type = - typename protocol_type::resolver; - - /** Destructor. - - @note A stream object must not be destroyed while there - are pending asynchronous operations associated with it. - */ - ~stream(); - - /** Move constructor. - - Undefined behavior if operations are active or pending. - */ - stream(stream&&) = default; - - /** Move assignment. - - Undefined behavior if operations are active or pending. - */ - stream& operator=(stream&&) = default; - - /** Construct a HTTP stream. - - This constructor creates a HTTP stream and initialises - the next layer. - - @throws Any exceptions thrown by the Stream constructor. - - @param args The arguments to be passed to initialise the - next layer. The arguments are forwarded to the next layer's - constructor. - */ - template - explicit - stream(Args&&... args); - - /** Get the io_service associated with the stream. - - This function may be used to obtain the io_service object - that the stream uses to dispatch handlers for asynchronous - operations. - - @return A reference to the io_service object that the stream - will use to dispatch handlers. Ownership is not transferred - to the caller. - */ - boost::asio::io_service& - get_io_service() - { - return next_layer_.lowest_layer().get_io_service(); - } - - /** Get a reference to the next layer. - - This function returns a reference to the next layer - in a stack of stream layers. - - @return A reference to the next layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - next_layer_type& - next_layer() - { - return next_layer_; - } - - /** Get a reference to the next layer. - - This function returns a reference to the next layer in a - stack of stream layers. - - @return A reference to the next layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - next_layer_type const& - next_layer() const - { - return next_layer_; - } - - /** Get a reference to the lowest layer. - - This function returns a reference to the lowest layer - in a stack of stream layers. - - @return A reference to the lowest layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - lowest_layer_type& - lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /** Get a reference to the lowest layer. - - This function returns a reference to the lowest layer - in a stack of stream layers. - - @return A reference to the lowest layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - lowest_layer_type const& - lowest_layer() const - { - return next_layer_.lowest_layer(); - } - - /** Cancel pending operations. - - This will cancel all of the asynchronous operations pending, - including pipelined writes that have not been started. Handlers for - canceled writes will be called with - `boost::asio::error::operation_aborted`. - - @throws boost::system::system_error Thrown on failure. - */ - void - cancel() - { - error_code ec; - cancel(ec); - if(ec) - throw system_error{ec}; - } - - /** Cancel pending operations. - - This will cancel all of the asynchronous operations pending, - including pipelined writes that have not been started. Handlers for - canceled writes will be called with - `boost::asio::error::operation_aborted`. - - @param ec Set to indicate what error occurred, if any. - */ - void - cancel(error_code& ec); - - /** Read a HTTP message from the stream. - - This function is used to read a single HTTP message from the stream. - The call will block until one of the followign conditions is true: - - @li A message has been read. - - @li An error occurred. - - The operation is implemented in terms of zero or more calls to the - next layer's `read_some` function. - - @param msg An object used to store the message. The previous - contents of the object will be overwritten. - - @throws boost::system::system_error Thrown on failure. - */ - template - void - read(message_v1& msg) - { - error_code ec; - read(msg, ec); - if(ec) - throw system_error{ec}; - } - - /** Read a HTTP message from the stream. - - This function is used to read a single HTTP message from the stream. - The call will block until one of the followign conditions is true: - - @li A message has been read. - - @li An error occurred. - - The operation is implemented in terms of zero or more calls to the - next layer's `read_some` function. - - @param msg An object used to store the message. The previous - contents of the object will be overwritten. - - @param ec Set to indicate what error occurred, if any. - */ - template - void - read(message_v1& msg, - error_code& ec); - - /** Start reading a HTTP message from the stream asynchronously. - - This function is used to asynchronously read a single HTTP message - from the stream. The function call always returns immediately. The - asynchronous operation will continue until one of the following - conditions is true: - - @li The message has been written. - - @li An error occurred. - - This operation is implemented in terms of zero or more calls to the - next layer's async_read_some function, and is known as a composed - operation. The program must ensure that the stream performs no other - read operations or any other composed operations that perform reads - until this operation completes. - - @param msg An object used to store the message. The previous - contents of the object will be overwritten. Ownership of the message - is not transferred; the caller must guarantee that the object remains - valid until the handler is called. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - */ - template -#if GENERATING_DOCS - void_or_deduced -#else - typename async_completion< - ReadHandler, void(error_code)>::result_type -#endif - async_read(message_v1& msg, - ReadHandler&& handler); - - /** Write a HTTP message to the stream. - - This function is used to write a single HTTP message to the - stream. The call will block until one of the following conditions - is true: - - @li The entire message is sent. - - @li An error occurred. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, - `boost::asio::error::eof` is thrown after the message is sent. - successfuly. The caller is responsible for actually closing the - connection. For regular TCP/IP streams this means shutting down the - send side, while SSL streams may call the SSL shutdown function. - - @param msg The message to send. - - @throws boost::system::system_error Thrown on failure. - */ - template - void - write(message_v1 const& msg) - { - error_code ec; - write(msg, ec); - if(ec) - throw system_error{ec}; - } - - /** Write a HTTP message to the stream. - - This function is used to write a single HTTP message to the - stream. The call will block until one of the following conditions - is true: - - @li The entire message is sent. - - @li An error occurred. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, - `boost::asio::error::eof` is returned after the message is sent. - successfuly. The caller is responsible for actually closing the - connection. For regular TCP/IP streams this means shutting down the - send side, while SSL streams may call the SSL shutdown function. - - @param msg The message to send. - - @param ec Set to the error, if any occurred. - */ - template - void - write(message_v1 const& msg, - error_code& ec); - - /** Start pipelining a HTTP message to the stream asynchronously. - - This function is used to queue a message to be sent on the stream. - Unlike the free function, this version will place the message on an - outgoing message queue if there is already a write pending. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, the handler - is called with the error `boost::asio::error::eof` after the message - has been sent successfully. The caller is responsible for actually - closing the connection. For regular TCP/IP streams this means - shutting down the send side, while SSL streams may call the SSL - `async_shutdown` function. - - @param msg The message to send. A copy of the message will be made. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - */ - template -#if GENERATING_DOCS - void_or_deduced -#else - typename async_completion< - WriteHandler, void(error_code)>::result_type -#endif - async_write(message_v1 const& msg, - WriteHandler&& handler); - - /** Start pipelining a HTTP message to the stream asynchronously. - - This function is used to queue a message to be sent on the stream. - Unlike the free function, this version will place the message on an - outgoing message queue if there is already a write pending. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, the handler - is called with the error boost::asio::error::eof. The caller is - responsible for actually closing the connection. For regular - TCP/IP streams this means shutting down the send side, while SSL - streams may call the SSL async_shutdown function. - - @param msg The message to send. Ownership of the message, which - must be movable, is transferred to the implementation. The message - will not be destroyed until the asynchronous operation completes. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - */ - template - #if GENERATING_DOCS - void_or_deduced - #else - typename async_completion< - WriteHandler, void(error_code)>::result_type - #endif - async_write(message_v1&& msg, - WriteHandler&& handler); - -private: - template class read_op; - template class write_op; - - void - cancel_all(); -}; - -} // http -} // beast - -#include "http_stream.ipp" - -#endif diff --git a/src/beast/examples/http_stream.ipp b/src/beast/examples/http_stream.ipp deleted file mode 100644 index 4e9df6e77d..0000000000 --- a/src/beast/examples/http_stream.ipp +++ /dev/null @@ -1,412 +0,0 @@ -// -// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// 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) -// - -#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED -#define BEAST_HTTP_STREAM_IPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace beast { -namespace http { - -template -template -class stream::read_op -{ - using alloc_type = - handler_alloc; - - struct data - { - stream& s; - message_v1& m; - Handler h; - bool cont; - int state = 0; - - template - data(DeducedHandler&& h_, stream& s_, - message_v1& m_) - : s(s_) - , m(m_) - , h(std::forward(h_)) - , cont(boost_asio_handler_cont_helpers:: - is_continuation(h)) - { - } - }; - - std::shared_ptr d_; - -public: - read_op(read_op&&) = default; - read_op(read_op const&) = default; - - template - read_op(DeducedHandler&& h, - stream& s, Args&&... args) - : d_(std::allocate_shared(alloc_type{h}, - std::forward(h), s, - std::forward(args)...)) - { - (*this)(error_code{}, false); - } - - void operator()(error_code const& ec, bool again = true); - - friend - void* asio_handler_allocate( - std::size_t size, read_op* op) - { - return boost_asio_handler_alloc_helpers:: - allocate(size, op->d_->h); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_op* op) - { - return boost_asio_handler_alloc_helpers:: - deallocate(p, size, op->d_->h); - } - - friend - bool asio_handler_is_continuation(read_op* op) - { - return op->d_->cont; - } - - template - friend - void asio_handler_invoke(Function&& f, read_op* op) - { - return boost_asio_handler_invoke_helpers:: - invoke(f, op->d_->h); - } -}; - -template -template -void -stream:: -read_op:: -operator()(error_code const& ec, bool again) -{ - auto& d = *d_; - d.cont = d.cont || again; - while(! ec && d.state != 99) - { - switch(d.state) - { - case 0: - d.state = 99; - beast::http::async_read(d.s.next_layer_, - d.s.rd_buf_, d.m, std::move(*this)); - return; - } - } - d.h(ec); -} - -//------------------------------------------------------------------------------ - -template -template -class stream::write_op : public op -{ - using alloc_type = - handler_alloc; - - struct data - { - stream& s; - message_v1 m; - Handler h; - bool cont; - int state = 0; - - template - data(DeducedHandler&& h_, stream& s_, - message_v1 const& m_, - bool cont_) - : s(s_) - , m(m_) - , h(std::forward(h_)) - , cont(cont_) - { - } - - template - data(DeducedHandler&& h_, stream& s_, - message_v1&& m_, - bool cont_) - : s(s_) - , m(std::move(m_)) - , h(std::forward(h_)) - , cont(cont_) - { - } - }; - - std::shared_ptr d_; - -public: - write_op(write_op&&) = default; - write_op(write_op const&) = default; - - template - write_op(DeducedHandler&& h, - stream& s, Args&&... args) - : d_(std::allocate_shared(alloc_type{h}, - std::forward(h), s, - std::forward(args)...)) - { - } - - void - operator()() override - { - (*this)(error_code{}, false); - } - - void cancel() override; - - void operator()(error_code const& ec, bool again = true); - - friend - void* asio_handler_allocate( - std::size_t size, write_op* op) - { - return boost_asio_handler_alloc_helpers:: - allocate(size, op->d_->h); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_op* op) - { - return boost_asio_handler_alloc_helpers:: - deallocate(p, size, op->d_->h); - } - - friend - bool asio_handler_is_continuation(write_op* op) - { - return op->d_->cont; - } - - template - friend - void asio_handler_invoke(Function&& f, write_op* op) - { - return boost_asio_handler_invoke_helpers:: - invoke(f, op->d_->h); - } -}; - -template -template -void -stream:: -write_op:: -cancel() -{ - auto& d = *d_; - d.s.get_io_service().post( - bind_handler(std::move(*this), - boost::asio::error::operation_aborted)); -} - -template -template -void -stream:: -write_op:: -operator()(error_code const& ec, bool again) -{ - auto& d = *d_; - d.cont = d.cont || again; - while(! ec && d.state != 99) - { - switch(d.state) - { - case 0: - d.state = 99; - beast::http::async_write(d.s.next_layer_, - d.m, std::move(*this)); - return; - } - } - d.h(ec); - if(! d.s.wr_q_.empty()) - { - auto& op = d.s.wr_q_.front(); - op(); - // VFALCO Use allocator - delete &op; - d.s.wr_q_.pop_front(); - } - else - { - d.s.wr_active_ = false; - } -} - -//------------------------------------------------------------------------------ - -template -stream:: -~stream() -{ - // Can't destroy with pending operations! - assert(wr_q_.empty()); -} - -template -template -stream:: -stream(Args&&... args) - : next_layer_(std::forward(args)...) -{ -} - -template -void -stream:: -cancel(error_code& ec) -{ - cancel_all(); - lowest_layer().cancel(ec); -} - -template -template -void -stream:: -read(message_v1& msg, - error_code& ec) -{ - beast::http::read(next_layer_, rd_buf_, msg, ec); -} - -template -template -auto -stream:: -async_read(message_v1& msg, - ReadHandler&& handler) -> - typename async_completion< - ReadHandler, void(error_code)>::result_type -{ - async_completion< - ReadHandler, void(error_code) - > completion(handler); - read_op{ - completion.handler, *this, msg}; - return completion.result.get(); -} - -template -template -void -stream:: -write(message_v1 const& msg, - error_code& ec) -{ - beast::http::write(next_layer_, msg, ec); -} - -template -template -auto -stream:: -async_write(message_v1 const& msg, - WriteHandler&& handler) -> - typename async_completion< - WriteHandler, void(error_code)>::result_type -{ - async_completion< - WriteHandler, void(error_code)> completion(handler); - auto const cont = wr_active_ || - boost_asio_handler_cont_helpers::is_continuation(handler); - if(! wr_active_) - { - wr_active_ = true; - write_op{ - completion.handler, *this, msg, cont }(); - } - else - { - // VFALCO Use allocator - wr_q_.push_back(*new write_op( - completion.handler, *this, msg, cont)); - } - return completion.result.get(); -} - -template -template -auto -stream:: -async_write(message_v1&& msg, - WriteHandler&& handler) -> - typename async_completion< - WriteHandler, void(error_code)>::result_type -{ - async_completion< - WriteHandler, void(error_code)> completion(handler); - auto const cont = wr_active_ || - boost_asio_handler_cont_helpers::is_continuation(handler); - if(! wr_active_) - { - wr_active_ = true; - write_op{completion.handler, - *this, std::move(msg), cont}(); - } - else - { - // VFALCO Use allocator - wr_q_.push_back(*new write_op(completion.handler, - *this, std::move(msg), cont)); - } - return completion.result.get(); -} - -template -void -stream:: -cancel_all() -{ - for(auto it = wr_q_.begin(); it != wr_q_.end();) - { - auto& op = *it++; - op.cancel(); - // VFALCO Use allocator - delete &op; - } - wr_q_.clear(); -} - -} // http -} // beast - -#endif diff --git a/src/beast/examples/http_sync_server.hpp b/src/beast/examples/http_sync_server.hpp index af3f1d196e..8370684723 100644 --- a/src/beast/examples/http_sync_server.hpp +++ b/src/beast/examples/http_sync_server.hpp @@ -9,8 +9,9 @@ #define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED #include "file_body.hpp" -#include "http_stream.hpp" +#include "mime_type.hpp" +#include #include #include #include @@ -34,6 +35,8 @@ class http_sync_server using req_type = request_v1; using resp_type = response_v1; + bool log_ = true; + std::mutex m_; boost::asio::io_service ios_; socket_type sock_; boost::asio::ip::tcp::acceptor acceptor_; @@ -65,21 +68,43 @@ public: thread_.join(); } + template void - fail(error_code ec, std::string what) + log(Args const&... args) { - std::cerr << - what << ": " << ec.message() << std::endl; + if(log_) + { + std::lock_guard lock(m_); + log_args(args...); + } + } + +private: + void + log_args() + { + } + + template + void + log_args(Arg const& arg, Args const&... args) + { + std::cerr << arg; + log_args(args...); } void - maybe_throw(error_code ec, std::string what) + fail(error_code ec, std::string what) { - if(ec) - { - fail(ec, what); - throw ec; - } + log(what, ": ", ec.message(), "\n"); + } + + void + fail(int id, error_code const& ec) + { + if(ec != boost::asio::error::operation_aborted && + ec != boost::asio::error::eof) + log("#", id, " ", ec.message(), "\n"); } struct lambda @@ -109,7 +134,8 @@ public: { if(! acceptor_.is_open()) return; - maybe_throw(ec, "accept"); + if(ec) + return fail(ec, "accept"); static int id_ = 0; std::thread{lambda{++id_, *this, std::move(sock_)}}.detach(); acceptor_.async_accept(sock_, @@ -118,23 +144,15 @@ public: } void - fail(int id, error_code const& ec) + do_peer(int id, socket_type&& sock0) { - if(ec != boost::asio::error::operation_aborted && - ec != boost::asio::error::eof) - std::cerr << - "#" << std::to_string(id) << " " << std::endl; - } - - void - do_peer(int id, socket_type&& sock) - { - http::stream hs(std::move(sock)); + socket_type sock(std::move(sock0)); + streambuf sb; error_code ec; for(;;) { req_type req; - hs.read(req, ec); + http::read(sock, sb, req, ec); if(ec) break; auto path = req.url; @@ -143,26 +161,42 @@ public: path = root_ + path; if(! boost::filesystem::exists(path)) { - response_v1 resp; - resp.status = 404; - resp.reason = "Not Found"; - resp.version = req.version; - resp.headers.replace("Server", "http_sync_server"); - resp.body = "The file '" + path + "' was not found"; - prepare(resp); - hs.write(resp, ec); + response_v1 res; + res.status = 404; + res.reason = "Not Found"; + res.version = req.version; + res.headers.insert("Server", "http_sync_server"); + res.headers.insert("Content-Type", "text/html"); + res.body = "The file '" + path + "' was not found"; + prepare(res); + write(sock, res, ec); if(ec) break; } - resp_type resp; - resp.status = 200; - resp.reason = "OK"; - resp.version = req.version; - resp.headers.replace("Server", "http_sync_server"); - resp.headers.replace("Content-Type", "text/html"); - resp.body = path; - prepare(resp); - hs.write(resp, ec); + resp_type res; + res.status = 200; + res.reason = "OK"; + res.version = req.version; + res.headers.insert("Server", "http_sync_server"); + res.headers.insert("Content-Type", mime_type(path)); + res.body = path; + try + { + prepare(res); + } + catch(std::exception const& e) + { + res = {}; + res.status = 500; + res.reason = "Internal Error"; + res.version = req.version; + res.headers.insert("Server", "http_sync_server"); + res.headers.insert("Content-Type", "text/html"); + res.body = + std::string{"An internal error occurred"} + e.what(); + prepare(res); + } + write(sock, res, ec); if(ec) break; } diff --git a/src/beast/examples/mime_type.hpp b/src/beast/examples/mime_type.hpp new file mode 100644 index 0000000000..d20aa605a4 --- /dev/null +++ b/src/beast/examples/mime_type.hpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// 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) +// + +#ifndef BEAST_EXAMPLE_HTTP_MIME_TYPE_H_INCLUDED +#define BEAST_EXAMPLE_HTTP_MIME_TYPE_H_INCLUDED + +#include +#include + +namespace beast { +namespace http { + +// Return the Mime-Type for a given file extension +template +std::string +mime_type(std::string const& path) +{ + auto const ext = + boost::filesystem::path{path}.extension().string(); + if(ext == ".txt") return "text/plain"; + if(ext == ".htm") return "text/html"; + if(ext == ".html") return "text/html"; + if(ext == ".php") return "text/html"; + if(ext == ".css") return "text/css"; + if(ext == ".js") return "application/javascript"; + if(ext == ".json") return "application/json"; + if(ext == ".xml") return "application/xml"; + if(ext == ".swf") return "application/x-shockwave-flash"; + if(ext == ".flv") return "video/x-flv"; + if(ext == ".png") return "image/png"; + if(ext == ".jpe") return "image/jpeg"; + if(ext == ".jpeg") return "image/jpeg"; + if(ext == ".jpg") return "image/jpeg"; + if(ext == ".gif") return "image/gif"; + if(ext == ".bmp") return "image/bmp"; + if(ext == ".ico") return "image/vnd.microsoft.icon"; + if(ext == ".tiff") return "image/tiff"; + if(ext == ".tif") return "image/tiff"; + if(ext == ".svg") return "image/svg+xml"; + if(ext == ".svgz") return "image/svg+xml"; + return "application/text"; +} + +} // http +} // beast + +#endif diff --git a/src/beast/examples/websocket_example.cpp b/src/beast/examples/websocket_example.cpp index 671af037d8..e9978d5a6f 100644 --- a/src/beast/examples/websocket_example.cpp +++ b/src/beast/examples/websocket_example.cpp @@ -16,13 +16,13 @@ int main() // Normal boost::asio setup std::string const host = "echo.websocket.org"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - boost::asio::ip::tcp::socket sock(ios); + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; boost::asio::connect(sock, r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"})); // WebSocket connect and send message using beast - beast::websocket::stream ws(sock); + beast::websocket::stream ws{sock}; ws.handshake(host, "/"); ws.write(boost::asio::buffer("Hello, world!")); diff --git a/src/beast/extras/beast/test/fail_counter.hpp b/src/beast/extras/beast/test/fail_counter.hpp index 28e1c90c98..b58e1f1263 100644 --- a/src/beast/extras/beast/test/fail_counter.hpp +++ b/src/beast/extras/beast/test/fail_counter.hpp @@ -15,7 +15,9 @@ namespace test { enum error { - fail_error = 1 + success = 0, + + fail_error }; namespace detail { diff --git a/src/beast/extras/beast/test/fail_stream.hpp b/src/beast/extras/beast/test/fail_stream.hpp index 1c3a34e267..47742d06cc 100644 --- a/src/beast/extras/beast/test/fail_stream.hpp +++ b/src/beast/extras/beast/test/fail_stream.hpp @@ -161,19 +161,21 @@ public: friend void - teardown(fail_stream& stream, - boost::system::error_code& ec) + teardown(websocket::teardown_tag, + fail_stream& stream, + boost::system::error_code& ec) { if(stream.pfc_->fail(ec)) return; - websocket_helpers::call_teardown(stream.next_layer(), ec); + beast::websocket_helpers::call_teardown(stream.next_layer(), ec); } template friend void - async_teardown(fail_stream& stream, - TeardownHandler&& handler) + async_teardown(websocket::teardown_tag, + fail_stream& stream, + TeardownHandler&& handler) { error_code ec; if(stream.pfc_->fail(ec)) @@ -182,7 +184,7 @@ public: bind_handler(std::move(handler), ec)); return; } - websocket_helpers::call_async_teardown( + beast::websocket_helpers::call_async_teardown( stream.next_layer(), std::forward(handler)); } }; diff --git a/src/beast/extras/beast/unit_test/amount.hpp b/src/beast/extras/beast/unit_test/amount.hpp index b4c1f72e37..ebe76efda8 100644 --- a/src/beast/extras/beast/unit_test/amount.hpp +++ b/src/beast/extras/beast/unit_test/amount.hpp @@ -23,29 +23,29 @@ private: std::string const& what_; public: - amount (amount const&) = default; - amount& operator= (amount const&) = delete; + amount(amount const&) = default; + amount& operator=(amount const&) = delete; - template - amount (std::size_t n, std::string const& what); + template + amount(std::size_t n, std::string const& what); friend std::ostream& - operator<< (std::ostream& s, amount const& t); + operator<<(std::ostream& s, amount const& t); }; -template -amount::amount (std::size_t n, std::string const& what) - : n_ (n) - , what_ (what) +template +amount::amount(std::size_t n, std::string const& what) + : n_(n) + , what_(what) { } inline std::ostream& -operator<< (std::ostream& s, amount const& t) +operator<<(std::ostream& s, amount const& t) { - s << t.n_ << " " << t.what_ << ((t.n_ != 1) ? "s" : ""); + s << t.n_ << " " << t.what_ <<((t.n_ != 1) ? "s" : ""); return s; } diff --git a/src/beast/extras/beast/unit_test/detail/const_container.hpp b/src/beast/extras/beast/unit_test/detail/const_container.hpp index bf34318f5e..a4910f01ec 100644 --- a/src/beast/extras/beast/unit_test/detail/const_container.hpp +++ b/src/beast/extras/beast/unit_test/detail/const_container.hpp @@ -16,7 +16,7 @@ namespace detail { The interface allows for limited read only operations. Derived classes provide additional behavior. */ -template +template class const_container { private: diff --git a/src/beast/extras/beast/unit_test/dstream.hpp b/src/beast/extras/beast/unit_test/dstream.hpp index 2bd8e59032..b3d26ca5ea 100644 --- a/src/beast/extras/beast/unit_test/dstream.hpp +++ b/src/beast/extras/beast/unit_test/dstream.hpp @@ -8,11 +8,10 @@ #ifndef BEAST_UNIT_TEST_DSTREAM_HPP #define BEAST_UNIT_TEST_DSTREAM_HPP -#include -#include +#include #include #include -#include +#include #include #ifdef _MSC_VER @@ -30,15 +29,18 @@ namespace beast { namespace unit_test { -namespace detail { - #ifdef _MSC_VER +namespace detail { + template class dstream_buf : public std::basic_stringbuf { + using ostream = std::basic_ostream; + bool dbg_; + ostream& os_; template void write(T const*) = delete; @@ -47,21 +49,21 @@ class dstream_buf { if(dbg_) OutputDebugStringA(s); - else - std::cout << s; + os_ << s; } void write(wchar_t const* s) { if(dbg_) OutputDebugStringW(s); - else - std::wcout << s; + os_ << s; } public: - dstream_buf() - : dbg_(IsDebuggerPresent() != FALSE) + explicit + dstream_buf(ostream& os) + : os_(os) + , dbg_(IsDebuggerPresent() != FALSE) { } @@ -79,66 +81,52 @@ public: } }; -#else - -template -class dstream_buf - : public std::basic_stringbuf -{ - template - void write(T const*) = delete; - - void write(char const* s) - { - std::cout << s; - } - - void write(wchar_t const* s) - { - std::wcout << s; - } - -public: - ~dstream_buf() - { - sync(); - } - - int - sync() override - { - write(this->str().c_str()); - this->str(""); - return 0; - } -}; - -#endif - } // detail -/// A std::ostream that redirects output to the debugger if attached. +/** std::ostream with Visual Studio IDE redirection. + + Instances of this stream wrap a specified `std::ostream` + (such as `std::cout` or `std::cerr`). If the IDE debugger + is attached when the stream is created, output will be + additionally copied to the Visual Studio Output window. +*/ template< class CharT, class Traits = std::char_traits, class Allocator = std::allocator > class basic_dstream - : private boost::base_from_member< - detail::dstream_buf> - , public std::basic_ostream + : public std::basic_ostream { + detail::dstream_buf< + CharT, Traits, Allocator> buf_; + public: - basic_dstream() - : std::basic_ostream(&this->member) + /** Construct a stream. + + @param os The output stream to wrap. + */ + explicit + basic_dstream(std::ostream& os) + : std::basic_ostream(&buf_) + , buf_(os) { + if(os.flags() && std::ios::unitbuf) + std::unitbuf(*this); } }; using dstream = basic_dstream; using dwstream = basic_dstream; -} // test +#else + +using dstream = std::ostream&; +using dwstream = std::wostream&; + +#endif + +} // unit_test } // beast #endif diff --git a/src/beast/extras/beast/unit_test/main.cpp b/src/beast/extras/beast/unit_test/main.cpp index d461ea83b3..1da1de32be 100644 --- a/src/beast/extras/beast/unit_test/main.cpp +++ b/src/beast/extras/beast/unit_test/main.cpp @@ -33,7 +33,7 @@ static std::string prefix(suite_info const& s) { - if (s.manual()) + if(s.manual()) return "|M| "; return " "; } @@ -45,7 +45,7 @@ print(std::ostream& os, suite_list const& c) std::size_t manual = 0; for(auto const& s : c) { - os << prefix (s) << s.full_name() << '\n'; + os << prefix(s) << s.full_name() << '\n'; if(s.manual()) ++manual; } @@ -80,18 +80,18 @@ int main(int ac, char const* av[]) #ifdef _MSC_VER { - int flags = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG); + int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); flags |= _CRTDBG_LEAK_CHECK_DF; - _CrtSetDbgFlag (flags); + _CrtSetDbgFlag(flags); } #endif namespace po = boost::program_options; po::options_description desc("Options"); desc.add_options() - ("help,h", "Produce a help message") - ("print,r", "Print the list of available test suites") - ("suites,s", po::value(), "suites to run") + ("help,h", "Produce a help message") + ("print,p", "Print the list of available test suites") + ("suites,s", po::value(), "suites to run") ; po::positional_options_description p; @@ -99,7 +99,8 @@ int main(int ac, char const* av[]) po::store(po::parse_command_line(ac, av, desc), vm); po::notify(vm); - dstream log; + dstream log{std::cerr}; + std::unitbuf(log); if(vm.count("help")) { @@ -121,7 +122,7 @@ int main(int ac, char const* av[]) match_auto(suites)); else failed = r.run_each(global_suites()); - if (failed) + if(failed) return EXIT_FAILURE; return EXIT_SUCCESS; } diff --git a/src/beast/extras/beast/unit_test/match.hpp b/src/beast/extras/beast/unit_test/match.hpp index 9137fd0e15..8e0e9b6447 100644 --- a/src/beast/extras/beast/unit_test/match.hpp +++ b/src/beast/extras/beast/unit_test/match.hpp @@ -45,42 +45,42 @@ private: std::string library_; public: - template + template explicit - selector (mode_t mode, std::string const& pattern = ""); + selector(mode_t mode, std::string const& pattern = ""); - template + template bool - operator() (suite_info const& s); + operator()(suite_info const& s); }; //------------------------------------------------------------------------------ -template -selector::selector (mode_t mode, std::string const& pattern) - : mode_ (mode) - , pat_ (pattern) +template +selector::selector(mode_t mode, std::string const& pattern) + : mode_(mode) + , pat_(pattern) { - if (mode_ == automatch && pattern.empty()) + if(mode_ == automatch && pattern.empty()) mode_ = all; } -template +template bool -selector::operator() (suite_info const& s) +selector::operator()(suite_info const& s) { - switch (mode_) + switch(mode_) { case automatch: // suite or full name - if (s.name() == pat_ || s.full_name() == pat_) + if(s.name() == pat_ || s.full_name() == pat_) { mode_ = none; return true; } // check module - if (pat_ == s.module()) + if(pat_ == s.module()) { mode_ = module; library_ = s.library(); @@ -88,7 +88,7 @@ selector::operator() (suite_info const& s) } // check library - if (pat_ == s.library()) + if(pat_ == s.library()) { mode_ = library; return ! s.manual(); @@ -138,9 +138,9 @@ selector::operator() (suite_info const& s) */ inline selector -match_auto (std::string const& name) +match_auto(std::string const& name) { - return selector (selector::automatch, name); + return selector(selector::automatch, name); } /** Return a predicate that matches all suites not marked manual. */ @@ -148,23 +148,23 @@ inline selector match_all() { - return selector (selector::all); + return selector(selector::all); } /** Returns a predicate that matches a specific suite. */ inline selector -match_suite (std::string const& name) +match_suite(std::string const& name) { - return selector (selector::suite, name); + return selector(selector::suite, name); } /** Returns a predicate that matches all suites in a library. */ inline selector -match_library (std::string const& name) +match_library(std::string const& name) { - return selector (selector::library, name); + return selector(selector::library, name); } } // unit_test diff --git a/src/beast/extras/beast/unit_test/recorder.hpp b/src/beast/extras/beast/unit_test/recorder.hpp index e17e9a01f3..72cc3ac73b 100644 --- a/src/beast/extras/beast/unit_test/recorder.hpp +++ b/src/beast/extras/beast/unit_test/recorder.hpp @@ -24,8 +24,8 @@ private: public: recorder() = default; - recorder (recorder const&) = default; - recorder& operator= (recorder const&) = default; + recorder(recorder const&) = default; + recorder& operator=(recorder const&) = default; /** Returns a report with the results of all completed suites. */ results const& @@ -37,31 +37,31 @@ public: private: virtual void - on_suite_begin (suite_info const& info) override + on_suite_begin(suite_info const& info) override { - m_suite = suite_results (info.full_name()); + m_suite = suite_results(info.full_name()); } virtual void on_suite_end() override { - m_results.insert (std::move (m_suite)); + m_results.insert(std::move(m_suite)); } virtual void - on_case_begin (std::string const& name) override + on_case_begin(std::string const& name) override { - m_case = case_results (name); + m_case = case_results(name); } virtual void on_case_end() override { - if (m_case.tests.size() > 0) - m_suite.insert (std::move (m_case)); + if(m_case.tests.size() > 0) + m_suite.insert(std::move(m_case)); } virtual @@ -73,16 +73,16 @@ private: virtual void - on_fail (std::string const& reason) override + on_fail(std::string const& reason) override { - m_case.tests.fail (reason); + m_case.tests.fail(reason); } virtual void - on_log (std::string const& s) override + on_log(std::string const& s) override { - m_case.log.insert (s); + m_case.log.insert(s); } }; diff --git a/src/beast/extras/beast/unit_test/reporter.hpp b/src/beast/extras/beast/unit_test/reporter.hpp index 2d155946c9..9b771cd6d2 100644 --- a/src/beast/extras/beast/unit_test/reporter.hpp +++ b/src/beast/extras/beast/unit_test/reporter.hpp @@ -56,7 +56,7 @@ private: typename clock_type::time_point start = clock_type::now(); explicit - suite_results(std::string const& name_ = "") + suite_results(std::string name_ = "") : name(std::move(name_)) { } @@ -83,7 +83,7 @@ private: typename clock_type::time_point start = clock_type::now(); void - add (suite_results const& r); + add(suite_results const& r); }; std::ostream& os_; @@ -107,7 +107,7 @@ private: virtual void - on_suite_begin (suite_info const& info) override; + on_suite_begin(suite_info const& info) override; virtual void @@ -115,7 +115,7 @@ private: virtual void - on_case_begin (std::string const& name) override; + on_case_begin(std::string const& name) override; virtual void @@ -127,11 +127,11 @@ private: virtual void - on_fail (std::string const& reason) override; + on_fail(std::string const& reason) override; virtual void - on_log (std::string const& s) override; + on_log(std::string const& s) override; }; //------------------------------------------------------------------------------ @@ -156,7 +156,7 @@ results::add(suite_results const& r) cases += r.cases; failed += r.failed; auto const elapsed = clock_type::now() - r.start; - if (elapsed >= std::chrono::seconds{1}) + if(elapsed >= std::chrono::seconds{1}) { auto const iter = std::lower_bound(top.begin(), top.end(), elapsed, @@ -165,13 +165,13 @@ results::add(suite_results const& r) { return t1.second > t2; }); - if (iter != top.end()) + if(iter != top.end()) { - if (top.size() == max_top) + if(top.size() == max_top) top.resize(top.size() - 1); top.emplace(iter, r.name, elapsed); } - else if (top.size() < max_top) + else if(top.size() < max_top) { top.emplace_back(r.name, elapsed); } @@ -213,11 +213,11 @@ reporter<_>::fmtdur(typename clock_type::duration const& d) { using namespace std::chrono; auto const ms = duration_cast(d); - if (ms < seconds{1}) + if(ms < seconds{1}) return std::to_string(ms.count()) + "ms"; std::stringstream ss; ss << std::fixed << std::setprecision(1) << - (ms.count()/1000.) << "s"; + (ms.count()/1000.) << "s"; return ss.str(); } @@ -241,11 +241,10 @@ void reporter<_>:: on_case_begin(std::string const& name) { - case_results_ = case_results (name); - os_ << - suite_results_.name << - (case_results_.name.empty() ? - "" : (" " + case_results_.name)) << std::endl; + case_results_ = case_results(name); + os_ << suite_results_.name << + (case_results_.name.empty() ? "" : + (" " + case_results_.name)) << std::endl; } template @@ -273,7 +272,7 @@ on_fail(std::string const& reason) ++case_results_.total; os_ << "#" << case_results_.total << " failed" << - (reason.empty() ? "" : ": ") << reason << std::endl; + (reason.empty() ? "" : ": ") << reason << std::endl; } template diff --git a/src/beast/extras/beast/unit_test/results.hpp b/src/beast/extras/beast/unit_test/results.hpp index acc1710856..12b2add931 100644 --- a/src/beast/extras/beast/unit_test/results.hpp +++ b/src/beast/extras/beast/unit_test/results.hpp @@ -23,14 +23,14 @@ public: /** Holds the result of evaluating one test condition. */ struct test { - explicit test (bool pass_) - : pass (pass_) + explicit test(bool pass_) + : pass(pass_) { } - test (bool pass_, std::string const& reason_) - : pass (pass_) - , reason (reason_) + test(bool pass_, std::string const& reason_) + : pass(pass_) + , reason(reason_) { } @@ -46,8 +46,8 @@ private: std::size_t failed_; public: - tests_t () - : failed_ (0) + tests_t() + : failed_(0) { } @@ -69,15 +69,15 @@ private: void pass() { - cont().emplace_back (true); + cont().emplace_back(true); } /** Register a failed test condition. */ void - fail (std::string const& reason = "") + fail(std::string const& reason = "") { ++failed_; - cont().emplace_back (false, reason); + cont().emplace_back(false, reason); } }; @@ -87,17 +87,17 @@ private: public: /** Insert a string into the log. */ void - insert (std::string const& s) + insert(std::string const& s) { - cont().push_back (s); + cont().push_back(s); } }; std::string name_; public: - explicit case_results (std::string const& name = "") - : name_ (name) + explicit case_results(std::string const& name = "") + : name_(name) { } @@ -127,8 +127,8 @@ private: std::size_t failed_ = 0; public: - explicit suite_results (std::string const& name = "") - : name_ (name) + explicit suite_results(std::string const& name = "") + : name_(name) { } @@ -156,17 +156,17 @@ public: /** Insert a set of testcase results. */ /** @{ */ void - insert (case_results&& r) + insert(case_results&& r) { - cont().emplace_back (std::move (r)); + cont().emplace_back(std::move(r)); total_ += r.tests.total(); failed_ += r.tests.failed(); } void - insert (case_results const& r) + insert(case_results const& r) { - cont().push_back (r); + cont().push_back(r); total_ += r.tests.total(); failed_ += r.tests.failed(); } @@ -187,9 +187,9 @@ private: public: results() - : m_cases (0) - , total_ (0) - , failed_ (0) + : m_cases(0) + , total_(0) + , failed_(0) { } @@ -217,21 +217,21 @@ public: /** Insert a set of suite results. */ /** @{ */ void - insert (suite_results&& r) + insert(suite_results&& r) { m_cases += r.size(); total_ += r.total(); failed_ += r.failed(); - cont().emplace_back (std::move (r)); + cont().emplace_back(std::move(r)); } void - insert (suite_results const& r) + insert(suite_results const& r) { m_cases += r.size(); total_ += r.total(); failed_ += r.failed(); - cont().push_back (r); + cont().push_back(r); } /** @} */ }; diff --git a/src/beast/extras/beast/unit_test/runner.hpp b/src/beast/extras/beast/unit_test/runner.hpp index 038985659d..3530c46b55 100644 --- a/src/beast/extras/beast/unit_test/runner.hpp +++ b/src/beast/extras/beast/unit_test/runner.hpp @@ -18,6 +18,7 @@ namespace beast { namespace unit_test { /** Unit test runner interface. + Derived classes can customize the reporting behavior. This interface is injected into the unit_test class to receive the results of the tests. */ @@ -60,7 +61,7 @@ public: */ template bool - run (suite_info const& s); + run(suite_info const& s); /** Run a sequence of suites. The expression @@ -68,44 +69,40 @@ public: must be convertible to `suite_info`. @return `true` if any conditions failed. */ - template + template bool - run (FwdIter first, FwdIter last); + run(FwdIter first, FwdIter last); /** Conditionally run a sequence of suites. pred will be called as: @code - bool pred (suite_info const&); + bool pred(suite_info const&); @endcode @return `true` if any conditions failed. */ - template + template bool - run_if (FwdIter first, FwdIter last, Pred pred = Pred{}); + run_if(FwdIter first, FwdIter last, Pred pred = Pred{}); /** Run all suites in a container. @return `true` if any conditions failed. */ - template + template bool - run_each (SequenceContainer const& c); + run_each(SequenceContainer const& c); /** Conditionally run suites in a container. pred will be called as: @code - bool pred (suite_info const&); + bool pred(suite_info const&); @endcode @return `true` if any conditions failed. */ - template + template bool - run_each_if (SequenceContainer const& c, Pred pred = Pred{}); + run_each_if(SequenceContainer const& c, Pred pred = Pred{}); protected: - // - // Overrides - // - /// Called when a new suite starts. virtual void @@ -159,130 +156,130 @@ private: friend class suite; // Start a new testcase. - template + template void - testcase (std::string const& name); + testcase(std::string const& name); - template + template void pass(); - template + template void - fail (std::string const& reason); + fail(std::string const& reason); - template + template void - log (std::string const& s); + log(std::string const& s); }; //------------------------------------------------------------------------------ -template +template bool -runner::run (suite_info const& s) +runner::run(suite_info const& s) { // Enable 'default' testcase default_ = true; failed_ = false; - on_suite_begin (s); - s.run (*this); + on_suite_begin(s); + s.run(*this); // Forgot to call pass or fail. - assert (cond_); + assert(cond_); on_case_end(); on_suite_end(); return failed_; } -template +template bool -runner::run (FwdIter first, FwdIter last) +runner::run(FwdIter first, FwdIter last) { - bool failed (false); - for (;first != last; ++first) - failed = run (*first) || failed; + bool failed(false); + for(;first != last; ++first) + failed = run(*first) || failed; return failed; } -template +template bool -runner::run_if (FwdIter first, FwdIter last, Pred pred) +runner::run_if(FwdIter first, FwdIter last, Pred pred) { - bool failed (false); - for (;first != last; ++first) - if (pred (*first)) - failed = run (*first) || failed; + bool failed(false); + for(;first != last; ++first) + if(pred(*first)) + failed = run(*first) || failed; return failed; } -template +template bool -runner::run_each (SequenceContainer const& c) +runner::run_each(SequenceContainer const& c) { - bool failed (false); - for (auto const& s : c) - failed = run (s) || failed; + bool failed(false); + for(auto const& s : c) + failed = run(s) || failed; return failed; } -template +template bool -runner::run_each_if (SequenceContainer const& c, Pred pred) +runner::run_each_if(SequenceContainer const& c, Pred pred) { - bool failed (false); - for (auto const& s : c) - if (pred (s)) - failed = run (s) || failed; + bool failed(false); + for(auto const& s : c) + if(pred(s)) + failed = run(s) || failed; return failed; } -template +template void -runner::testcase (std::string const& name) +runner::testcase(std::string const& name) { std::lock_guard lock(mutex_); // Name may not be empty - assert (default_ || ! name.empty()); + assert(default_ || ! name.empty()); // Forgot to call pass or fail - assert (default_ || cond_); - if (! default_) + assert(default_ || cond_); + if(! default_) on_case_end(); default_ = false; cond_ = false; - on_case_begin (name); + on_case_begin(name); } -template +template void runner::pass() { std::lock_guard lock(mutex_); - if (default_) - testcase (""); + if(default_) + testcase(""); on_pass(); cond_ = true; } -template +template void -runner::fail (std::string const& reason) +runner::fail(std::string const& reason) { std::lock_guard lock(mutex_); - if (default_) - testcase (""); - on_fail (reason); + if(default_) + testcase(""); + on_fail(reason); failed_ = true; cond_ = true; } -template +template void -runner::log (std::string const& s) +runner::log(std::string const& s) { std::lock_guard lock(mutex_); - if (default_) - testcase (""); - on_log (s); + if(default_) + testcase(""); + on_log(s); } } // unit_test diff --git a/src/beast/extras/beast/unit_test/suite.hpp b/src/beast/extras/beast/unit_test/suite.hpp index 476c0b0aac..ab12f1c6e1 100644 --- a/src/beast/extras/beast/unit_test/suite.hpp +++ b/src/beast/extras/beast/unit_test/suite.hpp @@ -9,6 +9,7 @@ #define BEAST_UNIT_TEST_SUITE_HPP #include +#include #include #include #include @@ -72,7 +73,7 @@ private: { auto const& s = this->str(); if(s.size() > 0) - suite_.runner_->on_log(s); + suite_.runner_->log(s); this->str(""); return 0; } @@ -127,7 +128,7 @@ private: scoped_testcase operator()(abort_t abort); - template + template scoped_testcase operator<<(T const& t); }; @@ -146,7 +147,9 @@ public: /** Returns the "current" running suite. If no suite is running, nullptr is returned. */ - static suite* this_suite() + static + suite* + this_suite() { return *p_this_suite(); } @@ -158,6 +161,7 @@ public: } /** Invokes the test using the specified runner. + Data members are set up here instead of the constructor as a convenience to writing the derived class to avoid repetition of forwarded constructor arguments to the base. @@ -165,67 +169,95 @@ public: */ template void - operator() (runner& r); + operator()(runner& r); + + /** Record a successful test condition. */ + template + void + pass(); + + /** Record a failure. + + @param reason + */ + template + void + fail(std::string const& reason = ""); /** Evaluate a test condition. - The condition is passed as a template argument instead of `bool` so - that implicit conversion is not required. The `reason` argument is - logged if the condition is false. + + This function provides improved logging by incorporating the + file name and line number into the reported output on failure, + as well as additional text specified by the caller. + + @param shouldBeTrue The condition to test. The condition + is evaluated in a boolean context. + + @param reason Optional added text to output on a failure. + + @param file The source code file where the test failed. + + @param line The source code line number where the test failed. + @return `true` if the test condition indicates success. */ - template - bool - expect(Condition const& shouldBeTrue, - String const& reason); - + /** @{ */ template bool expect(Condition const& shouldBeTrue) { - return expect(shouldBeTrue, ""); + return expect(shouldBeTrue, {}); } - /** Expect an exception from f() */ - /** @{ */ - template + template bool - except (F&& f, String const& reason); + expect(Condition const& shouldBeTrue, std::string const& reason); - template + template bool - except (F&& f) + expect(Condition const& shouldBeTrue, + char const* file, int line) + { + return expect(shouldBeTrue, {}, file, line); + } + + template + bool + expect(Condition const& shouldBeTrue, + std::string const& reason, char const* file, int line); + /** @} */ + + // + // DEPRECATED + // + // Expect an exception from f() + template + bool + except(F&& f, String const& reason); + template + bool + except(F&& f) { return except(f, ""); } - /** @} */ - - /** Expect an exception of the given type from f() */ - /** @{ */ - template + template bool - except (F&& f, String const& reason); - - template + except(F&& f, String const& reason); + template bool - except (F&& f) + except(F&& f) { return except(f, ""); } - /** @} */ - - /** Fail if f() throws */ - /** @{ */ - template + template bool - unexcept (F&& f, String const& reason); - - template + unexcept(F&& f, String const& reason); + template bool - unexcept (F&& f) + unexcept(F&& f) { return unexcept(f, ""); } - /** @} */ /** Return the argument associated with the runner. */ std::string const& @@ -235,29 +267,19 @@ public: } // DEPRECATED - // @return `true` if the test condition indicates success (a false value) - template + // @return `true` if the test condition indicates success(a false value) + template bool - unexpected (Condition shouldBeFalse, + unexpected(Condition shouldBeFalse, String const& reason); - template + template bool - unexpected (Condition shouldBeFalse) + unexpected(Condition shouldBeFalse) { - return unexpected (shouldBeFalse, ""); + return unexpected(shouldBeFalse, ""); } - /** Record a successful test condition. */ - template - void - pass(); - - /** Record a failure. */ - template - void - fail (std::string const& reason = ""); - private: friend class thread; @@ -277,9 +299,9 @@ private: void propagate_abort(); - template + template void - run (runner& r); + run(runner& r); }; //------------------------------------------------------------------------------ @@ -298,7 +320,10 @@ public: { auto const& name = ss_.str(); if(! name.empty()) - suite_.runner_->testcase (name); + { + suite_.log.flush(); + suite_.runner_->testcase(name); + } } scoped_testcase(suite& self, std::stringstream& ss) @@ -333,16 +358,17 @@ public: inline void -suite::testcase_t::operator() (std::string const& name, - abort_t abort) +suite::testcase_t::operator()( + std::string const& name, abort_t abort) { suite_.abort_ = abort == abort_on_fail; - suite_.runner_->testcase (name); + suite_.log.flush(); + suite_.runner_->testcase(name); } inline suite::scoped_testcase -suite::testcase_t::operator() (abort_t abort) +suite::testcase_t::operator()(abort_t abort) { suite_.abort_ = abort == abort_on_fail; return { suite_, ss_ }; @@ -351,7 +377,7 @@ suite::testcase_t::operator() (abort_t abort) template inline suite::scoped_testcase -suite::testcase_t::operator<< (T const& t) +suite::testcase_t::operator<<(T const& t) { return { suite_, ss_, t }; } @@ -360,7 +386,8 @@ suite::testcase_t::operator<< (T const& t) template void -suite::operator()(runner& r) +suite:: +operator()(runner& r) { *p_this_suite() = this; try @@ -375,11 +402,11 @@ suite::operator()(runner& r) } } -template -inline +template bool -suite::expect(Condition const& shouldBeTrue, - String const& reason) +suite:: +expect( + Condition const& shouldBeTrue, std::string const& reason) { if(shouldBeTrue) { @@ -390,9 +417,35 @@ suite::expect(Condition const& shouldBeTrue, return false; } -template +template bool -suite::except (F&& f, String const& reason) +suite:: +expect(Condition const& shouldBeTrue, + std::string const& reason, char const* file, int line) +{ + if(shouldBeTrue) + { + pass(); + return true; + } + std::string s; + if(! reason.empty()) + { + s += reason; + s += " "; + } + s += boost::filesystem::path{file}.filename().string() + + "(" + std::to_string(line) + ")"; + fail(s); + return false; +} + +// DEPRECATED + +template +bool +suite:: +except(F&& f, String const& reason) { try { @@ -407,9 +460,10 @@ suite::except (F&& f, String const& reason) return true; } -template +template bool -suite::except (F&& f, String const& reason) +suite:: +except(F&& f, String const& reason) { try { @@ -424,9 +478,10 @@ suite::except (F&& f, String const& reason) return true; } -template +template bool -suite::unexcept (F&& f, String const& reason) +suite:: +unexcept(F&& f, String const& reason) { try { @@ -441,36 +496,39 @@ suite::unexcept (F&& f, String const& reason) return false; } -template -inline +template bool -suite::unexpected (Condition shouldBeFalse, - String const& reason) +suite:: +unexpected( + Condition shouldBeFalse, String const& reason) { bool const b = static_cast(shouldBeFalse); - if (! b) + if(! b) pass(); else - fail (reason); + fail(reason); return ! b; } -template +template void -suite::pass() +suite:: +pass() { propagate_abort(); runner_->pass(); } -template +// ::fail +template void -suite::fail (std::string const& reason) +suite:: +fail(std::string const& reason) { propagate_abort(); - runner_->fail (reason); - if (abort_) + runner_->fail(reason); + if(abort_) { aborted_ = true; throw abort_exception(); @@ -479,15 +537,17 @@ suite::fail (std::string const& reason) inline void -suite::propagate_abort() +suite:: +propagate_abort() { - if (abort_ && aborted_) + if(abort_ && aborted_) throw abort_exception(); } -template +template void -suite::run (runner& r) +suite:: +run(runner& r) { runner_ = &r; @@ -495,21 +555,37 @@ suite::run (runner& r) { run(); } - catch (abort_exception const&) + catch(abort_exception const&) { // ends the suite } - catch (std::exception const& e) + catch(std::exception const& e) { - runner_->fail ("unhandled exception: " + - std::string (e.what())); + runner_->fail("unhandled exception: " + + std::string(e.what())); } - catch (...) + catch(...) { - runner_->fail ("unhandled exception"); + runner_->fail("unhandled exception"); } } +#ifndef BEAST_EXPECT +/** Check a precondition. + + If the condition is false, the file and line number are reported. +*/ +#define BEAST_EXPECT(cond) expect(cond, __FILE__, __LINE__) +#endif + +#ifndef BEAST_EXPECTS +/** Check a precondition. + + If the condition is false, the file and line number are reported. +*/ +#define BEAST_EXPECTS(cond, reason) expect(cond, reason, __FILE__, __LINE__) +#endif + } // unit_test } // beast @@ -519,7 +595,7 @@ suite::run (runner& r) // This inserts the suite with the given manual flag #define BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,manual) \ static beast::unit_test::detail::insert_suite \ - Library ## Module ## Class ## _test_instance ( \ + Library ## Module ## Class ## _test_instance( \ #Class, #Module, #Library, manual) //------------------------------------------------------------------------------ diff --git a/src/beast/extras/beast/unit_test/suite_info.hpp b/src/beast/extras/beast/unit_test/suite_info.hpp index 428d81ee13..8e1d0f5ca4 100644 --- a/src/beast/extras/beast/unit_test/suite_info.hpp +++ b/src/beast/extras/beast/unit_test/suite_info.hpp @@ -80,7 +80,7 @@ public: void run(runner& r) const { - run_ (r); + run_(r); } friend diff --git a/src/beast/extras/beast/unit_test/suite_list.hpp b/src/beast/extras/beast/unit_test/suite_list.hpp index d8f62c5df6..77020e9223 100644 --- a/src/beast/extras/beast/unit_test/suite_list.hpp +++ b/src/beast/extras/beast/unit_test/suite_list.hpp @@ -33,7 +33,7 @@ public: The suite must not already exist. */ - template + template void insert( char const* name, @@ -44,7 +44,7 @@ public: //------------------------------------------------------------------------------ -template +template void suite_list::insert( char const* name, @@ -56,14 +56,14 @@ suite_list::insert( { std::string s; s = std::string(library) + "." + module + "." + name; - auto const result (names_.insert(s)); - assert (result.second); // Duplicate name + auto const result(names_.insert(s)); + assert(result.second); // Duplicate name } { - auto const result (classes_.insert ( - std::type_index (typeid(Suite)))); - assert (result.second); // Duplicate type + auto const result(classes_.insert( + std::type_index(typeid(Suite)))); + assert(result.second); // Duplicate type } #endif cont().emplace(make_suite_info( diff --git a/src/beast/extras/beast/unit_test/thread.hpp b/src/beast/extras/beast/unit_test/thread.hpp index 5e8364b891..0de8577a03 100644 --- a/src/beast/extras/beast/unit_test/thread.hpp +++ b/src/beast/extras/beast/unit_test/thread.hpp @@ -28,31 +28,31 @@ public: using native_handle_type = std::thread::native_handle_type; thread() = default; - thread (thread const&) = delete; - thread& operator= (thread const&) = delete; + thread(thread const&) = delete; + thread& operator=(thread const&) = delete; - thread (thread&& other) - : s_ (other.s_) - , t_ (std::move(other.t_)) + thread(thread&& other) + : s_(other.s_) + , t_(std::move(other.t_)) { } - thread& operator= (thread&& other) + thread& operator=(thread&& other) { s_ = other.s_; t_ = std::move(other.t_); return *this; } - template + template explicit - thread (suite& s, F&& f, Args&&... args) - : s_ (&s) + thread(suite& s, F&& f, Args&&... args) + : s_(&s) { std::function b = std::bind(std::forward(f), std::forward(args)...); - t_ = std::thread (&thread::run, this, + t_ = std::thread(&thread::run, this, std::move(b)); } @@ -89,7 +89,7 @@ public: } void - swap (thread& other) + swap(thread& other) { std::swap(s_, other.s_); std::swap(t_, other.t_); @@ -97,23 +97,23 @@ public: private: void - run (std::function f) + run(std::function f) { try { f(); } - catch (suite::abort_exception const&) + catch(suite::abort_exception const&) { } - catch (std::exception const& e) + catch(std::exception const& e) { - s_->fail ("unhandled exception: " + - std::string (e.what())); + s_->fail("unhandled exception: " + + std::string(e.what())); } - catch (...) + catch(...) { - s_->fail ("unhandled exception"); + s_->fail("unhandled exception"); } } }; diff --git a/src/beast/include/beast/core/async_completion.hpp b/src/beast/include/beast/core/async_completion.hpp index 51c2e29039..dc39d5caa8 100644 --- a/src/beast/include/beast/core/async_completion.hpp +++ b/src/beast/include/beast/core/async_completion.hpp @@ -47,7 +47,7 @@ namespace beast { @note See Library Foundations For Asynchronous Operations */ -template +template struct async_completion { /** The type of the final handler called by the asynchronous initiation function. diff --git a/src/beast/include/beast/core/buffers_adapter.hpp b/src/beast/include/beast/core/buffers_adapter.hpp index fa116a29c5..23adee1651 100644 --- a/src/beast/include/beast/core/buffers_adapter.hpp +++ b/src/beast/include/beast/core/buffers_adapter.hpp @@ -14,10 +14,10 @@ namespace beast { -/** Adapts a @b `MutableBufferSequence` into a @b `Streambuf`. +/** Adapts a @b `MutableBufferSequence` into a @b `DynamicBuffer`. This class wraps a @b `MutableBufferSequence` to meet the requirements - of @b `Streambuf`. Upon construction the input and output sequences are + of @b `DynamicBuffer`. Upon construction the input and output sequences are empty. A copy of the mutable buffer sequence object is stored; however, ownership of the underlying memory is not transferred. The caller is responsible for making sure that referenced memory remains valid diff --git a/src/beast/include/beast/core/detail/base64.hpp b/src/beast/include/beast/core/detail/base64.hpp index 0256aa7d0b..801562d512 100644 --- a/src/beast/include/beast/core/detail/base64.hpp +++ b/src/beast/include/beast/core/detail/base64.hpp @@ -44,7 +44,7 @@ namespace detail { */ -template +template std::string const& base64_alphabet() { @@ -62,7 +62,7 @@ is_base64(unsigned char c) return (std::isalnum(c) || (c == '+') || (c == '/')); } -template +template std::string base64_encode (std::uint8_t const* data, std::size_t in_len) @@ -112,7 +112,7 @@ base64_encode (std::uint8_t const* data, } -template +template std::string base64_encode (std::string const& s) { @@ -120,11 +120,11 @@ base64_encode (std::string const& s) std::uint8_t const*> (s.data()), s.size()); } -template +template std::string base64_decode(std::string const& data) { - int in_len = data.size(); + auto in_len = data.size(); unsigned char c3[3], c4[4]; int i = 0; int j = 0; diff --git a/src/beast/include/beast/core/detail/bind_handler.hpp b/src/beast/include/beast/core/detail/bind_handler.hpp index 849ab619f0..6b540c2811 100644 --- a/src/beast/include/beast/core/detail/bind_handler.hpp +++ b/src/beast/include/beast/core/detail/bind_handler.hpp @@ -54,14 +54,14 @@ public: operator()() { invoke(h_, args_, - index_sequence_for ()); + index_sequence_for()); } void operator()() const { invoke(h_, args_, - index_sequence_for ()); + index_sequence_for()); } friend diff --git a/src/beast/include/beast/core/detail/empty_base_optimization.hpp b/src/beast/include/beast/core/detail/empty_base_optimization.hpp index 1be8ccde4b..635f71ff1a 100644 --- a/src/beast/include/beast/core/detail/empty_base_optimization.hpp +++ b/src/beast/include/beast/core/detail/empty_base_optimization.hpp @@ -14,7 +14,7 @@ namespace beast { namespace detail { -template +template struct empty_base_optimization_decide : std::integral_constant ::value @@ -25,7 +25,7 @@ struct empty_base_optimization_decide { }; -template < +template< class T, int UniqueID = 0, bool ShouldDeriveFrom = @@ -57,7 +57,7 @@ public: //------------------------------------------------------------------------------ -template < +template< class T, int UniqueID > diff --git a/src/beast/include/beast/core/detail/is_call_possible.hpp b/src/beast/include/beast/core/detail/is_call_possible.hpp index c14dbd3482..076c9ce22e 100644 --- a/src/beast/include/beast/core/detail/is_call_possible.hpp +++ b/src/beast/include/beast/core/detail/is_call_possible.hpp @@ -13,7 +13,7 @@ namespace beast { namespace detail { -template +template auto is_call_possible_test(C&& c, int, A&& ...a) -> decltype(std::is_convertible< @@ -21,7 +21,7 @@ is_call_possible_test(C&& c, int, A&& ...a) std::is_same::value, std::true_type()); -template +template std::false_type is_call_possible_test(C&& c, long, A&& ...a); @@ -30,13 +30,13 @@ is_call_possible_test(C&& c, long, A&& ...a); is_call_possible */ /** @{ */ -template +template struct is_call_possible : std::false_type { }; -template +template struct is_call_possible : decltype(is_call_possible_test( std::declval(), 1, std::declval()...)) diff --git a/src/beast/include/beast/core/detail/sha1.hpp b/src/beast/include/beast/core/detail/sha1.hpp index a868568f11..4aa83037a5 100644 --- a/src/beast/include/beast/core/detail/sha1.hpp +++ b/src/beast/include/beast/core/detail/sha1.hpp @@ -281,10 +281,10 @@ finish(sha1_context& ctx, void* digest) noexcept ctx.buf[ctx.buflen++] = 0x00; std::uint32_t block[BLOCK_INTS]; sha1::make_block(ctx.buf, block); - if (buflen > BLOCK_BYTES - 8) + if(buflen > BLOCK_BYTES - 8) { sha1::transform(ctx.digest, block); - for (size_t i = 0; i < BLOCK_INTS - 2; i++) + for(size_t i = 0; i < BLOCK_INTS - 2; i++) block[i] = 0; } diff --git a/src/beast/include/beast/core/detail/stream_concepts.hpp b/src/beast/include/beast/core/detail/stream_concepts.hpp index 39edccedce..b71557f660 100644 --- a/src/beast/include/beast/core/detail/stream_concepts.hpp +++ b/src/beast/include/beast/core/detail/stream_concepts.hpp @@ -34,7 +34,7 @@ class has_get_io_service decltype(std::declval().get_io_service()), boost::asio::io_service&>> static R check(int); - template + template static std::false_type check(...); public: using type = decltype(check(0)); diff --git a/src/beast/include/beast/core/dynabuf_readstream.hpp b/src/beast/include/beast/core/dynabuf_readstream.hpp index 9e8199db8b..be7465f4fe 100644 --- a/src/beast/include/beast/core/dynabuf_readstream.hpp +++ b/src/beast/include/beast/core/dynabuf_readstream.hpp @@ -227,7 +227,7 @@ public: /// Write the given data to the stream. Returns the number of bytes written, /// or 0 if an error occurred. - template + template std::size_t write_some(ConstBufferSequence const& buffers, error_code& ec) diff --git a/src/beast/include/beast/core/handler_alloc.hpp b/src/beast/include/beast/core/handler_alloc.hpp index cc12eace1a..50fc0929fb 100644 --- a/src/beast/include/beast/core/handler_alloc.hpp +++ b/src/beast/include/beast/core/handler_alloc.hpp @@ -34,10 +34,10 @@ namespace beast { caller is still responsible for freeing memory. */ #if GENERATING_DOCS -template +template class handler_alloc; #else -template +template class handler_alloc { private: @@ -46,7 +46,7 @@ private: // should produce a compile error if CompletionHandler is not // constructible from H. // - template + template friend class handler_alloc; CompletionHandler h_; diff --git a/src/beast/include/beast/core/impl/dynabuf_readstream.ipp b/src/beast/include/beast/core/impl/dynabuf_readstream.ipp index a0fbd9b169..73e75afc7f 100644 --- a/src/beast/include/beast/core/impl/dynabuf_readstream.ipp +++ b/src/beast/include/beast/core/impl/dynabuf_readstream.ipp @@ -85,7 +85,7 @@ public: is_continuation(op->d_->h); } - template + template friend void asio_handler_invoke(Function&& f, read_some_op* op) { diff --git a/src/beast/include/beast/core/static_streambuf.hpp b/src/beast/include/beast/core/static_streambuf.hpp index 2166ba200a..eb1f6c9cc1 100644 --- a/src/beast/include/beast/core/static_streambuf.hpp +++ b/src/beast/include/beast/core/static_streambuf.hpp @@ -129,7 +129,7 @@ protected: //------------------------------------------------------------------------------ -/** A `Streambuf` with a fixed size internal buffer. +/** A `DynamicBuffer` with a fixed size internal buffer. @tparam N The number of bytes in the internal buffer. diff --git a/src/beast/include/beast/core/streambuf.hpp b/src/beast/include/beast/core/streambuf.hpp index 468c8dfa52..1726543f17 100644 --- a/src/beast/include/beast/core/streambuf.hpp +++ b/src/beast/include/beast/core/streambuf.hpp @@ -12,14 +12,14 @@ namespace beast { -/** A @b `Streambuf` that uses multiple buffers internally. +/** A @b `DynamicBuffer` that uses multiple buffers internally. The implementation uses a sequence of one or more character arrays of varying sizes. Additional character array objects are appended to the sequence to accommodate changes in the size of the character sequence. - @note Meets the requirements of @b `Streambuf`. + @note Meets the requirements of @b `DynamicBuffer`. */ using streambuf = basic_streambuf>; diff --git a/src/beast/include/beast/http/basic_headers.hpp b/src/beast/include/beast/http/basic_headers.hpp index ee6b3b0f86..8972ae3435 100644 --- a/src/beast/include/beast/http/basic_headers.hpp +++ b/src/beast/include/beast/http/basic_headers.hpp @@ -105,7 +105,7 @@ protected: using list_t = typename boost::intrusive::make_list< element, boost::intrusive::constant_time_size>::type; - using set_t = typename boost::intrusive::make_set< + using set_t = typename boost::intrusive::make_multiset< element, boost::intrusive::constant_time_size, boost::intrusive::compare>::type; @@ -117,7 +117,6 @@ protected: : set_(std::move(set)) , list_(std::move(list)) { - } public: @@ -244,9 +243,10 @@ public: value. Field names are stored as-is, but comparison are case-insensitive. - The container preserves the order of insertion of fields with - different names. For fields with the same name, the implementation - concatenates values inserted with duplicate names as per rfc7230. + When the container is iterated, the fields are presented in the order + of insertion. For fields with the same name, the container behaves + as a std::multiset; there will be a separate value for each occurrence + of the field name. @note Meets the requirements of @b `FieldSequence`. */ @@ -359,27 +359,44 @@ public: return set_.size(); } - /** Returns `true` if the specified field exists. */ + /// Returns `true` if the specified field exists. bool exists(boost::string_ref const& name) const { return set_.find(name, less{}) != set_.end(); } - /** Returns an iterator to the case-insensitive matching header. */ + /// Returns the number of values for the specified field. + std::size_t + count(boost::string_ref const& name) const; + + /** Returns an iterator to the case-insensitive matching field name. + + If more than one field with the specified name exists, the + first field defined by insertion order is returned. + */ iterator find(boost::string_ref const& name) const; - /** Returns the value for a case-insensitive matching header, or "" */ + /** Returns the value for a case-insensitive matching header, or `""`. + + If more than one field with the specified name exists, the + first field defined by insertion order is returned. + */ boost::string_ref operator[](boost::string_ref const& name) const; - /** Clear the contents of the basic_headers. */ + /// Clear the contents of the basic_headers. void clear() noexcept; /** Remove a field. + If more than one field with the specified name exists, all + matching fields will be removed. + + @param name The name of the field(s) to remove. + @return The number of fields removed. */ std::size_t @@ -387,39 +404,57 @@ public: /** Insert a field value. - If a field value already exists the new value will be - extended as per RFC2616 Section 4.2. + If a field with the same name already exists, the + existing field is untouched and a new field value pair + is inserted into the container. + + @param name The name of the field. + + @param value A string holding the value of the field. */ - // VFALCO TODO Consider allowing rvalue references for std::move? void insert(boost::string_ref const& name, boost::string_ref value); /** Insert a field value. - If a field value already exists the new value will be - extended as per RFC2616 Section 4.2. + If a field with the same name already exists, the + existing field is untouched and a new field value pair + is inserted into the container. + + @param name The name of the field + + @param value The value of the field. The object will be + converted to a string using `boost::lexical_cast`. */ template typename std::enable_if< ! std::is_constructible::value>::type insert(boost::string_ref name, T const& value) { - insert(name, - boost::lexical_cast(value)); + insert(name, boost::lexical_cast(value)); } /** Replace a field value. - The current field value, if any, is removed. Then the - specified value is inserted as if by `insert(field, value)`. + First removes any values with matching field names, then + inserts the new field value. + + @param name The name of the field. + + @param value A string holding the value of the field. */ void replace(boost::string_ref const& name, boost::string_ref value); /** Replace a field value. - The current field value, if any, is removed. Then the - specified value is inserted as if by `insert(field, value)`. + First removes any values with matching field names, then + inserts the new field value. + + @param name The name of the field + + @param value The value of the field. The object will be + converted to a string using `boost::lexical_cast`. */ template typename std::enable_if< diff --git a/src/beast/include/beast/http/basic_parser_v1.hpp b/src/beast/include/beast/http/basic_parser_v1.hpp index 871f04cdad..555d3f6ea7 100644 --- a/src/beast/include/beast/http/basic_parser_v1.hpp +++ b/src/beast/include/beast/http/basic_parser_v1.hpp @@ -482,7 +482,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -501,7 +501,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -520,7 +520,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -539,7 +539,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -557,7 +557,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -575,7 +575,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -594,7 +594,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -613,7 +613,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -630,7 +630,7 @@ private: decltype(std::declval().on_headers( std::declval(), std::declval()))>> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -649,7 +649,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -667,7 +667,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: diff --git a/src/beast/include/beast/http/detail/chunk_encode.hpp b/src/beast/include/beast/http/detail/chunk_encode.hpp index db38ee8819..62accf1638 100644 --- a/src/beast/include/beast/http/detail/chunk_encode.hpp +++ b/src/beast/include/beast/http/detail/chunk_encode.hpp @@ -29,7 +29,7 @@ class chunk_encode_text // Storage for the longest hex string we might need, plus delimiters. std::array buf_; - template + template static OutIter to_hex(OutIter last, std::size_t n) diff --git a/src/beast/include/beast/http/detail/has_content_length.hpp b/src/beast/include/beast/http/detail/has_content_length.hpp index 6ec167c9f4..09584a5eab 100644 --- a/src/beast/include/beast/http/detail/has_content_length.hpp +++ b/src/beast/include/beast/http/detail/has_content_length.hpp @@ -22,7 +22,7 @@ class has_content_length_value decltype(std::declval().content_length()), std::uint64_t>> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: diff --git a/src/beast/include/beast/http/impl/basic_headers.ipp b/src/beast/include/beast/http/impl/basic_headers.ipp index 27b9d41600..206ed57593 100644 --- a/src/beast/include/beast/http/impl/basic_headers.ipp +++ b/src/beast/include/beast/http/impl/basic_headers.ipp @@ -9,6 +9,7 @@ #define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP #include +#include namespace beast { namespace http { @@ -204,6 +205,18 @@ basic_headers(FwdIt first, FwdIt last) insert(first->name(), first->value()); } +template +std::size_t +basic_headers:: +count(boost::string_ref const& name) const +{ + auto const it = set_.find(name, less{}); + if(it == set_.end()) + return 0; + auto const last = set_.upper_bound(name, less{}); + return static_cast(std::distance(it, last)); +} + template auto basic_headers:: @@ -221,11 +234,9 @@ boost::string_ref basic_headers:: operator[](boost::string_ref const& name) const { - // VFALCO This none object looks sketchy - static boost::string_ref const none; auto const it = find(name); if(it == end()) - return none; + return {}; return it->second; } @@ -244,15 +255,23 @@ std::size_t basic_headers:: erase(boost::string_ref const& name) { - auto const it = set_.find(name, less{}); + auto it = set_.find(name, less{}); if(it == set_.end()) return 0; - auto& e = *it; - set_.erase(set_.iterator_to(e)); - list_.erase(list_.iterator_to(e)); - alloc_traits::destroy(this->member(), &e); - alloc_traits::deallocate(this->member(), &e, 1); - return 1; + auto const last = set_.upper_bound(name, less{}); + std::size_t n = 1; + for(;;) + { + auto& e = *it++; + set_.erase(set_.iterator_to(e)); + list_.erase(list_.iterator_to(e)); + alloc_traits::destroy(this->member(), &e); + alloc_traits::deallocate(this->member(), &e, 1); + if(it == last) + break; + ++n; + } + return n; } template @@ -262,25 +281,10 @@ insert(boost::string_ref const& name, boost::string_ref value) { value = detail::trim(value); - typename set_t::insert_commit_data d; - auto const result = - set_.insert_check(name, less{}, d); - if(result.second) - { - auto const p = alloc_traits::allocate( - this->member(), 1); - alloc_traits::construct( - this->member(), p, name, value); - list_.push_back(*p); - set_.insert_commit(*p, d); - return; - } - // If field already exists, insert comma - // separated value as per RFC2616 section 4.2 - auto& cur = result.first->data.second; - cur.reserve(cur.size() + 1 + value.size()); - cur.append(1, ','); - cur.append(value.data(), value.size()); + auto const p = alloc_traits::allocate(this->member(), 1); + alloc_traits::construct(this->member(), p, name, value); + set_.insert_before(set_.upper_bound(name, less{}), *p); + list_.push_back(*p); } template diff --git a/src/beast/include/beast/http/impl/message_v1.ipp b/src/beast/include/beast/http/impl/message_v1.ipp index d0b69e4ef6..e2a2568d88 100644 --- a/src/beast/include/beast/http/impl/message_v1.ipp +++ b/src/beast/include/beast/http/impl/message_v1.ipp @@ -8,6 +8,7 @@ #ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP #define BEAST_HTTP_IMPL_MESSAGE_V1_IPP +#include #include #include #include @@ -87,7 +88,11 @@ prepare_content_length(prepare_info& pi, std::true_type) { typename Body::writer w(msg); - //w.init(ec); // VFALCO This is a design problem! + // VFALCO This is a design problem! + error_code ec; + w.init(ec); + if(ec) + throw system_error{ec}; pi.content_length = w.content_length(); } diff --git a/src/beast/include/beast/http/impl/read.ipp b/src/beast/include/beast/http/impl/read.ipp index 38c09eb568..b2acc0d918 100644 --- a/src/beast/include/beast/http/impl/read.ipp +++ b/src/beast/include/beast/http/impl/read.ipp @@ -91,7 +91,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, parse_op* op) { @@ -277,7 +277,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, read_op* op) { @@ -412,7 +412,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf, static_assert(is_ReadableBody::value, "ReadableBody requirements not met"); error_code ec; - read(stream, dynabuf, msg, ec); + beast::http::read(stream, dynabuf, msg, ec); if(ec) throw system_error{ec}; } @@ -431,7 +431,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf, static_assert(is_ReadableBody::value, "ReadableBody requirements not met"); parser_v1 p; - parse(stream, dynabuf, p, ec); + beast::http::parse(stream, dynabuf, p, ec); if(ec) return; assert(p.complete()); diff --git a/src/beast/include/beast/http/impl/write.ipp b/src/beast/include/beast/http/impl/write.ipp index e06d4ab1e9..64f7a98d22 100644 --- a/src/beast/include/beast/http/impl/write.ipp +++ b/src/beast/include/beast/http/impl/write.ipp @@ -262,7 +262,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, write_op* op) { diff --git a/src/beast/include/beast/http/parse_error.hpp b/src/beast/include/beast/http/parse_error.hpp index c98934dc80..b4d5c8d04f 100644 --- a/src/beast/include/beast/http/parse_error.hpp +++ b/src/beast/include/beast/http/parse_error.hpp @@ -15,6 +15,8 @@ namespace http { enum class parse_error { + success = 0, + connection_closed, bad_method, diff --git a/src/beast/include/beast/http/parser_v1.hpp b/src/beast/include/beast/http/parser_v1.hpp index 0909c298c9..aada5243b5 100644 --- a/src/beast/include/beast/http/parser_v1.hpp +++ b/src/beast/include/beast/http/parser_v1.hpp @@ -35,6 +35,37 @@ struct parser_response } // detail +/** Skip body option. + + The options controls whether or not the parser expects to see a + HTTP body, regardless of the presence or absence of certain fields + such as Content-Length. + + Depending on the request, some responses do not carry a body. + For example, a 200 response to a CONNECT request from a tunneling + proxy. In these cases, callers use the @ref skip_body option to + inform the parser that no body is expected. The parser will consider + the message complete after the all headers have been received. + + Example: + @code + parser_v1 p; + p.set_option(skip_body{true}); + @endcode + + @note Objects of this type are passed to @ref basic_parser_v1::set_option. +*/ +struct skip_body +{ + bool value; + + explicit + skip_body(bool v) + : value(v) + { + } +}; + /** A parser for producing HTTP/1 messages. This class uses the basic HTTP/1 wire format parser to convert @@ -62,6 +93,7 @@ private: std::string value_; message_type m_; typename message_type::body_type::reader r_; + std::uint8_t skip_body_ = 0; public: parser_v1(parser_v1&&) = default; @@ -81,6 +113,13 @@ public: { } + /// Set the expect body option. + void + set_option(skip_body const& o) + { + skip_body_ = o.value ? 1 : 0; + } + /** Returns the parsed message. Only valid if `complete()` would return `true`. @@ -176,7 +215,7 @@ private: { flush(); m_.version = 10 * this->http_major() + this->http_minor(); - return 0; + return skip_body_; } void on_request(error_code& ec) diff --git a/src/beast/include/beast/http/rfc7230.hpp b/src/beast/include/beast/http/rfc7230.hpp index e429efba2b..3b6f52c4b0 100644 --- a/src/beast/include/beast/http/rfc7230.hpp +++ b/src/beast/include/beast/http/rfc7230.hpp @@ -30,6 +30,16 @@ namespace http { the behavior of the container will be as if a string containing only characters up to but excluding the first invalid character was used to construct the list. + + @code + for(auto const& param : param_list{";level=9;no_context_takeover;bits=15"}) + { + std::cout << ";" << param.first; + if(! param.second.empty()) + std::cout << "=" << param.second; + std::cout << "\n"; + } + @endcode */ class param_list { @@ -98,6 +108,24 @@ public: the behavior of the container will be as if a string containing only characters up to but excluding the first invalid character was used to construct the list. + + To use this class, construct with the string to be parsed and + then use @ref begin and @end, or range-for to iterate each + item: + + @code + for(auto const& ext : ext_list{"none, 7z;level=9, zip;no_context_takeover;bits=15"}) + { + std::cout << ext.first << "\n"; + for(auto const& param : ext.second) + { + std::cout << ";" << param.first; + if(! param.second.empty()) + std::cout << "=" << param.second; + std::cout << "\n"; + } + } + @endcode */ class ext_list { @@ -181,6 +209,15 @@ public: the behavior of the container will be as if a string containing only characters up to but excluding the first invalid character was used to construct the list. + + To use this class, construct with the string to be parsed and + then use @ref begin and @end, or range-for to iterate each + item: + + @code + for(auto const& token : token_list{"apple, pear, banana"}) + std::cout << token << "\n"; + @endcode */ class token_list { diff --git a/src/beast/include/beast/http/status.hpp b/src/beast/include/beast/http/status.hpp deleted file mode 100644 index ee7a9c9c80..0000000000 --- a/src/beast/include/beast/http/status.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// 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) -// - -#ifndef BEAST_HTTP_STATUS_HPP -#define BEAST_HTTP_STATUS_HPP - -namespace beast { -namespace http { - -/** Returns the string corresponding to the numeric HTTP status code. */ -template -char const* -status_text(int status) -{ - switch(status) - { - case 100: return "Continue"; - case 101: return "Switching Protocols"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; -// case 306: return ""; - case 307: return "Temporary Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Request Entity Too Large"; - case 414: return "Request-URI Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "HTTP Version Not Supported"; - default: - break; - } - return "Unknown HTTP status"; -} - -} // http -} // beast - -#endif diff --git a/src/beast/include/beast/version.hpp b/src/beast/include/beast/version.hpp index e85e4107d1..feb17e679d 100644 --- a/src/beast/include/beast/version.hpp +++ b/src/beast/include/beast/version.hpp @@ -14,8 +14,8 @@ // BEAST_VERSION / 100 % 1000 is the minor version // BEAST_VERSION / 100000 is the major version // -#define BEAST_VERSION 100006 +#define BEAST_VERSION 100000 -#define BEAST_VERSION_STRING "1.0.0-b6" +#define BEAST_VERSION_STRING "1.0.0-b13" #endif diff --git a/src/beast/include/beast/websocket/detail/frame.hpp b/src/beast/include/beast/websocket/detail/frame.hpp index 0de62d77f8..672d11c14d 100644 --- a/src/beast/include/beast/websocket/detail/frame.hpp +++ b/src/beast/include/beast/websocket/detail/frame.hpp @@ -110,7 +110,7 @@ is_valid(close_code::value code) if(v >= 1016 && v <= 2999) return false; // not used - if(v >= 0 && v <= 999) + if(v <= 999) return false; return true; } @@ -136,12 +136,12 @@ write(DynamicBuffer& db, frame_header const& fh) if(fh.rsv3) b[0] |= 0x10; b[1] = fh.mask ? 0x80 : 0x00; - if (fh.len <= 125) + if(fh.len <= 125) { b[1] |= fh.len; n = 2; } - else if (fh.len <= 65535) + else if(fh.len <= 65535) { b[1] |= 126; ::new(&b[2]) big_uint16_buf_t{ diff --git a/src/beast/include/beast/websocket/detail/mask.hpp b/src/beast/include/beast/websocket/detail/mask.hpp index 78f6f1f8b8..fb67b511e8 100644 --- a/src/beast/include/beast/websocket/detail/mask.hpp +++ b/src/beast/include/beast/websocket/detail/mask.hpp @@ -113,7 +113,7 @@ mask_inplace_general( { using boost::asio::buffer_cast; using boost::asio::buffer_size; - auto n = buffer_size(b); + auto const n = buffer_size(b); auto p = buffer_cast(b); for(auto i = n / sizeof(key); i; --i) { @@ -122,13 +122,14 @@ mask_inplace_general( *p ^= (key >>16); ++p; *p ^= (key >>24); ++p; } - n %= sizeof(key); - switch(n) + auto const m = + static_cast(n % sizeof(key)); + switch(m) { case 3: p[2] ^= (key >>16); case 2: p[1] ^= (key >> 8); case 1: p[0] ^= key; - key = ror(key, n*8); + key = ror(key, m*8); default: break; } @@ -144,7 +145,7 @@ mask_inplace_general( { using boost::asio::buffer_cast; using boost::asio::buffer_size; - auto n = buffer_size(b); + auto const n = buffer_size(b); auto p = buffer_cast(b); for(auto i = n / sizeof(key); i; --i) { @@ -157,8 +158,9 @@ mask_inplace_general( *p ^= (key >>48); ++p; *p ^= (key >>56); ++p; } - n %= sizeof(key); - switch(n) + auto const m = + static_cast(n % sizeof(key)); + switch(m) { case 7: p[6] ^= (key >>16); case 6: p[5] ^= (key >> 8); @@ -167,7 +169,7 @@ mask_inplace_general( case 3: p[2] ^= (key >>16); case 2: p[1] ^= (key >> 8); case 1: p[0] ^= key; - key = ror(key, n*8); + key = ror(key, m*8); default: break; } diff --git a/src/beast/include/beast/websocket/detail/utf8_checker.hpp b/src/beast/include/beast/websocket/detail/utf8_checker.hpp index ea3a15f4fc..6960819ddc 100644 --- a/src/beast/include/beast/websocket/detail/utf8_checker.hpp +++ b/src/beast/include/beast/websocket/detail/utf8_checker.hpp @@ -131,7 +131,7 @@ utf8_checker_t<_>::write(BufferSequence const& bs) { using boost::asio::buffer_cast; using boost::asio::buffer_size; - for (auto const& b : bs) + for(auto const& b : bs) if(! write(buffer_cast(b), buffer_size(b))) return false; diff --git a/src/beast/include/beast/websocket/error.hpp b/src/beast/include/beast/websocket/error.hpp index 9af24b1cb8..c86307cb41 100644 --- a/src/beast/include/beast/websocket/error.hpp +++ b/src/beast/include/beast/websocket/error.hpp @@ -16,8 +16,10 @@ namespace websocket { /// Error codes returned from @ref stream operations. enum class error { + success = 0, + /// Both sides performed a WebSocket close - closed = 1, + closed, /// WebSocket connection failed, protocol violation failed, diff --git a/src/beast/include/beast/websocket/impl/accept_op.ipp b/src/beast/include/beast/websocket/impl/accept_op.ipp index bc94ac352e..38443eb4aa 100644 --- a/src/beast/include/beast/websocket/impl/accept_op.ipp +++ b/src/beast/include/beast/websocket/impl/accept_op.ipp @@ -101,7 +101,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, accept_op* op) { diff --git a/src/beast/include/beast/websocket/impl/close_op.ipp b/src/beast/include/beast/websocket/impl/close_op.ipp index 379b756dd9..4884a2a174 100644 --- a/src/beast/include/beast/websocket/impl/close_op.ipp +++ b/src/beast/include/beast/websocket/impl/close_op.ipp @@ -97,7 +97,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, close_op* op) { diff --git a/src/beast/include/beast/websocket/impl/handshake_op.ipp b/src/beast/include/beast/websocket/impl/handshake_op.ipp index 96afabb9c9..8443fd9ad4 100644 --- a/src/beast/include/beast/websocket/impl/handshake_op.ipp +++ b/src/beast/include/beast/websocket/impl/handshake_op.ipp @@ -93,7 +93,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, handshake_op* op) { diff --git a/src/beast/include/beast/websocket/impl/ping_op.ipp b/src/beast/include/beast/websocket/impl/ping_op.ipp index 4689789627..8fc9936d8f 100644 --- a/src/beast/include/beast/websocket/impl/ping_op.ipp +++ b/src/beast/include/beast/websocket/impl/ping_op.ipp @@ -95,7 +95,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, ping_op* op) { diff --git a/src/beast/include/beast/websocket/impl/read_frame_op.ipp b/src/beast/include/beast/websocket/impl/read_frame_op.ipp index 6102e1145e..0ba001764d 100644 --- a/src/beast/include/beast/websocket/impl/read_frame_op.ipp +++ b/src/beast/include/beast/websocket/impl/read_frame_op.ipp @@ -117,7 +117,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, read_frame_op* op) { @@ -252,7 +252,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again) break; } d.state = do_read_fh + 2; - if (n == 0) + if(n == 0) { bytes_transferred = 0; break; diff --git a/src/beast/include/beast/websocket/impl/read_op.ipp b/src/beast/include/beast/websocket/impl/read_op.ipp index e00d19d3e6..35fa3a0c6c 100644 --- a/src/beast/include/beast/websocket/impl/read_op.ipp +++ b/src/beast/include/beast/websocket/impl/read_op.ipp @@ -88,7 +88,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, read_op* op) { diff --git a/src/beast/include/beast/websocket/impl/response_op.ipp b/src/beast/include/beast/websocket/impl/response_op.ipp index e1ed45e125..39af5c7b47 100644 --- a/src/beast/include/beast/websocket/impl/response_op.ipp +++ b/src/beast/include/beast/websocket/impl/response_op.ipp @@ -93,7 +93,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, response_op* op) { diff --git a/src/beast/include/beast/websocket/impl/ssl.ipp b/src/beast/include/beast/websocket/impl/ssl.ipp index 681ecd341d..07570e5ced 100644 --- a/src/beast/include/beast/websocket/impl/ssl.ipp +++ b/src/beast/include/beast/websocket/impl/ssl.ipp @@ -93,7 +93,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, teardown_ssl_op* op) @@ -129,7 +129,7 @@ operator()(error_code ec, bool again) template void -teardown( +teardown(teardown_tag, boost::asio::ssl::stream& stream, error_code& ec) { @@ -138,7 +138,7 @@ teardown( template void -async_teardown( +async_teardown(teardown_tag, boost::asio::ssl::stream& stream, TeardownHandler&& handler) { diff --git a/src/beast/include/beast/websocket/impl/stream.ipp b/src/beast/include/beast/websocket/impl/stream.ipp index 874081df31..4c69a032b1 100644 --- a/src/beast/include/beast/websocket/impl/stream.ipp +++ b/src/beast/include/beast/websocket/impl/stream.ipp @@ -920,7 +920,7 @@ build_request(boost::string_ref const& host, boost::string_ref const& resource, std::string& key) { http::request_v1 req; - req.url = "/"; + req.url = { resource.data(), resource.size() }; req.version = 11; req.method = "GET"; req.headers.insert("Host", host); diff --git a/src/beast/include/beast/websocket/impl/teardown.ipp b/src/beast/include/beast/websocket/impl/teardown.ipp index fa7133b282..4de5444bce 100644 --- a/src/beast/include/beast/websocket/impl/teardown.ipp +++ b/src/beast/include/beast/websocket/impl/teardown.ipp @@ -80,7 +80,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, teardown_tcp_op* op) @@ -128,7 +128,7 @@ operator()(error_code ec, std::size_t, bool again) inline void -teardown( +teardown(teardown_tag, boost::asio::ip::tcp::socket& socket, error_code& ec) { @@ -151,7 +151,7 @@ teardown( template inline void -async_teardown( +async_teardown(teardown_tag, boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler) { diff --git a/src/beast/include/beast/websocket/impl/write_frame_op.ipp b/src/beast/include/beast/websocket/impl/write_frame_op.ipp index f1b3336753..2bc9e74f83 100644 --- a/src/beast/include/beast/websocket/impl/write_frame_op.ipp +++ b/src/beast/include/beast/websocket/impl/write_frame_op.ipp @@ -134,7 +134,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, write_frame_op* op) { diff --git a/src/beast/include/beast/websocket/impl/write_op.ipp b/src/beast/include/beast/websocket/impl/write_op.ipp index ebffc2623b..3aa4836113 100644 --- a/src/beast/include/beast/websocket/impl/write_op.ipp +++ b/src/beast/include/beast/websocket/impl/write_op.ipp @@ -91,7 +91,7 @@ public: return op->d_->cont; } - template + template friend void asio_handler_invoke(Function&& f, write_op* op) { diff --git a/src/beast/include/beast/websocket/ssl.hpp b/src/beast/include/beast/websocket/ssl.hpp index 5ed57222c2..ef94ed9a7b 100644 --- a/src/beast/include/beast/websocket/ssl.hpp +++ b/src/beast/include/beast/websocket/ssl.hpp @@ -31,7 +31,7 @@ namespace websocket { */ template void -teardown( +teardown(teardown_tag, boost::asio::ssl::stream& stream, error_code& ec); @@ -62,7 +62,7 @@ teardown( template inline void -async_teardown( +async_teardown(teardown_tag, boost::asio::ssl::stream& stream, TeardownHandler&& handler); diff --git a/src/beast/include/beast/websocket/teardown.hpp b/src/beast/include/beast/websocket/teardown.hpp index ecb6dba310..d3ffd2c8ab 100644 --- a/src/beast/include/beast/websocket/teardown.hpp +++ b/src/beast/include/beast/websocket/teardown.hpp @@ -13,8 +13,17 @@ #include namespace beast { + namespace websocket { +/** Tag type used to find teardown and async_teardown overloads + + Overloads of @ref teardown and @async_teardown for user defined + types must take a value of type @ref teardown_tag in the first + argument in order to be found by the implementation. +*/ +struct teardown_tag {}; + /** Tear down a connection. This tears down a connection. The implementation will call @@ -30,7 +39,19 @@ namespace websocket { */ template void -teardown(Socket& socket, error_code& ec) = delete; +teardown(teardown_tag, Socket& socket, error_code& ec) +{ +/* + If you are trying to use OpenSSL and this goes off, you need to + add an include for . + + If you are creating an instance of beast::websocket::stream with your + own user defined type, you must provide an overload of teardown with + the corresponding signature (including the teardown_tag). +*/ + static_assert(sizeof(Socket)==-1, + "Unknown Socket type in teardown."); +} /** Start tearing down a connection. @@ -49,7 +70,8 @@ teardown(Socket& socket, error_code& ec) = delete; function signature of the handler must be: @code void handler( error_code const& error // result of operation - ); @endcode + ); + @endcode Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a @@ -58,57 +80,19 @@ teardown(Socket& socket, error_code& ec) = delete; */ template void -async_teardown(Socket& socket, TeardownHandler&& handler) = delete; +async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler) +{ +/* + If you are trying to use OpenSSL and this goes off, you need to + add an include for . -//------------------------------------------------------------------------------ - -/** Tear down a `boost::asio::ip::tcp::socket`. - - This tears down a connection. The implementation will call - the overload of this function based on the `Stream` parameter - used to consruct the socket. When `Stream` is a user defined - type, and not a `boost::asio::ip::tcp::socket` or any - `boost::asio::ssl::stream`, callers are responsible for - providing a suitable overload of this function. - - @param socket The socket to tear down. - - @param ec Set to the error if any occurred. + If you are creating an instance of beast::websocket::stream with your + own user defined type, you must provide an overload of teardown with + the corresponding signature (including the teardown_tag). */ -void -teardown( - boost::asio::ip::tcp::socket& socket, - error_code& ec); - -/** Start tearing down a `boost::asio::ip::tcp::socket`. - - This begins tearing down a connection asynchronously. - The implementation will call the overload of this function - based on the `Stream` parameter used to consruct the socket. - When `Stream` is a user defined type, and not a - `boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`, - callers are responsible for providing a suitable overload - of this function. - - @param socket The socket to tear down. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - -*/ -template -void -async_teardown( - boost::asio::ip::tcp::socket& socket, - TeardownHandler&& handler); + static_assert(sizeof(Socket)==-1, + "Unknown Socket type in async_teardown."); +} } // websocket @@ -127,7 +111,7 @@ void call_teardown(Socket& socket, error_code& ec) { using websocket::teardown; - teardown(socket, ec); + teardown(websocket::teardown_tag{}, socket, ec); } template @@ -136,12 +120,65 @@ void call_async_teardown(Socket& socket, TeardownHandler&& handler) { using websocket::async_teardown; - async_teardown(socket, + async_teardown(websocket::teardown_tag{}, socket, std::forward(handler)); } } // websocket_helpers +//------------------------------------------------------------------------------ + +namespace websocket { + +/** Tear down a `boost::asio::ip::tcp::socket`. + + This tears down a connection. The implementation will call + the overload of this function based on the `Stream` parameter + used to consruct the socket. When `Stream` is a user defined + type, and not a `boost::asio::ip::tcp::socket` or any + `boost::asio::ssl::stream`, callers are responsible for + providing a suitable overload of this function. + + @param socket The socket to tear down. + + @param ec Set to the error if any occurred. +*/ +void +teardown(teardown_tag, + boost::asio::ip::tcp::socket& socket, error_code& ec); + +/** Start tearing down a `boost::asio::ip::tcp::socket`. + + This begins tearing down a connection asynchronously. + The implementation will call the overload of this function + based on the `Stream` parameter used to consruct the socket. + When `Stream` is a user defined type, and not a + `boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`, + callers are responsible for providing a suitable overload + of this function. + + @param socket The socket to tear down. + + @param handler The handler to be called when the request completes. + Copies will be made of the handler as required. The equivalent + function signature of the handler must be: + @code void handler( + error_code const& error // result of operation + ); + @endcode + Regardless of whether the asynchronous operation completes + immediately or not, the handler will not be invoked from within + this function. Invocation of the handler will be performed in a + manner equivalent to using boost::asio::io_service::post(). + +*/ +template +void +async_teardown(teardown_tag, + boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler); + +} // websocket + } // beast #include diff --git a/src/beast/scripts/build-and-test.sh b/src/beast/scripts/build-and-test.sh index 0aa4104067..3eecf30e09 100755 --- a/src/beast/scripts/build-and-test.sh +++ b/src/beast/scripts/build-and-test.sh @@ -37,8 +37,8 @@ elif [[ $(uname -s) == "Linux" ]]; then num_proc_units=$(nproc) # Physical cores num_jobs=$(lscpu -p | grep -v '^#' | sort -u -t, -k 2,4 | wc -l) - if (("$num_proc_units" < "$num_jobs")); then - num_jobs=$num_proc_units + if ((${num_proc_units} < ${num_jobs})); then + num_jobs=$num_proc_units fi fi @@ -82,6 +82,16 @@ function build_beast { -j${num_jobs} } +function build_beast_cmake { + mkdir -p build + pushd build > /dev/null + cmake -DVARIANT=${VARIANT} .. + make -j${num_jobs} + mkdir -p ../bin/$VARIANT + find . -executable -type f -exec cp {} ../bin/$VARIANT/. \; + popd > /dev/null +} + function run_autobahn_test_suite { # Run autobahn tests wsecho=$(find bin -name "websocket-echo" | grep /$VARIANT/) @@ -108,7 +118,11 @@ function run_autobahn_test_suite { ##################################### BUILD #################################### -build_beast +if [[ ${BUILD_SYSTEM:-} == cmake ]]; then + build_beast_cmake +else + build_beast +fi ##################################### TESTS #################################### @@ -123,6 +137,7 @@ if [[ $VARIANT == "coverage" ]]; then run_tests_with_valgrind run_autobahn_test_suite else + echo "skipping autobahn tests for feature branch build" run_tests fi diff --git a/src/beast/scripts/install-dependencies.sh b/src/beast/scripts/install-dependencies.sh index 4130e2b473..4f0b7cb722 100755 --- a/src/beast/scripts/install-dependencies.sh +++ b/src/beast/scripts/install-dependencies.sh @@ -12,11 +12,32 @@ do test -x $( type -p ${g}-$GCC_VER ) ln -sv $(type -p ${g}-$GCC_VER) $HOME/bin/${g} done -for c in clang clang++ llvm-symbolizer -do - test -x $( type -p ${c}-$CLANG_VER ) - ln -sv $(type -p ${c}-$CLANG_VER) $HOME/bin/${c} -done + +if [[ -n ${CLANG_VER:-} ]]; then + # There are cases where the directory exists, but the exe is not available. + # Use this workaround for now. + if [[ ! -x llvm-${LLVM_VERSION}/bin/llvm-config ]] && [[ -d llvm-${LLVM_VERSION} ]]; then + rm -fr llvm-${LLVM_VERSION} + fi + if [[ ! -d llvm-${LLVM_VERSION} ]]; then + mkdir llvm-${LLVM_VERSION} + LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz" + wget -O - ${LLVM_URL} | tar -Jxvf - --strip 1 -C llvm-${LLVM_VERSION} + fi + llvm-${LLVM_VERSION}/bin/llvm-config --version; + export LLVM_CONFIG="llvm-${LLVM_VERSION}/bin/llvm-config"; +fi + +# There are cases where the directory exists, but the exe is not available. +# Use this workaround for now. +if [[ ! -x cmake/bin/cmake && -d cmake ]]; then + rm -fr cmake +fi +if [[ ! -d cmake && ${BUILD_SYSTEM:-} == cmake ]]; then + CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz" + mkdir cmake && wget --no-check-certificate -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake +fi + # NOTE, changed from PWD -> HOME export PATH=$HOME/bin:$PATH diff --git a/src/beast/test/CMakeLists.txt b/src/beast/test/CMakeLists.txt index 6c8bb2b753..c2e5386377 100644 --- a/src/beast/test/CMakeLists.txt +++ b/src/beast/test/CMakeLists.txt @@ -1,11 +1,12 @@ # Part of Beast -GroupSources(extras/beast beast) +GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(test "/") add_executable (lib-tests ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} ../extras/beast/unit_test/main.cpp core.cpp http.cpp diff --git a/src/beast/test/Jamfile b/src/beast/test/Jamfile index 508b6e06e7..7807972f31 100644 --- a/src/beast/test/Jamfile +++ b/src/beast/test/Jamfile @@ -33,10 +33,10 @@ unit-test core-tests : core/streambuf.cpp core/to_string.cpp core/write_dynabuf.cpp - core/detail/base64.cpp - core/detail/empty_base_optimization.cpp - core/detail/get_lowest_layer.cpp - core/detail/sha1.cpp + core/base64.cpp + core/empty_base_optimization.cpp + core/get_lowest_layer.cpp + core/sha1.cpp ; unit-test http-tests : @@ -56,11 +56,10 @@ unit-test http-tests : http/reason.cpp http/resume_context.cpp http/rfc7230.cpp - http/status.cpp http/streambuf_body.cpp http/string_body.cpp http/write.cpp - http/detail/chunk_encode.cpp + http/chunk_encode.cpp ; unit-test bench-tests : @@ -76,10 +75,10 @@ unit-test websocket-tests : websocket/rfc6455.cpp websocket/stream.cpp websocket/teardown.cpp - websocket/detail/frame.cpp - websocket/detail/mask.cpp - websocket/detail/stream_base.cpp - websocket/detail/utf8_checker.cpp + websocket/frame.cpp + websocket/mask.cpp + websocket/stream_base.cpp + websocket/utf8_checker.cpp ; exe websocket-echo : diff --git a/src/beast/test/core/CMakeLists.txt b/src/beast/test/core/CMakeLists.txt index 3cc71b05df..e6d291cdbd 100644 --- a/src/beast/test/core/CMakeLists.txt +++ b/src/beast/test/core/CMakeLists.txt @@ -1,11 +1,12 @@ # Part of Beast -GroupSources(extras/beast beast) +GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(test/core "/") add_executable (core-tests ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} ../../extras/beast/unit_test/main.cpp buffer_test.hpp async_completion.cpp @@ -27,12 +28,12 @@ add_executable (core-tests streambuf.cpp to_string.cpp write_dynabuf.cpp - detail/base64.cpp - detail/empty_base_optimization.cpp - detail/get_lowest_layer.cpp - detail/sha1.cpp + base64.cpp + empty_base_optimization.cpp + get_lowest_layer.cpp + sha1.cpp ) if (NOT WIN32) - target_link_libraries(core-tests ${Boost_LIBRARIES}) + target_link_libraries(core-tests ${Boost_LIBRARIES} Threads::Threads) endif() diff --git a/src/beast/test/core/detail/base64.cpp b/src/beast/test/core/base64.cpp similarity index 91% rename from src/beast/test/core/detail/base64.cpp rename to src/beast/test/core/base64.cpp index f0445771bf..c667b3b1a3 100644 --- a/src/beast/test/core/detail/base64.cpp +++ b/src/beast/test/core/base64.cpp @@ -20,8 +20,8 @@ public: check (std::string const& in, std::string const& out) { auto const encoded = base64_encode (in); - expect (encoded == out); - expect (base64_decode (encoded) == in); + BEAST_EXPECT(encoded == out); + BEAST_EXPECT(base64_decode (encoded) == in); } void diff --git a/src/beast/test/core/basic_streambuf.cpp b/src/beast/test/core/basic_streambuf.cpp index 48898e5832..9bb79b6a4f 100644 --- a/src/beast/test/core/basic_streambuf.cpp +++ b/src/beast/test/core/basic_streambuf.cpp @@ -153,10 +153,10 @@ public: void expect_size(std::size_t n, ConstBufferSequence const& buffers) { - expect(test::size_pre(buffers) == n); - expect(test::size_post(buffers) == n); - expect(test::size_rev_pre(buffers) == n); - expect(test::size_rev_post(buffers) == n); + BEAST_EXPECT(test::size_pre(buffers) == n); + BEAST_EXPECT(test::size_post(buffers) == n); + BEAST_EXPECT(test::size_rev_pre(buffers) == n); + BEAST_EXPECT(test::size_rev_post(buffers) == n); } template @@ -173,7 +173,7 @@ public: using boost::asio::buffer_cast; using boost::asio::buffer_size; std::string const s = "Hello, world"; - expect(s.size() == 12); + BEAST_EXPECT(s.size() == 12); for(std::size_t i = 1; i < 12; ++i) { for(std::size_t x = 1; x < 4; ++x) { for(std::size_t y = 1; y < 4; ++y) { @@ -183,28 +183,28 @@ public: sb.commit(buffer_copy(sb.prepare(x), buffer(s.data(), x))); sb.commit(buffer_copy(sb.prepare(y), buffer(s.data()+x, y))); sb.commit(buffer_copy(sb.prepare(z), buffer(s.data()+x+y, z))); - expect(to_string(sb.data()) == s); + BEAST_EXPECT(to_string(sb.data()) == s); { streambuf sb2(sb); - expect(eq(sb, sb2)); + BEAST_EXPECT(eq(sb, sb2)); } { streambuf sb2; sb2 = sb; - expect(eq(sb, sb2)); + BEAST_EXPECT(eq(sb, sb2)); } { streambuf sb2(std::move(sb)); - expect(to_string(sb2.data()) == s); + BEAST_EXPECT(to_string(sb2.data()) == s); expect_size(0, sb.data()); sb = std::move(sb2); - expect(to_string(sb.data()) == s); + BEAST_EXPECT(to_string(sb.data()) == s); expect_size(0, sb2.data()); } self_assign(sb, sb); - expect(to_string(sb.data()) == s); + BEAST_EXPECT(to_string(sb.data()) == s); self_assign(sb, std::move(sb)); - expect(to_string(sb.data()) == s); + BEAST_EXPECT(to_string(sb.data()) == s); } }}} try @@ -226,16 +226,16 @@ public: test_allocator; using sb_type = basic_streambuf; sb_type sb; - expect(sb.get_allocator().id() == 1); + BEAST_EXPECT(sb.get_allocator().id() == 1); } { using alloc_type = test_allocator; using sb_type = basic_streambuf; sb_type sb; - expect(sb.get_allocator().id() == 2); + BEAST_EXPECT(sb.get_allocator().id() == 2); sb_type sb2(sb); - expect(sb2.get_allocator().id() == 2); + BEAST_EXPECT(sb2.get_allocator().id() == 2); sb_type sb3(sb, alloc_type{}); } } @@ -246,16 +246,16 @@ public: using boost::asio::buffer_size; { streambuf sb(2); - expect(buffer_size(sb.prepare(5)) == 5); - expect(buffer_size(sb.prepare(8)) == 8); - expect(buffer_size(sb.prepare(7)) == 7); + BEAST_EXPECT(buffer_size(sb.prepare(5)) == 5); + BEAST_EXPECT(buffer_size(sb.prepare(8)) == 8); + BEAST_EXPECT(buffer_size(sb.prepare(7)) == 7); } { streambuf sb(2); sb.prepare(2); - expect(test::buffer_count(sb.prepare(5)) == 2); - expect(test::buffer_count(sb.prepare(8)) == 3); - expect(test::buffer_count(sb.prepare(4)) == 2); + BEAST_EXPECT(test::buffer_count(sb.prepare(5)) == 2); + BEAST_EXPECT(test::buffer_count(sb.prepare(8)) == 3); + BEAST_EXPECT(test::buffer_count(sb.prepare(4)) == 2); } } @@ -286,7 +286,7 @@ public: using boost::asio::buffer_cast; using boost::asio::buffer_size; std::string const s = "Hello, world"; - expect(s.size() == 12); + BEAST_EXPECT(s.size() == 12); for(std::size_t i = 1; i < 12; ++i) { for(std::size_t x = 1; x < 4; ++x) { for(std::size_t y = 1; y < 4; ++y) { @@ -298,78 +298,78 @@ public: streambuf sb(i); { auto d = sb.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); } { auto d = sb.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = sb.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); } { auto d = sb.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); sb.commit(buffer_copy(d, buffer(s.data(), x))); } - expect(sb.size() == x); - expect(buffer_size(sb.data()) == sb.size()); + BEAST_EXPECT(sb.size() == x); + BEAST_EXPECT(buffer_size(sb.data()) == sb.size()); { auto d = sb.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); } { auto d = sb.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = sb.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); } { auto d = sb.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); sb.commit(buffer_copy(d, buffer(s.data()+x, y))); } sb.commit(1); - expect(sb.size() == x + y); - expect(buffer_size(sb.data()) == sb.size()); + BEAST_EXPECT(sb.size() == x + y); + BEAST_EXPECT(buffer_size(sb.data()) == sb.size()); { auto d = sb.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); } { auto d = sb.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); } { auto d = sb.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = sb.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); sb.commit(buffer_copy(d, buffer(s.data()+x+y, z))); } sb.commit(2); - expect(sb.size() == x + y + z); - expect(buffer_size(sb.data()) == sb.size()); - expect(to_string(sb.data()) == s); + BEAST_EXPECT(sb.size() == x + y + z); + BEAST_EXPECT(buffer_size(sb.data()) == sb.size()); + BEAST_EXPECT(to_string(sb.data()) == s); sb.consume(t); { auto d = sb.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } - expect(to_string(sb.data()) == s.substr(t, std::string::npos)); + BEAST_EXPECT(to_string(sb.data()) == s.substr(t, std::string::npos)); sb.consume(u); - expect(to_string(sb.data()) == s.substr(t + u, std::string::npos)); + BEAST_EXPECT(to_string(sb.data()) == s.substr(t + u, std::string::npos)); sb.consume(v); - expect(to_string(sb.data()) == ""); + BEAST_EXPECT(to_string(sb.data()) == ""); sb.consume(1); { auto d = sb.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } } }}}}} @@ -387,14 +387,14 @@ public: sb.prepare(1); expect_size(3, sb.prepare(3)); sb.commit(2); - expect(test::buffer_count(sb.data()) == 4); + BEAST_EXPECT(test::buffer_count(sb.data()) == 4); } void testOutputStream() { streambuf sb; sb << "x"; - expect(to_string(sb.data()) == "x"); + BEAST_EXPECT(to_string(sb.data()) == "x"); } void testReadSizeHelper() @@ -402,44 +402,44 @@ public: using boost::asio::buffer_size; { streambuf sb(10); - expect(read_size_helper(sb, 0) == 0); - expect(read_size_helper(sb, 1) == 1); - expect(read_size_helper(sb, 10) == 10); - expect(read_size_helper(sb, 20) == 20); - expect(read_size_helper(sb, 1000) == 512); + BEAST_EXPECT(read_size_helper(sb, 0) == 0); + BEAST_EXPECT(read_size_helper(sb, 1) == 1); + BEAST_EXPECT(read_size_helper(sb, 10) == 10); + BEAST_EXPECT(read_size_helper(sb, 20) == 20); + BEAST_EXPECT(read_size_helper(sb, 1000) == 512); sb.prepare(3); sb.commit(3); - expect(read_size_helper(sb, 10) == 7); - expect(read_size_helper(sb, 1000) == 7); + BEAST_EXPECT(read_size_helper(sb, 10) == 7); + BEAST_EXPECT(read_size_helper(sb, 1000) == 7); } { streambuf sb(1000); - expect(read_size_helper(sb, 0) == 0); - expect(read_size_helper(sb, 1) == 1); - expect(read_size_helper(sb, 1000) == 1000); - expect(read_size_helper(sb, 2000) == 1000); + BEAST_EXPECT(read_size_helper(sb, 0) == 0); + BEAST_EXPECT(read_size_helper(sb, 1) == 1); + BEAST_EXPECT(read_size_helper(sb, 1000) == 1000); + BEAST_EXPECT(read_size_helper(sb, 2000) == 1000); sb.prepare(3); - expect(read_size_helper(sb, 0) == 0); - expect(read_size_helper(sb, 1) == 1); - expect(read_size_helper(sb, 1000) == 1000); - expect(read_size_helper(sb, 2000) == 1000); + BEAST_EXPECT(read_size_helper(sb, 0) == 0); + BEAST_EXPECT(read_size_helper(sb, 1) == 1); + BEAST_EXPECT(read_size_helper(sb, 1000) == 1000); + BEAST_EXPECT(read_size_helper(sb, 2000) == 1000); sb.commit(3); - expect(read_size_helper(sb, 0) == 0); - expect(read_size_helper(sb, 1) == 1); - expect(read_size_helper(sb, 1000) == 997); - expect(read_size_helper(sb, 2000) == 997); + BEAST_EXPECT(read_size_helper(sb, 0) == 0); + BEAST_EXPECT(read_size_helper(sb, 1) == 1); + BEAST_EXPECT(read_size_helper(sb, 1000) == 997); + BEAST_EXPECT(read_size_helper(sb, 2000) == 997); sb.consume(2); - expect(read_size_helper(sb, 0) == 0); - expect(read_size_helper(sb, 1) == 1); - expect(read_size_helper(sb, 1000) == 997); - expect(read_size_helper(sb, 2000) == 997); + BEAST_EXPECT(read_size_helper(sb, 0) == 0); + BEAST_EXPECT(read_size_helper(sb, 1) == 1); + BEAST_EXPECT(read_size_helper(sb, 1000) == 997); + BEAST_EXPECT(read_size_helper(sb, 2000) == 997); } { streambuf sb(2); - expect(test::buffer_count(sb.prepare(2)) == 1); - expect(test::buffer_count(sb.prepare(3)) == 2); - expect(buffer_size(sb.prepare(5)) == 5); - expect(read_size_helper(sb, 10) == 6); + BEAST_EXPECT(test::buffer_count(sb.prepare(2)) == 1); + BEAST_EXPECT(test::buffer_count(sb.prepare(3)) == 2); + BEAST_EXPECT(buffer_size(sb.prepare(5)) == 5); + BEAST_EXPECT(read_size_helper(sb, 10) == 6); } } diff --git a/src/beast/test/core/buffer_cat.cpp b/src/beast/test/core/buffer_cat.cpp index c78f75c677..803d2efcb3 100644 --- a/src/beast/test/core/buffer_cat.cpp +++ b/src/beast/test/core/buffer_cat.cpp @@ -47,32 +47,32 @@ public: std::list b6; auto bs = buffer_cat( b1, b2, b3, b4, b5, b6); - expect(buffer_size(bs) == 10); + BEAST_EXPECT(buffer_size(bs) == 10); std::vector v; for(auto iter = make_reverse_iterator(bs.end()); iter != make_reverse_iterator(bs.begin()); ++iter) v.emplace_back(*iter); - expect(buffer_size(bs) == 10); + BEAST_EXPECT(buffer_size(bs) == 10); decltype(bs) bs2(bs); auto bs3(std::move(bs)); bs = bs2; bs3 = std::move(bs2); { boost::asio::streambuf sb1, sb2; - expect(buffer_size(buffer_cat( + BEAST_EXPECT(buffer_size(buffer_cat( sb1.prepare(5), sb2.prepare(7))) == 12); sb1.commit(5); sb2.commit(7); - expect(buffer_size(buffer_cat( + BEAST_EXPECT(buffer_size(buffer_cat( sb1.data(), sb2.data())) == 12); } for(auto it = bs.begin(); it != bs.end(); ++it) { decltype(bs)::const_iterator copy; copy = it; - expect(copy == it); + BEAST_EXPECT(copy == it); copy = copy; - expect(copy == it); + BEAST_EXPECT(copy == it); } } @@ -132,11 +132,11 @@ public: pass(); } auto bs2 = bs; - expect(bs.begin() != bs2.begin()); - expect(bs.end() != bs2.end()); + BEAST_EXPECT(bs.begin() != bs2.begin()); + BEAST_EXPECT(bs.end() != bs2.end()); decltype(bs)::const_iterator it; decltype(bs2)::const_iterator it2; - expect(it == it2); + BEAST_EXPECT(it == it2); } void run() override diff --git a/src/beast/test/core/buffers_adapter.cpp b/src/beast/test/core/buffers_adapter.cpp index 69f56d9ce6..551478ed59 100644 --- a/src/beast/test/core/buffers_adapter.cpp +++ b/src/beast/test/core/buffers_adapter.cpp @@ -43,7 +43,7 @@ public: using boost::asio::mutable_buffer; char buf[12]; std::string const s = "Hello, world"; - expect(s.size() == sizeof(buf)); + BEAST_EXPECT(s.size() == sizeof(buf)); for(std::size_t i = 1; i < 4; ++i) { for(std::size_t j = 1; j < 4; ++j) { for(std::size_t x = 1; x < 4; ++x) { @@ -60,83 +60,83 @@ public: mutable_buffer{&buf[i], j}, mutable_buffer{&buf[i+j], k}}}; buffers_adapter ba(std::move(bs)); - expect(ba.max_size() == sizeof(buf)); + BEAST_EXPECT(ba.max_size() == sizeof(buf)); { auto d = ba.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); } { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = ba.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); } { auto d = ba.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); ba.commit(buffer_copy(d, buffer(s.data(), x))); } - expect(ba.size() == x); - expect(ba.max_size() == sizeof(buf) - x); - expect(buffer_size(ba.data()) == ba.size()); + BEAST_EXPECT(ba.size() == x); + BEAST_EXPECT(ba.max_size() == sizeof(buf) - x); + BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); { auto d = ba.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); } { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = ba.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); } { auto d = ba.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); ba.commit(buffer_copy(d, buffer(s.data()+x, y))); } ba.commit(1); - expect(ba.size() == x + y); - expect(ba.max_size() == sizeof(buf) - (x + y)); - expect(buffer_size(ba.data()) == ba.size()); + BEAST_EXPECT(ba.size() == x + y); + BEAST_EXPECT(ba.max_size() == sizeof(buf) - (x + y)); + BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); { auto d = ba.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); } { auto d = ba.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); } { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { - auto d = ba.prepare(z); expect(buffer_size(d) == z); + auto d = ba.prepare(z); BEAST_EXPECT(buffer_size(d) == z); ba.commit(buffer_copy(d, buffer(s.data()+x+y, z))); } ba.commit(2); - expect(ba.size() == x + y + z); - expect(ba.max_size() == 0); - expect(buffer_size(ba.data()) == ba.size()); - expect(to_string(ba.data()) == s); + BEAST_EXPECT(ba.size() == x + y + z); + BEAST_EXPECT(ba.max_size() == 0); + BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); + BEAST_EXPECT(to_string(ba.data()) == s); ba.consume(t); { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } - expect(to_string(ba.data()) == s.substr(t, std::string::npos)); + BEAST_EXPECT(to_string(ba.data()) == s.substr(t, std::string::npos)); ba.consume(u); - expect(to_string(ba.data()) == s.substr(t + u, std::string::npos)); + BEAST_EXPECT(to_string(ba.data()) == s.substr(t + u, std::string::npos)); ba.consume(v); - expect(to_string(ba.data()) == ""); + BEAST_EXPECT(to_string(ba.data()) == ""); ba.consume(1); { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } try { @@ -158,9 +158,9 @@ public: sb_type sb; buffers_adapter< sb_type::mutable_buffers_type> ba(sb.prepare(3)); - expect(buffer_size(ba.prepare(3)) == 3); + BEAST_EXPECT(buffer_size(ba.prepare(3)) == 3); ba.commit(2); - expect(buffer_size(ba.data()) == 2); + BEAST_EXPECT(buffer_size(ba.data()) == 2); } { using sb_type = beast::streambuf; @@ -168,13 +168,13 @@ public: sb.prepare(3); buffers_adapter< sb_type::mutable_buffers_type> ba(sb.prepare(8)); - expect(buffer_size(ba.prepare(8)) == 8); + BEAST_EXPECT(buffer_size(ba.prepare(8)) == 8); ba.commit(2); - expect(buffer_size(ba.data()) == 2); + BEAST_EXPECT(buffer_size(ba.data()) == 2); ba.consume(1); ba.commit(6); ba.consume(2); - expect(buffer_size(ba.data()) == 5); + BEAST_EXPECT(buffer_size(ba.data()) == 5); ba.consume(5); } } diff --git a/src/beast/test/core/consuming_buffers.cpp b/src/beast/test/core/consuming_buffers.cpp index 6a7f0c5e86..857000722b 100644 --- a/src/beast/test/core/consuming_buffers.cpp +++ b/src/beast/test/core/consuming_buffers.cpp @@ -31,10 +31,10 @@ public: void expect_size(std::size_t n, ConstBufferSequence const& buffers) { - expect(test::size_pre(buffers) == n); - expect(test::size_post(buffers) == n); - expect(test::size_rev_pre(buffers) == n); - expect(test::size_rev_post(buffers) == n); + BEAST_EXPECT(test::size_pre(buffers) == n); + BEAST_EXPECT(test::size_post(buffers) == n); + BEAST_EXPECT(test::size_rev_pre(buffers) == n); + BEAST_EXPECT(test::size_rev_post(buffers) == n); } void testMatrix() @@ -43,9 +43,9 @@ public: using boost::asio::const_buffer; char buf[12]; std::string const s = "Hello, world"; - expect(s.size() == sizeof(buf)); + BEAST_EXPECT(s.size() == sizeof(buf)); buffer_copy(buffer(buf), buffer(s)); - expect(to_string(buffer(buf)) == s); + BEAST_EXPECT(to_string(buffer(buf)) == s); for(std::size_t i = 1; i < 4; ++i) { for(std::size_t j = 1; j < 4; ++j) { for(std::size_t x = 1; x < 4; ++x) { @@ -58,24 +58,24 @@ public: const_buffer{&buf[i], j}, const_buffer{&buf[i+j], k}}}; consuming_buffers cb(bs); - expect(to_string(cb) == s); + BEAST_EXPECT(to_string(cb) == s); expect_size(s.size(), cb); cb.consume(0); - expect(eq(cb, consumed_buffers(bs, 0))); - expect(to_string(cb) == s); + BEAST_EXPECT(eq(cb, consumed_buffers(bs, 0))); + BEAST_EXPECT(to_string(cb) == s); expect_size(s.size(), cb); cb.consume(x); - expect(to_string(cb) == s.substr(x)); - expect(eq(cb, consumed_buffers(bs, x))); + BEAST_EXPECT(to_string(cb) == s.substr(x)); + BEAST_EXPECT(eq(cb, consumed_buffers(bs, x))); cb.consume(y); - expect(to_string(cb) == s.substr(x+y)); - expect(eq(cb, consumed_buffers(bs, x+y))); + BEAST_EXPECT(to_string(cb) == s.substr(x+y)); + BEAST_EXPECT(eq(cb, consumed_buffers(bs, x+y))); cb.consume(z); - expect(to_string(cb) == ""); - expect(eq(cb, consumed_buffers(bs, x+y+z))); + BEAST_EXPECT(to_string(cb) == ""); + BEAST_EXPECT(eq(cb, consumed_buffers(bs, x+y+z))); cb.consume(1); - expect(to_string(cb) == ""); - expect(eq(cb, consumed_buffers(bs, x+y+z))); + BEAST_EXPECT(to_string(cb) == ""); + BEAST_EXPECT(eq(cb, consumed_buffers(bs, x+y+z))); } }}}} } @@ -87,10 +87,10 @@ public: using boost::asio::null_buffers; consuming_buffers cb( null_buffers{}); - expect(buffer_size(cb) == 0); + BEAST_EXPECT(buffer_size(cb) == 0); consuming_buffers cb2( null_buffers{}); - expect(buffer_copy(cb2, cb) == 0); + BEAST_EXPECT(buffer_copy(cb2, cb) == 0); } void testIterator() @@ -101,7 +101,7 @@ public: std::size_t n = 0; for(auto it = cb.end(); it != cb.begin(); --it) ++n; - expect(n == 3); + BEAST_EXPECT(n == 3); } void run() override diff --git a/src/beast/test/core/dynabuf_readstream.cpp b/src/beast/test/core/dynabuf_readstream.cpp index 97af7455e9..9f76551e40 100644 --- a/src/beast/test/core/dynabuf_readstream.cpp +++ b/src/beast/test/core/dynabuf_readstream.cpp @@ -32,8 +32,8 @@ public: dynabuf_readstream srs(ios); dynabuf_readstream srs2(std::move(srs)); srs = std::move(srs2); - expect(&srs.get_io_service() == &ios); - expect(&srs.get_io_service() == &srs2.get_io_service()); + BEAST_EXPECT(&srs.get_io_service() == &ios); + BEAST_EXPECT(&srs.get_io_service() == &srs2.get_io_service()); } { socket_type sock(ios); @@ -63,11 +63,11 @@ public: boost::asio::read(srs, buffer(&s[0], s.size()), ec); if(! ec) { - expect(s == "Hello, world!"); + BEAST_EXPECT(s == "Hello, world!"); break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -82,11 +82,11 @@ public: boost::asio::read(srs, buffer(&s[0], s.size()), ec); if(! ec) { - expect(s == "Hello, world!"); + BEAST_EXPECT(s == "Hello, world!"); break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -101,11 +101,11 @@ public: srs, buffer(&s[0], s.size()), do_yield[ec]); if(! ec) { - expect(s == "Hello, world!"); + BEAST_EXPECT(s == "Hello, world!"); break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -121,11 +121,11 @@ public: srs, buffer(&s[0], s.size()), do_yield[ec]); if(! ec) { - expect(s == "Hello, world!"); + BEAST_EXPECT(s == "Hello, world!"); break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); } void run() override diff --git a/src/beast/test/core/detail/empty_base_optimization.cpp b/src/beast/test/core/empty_base_optimization.cpp similarity index 85% rename from src/beast/test/core/detail/empty_base_optimization.cpp rename to src/beast/test/core/empty_base_optimization.cpp index 2f9285b312..8049266ae6 100644 --- a/src/beast/test/core/detail/empty_base_optimization.cpp +++ b/src/beast/test/core/empty_base_optimization.cpp @@ -17,7 +17,7 @@ class empty_base_optimization_test : public beast::unit_test::suite { public: - template + template class test1 : private empty_base_optimization { @@ -32,7 +32,7 @@ public: T const& member() const {return Base::member();} }; - template + template class test2 { void* m_p; @@ -53,38 +53,38 @@ public: static bool - test_one () + test_one() { test1 t1(1); test2 t2(2); static_assert(sizeof(t1) == sizeof(t2), "don't optimize for int"); - if (t1.member() != 1) + if(t1.member() != 1) return false; - if (t2.member() != 2) + if(t2.member() != 2) return false; return true; } static bool - test_two () + test_two() { test1 t1((Empty())); test2 t2((Empty())); static_assert(sizeof(t1) < sizeof(t2), "do optimize for Empty"); - if (t1.member() != true) + if(t1.member() != true) return false; - if (t2.member() != true) + if(t2.member() != true) return false; return true; } void - run () + run() { - expect (test_one()); - expect (test_two()); - pass (); + BEAST_EXPECT(test_one()); + BEAST_EXPECT(test_two()); + pass(); } }; diff --git a/src/beast/test/core/detail/get_lowest_layer.cpp b/src/beast/test/core/get_lowest_layer.cpp similarity index 100% rename from src/beast/test/core/detail/get_lowest_layer.cpp rename to src/beast/test/core/get_lowest_layer.cpp diff --git a/src/beast/test/core/handler_alloc.cpp b/src/beast/test/core/handler_alloc.cpp index fe890c53e1..620a409b31 100644 --- a/src/beast/test/core/handler_alloc.cpp +++ b/src/beast/test/core/handler_alloc.cpp @@ -18,7 +18,7 @@ class to_string_test : public beast::unit_test::suite public: void run() { - expect(to_string(boost::asio::const_buffers_1("x", 1)) == "x"); + BEAST_EXPECT(to_string(boost::asio::const_buffers_1("x", 1)) == "x"); } }; diff --git a/src/beast/test/core/prepare_buffers.cpp b/src/beast/test/core/prepare_buffers.cpp index 38d71a4aff..eb40d4c497 100644 --- a/src/beast/test/core/prepare_buffers.cpp +++ b/src/beast/test/core/prepare_buffers.cpp @@ -38,7 +38,7 @@ public: { using boost::asio::buffer_size; std::string s = "Hello, world"; - expect(s.size() == 12); + BEAST_EXPECT(s.size() == 12); for(std::size_t x = 1; x < 4; ++x) { for(std::size_t y = 1; y < 4; ++y) { std::size_t z = s.size() - (x + y); @@ -50,14 +50,14 @@ public: for(std::size_t i = 0; i <= s.size() + 1; ++i) { auto pb = prepare_buffers(i, bs); - expect(to_string(pb) == s.substr(0, i)); + BEAST_EXPECT(to_string(pb) == s.substr(0, i)); auto pb2 = pb; - expect(to_string(pb2) == to_string(pb)); + BEAST_EXPECT(to_string(pb2) == to_string(pb)); pb = prepare_buffers(0, bs); pb2 = pb; - expect(buffer_size(pb2) == 0); + BEAST_EXPECT(buffer_size(pb2) == 0); pb2 = prepare_buffers(i, bs); - expect(to_string(pb2) == s.substr(0, i)); + BEAST_EXPECT(to_string(pb2) == s.substr(0, i)); } } }} @@ -69,22 +69,22 @@ public: using boost::asio::buffer_size; using boost::asio::null_buffers; auto pb0 = prepare_buffers(0, null_buffers{}); - expect(buffer_size(pb0) == 0); + BEAST_EXPECT(buffer_size(pb0) == 0); auto pb1 = prepare_buffers(1, null_buffers{}); - expect(buffer_size(pb1) == 0); - expect(buffer_copy(pb0, pb1) == 0); + BEAST_EXPECT(buffer_size(pb1) == 0); + BEAST_EXPECT(buffer_copy(pb0, pb1) == 0); using pb_type = decltype(pb0); consuming_buffers cb(pb0); - expect(buffer_size(cb) == 0); - expect(buffer_copy(cb, pb1) == 0); + BEAST_EXPECT(buffer_size(cb) == 0); + BEAST_EXPECT(buffer_copy(cb, pb1) == 0); cb.consume(1); - expect(buffer_size(cb) == 0); - expect(buffer_copy(cb, pb1) == 0); + BEAST_EXPECT(buffer_size(cb) == 0); + BEAST_EXPECT(buffer_copy(cb, pb1) == 0); auto pbc = prepare_buffers(2, cb); - expect(buffer_size(pbc) == 0); - expect(buffer_copy(pbc, cb) == 0); + BEAST_EXPECT(buffer_size(pbc) == 0); + BEAST_EXPECT(buffer_copy(pbc, cb) == 0); } void testIterator() @@ -101,11 +101,11 @@ public: for(auto it = pb.end(); it != pb.begin(); --it) { decltype(pb)::const_iterator it2(std::move(it)); - expect(buffer_size(*it2) == 1); + BEAST_EXPECT(buffer_size(*it2) == 1); it = std::move(it2); ++n; } - expect(n == 2); + BEAST_EXPECT(n == 2); } void run() override diff --git a/src/beast/test/core/detail/sha1.cpp b/src/beast/test/core/sha1.cpp similarity index 98% rename from src/beast/test/core/detail/sha1.cpp rename to src/beast/test/core/sha1.cpp index 6764a09017..7c4443c311 100644 --- a/src/beast/test/core/detail/sha1.cpp +++ b/src/beast/test/core/sha1.cpp @@ -54,7 +54,7 @@ public: init(ctx); update(ctx, message.data(), message.size()); finish(ctx, &result[0]); - expect(result == digest); + BEAST_EXPECT(result == digest); } void diff --git a/src/beast/test/core/static_streambuf.cpp b/src/beast/test/core/static_streambuf.cpp index bfcf4a6a25..eba5a65840 100644 --- a/src/beast/test/core/static_streambuf.cpp +++ b/src/beast/test/core/static_streambuf.cpp @@ -39,7 +39,7 @@ public: using boost::asio::buffer_size; char buf[12]; std::string const s = "Hello, world"; - expect(s.size() == sizeof(buf)); + BEAST_EXPECT(s.size() == sizeof(buf)); for(std::size_t i = 1; i < 4; ++i) { for(std::size_t j = 1; j < 4; ++j) { for(std::size_t x = 1; x < 4; ++x) { @@ -53,78 +53,78 @@ public: static_streambuf_n ba; { auto d = ba.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); } { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = ba.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); } { auto d = ba.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); ba.commit(buffer_copy(d, buffer(s.data(), x))); } - expect(ba.size() == x); - expect(buffer_size(ba.data()) == ba.size()); + BEAST_EXPECT(ba.size() == x); + BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); { auto d = ba.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); } { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = ba.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); } { auto d = ba.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); ba.commit(buffer_copy(d, buffer(s.data()+x, y))); } ba.commit(1); - expect(ba.size() == x + y); - expect(buffer_size(ba.data()) == ba.size()); + BEAST_EXPECT(ba.size() == x + y); + BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); { auto d = ba.prepare(x); - expect(buffer_size(d) == x); + BEAST_EXPECT(buffer_size(d) == x); } { auto d = ba.prepare(y); - expect(buffer_size(d) == y); + BEAST_EXPECT(buffer_size(d) == y); } { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } { auto d = ba.prepare(z); - expect(buffer_size(d) == z); + BEAST_EXPECT(buffer_size(d) == z); ba.commit(buffer_copy(d, buffer(s.data()+x+y, z))); } ba.commit(2); - expect(ba.size() == x + y + z); - expect(buffer_size(ba.data()) == ba.size()); - expect(to_string(ba.data()) == s); + BEAST_EXPECT(ba.size() == x + y + z); + BEAST_EXPECT(buffer_size(ba.data()) == ba.size()); + BEAST_EXPECT(to_string(ba.data()) == s); ba.consume(t); { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } - expect(to_string(ba.data()) == s.substr(t, std::string::npos)); + BEAST_EXPECT(to_string(ba.data()) == s.substr(t, std::string::npos)); ba.consume(u); - expect(to_string(ba.data()) == s.substr(t + u, std::string::npos)); + BEAST_EXPECT(to_string(ba.data()) == s.substr(t + u, std::string::npos)); ba.consume(v); - expect(to_string(ba.data()) == ""); + BEAST_EXPECT(to_string(ba.data()) == ""); ba.consume(1); { auto d = ba.prepare(0); - expect(buffer_size(d) == 0); + BEAST_EXPECT(buffer_size(d) == 0); } try { @@ -149,25 +149,25 @@ public: for(auto it = mb.begin(); it != mb.end(); it++) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); mb = ba.prepare(2); n = 0; for(auto it = mb.begin(); it != mb.end(); ++it) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); mb = ba.prepare(2); n = 0; for(auto it = mb.end(); it != mb.begin(); it--) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); mb = ba.prepare(2); n = 0; for(auto it = mb.end(); it != mb.begin(); --it) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); } ba.prepare(2); ba.commit(1); @@ -176,22 +176,22 @@ public: for(auto it = ba.data().begin(); it != ba.data().end(); it++) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); n = 0; for(auto it = ba.data().begin(); it != ba.data().end(); ++it) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); n = 0; for(auto it = ba.data().end(); it != ba.data().begin(); it--) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); n = 0; for(auto it = ba.data().end(); it != ba.data().begin(); --it) ++n; - expect(n == 1); + BEAST_EXPECT(n == 1); } void run() override diff --git a/src/beast/test/core/static_string.cpp b/src/beast/test/core/static_string.cpp index 1fe084e707..0511cc3e8a 100644 --- a/src/beast/test/core/static_string.cpp +++ b/src/beast/test/core/static_string.cpp @@ -21,107 +21,107 @@ public: using str2 = static_string<2>; { str1 s1; - expect(s1 == ""); - expect(s1.empty()); - expect(s1.size() == 0); - expect(s1.max_size() == 1); - expect(s1.capacity() == 1); - expect(s1.begin() == s1.end()); - expect(s1.cbegin() == s1.cend()); - expect(s1.rbegin() == s1.rend()); - expect(s1.crbegin() == s1.crend()); + BEAST_EXPECT(s1 == ""); + BEAST_EXPECT(s1.empty()); + BEAST_EXPECT(s1.size() == 0); + BEAST_EXPECT(s1.max_size() == 1); + BEAST_EXPECT(s1.capacity() == 1); + BEAST_EXPECT(s1.begin() == s1.end()); + BEAST_EXPECT(s1.cbegin() == s1.cend()); + BEAST_EXPECT(s1.rbegin() == s1.rend()); + BEAST_EXPECT(s1.crbegin() == s1.crend()); try { - expect(s1.at(0) == 0); + BEAST_EXPECT(s1.at(0) == 0); fail(); } catch(std::exception const&) { pass(); } - expect(s1.data()[0] == 0); - expect(*s1.c_str() == 0); - expect(std::distance(s1.begin(), s1.end()) == 0); - expect(std::distance(s1.cbegin(), s1.cend()) == 0); - expect(std::distance(s1.rbegin(), s1.rend()) == 0); - expect(std::distance(s1.crbegin(), s1.crend()) == 0); - expect(s1.compare(s1) == 0); - expect(s1.to_string() == std::string{}); + BEAST_EXPECT(s1.data()[0] == 0); + BEAST_EXPECT(*s1.c_str() == 0); + BEAST_EXPECT(std::distance(s1.begin(), s1.end()) == 0); + BEAST_EXPECT(std::distance(s1.cbegin(), s1.cend()) == 0); + BEAST_EXPECT(std::distance(s1.rbegin(), s1.rend()) == 0); + BEAST_EXPECT(std::distance(s1.crbegin(), s1.crend()) == 0); + BEAST_EXPECT(s1.compare(s1) == 0); + BEAST_EXPECT(s1.to_string() == std::string{}); } { str1 const s1; - expect(s1 == ""); - expect(s1.empty()); - expect(s1.size() == 0); - expect(s1.max_size() == 1); - expect(s1.capacity() == 1); - expect(s1.begin() == s1.end()); - expect(s1.cbegin() == s1.cend()); - expect(s1.rbegin() == s1.rend()); - expect(s1.crbegin() == s1.crend()); + BEAST_EXPECT(s1 == ""); + BEAST_EXPECT(s1.empty()); + BEAST_EXPECT(s1.size() == 0); + BEAST_EXPECT(s1.max_size() == 1); + BEAST_EXPECT(s1.capacity() == 1); + BEAST_EXPECT(s1.begin() == s1.end()); + BEAST_EXPECT(s1.cbegin() == s1.cend()); + BEAST_EXPECT(s1.rbegin() == s1.rend()); + BEAST_EXPECT(s1.crbegin() == s1.crend()); try { - expect(s1.at(0) == 0); + BEAST_EXPECT(s1.at(0) == 0); fail(); } catch(std::exception const&) { pass(); } - expect(s1.data()[0] == 0); - expect(*s1.c_str() == 0); - expect(std::distance(s1.begin(), s1.end()) == 0); - expect(std::distance(s1.cbegin(), s1.cend()) == 0); - expect(std::distance(s1.rbegin(), s1.rend()) == 0); - expect(std::distance(s1.crbegin(), s1.crend()) == 0); - expect(s1.compare(s1) == 0); - expect(s1.to_string() == std::string{}); + BEAST_EXPECT(s1.data()[0] == 0); + BEAST_EXPECT(*s1.c_str() == 0); + BEAST_EXPECT(std::distance(s1.begin(), s1.end()) == 0); + BEAST_EXPECT(std::distance(s1.cbegin(), s1.cend()) == 0); + BEAST_EXPECT(std::distance(s1.rbegin(), s1.rend()) == 0); + BEAST_EXPECT(std::distance(s1.crbegin(), s1.crend()) == 0); + BEAST_EXPECT(s1.compare(s1) == 0); + BEAST_EXPECT(s1.to_string() == std::string{}); } { str1 s1; str1 s2("x"); - expect(s2 == "x"); - expect(s2[0] == 'x'); - expect(s2.at(0) == 'x'); - expect(s2.front() == 'x'); - expect(s2.back() == 'x'); + BEAST_EXPECT(s2 == "x"); + BEAST_EXPECT(s2[0] == 'x'); + BEAST_EXPECT(s2.at(0) == 'x'); + BEAST_EXPECT(s2.front() == 'x'); + BEAST_EXPECT(s2.back() == 'x'); str1 const s3(s2); - expect(s3 == "x"); - expect(s3[0] == 'x'); - expect(s3.at(0) == 'x'); - expect(s3.front() == 'x'); - expect(s3.back() == 'x'); + BEAST_EXPECT(s3 == "x"); + BEAST_EXPECT(s3[0] == 'x'); + BEAST_EXPECT(s3.at(0) == 'x'); + BEAST_EXPECT(s3.front() == 'x'); + BEAST_EXPECT(s3.back() == 'x'); s2 = "y"; - expect(s2 == "y"); - expect(s3 == "x"); + BEAST_EXPECT(s2 == "y"); + BEAST_EXPECT(s3 == "x"); s1 = s2; - expect(s1 == "y"); + BEAST_EXPECT(s1 == "y"); s1.clear(); - expect(s1.empty()); - expect(s1.size() == 0); + BEAST_EXPECT(s1.empty()); + BEAST_EXPECT(s1.size() == 0); } { str2 s1("x"); str1 s2(s1); - expect(s2 == "x"); + BEAST_EXPECT(s2 == "x"); str1 s3; s3 = s2; - expect(s3 == "x"); + BEAST_EXPECT(s3 == "x"); s1 = "xy"; - expect(s1.size() == 2); - expect(s1[0] == 'x'); - expect(s1[1] == 'y'); - expect(s1.at(0) == 'x'); - expect(s1.at(1) == 'y'); - expect(s1.front() == 'x'); - expect(s1.back() == 'y'); + BEAST_EXPECT(s1.size() == 2); + BEAST_EXPECT(s1[0] == 'x'); + BEAST_EXPECT(s1[1] == 'y'); + BEAST_EXPECT(s1.at(0) == 'x'); + BEAST_EXPECT(s1.at(1) == 'y'); + BEAST_EXPECT(s1.front() == 'x'); + BEAST_EXPECT(s1.back() == 'y'); auto const s4 = s1; - expect(s4[0] == 'x'); - expect(s4[1] == 'y'); - expect(s4.at(0) == 'x'); - expect(s4.at(1) == 'y'); - expect(s4.front() == 'x'); - expect(s4.back() == 'y'); + BEAST_EXPECT(s4[0] == 'x'); + BEAST_EXPECT(s4[1] == 'y'); + BEAST_EXPECT(s4.at(0) == 'x'); + BEAST_EXPECT(s4.at(1) == 'y'); + BEAST_EXPECT(s4.front() == 'x'); + BEAST_EXPECT(s4.back() == 'y'); try { s3 = s1; @@ -167,87 +167,87 @@ public: str2 s2; s1 = "1"; s2 = "22"; - expect(s1.compare(s2) < 0); - expect(s2.compare(s1) > 0); - expect(s1 < "10"); - expect(s2 > "1"); - expect("10" > s1); - expect("1" < s2); - expect(s1 < "20"); - expect(s2 > "1"); - expect(s2 > "2"); + BEAST_EXPECT(s1.compare(s2) < 0); + BEAST_EXPECT(s2.compare(s1) > 0); + BEAST_EXPECT(s1 < "10"); + BEAST_EXPECT(s2 > "1"); + BEAST_EXPECT("10" > s1); + BEAST_EXPECT("1" < s2); + BEAST_EXPECT(s1 < "20"); + BEAST_EXPECT(s2 > "1"); + BEAST_EXPECT(s2 > "2"); } { str2 s1("x"); str2 s2("x"); - expect(s1 == s2); - expect(s1 <= s2); - expect(s1 >= s2); - expect(! (s1 < s2)); - expect(! (s1 > s2)); - expect(! (s1 != s2)); + BEAST_EXPECT(s1 == s2); + BEAST_EXPECT(s1 <= s2); + BEAST_EXPECT(s1 >= s2); + BEAST_EXPECT(! (s1 < s2)); + BEAST_EXPECT(! (s1 > s2)); + BEAST_EXPECT(! (s1 != s2)); } { str1 s1("x"); str2 s2("x"); - expect(s1 == s2); - expect(s1 <= s2); - expect(s1 >= s2); - expect(! (s1 < s2)); - expect(! (s1 > s2)); - expect(! (s1 != s2)); + BEAST_EXPECT(s1 == s2); + BEAST_EXPECT(s1 <= s2); + BEAST_EXPECT(s1 >= s2); + BEAST_EXPECT(! (s1 < s2)); + BEAST_EXPECT(! (s1 > s2)); + BEAST_EXPECT(! (s1 != s2)); } { str2 s("x"); - expect(s == "x"); - expect(s <= "x"); - expect(s >= "x"); - expect(! (s < "x")); - expect(! (s > "x")); - expect(! (s != "x")); - expect("x" == s); - expect("x" <= s); - expect("x" >= s); - expect(! ("x" < s)); - expect(! ("x" > s)); - expect(! ("x" != s)); + BEAST_EXPECT(s == "x"); + BEAST_EXPECT(s <= "x"); + BEAST_EXPECT(s >= "x"); + BEAST_EXPECT(! (s < "x")); + BEAST_EXPECT(! (s > "x")); + BEAST_EXPECT(! (s != "x")); + BEAST_EXPECT("x" == s); + BEAST_EXPECT("x" <= s); + BEAST_EXPECT("x" >= s); + BEAST_EXPECT(! ("x" < s)); + BEAST_EXPECT(! ("x" > s)); + BEAST_EXPECT(! ("x" != s)); } { str2 s("x"); - expect(s <= "y"); - expect(s < "y"); - expect(s != "y"); - expect(! (s == "y")); - expect(! (s >= "y")); - expect(! (s > "x")); - expect("y" >= s); - expect("y" > s); - expect("y" != s); - expect(! ("y" == s)); - expect(! ("y" <= s)); - expect(! ("y" < s)); + BEAST_EXPECT(s <= "y"); + BEAST_EXPECT(s < "y"); + BEAST_EXPECT(s != "y"); + BEAST_EXPECT(! (s == "y")); + BEAST_EXPECT(! (s >= "y")); + BEAST_EXPECT(! (s > "x")); + BEAST_EXPECT("y" >= s); + BEAST_EXPECT("y" > s); + BEAST_EXPECT("y" != s); + BEAST_EXPECT(! ("y" == s)); + BEAST_EXPECT(! ("y" <= s)); + BEAST_EXPECT(! ("y" < s)); } { str1 s1("x"); str2 s2("y"); - expect(s1 <= s2); - expect(s1 < s2); - expect(s1 != s2); - expect(! (s1 == s2)); - expect(! (s1 >= s2)); - expect(! (s1 > s2)); + BEAST_EXPECT(s1 <= s2); + BEAST_EXPECT(s1 < s2); + BEAST_EXPECT(s1 != s2); + BEAST_EXPECT(! (s1 == s2)); + BEAST_EXPECT(! (s1 >= s2)); + BEAST_EXPECT(! (s1 > s2)); } { str1 s1("x"); str2 s2("xx"); - expect(s1 < s2); - expect(s2 > s1); + BEAST_EXPECT(s1 < s2); + BEAST_EXPECT(s2 > s1); } { str1 s1("x"); str2 s2("yy"); - expect(s1 < s2); - expect(s2 > s1); + BEAST_EXPECT(s1 < s2); + BEAST_EXPECT(s2 > s1); } } diff --git a/src/beast/test/http/CMakeLists.txt b/src/beast/test/http/CMakeLists.txt index 0d9f9da2eb..af038f6db8 100644 --- a/src/beast/test/http/CMakeLists.txt +++ b/src/beast/test/http/CMakeLists.txt @@ -1,11 +1,12 @@ # Part of Beast -GroupSources(extras/beast beast) +GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(test/http "/") add_executable (http-tests ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} message_fuzz.hpp fail_parser.hpp ../../extras/beast/unit_test/main.cpp @@ -24,19 +25,19 @@ add_executable (http-tests reason.cpp resume_context.cpp rfc7230.cpp - status.cpp streambuf_body.cpp string_body.cpp write.cpp - detail/chunk_encode.cpp + chunk_encode.cpp ) if (NOT WIN32) - target_link_libraries(http-tests ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(http-tests ${Boost_LIBRARIES} Threads::Threads) endif() add_executable (bench-tests ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} nodejs_parser.hpp ../../extras/beast/unit_test/main.cpp nodejs_parser.cpp diff --git a/src/beast/test/http/basic_headers.cpp b/src/beast/test/http/basic_headers.cpp index 2508c4d413..cc01d7d381 100644 --- a/src/beast/test/http/basic_headers.cpp +++ b/src/beast/test/http/basic_headers.cpp @@ -41,31 +41,45 @@ public: void testHeaders() { bh h1; - expect(h1.empty()); + BEAST_EXPECT(h1.empty()); fill(1, h1); - expect(h1.size() == 1); + BEAST_EXPECT(h1.size() == 1); bh h2; h2 = h1; - expect(h2.size() == 1); + BEAST_EXPECT(h2.size() == 1); h2.insert("2", "2"); - expect(std::distance(h2.begin(), h2.end()) == 2); + BEAST_EXPECT(std::distance(h2.begin(), h2.end()) == 2); h1 = std::move(h2); - expect(h1.size() == 2); - expect(h2.size() == 0); + BEAST_EXPECT(h1.size() == 2); + BEAST_EXPECT(h2.size() == 0); bh h3(std::move(h1)); - expect(h3.size() == 2); - expect(h1.size() == 0); + BEAST_EXPECT(h3.size() == 2); + BEAST_EXPECT(h1.size() == 0); self_assign(h3, std::move(h3)); - expect(h3.size() == 2); - expect(h2.erase("Not-Present") == 0); + BEAST_EXPECT(h3.size() == 2); + BEAST_EXPECT(h2.erase("Not-Present") == 0); } void testRFC2616() { bh h; + h.insert("a", "w"); h.insert("a", "x"); - h.insert("a", "y"); - expect(h["a"] == "x,y"); + h.insert("aa", "y"); + h.insert("b", "z"); + BEAST_EXPECT(h.count("a") == 2); + } + + void testErase() + { + bh h; + h.insert("a", "w"); + h.insert("a", "x"); + h.insert("aa", "y"); + h.insert("b", "z"); + BEAST_EXPECT(h.size() == 4); + h.erase("a"); + BEAST_EXPECT(h.size() == 2); } void run() override diff --git a/src/beast/test/http/basic_parser_v1.cpp b/src/beast/test/http/basic_parser_v1.cpp index b8b207b60c..304be84f03 100644 --- a/src/beast/test/http/basic_parser_v1.cpp +++ b/src/beast/test/http/basic_parser_v1.cpp @@ -120,17 +120,17 @@ public: "\r\n" "*"; p.write(buffer(s), ec); - if(expect(! ec)) + if(BEAST_EXPECT(! ec)) { - expect(p.start); - expect(p.method); - expect(p.uri); - expect(p.request); - expect(p.field); - expect(p.value); - expect(p.headers); - expect(p.body); - expect(p.complete); + BEAST_EXPECT(p.start); + BEAST_EXPECT(p.method); + BEAST_EXPECT(p.uri); + BEAST_EXPECT(p.request); + BEAST_EXPECT(p.field); + BEAST_EXPECT(p.value); + BEAST_EXPECT(p.headers); + BEAST_EXPECT(p.body); + BEAST_EXPECT(p.complete); } } { @@ -143,16 +143,16 @@ public: "\r\n" "*"; p.write(buffer(s), ec); - if(expect(! ec)) + if(BEAST_EXPECT(! ec)) { - expect(p.start); - expect(p.reason); - expect(p.response); - expect(p.field); - expect(p.value); - expect(p.headers); - expect(p.body); - expect(p.complete); + BEAST_EXPECT(p.start); + BEAST_EXPECT(p.reason); + BEAST_EXPECT(p.response); + BEAST_EXPECT(p.field); + BEAST_EXPECT(p.value); + BEAST_EXPECT(p.headers); + BEAST_EXPECT(p.body); + BEAST_EXPECT(p.complete); } } } @@ -211,25 +211,25 @@ public: p.write(buffer(s1.data(), s1.size()), ec); if(ec == test::fail_error) continue; - if(! expect(! ec)) + if(! BEAST_EXPECT(! ec)) break; - if(! expect(s2.empty() || ! p.complete())) + if(! BEAST_EXPECT(s2.empty() || ! p.complete())) break; p.write(buffer(s2.data(), s2.size()), ec); if(ec == test::fail_error) continue; - if(! expect(! ec)) + if(! BEAST_EXPECT(! ec)) break; p.write_eof(ec); if(ec == test::fail_error) continue; - if(! expect(! ec)) + if(! BEAST_EXPECT(! ec)) break; - expect(p.complete()); + BEAST_EXPECT(p.complete()); f(p); break; } - expect(n < Limit); + BEAST_EXPECT(n < Limit); }); } @@ -261,10 +261,10 @@ public: continue; if(ec) { - expect((ec && ! ev) || ec == ev); + BEAST_EXPECT((ec && ! ev) || ec == ev); break; } - if(! expect(! p.complete())) + if(! BEAST_EXPECT(! p.complete())) break; if(! s2.empty()) { @@ -273,20 +273,20 @@ public: continue; if(ec) { - expect((ec && ! ev) || ec == ev); + BEAST_EXPECT((ec && ! ev) || ec == ev); break; } - if(! expect(! p.complete())) + if(! BEAST_EXPECT(! p.complete())) break; } p.write_eof(ec); if(ec == test::fail_error) continue; - expect(! p.complete()); - expect((ec && ! ev) || ec == ev); + BEAST_EXPECT(! p.complete()); + BEAST_EXPECT((ec && ! ev) || ec == ev); break; } - expect(n < Limit); + BEAST_EXPECT(n < Limit); }); } @@ -317,8 +317,8 @@ public: void operator()(Parser const& p) const { - s_.expect(p.http_major() == major_); - s_.expect(p.http_minor() == minor_); + s_.BEAST_EXPECT(p.http_major() == major_); + s_.BEAST_EXPECT(p.http_minor() == minor_); } }; @@ -337,7 +337,7 @@ public: void operator()(Parser const& p) const { - s_.expect(p.status_code() == code_); + s_.BEAST_EXPECT(p.status_code() == code_); } }; @@ -392,7 +392,7 @@ public: buf("GET / "), buf("_TTP/1.1\r\n"), buf("\r\n") ), ec); - expect(ec == parse_error::bad_version); + BEAST_EXPECT(ec == parse_error::bad_version); } } @@ -509,7 +509,7 @@ public: void operator()(Parser const& p) const { - s_.expect(p.flags() == value_); + s_.BEAST_EXPECT(p.flags() == value_); } }; @@ -529,7 +529,7 @@ public: void operator()(Parser const& p) const { - s_.expect(p.keep_alive() == value_); + s_.BEAST_EXPECT(p.keep_alive() == value_); } }; @@ -661,9 +661,9 @@ public: good(1, s, [&](fail_parser const& p) { - expect(p.content_length() == v); + BEAST_EXPECT(p.content_length() == v); if(v != no_content_length) - expect(p.flags() & parse_flag::contentlength); + BEAST_EXPECT(p.flags() & parse_flag::contentlength); }); }; auto const c = @@ -787,7 +787,7 @@ public: "\r\n", [&](fail_parser const& p) { - expect(p.upgrade()); + BEAST_EXPECT(p.upgrade()); }); } @@ -811,7 +811,7 @@ public: void operator()(Parser const& p) const { - s_.expect(p.body == body_); + s_.BEAST_EXPECT(p.body == body_); } }; @@ -855,8 +855,8 @@ public: "Content-Length: 1\r\n" "\r\n" ), ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); } // write the body in 3 pieces @@ -871,15 +871,15 @@ public: buf("12"), buf("345"), buf("67890")), ec); - expect(! ec); - expect(p.complete()); - expect(! p.needs_eof()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); + BEAST_EXPECT(! p.needs_eof()); p.write_eof(ec); - expect(! ec); + BEAST_EXPECT(! ec); p.write_eof(ec); - expect(! ec); + BEAST_EXPECT(! ec); p.write(buf("GET / HTTP/1.1\r\n\r\n"), ec); - expect(ec == parse_error::connection_closed); + BEAST_EXPECT(ec == parse_error::connection_closed); } // request without Content-Length or @@ -892,9 +892,9 @@ public: "GET / HTTP/1.0\r\n" "\r\n" ), ec); - expect(! ec); - expect(! p.needs_eof()); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.needs_eof()); + BEAST_EXPECT(p.complete()); } { error_code ec; @@ -904,9 +904,9 @@ public: "GET / HTTP/1.1\r\n" "\r\n" ), ec); - expect(! ec); - expect(! p.needs_eof()); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.needs_eof()); + BEAST_EXPECT(p.complete()); } // response without Content-Length or @@ -919,20 +919,20 @@ public: "HTTP/1.0 200 OK\r\n" "\r\n" ), ec); - expect(! ec); - expect(! p.complete()); - expect(p.needs_eof()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.complete()); + BEAST_EXPECT(p.needs_eof()); p.write(buf( "hello" ), ec); - expect(! ec); - expect(! p.complete()); - expect(p.needs_eof()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.complete()); + BEAST_EXPECT(p.needs_eof()); p.write_eof(ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); p.write(buf("GET / HTTP/1.1\r\n\r\n"), ec); - expect(ec == parse_error::connection_closed); + BEAST_EXPECT(ec == parse_error::connection_closed); } // 304 "Not Modified" response does not require eof @@ -944,9 +944,9 @@ public: "HTTP/1.0 304 Not Modified\r\n" "\r\n" ), ec); - expect(! ec); - expect(! p.needs_eof()); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.needs_eof()); + BEAST_EXPECT(p.complete()); } // Chunked response does not require eof @@ -959,15 +959,15 @@ public: "Transfer-Encoding: chunked\r\n" "\r\n" ), ec); - expect(! ec); - expect(! p.needs_eof()); - expect(! p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.needs_eof()); + BEAST_EXPECT(! p.complete()); p.write(buf( "0\r\n\r\n" ), ec); - expect(! ec); - expect(! p.needs_eof()); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(! p.needs_eof()); + BEAST_EXPECT(p.complete()); } // restart: 1.0 assumes Connection: close @@ -979,13 +979,13 @@ public: "GET / HTTP/1.0\r\n" "\r\n" ), ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); p.write(buf( "GET / HTTP/1.0\r\n" "\r\n" ), ec); - expect(ec == parse_error::connection_closed); + BEAST_EXPECT(ec == parse_error::connection_closed); } // restart: 1.1 assumes Connection: keep-alive @@ -997,14 +997,14 @@ public: "GET / HTTP/1.1\r\n" "\r\n" ), ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); p.write(buf( "GET / HTTP/1.0\r\n" "\r\n" ), ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); } bad(3, @@ -1110,9 +1110,9 @@ public: ), ec); if(! ec) break; - expect(ec == parse_error::headers_too_big); + BEAST_EXPECT(ec == parse_error::headers_too_big); } - expect(n < Limit); + BEAST_EXPECT(n < Limit); } { for(n = 1; n < Limit; ++n) @@ -1130,9 +1130,9 @@ public: ), ec); if(! ec) break; - expect(ec == parse_error::headers_too_big); + BEAST_EXPECT(ec == parse_error::headers_too_big); } - expect(n < Limit); + BEAST_EXPECT(n < Limit); } { test::fail_counter fc(1000); @@ -1146,7 +1146,7 @@ public: "\r\n" "****" ), ec); - expect(ec == parse_error::body_too_big); + BEAST_EXPECT(ec == parse_error::body_too_big); } } diff --git a/src/beast/test/http/detail/chunk_encode.cpp b/src/beast/test/http/chunk_encode.cpp similarity index 98% rename from src/beast/test/http/detail/chunk_encode.cpp rename to src/beast/test/http/chunk_encode.cpp index a952df79c4..f44e3eca9b 100644 --- a/src/beast/test/http/detail/chunk_encode.cpp +++ b/src/beast/test/http/chunk_encode.cpp @@ -71,7 +71,7 @@ public: { std::string s; encode(s, args...); - expect(s == answer); + BEAST_EXPECT(s == answer); } void run() override diff --git a/src/beast/test/http/message.cpp b/src/beast/test/http/message.cpp index 3c549248e9..68696a06c8 100644 --- a/src/beast/test/http/message.cpp +++ b/src/beast/test/http/message.cpp @@ -108,22 +108,22 @@ public: { Arg1 arg1; message{std::move(arg1)}; - expect(arg1.moved); + BEAST_EXPECT(arg1.moved); } { headers h; h.insert("User-Agent", "test"); message m{Arg1{}, h}; - expect(h["User-Agent"] == "test"); - expect(m.headers["User-Agent"] == "test"); + BEAST_EXPECT(h["User-Agent"] == "test"); + BEAST_EXPECT(m.headers["User-Agent"] == "test"); } { headers h; h.insert("User-Agent", "test"); message m{Arg1{}, std::move(h)}; - expect(! h.exists("User-Agent")); - expect(m.headers["User-Agent"] == "test"); + BEAST_EXPECT(! h.exists("User-Agent")); + BEAST_EXPECT(m.headers["User-Agent"] == "test"); } } @@ -137,14 +137,14 @@ public: m2.method = "G"; m2.body = "2"; swap(m1, m2); - expect(m1.method == "G"); - expect(m2.method.empty()); - expect(m1.url.empty()); - expect(m2.url == "u"); - expect(m1.body == "2"); - expect(m2.body == "1"); - expect(! m1.headers.exists("h")); - expect(m2.headers.exists("h")); + BEAST_EXPECT(m1.method == "G"); + BEAST_EXPECT(m2.method.empty()); + BEAST_EXPECT(m1.url.empty()); + BEAST_EXPECT(m2.url == "u"); + BEAST_EXPECT(m1.body == "2"); + BEAST_EXPECT(m2.body == "1"); + BEAST_EXPECT(! m1.headers.exists("h")); + BEAST_EXPECT(m2.headers.exists("h")); } void run() override diff --git a/src/beast/test/http/message_fuzz.hpp b/src/beast/test/http/message_fuzz.hpp index fd29c3931c..e736c96070 100644 --- a/src/beast/test/http/message_fuzz.hpp +++ b/src/beast/test/http/message_fuzz.hpp @@ -30,7 +30,7 @@ escaped_string(boost::string_ref const& s) out.append("\\r"); else if(*p == '\n') out.append("\\n"); - else if (*p == '\t') + else if(*p == '\t') out.append("\\t"); else out.append(p, 1); @@ -472,85 +472,85 @@ public: return s; } - template + template void - headers(Streambuf& sb) + headers(DynamicBuffer& db) { while(rand(6)) { - write(sb, field()); - write(sb, rand(4) ? ": " : ":"); - write(sb, value()); - write(sb, "\r\n"); + write(db, field()); + write(db, rand(4) ? ": " : ":"); + write(db, value()); + write(db, "\r\n"); } } - template + template void - body(Streambuf& sb) + body(DynamicBuffer& db) { if(! rand(4)) { - write(sb, "Content-Length: 0\r\n\r\n"); + write(db, "Content-Length: 0\r\n\r\n"); return; } if(rand(2)) { auto const len = rand(500); - write(sb, "Content-Length: ", len, "\r\n\r\n"); - for(auto const& b : sb.prepare(len)) + write(db, "Content-Length: ", len, "\r\n\r\n"); + for(auto const& b : db.prepare(len)) { auto p = boost::asio::buffer_cast(b); auto n = boost::asio::buffer_size(b); while(n--) *p++ = static_cast(32 + rand(26+26+10+6)); } - sb.commit(len); + db.commit(len); } else { auto len = rand(500); - write(sb, "Transfer-Encoding: chunked\r\n\r\n"); + write(db, "Transfer-Encoding: chunked\r\n\r\n"); while(len > 0) { auto n = std::min(1 + rand(300), len); len -= n; - write(sb, to_hex(n), "\r\n"); - for(auto const& b : sb.prepare(n)) + write(db, to_hex(n), "\r\n"); + for(auto const& b : db.prepare(n)) { auto p = boost::asio::buffer_cast(b); auto m = boost::asio::buffer_size(b); while(m--) *p++ = static_cast(32 + rand(26+26+10+6)); } - sb.commit(n); - write(sb, "\r\n"); + db.commit(n); + write(db, "\r\n"); } - write(sb, "0\r\n\r\n"); + write(db, "0\r\n\r\n"); } } - template + template void - request(Streambuf& sb) + request(DynamicBuffer& db) { - write(sb, method(), " ", uri(), " HTTP/1.1\r\n"); - headers(sb); - body(sb); + write(db, method(), " ", uri(), " HTTP/1.1\r\n"); + headers(db); + body(db); } - template + template void - response(Streambuf& sb) + response(DynamicBuffer& db) { - write(sb, "HTTP/1."); - write(sb, rand(2) ? "0" : "1"); - write(sb, " ", 100 + rand(401), " "); - write(sb, token()); - write(sb, "\r\n"); - headers(sb); - body(sb); - write(sb, "\r\n"); + write(db, "HTTP/1."); + write(db, rand(2) ? "0" : "1"); + write(db, " ", 100 + rand(401), " "); + write(db, token()); + write(db, "\r\n"); + headers(db); + body(db); + write(db, "\r\n"); } }; diff --git a/src/beast/test/http/message_v1.cpp b/src/beast/test/http/message_v1.cpp index a8954c6818..faedd42372 100644 --- a/src/beast/test/http/message_v1.cpp +++ b/src/beast/test/http/message_v1.cpp @@ -27,14 +27,14 @@ public: m.url = "/"; m.version = 11; m.headers.insert("Upgrade", "test"); - expect(! is_upgrade(m)); + BEAST_EXPECT(! is_upgrade(m)); prepare(m, connection::upgrade); - expect(is_upgrade(m)); - expect(m.headers["Connection"] == "upgrade"); + BEAST_EXPECT(is_upgrade(m)); + BEAST_EXPECT(m.headers["Connection"] == "upgrade"); m.version = 10; - expect(! is_upgrade(m)); + BEAST_EXPECT(! is_upgrade(m)); } } @@ -42,7 +42,7 @@ public: { request_v1 m; m.version = 10; - expect(! is_upgrade(m)); + BEAST_EXPECT(! is_upgrade(m)); m.headers.insert("Transfer-Encoding", "chunked"); try { @@ -77,7 +77,7 @@ public: m.version = 11; m.headers.erase("Connection"); m.headers.insert("Connection", "close"); - expect(! is_keep_alive(m)); + BEAST_EXPECT(! is_keep_alive(m)); } void testSwap() @@ -93,16 +93,16 @@ public: m2.body = "2"; m2.version = 11; swap(m1, m2); - expect(m1.status == 404); - expect(m2.status == 200); - expect(m1.reason == "OK"); - expect(m2.reason.empty()); - expect(m1.version == 11); - expect(m2.version == 10); - expect(m1.body == "2"); - expect(m2.body == "1"); - expect(! m1.headers.exists("h")); - expect(m2.headers.exists("h")); + BEAST_EXPECT(m1.status == 404); + BEAST_EXPECT(m2.status == 200); + BEAST_EXPECT(m1.reason == "OK"); + BEAST_EXPECT(m2.reason.empty()); + BEAST_EXPECT(m1.version == 11); + BEAST_EXPECT(m2.version == 10); + BEAST_EXPECT(m1.body == "2"); + BEAST_EXPECT(m2.body == "1"); + BEAST_EXPECT(! m1.headers.exists("h")); + BEAST_EXPECT(m2.headers.exists("h")); } void run() override diff --git a/src/beast/test/http/nodejs_parser.hpp b/src/beast/test/http/nodejs_parser.hpp index 4cbf2b5737..19c09cd5dd 100644 --- a/src/beast/test/http/nodejs_parser.hpp +++ b/src/beast/test/http/nodejs_parser.hpp @@ -223,7 +223,7 @@ private: template().on_start(), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -253,7 +253,7 @@ private: std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -283,7 +283,7 @@ private: decltype(std::declval().on_headers_complete( std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -314,7 +314,7 @@ private: std::declval(), std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -349,7 +349,7 @@ private: std::declval(), std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); #if 0 using type = decltype(check(0)); @@ -389,7 +389,7 @@ private: std::declval(), std::declval(), std::declval()), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -418,7 +418,7 @@ private: template().on_complete(), std::true_type{})> static R check(int); - template + template static std::false_type check(...); using type = decltype(check(0)); public: @@ -488,7 +488,7 @@ nodejs_basic_parser::write( using boost::asio::buffer_cast; using boost::asio::buffer_size; std::size_t bytes_used = 0; - for (auto const& buffer : buffers) + for(auto const& buffer : buffers) { auto const n = write( buffer_cast(buffer), @@ -609,7 +609,7 @@ template void nodejs_basic_parser::check_header() { - if (! value_.empty()) + if(! value_.empty()) { //detail::trim(value_); call_on_field(field_, value_, diff --git a/src/beast/test/http/parse_error.cpp b/src/beast/test/http/parse_error.cpp index ad7f47290f..769d09e677 100644 --- a/src/beast/test/http/parse_error.cpp +++ b/src/beast/test/http/parse_error.cpp @@ -20,13 +20,13 @@ public: void check(char const* name, parse_error ev) { auto const ec = make_error_code(ev); - expect(std::string{ec.category().name()} == name); - expect(! ec.message().empty()); - expect(std::addressof(ec.category()) == + BEAST_EXPECT(std::string{ec.category().name()} == name); + BEAST_EXPECT(! ec.message().empty()); + BEAST_EXPECT(std::addressof(ec.category()) == std::addressof(get_parse_error_category())); - expect(get_parse_error_category().equivalent(static_cast(ev), + BEAST_EXPECT(get_parse_error_category().equivalent(static_cast(ev), ec.category().default_error_condition(static_cast(ev)))); - expect(get_parse_error_category().equivalent( + BEAST_EXPECT(get_parse_error_category().equivalent( ec, static_cast(ev))); } diff --git a/src/beast/test/http/parser_bench.cpp b/src/beast/test/http/parser_bench.cpp index aacda98d6c..c1840069e1 100644 --- a/src/beast/test/http/parser_bench.cpp +++ b/src/beast/test/http/parser_bench.cpp @@ -74,7 +74,7 @@ public: Parser p; error_code ec; p.write(sb.data(), ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) log << to_string(sb.data()) << std::endl; } } diff --git a/src/beast/test/http/parser_v1.cpp b/src/beast/test/http/parser_v1.cpp index 238e13052b..a5d3427cc5 100644 --- a/src/beast/test/http/parser_v1.cpp +++ b/src/beast/test/http/parser_v1.cpp @@ -32,14 +32,14 @@ public: "\r\n" "*"; p.write(buffer(s), ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); auto m = p.release(); - expect(m.method == "GET"); - expect(m.url == "/"); - expect(m.version == 11); - expect(m.headers["User-Agent"] == "test"); - expect(m.body == "*"); + BEAST_EXPECT(m.method == "GET"); + BEAST_EXPECT(m.url == "/"); + BEAST_EXPECT(m.version == 11); + BEAST_EXPECT(m.headers["User-Agent"] == "test"); + BEAST_EXPECT(m.body == "*"); } { error_code ec; @@ -52,14 +52,27 @@ public: "\r\n" "*"; p.write(buffer(s), ec); - expect(! ec); - expect(p.complete()); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); auto m = p.release(); - expect(m.status == 200); - expect(m.reason == "OK"); - expect(m.version == 11); - expect(m.headers["Server"] == "test"); - expect(m.body == "*"); + BEAST_EXPECT(m.status == 200); + BEAST_EXPECT(m.reason == "OK"); + BEAST_EXPECT(m.version == 11); + BEAST_EXPECT(m.headers["Server"] == "test"); + BEAST_EXPECT(m.body == "*"); + } + // skip body + { + error_code ec; + parser_v1 p; + std::string const s = + "HTTP/1.1 200 Connection Established\r\n" + "Proxy-Agent: Zscaler/5.1\r\n" + "\r\n"; + p.set_option(skip_body{true}); + p.write(buffer(s), ec); + BEAST_EXPECT(! ec); + BEAST_EXPECT(p.complete()); } } }; diff --git a/src/beast/test/http/read.cpp b/src/beast/test/http/read.cpp index d1e6c05402..f3f1c32791 100644 --- a/src/beast/test/http/read.cpp +++ b/src/beast/test/http/read.cpp @@ -48,7 +48,7 @@ public: if(! ec) break; } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { static std::size_t constexpr pre = 10; @@ -64,7 +64,7 @@ public: if(! ec) break; } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { streambuf sb; @@ -79,7 +79,7 @@ public: if(! ec) break; } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { static std::size_t constexpr pre = 10; @@ -95,7 +95,7 @@ public: if(! ec) break; } - expect(n < limit); + BEAST_EXPECT(n < limit); } void testThrow() @@ -201,7 +201,7 @@ public: { } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -219,7 +219,7 @@ public: if(! ec) break; } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -237,7 +237,7 @@ public: if(! ec) break; } - expect(n < limit); + BEAST_EXPECT(n < limit); } void testEof(yield_context do_yield) @@ -248,7 +248,7 @@ public: parser_v1 p; error_code ec; parse(ss, sb, p, ec); - expect(ec == boost::asio::error::eof); + BEAST_EXPECT(ec == boost::asio::error::eof); } { streambuf sb; @@ -256,7 +256,7 @@ public: parser_v1 p; error_code ec; async_parse(ss, sb, p, do_yield[ec]); - expect(ec == boost::asio::error::eof); + BEAST_EXPECT(ec == boost::asio::error::eof); } } diff --git a/src/beast/test/http/reason.cpp b/src/beast/test/http/reason.cpp index 9acb938571..e4d6efe823 100644 --- a/src/beast/test/http/reason.cpp +++ b/src/beast/test/http/reason.cpp @@ -19,7 +19,7 @@ public: void run() override { for(int i = 1; i <= 999; ++i) - expect(reason_string(i) != nullptr); + BEAST_EXPECT(reason_string(i) != nullptr); } }; diff --git a/src/beast/test/http/rfc7230.cpp b/src/beast/test/http/rfc7230.cpp index c63fd8ae9c..49b1c95256 100644 --- a/src/beast/test/http/rfc7230.cpp +++ b/src/beast/test/http/rfc7230.cpp @@ -56,7 +56,7 @@ public: [&](std::string const& s) { auto const got = str(param_list{s}); - expect(got == s, fmt(got)); + BEAST_EXPECTS(got == s, fmt(got)); }; auto const cs = [&](std::string const& s, std::string const& good) @@ -64,13 +64,13 @@ public: ce(good); auto const got = str(param_list{s}); ce(got); - expect(got == good, fmt(got)); + BEAST_EXPECTS(got == good, fmt(got)); }; auto const cq = [&](std::string const& s, std::string const& good) { auto const got = str(param_list{s}); - expect(got == good, fmt(got)); + BEAST_EXPECTS(got == good, fmt(got)); }; ce(""); @@ -114,7 +114,7 @@ public: [&](std::string const& s) { auto const got = str(ext_list{s}); - expect(got == s, fmt(got)); + BEAST_EXPECTS(got == s, fmt(got)); }; auto const cs = [&](std::string const& s, std::string const& good) @@ -122,13 +122,13 @@ public: ce(good); auto const got = str(ext_list{s}); ce(got); - expect(got == good, fmt(got)); + BEAST_EXPECTS(got == good, fmt(got)); }; auto const cq = [&](std::string const& s, std::string const& good) { auto const got = str(ext_list{s}); - expect(got == good, fmt(got)); + BEAST_EXPECTS(got == good, fmt(got)); }; /* ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] ) @@ -161,9 +161,9 @@ public: cq("ab;x=\" \"", "ab;x= "); cq("ab;x=\"\\\"\"", "ab;x=\""); - expect(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("A")); - expect(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("b")); - expect(! ext_list{"a,b;i=1,c;j=2;k=3"}.exists("d")); + BEAST_EXPECT(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("A")); + BEAST_EXPECT(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("b")); + BEAST_EXPECT(! ext_list{"a,b;i=1,c;j=2;k=3"}.exists("d")); // invalid strings cs("i j", "i"); @@ -193,7 +193,7 @@ public: [&](std::string const& s) { auto const got = str(token_list{s}); - expect(got == s, fmt(got)); + BEAST_EXPECTS(got == s, fmt(got)); }; auto const cs = [&](std::string const& s, std::string const& good) @@ -201,7 +201,7 @@ public: ce(good); auto const got = str(token_list{s}); ce(got); - expect(got == good, fmt(got)); + BEAST_EXPECTS(got == good, fmt(got)); }; cs("", ""); @@ -222,9 +222,9 @@ public: cs("x ,\ty ", "x,y"); cs("x, y, z", "x,y,z"); - expect(token_list{"a,b,c"}.exists("A")); - expect(token_list{"a,b,c"}.exists("b")); - expect(! token_list{"a,b,c"}.exists("d")); + BEAST_EXPECT(token_list{"a,b,c"}.exists("A")); + BEAST_EXPECT(token_list{"a,b,c"}.exists("b")); + BEAST_EXPECT(! token_list{"a,b,c"}.exists("d")); // invalid cs("x y", "x"); diff --git a/src/beast/test/http/status.cpp b/src/beast/test/http/status.cpp deleted file mode 100644 index df270195d7..0000000000 --- a/src/beast/test/http/status.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// 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) -// - -// Test that header file is self-contained. -#include diff --git a/src/beast/test/http/streambuf_body.cpp b/src/beast/test/http/streambuf_body.cpp index 33ac29b70a..eec8412206 100644 --- a/src/beast/test/http/streambuf_body.cpp +++ b/src/beast/test/http/streambuf_body.cpp @@ -37,8 +37,8 @@ public: parser_v1 p; streambuf sb; parse(ss, sb, p); - expect(to_string(p.get().body.data()) == "xyz"); - expect(boost::lexical_cast(p.get()) == s); + BEAST_EXPECT(to_string(p.get().body.data()) == "xyz"); + BEAST_EXPECT(boost::lexical_cast(p.get()) == s); } }; diff --git a/src/beast/test/http/write.cpp b/src/beast/test/http/write.cpp index 0143a79575..f08c6b6246 100644 --- a/src/beast/test/http/write.cpp +++ b/src/beast/test/http/write.cpp @@ -241,8 +241,8 @@ public: error_code ec; string_write_stream ss(ios_); async_write(ss, m, do_yield[ec]); - if(expect(! ec, ec.message())) - expect(ss.str == + if(BEAST_EXPECTS(! ec, ec.message())) + BEAST_EXPECT(ss.str == "HTTP/1.0 200 OK\r\n" "Server: test\r\n" "Content-Length: 5\r\n" @@ -260,8 +260,8 @@ public: error_code ec; string_write_stream ss(ios_); async_write(ss, m, do_yield[ec]); - if(expect(! ec, ec.message())) - expect(ss.str == + if(BEAST_EXPECTS(! ec, ec.message())) + BEAST_EXPECT(ss.str == "HTTP/1.1 200 OK\r\n" "Server: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -295,7 +295,7 @@ public: try { write(fs, m); - expect(fs.next_layer().str == + BEAST_EXPECT(fs.next_layer().str == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Content-Length: 5\r\n" @@ -309,7 +309,7 @@ public: { } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -329,7 +329,7 @@ public: write(fs, m, ec); if(ec == boost::asio::error::eof) { - expect(fs.next_layer().str == + BEAST_EXPECT(fs.next_layer().str == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -344,7 +344,7 @@ public: break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -364,7 +364,7 @@ public: async_write(fs, m, do_yield[ec]); if(ec == boost::asio::error::eof) { - expect(fs.next_layer().str == + BEAST_EXPECT(fs.next_layer().str == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -379,7 +379,7 @@ public: break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -399,7 +399,7 @@ public: write(fs, m, ec); if(! ec) { - expect(fs.next_layer().str == + BEAST_EXPECT(fs.next_layer().str == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Content-Length: 5\r\n" @@ -409,7 +409,7 @@ public: break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); for(n = 0; n < limit; ++n) { @@ -429,7 +429,7 @@ public: async_write(fs, m, do_yield[ec]); if(! ec) { - expect(fs.next_layer().str == + BEAST_EXPECT(fs.next_layer().str == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Content-Length: 5\r\n" @@ -439,7 +439,7 @@ public: break; } } - expect(n < limit); + BEAST_EXPECT(n < limit); } void @@ -454,7 +454,7 @@ public: m.headers.insert("User-Agent", "test"); m.body = "*"; prepare(m); - expect(str(m) == + BEAST_EXPECT(str(m) == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Content-Length: 1\r\n" @@ -471,7 +471,7 @@ public: m.headers.insert("User-Agent", "test"); m.body = "*"; prepare(m, connection::keep_alive); - expect(str(m) == + BEAST_EXPECT(str(m) == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Content-Length: 1\r\n" @@ -510,8 +510,8 @@ public: string_write_stream ss(ios_); error_code ec; write(ss, m, ec); - expect(ec == boost::asio::error::eof); - expect(ss.str == + BEAST_EXPECT(ec == boost::asio::error::eof); + BEAST_EXPECT(ss.str == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "\r\n" @@ -527,7 +527,7 @@ public: m.headers.insert("User-Agent", "test"); m.body = "*"; prepare(m); - expect(str(m) == + BEAST_EXPECT(str(m) == "GET / HTTP/1.1\r\n" "User-Agent: test\r\n" "Content-Length: 1\r\n" @@ -547,8 +547,8 @@ public: string_write_stream ss(ios_); error_code ec; write(ss, m, ec); - expect(ec == boost::asio::error::eof); - expect(ss.str == + BEAST_EXPECT(ec == boost::asio::error::eof); + BEAST_EXPECT(ss.str == "GET / HTTP/1.1\r\n" "User-Agent: test\r\n" "Content-Length: 1\r\n" @@ -565,7 +565,7 @@ public: m.version = 11; m.headers.insert("User-Agent", "test"); prepare(m, connection::upgrade); - expect(str(m) == + BEAST_EXPECT(str(m) == "GET / HTTP/1.1\r\n" "User-Agent: test\r\n" "Connection: upgrade\r\n" @@ -584,7 +584,7 @@ public: string_write_stream ss(ios_); error_code ec; write(ss, m, ec); - expect(ss.str == + BEAST_EXPECT(ss.str == "GET / HTTP/1.1\r\n" "User-Agent: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -605,7 +605,7 @@ public: m.headers.insert("User-Agent", "test"); m.body = "*"; prepare(m); - expect(boost::lexical_cast(m) == + BEAST_EXPECT(boost::lexical_cast(m) == "GET / HTTP/1.1\r\nUser-Agent: test\r\nContent-Length: 1\r\n\r\n*"); } diff --git a/src/beast/test/websocket/CMakeLists.txt b/src/beast/test/websocket/CMakeLists.txt index 7a52207b60..5cc4c20b13 100644 --- a/src/beast/test/websocket/CMakeLists.txt +++ b/src/beast/test/websocket/CMakeLists.txt @@ -1,36 +1,38 @@ # Part of Beast -GroupSources(extras/beast beast) +GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(test/websocket "/") add_executable (websocket-tests ${BEAST_INCLUDES} + ${EXTRAS_INCLUDES} ../../extras/beast/unit_test/main.cpp - websocket_async_echo_peer.hpp - websocket_sync_echo_peer.hpp + websocket_async_echo_server.hpp + websocket_sync_echo_server.hpp error.cpp option.cpp rfc6455.cpp stream.cpp teardown.cpp - detail/frame.cpp - detail/mask.cpp - detail/stream_base.cpp - detail/utf8_checker.cpp + frame.cpp + mask.cpp + stream_base.cpp + utf8_checker.cpp ) if (NOT WIN32) - target_link_libraries(websocket-tests ${Boost_LIBRARIES}) + target_link_libraries(websocket-tests ${Boost_LIBRARIES} Threads::Threads) endif() add_executable (websocket-echo ${BEAST_INCLUDES} - websocket_async_echo_peer.hpp - websocket_sync_echo_peer.hpp + ${EXTRAS_INCLUDES} + websocket_async_echo_server.hpp + websocket_sync_echo_server.hpp websocket_echo.cpp ) if (NOT WIN32) - target_link_libraries(websocket-echo ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(websocket-echo ${Boost_LIBRARIES} Threads::Threads) endif() diff --git a/src/beast/test/websocket/error.cpp b/src/beast/test/websocket/error.cpp index 0e5ebf6bb6..29a0210fa0 100644 --- a/src/beast/test/websocket/error.cpp +++ b/src/beast/test/websocket/error.cpp @@ -20,13 +20,13 @@ public: void check(char const* name, error ev) { auto const ec = make_error_code(ev); - expect(std::string{ec.category().name()} == name); - expect(! ec.message().empty()); - expect(std::addressof(ec.category()) == + BEAST_EXPECT(std::string{ec.category().name()} == name); + BEAST_EXPECT(! ec.message().empty()); + BEAST_EXPECT(std::addressof(ec.category()) == std::addressof(detail::get_error_category())); - expect(detail::get_error_category().equivalent(static_cast(ev), + BEAST_EXPECT(detail::get_error_category().equivalent(static_cast(ev), ec.category().default_error_condition(static_cast(ev)))); - expect(detail::get_error_category().equivalent( + BEAST_EXPECT(detail::get_error_category().equivalent( ec, static_cast(ev))); } diff --git a/src/beast/test/websocket/detail/frame.cpp b/src/beast/test/websocket/frame.cpp similarity index 82% rename from src/beast/test/websocket/detail/frame.cpp rename to src/beast/test/websocket/frame.cpp index d3e54b2b6b..0be416a8a8 100644 --- a/src/beast/test/websocket/detail/frame.cpp +++ b/src/beast/test/websocket/frame.cpp @@ -34,20 +34,20 @@ class frame_test : public beast::unit_test::suite public: void testCloseCodes() { - expect(! is_valid(0)); - expect(! is_valid(1)); - expect(! is_valid(999)); - expect(! is_valid(1004)); - expect(! is_valid(1005)); - expect(! is_valid(1006)); - expect(! is_valid(1016)); - expect(! is_valid(2000)); - expect(! is_valid(2999)); - expect(is_valid(1000)); - expect(is_valid(1002)); - expect(is_valid(3000)); - expect(is_valid(4000)); - expect(is_valid(5000)); + BEAST_EXPECT(! is_valid(0)); + BEAST_EXPECT(! is_valid(1)); + BEAST_EXPECT(! is_valid(999)); + BEAST_EXPECT(! is_valid(1004)); + BEAST_EXPECT(! is_valid(1005)); + BEAST_EXPECT(! is_valid(1006)); + BEAST_EXPECT(! is_valid(1016)); + BEAST_EXPECT(! is_valid(2000)); + BEAST_EXPECT(! is_valid(2999)); + BEAST_EXPECT(is_valid(1000)); + BEAST_EXPECT(is_valid(1002)); + BEAST_EXPECT(is_valid(3000)); + BEAST_EXPECT(is_valid(4000)); + BEAST_EXPECT(is_valid(5000)); } struct test_fh : frame_header @@ -80,16 +80,16 @@ public: close_code::value code; auto const n = read_fh1( fh1, sb, role, code); - if(! expect(! code)) + if(! BEAST_EXPECT(! code)) return; - if(! expect(sb.size() == n)) + if(! BEAST_EXPECT(sb.size() == n)) return; read_fh2(fh1, sb, role, code); - if(! expect(! code)) + if(! BEAST_EXPECT(! code)) return; - if(! expect(sb.size() == 0)) + if(! BEAST_EXPECT(sb.size() == 0)) return; - expect(fh1 == fh); + BEAST_EXPECT(fh1 == fh); }; test_fh fh; @@ -135,12 +135,12 @@ public: pass(); return; } - if(! expect(sb.size() == n)) + if(! BEAST_EXPECT(sb.size() == n)) return; read_fh2(fh1, sb, role, code); - if(! expect(code)) + if(! BEAST_EXPECT(code)) return; - if(! expect(sb.size() == 0)) + if(! BEAST_EXPECT(sb.size() == 0)) return; }; @@ -200,12 +200,12 @@ public: pass(); return; } - if(! expect(sb.size() == n)) + if(! BEAST_EXPECT(sb.size() == n)) return; read_fh2(fh, sb, role, code); - if(! expect(code)) + if(! BEAST_EXPECT(code)) return; - if(! expect(sb.size() == 0)) + if(! BEAST_EXPECT(sb.size() == 0)) return; } diff --git a/src/beast/test/websocket/detail/mask.cpp b/src/beast/test/websocket/mask.cpp similarity index 96% rename from src/beast/test/websocket/detail/mask.cpp rename to src/beast/test/websocket/mask.cpp index 201b516049..6f94ca1427 100644 --- a/src/beast/test/websocket/detail/mask.cpp +++ b/src/beast/test/websocket/mask.cpp @@ -38,7 +38,7 @@ public: void run() override { maskgen_t mg; - expect(mg() != 0); + BEAST_EXPECT(mg() != 0); } }; diff --git a/src/beast/test/websocket/stream.cpp b/src/beast/test/websocket/stream.cpp index de0b00fda7..775c3c06a9 100644 --- a/src/beast/test/websocket/stream.cpp +++ b/src/beast/test/websocket/stream.cpp @@ -8,8 +8,8 @@ // Test that header file is self-contained. #include -#include "websocket_async_echo_peer.hpp" -#include "websocket_sync_echo_peer.hpp" +#include "websocket_async_echo_server.hpp" +#include "websocket_sync_echo_server.hpp" #include #include @@ -109,15 +109,15 @@ public: return false; } - template + template static void - read(stream& ws, opcode& op, Streambuf& sb) + read(stream& ws, opcode& op, DynamicBuffer& db) { frame_info fi; for(;;) { - ws.read_frame(fi, sb); + ws.read_frame(fi, db); op = fi.op; if(fi.fin) break; @@ -204,7 +204,7 @@ public: { } } - expect(n < limit); + BEAST_EXPECT(n < limit); } { // valid @@ -259,11 +259,11 @@ public: { ws.accept(boost::asio::buffer( s.substr(0, i), i)); - expect(! ev); + BEAST_EXPECTS(! ev, ev.message()); } catch(system_error const& se) { - expect(se.code() == ev); + BEAST_EXPECT(se.code() == ev); } } }; @@ -369,7 +369,7 @@ public: } catch(system_error const& se) { - expect(se.code() == error::response_failed); + BEAST_EXPECT(se.code() == error::response_failed); } }; // wrong HTTP version @@ -443,22 +443,22 @@ public: error_code ec; socket_type sock(ios_); sock.connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; stream ws(sock); ws.handshake("localhost", "/", ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; ws.write(boost::asio::buffer(v), ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; opcode op; - streambuf sb; - ws.read(op, sb, ec); - if(! expect(! ec, ec.message())) + streambuf db; + ws.read(op, db, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) break; - expect(to_string(sb.data()) == - std::string{v.data(), v.size()}); + BEAST_EXPECT(to_string(db.data()) == + std::string(v.data(), v.size())); v.push_back(n+1); } } @@ -469,22 +469,22 @@ public: error_code ec; socket_type sock(ios_); sock.connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; stream ws(sock); ws.handshake("localhost", "/", ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; ws.async_write(boost::asio::buffer(v), do_yield[ec]); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); - if(! expect(! ec, ec.message())) + streambuf db; + ws.async_read(op, db, do_yield[ec]); + if(! BEAST_EXPECTS(! ec, ec.message())) break; - expect(to_string(sb.data()) == - std::string{v.data(), v.size()}); + BEAST_EXPECT(to_string(db.data()) == + std::string(v.data(), v.size())); v.push_back(n+1); } } @@ -544,9 +544,9 @@ public: // Read opcode op; - streambuf sb; + streambuf db; ++count; - ws.async_read(op, sb, + ws.async_read(op, db, [&](error_code ec) { --count; @@ -561,7 +561,7 @@ public: { ++count; // Send is canceled because close received. - expect(ec == boost::asio:: + BEAST_EXPECT(ec == boost::asio:: error::operation_aborted, ec.message()); // Writes after close are aborted. @@ -569,7 +569,7 @@ public: [&](error_code ec) { ++count; - expect(ec == boost::asio:: + BEAST_EXPECT(ec == boost::asio:: error::operation_aborted, ec.message()); }); @@ -583,7 +583,7 @@ public: break; ios.run_one(); } - expect(n < limit); + BEAST_EXPECT(n < limit); ios.run(); } #endif @@ -600,23 +600,23 @@ public: ws.write(buffer_cat(sbuf("TEXT"), cbuf(0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc))); opcode op; - streambuf sb; + streambuf db; std::size_t count = 0; // Read text message with bad utf8. // Causes a close to be sent, blocking writes. - ws.async_read(op, sb, + ws.async_read(op, db, [&](error_code ec) { // Read should fail with protocol error ++count; - expect(ec == error::failed, - ec.message()); + BEAST_EXPECTS( + ec == error::failed, ec.message()); // Reads after failure are aborted - ws.async_read(op, sb, + ws.async_read(op, db, [&](error_code ec) { ++count; - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); }); @@ -631,7 +631,7 @@ public: { ++count; // Send is canceled because close received. - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); // Writes after close are aborted. @@ -639,7 +639,7 @@ public: [&](error_code ec) { ++count; - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); }); @@ -653,7 +653,7 @@ public: break; ios.run_one(); } - expect(n < limit); + BEAST_EXPECT(n < limit); ios.run(); } @@ -668,28 +668,28 @@ public: ws.set_option(message_type(opcode::binary)); ws.write(sbuf("CLOSE")); opcode op; - streambuf sb; + streambuf db; std::size_t count = 0; // Read a close frame. // Sends a close frame, blocking writes. - ws.async_read(op, sb, + ws.async_read(op, db, [&](error_code ec) { // Read should complete with error::closed ++count; - expect(ec == error::closed, + BEAST_EXPECTS(ec == error::closed, ec.message()); // Pings after a close are aborted ws.async_ping("", [&](error_code ec) { ++count; - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); }); }); - if(! expect(run_until(ios, 100, + if(! BEAST_EXPECT(run_until(ios, 100, [&]{ return ws.wr_close_; }))) return; // Try to ping @@ -698,7 +698,7 @@ public: { // Pings after a close are aborted ++count; - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); // Subsequent calls to close are aborted @@ -706,7 +706,7 @@ public: [&](error_code ec) { ++count; - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); }); @@ -719,7 +719,7 @@ public: break; ios.run_one(); } - expect(n < limit); + BEAST_EXPECT(n < limit); ios.run(); } @@ -734,13 +734,13 @@ public: ws.set_option(message_type(opcode::binary)); ws.write(sbuf("CLOSE")); opcode op; - streambuf sb; + streambuf db; std::size_t count = 0; - ws.async_read(op, sb, + ws.async_read(op, db, [&](error_code ec) { ++count; - expect(ec == error::closed, + BEAST_EXPECTS(ec == error::closed, ec.message()); }); while(! ws.wr_block_) @@ -750,7 +750,7 @@ public: [&](error_code ec) { ++count; - expect(ec == boost::asio:: + BEAST_EXPECTS(ec == boost::asio:: error::operation_aborted, ec.message()); }); @@ -762,7 +762,7 @@ public: break; ios.run_one(); } - expect(n < limit); + BEAST_EXPECT(n < limit); ios.run(); } @@ -777,21 +777,21 @@ public: ws.async_write(sbuf("CLOSE"), [&](error_code ec) { - expect(! ec); + BEAST_EXPECT(! ec); ws.async_write(sbuf("PING"), [&](error_code ec) { - expect(! ec); + BEAST_EXPECT(! ec); }); }); opcode op; - streambuf sb; - ws.async_read(op, sb, + streambuf db; + ws.async_read(op, db, [&](error_code ec) { - expect(ec == error::closed, ec.message()); + BEAST_EXPECTS(ec == error::closed, ec.message()); }); - if(! expect(run_until(ios, 100, + if(! BEAST_EXPECT(run_until(ios, 100, [&]{ return ios.stopped(); }))) return; } @@ -811,8 +811,8 @@ public: try { opcode op; - streambuf sb; - ws.read(op, sb); + streambuf db; + ws.read(op, db); fail(); return false; } @@ -823,7 +823,7 @@ public: } error_code ec; ws.lowest_layer().connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) return false; ws.handshake("localhost", "/"); return true; @@ -834,7 +834,7 @@ public: // connect error_code ec; ws.lowest_layer().connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) return; } ws.handshake("localhost", "/"); @@ -846,10 +846,10 @@ public: { // receive echoed message opcode op; - streambuf sb; - read(ws, op, sb); - expect(op == opcode::text); - expect(to_string(sb.data()) == "Hello"); + streambuf db; + read(ws, op, db); + BEAST_EXPECT(op == opcode::text); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } // close, no payload @@ -872,9 +872,9 @@ public: ws.set_option(pong_callback{ [&](ping_data const& payload) { - expect(! pong); + BEAST_EXPECT(! pong); pong = true; - expect(payload == ""); + BEAST_EXPECT(payload == ""); }}); ws.ping(""); ws.set_option(message_type(opcode::binary)); @@ -882,11 +882,11 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.read(op, sb); - expect(pong == 1); - expect(op == opcode::binary); - expect(to_string(sb.data()) == "Hello"); + streambuf db; + ws.read(op, db); + BEAST_EXPECT(pong == 1); + BEAST_EXPECT(op == opcode::binary); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } ws.set_option(pong_callback{}); @@ -894,7 +894,7 @@ public: ws.set_option(pong_callback{ [&](ping_data const& payload) { - expect(payload == "payload"); + BEAST_EXPECT(payload == "payload"); }}); ws.ping("payload"); ws.write_frame(false, sbuf("Hello, ")); @@ -903,10 +903,10 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.read(op, sb); - expect(pong == 1); - expect(to_string(sb.data()) == "Hello, World!"); + streambuf db; + ws.read(op, db); + BEAST_EXPECT(pong == 1); + BEAST_EXPECT(to_string(db.data()) == "Hello, World!"); } ws.set_option(pong_callback{}); @@ -916,9 +916,9 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.read(op, sb); - expect(to_string(sb.data()) == "Hello"); + streambuf db; + ws.read(op, db); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } ws.set_option(auto_fragment_size(0)); @@ -930,9 +930,9 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.read(op, sb); - expect(to_string(sb.data()) == s); + streambuf db; + ws.read(op, db); + BEAST_EXPECT(to_string(db.data()) == s); } } @@ -944,10 +944,10 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.read(op, sb); - expect(op == opcode::text); - expect(to_string(sb.data()) == "Hello"); + streambuf db; + ws.read(op, db); + BEAST_EXPECT(op == opcode::text); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } // cause close @@ -1024,7 +1024,7 @@ public: } break; } - expect(n < limit); + BEAST_EXPECT(n < limit); } void testAsyncClient( @@ -1040,9 +1040,9 @@ public: [&](error_code ev) { opcode op; - streambuf sb; + streambuf db; error_code ec; - ws.async_read(op, sb, do_yield[ec]); + ws.async_read(op, db, do_yield[ec]); if(! ec) { fail(); @@ -1057,7 +1057,7 @@ public: ws.lowest_layer().close(ec); ec = {}; ws.lowest_layer().connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) return false; ws.async_handshake("localhost", "/", do_yield[ec]); if(ec) @@ -1070,7 +1070,7 @@ public: // connect ws.lowest_layer().connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) return; ws.async_handshake("localhost", "/", do_yield[ec]); if(ec) @@ -1085,12 +1085,12 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); + streambuf db; + ws.async_read(op, db, do_yield[ec]); if(ec) throw system_error{ec}; - expect(op == opcode::text); - expect(to_string(sb.data()) == "Hello"); + BEAST_EXPECT(op == opcode::text); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } // close, no payload @@ -1120,9 +1120,9 @@ public: ws.set_option(pong_callback{ [&](ping_data const& payload) { - expect(! pong); + BEAST_EXPECT(! pong); pong = true; - expect(payload == ""); + BEAST_EXPECT(payload == ""); }}); ws.async_ping("", do_yield[ec]); if(ec) @@ -1133,12 +1133,12 @@ public: throw system_error{ec}; // receive echoed message opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); + streambuf db; + ws.async_read(op, db, do_yield[ec]); if(ec) throw system_error{ec}; - expect(op == opcode::binary); - expect(to_string(sb.data()) == "Hello"); + BEAST_EXPECT(op == opcode::binary); + BEAST_EXPECT(to_string(db.data()) == "Hello"); ws.set_option(pong_callback{}); } @@ -1147,7 +1147,7 @@ public: ws.set_option(pong_callback{ [&](ping_data const& payload) { - expect(payload == "payload"); + BEAST_EXPECT(payload == "payload"); }}); ws.async_ping("payload", do_yield[ec]); if(! ec) @@ -1161,11 +1161,11 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); + streambuf db; + ws.async_read(op, db, do_yield[ec]); if(ec) throw system_error{ec}; - expect(to_string(sb.data()) == "Hello, World!"); + BEAST_EXPECT(to_string(db.data()) == "Hello, World!"); } ws.set_option(pong_callback{}); } @@ -1176,11 +1176,11 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); + streambuf db; + ws.async_read(op, db, do_yield[ec]); if(ec) throw system_error{ec}; - expect(to_string(sb.data()) == "Hello"); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } ws.set_option(auto_fragment_size(0)); @@ -1194,11 +1194,11 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); + streambuf db; + ws.async_read(op, db, do_yield[ec]); if(ec) throw system_error{ec}; - expect(to_string(sb.data()) == s); + BEAST_EXPECT(to_string(db.data()) == s); } } @@ -1214,12 +1214,12 @@ public: { // receive echoed message opcode op; - streambuf sb; - ws.async_read(op, sb, do_yield[ec]); + streambuf db; + ws.async_read(op, db, do_yield[ec]); if(ec) throw system_error{ec}; - expect(op == opcode::text); - expect(to_string(sb.data()) == "Hello"); + BEAST_EXPECT(op == opcode::text); + BEAST_EXPECT(to_string(db.data()) == "Hello"); } // cause close @@ -1325,7 +1325,7 @@ public: } break; } - expect(n < limit); + BEAST_EXPECT(n < limit); } void testAsyncWriteFrame(endpoint_type const& ep) @@ -1336,11 +1336,11 @@ public: error_code ec; socket_type sock(ios); sock.connect(ep, ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; stream ws(sock); ws.handshake("localhost", "/", ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; ws.async_write_frame(false, boost::asio::null_buffers{}, @@ -1349,7 +1349,7 @@ public: fail(); }); ws.next_layer().cancel(ec); - if(! expect(! ec, ec.message())) + if(! BEAST_EXPECTS(! ec, ec.message())) break; // // Destruction of the io_service will cause destruction @@ -1389,7 +1389,7 @@ public: testBadHandshakes(); testBadResponses(); { - sync_echo_peer server(true, any); + sync_echo_server server(true, any); auto const ep = server.local_endpoint(); //testInvokable1(ep); @@ -1403,7 +1403,7 @@ public: yield_to_mf(ep, &stream_test::testAsyncClient); } { - async_echo_peer server(true, any, 4); + async_echo_server server(true, any, 4); auto const ep = server.local_endpoint(); testSyncClient(ep); testAsyncWriteFrame(ep); diff --git a/src/beast/test/websocket/detail/stream_base.cpp b/src/beast/test/websocket/stream_base.cpp similarity index 95% rename from src/beast/test/websocket/detail/stream_base.cpp rename to src/beast/test/websocket/stream_base.cpp index e76eeae183..4bba083efa 100644 --- a/src/beast/test/websocket/detail/stream_base.cpp +++ b/src/beast/test/websocket/stream_base.cpp @@ -21,7 +21,7 @@ class stream_base_test : public beast::unit_test::suite public: void testClamp() { - expect(detail::clamp( + BEAST_EXPECT(detail::clamp( std::numeric_limits::max()) == std::numeric_limits::max()); } diff --git a/src/beast/test/websocket/detail/utf8_checker.cpp b/src/beast/test/websocket/utf8_checker.cpp similarity index 75% rename from src/beast/test/websocket/detail/utf8_checker.cpp rename to src/beast/test/websocket/utf8_checker.cpp index 8b1ee9c560..14749fda4e 100644 --- a/src/beast/test/websocket/detail/utf8_checker.cpp +++ b/src/beast/test/websocket/utf8_checker.cpp @@ -29,24 +29,24 @@ public: { std::array values; std::uint8_t i = 0; - for (auto& c : values) + for(auto& c : values) c = i++; return values; })(); // Valid range 0-127 - expect(utf8.write(buf.data(), 128)); - expect(utf8.finish()); + BEAST_EXPECT(utf8.write(buf.data(), 128)); + BEAST_EXPECT(utf8.finish()); // Invalid range 128-193 - for (auto it = std::next(buf.begin(), 128); + for(auto it = std::next(buf.begin(), 128); it != std::next(buf.begin(), 194); ++it) - expect(! utf8.write(&(*it), 1)); + BEAST_EXPECT(! utf8.write(&(*it), 1)); // Invalid range 245-255 - for (auto it = std::next(buf.begin(), 245); + for(auto it = std::next(buf.begin(), 245); it != buf.end(); ++it) - expect(! utf8.write(&(*it), 1)); + BEAST_EXPECT(! utf8.write(&(*it), 1)); } void @@ -59,26 +59,26 @@ public: // First byte valid range 194-223 buf[0] = static_cast(i); - for (auto j = 128; j <= 191; ++j) + for(auto j = 128; j <= 191; ++j) { // Second byte valid range 128-191 buf[1] = static_cast(j); - expect(utf8.write(buf, 2)); - expect(utf8.finish()); + BEAST_EXPECT(utf8.write(buf, 2)); + BEAST_EXPECT(utf8.finish()); } - for (auto j = 0; j <= 127; ++j) + for(auto j = 0; j <= 127; ++j) { // Second byte invalid range 0-127 buf[1] = static_cast(j); - expect(! utf8.write(buf, 2)); + BEAST_EXPECT(! utf8.write(buf, 2)); } - for (auto j = 192; j <= 255; ++j) + for(auto j = 192; j <= 255; ++j) { // Second byte invalid range 192-255 buf[1] = static_cast(j); - expect(! utf8.write(buf, 2)); + BEAST_EXPECT(! utf8.write(buf, 2)); } } } @@ -88,53 +88,53 @@ public: { utf8_checker utf8; std::uint8_t buf[3]; - for (auto i = 224; i <= 239; ++i) + for(auto i = 224; i <= 239; ++i) { // First byte valid range 224-239 buf[0] = static_cast(i); std::int32_t const b = (i == 224 ? 160 : 128); std::int32_t const e = (i == 237 ? 159 : 191); - for (auto j = b; j <= e; ++j) + for(auto j = b; j <= e; ++j) { // Second byte valid range 128-191 or 160-191 or 128-159 buf[1] = static_cast(j); - for (auto k = 128; k <= 191; ++k) + for(auto k = 128; k <= 191; ++k) { // Third byte valid range 128-191 buf[2] = static_cast(k); - expect(utf8.write(buf, 3)); - expect(utf8.finish()); + BEAST_EXPECT(utf8.write(buf, 3)); + BEAST_EXPECT(utf8.finish()); } - for (auto k = 0; k <= 127; ++k) + for(auto k = 0; k <= 127; ++k) { // Third byte invalid range 0-127 buf[2] = static_cast(k); - expect(! utf8.write(buf, 3)); + BEAST_EXPECT(! utf8.write(buf, 3)); } - for (auto k = 192; k <= 255; ++k) + for(auto k = 192; k <= 255; ++k) { // Third byte invalid range 192-255 buf[2] = static_cast(k); - expect(! utf8.write(buf, 3)); + BEAST_EXPECT(! utf8.write(buf, 3)); } } - for (auto j = 0; j < b; ++j) + for(auto j = 0; j < b; ++j) { // Second byte invalid range 0-127 or 0-159 buf[1] = static_cast(j); - expect(! utf8.write(buf, 3)); + BEAST_EXPECT(! utf8.write(buf, 3)); } - for (auto j = e + 1; j <= 255; ++j) + for(auto j = e + 1; j <= 255; ++j) { // Second byte invalid range 160-255 or 192-255 buf[1] = static_cast(j); - expect(! utf8.write(buf, 3)); + BEAST_EXPECT(! utf8.write(buf, 3)); } } } @@ -145,73 +145,73 @@ public: using boost::asio::const_buffers_1; utf8_checker utf8; std::uint8_t buf[4]; - for (auto i = 240; i <= 244; ++i) + for(auto i = 240; i <= 244; ++i) { // First byte valid range 240-244 buf[0] = static_cast(i); std::int32_t const b = (i == 240 ? 144 : 128); std::int32_t const e = (i == 244 ? 143 : 191); - for (auto j = b; j <= e; ++j) + for(auto j = b; j <= e; ++j) { // Second byte valid range 128-191 or 144-191 or 128-143 buf[1] = static_cast(j); - for (auto k = 128; k <= 191; ++k) + for(auto k = 128; k <= 191; ++k) { // Third byte valid range 128-191 buf[2] = static_cast(k); - for (auto n = 128; n <= 191; ++n) + for(auto n = 128; n <= 191; ++n) { // Fourth byte valid range 128-191 buf[3] = static_cast(n); - expect(utf8.write(const_buffers_1{buf, 4})); - expect(utf8.finish()); + BEAST_EXPECT(utf8.write(const_buffers_1{buf, 4})); + BEAST_EXPECT(utf8.finish()); } - for (auto n = 0; n <= 127; ++n) + for(auto n = 0; n <= 127; ++n) { // Fourth byte invalid range 0-127 buf[3] = static_cast(n); - expect(! utf8.write(const_buffers_1{buf, 4})); + BEAST_EXPECT(! utf8.write(const_buffers_1{buf, 4})); } - for (auto n = 192; n <= 255; ++n) + for(auto n = 192; n <= 255; ++n) { // Fourth byte invalid range 192-255 buf[3] = static_cast(n); - expect(! utf8.write(buf, 4)); + BEAST_EXPECT(! utf8.write(buf, 4)); } } - for (auto k = 0; k <= 127; ++k) + for(auto k = 0; k <= 127; ++k) { // Third byte invalid range 0-127 buf[2] = static_cast(k); - expect(! utf8.write(buf, 4)); + BEAST_EXPECT(! utf8.write(buf, 4)); } - for (auto k = 192; k <= 255; ++k) + for(auto k = 192; k <= 255; ++k) { // Third byte invalid range 192-255 buf[2] = static_cast(k); - expect(! utf8.write(buf, 4)); + BEAST_EXPECT(! utf8.write(buf, 4)); } } - for (auto j = 0; j < b; ++j) + for(auto j = 0; j < b; ++j) { // Second byte invalid range 0-127 or 0-143 buf[1] = static_cast(j); - expect(! utf8.write(buf, 3)); + BEAST_EXPECT(! utf8.write(buf, 3)); } - for (auto j = e + 1; j <= 255; ++j) + for(auto j = e + 1; j <= 255; ++j) { // Second byte invalid range 144-255 or 192-255 buf[1] = static_cast(j); - expect(! utf8.write(buf, 3)); + BEAST_EXPECT(! utf8.write(buf, 3)); } } } @@ -258,8 +258,8 @@ public: cb.consume(amount); n -= amount; } - expect(utf8.write(sb.data())); - expect(utf8.finish()); + BEAST_EXPECT(utf8.write(sb.data())); + BEAST_EXPECT(utf8.finish()); } } } diff --git a/src/beast/test/websocket/websocket_async_echo_peer.hpp b/src/beast/test/websocket/websocket_async_echo_server.hpp similarity index 89% rename from src/beast/test/websocket/websocket_async_echo_peer.hpp rename to src/beast/test/websocket/websocket_async_echo_server.hpp index e374dc8cbc..35201f008c 100644 --- a/src/beast/test/websocket/websocket_async_echo_peer.hpp +++ b/src/beast/test/websocket/websocket_async_echo_server.hpp @@ -22,7 +22,7 @@ namespace websocket { // Asynchronous WebSocket echo client/server // -class async_echo_peer +class async_echo_server { public: using endpoint_type = boost::asio::ip::tcp::endpoint; @@ -37,7 +37,7 @@ private: std::vector thread_; public: - async_echo_peer(bool server, + async_echo_server(bool server, endpoint_type const& ep, std::size_t threads) : sock_(ios_) , acceptor_(ios_) @@ -55,7 +55,7 @@ public: boost::asio::socket_base::max_connections, ec); maybe_throw(ec, "listen"); acceptor_.async_accept(sock_, - std::bind(&async_echo_peer::on_accept, this, + std::bind(&async_echo_server::on_accept, this, beast::asio::placeholders::error)); } else @@ -68,7 +68,7 @@ public: [&]{ ios_.run(); }); } - ~async_echo_peer() + ~async_echo_server() { error_code ec; ios_.dispatch( @@ -94,7 +94,7 @@ private: stream ws; boost::asio::io_service::strand strand; opcode op; - beast::streambuf sb; + beast::streambuf db; int id; data(bool log_, socket_type&& sock_) @@ -177,22 +177,22 @@ private: } } - template + template static bool - match(Streambuf& sb, char const(&s)[N]) + match(DynamicBuffer& db, char const(&s)[N]) { using boost::asio::buffer; using boost::asio::buffer_copy; - if(sb.size() < N-1) + if(db.size() < N-1) return false; static_string t; t.resize(N-1); buffer_copy(buffer(t.data(), t.size()), - sb.data()); + db.data()); if(t != s) return false; - sb.consume(N-1); + db.consume(N-1); return true; } @@ -217,10 +217,10 @@ private: case 1: if(ec) return fail(ec, "async_handshake"); - d.sb.consume(d.sb.size()); + d.db.consume(d.db.size()); // read message d.state = 2; - d.ws.async_read(d.op, d.sb, + d.ws.async_read(d.op, d.db, d.strand.wrap(std::move(*this))); return; @@ -230,33 +230,33 @@ private: return; if(ec) return fail(ec, "async_read"); - if(match(d.sb, "RAW")) + if(match(d.db, "RAW")) { d.state = 1; boost::asio::async_write(d.ws.next_layer(), - d.sb.data(), d.strand.wrap(std::move(*this))); + d.db.data(), d.strand.wrap(std::move(*this))); return; } - else if(match(d.sb, "TEXT")) + else if(match(d.db, "TEXT")) { d.state = 1; d.ws.set_option(message_type{opcode::text}); d.ws.async_write( - d.sb.data(), d.strand.wrap(std::move(*this))); + d.db.data(), d.strand.wrap(std::move(*this))); return; } - else if(match(d.sb, "PING")) + else if(match(d.db, "PING")) { ping_data payload; - d.sb.consume(buffer_copy( + d.db.consume(buffer_copy( buffer(payload.data(), payload.size()), - d.sb.data())); + d.db.data())); d.state = 1; d.ws.async_ping(payload, d.strand.wrap(std::move(*this))); return; } - else if(match(d.sb, "CLOSE")) + else if(match(d.db, "CLOSE")) { d.state = 1; d.ws.async_close({}, @@ -266,7 +266,7 @@ private: // write message d.state = 1; d.ws.set_option(message_type(d.op)); - d.ws.async_write(d.sb.data(), + d.ws.async_write(d.db.data(), d.strand.wrap(std::move(*this))); return; @@ -325,7 +325,7 @@ private: maybe_throw(ec, "accept"); socket_type sock(std::move(sock_)); acceptor_.async_accept(sock_, - std::bind(&async_echo_peer::on_accept, this, + std::bind(&async_echo_server::on_accept, this, beast::asio::placeholders::error)); Peer{false, std::move(sock)}; } diff --git a/src/beast/test/websocket/websocket_echo.cpp b/src/beast/test/websocket/websocket_echo.cpp index 98b8c8963c..636087b4c3 100644 --- a/src/beast/test/websocket/websocket_echo.cpp +++ b/src/beast/test/websocket/websocket_echo.cpp @@ -5,8 +5,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include "websocket_async_echo_peer.hpp" -#include "websocket_sync_echo_peer.hpp" +#include "websocket_async_echo_server.hpp" +#include "websocket_sync_echo_server.hpp" #include int main() @@ -14,10 +14,10 @@ int main() using endpoint_type = boost::asio::ip::tcp::endpoint; using address_type = boost::asio::ip::address; - beast::websocket::async_echo_peer s1(true, endpoint_type{ + beast::websocket::async_echo_server s1(true, endpoint_type{ address_type::from_string("127.0.0.1"), 6000 }, 4); - beast::websocket::sync_echo_peer s2(true, endpoint_type{ + beast::websocket::sync_echo_server s2(true, endpoint_type{ address_type::from_string("127.0.0.1"), 6001 }); beast::test::sig_wait(); diff --git a/src/beast/test/websocket/websocket_sync_echo_peer.hpp b/src/beast/test/websocket/websocket_sync_echo_server.hpp similarity index 92% rename from src/beast/test/websocket/websocket_sync_echo_peer.hpp rename to src/beast/test/websocket/websocket_sync_echo_server.hpp index 6d0665461f..a09e475044 100644 --- a/src/beast/test/websocket/websocket_sync_echo_peer.hpp +++ b/src/beast/test/websocket/websocket_sync_echo_server.hpp @@ -21,7 +21,7 @@ namespace websocket { // Synchronous WebSocket echo client/server // -class sync_echo_peer +class sync_echo_server { public: using endpoint_type = boost::asio::ip::tcp::endpoint; @@ -36,7 +36,7 @@ private: std::thread thread_; public: - sync_echo_peer(bool server, endpoint_type ep) + sync_echo_server(bool server, endpoint_type ep) : sock_(ios_) , acceptor_(ios_) { @@ -51,12 +51,12 @@ public: boost::asio::socket_base::max_connections, ec); maybe_throw(ec, "listen"); acceptor_.async_accept(sock_, - std::bind(&sync_echo_peer::on_accept, this, + std::bind(&sync_echo_server::on_accept, this, beast::asio::placeholders::error)); thread_ = std::thread{[&]{ ios_.run(); }}; } - ~sync_echo_peer() + ~sync_echo_server() { error_code ec; ios_.dispatch( @@ -100,13 +100,13 @@ private: struct lambda { int id; - sync_echo_peer& self; + sync_echo_server& self; boost::asio::io_service::work work; // Must be destroyed before work otherwise the // io_service could be destroyed before the socket. socket_type sock; - lambda(int id_, sync_echo_peer& self_, + lambda(int id_, sync_echo_server& self_, socket_type&& sock_) : id(id_) , self(self_) @@ -130,7 +130,7 @@ private: static int id_ = 0; std::thread{lambda{++id_, *this, std::move(sock_)}}.detach(); acceptor_.async_accept(sock_, - std::bind(&sync_echo_peer::on_accept, this, + std::bind(&sync_echo_server::on_accept, this, beast::asio::placeholders::error)); } @@ -151,22 +151,22 @@ private: } }; - template + template static bool - match(Streambuf& sb, char const(&s)[N]) + match(DynamicBuffer& db, char const(&s)[N]) { using boost::asio::buffer; using boost::asio::buffer_copy; - if(sb.size() < N-1) + if(db.size() < N-1) return false; static_string t; t.resize(N-1); buffer_copy(buffer(t.data(), t.size()), - sb.data()); + db.data()); if(t != s) return false; - sb.consume(N-1); + db.consume(N-1); return true; }