]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5099] Improved unit tests for the HttpListener.
authorMarcin Siodelski <marcin@isc.org>
Wed, 11 Jan 2017 16:54:02 +0000 (17:54 +0100)
committerMarcin Siodelski <marcin@isc.org>
Wed, 11 Jan 2017 16:54:02 +0000 (17:54 +0100)
src/lib/http/connection.cc
src/lib/http/connection_pool.cc
src/lib/http/connection_pool.h
src/lib/http/listener.cc
src/lib/http/listener.h
src/lib/http/tests/listener_unittests.cc

index 7aebb1de3bb1e6aec288f68776273ee2fa401225..8f1222542955b5a935c4de084b9e52f0634a3eb3 100644 (file)
@@ -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();
index eb06d3fca5180f73b1ad484fde792c1cba5d2cb9..1d022192e83fb9b4a288fe208b9da12d4861f190 100644 (file)
@@ -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();
+}
 
 }
 }
index fa9462b3e549739329f2e4d4c47f796e95a6207f..1cfa7121b655ea018919d91b9f811aed64afef82 100644 (file)
@@ -20,6 +20,8 @@ public:
 
     void stop(const HttpConnectionPtr& connection);
 
+    void stopAll();
+
 private:
 
     std::set<HttpConnectionPtr> connections_;
index 4acd59cc377f870758de1470d0d9a0fdafc07701..d9d727497746d5b86e4426846e0cf56c91d5b8b0 100644 (file)
@@ -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();
index 6d8f5a2afe183602fe5323de6010d98ed1a56fa0..fbc2071821cd8b82d2467ad340563b5ebfeed1b9 100644 (file)
@@ -26,8 +26,12 @@ public:
                  const unsigned short server_port,
                  const HttpResponseCreatorFactoryPtr& creator_factory);
 
+    ~HttpListener();
+
     void start();
 
+    void stop();
+
 private:
 
     void accept();
index c8f4e6fcd490c5bf0fc825bafa0a540865a30c25..61485de0efdf5348888c603063e6795d3afef64e 100644 (file)
@@ -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());
 }
 
 }