]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | ||
8 | // Test that header file is self-contained. | |
9 | #include <beast/http/rfc7230.hpp> | |
10 | ||
11 | #include <beast/http/detail/rfc7230.hpp> | |
12 | #include <beast/unit_test/suite.hpp> | |
13 | #include <string> | |
14 | #include <vector> | |
15 | ||
16 | #include <beast/core/detail/empty_base_optimization.hpp> | |
17 | ||
18 | namespace beast { | |
19 | namespace http { | |
20 | ||
21 | class rfc7230_test : public beast::unit_test::suite | |
22 | { | |
23 | public: | |
24 | static | |
25 | std::string | |
26 | fmt(std::string const& s) | |
27 | { | |
28 | return '\'' + s + '\''; | |
29 | } | |
30 | ||
31 | static | |
32 | std::string | |
33 | str(boost::string_ref const& s) | |
34 | { | |
35 | return std::string(s.data(), s.size()); | |
36 | } | |
37 | ||
38 | static | |
39 | std::string | |
40 | str(param_list const& c) | |
41 | { | |
42 | std::string s; | |
43 | for(auto const& p : c) | |
44 | { | |
45 | s.push_back(';'); | |
46 | s.append(str(p.first)); | |
47 | if(! p.second.empty()) | |
48 | { | |
49 | s.push_back('='); | |
50 | s.append(str(p.second)); | |
51 | } | |
52 | } | |
53 | return s; | |
54 | } | |
55 | ||
56 | void | |
57 | testParamList() | |
58 | { | |
59 | auto const ce = | |
60 | [&](std::string const& s) | |
61 | { | |
62 | auto const got = str(param_list{s}); | |
63 | BEAST_EXPECTS(got == s, fmt(got)); | |
64 | }; | |
65 | auto const cs = | |
66 | [&](std::string const& s, std::string const& good) | |
67 | { | |
68 | ce(good); | |
69 | auto const got = str(param_list{s}); | |
70 | ce(got); | |
71 | BEAST_EXPECTS(got == good, fmt(got)); | |
72 | }; | |
73 | auto const cq = | |
74 | [&](std::string const& s, std::string const& good) | |
75 | { | |
76 | auto const got = str(param_list{s}); | |
77 | BEAST_EXPECTS(got == good, fmt(got)); | |
78 | }; | |
79 | ||
80 | ce(""); | |
81 | ce(";x"); | |
82 | ce(";xy"); | |
83 | ce(";x;y"); | |
84 | ||
85 | ce(""); | |
86 | cs(" ;\t i =\t 1 \t", ";i=1"); | |
87 | cq("\t; \t xyz=1 ; ijk=\"q\\\"t\"", ";xyz=1;ijk=q\"t"); | |
88 | ce(";x;y"); | |
89 | ||
90 | // invalid strings | |
91 | cs(";", ""); | |
92 | cs(";,", ""); | |
93 | cq(";x=,", ""); | |
94 | cq(";xy=\"", ""); | |
95 | cq(";xy=\"\x7f", ""); | |
96 | cq(";xy=\"\\", ""); | |
97 | cq(";xy=\"\\\x01\"", ""); | |
98 | } | |
99 | ||
100 | static | |
101 | std::string | |
102 | str(ext_list const& ex) | |
103 | { | |
104 | std::string s; | |
105 | for(auto const& e : ex) | |
106 | { | |
107 | if(! s.empty()) | |
108 | s += ','; | |
109 | s.append(str(e.first)); | |
110 | s += str(e.second); | |
111 | } | |
112 | return s; | |
113 | } | |
114 | ||
115 | void | |
116 | testExtList() | |
117 | { | |
118 | auto const ce = | |
119 | [&](std::string const& s) | |
120 | { | |
121 | auto const got = str(ext_list{s}); | |
122 | BEAST_EXPECTS(got == s, fmt(got)); | |
123 | }; | |
124 | auto const cs = | |
125 | [&](std::string const& s, std::string const& good) | |
126 | { | |
127 | ce(good); | |
128 | auto const got = str(ext_list{s}); | |
129 | ce(got); | |
130 | BEAST_EXPECTS(got == good, fmt(got)); | |
131 | }; | |
132 | auto const cq = | |
133 | [&](std::string const& s, std::string const& good) | |
134 | { | |
135 | auto const got = str(ext_list{s}); | |
136 | BEAST_EXPECTS(got == good, fmt(got)); | |
137 | }; | |
138 | /* | |
139 | ext-basic_parsed_list = *( "," OWS ) ext *( OWS "," [ OWS ext ] ) | |
140 | ext = token param-basic_parsed_list | |
141 | param-basic_parsed_list = *( OWS ";" OWS param ) | |
142 | param = token OWS "=" OWS ( token / quoted-string ) | |
143 | */ | |
144 | cs(",", ""); | |
145 | cs(", ", ""); | |
146 | cs(",\t", ""); | |
147 | cs(", \t", ""); | |
148 | cs(" ", ""); | |
149 | cs(" ,", ""); | |
150 | cs("\t,", ""); | |
151 | cs("\t , \t", ""); | |
152 | cs(",,", ""); | |
153 | cs(" , \t,, \t,", ""); | |
154 | cs( "permessage-deflate; client_no_context_takeover; client_max_window_bits", | |
155 | "permessage-deflate;client_no_context_takeover;client_max_window_bits"); | |
156 | ||
157 | ce("a"); | |
158 | ce("ab"); | |
159 | ce("a,b"); | |
160 | cs(" a ", "a"); | |
161 | cs("\t a, b\t , c\t", "a,b,c"); | |
162 | ce("a;b"); | |
163 | ce("a;b;c"); | |
164 | ||
165 | cs("a; \t i\t=\t \t1\t ", "a;i=1"); | |
166 | ce("a;i=1;j=2;k=3"); | |
167 | ce("a;i=1;j=2;k=3,b;i=4;j=5;k=6"); | |
168 | ||
169 | cq("ab;x=\" \"", "ab;x= "); | |
170 | cq("ab;x=\"\\\"\"", "ab;x=\""); | |
171 | ||
172 | BEAST_EXPECT(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("A")); | |
173 | BEAST_EXPECT(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("b")); | |
174 | BEAST_EXPECT(! ext_list{"a,b;i=1,c;j=2;k=3"}.exists("d")); | |
175 | ||
176 | // invalid strings | |
177 | cs("i j", "i"); | |
178 | cs(";", ""); | |
179 | } | |
180 | ||
181 | static | |
182 | std::string | |
183 | str(token_list const& c) | |
184 | { | |
185 | bool first = true; | |
186 | std::string s; | |
187 | for(auto const& p : c) | |
188 | { | |
189 | if(! first) | |
190 | s.push_back(','); | |
191 | s.append(str(p)); | |
192 | first = false; | |
193 | } | |
194 | return s; | |
195 | } | |
196 | ||
197 | void | |
198 | testTokenList() | |
199 | { | |
200 | auto const ce = | |
201 | [&](std::string const& s) | |
202 | { | |
203 | auto const got = str(token_list{s}); | |
204 | BEAST_EXPECTS(got == s, fmt(got)); | |
205 | }; | |
206 | auto const cs = | |
207 | [&](std::string const& s, std::string const& good) | |
208 | { | |
209 | ce(good); | |
210 | auto const got = str(token_list{s}); | |
211 | ce(got); | |
212 | BEAST_EXPECTS(got == good, fmt(got)); | |
213 | }; | |
214 | ||
215 | cs("", ""); | |
216 | cs(" ", ""); | |
217 | cs(" ", ""); | |
218 | cs("\t", ""); | |
219 | cs(" \t ", ""); | |
220 | cs(",", ""); | |
221 | cs(",,", ""); | |
222 | cs(" ,", ""); | |
223 | cs(" , ,", ""); | |
224 | cs(" x", "x"); | |
225 | cs(" \t x", "x"); | |
226 | cs("x ", "x"); | |
227 | cs("x \t", "x"); | |
228 | cs(" \t x \t ", "x"); | |
229 | ce("x,y"); | |
230 | cs("x ,\ty ", "x,y"); | |
231 | cs("x, y, z", "x,y,z"); | |
232 | ||
233 | BEAST_EXPECT(token_list{"a,b,c"}.exists("A")); | |
234 | BEAST_EXPECT(token_list{"a,b,c"}.exists("b")); | |
235 | BEAST_EXPECT(! token_list{"a,b,c"}.exists("d")); | |
236 | ||
237 | // invalid | |
238 | cs("x y", "x"); | |
239 | } | |
240 | ||
241 | template<class Policy> | |
242 | static | |
243 | std::vector<std::string> | |
244 | to_vector(boost::string_ref const& in) | |
245 | { | |
246 | std::vector<std::string> v; | |
247 | detail::basic_parsed_list<Policy> list{in}; | |
248 | for(auto const& s : | |
249 | detail::basic_parsed_list<Policy>{in}) | |
250 | v.emplace_back(s.data(), s.size()); | |
251 | return v; | |
252 | } | |
253 | ||
254 | template<class Policy> | |
255 | void | |
256 | validate(boost::string_ref const& in, | |
257 | std::vector<std::string> const& v) | |
258 | { | |
259 | BEAST_EXPECT(to_vector<Policy>(in) == v); | |
260 | } | |
261 | ||
262 | template<class Policy> | |
263 | void | |
264 | good(boost::string_ref const& in) | |
265 | { | |
266 | BEAST_EXPECT(validate_list( | |
267 | detail::basic_parsed_list<Policy>{in})); | |
268 | } | |
269 | ||
270 | template<class Policy> | |
271 | void | |
272 | good(boost::string_ref const& in, | |
273 | std::vector<std::string> const& v) | |
274 | { | |
275 | BEAST_EXPECT(validate_list( | |
276 | detail::basic_parsed_list<Policy>{in})); | |
277 | validate<Policy>(in, v); | |
278 | } | |
279 | ||
280 | template<class Policy> | |
281 | void | |
282 | bad(boost::string_ref const& in) | |
283 | { | |
284 | BEAST_EXPECT(! validate_list( | |
285 | detail::basic_parsed_list<Policy>{in})); | |
286 | } | |
287 | ||
288 | void | |
289 | testOptTokenList() | |
290 | { | |
291 | /* | |
292 | #token = [ ( "," / token ) *( OWS "," [ OWS token ] ) ] | |
293 | */ | |
294 | using type = detail::opt_token_list_policy; | |
295 | ||
296 | good<type>("", {}); | |
297 | good<type>(" ", {}); | |
298 | good<type>("\t", {}); | |
299 | good<type>(" \t", {}); | |
300 | good<type>(",", {}); | |
301 | good<type>(",,", {}); | |
302 | good<type>(", ,", {}); | |
303 | good<type>(",\t,", {}); | |
304 | good<type>(", \t,", {}); | |
305 | good<type>(", \t, ", {}); | |
306 | good<type>(", \t,\t", {}); | |
307 | good<type>(", \t, \t", {}); | |
308 | ||
309 | good<type>("x", {"x"}); | |
310 | good<type>(" x", {"x"}); | |
311 | good<type>("x,,", {"x"}); | |
312 | good<type>("x, ,", {"x"}); | |
313 | good<type>("x,, ", {"x"}); | |
314 | good<type>("x,,,", {"x"}); | |
315 | ||
316 | good<type>("x,y", {"x","y"}); | |
317 | good<type>("x ,y", {"x","y"}); | |
318 | good<type>("x\t,y", {"x","y"}); | |
319 | good<type>("x \t,y", {"x","y"}); | |
320 | good<type>(" x,y", {"x","y"}); | |
321 | good<type>(" x,y ", {"x","y"}); | |
322 | good<type>(",x,y", {"x","y"}); | |
323 | good<type>("x,y,", {"x","y"}); | |
324 | good<type>(",,x,y", {"x","y"}); | |
325 | good<type>(",x,,y", {"x","y"}); | |
326 | good<type>(",x,y,", {"x","y"}); | |
327 | good<type>("x ,, y", {"x","y"}); | |
328 | good<type>("x , ,y", {"x","y"}); | |
329 | ||
330 | good<type>("x,y,z", {"x","y","z"}); | |
331 | ||
332 | bad<type>("("); | |
333 | bad<type>("x("); | |
334 | bad<type>("(x"); | |
335 | bad<type>(",("); | |
336 | bad<type>("(,"); | |
337 | bad<type>("x,("); | |
338 | bad<type>("(,x"); | |
339 | bad<type>("x y"); | |
340 | } | |
341 | ||
342 | void | |
343 | run() | |
344 | { | |
345 | testOptTokenList(); | |
346 | #if 0 | |
347 | testParamList(); | |
348 | testExtList(); | |
349 | testTokenList(); | |
350 | #endif | |
351 | } | |
352 | }; | |
353 | ||
354 | BEAST_DEFINE_TESTSUITE(rfc7230,http,beast); | |
355 | ||
356 | } // http | |
357 | } // beast |