diff --git a/CHANGELOG.md b/CHANGELOG.md index 02904387..81cf9ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Version 62: * Remove libssl-dev from a Travis matrix item * Increase detail::static_ostream coverage +* Add server-framework tests -------------------------------------------------------------------------------- diff --git a/example/server-framework/multi_port.hpp b/example/server-framework/multi_port.hpp index 934d1abe..53f06f80 100644 --- a/example/server-framework/multi_port.hpp +++ b/example/server-framework/multi_port.hpp @@ -138,8 +138,7 @@ private: this->log_, this->services_, this->id_, - ep - )->handshake(buffer_.data()); + ep)->handshake(buffer_.data()); // When we return the last shared pointer to this // object will go away and `*this` will be destroyed. @@ -318,8 +317,7 @@ public: log_, instance_.next_id(), ep, - cb2_ - )->run(std::move(req)); + cb2_)->run(std::move(req)); } }; @@ -388,8 +386,7 @@ public: log_, services_, instance_.next_id(), - ep - )->detect(); + ep)->detect(); } }; diff --git a/test/Jamfile b/test/Jamfile index a19c70a1..61119bc2 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -15,6 +15,7 @@ compile websocket.cpp : : ; compile zlib.cpp : : ; build-project server ; +build-project websocket ; unit-test core-tests : ../extras/beast/unit_test/main.cpp @@ -76,19 +77,6 @@ unit-test http-bench : http/parser_bench.cpp ; -unit-test websocket-tests : - ../extras/beast/unit_test/main.cpp - websocket/doc_snippets.cpp - websocket/error.cpp - websocket/option.cpp - websocket/rfc6455.cpp - websocket/stream.cpp - websocket/teardown.cpp - websocket/frame.cpp - websocket/mask.cpp - websocket/utf8_checker.cpp - ; - unit-test zlib-tests : ../extras/beast/unit_test/main.cpp zlib/zlib-1.2.8/adler32.c diff --git a/test/server/CMakeLists.txt b/test/server/CMakeLists.txt index 8a948b76..73b73dce 100644 --- a/test/server/CMakeLists.txt +++ b/test/server/CMakeLists.txt @@ -1,23 +1,19 @@ # Part of Beast GroupSources(example/server-framework framework) +GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(test/server "/") if (OPENSSL_FOUND) include_directories(${OPENSSL_INCLUDE_DIR}) - set(SSL_SOURCES - https_ports.cpp - ssl_stream.cpp - ) -else () - set(SSL_SOURCES "") endif() add_executable (server-test ${BEAST_INCLUDES} ${SERVER_INCLUDES} + ../../extras/beast/unit_test/main.cpp file_body.cpp file_service.cpp framework.cpp @@ -25,21 +21,25 @@ add_executable (server-test http_base.cpp http_sync_port.cpp https_ports.cpp - main.cpp multi_port.cpp rfc7231.cpp server.cpp service_list.cpp ssl_certificate + ssl_stream.cpp + tests.cpp write_msg.cpp ws_async_port.cpp ws_sync_port.cpp ws_upgrade_service.cpp wss_ports.cpp - ${SSL_SOURCES} ) -target_link_libraries(server-test Beast) +target_link_libraries(server-test + Beast + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ) if (OPENSSL_FOUND) target_link_libraries(server-test ${OPENSSL_LIBRARIES}) diff --git a/test/server/Jamfile b/test/server/Jamfile index 4086abe2..52c4ca8b 100644 --- a/test/server/Jamfile +++ b/test/server/Jamfile @@ -5,23 +5,24 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # -exe server-test : +unit-test server-test : + ../../extras/beast/unit_test/main.cpp file_body.cpp file_service.cpp framework.cpp http_async_port.cpp http_base.cpp http_sync_port.cpp - main.cpp + https_ports.cpp + multi_port.cpp rfc7231.cpp server.cpp service_list.cpp + ssl_certificate.cpp + ssl_stream.cpp + tests.cpp write_msg.cpp ws_async_port.cpp ws_sync_port.cpp ws_upgrade_service.cpp - #https_ports.cpp - #multi_port.cpp - #ssl_certificate.cpp - #ssl_stream.cpp ; diff --git a/test/server/main.cpp b/test/server/main.cpp deleted file mode 100644 index e9335ff3..00000000 --- a/test/server/main.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright (c) 2013-2017 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) -// - -int main(int argc, char** argv) -{ -} diff --git a/test/server/multi_port.cpp b/test/server/multi_port.cpp index 6b108b49..a86ee0f3 100644 --- a/test/server/multi_port.cpp +++ b/test/server/multi_port.cpp @@ -5,6 +5,10 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // +#if BEAST_USE_OPENSSL + // Test that header file is self-contained. #include "../../example/server-framework/multi_port.hpp" +#endif + diff --git a/test/server/tests.cpp b/test/server/tests.cpp new file mode 100644 index 00000000..13643447 --- /dev/null +++ b/test/server/tests.cpp @@ -0,0 +1,328 @@ +// +// Copyright (c) 2013-2017 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) +// + +#include "example/server-framework/http_sync_port.hpp" +#include "example/server-framework/http_async_port.hpp" +#include "example/server-framework/ws_sync_port.hpp" +#include "example/server-framework/ws_async_port.hpp" +#include "example/server-framework/ws_upgrade_service.hpp" + +#if BEAST_USE_OPENSSL +# include "example/server-framework/https_ports.hpp" +# include "example/server-framework/multi_port.hpp" +# include "example/server-framework/ssl_certificate.hpp" +# include "example/server-framework/wss_ports.hpp" +#endif + +#include +#include +#include +#include + +namespace beast { +namespace websocket { + +class server_test + : public beast::unit_test::suite + , public test::enable_yield_to +{ +public: + static unsigned short constexpr port_num = 6000; + + class set_ws_options + { + beast::websocket::permessage_deflate pmd_; + + public: + set_ws_options(beast::websocket::permessage_deflate const& pmd) + : pmd_(pmd) + { + } + + template + void + operator()(beast::websocket::stream& ws) const + { + ws.auto_fragment(false); + ws.set_option(pmd_); + ws.read_message_max(64 * 1024 * 1024); + } + }; + + set_ws_options + get_ws_options() + { + beast::websocket::permessage_deflate pmd; + pmd.client_enable = true; + pmd.server_enable = true; + pmd.compLevel = 3; + return set_ws_options{pmd}; + } + + template + void + doOptions(Stream& stream, error_code& ec) + { + beast::http::request req; + req.version = 11; + req.method(beast::http::verb::options); + req.target("*"); + req.set(beast::http::field::user_agent, "test"); + req.set(beast::http::field::connection, "close"); + + beast::http::write(stream, req, ec); + if(! BEAST_EXPECTS( + ec == beast::http::error::end_of_stream, + ec.message())) + return; + + beast::flat_buffer b; + beast::http::response res; + beast::http::read(stream, b, res, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + } + + template + void + doHello(stream& ws, error_code& ec) + { + ws.handshake("localhost", "/", ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + ws.write(boost::asio::buffer(std::string("Hello, world!")), ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + beast::multi_buffer b; + ws.read(b, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + ws.close(beast::websocket::close_code::normal, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + // VFALCO Verify the buffer's contents + drain_buffer drain; + for(;;) + { + ws.read(drain, ec); + if(ec == beast::websocket::error::closed) + break; + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + } + } + + void + httpClient(framework::endpoint_type const& ep) + { + error_code ec; + boost::asio::ip::tcp::socket con{ios_}; + con.connect(ep, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + doOptions(con, ec); + } + + void + wsClient(framework::endpoint_type const& ep) + { + error_code ec; + stream ws{ios_}; + ws.next_layer().connect(ep, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + doHello(ws, ec); + } + + void + testPlain() + { + using namespace framework; + + // ws sync + { + error_code ec; + server instance; + auto const ep1 = endpoint_type{ + address_type::from_string("127.0.0.1"), port_num}; + auto const wsp = instance.make_port( + ec, ep1, instance, log, get_ws_options()); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + auto const ep2 = endpoint_type{ + address_type::from_string("127.0.0.1"), + static_cast(port_num + 1)}; + auto const sp = instance.make_port< + http_sync_port>>( + ec, ep2, instance, log); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + sp->template init<0>(ec, *wsp); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + + wsClient(ep1); + wsClient(ep2); + + httpClient(ep2); + } + + // ws async + { + error_code ec; + server instance; + auto const ep1 = endpoint_type{ + address_type::from_string("127.0.0.1"), port_num}; + auto const wsp = instance.make_port( + ec, ep1, instance, log, get_ws_options()); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + auto const ep2 = endpoint_type{ + address_type::from_string("127.0.0.1"), + static_cast(port_num + 1)}; + auto const sp = instance.make_port< + http_async_port>>( + ec, ep2, instance, log); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + sp->template init<0>(ec, *wsp); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + + wsClient(ep1); + wsClient(ep2); + + httpClient(ep2); + } + } + +#if BEAST_USE_OPENSSL + // + // OpenSSL enabled ports + // + + void + httpsClient(framework::endpoint_type const& ep, + boost::asio::ssl::context& ctx) + { + error_code ec; + boost::asio::ssl::stream con{ios_, ctx}; + con.next_layer().connect(ep, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + con.handshake( + boost::asio::ssl::stream_base::client, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + doOptions(con, ec); + if(ec) + return; + con.shutdown(ec); + // VFALCO No idea why we get eof in the normal case + if(ec == boost::asio::error::eof) + ec = {}; + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + } + + void + wssClient(framework::endpoint_type const& ep, + boost::asio::ssl::context& ctx) + { + error_code ec; + stream> wss{ios_, ctx}; + wss.next_layer().next_layer().connect(ep, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + wss.next_layer().handshake( + boost::asio::ssl::stream_base::client, ec); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + doHello(wss, ec); + } + + void + testSSL() + { + using namespace framework; + + ssl_certificate cert; + + // wss sync + { + error_code ec; + server instance; + auto const ep1 = endpoint_type{ + address_type::from_string("127.0.0.1"), port_num}; + auto const wsp = instance.make_port( + ec, ep1, instance, log, cert.get(), get_ws_options()); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + auto const ep2 = endpoint_type{ + address_type::from_string("127.0.0.1"), + static_cast(port_num + 1)}; + auto const sp = instance.make_port< + https_sync_port>>( + ec, ep2, instance, log, cert.get()); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + sp->template init<0>(ec, *wsp); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + + wssClient(ep1, cert.get()); + wssClient(ep2, cert.get()); + + httpsClient(ep2, cert.get()); + } + + // wss async + { + error_code ec; + server instance; + auto const ep1 = endpoint_type{ + address_type::from_string("127.0.0.1"), port_num}; + auto const wsp = instance.make_port( + ec, ep1, instance, log, cert.get(), get_ws_options()); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + auto const ep2 = endpoint_type{ + address_type::from_string("127.0.0.1"), + static_cast(port_num + 1)}; + auto const sp = instance.make_port< + https_async_port>>( + ec, ep2, instance, log, cert.get()); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + sp->template init<0>(ec, *wsp); + if(! BEAST_EXPECTS(! ec, ec.message())) + return; + + wssClient(ep1, cert.get()); + wssClient(ep2, cert.get()); + + httpsClient(ep2, cert.get()); + } + } +#endif + + void + run() override + { + testPlain(); + + #if BEAST_USE_OPENSSL + testSSL(); + #endif + } +}; + +BEAST_DEFINE_TESTSUITE(server,websocket,beast); + +} // websocket +} // beast + diff --git a/test/websocket/CMakeLists.txt b/test/websocket/CMakeLists.txt index 8d709eb1..a4a04490 100644 --- a/test/websocket/CMakeLists.txt +++ b/test/websocket/CMakeLists.txt @@ -4,6 +4,8 @@ GroupSources(extras/beast extras) GroupSources(include/beast beast) GroupSources(test/websocket "/") +include_directories(../../example/) + add_executable (websocket-tests ${BEAST_INCLUDES} ${EXTRAS_INCLUDES} @@ -21,8 +23,11 @@ add_executable (websocket-tests utf8_checker.cpp ) -target_link_libraries(websocket-tests Beast ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_COROUTINE_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY}) - -if (MINGW) - set_target_properties(websocket-tests PROPERTIES COMPILE_FLAGS "-Wa,-mbig-obj -Og") -endif() +target_link_libraries(websocket-tests + Beast + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_COROUTINE_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_CONTEXT_LIBRARY} + ) diff --git a/test/websocket/Jamfile b/test/websocket/Jamfile new file mode 100644 index 00000000..4781f16a --- /dev/null +++ b/test/websocket/Jamfile @@ -0,0 +1,19 @@ +# +# Copyright (c) 2013-2017 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) +# + +unit-test websocket-tests : + ../../extras/beast/unit_test/main.cpp + doc_snippets.cpp + error.cpp + option.cpp + rfc6455.cpp + stream.cpp + teardown.cpp + frame.cpp + mask.cpp + utf8_checker.cpp + ;