From: Marcin Siodelski Date: Mon, 13 May 2019 14:52:21 +0000 (+0200) Subject: [#599,!320] Implemented unit test for premature timeout. X-Git-Tag: Kea-1.6.0-beta~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3e38736cc03176beaa3b426ee44ac0b3b2cbd22;p=thirdparty%2Fkea.git [#599,!320] Implemented unit test for premature timeout. --- diff --git a/src/lib/http/client.cc b/src/lib/http/client.cc index c45f1fd435..c2c6b30f5f 100644 --- a/src/lib/http/client.cc +++ b/src/lib/http/client.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/src/lib/http/tests/server_client_unittests.cc b/src/lib/http/tests/server_client_unittests.cc index fe88cc0601..1478f5201f 100644 --- a/src/lib/http/tests/server_client_unittests.cc +++ b/src/lib/http/tests/server_client_unittests.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -1249,6 +1249,67 @@ TEST_F(HttpClientTest, clientRequestTimeout) { ASSERT_NO_THROW(runIOService()); } +// This test verifies the behavior of the HTTP client when the premature +// (and unexpected) timeout occurs. The premature timeout may be caused +// by the system clock move. +TEST_F(HttpClientTest, clientRequestLateStart) { + // Start the server. + ASSERT_NO_THROW(listener_.start()); + + // Create the client. + HttpClient client(io_service_); + + // Specify the URL of the server. + Url url("http://127.0.0.1:18123"); + + unsigned cb_num = 0; + + // Generate first request. + PostHttpRequestJsonPtr request1 = createRequest("partial-response", true); + HttpResponseJsonPtr response1(new HttpResponseJson()); + + // Use very short timeout to make sure that it occurs before we actually + // run the transaction. + ASSERT_NO_THROW(client.asyncSendRequest(url, request1, response1, + [](const boost::system::error_code& ec, + const HttpResponsePtr& response, + const std::string&) { + // In this particular case we know exactly the type of the + // IO error returned, because the client explicitly sets this + // error code. + EXPECT_TRUE(ec.value() == boost::asio::error::timed_out); + // There should be no response returned. + EXPECT_FALSE(response); + }, HttpClient::RequestTimeout(1))); + + // This waits for 3ms to make sure that the timeout occurs before we + // run the transaction. This leads to an unusual situation that the + // transaction state is reset as a result of the timeout but the + // transaction is alive. We want to make sure that the client can + // gracefully deal with this situation. + usleep(3000); + + // Run the transaction and hope it will gracefully tear down. + ASSERT_NO_THROW(runIOService(100)); + + // Now try to send another request to make sure that the client + // is healthy. + PostHttpRequestJsonPtr request2 = createRequest("sequence", 1); + HttpResponseJsonPtr response2(new HttpResponseJson()); + ASSERT_NO_THROW(client.asyncSendRequest(url, request2, response2, + [this](const boost::system::error_code& ec, + const HttpResponsePtr&, + const std::string&) { + io_service_.stop(); + + // Everything should be ok. + EXPECT_TRUE(ec.value() == 0); + })); + + // Actually trigger the requests. + ASSERT_NO_THROW(runIOService()); +} + // Test that client times out when connection takes too long. TEST_F(HttpClientTest, clientConnectTimeout) { // Start the server.