response_unittests.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <http/date_time.h>
  8. #include <http/http_types.h>
  9. #include <http/response.h>
  10. #include <http/tests/response_test.h>
  11. #include <gtest/gtest.h>
  12. #include <sstream>
  13. #include <string>
  14. using namespace boost::posix_time;
  15. using namespace isc::http;
  16. using namespace isc::http::test;
  17. namespace {
  18. /// @brief Response type used in tests.
  19. typedef TestHttpResponseBase<HttpResponse> TestHttpResponse;
  20. /// @brief Test fixture class for @ref HttpResponse.
  21. class HttpResponseTest : public ::testing::Test {
  22. public:
  23. /// @brief Checks if the format of the response is correct.
  24. ///
  25. /// @param status_code HTTP status code in the response.
  26. /// @param status_message HTTP status message in the response.
  27. void testResponse(const HttpStatusCode& status_code,
  28. const std::string& status_message) {
  29. // Create the response. Because we're using derived class
  30. // it returns the fixed value of the Date header, which is
  31. // very useful in unit tests.
  32. TestHttpResponse response(HttpVersion(1, 0), status_code);
  33. response.addHeader("Content-Type", "text/html");
  34. std::ostringstream response_string;
  35. response_string << "HTTP/1.0 " << static_cast<uint16_t>(status_code)
  36. << " " << status_message << "\r\n"
  37. << "Content-Type: text/html\r\n"
  38. << "Date: " << response.getDateHeaderValue() << "\r\n\r\n";
  39. EXPECT_EQ(response_string.str(), response.toString());
  40. }
  41. };
  42. // Test the case of HTTP OK message.
  43. TEST_F(HttpResponseTest, responseOK) {
  44. // Include HTML body.
  45. const std::string sample_body =
  46. "<html>"
  47. "<head><title>Kea page title</title></head>"
  48. "<body><h1>Some header</h1></body>"
  49. "</html>";
  50. // Create the message and add some headers.
  51. TestHttpResponse response(HttpVersion(1, 0), HttpStatusCode::OK);
  52. response.addHeader("Content-Type", "text/html");
  53. response.addHeader("Host", "kea.example.org");
  54. response.setBody(sample_body);
  55. // Create a string holding expected response. Note that the Date
  56. // is a fixed value returned by the customized TestHttpResponse
  57. // classs.
  58. std::ostringstream response_string;
  59. response_string <<
  60. "HTTP/1.0 200 OK\r\n"
  61. "Content-Length: " << sample_body.length() << "\r\n"
  62. "Content-Type: text/html\r\n"
  63. "Date: " << response.getDateHeaderValue() << "\r\n"
  64. "Host: kea.example.org\r\n\r\n" << sample_body;
  65. EXPECT_EQ(response_string.str(), response.toString());
  66. }
  67. // Test generic responses for various status codes.
  68. TEST_F(HttpResponseTest, genericResponse) {
  69. testResponse(HttpStatusCode::OK, "OK");
  70. testResponse(HttpStatusCode::CREATED, "Created");
  71. testResponse(HttpStatusCode::ACCEPTED, "Accepted");
  72. testResponse(HttpStatusCode::NO_CONTENT, "No Content");
  73. testResponse(HttpStatusCode::MULTIPLE_CHOICES, "Multiple Choices");
  74. testResponse(HttpStatusCode::MOVED_PERMANENTLY, "Moved Permanently");
  75. testResponse(HttpStatusCode::MOVED_TEMPORARILY, "Moved Temporarily");
  76. testResponse(HttpStatusCode::NOT_MODIFIED, "Not Modified");
  77. testResponse(HttpStatusCode::BAD_REQUEST, "Bad Request");
  78. testResponse(HttpStatusCode::UNAUTHORIZED, "Unauthorized");
  79. testResponse(HttpStatusCode::FORBIDDEN, "Forbidden");
  80. testResponse(HttpStatusCode::NOT_FOUND, "Not Found");
  81. testResponse(HttpStatusCode::REQUEST_TIMEOUT, "Request Timeout");
  82. testResponse(HttpStatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error");
  83. testResponse(HttpStatusCode::NOT_IMPLEMENTED, "Not Implemented");
  84. testResponse(HttpStatusCode::BAD_GATEWAY, "Bad Gateway");
  85. testResponse(HttpStatusCode::SERVICE_UNAVAILABLE, "Service Unavailable");
  86. }
  87. // Test if the class correctly identifies client errors.
  88. TEST_F(HttpResponseTest, isClientError) {
  89. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::OK));
  90. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::CREATED));
  91. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::ACCEPTED));
  92. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::NO_CONTENT));
  93. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::MULTIPLE_CHOICES));
  94. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::MOVED_PERMANENTLY));
  95. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::MOVED_TEMPORARILY));
  96. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::NOT_MODIFIED));
  97. EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::BAD_REQUEST));
  98. EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::UNAUTHORIZED));
  99. EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::FORBIDDEN));
  100. EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::NOT_FOUND));
  101. EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::REQUEST_TIMEOUT));
  102. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::INTERNAL_SERVER_ERROR));
  103. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::NOT_IMPLEMENTED));
  104. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::BAD_GATEWAY));
  105. EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::SERVICE_UNAVAILABLE));
  106. }
  107. // Test if the class correctly identifies server errors.
  108. TEST_F(HttpResponseTest, isServerError) {
  109. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::OK));
  110. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::CREATED));
  111. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::ACCEPTED));
  112. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::NO_CONTENT));
  113. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::MULTIPLE_CHOICES));
  114. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::MOVED_PERMANENTLY));
  115. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::MOVED_TEMPORARILY));
  116. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::NOT_MODIFIED));
  117. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::BAD_REQUEST));
  118. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::UNAUTHORIZED));
  119. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::FORBIDDEN));
  120. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::NOT_FOUND));
  121. EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::REQUEST_TIMEOUT));
  122. EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::INTERNAL_SERVER_ERROR));
  123. EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::NOT_IMPLEMENTED));
  124. EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::BAD_GATEWAY));
  125. EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::SERVICE_UNAVAILABLE));
  126. }
  127. // Test that the generated time value, being included in the Date
  128. // header, is correct.
  129. TEST_F(HttpResponseTest, getDateHeaderValue) {
  130. // Create a response and retrieve the value to be included in the
  131. // Date header. This value should hold a current time in the
  132. // RFC1123 format.
  133. TestHttpResponse response(HttpVersion(1, 0), HttpStatusCode::OK);
  134. std::string generated_date = response.generateDateHeaderValue();
  135. // Use our date/time utilities to parse this value into the ptime.
  136. HttpDateTime parsed_time = HttpDateTime::fromRfc1123(generated_date);
  137. // Now that we have it converted back, we can check how far this
  138. // value is from the current time. To be on the safe side, we check
  139. // that it is not later than 10 seconds apart, rather than checking
  140. // it for equality. In fact, checking it for equality would almost
  141. // certainly cause an error. Especially on a virtual machine.
  142. time_duration parsed_to_current =
  143. microsec_clock::universal_time() - parsed_time.getPtime();
  144. EXPECT_LT(parsed_to_current.seconds(), 10);
  145. }
  146. }