From: Marcin Siodelski Date: Wed, 11 Jan 2017 16:54:02 +0000 (+0100) Subject: [5099] Improved unit tests for the HttpListener. X-Git-Tag: trac1205_base~3^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=71b43715810ec5e6df430db93e03db3608e902c5;p=thirdparty%2Fkea.git [5099] Improved unit tests for the HttpListener. --- diff --git a/src/lib/http/connection.cc b/src/lib/http/connection.cc index 7aebb1de3b..8f12225429 100644 --- a/src/lib/http/connection.cc +++ b/src/lib/http/connection.cc @@ -100,7 +100,10 @@ HttpConnection::socketReadCallback(boost::system::error_code ec, size_t length) doRead(); } else { - request_->finalize(); + try { + request_->finalize(); + } catch (...) { + } HttpResponsePtr response = response_creator_->createHttpResponse(request_); output_buf_ = response->toString(); doWrite(); diff --git a/src/lib/http/connection_pool.cc b/src/lib/http/connection_pool.cc index eb06d3fca5..1d022192e8 100644 --- a/src/lib/http/connection_pool.cc +++ b/src/lib/http/connection_pool.cc @@ -22,6 +22,15 @@ HttpConnectionPool::stop(const HttpConnectionPtr& connection) { connection->close(); } +void +HttpConnectionPool::stopAll() { + for (auto connection = connections_.begin(); + connection != connections_.end(); + ++connection) { + (*connection)->close(); + } + connections_.clear(); +} } } diff --git a/src/lib/http/connection_pool.h b/src/lib/http/connection_pool.h index fa9462b3e5..1cfa7121b6 100644 --- a/src/lib/http/connection_pool.h +++ b/src/lib/http/connection_pool.h @@ -20,6 +20,8 @@ public: void stop(const HttpConnectionPtr& connection); + void stopAll(); + private: std::set connections_; diff --git a/src/lib/http/listener.cc b/src/lib/http/listener.cc index 4acd59cc37..d9d7274977 100644 --- a/src/lib/http/listener.cc +++ b/src/lib/http/listener.cc @@ -21,15 +21,26 @@ HttpListener::HttpListener(IOService& io_service, creator_factory_(creator_factory) { } +HttpListener::~HttpListener() { + stop(); +} + void HttpListener::start() { acceptor_.open(endpoint_); + acceptor_.setOption(HttpAcceptor::ReuseAddress(true)); acceptor_.bind(endpoint_); acceptor_.listen(); accept(); } +void +HttpListener::stop() { + connections_.stopAll(); + acceptor_.close(); +} + void HttpListener::accept() { HttpResponseCreatorPtr response_creator = creator_factory_->create(); diff --git a/src/lib/http/listener.h b/src/lib/http/listener.h index 6d8f5a2afe..fbc2071821 100644 --- a/src/lib/http/listener.h +++ b/src/lib/http/listener.h @@ -26,8 +26,12 @@ public: const unsigned short server_port, const HttpResponseCreatorFactoryPtr& creator_factory); + ~HttpListener(); + void start(); + void stop(); + private: void accept(); diff --git a/src/lib/http/tests/listener_unittests.cc b/src/lib/http/tests/listener_unittests.cc index c8f4e6fcd4..61485de0ef 100644 --- a/src/lib/http/tests/listener_unittests.cc +++ b/src/lib/http/tests/listener_unittests.cc @@ -114,25 +114,22 @@ public: close(); } - void startRequest() { + void startRequest(const std::string& request) { boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(SERVER_ADDRESS), SERVER_PORT); - socket_.async_connect(endpoint, [this](const boost::system::error_code& ec) { + socket_.async_connect(endpoint, + [this, request](const boost::system::error_code& ec) { if (ec) { ADD_FAILURE() << "error occurred while connecting: " << ec.message(); io_service_.stop(); } - sendRequest(); + sendRequest(request); }); } - void sendRequest() { - const std::string request = "POST /foo/bar HTTP/1.1\r\n" - "Content-Type: application/json\r\n" - "Content-Length: 3\r\n\r\n" - "{ }"; + void sendRequest(const std::string& request) { sendPartialRequest(request); } @@ -215,19 +212,26 @@ public: HttpListenerTest() : io_service_(), factory_(new TestHttpResponseCreatorFactory()), - test_timer_(io_service_) { + test_timer_(io_service_), clients_() { test_timer_.setup(boost::bind(&HttpListenerTest::timeoutHandler, this), TEST_TIMEOUT, IntervalTimer::ONE_SHOT); } + ~HttpListenerTest() { + for (auto client = clients_.begin(); client != clients_.end(); + ++client) { + (*client)->close(); + } + } + /// @brief Connect to the endpoint. /// /// This method creates HttpClient instance and retains it in the clients_ /// list. - void startRequest() { + void startRequest(const std::string& request) { HttpClientPtr client(new HttpClient(io_service_)); clients_.push_back(client); - clients_.back()->startRequest(); + clients_.back()->startRequest(request); } /// @brief Callback function invoke upon test timeout. @@ -250,10 +254,15 @@ public: }; TEST_F(HttpListenerTest, listen) { + const std::string request = "POST /foo/bar HTTP/1.1\r\n" + "Content-Type: application/json\r\n" + "Content-Length: 3\r\n\r\n" + "{ }"; + HttpListener listener(io_service_, IOAddress(SERVER_ADDRESS), SERVER_PORT, factory_); ASSERT_NO_THROW(listener.start()); - ASSERT_NO_THROW(startRequest()); + ASSERT_NO_THROW(startRequest(request)); ASSERT_NO_THROW(io_service_.run()); ASSERT_EQ(1, clients_.size()); HttpClientPtr client = *clients_.begin(); @@ -263,6 +272,31 @@ TEST_F(HttpListenerTest, listen) { "Date: Tue, 19 Dec 2016 18:53:35 GMT\r\n" "\r\n", client->getResponse()); + listener.stop(); + io_service_.poll(); +} + +TEST_F(HttpListenerTest, badRequest) { + const std::string request = "POST /foo/bar HTTP/1.1\r\n" + "Content-Type: foo\r\n" + "Content-Length: 3\r\n\r\n" + "{ }"; + + HttpListener listener(io_service_, IOAddress(SERVER_ADDRESS), SERVER_PORT, + factory_); + ASSERT_NO_THROW(listener.start()); + ASSERT_NO_THROW(startRequest(request)); + ASSERT_NO_THROW(io_service_.run()); + ASSERT_EQ(1, clients_.size()); + HttpClientPtr client = *clients_.begin(); + ASSERT_TRUE(client); + EXPECT_EQ("HTTP/1.1 400 Bad Request\r\n" + "Content-Length: 40\r\n" + "Content-Type: application/json\r\n" + "Date: Tue, 19 Dec 2016 18:53:35 GMT\r\n" + "\r\n" + "{ \"result\": 400, \"text\": \"Bad Request\" }", + client->getResponse()); } }