7f8faee8847d5ad2728b9f94f104a53407f85a58
[folly.git] / folly / test / UriTest.cpp
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <folly/Uri.h>
18
19 #include <boost/algorithm/string.hpp>
20 #include <glog/logging.h>
21 #include <gtest/gtest.h>
22 #include <map>
23
24 using namespace folly;
25
26 namespace {
27
28 }  // namespace
29
30 TEST(Uri, Simple) {
31   {
32     fbstring s("http://www.facebook.com/hello/world?query#fragment");
33     Uri u(s);
34     EXPECT_EQ("http", u.scheme());
35     EXPECT_EQ("", u.username());
36     EXPECT_EQ("", u.password());
37     EXPECT_EQ("www.facebook.com", u.host());
38     EXPECT_EQ(0, u.port());
39     EXPECT_EQ("www.facebook.com", u.authority());
40     EXPECT_EQ("/hello/world", u.path());
41     EXPECT_EQ("query", u.query());
42     EXPECT_EQ("fragment", u.fragment());
43     EXPECT_EQ(s, u.fbstr());  // canonical
44   }
45
46   {
47     fbstring s("http://www.facebook.com:8080/hello/world?query#fragment");
48     Uri u(s);
49     EXPECT_EQ("http", u.scheme());
50     EXPECT_EQ("", u.username());
51     EXPECT_EQ("", u.password());
52     EXPECT_EQ("www.facebook.com", u.host());
53     EXPECT_EQ(8080, u.port());
54     EXPECT_EQ("www.facebook.com:8080", u.authority());
55     EXPECT_EQ("/hello/world", u.path());
56     EXPECT_EQ("query", u.query());
57     EXPECT_EQ("fragment", u.fragment());
58     EXPECT_EQ(s, u.fbstr());  // canonical
59   }
60
61   {
62     fbstring s("http://127.0.0.1:8080/hello/world?query#fragment");
63     Uri u(s);
64     EXPECT_EQ("http", u.scheme());
65     EXPECT_EQ("", u.username());
66     EXPECT_EQ("", u.password());
67     EXPECT_EQ("127.0.0.1", u.host());
68     EXPECT_EQ(8080, u.port());
69     EXPECT_EQ("127.0.0.1:8080", u.authority());
70     EXPECT_EQ("/hello/world", u.path());
71     EXPECT_EQ("query", u.query());
72     EXPECT_EQ("fragment", u.fragment());
73     EXPECT_EQ(s, u.fbstr());  // canonical
74   }
75
76   {
77     fbstring s("http://[::1]:8080/hello/world?query#fragment");
78     Uri u(s);
79     EXPECT_EQ("http", u.scheme());
80     EXPECT_EQ("", u.username());
81     EXPECT_EQ("", u.password());
82     EXPECT_EQ("[::1]", u.host());
83     EXPECT_EQ("::1", u.hostname());
84     EXPECT_EQ(8080, u.port());
85     EXPECT_EQ("[::1]:8080", u.authority());
86     EXPECT_EQ("/hello/world", u.path());
87     EXPECT_EQ("query", u.query());
88     EXPECT_EQ("fragment", u.fragment());
89     EXPECT_EQ(s, u.fbstr());  // canonical
90   }
91
92   {
93     fbstring s("http://[2401:db00:20:7004:face:0:29:0]:8080/hello/world?query");
94     Uri u(s);
95     EXPECT_EQ("http", u.scheme());
96     EXPECT_EQ("", u.username());
97     EXPECT_EQ("", u.password());
98     EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]", u.host());
99     EXPECT_EQ("2401:db00:20:7004:face:0:29:0", u.hostname());
100     EXPECT_EQ(8080, u.port());
101     EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]:8080", u.authority());
102     EXPECT_EQ("/hello/world", u.path());
103     EXPECT_EQ("query", u.query());
104     EXPECT_EQ("", u.fragment());
105     EXPECT_EQ(s, u.fbstr());  // canonical
106   }
107
108   {
109     fbstring s("http://[2401:db00:20:7004:face:0:29:0]/hello/world?query");
110     Uri u(s);
111     EXPECT_EQ("http", u.scheme());
112     EXPECT_EQ("", u.username());
113     EXPECT_EQ("", u.password());
114     EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]", u.host());
115     EXPECT_EQ("2401:db00:20:7004:face:0:29:0", u.hostname());
116     EXPECT_EQ(0, u.port());
117     EXPECT_EQ("[2401:db00:20:7004:face:0:29:0]", u.authority());
118     EXPECT_EQ("/hello/world", u.path());
119     EXPECT_EQ("query", u.query());
120     EXPECT_EQ("", u.fragment());
121     EXPECT_EQ(s, u.fbstr());  // canonical
122   }
123
124   {
125     fbstring s("http://user:pass@host.com/");
126     Uri u(s);
127     EXPECT_EQ("http", u.scheme());
128     EXPECT_EQ("user", u.username());
129     EXPECT_EQ("pass", u.password());
130     EXPECT_EQ("host.com", u.host());
131     EXPECT_EQ(0, u.port());
132     EXPECT_EQ("user:pass@host.com", u.authority());
133     EXPECT_EQ("/", u.path());
134     EXPECT_EQ("", u.query());
135     EXPECT_EQ("", u.fragment());
136     EXPECT_EQ(s, u.fbstr());
137   }
138
139   {
140     fbstring s("http://user@host.com/");
141     Uri u(s);
142     EXPECT_EQ("http", u.scheme());
143     EXPECT_EQ("user", u.username());
144     EXPECT_EQ("", u.password());
145     EXPECT_EQ("host.com", u.host());
146     EXPECT_EQ(0, u.port());
147     EXPECT_EQ("user@host.com", u.authority());
148     EXPECT_EQ("/", u.path());
149     EXPECT_EQ("", u.query());
150     EXPECT_EQ("", u.fragment());
151     EXPECT_EQ(s, u.fbstr());
152   }
153
154   {
155     fbstring s("http://user:@host.com/");
156     Uri u(s);
157     EXPECT_EQ("http", u.scheme());
158     EXPECT_EQ("user", u.username());
159     EXPECT_EQ("", u.password());
160     EXPECT_EQ("host.com", u.host());
161     EXPECT_EQ(0, u.port());
162     EXPECT_EQ("user@host.com", u.authority());
163     EXPECT_EQ("/", u.path());
164     EXPECT_EQ("", u.query());
165     EXPECT_EQ("", u.fragment());
166     EXPECT_EQ("http://user@host.com/", u.fbstr());
167   }
168
169   {
170     fbstring s("http://:pass@host.com/");
171     Uri u(s);
172     EXPECT_EQ("http", u.scheme());
173     EXPECT_EQ("", u.username());
174     EXPECT_EQ("pass", u.password());
175     EXPECT_EQ("host.com", u.host());
176     EXPECT_EQ(0, u.port());
177     EXPECT_EQ(":pass@host.com", u.authority());
178     EXPECT_EQ("/", u.path());
179     EXPECT_EQ("", u.query());
180     EXPECT_EQ("", u.fragment());
181     EXPECT_EQ(s, u.fbstr());
182   }
183
184   {
185     fbstring s("http://@host.com/");
186     Uri u(s);
187     EXPECT_EQ("http", u.scheme());
188     EXPECT_EQ("", u.username());
189     EXPECT_EQ("", u.password());
190     EXPECT_EQ("host.com", u.host());
191     EXPECT_EQ(0, u.port());
192     EXPECT_EQ("host.com", u.authority());
193     EXPECT_EQ("/", u.path());
194     EXPECT_EQ("", u.query());
195     EXPECT_EQ("", u.fragment());
196     EXPECT_EQ("http://host.com/", u.fbstr());
197   }
198
199   {
200     fbstring s("http://:@host.com/");
201     Uri u(s);
202     EXPECT_EQ("http", u.scheme());
203     EXPECT_EQ("", u.username());
204     EXPECT_EQ("", u.password());
205     EXPECT_EQ("host.com", u.host());
206     EXPECT_EQ(0, u.port());
207     EXPECT_EQ("host.com", u.authority());
208     EXPECT_EQ("/", u.path());
209     EXPECT_EQ("", u.query());
210     EXPECT_EQ("", u.fragment());
211     EXPECT_EQ("http://host.com/", u.fbstr());
212   }
213
214   {
215     fbstring s("file:///etc/motd");
216     Uri u(s);
217     EXPECT_EQ("file", u.scheme());
218     EXPECT_EQ("", u.username());
219     EXPECT_EQ("", u.password());
220     EXPECT_EQ("", u.host());
221     EXPECT_EQ(0, u.port());
222     EXPECT_EQ("", u.authority());
223     EXPECT_EQ("/etc/motd", u.path());
224     EXPECT_EQ("", u.query());
225     EXPECT_EQ("", u.fragment());
226     EXPECT_EQ(s, u.fbstr());
227   }
228
229   {
230     fbstring s("file:/etc/motd");
231     Uri u(s);
232     EXPECT_EQ("file", u.scheme());
233     EXPECT_EQ("", u.username());
234     EXPECT_EQ("", u.password());
235     EXPECT_EQ("", u.host());
236     EXPECT_EQ(0, u.port());
237     EXPECT_EQ("", u.authority());
238     EXPECT_EQ("/etc/motd", u.path());
239     EXPECT_EQ("", u.query());
240     EXPECT_EQ("", u.fragment());
241     EXPECT_EQ("file:///etc/motd", u.fbstr());
242   }
243
244   {
245     fbstring s("file://etc/motd");
246     Uri u(s);
247     EXPECT_EQ("file", u.scheme());
248     EXPECT_EQ("", u.username());
249     EXPECT_EQ("", u.password());
250     EXPECT_EQ("etc", u.host());
251     EXPECT_EQ(0, u.port());
252     EXPECT_EQ("etc", u.authority());
253     EXPECT_EQ("/motd", u.path());
254     EXPECT_EQ("", u.query());
255     EXPECT_EQ("", u.fragment());
256     EXPECT_EQ(s, u.fbstr());
257   }
258
259   {
260     // test query parameters
261     fbstring s("http://localhost?&key1=foo&key2=&key3&=bar&=bar=&");
262     Uri u(s);
263     auto paramsList = u.getQueryParams();
264     std::map<fbstring, fbstring> params;
265     for (auto& param : paramsList) {
266       params[param.first] = param.second;
267     }
268     EXPECT_EQ(3, params.size());
269     EXPECT_EQ("foo", params["key1"]);
270     EXPECT_NE(params.end(), params.find("key2"));
271     EXPECT_EQ("", params["key2"]);
272     EXPECT_NE(params.end(), params.find("key3"));
273     EXPECT_EQ("", params["key3"]);
274   }
275
276   {
277     // test query parameters
278     fbstring s("http://localhost?&&&&&&&&&&&&&&&");
279     Uri u(s);
280     auto params = u.getQueryParams();
281     EXPECT_TRUE(params.empty());
282   }
283
284   {
285     // test query parameters
286     fbstring s("http://localhost?&=invalid_key&key2&key3=foo");
287     Uri u(s);
288     auto paramsList = u.getQueryParams();
289     std::map<fbstring, fbstring> params;
290     for (auto& param : paramsList) {
291       params[param.first] = param.second;
292     }
293     EXPECT_EQ(2, params.size());
294     EXPECT_NE(params.end(), params.find("key2"));
295     EXPECT_EQ("", params["key2"]);
296     EXPECT_EQ("foo", params["key3"]);
297   }
298
299   {
300     // test query parameters
301     fbstring s("http://localhost?&key1=====&&=key2&key3=");
302     Uri u(s);
303     auto paramsList = u.getQueryParams();
304     std::map<fbstring, fbstring> params;
305     for (auto& param : paramsList) {
306       params[param.first] = param.second;
307     }
308     EXPECT_EQ(1, params.size());
309     EXPECT_NE(params.end(), params.find("key3"));
310     EXPECT_EQ("", params["key3"]);
311   }
312
313   {
314     // test query parameters
315     fbstring s("http://localhost?key1=foo=bar&key2=foobar&");
316     Uri u(s);
317     auto paramsList = u.getQueryParams();
318     std::map<fbstring, fbstring> params;
319     for (auto& param : paramsList) {
320       params[param.first] = param.second;
321     }
322     EXPECT_EQ(1, params.size());
323     EXPECT_EQ("foobar", params["key2"]);
324   }
325
326   {
327     fbstring s("2http://www.facebook.com");
328
329     try {
330       Uri u(s);
331       CHECK(false) << "Control should not have reached here";
332     } catch (const std::invalid_argument& ex) {
333       EXPECT_TRUE(boost::algorithm::ends_with(ex.what(), s));
334     }
335   }
336
337   {
338     fbstring s("www[facebook]com");
339
340     try {
341       Uri u("http://" + s);
342       CHECK(false) << "Control should not have reached here";
343     } catch (const std::invalid_argument& ex) {
344       EXPECT_TRUE(boost::algorithm::ends_with(ex.what(), s));
345     }
346   }
347
348   {
349     fbstring s("http://[::1:8080/hello/world?query#fragment");
350
351     try {
352       Uri u(s);
353       CHECK(false) << "Control should not have reached here";
354     } catch (const std::invalid_argument& ex) {
355       // success
356     }
357   }
358
359   {
360     fbstring s("http://::1]:8080/hello/world?query#fragment");
361
362     try {
363       Uri u(s);
364       CHECK(false) << "Control should not have reached here";
365     } catch (const std::invalid_argument& ex) {
366       // success
367     }
368   }
369
370   {
371     fbstring s("http://::1:8080/hello/world?query#fragment");
372
373     try {
374       Uri u(s);
375       CHECK(false) << "Control should not have reached here";
376     } catch (const std::invalid_argument& ex) {
377       // success
378     }
379   }
380
381   {
382     fbstring s("http://2401:db00:20:7004:face:0:29:0/hello/world?query");
383
384     try {
385       Uri u(s);
386       CHECK(false) << "Control should not have reached here";
387     } catch (const std::invalid_argument& ex) {
388       // success
389     }
390   }
391 }