2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/Uri.h>
18 #include <folly/portability/GTest.h>
20 #include <boost/algorithm/string.hpp>
21 #include <glog/logging.h>
24 using namespace folly;
28 fbstring s("http://www.facebook.com/hello/world?query#fragment");
30 EXPECT_EQ("http", u.scheme());
31 EXPECT_EQ("", u.username());
32 EXPECT_EQ("", u.password());
33 EXPECT_EQ("www.facebook.com", u.host());
34 EXPECT_EQ(0, u.port());
35 EXPECT_EQ("www.facebook.com", u.authority());
36 EXPECT_EQ("/hello/world", u.path());
37 EXPECT_EQ("query", u.query());
38 EXPECT_EQ("fragment", u.fragment());
39 EXPECT_EQ(s, u.fbstr()); // canonical
43 fbstring s("http://www.facebook.com:8080/hello/world?query#fragment");
45 EXPECT_EQ("http", u.scheme());
46 EXPECT_EQ("", u.username());
47 EXPECT_EQ("", u.password());
48 EXPECT_EQ("www.facebook.com", u.host());
49 EXPECT_EQ(8080, u.port());
50 EXPECT_EQ("www.facebook.com:8080", u.authority());
51 EXPECT_EQ("/hello/world", u.path());
52 EXPECT_EQ("query", u.query());
53 EXPECT_EQ("fragment", u.fragment());
54 EXPECT_EQ(s, u.fbstr()); // canonical
58 fbstring s("http://127.0.0.1:8080/hello/world?query#fragment");
60 EXPECT_EQ("http", u.scheme());
61 EXPECT_EQ("", u.username());
62 EXPECT_EQ("", u.password());
63 EXPECT_EQ("127.0.0.1", u.host());
64 EXPECT_EQ(8080, u.port());
65 EXPECT_EQ("127.0.0.1:8080", u.authority());
66 EXPECT_EQ("/hello/world", u.path());
67 EXPECT_EQ("query", u.query());
68 EXPECT_EQ("fragment", u.fragment());
69 EXPECT_EQ(s, u.fbstr()); // canonical
73 fbstring s("http://[::1]:8080/hello/world?query#fragment");
75 EXPECT_EQ("http", u.scheme());
76 EXPECT_EQ("", u.username());
77 EXPECT_EQ("", u.password());
78 EXPECT_EQ("[::1]", u.host());
79 EXPECT_EQ("::1", u.hostname());
80 EXPECT_EQ(8080, u.port());
81 EXPECT_EQ("[::1]:8080", u.authority());
82 EXPECT_EQ("/hello/world", u.path());
83 EXPECT_EQ("query", u.query());
84 EXPECT_EQ("fragment", u.fragment());
85 EXPECT_EQ(s, u.fbstr()); // canonical
89 fbstring s("http://[2401:db00:20:7004:face:0:29:0]:8080/hello/world?query");
91 EXPECT_EQ("http", u.scheme());
92 EXPECT_EQ("", u.username());
93 EXPECT_EQ("", u.password());
94 EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]", u.host());
95 EXPECT_EQ("2401:db00:20:7004:face:0:29:0", u.hostname());
96 EXPECT_EQ(8080, u.port());
97 EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]:8080", u.authority());
98 EXPECT_EQ("/hello/world", u.path());
99 EXPECT_EQ("query", u.query());
100 EXPECT_EQ("", u.fragment());
101 EXPECT_EQ(s, u.fbstr()); // canonical
105 fbstring s("http://[2401:db00:20:7004:face:0:29:0]/hello/world?query");
107 EXPECT_EQ("http", u.scheme());
108 EXPECT_EQ("", u.username());
109 EXPECT_EQ("", u.password());
110 EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]", u.host());
111 EXPECT_EQ("2401:db00:20:7004:face:0:29:0", u.hostname());
112 EXPECT_EQ(0, u.port());
113 EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]", u.authority());
114 EXPECT_EQ("/hello/world", u.path());
115 EXPECT_EQ("query", u.query());
116 EXPECT_EQ("", u.fragment());
117 EXPECT_EQ(s, u.fbstr()); // canonical
121 fbstring s("http://user:pass@host.com/");
123 EXPECT_EQ("http", u.scheme());
124 EXPECT_EQ("user", u.username());
125 EXPECT_EQ("pass", u.password());
126 EXPECT_EQ("host.com", u.host());
127 EXPECT_EQ(0, u.port());
128 EXPECT_EQ("user:pass@host.com", u.authority());
129 EXPECT_EQ("/", u.path());
130 EXPECT_EQ("", u.query());
131 EXPECT_EQ("", u.fragment());
132 EXPECT_EQ(s, u.fbstr());
136 fbstring s("http://user@host.com/");
138 EXPECT_EQ("http", u.scheme());
139 EXPECT_EQ("user", u.username());
140 EXPECT_EQ("", u.password());
141 EXPECT_EQ("host.com", u.host());
142 EXPECT_EQ(0, u.port());
143 EXPECT_EQ("user@host.com", u.authority());
144 EXPECT_EQ("/", u.path());
145 EXPECT_EQ("", u.query());
146 EXPECT_EQ("", u.fragment());
147 EXPECT_EQ(s, u.fbstr());
151 fbstring s("http://user:@host.com/");
153 EXPECT_EQ("http", u.scheme());
154 EXPECT_EQ("user", u.username());
155 EXPECT_EQ("", u.password());
156 EXPECT_EQ("host.com", u.host());
157 EXPECT_EQ(0, u.port());
158 EXPECT_EQ("user@host.com", u.authority());
159 EXPECT_EQ("/", u.path());
160 EXPECT_EQ("", u.query());
161 EXPECT_EQ("", u.fragment());
162 EXPECT_EQ("http://user@host.com/", u.fbstr());
166 fbstring s("http://:pass@host.com/");
168 EXPECT_EQ("http", u.scheme());
169 EXPECT_EQ("", u.username());
170 EXPECT_EQ("pass", u.password());
171 EXPECT_EQ("host.com", u.host());
172 EXPECT_EQ(0, u.port());
173 EXPECT_EQ(":pass@host.com", u.authority());
174 EXPECT_EQ("/", u.path());
175 EXPECT_EQ("", u.query());
176 EXPECT_EQ("", u.fragment());
177 EXPECT_EQ(s, u.fbstr());
181 fbstring s("http://@host.com/");
183 EXPECT_EQ("http", u.scheme());
184 EXPECT_EQ("", u.username());
185 EXPECT_EQ("", u.password());
186 EXPECT_EQ("host.com", u.host());
187 EXPECT_EQ(0, u.port());
188 EXPECT_EQ("host.com", u.authority());
189 EXPECT_EQ("/", u.path());
190 EXPECT_EQ("", u.query());
191 EXPECT_EQ("", u.fragment());
192 EXPECT_EQ("http://host.com/", u.fbstr());
196 fbstring s("http://:@host.com/");
198 EXPECT_EQ("http", u.scheme());
199 EXPECT_EQ("", u.username());
200 EXPECT_EQ("", u.password());
201 EXPECT_EQ("host.com", u.host());
202 EXPECT_EQ(0, u.port());
203 EXPECT_EQ("host.com", u.authority());
204 EXPECT_EQ("/", u.path());
205 EXPECT_EQ("", u.query());
206 EXPECT_EQ("", u.fragment());
207 EXPECT_EQ("http://host.com/", u.fbstr());
211 fbstring s("file:///etc/motd");
213 EXPECT_EQ("file", u.scheme());
214 EXPECT_EQ("", u.username());
215 EXPECT_EQ("", u.password());
216 EXPECT_EQ("", u.host());
217 EXPECT_EQ(0, u.port());
218 EXPECT_EQ("", u.authority());
219 EXPECT_EQ("/etc/motd", u.path());
220 EXPECT_EQ("", u.query());
221 EXPECT_EQ("", u.fragment());
222 EXPECT_EQ(s, u.fbstr());
226 fbstring s("file:/etc/motd");
228 EXPECT_EQ("file", u.scheme());
229 EXPECT_EQ("", u.username());
230 EXPECT_EQ("", u.password());
231 EXPECT_EQ("", u.host());
232 EXPECT_EQ(0, u.port());
233 EXPECT_EQ("", u.authority());
234 EXPECT_EQ("/etc/motd", u.path());
235 EXPECT_EQ("", u.query());
236 EXPECT_EQ("", u.fragment());
237 EXPECT_EQ("file:/etc/motd", u.fbstr());
241 fbstring s("file://etc/motd");
243 EXPECT_EQ("file", u.scheme());
244 EXPECT_EQ("", u.username());
245 EXPECT_EQ("", u.password());
246 EXPECT_EQ("etc", u.host());
247 EXPECT_EQ(0, u.port());
248 EXPECT_EQ("etc", u.authority());
249 EXPECT_EQ("/motd", u.path());
250 EXPECT_EQ("", u.query());
251 EXPECT_EQ("", u.fragment());
252 EXPECT_EQ(s, u.fbstr());
256 // test query parameters
257 fbstring s("http://localhost?&key1=foo&key2=&key3&=bar&=bar=&");
259 auto paramsList = u.getQueryParams();
260 std::map<fbstring, fbstring> params;
261 for (auto& param : paramsList) {
262 params[param.first] = param.second;
264 EXPECT_EQ(3, params.size());
265 EXPECT_EQ("foo", params["key1"]);
266 EXPECT_NE(params.end(), params.find("key2"));
267 EXPECT_EQ("", params["key2"]);
268 EXPECT_NE(params.end(), params.find("key3"));
269 EXPECT_EQ("", params["key3"]);
273 // test query parameters
274 fbstring s("http://localhost?&&&&&&&&&&&&&&&");
276 auto params = u.getQueryParams();
277 EXPECT_TRUE(params.empty());
281 // test query parameters
282 fbstring s("http://localhost?&=invalid_key&key2&key3=foo");
284 auto paramsList = u.getQueryParams();
285 std::map<fbstring, fbstring> params;
286 for (auto& param : paramsList) {
287 params[param.first] = param.second;
289 EXPECT_EQ(2, params.size());
290 EXPECT_NE(params.end(), params.find("key2"));
291 EXPECT_EQ("", params["key2"]);
292 EXPECT_EQ("foo", params["key3"]);
296 // test query parameters
297 fbstring s("http://localhost?&key1=====&&=key2&key3=");
299 auto paramsList = u.getQueryParams();
300 std::map<fbstring, fbstring> params;
301 for (auto& param : paramsList) {
302 params[param.first] = param.second;
304 EXPECT_EQ(1, params.size());
305 EXPECT_NE(params.end(), params.find("key3"));
306 EXPECT_EQ("", params["key3"]);
310 // test query parameters
311 fbstring s("http://localhost?key1=foo=bar&key2=foobar&");
313 auto paramsList = u.getQueryParams();
314 std::map<fbstring, fbstring> params;
315 for (auto& param : paramsList) {
316 params[param.first] = param.second;
318 EXPECT_EQ(1, params.size());
319 EXPECT_EQ("foobar", params["key2"]);
323 fbstring s("2http://www.facebook.com");
327 CHECK(false) << "Control should not have reached here";
328 } catch (const std::invalid_argument& ex) {
329 EXPECT_TRUE(boost::algorithm::ends_with(ex.what(), s));
334 fbstring s("www[facebook]com");
337 Uri u("http://" + s);
338 CHECK(false) << "Control should not have reached here";
339 } catch (const std::invalid_argument& ex) {
340 EXPECT_TRUE(boost::algorithm::ends_with(ex.what(), s));
345 fbstring s("http://[::1:8080/hello/world?query#fragment");
349 CHECK(false) << "Control should not have reached here";
350 } catch (const std::invalid_argument& ex) {
356 fbstring s("http://::1]:8080/hello/world?query#fragment");
360 CHECK(false) << "Control should not have reached here";
361 } catch (const std::invalid_argument& ex) {
367 fbstring s("http://::1:8080/hello/world?query#fragment");
371 CHECK(false) << "Control should not have reached here";
372 } catch (const std::invalid_argument& ex) {
378 fbstring s("http://2401:db00:20:7004:face:0:29:0/hello/world?query");
382 CHECK(false) << "Control should not have reached here";
383 } catch (const std::invalid_argument& ex) {
388 // No authority (no "//") is valid
390 fbstring s("this:is/a/valid/uri");
392 EXPECT_EQ("this", u.scheme());
393 EXPECT_EQ("is/a/valid/uri", u.path());
394 EXPECT_EQ(s, u.fbstr());
397 fbstring s("this:is:another:valid:uri");
399 EXPECT_EQ("this", u.scheme());
400 EXPECT_EQ("is:another:valid:uri", u.path());
401 EXPECT_EQ(s, u.fbstr());
404 fbstring s("this:is@another:valid:uri");
406 EXPECT_EQ("this", u.scheme());
407 EXPECT_EQ("is@another:valid:uri", u.path());
408 EXPECT_EQ(s, u.fbstr());