Files
scylladb/tests/httpd.cc
Amnon Heiman 38a22d9cd8 json: float and double support
This change how the json formatter handle float and adds double support.
float and double conversion will throw exceptions when try to convert
inf or nan.

It also contains tests for both float and double including inf, -inf and
nan for both float and double.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-06-03 10:01:00 +03:00

168 lines
5.5 KiB
C++

/*
* Copyright 2015 Cloudius Systems
*/
#include "http/httpd.hh"
#include "http/handlers.hh"
#include "http/matcher.hh"
#include "http/matchrules.hh"
#include "json/formatter.hh"
#include "http/routes.hh"
#include "http/exception.hh"
#include "http/transformers.hh"
#include "core/future-util.hh"
#include "tests/test-utils.hh"
using namespace httpd;
class handl : public httpd::handler_base {
public:
virtual future<std::unique_ptr<reply> > handle(const sstring& path,
std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
rep->done("html");
return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
}
};
SEASTAR_TEST_CASE(test_reply)
{
reply r;
r.set_content_type("txt");
BOOST_REQUIRE_EQUAL(r._headers["Content-Type"], sstring("text/plain"));
return make_ready_future<>();
}
SEASTAR_TEST_CASE(test_str_matcher)
{
str_matcher m("/hello");
parameters param;
BOOST_REQUIRE_EQUAL(m.match("/abc/hello", 4, param), 10);
return make_ready_future<>();
}
SEASTAR_TEST_CASE(test_param_matcher)
{
param_matcher m("param");
parameters param;
BOOST_REQUIRE_EQUAL(m.match("/abc/hello", 4, param), 10);
BOOST_REQUIRE_EQUAL(param.path("param"), "/hello");
BOOST_REQUIRE_EQUAL(param["param"], "hello");
return make_ready_future<>();
}
SEASTAR_TEST_CASE(test_match_rule)
{
parameters param;
handl* h = new handl();
match_rule mr(h);
mr.add_str("/hello").add_param("param");
httpd::handler_base* res = mr.get("/hello/val1", param);
BOOST_REQUIRE_EQUAL(res, h);
BOOST_REQUIRE_EQUAL(param["param"], "val1");
res = mr.get("/hell/val1", param);
httpd::handler_base* nl = nullptr;
BOOST_REQUIRE_EQUAL(res, nl);
return make_ready_future<>();
}
SEASTAR_TEST_CASE(test_formatter)
{
BOOST_REQUIRE_EQUAL(json::formatter::to_json(true), "true");
BOOST_REQUIRE_EQUAL(json::formatter::to_json(false), "false");
BOOST_REQUIRE_EQUAL(json::formatter::to_json(1), "1");
const char* txt = "efg";
BOOST_REQUIRE_EQUAL(json::formatter::to_json(txt), "\"efg\"");
sstring str = "abc";
BOOST_REQUIRE_EQUAL(json::formatter::to_json(str), "\"abc\"");
float f = 1;
BOOST_REQUIRE_EQUAL(json::formatter::to_json(f), "1.000000");
f = 1.0/0.0;
BOOST_CHECK_THROW(json::formatter::to_json(f), std::out_of_range);
f = -1.0/0.0;
BOOST_CHECK_THROW(json::formatter::to_json(f), std::out_of_range);
f = 0.0/0.0;
BOOST_CHECK_THROW(json::formatter::to_json(f), std::invalid_argument);
double d = -1;
BOOST_REQUIRE_EQUAL(json::formatter::to_json(d), "-1.000000");
d = 1.0/0.0;
BOOST_CHECK_THROW(json::formatter::to_json(d), std::out_of_range);
d = -1.0/0.0;
BOOST_CHECK_THROW(json::formatter::to_json(d), std::out_of_range);
d = 0.0/0.0;
BOOST_CHECK_THROW(json::formatter::to_json(d), std::invalid_argument);
return make_ready_future<>();
}
SEASTAR_TEST_CASE(test_decode_url) {
request req;
req._url = "/a?q=%23%24%23";
sstring url = http_server::connection::set_query_param(req);
BOOST_REQUIRE_EQUAL(url, "/a");
BOOST_REQUIRE_EQUAL(req.get_query_param("q"), "#$#");
req._url = "/a?a=%23%24%23&b=%22%26%22";
http_server::connection::set_query_param(req);
BOOST_REQUIRE_EQUAL(req.get_query_param("a"), "#$#");
BOOST_REQUIRE_EQUAL(req.get_query_param("b"), "\"&\"");
return make_ready_future<>();
}
SEASTAR_TEST_CASE(test_routes) {
handl* h1 = new handl();
handl* h2 = new handl();
routes route;
route.add(operation_type::GET, url("/api").remainder("path"), h1);
route.add(operation_type::GET, url("/"), h2);
std::unique_ptr<request> req = std::make_unique<request>();
std::unique_ptr<reply> rep = std::make_unique<reply>();
auto f1 =
route.handle("/api", std::move(req), std::move(rep)).then(
[] (std::unique_ptr<reply> rep) {
BOOST_REQUIRE_EQUAL((int )rep->_status, (int )reply::status_type::ok);
});
req.reset(new request);
rep.reset(new reply);
auto f2 =
route.handle("/", std::move(req), std::move(rep)).then(
[] (std::unique_ptr<reply> rep) {
BOOST_REQUIRE_EQUAL((int )rep->_status, (int )reply::status_type::ok);
});
req.reset(new request);
rep.reset(new reply);
auto f3 =
route.handle("/api/abc", std::move(req), std::move(rep)).then(
[] (std::unique_ptr<reply> rep) {
});
req.reset(new request);
rep.reset(new reply);
auto f4 =
route.handle("/ap", std::move(req), std::move(rep)).then(
[] (std::unique_ptr<reply> rep) {
BOOST_REQUIRE_EQUAL((int )rep->_status,
(int )reply::status_type::not_found);
});
return when_all(std::move(f1), std::move(f2), std::move(f3), std::move(f4))
.then([] (std::tuple<future<>, future<>, future<>, future<>> fs) {
std::get<0>(fs).get();
std::get<1>(fs).get();
std::get<2>(fs).get();
std::get<3>(fs).get();
});
}
SEASTAR_TEST_CASE(test_transformer) {
request req;
content_replace cr("json");
sstring content = "hello-{{Protocol}}-xyz-{{Host}}";
cr.transform(content, req, "html");
BOOST_REQUIRE_EQUAL(content, "hello-{{Protocol}}-xyz-{{Host}}");
req._headers["Host"] = "localhost";
cr.transform(content, req, "json");
BOOST_REQUIRE_EQUAL(content, "hello-http-xyz-localhost");
return make_ready_future<>();
}