1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
// Copyright (C) 2016-2017 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <cc/data.h>
#include <http/http_types.h>
#include <http/response_json.h>
#include <http/tests/response_test.h>
#include <gtest/gtest.h>
#include <sstream>
using namespace isc::data;
using namespace isc::http;
using namespace isc::http::test;
namespace {
/// @brief Response type used in tests.
typedef TestHttpResponseBase<HttpResponseJson> TestHttpResponseJson;
/// @brief Test fixture class for @ref HttpResponseJson.
class HttpResponseJsonTest : public ::testing::Test {
public:
/// @brief Constructor.
///
/// Initializes the following class members:
/// - json_string_ - which is a pretty formatted JSON content,
/// - json_ - A structure of Element objects representing the JSON,
/// - json_string_from_json_ - which is a JSON text converted back from
/// the json_ data structure. It is the same content as json_string_
/// but has different whitespaces.
HttpResponseJsonTest()
: json_(), json_string_(), json_string_from_json_() {
json_string_ =
"["
" {"
" \"pid\": 8080,"
" \"status\": 10,"
" \"comment\": \"Nice comment from 8080\""
" },"
" {"
" \"pid\": 8081,"
" \"status\": 12,"
" \"comment\": \"A comment from 8081\""
" }"
"]";
json_ = Element::fromJSON(json_string_);
json_string_from_json_ = json_->str();
}
/// @brief Test that the response format is correct.
///
/// @param status_code HTTP status code for which the response should
/// be tested.
/// @param status_message HTTP status message.
void testGenericResponse(const HttpStatusCode& status_code,
const std::string& status_message) {
TestHttpResponseJson response(HttpVersion(1, 0), status_code);
std::ostringstream status_message_json;
// Build the expected content.
status_message_json << "{ \"result\": "
<< static_cast<uint16_t>(status_code)
<< ", \"text\": "
<< "\"" << status_message << "\" }";
std::ostringstream response_string;
response_string <<
"HTTP/1.0 " << static_cast<uint16_t>(status_code) << " "
<< status_message << "\r\n";
// The content must only be generated for error codes.
if (HttpResponse::isClientError(status_code) ||
HttpResponse::isServerError(status_code)) {
response_string << "Content-Length: " << status_message_json.str().size()
<< "\r\n";
} else {
response_string << "Content-Length: 0\r\n";
}
// Content-Type and Date are automatically included.
response_string << "Content-Type: application/json\r\n"
"Date: " << response.getDateHeaderValue() << "\r\n\r\n";
if (HttpResponse::isClientError(status_code) ||
HttpResponse::isServerError(status_code)) {
response_string << status_message_json.str();
}
// Check that the output is as expected.
EXPECT_EQ(response_string.str(), response.toString());
}
/// @brief JSON content represented as structure of Element objects.
ConstElementPtr json_;
/// @brief Pretty formatted JSON content.
std::string json_string_;
/// @brief JSON content parsed back from json_ structure.
std::string json_string_from_json_;
};
// Test that the response with custom JSON content is generated properly.
TEST_F(HttpResponseJsonTest, responseWithContent) {
TestHttpResponseJson response(HttpVersion(1, 1), HttpStatusCode::OK);
ASSERT_NO_THROW(response.setBodyAsJson(json_));
std::ostringstream response_string;
response_string <<
"HTTP/1.1 200 OK\r\n"
"Content-Length: " << json_string_from_json_.length() << "\r\n"
"Content-Type: application/json\r\n"
"Date: " << response.getDateHeaderValue() << "\r\n\r\n"
<< json_string_from_json_;
EXPECT_EQ(response_string.str(), response.toString());
}
// Test that generic responses are created properly.
TEST_F(HttpResponseJsonTest, genericResponse) {
testGenericResponse(HttpStatusCode::OK, "OK");
testGenericResponse(HttpStatusCode::CREATED, "Created");
testGenericResponse(HttpStatusCode::ACCEPTED, "Accepted");
testGenericResponse(HttpStatusCode::NO_CONTENT, "No Content");
testGenericResponse(HttpStatusCode::MULTIPLE_CHOICES,
"Multiple Choices");
testGenericResponse(HttpStatusCode::MOVED_PERMANENTLY,
"Moved Permanently");
testGenericResponse(HttpStatusCode::MOVED_TEMPORARILY,
"Moved Temporarily");
testGenericResponse(HttpStatusCode::NOT_MODIFIED, "Not Modified");
testGenericResponse(HttpStatusCode::BAD_REQUEST, "Bad Request");
testGenericResponse(HttpStatusCode::UNAUTHORIZED, "Unauthorized");
testGenericResponse(HttpStatusCode::FORBIDDEN, "Forbidden");
testGenericResponse(HttpStatusCode::NOT_FOUND, "Not Found");
testGenericResponse(HttpStatusCode::REQUEST_TIMEOUT, "Request Timeout");
testGenericResponse(HttpStatusCode::INTERNAL_SERVER_ERROR,
"Internal Server Error");
testGenericResponse(HttpStatusCode::NOT_IMPLEMENTED, "Not Implemented");
testGenericResponse(HttpStatusCode::BAD_GATEWAY, "Bad Gateway");
testGenericResponse(HttpStatusCode::SERVICE_UNAVAILABLE,
"Service Unavailable");
}
}
|