mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 13:27:33 +02:00
@ -1,3 +1,9 @@
|
|||||||
|
1.0.0-b32
|
||||||
|
|
||||||
|
* Add io_service completion invariants test
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
1.0.0-b31
|
1.0.0-b31
|
||||||
|
|
||||||
* Tidy up build settings
|
* Tidy up build settings
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <beast/test/yield_to.hpp>
|
#include <beast/test/yield_to.hpp>
|
||||||
#include <beast/unit_test/suite.hpp>
|
#include <beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
@ -374,6 +375,55 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure completion handlers are not leaked
|
||||||
|
struct handler
|
||||||
|
{
|
||||||
|
static std::atomic<std::size_t>&
|
||||||
|
count() { static std::atomic<std::size_t> 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<true, streambuf_body, fields> 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<true, streambuf_body, fields> m;
|
||||||
|
async_read(is, sb, m, handler{});
|
||||||
|
BEAST_EXPECT(handler::count() > 0);
|
||||||
|
}
|
||||||
|
BEAST_EXPECT(handler::count() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
testThrow();
|
testThrow();
|
||||||
@ -382,6 +432,8 @@ public:
|
|||||||
yield_to(&read_test::testReadHeaders, this);
|
yield_to(&read_test::testReadHeaders, this);
|
||||||
yield_to(&read_test::testRead, this);
|
yield_to(&read_test::testRead, this);
|
||||||
yield_to(&read_test::testEof, this);
|
yield_to(&read_test::testEof, this);
|
||||||
|
|
||||||
|
testIoService();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -389,4 +441,3 @@ BEAST_DEFINE_TESTSUITE(read,http,beast);
|
|||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
@ -639,6 +639,61 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure completion handlers are not leaked
|
||||||
|
struct handler
|
||||||
|
{
|
||||||
|
static std::atomic<std::size_t>&
|
||||||
|
count() { static std::atomic<std::size_t> 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<true, string_body, fields> 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<true, string_body, fields> 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
|
void run() override
|
||||||
{
|
{
|
||||||
yield_to(&write_test::testAsyncWriteHeaders, this);
|
yield_to(&write_test::testAsyncWriteHeaders, this);
|
||||||
@ -647,6 +702,7 @@ public:
|
|||||||
testOutput();
|
testOutput();
|
||||||
test_std_ostream();
|
test_std_ostream();
|
||||||
testOstream();
|
testOstream();
|
||||||
|
testIoService();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user