Add BEAST_EXPECTS test failure macro:

New overloads of suite::expect take the file and line number
as individual parameters, cleaning up the file name output
by showing only the filename part (to not leak the full path,
which might contain sensitive information).

A new macro BEAST_EXPECTS allows an additional reason
string as well as reporting the file and line. Typical usage:

    ```
    error_code ec;
    ...
    if(! BEAST_EXPECTS(! ec, ec.message()))
        return;
    ```
This commit is contained in:
Vinnie Falco
2016-08-29 13:28:08 -04:00
parent f144619e7c
commit 28cabc5e28
6 changed files with 202 additions and 141 deletions

View File

@ -1,5 +1,6 @@
1.0.0-b12
* 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

View File

@ -9,6 +9,7 @@
#define BEAST_UNIT_TEST_SUITE_HPP
#include <beast/unit_test/runner.hpp>
#include <boost/filesystem.hpp>
#include <ostream>
#include <sstream>
#include <string>
@ -170,66 +171,93 @@ public:
void
operator()(runner& r);
/** Record a successful test condition. */
template<class = void>
void
pass();
/** Record a failure.
@param reason
*/
template<class = void>
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<class Condition, class String>
bool
expect(Condition const& shouldBeTrue,
String const& reason);
/** @{ */
template<class Condition>
bool
expect(Condition const& shouldBeTrue)
{
return expect(shouldBeTrue, "");
return expect(shouldBeTrue, {});
}
/** Expect an exception from f() */
/** @{ */
template<class Condition>
bool
expect(Condition const& shouldBeTrue, std::string const& reason);
template<class Condition>
bool
expect(Condition const& shouldBeTrue,
char const* file, int line)
{
return expect(shouldBeTrue, {}, file, line);
}
template<class Condition>
bool
expect(Condition const& shouldBeTrue,
std::string const& reason, char const* file, int line);
/** @} */
//
// DEPRECATED
//
// Expect an exception from f()
template<class F, class String>
bool
except(F&& f, String const& reason);
template<class F>
bool
except(F&& f)
{
return except(f, "");
}
/** @} */
/** Expect an exception of the given type from f() */
/** @{ */
template<class E, class F, class String>
bool
except(F&& f, String const& reason);
template<class E, class F>
bool
except(F&& f)
{
return except<E>(f, "");
}
/** @} */
/** Fail if f() throws */
/** @{ */
template<class F, class String>
bool
unexcept(F&& f, String const& reason);
template<class F>
bool
unexcept(F&& f)
{
return unexcept(f, "");
}
/** @} */
/** Return the argument associated with the runner. */
std::string const&
@ -252,16 +280,6 @@ public:
return unexpected(shouldBeFalse, "");
}
/** Record a successful test condition. */
template<class = void>
void
pass();
/** Record a failure. */
template<class = void>
void
fail(std::string const& reason = "");
private:
friend class thread;
@ -368,7 +386,8 @@ suite::testcase_t::operator<<(T const& t)
template<class>
void
suite::operator()(runner& r)
suite::
operator()(runner& r)
{
*p_this_suite() = this;
try
@ -383,11 +402,11 @@ suite::operator()(runner& r)
}
}
template<class Condition, class String>
inline
template<class Condition>
bool
suite::expect(Condition const& shouldBeTrue,
String const& reason)
suite::
expect(
Condition const& shouldBeTrue, std::string const& reason)
{
if(shouldBeTrue)
{
@ -398,9 +417,35 @@ suite::expect(Condition const& shouldBeTrue,
return false;
}
template<class Condition>
bool
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<class F, class String>
bool
suite::except(F&& f, String const& reason)
suite::
except(F&& f, String const& reason)
{
try
{
@ -417,7 +462,8 @@ suite::except(F&& f, String const& reason)
template<class E, class F, class String>
bool
suite::except(F&& f, String const& reason)
suite::
except(F&& f, String const& reason)
{
try
{
@ -434,7 +480,8 @@ suite::except(F&& f, String const& reason)
template<class F, class String>
bool
suite::unexcept(F&& f, String const& reason)
suite::
unexcept(F&& f, String const& reason)
{
try
{
@ -450,10 +497,10 @@ suite::unexcept(F&& f, String const& reason)
}
template<class Condition, class String>
inline
bool
suite::unexpected(Condition shouldBeFalse,
String const& reason)
suite::
unexpected(
Condition shouldBeFalse, String const& reason)
{
bool const b =
static_cast<bool>(shouldBeFalse);
@ -466,15 +513,18 @@ suite::unexpected(Condition shouldBeFalse,
template<class>
void
suite::pass()
suite::
pass()
{
propagate_abort();
runner_->pass();
}
// ::fail
template<class>
void
suite::fail(std::string const& reason)
suite::
fail(std::string const& reason)
{
propagate_abort();
runner_->fail(reason);
@ -487,7 +537,8 @@ suite::fail(std::string const& reason)
inline
void
suite::propagate_abort()
suite::
propagate_abort()
{
if(abort_ && aborted_)
throw abort_exception();
@ -495,7 +546,8 @@ suite::propagate_abort()
template<class>
void
suite::run(runner& r)
suite::
run(runner& r)
{
runner_ = &r;
@ -520,10 +572,18 @@ suite::run(runner& r)
#ifndef BEAST_EXPECT
/** Check a precondition.
If the condition is false, the file and line number are reported.
*/
#define BEAST_EXPECT_S1(x) #x
#define BEAST_EXPECT_S2(x) BEAST_EXPECT_S1(x)
#define BEAST_EXPECT(cond) expect(cond, __FILE__ ":" BEAST_EXPECT_S2(__LINE__))
#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

View File

@ -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;
}
}

View File

@ -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");

View File

@ -241,7 +241,7 @@ public:
error_code ec;
string_write_stream ss(ios_);
async_write(ss, m, do_yield[ec]);
if(expect(! ec, ec.message()))
if(BEAST_EXPECTS(! ec, ec.message()))
BEAST_EXPECT(ss.str ==
"HTTP/1.0 200 OK\r\n"
"Server: test\r\n"
@ -260,7 +260,7 @@ public:
error_code ec;
string_write_stream ss(ios_);
async_write(ss, m, do_yield[ec]);
if(expect(! ec, ec.message()))
if(BEAST_EXPECTS(! ec, ec.message()))
BEAST_EXPECT(ss.str ==
"HTTP/1.1 200 OK\r\n"
"Server: test\r\n"

View File

@ -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<socket_type&> 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 db;
ws.read(op, db, ec);
if(! expect(! ec, ec.message()))
if(! BEAST_EXPECTS(! ec, ec.message()))
break;
expect(to_string(db.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<socket_type&> 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 db;
ws.async_read(op, db, do_yield[ec]);
if(! expect(! ec, ec.message()))
if(! BEAST_EXPECTS(! ec, ec.message()))
break;
expect(to_string(db.data()) ==
std::string{v.data(), v.size()});
BEAST_EXPECT(to_string(db.data()) ==
std::string(v.data(), v.size()));
v.push_back(n+1);
}
}
@ -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
@ -609,14 +609,14 @@ public:
{
// 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, 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();
}
@ -677,19 +677,19 @@ public:
{
// 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();
}
@ -740,7 +740,7 @@ public:
[&](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,11 +777,11 @@ 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;
@ -789,9 +789,9 @@ public:
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;
}
@ -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", "/");
@ -848,8 +848,8 @@ public:
opcode op;
streambuf db;
read(ws, op, db);
expect(op == opcode::text);
expect(to_string(db.data()) == "Hello");
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));
@ -884,9 +884,9 @@ public:
opcode op;
streambuf db;
ws.read(op, db);
expect(pong == 1);
expect(op == opcode::binary);
expect(to_string(db.data()) == "Hello");
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, "));
@ -905,8 +905,8 @@ public:
opcode op;
streambuf db;
ws.read(op, db);
expect(pong == 1);
expect(to_string(db.data()) == "Hello, World!");
BEAST_EXPECT(pong == 1);
BEAST_EXPECT(to_string(db.data()) == "Hello, World!");
}
ws.set_option(pong_callback{});
@ -918,7 +918,7 @@ public:
opcode op;
streambuf db;
ws.read(op, db);
expect(to_string(db.data()) == "Hello");
BEAST_EXPECT(to_string(db.data()) == "Hello");
}
ws.set_option(auto_fragment_size(0));
@ -932,7 +932,7 @@ public:
opcode op;
streambuf db;
ws.read(op, db);
expect(to_string(db.data()) == s);
BEAST_EXPECT(to_string(db.data()) == s);
}
}
@ -946,8 +946,8 @@ public:
opcode op;
streambuf db;
ws.read(op, db);
expect(op == opcode::text);
expect(to_string(db.data()) == "Hello");
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(
@ -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)
@ -1089,8 +1089,8 @@ public:
ws.async_read(op, db, do_yield[ec]);
if(ec)
throw system_error{ec};
expect(op == opcode::text);
expect(to_string(db.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)
@ -1137,8 +1137,8 @@ public:
ws.async_read(op, db, do_yield[ec]);
if(ec)
throw system_error{ec};
expect(op == opcode::binary);
expect(to_string(db.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)
@ -1165,7 +1165,7 @@ public:
ws.async_read(op, db, do_yield[ec]);
if(ec)
throw system_error{ec};
expect(to_string(db.data()) == "Hello, World!");
BEAST_EXPECT(to_string(db.data()) == "Hello, World!");
}
ws.set_option(pong_callback{});
}
@ -1180,7 +1180,7 @@ public:
ws.async_read(op, db, do_yield[ec]);
if(ec)
throw system_error{ec};
expect(to_string(db.data()) == "Hello");
BEAST_EXPECT(to_string(db.data()) == "Hello");
}
ws.set_option(auto_fragment_size(0));
@ -1198,7 +1198,7 @@ public:
ws.async_read(op, db, do_yield[ec]);
if(ec)
throw system_error{ec};
expect(to_string(db.data()) == s);
BEAST_EXPECT(to_string(db.data()) == s);
}
}
@ -1218,8 +1218,8 @@ public:
ws.async_read(op, db, do_yield[ec]);
if(ec)
throw system_error{ec};
expect(op == opcode::text);
expect(to_string(db.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<socket_type&> 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