From 36027ba8447bdd1c56905f7b73a57efe0667e738 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 31 Mar 2017 10:12:58 -0400 Subject: [PATCH] Add io_service completion invariants tests fix #290 --- CHANGELOG.md | 6 +++++ test/http/read.cpp | 53 +++++++++++++++++++++++++++++++++++++++++- test/http/write.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c88de139..f478e850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +1.0.0-b32 + +* Add io_service completion invariants test + +-------------------------------------------------------------------------------- + 1.0.0-b31 * Tidy up build settings diff --git a/test/http/read.cpp b/test/http/read.cpp index bd4cde26..54356d4f 100644 --- a/test/http/read.cpp +++ b/test/http/read.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace beast { namespace http { @@ -374,6 +375,55 @@ public: } } + // Ensure completion handlers are not leaked + struct handler + { + static std::atomic& + count() { static std::atomic n; return n; } + handler() { ++count(); } + ~handler() { --count(); } + handler(handler const&) { ++count(); } + void operator()(error_code const&) const {} + }; + + void + testIoService() + { + { + // Make sure handlers are not destroyed + // after calling io_service::stop + boost::asio::io_service ios; + test::string_istream is{ios, + "GET / HTTP/1.1\r\n\r\n"}; + BEAST_EXPECT(handler::count() == 0); + streambuf sb; + message m; + async_read(is, sb, m, handler{}); + BEAST_EXPECT(handler::count() > 0); + ios.stop(); + BEAST_EXPECT(handler::count() > 0); + ios.reset(); + BEAST_EXPECT(handler::count() > 0); + ios.run_one(); + BEAST_EXPECT(handler::count() == 0); + } + { + // Make sure uninvoked handlers are + // destroyed when calling ~io_service + { + boost::asio::io_service ios; + test::string_istream is{ios, + "GET / HTTP/1.1\r\n\r\n"}; + BEAST_EXPECT(handler::count() == 0); + streambuf sb; + message m; + async_read(is, sb, m, handler{}); + BEAST_EXPECT(handler::count() > 0); + } + BEAST_EXPECT(handler::count() == 0); + } + } + void run() override { testThrow(); @@ -382,6 +432,8 @@ public: yield_to(&read_test::testReadHeaders, this); yield_to(&read_test::testRead, this); yield_to(&read_test::testEof, this); + + testIoService(); } }; @@ -389,4 +441,3 @@ BEAST_DEFINE_TESTSUITE(read,http,beast); } // http } // beast - diff --git a/test/http/write.cpp b/test/http/write.cpp index 10eeb92c..6aa84d3d 100644 --- a/test/http/write.cpp +++ b/test/http/write.cpp @@ -639,6 +639,61 @@ public: } } + // Ensure completion handlers are not leaked + struct handler + { + static std::atomic& + count() { static std::atomic n; return n; } + handler() { ++count(); } + ~handler() { --count(); } + handler(handler const&) { ++count(); } + void operator()(error_code const&) const {} + }; + + void + testIoService() + { + { + // Make sure handlers are not destroyed + // after calling io_service::stop + boost::asio::io_service ios; + test::string_ostream os{ios}; + BEAST_EXPECT(handler::count() == 0); + message m; + m.method = "GET"; + m.version = 11; + m.url = "/"; + m.fields["Content-Length"] = "5"; + m.body = "*****"; + async_write(os, m, handler{}); + BEAST_EXPECT(handler::count() > 0); + ios.stop(); + BEAST_EXPECT(handler::count() > 0); + ios.reset(); + BEAST_EXPECT(handler::count() > 0); + ios.run_one(); + BEAST_EXPECT(handler::count() == 0); + } + { + // Make sure uninvoked handlers are + // destroyed when calling ~io_service + { + boost::asio::io_service ios; + test::string_ostream is{ios}; + BEAST_EXPECT(handler::count() == 0); + message m; + m.method = "GET"; + m.version = 11; + m.url = "/"; + m.fields["Content-Length"] = "5"; + m.body = "*****"; + async_write(is, m, handler{}); + BEAST_EXPECT(handler::count() > 0); + } + BEAST_EXPECT(handler::count() == 0); + } + } + void run() override { yield_to(&write_test::testAsyncWriteHeaders, this); @@ -647,6 +702,7 @@ public: testOutput(); test_std_ostream(); testOstream(); + testIoService(); } };