Files
boost_beast/test/beast/http/chunk_encode.cpp
T

312 lines
7.8 KiB
C++
Raw Normal View History

2017-07-09 20:09:30 -07:00
//
2017-07-24 09:42:36 -07:00
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
2017-07-09 20:09:30 -07:00
//
// 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)
//
2017-07-20 13:40:34 -07:00
// Official repository: https://github.com/boostorg/beast
//
2017-07-09 20:09:30 -07:00
// Test that header file is self-contained.
2017-07-20 13:40:34 -07:00
#include <boost/beast/http/chunk_encode.hpp>
2017-07-09 20:09:30 -07:00
2017-07-12 18:06:36 -07:00
#include "message_fuzz.hpp"
2017-07-20 13:40:34 -07:00
#include <boost/beast/core/static_string.hpp>
#include <boost/beast/http/fields.hpp>
#include <boost/beast/test/fuzz.hpp>
#include <boost/beast/unit_test/suite.hpp>
2017-07-09 20:09:30 -07:00
#include <boost/optional.hpp>
2017-07-12 18:06:36 -07:00
#include <random>
2017-07-09 20:09:30 -07:00
2017-07-20 13:40:34 -07:00
namespace boost {
2017-07-09 20:09:30 -07:00
namespace beast {
namespace http {
class chunk_encode_test
: public beast::unit_test::suite
{
public:
struct not_chunk_extensions {};
BOOST_STATIC_ASSERT(
detail::is_chunk_extensions<chunk_extensions>::value);
BOOST_STATIC_ASSERT(
! detail::is_chunk_extensions<not_chunk_extensions>::value);
template<class ConstBufferSequence>
static
std::string
to_string(ConstBufferSequence const& buffers)
{
std::string s;
s.reserve(boost::asio::buffer_size(buffers));
for(boost::asio::const_buffer buffer : buffers)
s.append(
boost::asio::buffer_cast<char const*>(buffer),
boost::asio::buffer_size(buffer));
return s;
}
template<class T, class... Args>
void
check(string_view match, Args&&... args)
{
T t{std::forward<Args>(args)...};
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(to_string(t) == match);
2017-07-09 20:09:30 -07:00
T t2{t};
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(to_string(t2) == match);
2017-07-09 20:09:30 -07:00
T t3{std::move(t2)};
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(to_string(t3) == match);
2017-07-09 20:09:30 -07:00
}
template<class T, class... Args>
void
check_fwd(string_view match, Args&&... args)
{
T t{std::forward<Args>(args)...};
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(to_string(t) == match);
2017-07-09 20:09:30 -07:00
T t2{t};
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(to_string(t2) == match);
2017-07-09 20:09:30 -07:00
T t3{std::move(t2)};
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(to_string(t3) == match);
2017-07-09 20:09:30 -07:00
}
using cb_t = boost::asio::const_buffers_1;
static
cb_t
cb(string_view s)
{
return {s.data(), s.size()};
}
void
testChunkCRLF()
{
#if ! defined(BOOST_GCC) || BOOST_GCC >= 50000
check<chunk_crlf>("\r\n");
#endif
}
void
testChunkHeader()
{
check<chunk_header>("10\r\n", 16u);
check<chunk_header>("20;x\r\n", 32u, ";x");
chunk_extensions exts;
exts.insert("y");
exts.insert("z");
check<chunk_header>("30;y;z\r\n", 48u, exts);
{
auto exts2 = exts;
check_fwd<chunk_header>(
"30;y;z\r\n", 48u, std::move(exts2));
}
check<chunk_header>("30;y;z\r\n", 48u, exts,
std::allocator<double>{});
{
auto exts2 = exts;
check<chunk_header>(
"30;y;z\r\n", 48u, std::move(exts2),
std::allocator<double>{});
}
}
void
testChunkBody()
{
check<chunk_body<cb_t>>(
"3\r\n***\r\n", cb("***"));
check<chunk_body<cb_t>>(
"3;x\r\n***\r\n", cb("***"), ";x");
chunk_extensions exts;
exts.insert("y");
exts.insert("z");
check<chunk_body<cb_t>>(
"3;y;z\r\n***\r\n",
cb("***"), exts);
{
auto exts2 = exts;
check_fwd<chunk_body<cb_t>>(
"3;y;z\r\n***\r\n",
cb("***"), std::move(exts2));
}
check<chunk_body<cb_t>>(
"3;y;z\r\n***\r\n",
cb("***"), exts, std::allocator<double>{});
{
auto exts2 = exts;
check_fwd<chunk_body<cb_t>>(
"3;y;z\r\n***\r\n",
cb("***"), std::move(exts2),
std::allocator<double>{});
}
}
void
testChunkFinal()
{
check<chunk_last<>>(
"0\r\n\r\n");
check<chunk_last<cb_t>>(
"0\r\nMD5:ou812\r\n\r\n",
cb("MD5:ou812\r\n\r\n"));
fields trailers;
trailers.set(field::content_md5, "ou812");
check<chunk_last<fields>>(
"0\r\nContent-MD5: ou812\r\n\r\n",
trailers);
{
auto trailers2 = trailers;
check_fwd<chunk_last<fields>>(
"0\r\nContent-MD5: ou812\r\n\r\n",
std::move(trailers2));
}
check<chunk_last<fields>>(
"0\r\nContent-MD5: ou812\r\n\r\n",
trailers, std::allocator<double>{});
{
auto trailers2 = trailers;
check<chunk_last<fields>>(
"0\r\nContent-MD5: ou812\r\n\r\n",
std::move(trailers2), std::allocator<double>{});
}
}
void
testChunkExtensions()
{
2017-07-12 18:06:36 -07:00
auto const str =
[](chunk_extensions const& ce)
{
std::string s;
for(auto const& v : ce)
{
s.append(v.first.to_string());
s.push_back(',');
if(! v.second.empty())
{
s.append(v.second.to_string());
s.push_back(',');
}
}
return s;
};
2017-07-09 20:09:30 -07:00
chunk_extensions ce;
ce.insert("x");
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(ce.str() == ";x");
BEAST_EXPECT(str(ce) == "x,");
2017-07-09 20:09:30 -07:00
ce.insert("y", "z");
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(ce.str() == ";x;y=z");
BEAST_EXPECT(str(ce) == "x,y,z,");
2017-07-09 20:09:30 -07:00
ce.insert("z", R"(")");
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(ce.str() == R"(;x;y=z;z="\"")");
BEAST_EXPECT(str(ce) == R"(x,y,z,z,",)");
2017-07-09 20:09:30 -07:00
ce.insert("p", R"(\)");
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(ce.str() == R"(;x;y=z;z="\"";p="\\")");
BEAST_EXPECT(str(ce) == R"(x,y,z,z,",p,\,)");
2017-07-09 20:09:30 -07:00
ce.insert("q", R"(1"2\)");
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(ce.str() == R"(;x;y=z;z="\"";p="\\";q="1\"2\\")");
BEAST_EXPECT(str(ce) == R"(x,y,z,z,",p,\,q,1"2\,)");
2017-07-12 18:06:36 -07:00
}
void
testParseChunkExtensions()
{
auto const grind =
[&](string_view s)
{
error_code ec;
static_string<200> ss{s};
test::fuzz_rand r;
for(auto i = 3; i--;)
{
test::fuzz(ss, 5, 5, r,
[&](string_view s)
{
chunk_extensions c1;
c1.parse(s, ec);
if(ec)
{
pass();
return;
}
chunk_extensions c2;
c2.parse(c1.str(), ec);
2017-07-25 12:35:54 -07:00
if(! BEAST_EXPECTS(! ec, ec.message()))
2017-07-12 18:06:36 -07:00
return;
chunk_extensions c3;
for(auto const& v : c2)
if(v.second.empty())
c3.insert(v.first);
else
c3.insert(v.first, v.second);
2017-07-25 12:35:54 -07:00
BEAST_EXPECTS(c2.str() == c3.str(), c3.str());
2017-07-12 18:06:36 -07:00
});
}
};
auto const good =
[&](string_view s)
{
error_code ec;
chunk_extensions ce;
ce.parse(s, ec);
2017-07-25 12:35:54 -07:00
BEAST_EXPECTS(! ec, ec.message());
2017-07-12 18:06:36 -07:00
grind(s);
};
auto const bad =
[&](string_view s)
{
error_code ec;
chunk_extensions ce;
ce.parse(s, ec);
2017-07-25 12:35:54 -07:00
BEAST_EXPECT(ec);
2017-07-12 18:06:36 -07:00
grind(s);
};
chunkExtensionsTest(good, bad);
2017-07-09 20:09:30 -07:00
}
void
run() override
{
testChunkCRLF();
testChunkHeader();
testChunkBody();
testChunkFinal();
testChunkExtensions();
2017-07-12 18:06:36 -07:00
testParseChunkExtensions();
2017-07-09 20:09:30 -07:00
}
};
2017-08-01 17:01:57 -07:00
BEAST_DEFINE_TESTSUITE(beast,http,chunk_encode);
2017-07-09 20:09:30 -07:00
} // http
} // beast
2017-07-20 13:40:34 -07:00
} // boost