mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Refactor beast core, http, tests, and examples:
* Fix warnings * Port cmake scripts to linux * Add command line options for running test suites * Add examples to CMakeLists * Return std::uint64_t from writer::content_length * basic_parser::write takes asio::const_buffer instead of pointer and size * Turn message test back on now that it passes * Rename to http::headers, use std::allocator, remove http_headers * http::message::method is now a string * Refactor to_string for ConstBufferSequence * Remove chunk_encode from the public interface * Initialize members for default constructed iterators * Disallow default construction for dependent buffer sequences Refactor http::message serialization: * Serialization no longer creates a copy of the headers and modifies them * New function prepare(), sets Connection, Transfer-Encoding, Content-Length based on the body attributes and caller options. Callers can use prepare() to have the fields set automatically, or they can set the fields manually. * Use write for operator<< * Tests for serialization
This commit is contained in:
@@ -3,14 +3,14 @@
|
||||
GroupSources(include/beast)
|
||||
GroupSources(test)
|
||||
|
||||
set(CORE_TESTS_SRCS
|
||||
add_executable (core-tests
|
||||
${BEAST_INCLUDES}
|
||||
main.cpp
|
||||
async_completion.cpp
|
||||
basic_streambuf.cpp
|
||||
bind_handler.cpp
|
||||
buffer_cat.cpp
|
||||
buffers_adapter.cpp
|
||||
buffers_debug.cpp
|
||||
consuming_buffers.cpp
|
||||
handler_alloc.cpp
|
||||
placeholders.cpp
|
||||
@@ -18,26 +18,25 @@ set(CORE_TESTS_SRCS
|
||||
static_streambuf.cpp
|
||||
streambuf.cpp
|
||||
streambuf_readstream.cpp
|
||||
to_string.cpp
|
||||
type_check.cpp
|
||||
detail/base64.cpp
|
||||
detail/empty_base_optimization.cpp
|
||||
)
|
||||
|
||||
add_executable (core-tests
|
||||
${BEAST_INCLUDES}
|
||||
${CORE_TESTS_SRCS}
|
||||
)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(core-tests ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(HTTP_TESTS_SRCS
|
||||
add_executable (http-tests
|
||||
${BEAST_INCLUDES}
|
||||
main.cpp
|
||||
http/basic_headers.cpp
|
||||
http/basic_parser.cpp
|
||||
http/chunk_encode.cpp
|
||||
http/empty_body.cpp
|
||||
http/error.cpp
|
||||
http/headers.cpp
|
||||
http/message.cpp
|
||||
http/method.cpp
|
||||
http/parse_error.cpp
|
||||
http/parser.cpp
|
||||
http/read.cpp
|
||||
@@ -45,17 +44,18 @@ set(HTTP_TESTS_SRCS
|
||||
http/resume_context.cpp
|
||||
http/rfc2616.cpp
|
||||
http/rfc7230.cpp
|
||||
http/status.cpp
|
||||
http/streambuf_body.cpp
|
||||
http/string_body.cpp
|
||||
http/write.cpp
|
||||
)
|
||||
|
||||
add_executable (http-tests
|
||||
${BEAST_INCLUDES}
|
||||
${HTTP_TESTS_SRCS}
|
||||
)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(http-tests ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(WEBSOCKET_TESTS_SRCS
|
||||
add_executable (websocket-tests
|
||||
${BEAST_INCLUDES}
|
||||
main.cpp
|
||||
websocket/error.cpp
|
||||
websocket/option.cpp
|
||||
@@ -65,18 +65,18 @@ set(WEBSOCKET_TESTS_SRCS
|
||||
websocket/utf8_checker.cpp
|
||||
)
|
||||
|
||||
add_executable (websocket-tests
|
||||
${BEAST_INCLUDES}
|
||||
${WEBSOCKET_TESTS_SRCS}
|
||||
)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(websocket-tests ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(PARSER_BENCH_SRCS
|
||||
add_executable (parser-bench
|
||||
${BEAST_INCLUDES}
|
||||
main.cpp
|
||||
http/nodejs_parser.cpp
|
||||
http/parser_bench.cpp
|
||||
)
|
||||
|
||||
add_executable (parser-bench
|
||||
${BEAST_INCLUDES}
|
||||
${PARSER_BENCH_SRCS}
|
||||
)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(parser-bench ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ unit-test core-tests :
|
||||
bind_handler.cpp
|
||||
buffer_cat.cpp
|
||||
buffers_adapter.cpp
|
||||
buffers_debug.cpp
|
||||
consuming_buffers.cpp
|
||||
handler_alloc.cpp
|
||||
placeholders.cpp
|
||||
@@ -22,6 +21,7 @@ unit-test core-tests :
|
||||
static_streambuf.cpp
|
||||
streambuf.cpp
|
||||
streambuf_readstream.cpp
|
||||
to_string.cpp
|
||||
type_check.cpp
|
||||
detail/base64.cpp
|
||||
detail/empty_base_optimization.cpp
|
||||
@@ -31,12 +31,10 @@ unit-test http-tests :
|
||||
main.cpp
|
||||
http/basic_headers.cpp
|
||||
http/basic_parser.cpp
|
||||
http/chunk_encode.cpp
|
||||
http/empty_body.cpp
|
||||
http/error.cpp
|
||||
http/headers.cpp
|
||||
http/message.cpp
|
||||
http/method.cpp
|
||||
http/parse_error.cpp
|
||||
http/parser.cpp
|
||||
http/read.cpp
|
||||
@@ -44,6 +42,7 @@ unit-test http-tests :
|
||||
http/resume_context.cpp
|
||||
http/rfc2616.cpp
|
||||
http/rfc7230.cpp
|
||||
http/status.cpp
|
||||
http/streambuf_body.cpp
|
||||
http/string_body.cpp
|
||||
http/write.cpp
|
||||
|
||||
@@ -179,40 +179,81 @@ public:
|
||||
std::size_t v = s.size() - (t + u);
|
||||
{
|
||||
streambuf sb(i);
|
||||
decltype(sb)::mutable_buffers_type d;
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
sb.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
{
|
||||
auto d = sb.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
sb.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
}
|
||||
expect(sb.size() == x);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
{
|
||||
auto d = sb.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
}
|
||||
sb.commit(1);
|
||||
expect(sb.size() == x + y);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
{
|
||||
auto d = sb.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = sb.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
}
|
||||
sb.commit(2);
|
||||
expect(sb.size() == x + y + z);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
expect(to_string(sb.data()) == s);
|
||||
sb.consume(t);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
{
|
||||
auto d = sb.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
expect(to_string(sb.data()) == s.substr(t, std::string::npos));
|
||||
sb.consume(u);
|
||||
expect(to_string(sb.data()) == s.substr(t + u, std::string::npos));
|
||||
sb.consume(v);
|
||||
expect(to_string(sb.data()) == "");
|
||||
sb.consume(1);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
{
|
||||
auto d = sb.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
}
|
||||
}}}}}
|
||||
}
|
||||
|
||||
@@ -61,43 +61,83 @@ public:
|
||||
mutable_buffer{&buf[i+j], k}}};
|
||||
buffers_adapter<decltype(bs)> ba(std::move(bs));
|
||||
expect(ba.max_size() == sizeof(buf));
|
||||
decltype(ba)::mutable_buffers_type d;
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
}
|
||||
expect(ba.size() == x);
|
||||
expect(ba.max_size() == sizeof(buf) - x);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
}
|
||||
ba.commit(1);
|
||||
expect(ba.size() == x + y);
|
||||
expect(ba.max_size() == sizeof(buf) - (x + y));
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
}
|
||||
ba.commit(2);
|
||||
expect(ba.size() == x + y + z);
|
||||
expect(ba.max_size() == 0);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
expect(to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
expect(to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
expect(to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
expect(to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "message_fuzz.hpp"
|
||||
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/buffers_debug.hpp>
|
||||
#include <beast/write_streambuf.hpp>
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
@@ -183,6 +182,7 @@ public:
|
||||
void
|
||||
testCallbacks()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
{
|
||||
cb_checker<true> p;
|
||||
error_code ec;
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
p.write(buffer(s), ec);
|
||||
if( expect(! ec))
|
||||
{
|
||||
expect(p.method);
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
p.write(buffer(s), ec);
|
||||
if( expect(! ec))
|
||||
{
|
||||
expect(p.reason);
|
||||
@@ -235,10 +235,11 @@ public:
|
||||
void
|
||||
parse(boost::string_ref const& m, F&& f)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
{
|
||||
error_code ec;
|
||||
Parser p;
|
||||
p.write(m.data(), m.size(), ec);
|
||||
p.write(buffer(m.data(), m.size()), ec);
|
||||
if(expect(p.complete()))
|
||||
if(expect(! ec, ec.message()))
|
||||
f(p);
|
||||
@@ -247,7 +248,7 @@ public:
|
||||
{
|
||||
error_code ec;
|
||||
Parser p;
|
||||
p.write(&m[0], i, ec);
|
||||
p.write(buffer(&m[0], i), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
continue;
|
||||
if(p.complete())
|
||||
@@ -256,7 +257,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
p.write(&m[i], m.size() - i, ec);
|
||||
p.write(buffer(&m[i], m.size() - i), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
continue;
|
||||
expect(p.complete());
|
||||
@@ -271,10 +272,11 @@ public:
|
||||
void
|
||||
parse_ev(boost::string_ref const& m, parse_error ev)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
{
|
||||
error_code ec;
|
||||
null_parser<isRequest> p;
|
||||
p.write(m.data(), m.size(), ec);
|
||||
p.write(buffer(m.data(), m.size()), ec);
|
||||
if(expect(! p.complete()))
|
||||
expect(ec == ev, ec.message());
|
||||
}
|
||||
@@ -282,7 +284,7 @@ public:
|
||||
{
|
||||
error_code ec;
|
||||
null_parser<isRequest> p;
|
||||
p.write(&m[0], i, ec);
|
||||
p.write(buffer(&m[0], i), ec);
|
||||
if(! expect(! p.complete()))
|
||||
continue;
|
||||
if(ec)
|
||||
@@ -290,7 +292,7 @@ public:
|
||||
expect(ec == ev, ec.message());
|
||||
continue;
|
||||
}
|
||||
p.write(&m[i], m.size() - i, ec);
|
||||
p.write(buffer(&m[i], m.size() - i), ec);
|
||||
if(! expect(! p.complete()))
|
||||
continue;
|
||||
if(! expect(ec == ev, ec.message()))
|
||||
@@ -449,11 +451,12 @@ public:
|
||||
void
|
||||
testUpgrade()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
null_parser<true> p;
|
||||
boost::string_ref s =
|
||||
"GET / HTTP/1.1\r\nConnection: upgrade\r\nUpgrade: WebSocket\r\n\r\n";
|
||||
error_code ec;
|
||||
p.write(s.data(), s.size(), ec);
|
||||
p.write(buffer(s.data(), s.size()), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
return;
|
||||
expect(p.complete());
|
||||
@@ -481,6 +484,7 @@ public:
|
||||
void
|
||||
testRandomReq(std::size_t N)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
message_fuzz mg;
|
||||
@@ -499,7 +503,7 @@ public:
|
||||
for(std::size_t j = 1; j < s.size() - 1; ++j)
|
||||
{
|
||||
error_code ec;
|
||||
p.write(&s[0], j, ec);
|
||||
p.write(buffer(&s[0], j), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
{
|
||||
log << escaped_string(s);
|
||||
@@ -507,7 +511,7 @@ public:
|
||||
}
|
||||
if(! p.complete())
|
||||
{
|
||||
p.write(&s[j], s.size() - j, ec);
|
||||
p.write(buffer(&s[j], s.size() - j), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
{
|
||||
log << escaped_string(s);
|
||||
@@ -528,6 +532,7 @@ public:
|
||||
void
|
||||
testRandomResp(std::size_t N)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
message_fuzz mg;
|
||||
@@ -546,7 +551,7 @@ public:
|
||||
for(std::size_t j = 1; j < s.size() - 1; ++j)
|
||||
{
|
||||
error_code ec;
|
||||
p.write(&s[0], j, ec);
|
||||
p.write(buffer(&s[0], j), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
{
|
||||
log << escaped_string(s);
|
||||
@@ -554,7 +559,7 @@ public:
|
||||
}
|
||||
if(! p.complete())
|
||||
{
|
||||
p.write(&s[j], s.size() - j, ec);
|
||||
p.write(buffer(&s[j], s.size() - j), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
{
|
||||
log << escaped_string(s);
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/detail/unit_test/suite.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace test {
|
||||
|
||||
class chunk_encode_test : public beast::detail::unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Convert CR LF to printables for display
|
||||
static
|
||||
std::string
|
||||
encode (std::string const& s)
|
||||
{
|
||||
std::string result;
|
||||
for(auto const c : s)
|
||||
{
|
||||
if (c == '\r')
|
||||
result += "\\r";
|
||||
else if (c== '\n')
|
||||
result += "\\n";
|
||||
else
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Print the contents of a ConstBufferSequence to the log
|
||||
template <class ConstBufferSequence, class Log>
|
||||
static
|
||||
void
|
||||
print (ConstBufferSequence const& buffers, Log log)
|
||||
{
|
||||
for(auto const& buf : buffers)
|
||||
log << encode (std::string(
|
||||
boost::asio::buffer_cast<char const*>(buf),
|
||||
boost::asio::buffer_size(buf)));
|
||||
}
|
||||
|
||||
// Convert a ConstBufferSequence to a string
|
||||
template <class ConstBufferSequence>
|
||||
static
|
||||
std::string
|
||||
buffer_to_string (ConstBufferSequence const& b)
|
||||
{
|
||||
std::string s;
|
||||
auto const n = boost::asio::buffer_size(b);
|
||||
s.resize(n);
|
||||
boost::asio::buffer_copy(
|
||||
boost::asio::buffer(&s[0], n), b);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Append a ConstBufferSequence to an existing string
|
||||
template <class ConstBufferSequence>
|
||||
static
|
||||
void
|
||||
buffer_append (std::string& s, ConstBufferSequence const& b)
|
||||
{
|
||||
s += buffer_to_string(b);
|
||||
}
|
||||
|
||||
// Convert the input sequence of the stream to a
|
||||
// chunked-encoded string. The input sequence is consumed.
|
||||
template <class Streambuf>
|
||||
static
|
||||
std::string
|
||||
streambuf_to_string (Streambuf& sb,
|
||||
bool final_chunk = false)
|
||||
{
|
||||
std::string s;
|
||||
buffer_append(s, chunk_encode(sb.data(), final_chunk));
|
||||
return s;
|
||||
}
|
||||
|
||||
// Check an input against the correct chunk encoded version
|
||||
void
|
||||
check (std::string const& in, std::string const& answer,
|
||||
bool final_chunk = true)
|
||||
{
|
||||
streambuf sb(3);
|
||||
sb << in;
|
||||
auto const out = streambuf_to_string (sb, final_chunk);
|
||||
if (! expect (out == answer))
|
||||
log << "expected\n" << encode(answer) <<
|
||||
"\ngot\n" << encode(out);
|
||||
}
|
||||
|
||||
void testStreambuf()
|
||||
{
|
||||
streambuf sb(3);
|
||||
std::string const s =
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789";
|
||||
sb << s;
|
||||
expect(buffer_to_string(sb.data()) == s);
|
||||
}
|
||||
|
||||
void
|
||||
testEncoder()
|
||||
{
|
||||
check("", "0\r\n\r\n");
|
||||
check("x", "1\r\nx\r\n0\r\n\r\n");
|
||||
check("abcd", "4\r\nabcd\r\n0\r\n\r\n");
|
||||
check("x", "1\r\nx\r\n", false);
|
||||
check(
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
,
|
||||
"d2\r\n"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"\r\n"
|
||||
"0\r\n\r\n");
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testStreambuf();
|
||||
testEncoder();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(chunk_encode,http,beast);
|
||||
|
||||
} // test
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include <beast/detail/unit_test/suite.hpp>
|
||||
#include <beast/detail/unit_test/thread.hpp>
|
||||
#include <beast/buffers_debug.hpp>
|
||||
#include <beast/placeholders.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/http.hpp>
|
||||
@@ -151,8 +150,7 @@ public:
|
||||
|
||||
streambuf rb;
|
||||
{
|
||||
request<string_body> req(
|
||||
{beast::http::method_t::http_get, "/", 11});
|
||||
request<string_body> req({"GET", "/", 11});
|
||||
req.body = "Beast.HTTP";
|
||||
req.headers.replace("Host",
|
||||
ep.address().to_string() + ":" +
|
||||
@@ -176,7 +174,7 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
//testAsio();
|
||||
testAsio();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "nodejs-parser/http_parser.h"
|
||||
|
||||
#include <beast/http/method.hpp>
|
||||
#include <beast/http/basic_parser.hpp>
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
@@ -75,62 +74,62 @@ make_nodejs_error(int http_errno)
|
||||
}
|
||||
|
||||
inline
|
||||
beast::http::method_t
|
||||
convert_http_method(http_method m)
|
||||
char const*
|
||||
method_to_string(unsigned method)
|
||||
{
|
||||
using namespace beast;
|
||||
switch (m)
|
||||
switch(static_cast<http_method>(method))
|
||||
{
|
||||
case HTTP_DELETE: return http::method_t::http_delete;
|
||||
case HTTP_GET: return http::method_t::http_get;
|
||||
case HTTP_HEAD: return http::method_t::http_head;
|
||||
case HTTP_POST: return http::method_t::http_post;
|
||||
case HTTP_PUT: return http::method_t::http_put;
|
||||
case HTTP_DELETE: return "DELETE";
|
||||
case HTTP_GET: return "GET";
|
||||
case HTTP_HEAD: return "HEAD";
|
||||
case HTTP_POST: return "POST";
|
||||
case HTTP_PUT: return "PUT";
|
||||
|
||||
// pathological
|
||||
case HTTP_CONNECT: return http::method_t::http_connect;
|
||||
case HTTP_OPTIONS: return http::method_t::http_options;
|
||||
case HTTP_TRACE: return http::method_t::http_trace;
|
||||
case HTTP_CONNECT: return "CONNECT";
|
||||
case HTTP_OPTIONS: return "OPTIONS";
|
||||
case HTTP_TRACE: return "TRACE";
|
||||
|
||||
// webdav
|
||||
case HTTP_COPY: return http::method_t::http_copy;
|
||||
case HTTP_LOCK: return http::method_t::http_lock;
|
||||
case HTTP_MKCOL: return http::method_t::http_mkcol;
|
||||
case HTTP_MOVE: return http::method_t::http_move;
|
||||
case HTTP_PROPFIND: return http::method_t::http_propfind;
|
||||
case HTTP_PROPPATCH: return http::method_t::http_proppatch;
|
||||
case HTTP_SEARCH: return http::method_t::http_search;
|
||||
case HTTP_UNLOCK: return http::method_t::http_unlock;
|
||||
case HTTP_BIND: return http::method_t::http_bind;
|
||||
case HTTP_REBIND: return http::method_t::http_rebind;
|
||||
case HTTP_UNBIND: return http::method_t::http_unbind;
|
||||
case HTTP_ACL: return http::method_t::http_acl;
|
||||
case HTTP_COPY: return "COPY";
|
||||
case HTTP_LOCK: return "LOCK";
|
||||
case HTTP_MKCOL: return "MKCOL";
|
||||
case HTTP_MOVE: return "MOVE";
|
||||
case HTTP_PROPFIND: return "PROPFIND";
|
||||
case HTTP_PROPPATCH: return "PROPPATCH";
|
||||
case HTTP_SEARCH: return "SEARCH";
|
||||
case HTTP_UNLOCK: return "UNLOCK";
|
||||
case HTTP_BIND: return "BIND";
|
||||
case HTTP_REBIND: return "REBIND";
|
||||
case HTTP_UNBIND: return "UNBIND";
|
||||
case HTTP_ACL: return "ACL";
|
||||
|
||||
// subversion
|
||||
case HTTP_REPORT: return http::method_t::http_report;
|
||||
case HTTP_MKACTIVITY: return http::method_t::http_mkactivity;
|
||||
case HTTP_CHECKOUT: return http::method_t::http_checkout;
|
||||
case HTTP_MERGE: return http::method_t::http_merge;
|
||||
case HTTP_REPORT: return "REPORT";
|
||||
case HTTP_MKACTIVITY: return "MKACTIVITY";
|
||||
case HTTP_CHECKOUT: return "CHECKOUT";
|
||||
case HTTP_MERGE: return "MERGE";
|
||||
|
||||
// upnp
|
||||
case HTTP_MSEARCH: return http::method_t::http_msearch;
|
||||
case HTTP_NOTIFY: return http::method_t::http_notify;
|
||||
case HTTP_SUBSCRIBE: return http::method_t::http_subscribe;
|
||||
case HTTP_UNSUBSCRIBE: return http::method_t::http_unsubscribe;
|
||||
case HTTP_MSEARCH: return "MSEARCH";
|
||||
case HTTP_NOTIFY: return "NOTIFY";
|
||||
case HTTP_SUBSCRIBE: return "SUBSCRIBE";
|
||||
case HTTP_UNSUBSCRIBE: return "UNSUBSCRIBE";
|
||||
|
||||
// RFC-5789
|
||||
case HTTP_PATCH: return http::method_t::http_patch;
|
||||
case HTTP_PURGE: return http::method_t::http_purge;
|
||||
case HTTP_PATCH: return "PATCH";
|
||||
case HTTP_PURGE: return "PURGE";
|
||||
|
||||
// CalDav
|
||||
case HTTP_MKCALENDAR: return http::method_t::http_mkcalendar;
|
||||
case HTTP_MKCALENDAR: return "MKCALENDAR";
|
||||
|
||||
// RFC-2068, section 19.6.1.2
|
||||
case HTTP_LINK: return http::method_t::http_link;
|
||||
case HTTP_UNLINK: return http::method_t::http_unlink;
|
||||
case HTTP_LINK: return "LINK";
|
||||
case HTTP_UNLINK: return "UNLINK";
|
||||
};
|
||||
|
||||
return http::method_t::http_get;
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
} // detail
|
||||
@@ -308,7 +307,7 @@ private:
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_request(
|
||||
std::declval<method_t>(), std::declval<std::string>(),
|
||||
std::declval<unsigned>(), std::declval<std::string>(),
|
||||
std::declval<int>(), std::declval<int>(),
|
||||
std::declval<bool>(), std::declval<bool>()),
|
||||
std::true_type{})>
|
||||
@@ -324,7 +323,7 @@ private:
|
||||
std::integral_constant<bool, has_on_request_t<C>::value>;
|
||||
|
||||
void
|
||||
call_on_request(method_t method, std::string url,
|
||||
call_on_request(unsigned method, std::string url,
|
||||
int major, int minor, bool keep_alive, bool upgrade,
|
||||
std::true_type)
|
||||
{
|
||||
@@ -333,7 +332,7 @@ private:
|
||||
}
|
||||
|
||||
void
|
||||
call_on_request(method_t, std::string, int, int, bool, bool,
|
||||
call_on_request(unsigned, std::string, int, int, bool, bool,
|
||||
std::false_type)
|
||||
{
|
||||
}
|
||||
@@ -687,10 +686,9 @@ nodejs_basic_parser<Derived>::cb_headers_complete(http_parser* p)
|
||||
http_should_keep_alive(p) != 0;
|
||||
if(p->type == http_parser_type::HTTP_REQUEST)
|
||||
{
|
||||
t.call_on_request(detail::convert_http_method(
|
||||
http_method(p->method)), t.url_,
|
||||
p->http_major, p->http_minor, keep_alive,
|
||||
p->upgrade, has_on_request<Derived>{});
|
||||
t.call_on_request(p->method, t.url_,
|
||||
p->http_major, p->http_minor, keep_alive,
|
||||
p->upgrade, has_on_request<Derived>{});
|
||||
return 0;
|
||||
}
|
||||
return t.call_on_response(p->status_code, t.status_,
|
||||
@@ -807,18 +805,18 @@ private:
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t method, std::string const& url,
|
||||
on_request(unsigned method, std::string const& url,
|
||||
int major, int minor, bool keep_alive, bool upgrade,
|
||||
std::true_type)
|
||||
{
|
||||
m_.method = method;
|
||||
m_.method = detail::method_to_string(method);
|
||||
m_.url = url;
|
||||
m_.version = major * 10 + minor;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t, std::string const&,
|
||||
on_request(unsigned, std::string const&,
|
||||
int, int, bool, bool,
|
||||
std::false_type)
|
||||
{
|
||||
@@ -826,7 +824,7 @@ private:
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t method, std::string const& url,
|
||||
on_request(unsigned method, std::string const& url,
|
||||
int major, int minor, bool keep_alive, bool upgrade)
|
||||
{
|
||||
return on_request(method, url,
|
||||
|
||||
@@ -20,6 +20,7 @@ class parser_test : public beast::detail::unit_test::suite
|
||||
public:
|
||||
void run() override
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
{
|
||||
error_code ec;
|
||||
parser<true, string_body,
|
||||
@@ -30,11 +31,11 @@ public:
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
p.write(buffer(s), ec);
|
||||
expect(! ec);
|
||||
expect(p.complete());
|
||||
auto m = p.release();
|
||||
expect(m.method == method_t::http_get);
|
||||
expect(m.method == "GET");
|
||||
expect(m.url == "/");
|
||||
expect(m.version == 11);
|
||||
expect(m.headers["User-Agent"] == "test");
|
||||
@@ -50,7 +51,7 @@ public:
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
p.write(buffer(s), ec);
|
||||
expect(! ec);
|
||||
expect(p.complete());
|
||||
auto m = p.release();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "message_fuzz.hpp"
|
||||
#include <beast/http.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/buffers_debug.hpp>
|
||||
#include <beast/to_string.hpp>
|
||||
#include <beast/detail/unit_test/suite.hpp>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
@@ -74,8 +74,7 @@ public:
|
||||
error_code ec;
|
||||
p.write(sb.data(), ec);
|
||||
if(! expect(! ec, ec.message()))
|
||||
log << debug::buffers_to_string(
|
||||
sb.data()) << std::endl;
|
||||
log << to_string(sb.data()) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,20 +121,20 @@ public:
|
||||
[&]
|
||||
{
|
||||
testParser<nodejs_parser<
|
||||
true, streambuf_body, http_headers>>(
|
||||
true, streambuf_body, headers>>(
|
||||
Repeat, creq_);
|
||||
testParser<nodejs_parser<
|
||||
false, streambuf_body, http_headers>>(
|
||||
false, streambuf_body, headers>>(
|
||||
Repeat, cres_);
|
||||
});
|
||||
timedTest(Trials, "http::basic_parser",
|
||||
[&]
|
||||
{
|
||||
testParser<parser<
|
||||
true, streambuf_body, http_headers>>(
|
||||
true, streambuf_body, headers>>(
|
||||
Repeat, creq_);
|
||||
testParser<parser<
|
||||
false, streambuf_body, http_headers>>(
|
||||
false, streambuf_body, headers>>(
|
||||
Repeat, cres_);
|
||||
});
|
||||
pass();
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/method.hpp>
|
||||
#include <beast/http/status.hpp>
|
||||
9
test/http/type_check.cpp
Normal file
9
test/http/type_check.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/type_check.hpp>
|
||||
@@ -7,3 +7,252 @@
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/write.hpp>
|
||||
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/empty_body.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/to_string.hpp>
|
||||
#include <beast/detail/unit_test/suite.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class write_test : public beast::detail::unit_test::suite
|
||||
{
|
||||
public:
|
||||
struct string_SyncStream
|
||||
{
|
||||
std::string str;
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
write_some(ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write_some(buffers, ec);
|
||||
if(ec)
|
||||
throw boost::system::system_error{ec};
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t write_some(
|
||||
ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
auto const n = buffer_size(buffers);
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::buffer_cast;
|
||||
str.reserve(str.size() + n);
|
||||
for(auto const& buffer : buffers)
|
||||
str.append(buffer_cast<char const*>(buffer),
|
||||
buffer_size(buffer));
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
struct test_Body
|
||||
{
|
||||
using value_type = std::string;
|
||||
|
||||
class writer
|
||||
{
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
writer(message<isRequest, test_Body, Allocator> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Write>
|
||||
boost::tribool
|
||||
operator()(resume_context&&, error_code&, Write&& write)
|
||||
{
|
||||
write(boost::asio::buffer(body_));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
std::string
|
||||
str(message<isRequest, Body, Headers> const& m)
|
||||
{
|
||||
string_SyncStream ss;
|
||||
write(ss, m);
|
||||
return ss.str;
|
||||
}
|
||||
|
||||
void
|
||||
testWrite()
|
||||
{
|
||||
// auto content-length HTTP/1.0
|
||||
{
|
||||
message<true, string_body, headers> m{{
|
||||
"GET", "/", 10}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
expect(str(m) ==
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*"
|
||||
);
|
||||
}
|
||||
// keep-alive HTTP/1.0
|
||||
{
|
||||
message<true, string_body, headers> m{{
|
||||
"GET", "/", 10}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m, connection::keep_alive);
|
||||
expect(str(m) ==
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"\r\n"
|
||||
"*"
|
||||
);
|
||||
}
|
||||
// upgrade HTTP/1.0
|
||||
{
|
||||
message<true, string_body, headers> m{{
|
||||
"GET", "/", 10}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
try
|
||||
{
|
||||
prepare(m, connection::upgrade);
|
||||
fail();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
// no content-length HTTP/1.0
|
||||
{
|
||||
message<true, test_Body, headers> m{{
|
||||
"GET", "/", 10}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
string_SyncStream ss;
|
||||
error_code ec;
|
||||
write(ss, m, ec);
|
||||
expect(ec == boost::asio::error::eof);
|
||||
expect(ss.str ==
|
||||
"GET / HTTP/1.0\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"\r\n"
|
||||
"*"
|
||||
);
|
||||
}
|
||||
// auto content-length HTTP/1.1
|
||||
{
|
||||
message<true, string_body, headers> m{{
|
||||
"GET", "/", 11}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
expect(str(m) ==
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*"
|
||||
);
|
||||
}
|
||||
// close HTTP/1.1
|
||||
{
|
||||
message<true, string_body, headers> m{{
|
||||
"GET", "/", 11}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m, connection::close);
|
||||
string_SyncStream ss;
|
||||
error_code ec;
|
||||
write(ss, m, ec);
|
||||
expect(ec == boost::asio::error::eof);
|
||||
expect(ss.str ==
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n"
|
||||
"*"
|
||||
);
|
||||
}
|
||||
// upgrade HTTP/1.1
|
||||
{
|
||||
message<true, empty_body, headers> m{{
|
||||
"GET", "/", 11}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
prepare(m, connection::upgrade);
|
||||
expect(str(m) ==
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Connection: upgrade\r\n"
|
||||
"\r\n"
|
||||
);
|
||||
}
|
||||
// no content-length HTTP/1.1
|
||||
{
|
||||
message<true, test_Body, headers> m{{
|
||||
"GET", "/", 11}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
string_SyncStream ss;
|
||||
error_code ec;
|
||||
write(ss, m, ec);
|
||||
expect(ss.str ==
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n"
|
||||
"1\r\n"
|
||||
"*\r\n"
|
||||
"0\r\n\r\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void testConvert()
|
||||
{
|
||||
message<true, string_body, headers> m{{
|
||||
"GET", "/", 11}};
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
expect(boost::lexical_cast<std::string>(m) ==
|
||||
"GET / HTTP/1.1\r\nUser-Agent: test\r\nContent-Length: 1\r\n\r\n*");
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testWrite();
|
||||
testConvert();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(write,http,beast);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
@@ -17,26 +17,77 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/detail/unit_test/amount.hpp>
|
||||
#include <beast/detail/unit_test/global_suites.hpp>
|
||||
#include <beast/detail/unit_test/match.hpp>
|
||||
#include <beast/detail/unit_test/reporter.hpp>
|
||||
#include <beast/detail/unit_test/suite.hpp>
|
||||
#include <beast/detail/stream/debug_ostream.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifndef WIN32_LEAN_AND_MEAN // VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# else
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
namespace unit_test {
|
||||
|
||||
std::string
|
||||
prefix(suite_info const& s)
|
||||
{
|
||||
if (s.manual())
|
||||
return "|M| ";
|
||||
return " ";
|
||||
}
|
||||
|
||||
template<class Log>
|
||||
void
|
||||
print(Log& log, suite_list const& c)
|
||||
{
|
||||
std::size_t manual = 0;
|
||||
for(auto const& s : c)
|
||||
{
|
||||
log <<
|
||||
prefix (s) <<
|
||||
s.full_name();
|
||||
if(s.manual())
|
||||
++manual;
|
||||
}
|
||||
log <<
|
||||
amount(c.size(), "suite") << " total, " <<
|
||||
amount(manual, "manual suite")
|
||||
;
|
||||
}
|
||||
|
||||
template<class Log>
|
||||
void
|
||||
print(Log& log)
|
||||
{
|
||||
log << "------------------------------------------";
|
||||
print(log, global_suites());
|
||||
log << "------------------------------------------";
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
// Simple main used to produce stand
|
||||
// alone executables that run unit tests.
|
||||
int main()
|
||||
int main(int ac, char const* av[])
|
||||
{
|
||||
using namespace std;
|
||||
using namespace beast::detail::unit_test;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -47,10 +98,41 @@ int main()
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace po = boost::program_options;
|
||||
po::options_description desc("Options");
|
||||
desc.add_options()
|
||||
("help,h", "Produce a help message")
|
||||
("print,r", "Print the list of available test suites")
|
||||
("suites,s", po::value<string>(), "suites to run")
|
||||
;
|
||||
|
||||
po::positional_options_description p;
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(ac, av, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
beast::detail::debug_ostream log;
|
||||
|
||||
if(vm.count("help"))
|
||||
{
|
||||
beast::detail::debug_ostream s;
|
||||
reporter r (s);
|
||||
bool failed (r.run_each (global_suites()));
|
||||
log << desc;
|
||||
}
|
||||
else if(vm.count("print"))
|
||||
{
|
||||
print(log);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string suites;
|
||||
if(vm.count("suites") > 0)
|
||||
suites = vm["suites"].as<string>();
|
||||
reporter r(log);
|
||||
bool failed;
|
||||
if(! suites.empty())
|
||||
failed = r.run_each_if(global_suites(),
|
||||
match_auto(suites));
|
||||
else
|
||||
failed = r.run_each(global_suites());
|
||||
if (failed)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -52,40 +52,81 @@ public:
|
||||
{
|
||||
std::memset(buf, 0, sizeof(buf));
|
||||
static_streambuf_n<sizeof(buf)> ba;
|
||||
decltype(ba)::mutable_buffers_type d;
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
}
|
||||
expect(ba.size() == x);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
}
|
||||
ba.commit(1);
|
||||
expect(ba.size() == x + y);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
{
|
||||
auto d = ba.prepare(x);
|
||||
expect(buffer_size(d) == x);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(y);
|
||||
expect(buffer_size(d) == y);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
{
|
||||
auto d = ba.prepare(z);
|
||||
expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
}
|
||||
ba.commit(2);
|
||||
expect(ba.size() == x + y + z);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
expect(to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
expect(to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
expect(to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
expect(to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
{
|
||||
auto d = ba.prepare(0);
|
||||
expect(buffer_size(d) == 0);
|
||||
}
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/buffers_debug.hpp>
|
||||
#include <beast/to_string.hpp>
|
||||
Reference in New Issue
Block a user