diff --git a/CHANGELOG.md b/CHANGELOG.md index 696b202d..4cf3abd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ Version 107: +* Use test::stream + WebSocket * Fix done state for WebSocket reads diff --git a/test/beast/core/buffered_read_stream.cpp b/test/beast/core/buffered_read_stream.cpp index 92ae1273..a450b0f2 100644 --- a/test/beast/core/buffered_read_stream.cpp +++ b/test/beast/core/buffered_read_stream.cpp @@ -11,8 +11,7 @@ #include #include -#include -#include +#include #include #include #include @@ -32,35 +31,32 @@ class buffered_read_stream_test public: void testSpecialMembers() { - using socket_type = boost::asio::ip::tcp::socket; boost::asio::io_service ios; { - buffered_read_stream srs(ios); - buffered_read_stream srs2(std::move(srs)); + buffered_read_stream srs(ios); + buffered_read_stream srs2(std::move(srs)); srs = std::move(srs2); BEAST_EXPECT(&srs.get_io_service() == &ios); BEAST_EXPECT(&srs.get_io_service() == &srs2.get_io_service()); } { - socket_type sock(ios); - buffered_read_stream srs(sock); - buffered_read_stream srs2(std::move(srs)); + test::stream ts{ios}; + buffered_read_stream srs(ts); } } struct loop : std::enable_shared_from_this { - using stream_type = test::fail_stream< - test::string_istream>; static std::size_t constexpr limit = 100; std::string s_; std::size_t n_ = 0; std::size_t cap_; unit_test::suite& suite_; boost::asio::io_service& ios_; - boost::optional fs_; + boost::optional ts_; + boost::optional fc_; boost::optional> brs_; + test::stream&, multi_buffer>> brs_; loop( unit_test::suite& suite, @@ -101,8 +97,9 @@ public: using boost::asio::buffer; using boost::asio::buffer_copy; s_.resize(13); - fs_.emplace(n_, ios_, ", world!"); - brs_.emplace(*fs_); + fc_.emplace(n_); + ts_.emplace(ios_, *fc_, ", world!"); + brs_.emplace(*ts_); brs_->buffer().commit(buffer_copy( brs_->buffer().prepare(5), buffer("Hello", 5))); boost::asio::async_read(*brs_, @@ -133,10 +130,10 @@ public: for(n = 0; n < limit; ++n) { - test::fail_stream< - test::string_istream> fs(n, ios_, ", world!"); + test::fail_counter fc{n}; + test::stream ts(ios_, fc, ", world!"); buffered_read_stream< - decltype(fs)&, multi_buffer> srs(fs); + test::stream&, multi_buffer> srs(ts); srs.buffer().commit(buffer_copy( srs.buffer().prepare(5), buffer("Hello", 5))); error_code ec = test::error::fail_error; @@ -151,10 +148,10 @@ public: for(n = 0; n < limit; ++n) { - test::fail_stream< - test::string_istream> fs(n, ios_, ", world!"); + test::fail_counter fc{n}; + test::stream ts(ios_, fc, ", world!"); buffered_read_stream< - decltype(fs)&, multi_buffer> srs(fs); + test::stream&, multi_buffer> srs(ts); srs.capacity(3); srs.buffer().commit(buffer_copy( srs.buffer().prepare(5), buffer("Hello", 5))); @@ -170,10 +167,10 @@ public: for(n = 0; n < limit; ++n) { - test::fail_stream< - test::string_istream> fs(n, ios_, ", world!"); + test::fail_counter fc{n}; + test::stream ts(ios_, fc, ", world!"); buffered_read_stream< - decltype(fs)&, multi_buffer> srs(fs); + test::stream&, multi_buffer> srs(ts); srs.buffer().commit(buffer_copy( srs.buffer().prepare(5), buffer("Hello", 5))); error_code ec = test::error::fail_error; @@ -189,10 +186,10 @@ public: for(n = 0; n < limit; ++n) { - test::fail_stream< - test::string_istream> fs(n, ios_, ", world!"); + test::fail_counter fc{n}; + test::stream ts(ios_, fc, ", world!"); buffered_read_stream< - decltype(fs)&, multi_buffer> srs(fs); + test::stream&, multi_buffer> srs(ts); srs.capacity(3); srs.buffer().commit(buffer_copy( srs.buffer().prepare(5), buffer("Hello", 5))); diff --git a/test/beast/http/dynamic_body.cpp b/test/beast/http/dynamic_body.cpp index a1866948..80bcd044 100644 --- a/test/beast/http/dynamic_body.cpp +++ b/test/beast/http/dynamic_body.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include namespace boost { @@ -61,10 +61,10 @@ public: "Content-Length: 3\r\n" "\r\n" "xyz"; - test::string_istream ss(ios_, s); + test::stream ts(ios_, s); response_parser p; multi_buffer b; - read(ss, b, p); + read(ts, b, p); auto const& m = p.get(); BEAST_EXPECT(to_string(m.body.data()) == "xyz"); BEAST_EXPECT(to_string(m) == s); diff --git a/test/beast/http/parser.cpp b/test/beast/http/parser.cpp index 69fabdd1..ebc5558a 100644 --- a/test/beast/http/parser.cpp +++ b/test/beast/http/parser.cpp @@ -13,8 +13,6 @@ #include "test_parser.hpp" #include -#include -#include #include #include #include diff --git a/test/beast/http/read.cpp b/test/beast/http/read.cpp index 2c6c4707..bc508750 100644 --- a/test/beast/http/read.cpp +++ b/test/beast/http/read.cpp @@ -18,10 +18,7 @@ #include #include #include -#include -#include #include -#include #include #include #include @@ -51,11 +48,11 @@ public: b.commit(buffer_copy( b.prepare(len), buffer(s, len))); test::fail_counter fc(n); - test::fail_stream< - test::string_istream> fs{fc, ios_, ""}; + test::stream ts{ios_, fc}; test_parser p(fc); error_code ec = test::error::fail_error; - read(fs, b, p, ec); + ts.remote().close(); + read(ts, b, p, ec); if(! ec) break; } @@ -67,11 +64,12 @@ public: b.commit(buffer_copy( b.prepare(pre), buffer(s, pre))); test::fail_counter fc(n); - test::fail_stream fs{ - fc, ios_, std::string{s + pre, len - pre}}; + test::stream ts{ios_, fc, + std::string(s + pre, len - pre)}; test_parser p(fc); error_code ec = test::error::fail_error; - read(fs, b, p, ec); + ts.remote().close(); + read(ts, b, p, ec); if(! ec) break; } @@ -82,11 +80,11 @@ public: b.commit(buffer_copy( b.prepare(len), buffer(s, len))); test::fail_counter fc(n); - test::fail_stream< - test::string_istream> fs{fc, ios_, ""}; + test::stream ts{ios_, fc}; test_parser p(fc); error_code ec = test::error::fail_error; - async_read(fs, b, p, do_yield[ec]); + ts.remote().close(); + async_read(ts, b, p, do_yield[ec]); if(! ec) break; } @@ -98,11 +96,12 @@ public: b.commit(buffer_copy( b.prepare(pre), buffer(s, pre))); test::fail_counter fc(n); - test::fail_stream fs{ - fc, ios_, std::string{s + pre, len - pre}}; + test::stream ts(ios_, fc, + std::string{s + pre, len - pre}); test_parser p(fc); error_code ec = test::error::fail_error; - async_read(fs, b, p, do_yield[ec]); + ts.remote().close(); + async_read(ts, b, p, do_yield[ec]); if(! ec) break; } @@ -226,10 +225,8 @@ public: , nullptr }; - for(std::size_t i = 0; req[i]; ++i) failMatrix(req[i], do_yield); - for(std::size_t i = 0; res[i]; ++i) failMatrix(res[i], do_yield); } @@ -264,17 +261,18 @@ public: for(n = 0; n < limit; ++n) { - test::fail_stream fs(n, ios_, + test::fail_counter fc{n}; + test::stream ts{ios_, fc, "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "User-Agent: test\r\n" "Content-Length: 0\r\n" "\r\n" - ); + }; request m; error_code ec = test::error::fail_error; multi_buffer b; - read(fs, b, m, ec); + read(ts, b, m, ec); if(! ec) break; } @@ -305,18 +303,20 @@ public: { { multi_buffer b; - test::string_istream ss(ios_, ""); + test::stream ts{ios_}; request_parser p; error_code ec; - read(ss, b, p, ec); + ts.remote().close(); + read(ts, b, p, ec); BEAST_EXPECT(ec == http::error::end_of_stream); } { multi_buffer b; - test::string_istream ss(ios_, ""); + test::stream ts{ios_}; request_parser p; error_code ec; - async_read(ss, b, p, do_yield[ec]); + ts.remote().close(); + async_read(ts, b, p, do_yield[ec]); BEAST_EXPECT(ec == http::error::end_of_stream); } } @@ -339,12 +339,12 @@ public: // Make sure handlers are not destroyed // after calling io_service::stop boost::asio::io_service ios; - test::string_istream is{ios, + test::stream ts{ios, "GET / HTTP/1.1\r\n\r\n"}; BEAST_EXPECT(handler::count() == 0); multi_buffer b; request m; - async_read(is, b, m, handler{}); + async_read(ts, b, m, handler{}); BEAST_EXPECT(handler::count() > 0); ios.stop(); BEAST_EXPECT(handler::count() > 0); @@ -358,12 +358,12 @@ public: // destroyed when calling ~io_service { boost::asio::io_service ios; - test::string_istream is{ios, + test::stream ts{ios, "GET / HTTP/1.1\r\n\r\n"}; BEAST_EXPECT(handler::count() == 0); multi_buffer b; request m; - async_read(is, b, m, handler{}); + async_read(ts, b, m, handler{}); BEAST_EXPECT(handler::count() > 0); } BEAST_EXPECT(handler::count() == 0); @@ -374,9 +374,9 @@ public: void testRegression430() { - test::pipe c{ios_}; - c.server.read_size(1); - ostream(c.server.buffer) << + test::stream ts{ios_}; + ts.read_size(1); + ostream(ts.buffer()) << "HTTP/1.1 200 OK\r\n" "Transfer-Encoding: chunked\r\n" "Content-Type: application/octet-stream\r\n" @@ -386,7 +386,7 @@ public: error_code ec; flat_buffer fb; response_parser p; - read(c.server, fb, p, ec); + read(ts, fb, p, ec); BEAST_EXPECTS(! ec, ec.message()); } @@ -402,10 +402,10 @@ public: Parser p; error_code ec = test::error::fail_error; flat_buffer b; - test::pipe c{ios_}; - ostream(c.server.buffer) << s; - c.server.read_size(n); - read(c.server, b, p, ec); + test::stream ts{ios_}; + ostream(ts.buffer()) << s; + ts.read_size(n); + read(ts, b, p, ec); if(! BEAST_EXPECTS(! ec, ec.message())) continue; pred(p); @@ -452,12 +452,18 @@ public: testThrow(); testBufferOverflow(); - yield_to([&](yield_context yield){ - testFailures(yield); }); - yield_to([&](yield_context yield){ - testRead(yield); }); - yield_to([&](yield_context yield){ - testEof(yield); }); + yield_to([&](yield_context yield) + { + testFailures(yield); + }); + yield_to([&](yield_context yield) + { + testRead(yield); + }); + yield_to([&](yield_context yield) + { + testEof(yield); + }); testIoService(); testRegression430(); diff --git a/test/beast/http/write.cpp b/test/beast/http/write.cpp index e265371c..38b510e1 100644 --- a/test/beast/http/write.cpp +++ b/test/beast/http/write.cpp @@ -18,10 +18,7 @@ #include #include #include -#include -#include -#include -#include +#include #include #include #include @@ -287,13 +284,13 @@ public: bool equal_body(string_view sv, string_view body) { - test::string_istream si{ - get_io_service(), sv.to_string()}; + test::stream ts{ios_, sv}; message m; multi_buffer b; + ts.remote().close(); try { - read(si, b, m); + read(ts, b, m); return m.body == body; } catch(std::exception const& e) @@ -307,12 +304,12 @@ public: std::string str(message const& m) { - test::string_ostream ss(ios_); + test::stream ts(ios_); error_code ec; - write(ss, m, ec); + write(ts, m, ec); if(ec && ec != error::end_of_stream) BOOST_THROW_EXCEPTION(system_error{ec}); - return ss.str; + return ts.remote().str().to_string(); } void @@ -326,10 +323,10 @@ public: m.set(field::content_length, "5"); m.body = "*****"; error_code ec; - test::string_ostream ss{ios_}; - async_write(ss, m, do_yield[ec]); + test::stream ts{ios_}; + async_write(ts, m, do_yield[ec]); if(BEAST_EXPECTS(ec == error::end_of_stream, ec.message())) - BEAST_EXPECT(ss.str == + BEAST_EXPECT(ts.remote().str() == "HTTP/1.0 200 OK\r\n" "Server: test\r\n" "Content-Length: 5\r\n" @@ -344,10 +341,10 @@ public: m.set(field::transfer_encoding, "chunked"); m.body = "*****"; error_code ec; - test::string_ostream ss(ios_); - async_write(ss, m, do_yield[ec]); + test::stream ts{ios_}; + async_write(ts, m, do_yield[ec]); if(BEAST_EXPECTS(! ec, ec.message())) - BEAST_EXPECT(ss.str == + BEAST_EXPECT(ts.remote().str() == "HTTP/1.1 200 OK\r\n" "Server: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -367,8 +364,7 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::fail_stream< - test::string_ostream> fs(fc, ios_); + test::stream ts(ios_, fc); request m(verb::get, "/", 10, fc); m.set(field::user_agent, "test"); m.set(field::connection, "keep-alive"); @@ -376,8 +372,8 @@ public: m.body = "*****"; try { - write(fs, m); - BEAST_EXPECT(fs.next_layer().str == + write(ts, m); + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Connection: keep-alive\r\n" @@ -397,17 +393,16 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::fail_stream< - test::string_ostream> fs(fc, ios_); + test::stream ts(ios_, fc); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); m.set(field::transfer_encoding, "chunked"); m.body = "*****"; error_code ec = test::error::fail_error; - write(fs, m, ec); + write(ts, m, ec); if(ec == error::end_of_stream) { - BEAST_EXPECT(fs.next_layer().str == + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -427,17 +422,16 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::fail_stream< - test::string_ostream> fs(fc, ios_); + test::stream ts(ios_, fc); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); m.set(field::transfer_encoding, "chunked"); m.body = "*****"; error_code ec = test::error::fail_error; - async_write(fs, m, do_yield[ec]); + async_write(ts, m, do_yield[ec]); if(ec == error::end_of_stream) { - BEAST_EXPECT(fs.next_layer().str == + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -457,18 +451,17 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::fail_stream< - test::string_ostream> fs(fc, ios_); + test::stream ts(ios_, fc); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); m.set(field::connection, "keep-alive"); m.set(field::content_length, "5"); m.body = "*****"; error_code ec = test::error::fail_error; - write(fs, m, ec); + write(ts, m, ec); if(! ec) { - BEAST_EXPECT(fs.next_layer().str == + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Connection: keep-alive\r\n" @@ -484,18 +477,17 @@ public: for(n = 0; n < limit; ++n) { test::fail_counter fc(n); - test::fail_stream< - test::string_ostream> fs(fc, ios_); + test::stream ts(ios_, fc); request m{verb::get, "/", 10, fc}; m.set(field::user_agent, "test"); m.set(field::connection, "keep-alive"); m.set(field::content_length, "5"); m.body = "*****"; error_code ec = test::error::fail_error; - async_write(fs, m, do_yield[ec]); + async_write(ts, m, do_yield[ec]); if(! ec) { - BEAST_EXPECT(fs.next_layer().str == + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "Connection: keep-alive\r\n" @@ -538,11 +530,11 @@ public: m.set(field::user_agent, "test"); m.body = "*"; m.prepare_payload(); - test::string_ostream ss(ios_); + test::stream ts(ios_); error_code ec; - write(ss, m, ec); + write(ts, m, ec); BEAST_EXPECT(ec == error::end_of_stream); - BEAST_EXPECT(ss.str == + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.0\r\n" "User-Agent: test\r\n" "\r\n" @@ -575,10 +567,10 @@ public: m.set(field::user_agent, "test"); m.body = "*"; m.prepare_payload(); - test::string_ostream ss(ios_); + test::stream ts(ios_); error_code ec; - write(ss, m, ec); - BEAST_EXPECT(ss.str == + write(ts, m, ec); + BEAST_EXPECT(ts.remote().str() == "GET / HTTP/1.1\r\n" "User-Agent: test\r\n" "Transfer-Encoding: chunked\r\n" @@ -621,7 +613,7 @@ public: // Make sure handlers are not destroyed // after calling io_service::stop boost::asio::io_service ios; - test::string_ostream os{ios}; + test::stream ts{ios}; BEAST_EXPECT(handler::count() == 0); request m; m.method(verb::get); @@ -629,7 +621,7 @@ public: m.target("/"); m.set("Content-Length", 5); m.body = "*****"; - async_write(os, m, handler{}); + async_write(ts, m, handler{}); BEAST_EXPECT(handler::count() > 0); ios.stop(); BEAST_EXPECT(handler::count() > 0); @@ -643,7 +635,7 @@ public: // destroyed when calling ~io_service { boost::asio::io_service ios; - test::string_ostream is{ios}; + test::stream ts{ios}; BEAST_EXPECT(handler::count() == 0); request m; m.method(verb::get); @@ -651,7 +643,7 @@ public: m.target("/"); m.set("Content-Length", 5); m.body = "*****"; - async_write(is, m, handler{}); + async_write(ts, m, handler{}); BEAST_EXPECT(handler::count() > 0); } BEAST_EXPECT(handler::count() == 0); @@ -670,11 +662,9 @@ public: serializer sr{m}; for(;;) { - stream.nwrite = 0; write_some(stream, sr, ec); if(ec) return; - BEAST_EXPECT(stream.nwrite <= 1); if(sr.is_done()) break; } @@ -693,11 +683,9 @@ public: serializer sr{m}; for(;;) { - stream.nwrite = 0; async_write_some(stream, sr, yield[ec]); if(ec) return; - BEAST_EXPECT(stream.nwrite <= 1); if(sr.is_done()) break; } @@ -707,8 +695,9 @@ public: void testWriteStream(boost::asio::yield_context yield) { - test::pipe p{ios_}; - p.client.write_size(3); + test::stream ts{ios_}; + auto tr = ts.remote(); + ts.write_size(3); response m0; m0.version = 11; @@ -726,20 +715,20 @@ public: { auto m = m0; error_code ec; - do_write(p.client, m, ec); - BEAST_EXPECT(p.server.str() == result); + do_write(ts, m, ec); + BEAST_EXPECT(tr.str() == result); BEAST_EXPECT(equal_body( - p.server.str(), m.body.s)); - p.server.clear(); + tr.str(), m.body.s)); + tr.clear(); } { auto m = m0; error_code ec; - do_async_write(p.client, m, ec, yield); - BEAST_EXPECT(p.server.str() == result); + do_async_write(ts, m, ec, yield); + BEAST_EXPECT(tr.str() == result); BEAST_EXPECT(equal_body( - p.server.str(), m.body.s)); - p.server.clear(); + tr.str(), m.body.s)); + tr.clear(); } { auto m = m0; @@ -748,12 +737,12 @@ public: sr.split(true); for(;;) { - write_some(p.client, sr); + write_some(ts, sr); if(sr.is_header_done()) break; } BEAST_EXPECT(! m.body.read); - p.server.clear(); + tr.clear(); } { auto m = m0; @@ -762,12 +751,12 @@ public: sr.split(true); for(;;) { - async_write_some(p.client, sr, yield); + async_write_some(ts, sr, yield); if(sr.is_header_done()) break; } BEAST_EXPECT(! m.body.read); - p.server.clear(); + tr.clear(); } } { @@ -775,33 +764,18 @@ public: { auto m = m0; error_code ec; - do_write(p.client, m, ec); + do_write(ts, m, ec); BEAST_EXPECT(equal_body( - p.server.str(), m.body.s)); - p.server.clear(); + tr.str(), m.body.s)); + tr.clear(); } { auto m = m0; error_code ec; - do_async_write(p.client, m, ec, yield); + do_async_write(ts, m, ec, yield); BEAST_EXPECT(equal_body( - p.server.str(), m.body.s)); - p.server.clear(); - } - { - auto m = m0; - error_code ec; - test::string_ostream so{get_io_service(), 3}; - response_serializer sr{m}; - sr.split(true); - for(;;) - { - write_some(p.client, sr); - if(sr.is_header_done()) - break; - } - BEAST_EXPECT(! m.body.read); - p.server.clear(); + tr.str(), m.body.s)); + tr.clear(); } { auto m = m0; @@ -810,12 +784,26 @@ public: sr.split(true); for(;;) { - async_write_some(p.client, sr, yield); + write_some(ts, sr); if(sr.is_header_done()) break; } BEAST_EXPECT(! m.body.read); - p.server.clear(); + tr.clear(); + } + { + auto m = m0; + error_code ec; + response_serializer sr{m}; + sr.split(true); + for(;;) + { + async_write_some(ts, sr, yield); + if(sr.is_header_done()) + break; + } + BEAST_EXPECT(! m.body.read); + tr.clear(); } } } @@ -824,12 +812,12 @@ public: testIssue655() { boost::asio::io_service ios; - test::pipe c{ios}; + test::stream ts{ios}; response res; res.chunked(true); response_serializer sr{res}; - async_write_header(c.client, sr, + async_write_header(ts, sr, [&](const error_code&) { }); diff --git a/test/beast/websocket/frame.cpp b/test/beast/websocket/frame.cpp index df20a854..ba808aa5 100644 --- a/test/beast/websocket/frame.cpp +++ b/test/beast/websocket/frame.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/test/beast/websocket/stream.cpp b/test/beast/websocket/stream.cpp index dd6eb1a1..f4229de1 100644 --- a/test/beast/websocket/stream.cpp +++ b/test/beast/websocket/stream.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include diff --git a/test/doc/core_examples.cpp b/test/doc/core_examples.cpp index b56b6be4..7c29285b 100644 --- a/test/doc/core_examples.cpp +++ b/test/doc/core_examples.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -50,24 +50,23 @@ public: testRead() { { - test::pipe p{ios_}; - ostream(p.server.buffer) << - "\x16***"; + test::stream ts(ios_, + "\x16***"); error_code ec; flat_buffer b; - auto const result = detect_ssl(p.server, b, ec); + auto const result = detect_ssl(ts, b, ec); BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(result); } yield_to( [&](yield_context yield) { - test::pipe p{ios_}; - ostream(p.server.buffer) << - "\x16***"; + test::stream ts(ios_, + "\x16***"); error_code ec; flat_buffer b; - auto const result = async_detect_ssl(p.server, b, yield[ec]); + auto const result = + async_detect_ssl(ts, b, yield[ec]); BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(result); }); diff --git a/test/doc/http_examples.cpp b/test/doc/http_examples.cpp index bc2a247d..7f117389 100644 --- a/test/doc/http_examples.cpp +++ b/test/doc/http_examples.cpp @@ -17,9 +17,7 @@ #include #include #include -#include -#include -#include +#include #include #include #include @@ -38,7 +36,7 @@ class examples_test , public beast::test::enable_yield_to { public: - // two threads, for some examples using a pipe + // two threads, for some examples examples_test() : enable_yield_to(2) { @@ -73,13 +71,13 @@ public: bool equal_body(string_view sv, string_view body) { - test::string_istream si{ - get_io_service(), sv.to_string()}; + test::stream ts{ios_, sv}; message m; multi_buffer b; + ts.remote().close(); try { - read(si, b, m); + read(ts, b, m); return m.body == body; } catch(std::exception const& e) @@ -92,14 +90,15 @@ public: void doExpect100Continue() { - test::pipe p{ios_}; + test::stream ts{ios_}; + auto tr = ts.remote(); yield_to( [&](yield_context) { error_code ec; flat_buffer buffer; receive_expect_100_continue( - p.server, buffer, ec); + tr, buffer, ec); BEAST_EXPECTS(! ec, ec.message()); }, [&](yield_context) @@ -115,7 +114,7 @@ public: error_code ec; send_expect_100_continue( - p.client, buffer, req, ec); + ts, buffer, req, ec); BEAST_EXPECTS(! ec, ec.message()); }); } @@ -124,15 +123,14 @@ public: doCgiResponse() { std::string const s = "Hello, world!"; - test::pipe child{ios_}; - child.server.read_size(3); - ostream(child.server.buffer) << s; - child.client.close(); - test::pipe p{ios_}; + test::stream t0{ios_, s}; + t0.read_size(3); + t0.remote().close(); + test::stream t1{ios_}; error_code ec; - send_cgi_response(child.server, p.client, ec); + send_cgi_response(t0, t1, ec); BEAST_EXPECTS(! ec, ec.message()); - BEAST_EXPECT(equal_body(p.server.str(), s)); + BEAST_EXPECT(equal_body(t1.remote().str(), s)); } void @@ -146,18 +144,19 @@ public: req.body = "Hello, world!"; req.prepare_payload(); - test::pipe downstream{ios_}; - downstream.server.read_size(3); - test::pipe upstream{ios_}; - upstream.client.write_size(3); + test::stream ds{ios_}; + auto dsr = ds.remote(); + dsr.read_size(3); + test::stream us{ios_}; + us.write_size(3); error_code ec; - write(downstream.client, req); + write(ds, req); BEAST_EXPECTS(! ec, ec.message()); - downstream.client.close(); + ds.close(); flat_buffer buffer; - relay(upstream.client, downstream.server, buffer, ec, + relay(us, dsr, buffer, ec, [&](header& h, error_code& ev) { ev = {}; @@ -166,7 +165,7 @@ public: }); BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(equal_body( - upstream.server.str(), req.body)); + us.remote().str(), req.body)); } void @@ -240,20 +239,21 @@ public: void doHEAD() { - test::pipe p{ios_}; + test::stream ts{ios_}; + auto tr = ts.remote(); yield_to( [&](yield_context) { error_code ec; flat_buffer buffer; - do_server_head(p.server, buffer, ec); + do_server_head(tr, buffer, ec); BEAST_EXPECTS(! ec, ec.message()); }, [&](yield_context) { error_code ec; flat_buffer buffer; - auto res = do_head_request(p.client, buffer, "/", ec); + auto res = do_head_request(ts, buffer, "/", ec); BEAST_EXPECTS(! ec, ec.message()); }); } @@ -278,18 +278,17 @@ public: void doDeferredBody() { - test::pipe p{ios_}; - ostream(p.server.buffer) << + test::stream ts(ios_, "POST / HTTP/1.1\r\n" "User-Agent: test\r\n" "Content-Type: multipart/form-data\r\n" "Content-Length: 13\r\n" "\r\n" - "Hello, world!"; + "Hello, world!"); handler h; flat_buffer buffer; - do_form_request(p.server, buffer, h); + do_form_request(ts, buffer, h); BEAST_EXPECT(h.body == "Hello, world!"); } @@ -298,9 +297,9 @@ public: void doIncrementalRead() { - test::pipe c{ios_}; + test::stream ts{ios_}; std::string s(2048, '*'); - ostream(c.server.buffer) << + ostream(ts.buffer()) << "HTTP/1.1 200 OK\r\n" "Content-Length: 2048\r\n" "Server: test\r\n" @@ -309,7 +308,7 @@ public: error_code ec; flat_buffer b; std::stringstream ss; - read_and_print_body(ss, c.server, b, ec); + read_and_print_body(ss, ts, b, ec); if(BEAST_EXPECTS(! ec, ec.message())) BEAST_EXPECT(ss.str() == s); } @@ -325,7 +324,7 @@ public: return boost::asio::const_buffers_1{ s.data(), s.size()}; }; - test::pipe p{ios_}; + test::stream ts{ios_}; response res{status::ok, 11}; res.set(field::server, "test"); @@ -334,26 +333,26 @@ public: error_code ec; response_serializer sr{res}; - write_header(p.client, sr, ec); + write_header(ts, sr, ec); chunk_extensions exts; - boost::asio::write(p.client, + boost::asio::write(ts, make_chunk(buf("First")), ec); exts.insert("quality", "1.0"); - boost::asio::write(p.client, + boost::asio::write(ts, make_chunk(buf("Hello, world!"), exts), ec); exts.clear(); exts.insert("file", "abc.txt"); exts.insert("quality", "0.7"); - boost::asio::write(p.client, + boost::asio::write(ts, make_chunk(buf("The Next Chunk"), std::move(exts)), ec); exts.clear(); exts.insert("last"); - boost::asio::write(p.client, + boost::asio::write(ts, make_chunk(buf("Last one"), std::move(exts), std::allocator{}), ec); @@ -361,13 +360,13 @@ public: trailers.set(field::expires, "never"); trailers.set(field::content_md5, "f4a5c16584f03d90"); - boost::asio::write(p.client, + boost::asio::write(ts, make_chunk_last( trailers, std::allocator{} ), ec); BEAST_EXPECT( - to_string(p.server.buffer.data()) == + to_string(ts.remote().buffer().data()) == "HTTP/1.1 200 OK\r\n" "Server: test\r\n" "Accept: Expires, Content-MD5\r\n" @@ -392,8 +391,7 @@ public: void doExplicitChunkParse() { - test::pipe c{ios_}; - ostream(c.client.buffer) << + test::stream ts(ios_, "HTTP/1.1 200 OK\r\n" "Server: test\r\n" "Trailer: Expires, Content-MD5\r\n" @@ -410,13 +408,13 @@ public: "0\r\n" "Expires: never\r\n" "Content-MD5: f4a5c16584f03d90\r\n" - "\r\n"; + "\r\n"); error_code ec; flat_buffer b; std::stringstream ss; - print_chunked_body(ss, c.client, b, ec); + print_chunked_body(ss, ts, b, ec); BEAST_EXPECTS(! ec, ec.message()); BEAST_EXPECT(ss.str() == "Chunk Body: First\n" @@ -429,7 +427,6 @@ public: "Chunk Body: Last one\n" "Expires: never\n" "Content-MD5: f4a5c16584f03d90\n"); - } //-------------------------------------------------------------------------- diff --git a/test/extras/include/boost/beast/test/fail_stream.hpp b/test/extras/include/boost/beast/test/fail_stream.hpp deleted file mode 100644 index 48568781..00000000 --- a/test/extras/include/boost/beast/test/fail_stream.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// Copyright (c) 2016-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) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_TEST_FAIL_STREAM_HPP -#define BOOST_BEAST_TEST_FAIL_STREAM_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { -namespace test { - -/** A stream wrapper that fails. - - On the Nth operation, the stream will fail with the specified - error code, or the default error code of invalid_argument. -*/ -template -class fail_stream -{ - boost::optional fc_; - fail_counter* pfc_; - NextLayer next_layer_; - -public: - using next_layer_type = - typename std::remove_reference::type; - - using lowest_layer_type = - typename get_lowest_layer::type; - - fail_stream(fail_stream&&) = delete; - fail_stream(fail_stream const&) = delete; - fail_stream& operator=(fail_stream&&) = delete; - fail_stream& operator=(fail_stream const&) = delete; - - template - explicit - fail_stream(std::size_t n, Args&&... args) - : fc_(n) - , pfc_(&*fc_) - , next_layer_(std::forward(args)...) - { - } - - template - explicit - fail_stream(fail_counter& fc, Args&&... args) - : pfc_(&fc) - , next_layer_(std::forward(args)...) - { - } - - next_layer_type& - next_layer() - { - return next_layer_; - } - - lowest_layer_type& - lowest_layer() - { - return next_layer_.lowest_layer(); - } - - lowest_layer_type const& - lowest_layer() const - { - return next_layer_.lowest_layer(); - } - - boost::asio::io_service& - get_io_service() - { - return next_layer_.get_io_service(); - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers) - { - pfc_->fail(); - return next_layer_.read_some(buffers); - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers, error_code& ec) - { - if(pfc_->fail(ec)) - return 0; - return next_layer_.read_some(buffers, ec); - } - - template - async_return_type< - ReadHandler, void(error_code, std::size_t)> - async_read_some(MutableBufferSequence const& buffers, - ReadHandler&& handler) - { - error_code ec; - if(pfc_->fail(ec)) - { - async_completion init{handler}; - next_layer_.get_io_service().post( - bind_handler(init.completion_handler, ec, 0)); - return init.result.get(); - } - return next_layer_.async_read_some(buffers, - std::forward(handler)); - } - - template - std::size_t - write_some(ConstBufferSequence const& buffers) - { - pfc_->fail(); - return next_layer_.write_some(buffers); - } - - template - std::size_t - write_some(ConstBufferSequence const& buffers, error_code& ec) - { - if(pfc_->fail(ec)) - return 0; - return next_layer_.write_some(buffers, ec); - } - - template - async_return_type< - WriteHandler, void(error_code, std::size_t)> - async_write_some(ConstBufferSequence const& buffers, - WriteHandler&& handler) - { - error_code ec; - if(pfc_->fail(ec)) - { - async_completion init{handler}; - next_layer_.get_io_service().post( - bind_handler(init.completion_handler, ec, 0)); - return init.result.get(); - } - return next_layer_.async_write_some(buffers, - std::forward(handler)); - } - - friend - void - teardown( - websocket::role_type role, - fail_stream& stream, - boost::system::error_code& ec) - { - if(stream.pfc_->fail(ec)) - return; - using beast::websocket::teardown; - teardown(role, stream.next_layer(), ec); - } - - template - friend - void - async_teardown( - websocket::role_type role, - fail_stream& stream, - TeardownHandler&& handler) - { - error_code ec; - if(stream.pfc_->fail(ec)) - { - stream.get_io_service().post( - bind_handler(std::move(handler), ec)); - return; - } - using beast::websocket::async_teardown; - async_teardown(role, stream.next_layer(), - std::forward(handler)); - } -}; - -} // test -} // beast -} // boost - -#endif diff --git a/test/extras/include/boost/beast/test/pipe_stream.hpp b/test/extras/include/boost/beast/test/pipe_stream.hpp deleted file mode 100644 index 852b2576..00000000 --- a/test/extras/include/boost/beast/test/pipe_stream.hpp +++ /dev/null @@ -1,553 +0,0 @@ -// -// Copyright (c) 2016-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) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_TEST_PIPE_STREAM_HPP -#define BOOST_BEAST_TEST_PIPE_STREAM_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { -namespace test { - -/** A bidirectional in-memory communication channel - - An instance of this class provides a client and server - endpoint that are automatically connected to each other - similarly to a connected socket. - - Test pipes are used to facilitate writing unit tests - where the behavior of the transport is tightly controlled - to help illuminate all code paths (for code coverage) -*/ -class pipe -{ -public: - using buffer_type = flat_buffer; - -private: - struct read_op - { - virtual ~read_op() = default; - virtual void operator()() = 0; - }; - - struct state - { - std::mutex m; - buffer_type b; - std::condition_variable cv; - std::unique_ptr op; - bool eof = false; - }; - - state s_[2]; - -public: - /** Represents an endpoint. - - Each pipe has a client stream and a server stream. - */ - class stream - { - friend class pipe; - - template - class read_op_impl; - - state& in_; - state& out_; - boost::asio::io_service& ios_; - fail_counter* fc_ = nullptr; - std::size_t read_max_ = - (std::numeric_limits::max)(); - std::size_t write_max_ = - (std::numeric_limits::max)(); - - stream(state& in, state& out, - boost::asio::io_service& ios) - : in_(in) - , out_(out) - , ios_(ios) - , buffer(in_.b) - { - } - - public: - using buffer_type = pipe::buffer_type; - - /// Direct access to the underlying buffer - buffer_type& buffer; - - /// Counts the number of read calls - std::size_t nread = 0; - - /// Counts the number of write calls - std::size_t nwrite = 0; - - ~stream() = default; - stream(stream&&) = default; - - /// Set the fail counter on the object -#if 0 - void - fail(fail_counter& fc) - { - fc_ = &fc; - } -#endif - /// Return the `io_service` associated with the object - boost::asio::io_service& - get_io_service() - { - return ios_; - } - - /// Set the maximum number of bytes returned by read_some - void - read_size(std::size_t n) - { - read_max_ = n; - } - - /// Set the maximum number of bytes returned by write_some - void - write_size(std::size_t n) - { - write_max_ = n; - } - - /// Returns a string representing the pending input data - string_view - str() const - { - using boost::asio::buffer_cast; - using boost::asio::buffer_size; - return { - buffer_cast(*in_.b.data().begin()), - buffer_size(*in_.b.data().begin())}; - } - - /// Clear the buffer holding the input data - void - clear() - { - in_.b.consume((std::numeric_limits< - std::size_t>::max)()); - } - - /** Close the stream. - - The other end of the pipe will see - `boost::asio::error::eof` on read. - */ - template - void - close(); - - template - std::size_t - read_some(MutableBufferSequence const& buffers); - - template - std::size_t - read_some(MutableBufferSequence const& buffers, - error_code& ec); - - template - async_return_type< - ReadHandler, void(error_code, std::size_t)> - async_read_some(MutableBufferSequence const& buffers, - ReadHandler&& handler); - - template - std::size_t - write_some(ConstBufferSequence const& buffers); - - template - std::size_t - write_some( - ConstBufferSequence const& buffers, error_code&); - - template - async_return_type< - WriteHandler, void(error_code, std::size_t)> - async_write_some(ConstBufferSequence const& buffers, - WriteHandler&& handler); - - friend - void - teardown( - websocket::role_type role, - stream& s, boost::system::error_code& ec); - - template - friend - void - async_teardown( - websocket::role_type, - stream& s, TeardownHandler&& handler); - }; - - /** Constructor. - - The client and server endpoints will use the same `io_service`. - */ - explicit - pipe(boost::asio::io_service& ios) - : client(s_[0], s_[1], ios) - , server(s_[1], s_[0], ios) - { - } - - /// Represents the client endpoint - stream client; - - /// Represents the server endpoint - stream server; -}; - -//------------------------------------------------------------------------------ - -inline -void -teardown( - websocket::role_type, - pipe::stream& s, - boost::system::error_code& ec) -{ - if(s.fc_) - { - if(s.fc_->fail(ec)) - return; - } - else - { - s.close(); - ec.assign(0, ec.category()); - } -} - -template -inline -void -async_teardown(websocket::role_type, - pipe::stream& s, TeardownHandler&& handler) -{ - error_code ec; - if(s.fc_ && s.fc_->fail(ec)) - return s.get_io_service().post( - bind_handler(std::move(handler), ec)); - s.close(); - s.get_io_service().post( - bind_handler(std::move(handler), ec)); -} - -template -class pipe::stream::read_op_impl : - public pipe::read_op -{ - stream& s_; - Buffers b_; - Handler h_; - -public: - read_op_impl(stream& s, - Buffers const& b, Handler&& h) - : s_(s) - , b_(b) - , h_(std::move(h)) - { - } - - read_op_impl(stream& s, - Buffers const& b, Handler const& h) - : s_(s) - , b_(b) - , h_(h) - { - } - - void - operator()() override; -}; - -//------------------------------------------------------------------------------ - -template -void -pipe::stream:: -read_op_impl::operator()() -{ - using boost::asio::buffer_copy; - using boost::asio::buffer_size; - s_.ios_.post( - [&]() - { - BOOST_ASSERT(s_.in_.op); - std::unique_lock lock{s_.in_.m}; - if(s_.in_.b.size() > 0) - { - auto const bytes_transferred = buffer_copy( - b_, s_.in_.b.data(), s_.read_max_); - s_.in_.b.consume(bytes_transferred); - auto& s = s_; - Handler h{std::move(h_)}; - s.in_.op.reset(nullptr); - lock.unlock(); - ++s.nread; - s.ios_.post(bind_handler(std::move(h), - error_code{}, bytes_transferred)); - } - else - { - BOOST_ASSERT(s_.in_.eof); - auto& s = s_; - Handler h{std::move(h_)}; - s.in_.op.reset(nullptr); - lock.unlock(); - ++s.nread; - s.ios_.post(bind_handler(std::move(h), - boost::asio::error::eof, 0)); - } - }); -} - -//------------------------------------------------------------------------------ - -template -void -pipe::stream:: -close() -{ - std::lock_guard lock{out_.m}; - if(! out_.eof) - { - out_.eof = true; - if(out_.op) - out_.op.get()->operator()(); - else - out_.cv.notify_all(); - } -} - - -template -std::size_t -pipe::stream:: -read_some(MutableBufferSequence const& buffers) -{ - static_assert(is_mutable_buffer_sequence< - MutableBufferSequence>::value, - "MutableBufferSequence requirements not met"); - error_code ec; - auto const n = read_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; -} - -template -std::size_t -pipe::stream:: -read_some(MutableBufferSequence const& buffers, - error_code& ec) -{ - static_assert(is_mutable_buffer_sequence< - MutableBufferSequence>::value, - "MutableBufferSequence requirements not met"); - using boost::asio::buffer_copy; - using boost::asio::buffer_size; - BOOST_ASSERT(! in_.op); - BOOST_ASSERT(buffer_size(buffers) > 0); - if(fc_ && fc_->fail(ec)) - return 0; - std::unique_lock lock{in_.m}; - in_.cv.wait(lock, - [&]() - { - return in_.b.size() > 0 || in_.eof; - }); - std::size_t bytes_transferred; - if(in_.b.size() > 0) - { - ec.assign(0, ec.category()); - bytes_transferred = buffer_copy( - buffers, in_.b.data(), read_max_); - in_.b.consume(bytes_transferred); - } - else - { - BOOST_ASSERT(in_.eof); - bytes_transferred = 0; - ec = boost::asio::error::eof; - } - ++nread; - return bytes_transferred; -} - -template -async_return_type< - ReadHandler, void(error_code, std::size_t)> -pipe::stream:: -async_read_some(MutableBufferSequence const& buffers, - ReadHandler&& handler) -{ - static_assert(is_mutable_buffer_sequence< - MutableBufferSequence>::value, - "MutableBufferSequence requirements not met"); - using boost::asio::buffer_copy; - using boost::asio::buffer_size; - BOOST_ASSERT(! in_.op); - BOOST_ASSERT(buffer_size(buffers) > 0); - async_completion init{handler}; - if(fc_) - { - error_code ec; - if(fc_->fail(ec)) - return ios_.post(bind_handler( - init.completion_handler, ec, 0)); - } - { - std::unique_lock lock{in_.m}; - if(in_.eof) - { - lock.unlock(); - ++nread; - ios_.post(bind_handler(init.completion_handler, - boost::asio::error::eof, 0)); - } - else if(buffer_size(buffers) == 0 || - buffer_size(in_.b.data()) > 0) - { - auto const bytes_transferred = buffer_copy( - buffers, in_.b.data(), read_max_); - in_.b.consume(bytes_transferred); - lock.unlock(); - ++nread; - ios_.post(bind_handler(init.completion_handler, - error_code{}, bytes_transferred)); - } - else - { - in_.op.reset(new read_op_impl, - MutableBufferSequence>{*this, buffers, - init.completion_handler}); - } - } - return init.result.get(); -} - -template -std::size_t -pipe::stream:: -write_some(ConstBufferSequence const& buffers) -{ - static_assert(is_const_buffer_sequence< - ConstBufferSequence>::value, - "ConstBufferSequence requirements not met"); - BOOST_ASSERT(! out_.eof); - error_code ec; - auto const bytes_transferred = - write_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return bytes_transferred; -} - -template -std::size_t -pipe::stream:: -write_some( - ConstBufferSequence const& buffers, error_code& ec) -{ - static_assert(is_const_buffer_sequence< - ConstBufferSequence>::value, - "ConstBufferSequence requirements not met"); - using boost::asio::buffer_copy; - using boost::asio::buffer_size; - BOOST_ASSERT(! out_.eof); - if(fc_ && fc_->fail(ec)) - return 0; - auto const n = (std::min)( - buffer_size(buffers), write_max_); - std::unique_lock lock{out_.m}; - auto const bytes_transferred = - buffer_copy(out_.b.prepare(n), buffers); - out_.b.commit(bytes_transferred); - if(out_.op) - out_.op.get()->operator()(); - else - out_.cv.notify_all(); - lock.unlock(); - ++nwrite; - ec.assign(0, ec.category()); - return bytes_transferred; -} - -template -async_return_type< - WriteHandler, void(error_code, std::size_t)> -pipe::stream:: -async_write_some(ConstBufferSequence const& buffers, - WriteHandler&& handler) -{ - static_assert(is_const_buffer_sequence< - ConstBufferSequence>::value, - "ConstBufferSequence requirements not met"); - using boost::asio::buffer_copy; - using boost::asio::buffer_size; - BOOST_ASSERT(! out_.eof); - async_completion init{handler}; - if(fc_) - { - error_code ec; - if(fc_->fail(ec)) - return ios_.post(bind_handler( - init.completion_handler, ec, 0)); - } - auto const n = - (std::min)(buffer_size(buffers), write_max_); - std::unique_lock lock{out_.m}; - auto const bytes_transferred = - buffer_copy(out_.b.prepare(n), buffers); - out_.b.commit(bytes_transferred); - if(out_.op) - out_.op.get()->operator()(); - else - out_.cv.notify_all(); - lock.unlock(); - ++nwrite; - ios_.post(bind_handler(init.completion_handler, - error_code{}, bytes_transferred)); - return init.result.get(); -} - -} // test -} // beast -} // boost - -#endif diff --git a/test/extras/include/boost/beast/test/stream.hpp b/test/extras/include/boost/beast/test/stream.hpp index 7a1ac333..29db1d6d 100644 --- a/test/extras/include/boost/beast/test/stream.hpp +++ b/test/extras/include/boost/beast/test/stream.hpp @@ -239,38 +239,40 @@ class stream using status = detail::stream_impl::status; std::shared_ptr impl_; - detail::stream_impl::state& in_; - detail::stream_impl::state& out_; + detail::stream_impl::state* in_; + detail::stream_impl::state* out_; explicit stream(std::shared_ptr< detail::stream_impl> const& impl) : impl_(impl) - , in_(impl_->s1_) - , out_(impl_->s0_) + , in_(&impl_->s1_) + , out_(&impl_->s0_) { } public: using buffer_type = flat_buffer; - stream& operator=(stream const&) = delete; + /// Assignment + stream& operator=(stream&&) = default; /// Destructor ~stream() { if(! impl_) return; - BOOST_ASSERT(! in_.op); - std::unique_lock lock{out_.m}; - if(out_.code == status::ok) + BOOST_ASSERT(! in_->op); + std::unique_lock lock{out_->m}; + if(out_->code == status::ok) { - out_.code = status::reset; - out_.on_write(); + out_->code = status::reset; + out_->on_write(); } lock.unlock(); } + /// Constructor stream(stream&& other) : impl_(std::move(other.impl_)) , in_(other.in_) @@ -284,8 +286,8 @@ public: boost::asio::io_service& ios) : impl_(std::make_shared< detail::stream_impl>(ios, nullptr)) - , in_(impl_->s0_) - , out_(impl_->s1_) + , in_(&impl_->s0_) + , out_(&impl_->s1_) { } @@ -296,8 +298,8 @@ public: boost::asio::io_service& ios1) : impl_(std::make_shared< detail::stream_impl>(ios0, ios1)) - , in_(impl_->s0_) - , out_(impl_->s1_) + , in_(&impl_->s0_) + , out_(&impl_->s1_) { } @@ -308,8 +310,8 @@ public: fail_counter& fc) : impl_(std::make_shared< detail::stream_impl>(ios, &fc)) - , in_(impl_->s0_) - , out_(impl_->s1_) + , in_(&impl_->s0_) + , out_(&impl_->s1_) { } @@ -319,13 +321,13 @@ public: string_view s) : impl_(std::make_shared< detail::stream_impl>(ios, nullptr)) - , in_(impl_->s0_) - , out_(impl_->s1_) + , in_(&impl_->s0_) + , out_(&impl_->s1_) { using boost::asio::buffer; using boost::asio::buffer_copy; - in_.b.commit(buffer_copy( - in_.b.prepare(s.size()), + in_->b.commit(buffer_copy( + in_->b.prepare(s.size()), buffer(s.data(), s.size()))); } @@ -336,13 +338,13 @@ public: string_view s) : impl_(std::make_shared< detail::stream_impl>(ios, &fc)) - , in_(impl_->s0_) - , out_(impl_->s1_) + , in_(&impl_->s0_) + , out_(&impl_->s1_) { using boost::asio::buffer; using boost::asio::buffer_copy; - in_.b.commit(buffer_copy( - in_.b.prepare(s.size()), + in_->b.commit(buffer_copy( + in_->b.prepare(s.size()), buffer(s.data(), s.size()))); } @@ -350,7 +352,7 @@ public: stream remote() { - BOOST_ASSERT(&in_ == &impl_->s0_); + BOOST_ASSERT(in_ == &impl_->s0_); return stream{impl_}; } @@ -358,28 +360,28 @@ public: boost::asio::io_service& get_io_service() { - return in_.ios; + return in_->ios; } /// Set the maximum number of bytes returned by read_some void read_size(std::size_t n) { - in_.read_max = n; + in_->read_max = n; } /// Set the maximum number of bytes returned by write_some void write_size(std::size_t n) { - out_.write_max = n; + out_->write_max = n; } /// Direct input buffer access buffer_type& buffer() { - return in_.b; + return in_->b; } /// Returns a string view representing the pending input data @@ -389,8 +391,8 @@ public: using boost::asio::buffer_cast; using boost::asio::buffer_size; return { - buffer_cast(*in_.b.data().begin()), - buffer_size(*in_.b.data().begin())}; + buffer_cast(*in_->b.data().begin()), + buffer_size(*in_->b.data().begin())}; } /// Appends a string to the pending input data @@ -399,24 +401,32 @@ public: { using boost::asio::buffer; using boost::asio::buffer_copy; - std::unique_lock lock{in_.m}; - in_.b.commit(buffer_copy( - in_.b.prepare(s.size()), + std::lock_guard lock{in_->m}; + in_->b.commit(buffer_copy( + in_->b.prepare(s.size()), buffer(s.data(), s.size()))); } + /// Clear the pending input area + void + clear() + { + std::lock_guard lock{in_->m}; + in_->b.consume(in_->b.size()); + } + /// Return the number of reads std::size_t nread() const { - return in_.nread; + return in_->nread; } /// Return the number of writes std::size_t nwrite() const { - return out_.nwrite; + return out_->nwrite; } /** Close the stream. @@ -499,35 +509,35 @@ read_some(MutableBufferSequence const& buffers, using boost::asio::buffer_copy; using boost::asio::buffer_size; BOOST_ASSERT(buffer_size(buffers) > 0); - if(in_.fc && in_.fc->fail(ec)) + if(in_->fc && in_->fc->fail(ec)) return 0; - std::unique_lock lock{in_.m}; - BOOST_ASSERT(! in_.op); - in_.cv.wait(lock, + std::unique_lock lock{in_->m}; + BOOST_ASSERT(! in_->op); + in_->cv.wait(lock, [&]() { return - in_.b.size() > 0 || - in_.code != status::ok; + in_->b.size() > 0 || + in_->code != status::ok; }); std::size_t bytes_transferred; - if(in_.b.size() > 0) + if(in_->b.size() > 0) { ec.assign(0, ec.category()); bytes_transferred = buffer_copy( - buffers, in_.b.data(), in_.read_max); - in_.b.consume(bytes_transferred); + buffers, in_->b.data(), in_->read_max); + in_->b.consume(bytes_transferred); } else { - BOOST_ASSERT(in_.code != status::ok); + BOOST_ASSERT(in_->code != status::ok); bytes_transferred = 0; - if(in_.code == status::eof) + if(in_->code == status::eof) ec = boost::asio::error::eof; - else if(in_.code == status::reset) + else if(in_->code == status::reset) ec = boost::asio::error::connection_reset; } - ++in_.nread; + ++in_->nread; return bytes_transferred; } @@ -547,45 +557,45 @@ async_read_some( BOOST_ASSERT(buffer_size(buffers) > 0); async_completion init{handler}; - if(in_.fc) + if(in_->fc) { error_code ec; - if(in_.fc->fail(ec)) - return in_.ios.post(bind_handler( + if(in_->fc->fail(ec)) + return in_->ios.post(bind_handler( init.completion_handler, ec, 0)); } { - std::unique_lock lock{in_.m}; - BOOST_ASSERT(! in_.op); + std::unique_lock lock{in_->m}; + BOOST_ASSERT(! in_->op); if(buffer_size(buffers) == 0 || - buffer_size(in_.b.data()) > 0) + buffer_size(in_->b.data()) > 0) { auto const bytes_transferred = buffer_copy( - buffers, in_.b.data(), in_.read_max); - in_.b.consume(bytes_transferred); + buffers, in_->b.data(), in_->read_max); + in_->b.consume(bytes_transferred); lock.unlock(); - ++in_.nread; - in_.ios.post(bind_handler(init.completion_handler, + ++in_->nread; + in_->ios.post(bind_handler(init.completion_handler, error_code{}, bytes_transferred)); } - else if(in_.code != status::ok) + else if(in_->code != status::ok) { lock.unlock(); - ++in_.nread; + ++in_->nread; error_code ec; - if(in_.code == status::eof) + if(in_->code == status::eof) ec = boost::asio::error::eof; - else if(in_.code == status::reset) + else if(in_->code == status::reset) ec = boost::asio::error::connection_reset; - in_.ios.post(bind_handler( + in_->ios.post(bind_handler( init.completion_handler, ec, 0)); } else { - in_.op.reset(new + in_->op.reset(new detail::stream_impl::read_op_impl, - MutableBufferSequence>{in_, buffers, + MutableBufferSequence>{*in_, buffers, init.completion_handler}); } } @@ -600,7 +610,7 @@ write_some(ConstBufferSequence const& buffers) static_assert(is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - BOOST_ASSERT(out_.code == status::ok); + BOOST_ASSERT(out_->code == status::ok); error_code ec; auto const bytes_transferred = write_some(buffers, ec); @@ -620,18 +630,18 @@ write_some( "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; using boost::asio::buffer_size; - BOOST_ASSERT(out_.code == status::ok); - if(in_.fc && in_.fc->fail(ec)) + BOOST_ASSERT(out_->code == status::ok); + if(in_->fc && in_->fc->fail(ec)) return 0; auto const n = (std::min)( - buffer_size(buffers), out_.write_max); - std::unique_lock lock{out_.m}; + buffer_size(buffers), out_->write_max); + std::unique_lock lock{out_->m}; auto const bytes_transferred = - buffer_copy(out_.b.prepare(n), buffers); - out_.b.commit(bytes_transferred); - out_.on_write(); + buffer_copy(out_->b.prepare(n), buffers); + out_->b.commit(bytes_transferred); + out_->on_write(); lock.unlock(); - ++out_.nwrite; + ++out_->nwrite; ec.assign(0, ec.category()); return bytes_transferred; } @@ -648,26 +658,26 @@ async_write_some(ConstBufferSequence const& buffers, "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; using boost::asio::buffer_size; - BOOST_ASSERT(out_.code == status::ok); + BOOST_ASSERT(out_->code == status::ok); async_completion init{handler}; - if(in_.fc) + if(in_->fc) { error_code ec; - if(in_.fc->fail(ec)) - return in_.ios.post(bind_handler( + if(in_->fc->fail(ec)) + return in_->ios.post(bind_handler( init.completion_handler, ec, 0)); } auto const n = - (std::min)(buffer_size(buffers), out_.write_max); - std::unique_lock lock{out_.m}; + (std::min)(buffer_size(buffers), out_->write_max); + std::unique_lock lock{out_->m}; auto const bytes_transferred = - buffer_copy(out_.b.prepare(n), buffers); - out_.b.commit(bytes_transferred); - out_.on_write(); + buffer_copy(out_->b.prepare(n), buffers); + out_->b.commit(bytes_transferred); + out_->on_write(); lock.unlock(); - ++out_.nwrite; - in_.ios.post(bind_handler(init.completion_handler, + ++out_->nwrite; + in_->ios.post(bind_handler(init.completion_handler, error_code{}, bytes_transferred)); return init.result.get(); } @@ -677,9 +687,9 @@ void teardown(websocket::role_type, stream& s, boost::system::error_code& ec) { - if(s.in_.fc) + if(s.in_->fc) { - if(s.in_.fc->fail(ec)) + if(s.in_->fc->fail(ec)) return; } else @@ -696,7 +706,7 @@ async_teardown(websocket::role_type, stream& s, TeardownHandler&& handler) { error_code ec; - if(s.in_.fc && s.in_.fc->fail(ec)) + if(s.in_->fc && s.in_->fc->fail(ec)) return s.get_io_service().post( bind_handler(std::move(handler), ec)); s.close(); @@ -709,12 +719,12 @@ void stream:: close() { - BOOST_ASSERT(! in_.op); - std::lock_guard lock{out_.m}; - if(out_.code == status::ok) + BOOST_ASSERT(! in_->op); + std::lock_guard lock{out_->m}; + if(out_->code == status::ok) { - out_.code = status::eof; - out_.on_write(); + out_->code = status::eof; + out_->on_write(); } } diff --git a/test/extras/include/boost/beast/test/string_iostream.hpp b/test/extras/include/boost/beast/test/string_iostream.hpp deleted file mode 100644 index 6d9454ae..00000000 --- a/test/extras/include/boost/beast/test/string_iostream.hpp +++ /dev/null @@ -1,177 +0,0 @@ -// -// Copyright (c) 2016-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) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_TEST_STRING_IOSTREAM_HPP -#define BOOST_BEAST_TEST_STRING_IOSTREAM_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { -namespace test { - -/** A SyncStream and AsyncStream that reads from a string and writes to another string. - - This class behaves like a socket, except that written data is - appended to a string exposed as a public data member, and when - data is read it comes from a string provided at construction. -*/ -class string_iostream -{ - std::string s_; - boost::asio::const_buffer cb_; - boost::asio::io_service& ios_; - std::size_t read_max_; - -public: - std::string str; - - string_iostream(boost::asio::io_service& ios, - std::string s, std::size_t read_max = - (std::numeric_limits::max)()) - : s_(std::move(s)) - , cb_(boost::asio::buffer(s_)) - , ios_(ios) - , read_max_(read_max) - { - } - - boost::asio::io_service& - get_io_service() - { - return ios_; - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers) - { - error_code ec; - auto const n = read_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers, - error_code& ec) - { - auto const n = boost::asio::buffer_copy( - buffers, buffer_prefix(read_max_, cb_)); - if(n > 0) - { - ec.assign(0, ec.category()); - cb_ = cb_ + n; - } - else - { - ec = boost::asio::error::eof; - } - return n; - } - - template - async_return_type< - ReadHandler, void(error_code, std::size_t)> - async_read_some(MutableBufferSequence const& buffers, - ReadHandler&& handler) - { - auto const n = boost::asio::buffer_copy( - buffers, boost::asio::buffer(s_)); - error_code ec; - if(n > 0) - s_.erase(0, n); - else - ec = boost::asio::error::eof; - async_completion init{handler}; - ios_.post(bind_handler( - init.completion_handler, ec, n)); - return init.result.get(); - } - - template - std::size_t - write_some(ConstBufferSequence const& buffers) - { - error_code ec; - auto const n = write_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; - } - - template - std::size_t - write_some( - ConstBufferSequence const& buffers, error_code& ec) - { - ec.assign(0, ec.category()); - using boost::asio::buffer_size; - using boost::asio::buffer_cast; - auto const n = buffer_size(buffers); - str.reserve(str.size() + n); - for(boost::asio::const_buffer buffer : buffers) - str.append(buffer_cast(buffer), - buffer_size(buffer)); - return n; - } - - template - async_return_type< - WriteHandler, void(error_code, std::size_t)> - async_write_some(ConstBufferSequence const& buffers, - WriteHandler&& handler) - { - error_code ec; - auto const bytes_transferred = write_some(buffers, ec); - async_completion init{handler}; - get_io_service().post( - bind_handler(init.completion_handler, ec, bytes_transferred)); - return init.result.get(); - } - - friend - void - teardown(websocket::role_type, - string_iostream&, - boost::system::error_code& ec) - { - ec.assign(0, ec.category()); - } - - template - friend - void - async_teardown(websocket::role_type, - string_iostream& stream, - TeardownHandler&& handler) - { - stream.get_io_service().post( - bind_handler(std::move(handler), - error_code{})); - } -}; - -} // test -} // beast -} // boost - -#endif diff --git a/test/extras/include/boost/beast/test/string_istream.hpp b/test/extras/include/boost/beast/test/string_istream.hpp deleted file mode 100644 index b11a91e8..00000000 --- a/test/extras/include/boost/beast/test/string_istream.hpp +++ /dev/null @@ -1,165 +0,0 @@ -// -// Copyright (c) 2016-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) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_TEST_STRING_ISTREAM_HPP -#define BOOST_BEAST_TEST_STRING_ISTREAM_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { -namespace test { - -/** A SyncStream and AsyncStream that reads from a string. - - This class behaves like a socket, except that written data is simply - discarded, and when data is read it comes from a string provided - at construction. -*/ -class string_istream -{ - std::string s_; - boost::asio::const_buffer cb_; - boost::asio::io_service& ios_; - std::size_t read_max_; - -public: - string_istream(boost::asio::io_service& ios, - std::string s, std::size_t read_max = - (std::numeric_limits::max)()) - : s_(std::move(s)) - , cb_(boost::asio::buffer(s_)) - , ios_(ios) - , read_max_(read_max) - { - } - - boost::asio::io_service& - get_io_service() - { - return ios_; - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers) - { - error_code ec; - auto const n = read_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers, - error_code& ec) - { - auto const n = boost::asio::buffer_copy( - buffers, cb_, read_max_); - if(n > 0) - { - ec.assign(0, ec.category()); - cb_ = cb_ + n; - } - else - { - ec = boost::asio::error::eof; - } - return n; - } - - template - async_return_type< - ReadHandler, void(error_code, std::size_t)> - async_read_some(MutableBufferSequence const& buffers, - ReadHandler&& handler) - { - auto const n = boost::asio::buffer_copy( - buffers, boost::asio::buffer(s_)); - error_code ec; - if(n > 0) - s_.erase(0, n); - else - ec = boost::asio::error::eof; - async_completion init{handler}; - ios_.post(bind_handler( - init.completion_handler, ec, n)); - return init.result.get(); - } - - template - std::size_t - write_some(ConstBufferSequence const& buffers) - { - error_code ec; - auto const n = write_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; - } - - template - std::size_t - write_some(ConstBufferSequence const& buffers, - error_code& ec) - { - ec.assign(0, ec.category()); - return boost::asio::buffer_size(buffers); - } - - template - async_return_type< - WriteHandler, void(error_code, std::size_t)> - async_write_some(ConstBuffeSequence const& buffers, - WriteHandler&& handler) - { - async_completion init{handler}; - ios_.post(bind_handler(init.completion_handler, - error_code{}, boost::asio::buffer_size(buffers))); - return init.result.get(); - } - - friend - void - teardown(websocket::role_type, - string_istream&, - boost::system::error_code& ec) - { - ec.assign(0, ec.category()); - } - - template - friend - void - async_teardown(websocket::role_type, - string_istream& stream, - TeardownHandler&& handler) - { - stream.get_io_service().post( - bind_handler(std::move(handler), - error_code{})); - } -}; - -} // test -} // beast -} // boost - -#endif diff --git a/test/extras/include/boost/beast/test/string_ostream.hpp b/test/extras/include/boost/beast/test/string_ostream.hpp deleted file mode 100644 index 182bc0ed..00000000 --- a/test/extras/include/boost/beast/test/string_ostream.hpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// Copyright (c) 2016-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) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_TEST_STRING_OSTREAM_HPP -#define BOOST_BEAST_TEST_STRING_OSTREAM_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace beast { -namespace test { - -class string_ostream -{ - boost::asio::io_service& ios_; - std::size_t write_max_; - -public: - std::string str; - - explicit - string_ostream(boost::asio::io_service& ios, - std::size_t write_max = - (std::numeric_limits::max)()) - : ios_(ios) - , write_max_(write_max) - { - } - - boost::asio::io_service& - get_io_service() - { - return ios_; - } - - template - std::size_t - read_some(MutableBufferSequence const& buffers) - { - error_code ec; - auto const n = read_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; - } - - template - std::size_t - read_some(MutableBufferSequence const&, - error_code& ec) - { - ec = boost::asio::error::eof; - return 0; - } - - template - async_return_type< - ReadHandler, void(error_code, std::size_t)> - async_read_some(MutableBufferSequence const&, - ReadHandler&& handler) - { - async_completion init{handler}; - ios_.post(bind_handler(init.completion_handler, - boost::asio::error::eof, 0)); - return init.result.get(); - } - - template - std::size_t - write_some(ConstBufferSequence const& buffers) - { - error_code ec; - auto const n = write_some(buffers, ec); - if(ec) - BOOST_THROW_EXCEPTION(system_error{ec}); - return n; - } - - template - std::size_t - write_some( - ConstBufferSequence const& buffers, error_code& ec) - { - ec.assign(0, ec.category()); - using boost::asio::buffer_size; - using boost::asio::buffer_cast; - auto const n = - (std::min)(buffer_size(buffers), write_max_); - str.reserve(str.size() + n); - for(boost::asio::const_buffer buffer : - buffer_prefix(n, buffers)) - str.append(buffer_cast(buffer), - buffer_size(buffer)); - return n; - } - - template - async_return_type< - WriteHandler, void(error_code, std::size_t)> - async_write_some(ConstBufferSequence const& buffers, - WriteHandler&& handler) - { - error_code ec; - auto const bytes_transferred = write_some(buffers, ec); - async_completion init{handler}; - get_io_service().post( - bind_handler(init.completion_handler, ec, bytes_transferred)); - return init.result.get(); - } - - friend - void - teardown(websocket::role_type, - string_ostream&, - boost::system::error_code& ec) - { - ec.assign(0, ec.category()); - } - - template - friend - void - async_teardown(websocket::role_type, - string_ostream& stream, - TeardownHandler&& handler) - { - stream.get_io_service().post( - bind_handler(std::move(handler), - error_code{})); - } -}; - -} // test -} // beast -} // boost - -#endif