1 #include "assert.hpp"
2 #include "client_http.hpp"
3 #include "server_http.hpp"
4 #include <iostream>
5
6 using namespace std;
7 using namespace SimpleWeb;
8
9 class ServerTest : public ServerBase<HTTP> {
10 public:
ServerTest()11 ServerTest() : ServerBase<HTTP>::ServerBase(8080) {}
12
accept()13 void accept() noexcept override {}
14
parse_request_test()15 void parse_request_test() {
16 auto session = std::make_shared<Session>(static_cast<size_t>(-1), create_connection(*io_service));
17
18 std::ostream stream(&session->request->content.streambuf);
19 stream << "GET /test/ HTTP/1.1\r\n";
20 stream << "TestHeader: test\r\n";
21 stream << "TestHeader2:test2\r\n";
22 stream << "TestHeader3:test3a\r\n";
23 stream << "TestHeader3:test3b\r\n";
24 stream << "\r\n";
25
26 ASSERT(RequestMessage::parse(session->request->content, session->request->method, session->request->path,
27 session->request->query_string, session->request->http_version, session->request->header));
28
29 ASSERT(session->request->method == "GET");
30 ASSERT(session->request->path == "/test/");
31 ASSERT(session->request->http_version == "1.1");
32
33 ASSERT(session->request->header.size() == 4);
34 auto header_it = session->request->header.find("TestHeader");
35 ASSERT(header_it != session->request->header.end() && header_it->second == "test");
36 header_it = session->request->header.find("TestHeader2");
37 ASSERT(header_it != session->request->header.end() && header_it->second == "test2");
38
39 header_it = session->request->header.find("testheader");
40 ASSERT(header_it != session->request->header.end() && header_it->second == "test");
41 header_it = session->request->header.find("testheader2");
42 ASSERT(header_it != session->request->header.end() && header_it->second == "test2");
43
44 auto range = session->request->header.equal_range("testheader3");
45 auto first = range.first;
46 auto second = first;
47 ++second;
48 ASSERT(range.first != session->request->header.end() && range.second != session->request->header.end() &&
49 ((first->second == "test3a" && second->second == "test3b") ||
50 (first->second == "test3b" && second->second == "test3a")));
51 }
52 };
53
54 class ClientTest : public ClientBase<HTTP> {
55 public:
ClientTest(const std::string & server_port_path)56 ClientTest(const std::string &server_port_path) : ClientBase<HTTP>::ClientBase(server_port_path, 80) {}
57
create_connection()58 std::shared_ptr<Connection> create_connection() noexcept override {
59 return nullptr;
60 }
61
connect(const std::shared_ptr<Session> &)62 void connect(const std::shared_ptr<Session> &) noexcept override {}
63
parse_response_header_test()64 void parse_response_header_test() {
65 std::shared_ptr<Response> response(new Response(static_cast<size_t>(-1), nullptr));
66
67 ostream stream(&response->streambuf);
68 stream << "HTTP/1.1 200 OK\r\n";
69 stream << "TestHeader: test\r\n";
70 stream << "TestHeader2: test2\r\n";
71 stream << "TestHeader3:test3a\r\n";
72 stream << "TestHeader3:test3b\r\n";
73 stream << "TestHeader4:\r\n";
74 stream << "TestHeader5: \r\n";
75 stream << "TestHeader6: \r\n";
76 stream << "\r\n";
77
78 ASSERT(ResponseMessage::parse(response->content, response->http_version, response->status_code, response->header));
79
80 ASSERT(response->http_version == "1.1");
81 ASSERT(response->status_code == "200 OK");
82
83 ASSERT(response->header.size() == 7);
84 auto header_it = response->header.find("TestHeader");
85 ASSERT(header_it != response->header.end() && header_it->second == "test");
86 header_it = response->header.find("TestHeader2");
87 ASSERT(header_it != response->header.end() && header_it->second == "test2");
88
89 header_it = response->header.find("testheader");
90 ASSERT(header_it != response->header.end() && header_it->second == "test");
91 header_it = response->header.find("testheader2");
92 ASSERT(header_it != response->header.end() && header_it->second == "test2");
93
94 auto range = response->header.equal_range("testheader3");
95 auto first = range.first;
96 auto second = first;
97 ++second;
98 ASSERT(range.first != response->header.end() && range.second != response->header.end() &&
99 ((first->second == "test3a" && second->second == "test3b") ||
100 (first->second == "test3b" && second->second == "test3a")));
101
102 header_it = response->header.find("TestHeader4");
103 ASSERT(header_it != response->header.end() && header_it->second == "");
104 header_it = response->header.find("TestHeader5");
105 ASSERT(header_it != response->header.end() && header_it->second == "");
106 header_it = response->header.find("TestHeader6");
107 ASSERT(header_it != response->header.end() && header_it->second == "");
108 }
109 };
110
main()111 int main() {
112 ASSERT(case_insensitive_equal("Test", "tesT"));
113 ASSERT(case_insensitive_equal("tesT", "test"));
114 ASSERT(!case_insensitive_equal("test", "tseT"));
115 CaseInsensitiveEqual equal;
116 ASSERT(equal("Test", "tesT"));
117 ASSERT(equal("tesT", "test"));
118 ASSERT(!equal("test", "tset"));
119 CaseInsensitiveHash hash;
120 ASSERT(hash("Test") == hash("tesT"));
121 ASSERT(hash("tesT") == hash("test"));
122 ASSERT(hash("test") != hash("tset"));
123
124 auto percent_decoded = "testing æøå !#$&'()*+,/:;=?@[]123-._~\r\n";
125 auto percent_encoded = "testing%20%C3%A6%C3%B8%C3%A5%20%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D123-._~%0D%0A";
126 ASSERT(Percent::encode(percent_decoded) == percent_encoded);
127 ASSERT(Percent::decode(percent_encoded) == percent_decoded);
128 ASSERT(Percent::decode(Percent::encode(percent_decoded)) == percent_decoded);
129
130 SimpleWeb::CaseInsensitiveMultimap fields = {{"test1", "æøå"}, {"test2", "!#$&'()*+,/:;=?@[]"}};
131 auto query_string1 = "test1=%C3%A6%C3%B8%C3%A5&test2=%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D";
132 auto query_string2 = "test2=%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D&test1=%C3%A6%C3%B8%C3%A5";
133 auto query_string_result = QueryString::create(fields);
134 ASSERT(query_string_result == query_string1 || query_string_result == query_string2);
135 auto fields_result1 = QueryString::parse(query_string1);
136 auto fields_result2 = QueryString::parse(query_string2);
137 ASSERT(fields_result1 == fields_result2 && fields_result1 == fields);
138
139 auto serverTest = make_shared<ServerTest>();
140 serverTest->io_service = std::make_shared<io_context>();
141
142 serverTest->parse_request_test();
143
144 {
145 ClientTest clientTest("test.org");
146 ASSERT(clientTest.host == "test.org");
147 ASSERT(clientTest.port == 80);
148 clientTest.parse_response_header_test();
149 }
150
151 {
152 ClientTest clientTest("test.org:8080");
153 ASSERT(clientTest.host == "test.org");
154 ASSERT(clientTest.port == 8080);
155 }
156
157 {
158 ClientTest clientTest("test.org:test");
159 ASSERT(clientTest.host == "test.org");
160 ASSERT(clientTest.port == 80);
161 }
162
163 {
164 ClientTest clientTest("[::1]");
165 ASSERT(clientTest.host == "::1");
166 ASSERT(clientTest.port == 80);
167 }
168
169 {
170 ClientTest clientTest("[::1]:8080");
171 ASSERT(clientTest.host == "::1");
172 ASSERT(clientTest.port == 8080);
173 }
174
175
176 io_context io_service;
177 asio::ip::tcp::socket socket(io_service);
178 SimpleWeb::Server<HTTP>::Request request(static_cast<size_t>(-1), nullptr);
179 {
180 request.query_string = "";
181 auto queries = request.parse_query_string();
182 ASSERT(queries.empty());
183 }
184 {
185 request.query_string = "=";
186 auto queries = request.parse_query_string();
187 ASSERT(queries.empty());
188 }
189 {
190 request.query_string = "=test";
191 auto queries = request.parse_query_string();
192 ASSERT(queries.empty());
193 }
194 {
195 request.query_string = "a=1%202%20%203&b=3+4&c&d=æ%25ø%26å%3F";
196 auto queries = request.parse_query_string();
197 {
198 auto range = queries.equal_range("a");
199 ASSERT(range.first != range.second);
200 ASSERT(range.first->second == "1 2 3");
201 }
202 {
203 auto range = queries.equal_range("b");
204 ASSERT(range.first != range.second);
205 ASSERT(range.first->second == "3 4");
206 }
207 {
208 auto range = queries.equal_range("c");
209 ASSERT(range.first != range.second);
210 ASSERT(range.first->second == "");
211 }
212 {
213 auto range = queries.equal_range("d");
214 ASSERT(range.first != range.second);
215 ASSERT(range.first->second == "æ%ø&å?");
216 }
217 }
218
219 {
220 SimpleWeb::CaseInsensitiveMultimap solution;
221 std::stringstream header;
222 auto parsed = SimpleWeb::HttpHeader::parse(header);
223 ASSERT(parsed == solution);
224 }
225 {
226 SimpleWeb::CaseInsensitiveMultimap solution = {{"Content-Type", "application/json"}};
227 std::stringstream header("Content-Type: application/json");
228 auto parsed = SimpleWeb::HttpHeader::parse(header);
229 ASSERT(parsed == solution);
230 }
231 {
232 SimpleWeb::CaseInsensitiveMultimap solution = {{"Content-Type", "application/json"}};
233 std::stringstream header("Content-Type: application/json\r");
234 auto parsed = SimpleWeb::HttpHeader::parse(header);
235 ASSERT(parsed == solution);
236 }
237 {
238 SimpleWeb::CaseInsensitiveMultimap solution = {{"Content-Type", "application/json"}};
239 std::stringstream header("Content-Type: application/json\r\n");
240 auto parsed = SimpleWeb::HttpHeader::parse(header);
241 ASSERT(parsed == solution);
242 }
243
244 {
245 {
246 SimpleWeb::CaseInsensitiveMultimap solution;
247 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("");
248 ASSERT(parsed == solution);
249 }
250 {
251 SimpleWeb::CaseInsensitiveMultimap solution = {{"a", ""}};
252 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a");
253 ASSERT(parsed == solution);
254 }
255 {
256 SimpleWeb::CaseInsensitiveMultimap solution = {{"a", ""}, {"b", ""}};
257 {
258 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a; b");
259 ASSERT(parsed == solution);
260 }
261 {
262 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a;b");
263 ASSERT(parsed == solution);
264 }
265 }
266 {
267 SimpleWeb::CaseInsensitiveMultimap solution = {{"a", ""}, {"b", "c"}};
268 {
269 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a; b=c");
270 ASSERT(parsed == solution);
271 }
272 {
273 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("a;b=c");
274 ASSERT(parsed == solution);
275 }
276 }
277 {
278 SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}};
279 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data");
280 ASSERT(parsed == solution);
281 }
282 {
283 SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"test", ""}};
284 {
285 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; test");
286 ASSERT(parsed == solution);
287 }
288 }
289 {
290 SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"name", "file"}};
291 {
292 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"file\"");
293 ASSERT(parsed == solution);
294 }
295 {
296 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=file");
297 ASSERT(parsed == solution);
298 }
299 }
300 {
301 SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"name", "file"}, {"filename", "filename.png"}};
302 {
303 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"file\"; filename=\"filename.png\"");
304 ASSERT(parsed == solution);
305 }
306 {
307 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data;name=\"file\";filename=\"filename.png\"");
308 ASSERT(parsed == solution);
309 }
310 {
311 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=file; filename=filename.png");
312 ASSERT(parsed == solution);
313 }
314 {
315 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data;name=file;filename=filename.png");
316 ASSERT(parsed == solution);
317 }
318 }
319 {
320 SimpleWeb::CaseInsensitiveMultimap solution = {{"form-data", ""}, {"name", "fi le"}, {"filename", "file name.png"}};
321 {
322 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"fi le\"; filename=\"file name.png\"");
323 ASSERT(parsed == solution);
324 }
325 {
326 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=\"fi%20le\"; filename=\"file%20name.png\"");
327 ASSERT(parsed == solution);
328 }
329 {
330 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=fi le; filename=file name.png");
331 ASSERT(parsed == solution);
332 }
333 {
334 auto parsed = SimpleWeb::HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse("form-data; name=fi%20le; filename=file%20name.png");
335 ASSERT(parsed == solution);
336 }
337 }
338 }
339
340 ASSERT(SimpleWeb::Date::to_string(std::chrono::system_clock::now()).size() == 29);
341 }
342