Futex::futexWait returns FutexResult
[folly.git] / folly / test / UriTest.cpp
1 /*
2  * Copyright 2017 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 #include <folly/portability/GTest.h>
19
20 #include <boost/algorithm/string.hpp>
21 #include <glog/logging.h>
22 #include <map>
23
24 using namespace folly;
25
26 TEST(Uri, Simple) {
27   {
28     fbstring s("http://www.facebook.com/hello/world?query#fragment");
29     Uri u(s);
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
40   }
41
42   {
43     fbstring s("http://www.facebook.com:8080/hello/world?query#fragment");
44     Uri u(s);
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
55   }
56
57   {
58     fbstring s("http://127.0.0.1:8080/hello/world?query#fragment");
59     Uri u(s);
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
70   }
71
72   {
73     fbstring s("http://[::1]:8080/hello/world?query#fragment");
74     Uri u(s);
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
86   }
87
88   {
89     fbstring s("http://[2401:db00:20:7004:face:0:29:0]:8080/hello/world?query");
90     Uri u(s);
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
102   }
103
104   {
105     fbstring s("http://[2401:db00:20:7004:face:0:29:0]/hello/world?query");
106     Uri u(s);
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
118   }
119
120   {
121     fbstring s("http://user:pass@host.com/");
122     Uri u(s);
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());
133   }
134
135   {
136     fbstring s("http://user@host.com/");
137     Uri u(s);
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());
148   }
149
150   {
151     fbstring s("http://user:@host.com/");
152     Uri u(s);
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());
163   }
164
165   {
166     fbstring s("http://:pass@host.com/");
167     Uri u(s);
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());
178   }
179
180   {
181     fbstring s("http://@host.com/");
182     Uri u(s);
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());
193   }
194
195   {
196     fbstring s("http://:@host.com/");
197     Uri u(s);
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());
208   }
209
210   {
211     fbstring s("file:///etc/motd");
212     Uri u(s);
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());
223   }
224
225   {
226     fbstring s("file:/etc/motd");
227     Uri u(s);
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());
238   }
239
240   {
241     fbstring s("file://etc/motd");
242     Uri u(s);
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());
253   }
254
255   {
256     // test query parameters
257     fbstring s("http://localhost?&key1=foo&key2=&key3&=bar&=bar=&");
258     Uri u(s);
259     auto paramsList = u.getQueryParams();
260     std::map<fbstring, fbstring> params;
261     for (auto& param : paramsList) {
262       params[param.first] = param.second;
263     }
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"]);
270   }
271
272   {
273     // test query parameters
274     fbstring s("http://localhost?&&&&&&&&&&&&&&&");
275     Uri u(s);
276     auto params = u.getQueryParams();
277     EXPECT_TRUE(params.empty());
278   }
279
280   {
281     // test query parameters
282     fbstring s("http://localhost?&=invalid_key&key2&key3=foo");
283     Uri u(s);
284     auto paramsList = u.getQueryParams();
285     std::map<fbstring, fbstring> params;
286     for (auto& param : paramsList) {
287       params[param.first] = param.second;
288     }
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"]);
293   }
294
295   {
296     // test query parameters
297     fbstring s("http://localhost?&key1=====&&=key2&key3=");
298     Uri u(s);
299     auto paramsList = u.getQueryParams();
300     std::map<fbstring, fbstring> params;
301     for (auto& param : paramsList) {
302       params[param.first] = param.second;
303     }
304     EXPECT_EQ(1, params.size());
305     EXPECT_NE(params.end(), params.find("key3"));
306     EXPECT_EQ("", params["key3"]);
307   }
308
309   {
310     // test query parameters
311     fbstring s("http://localhost?key1=foo=bar&key2=foobar&");
312     Uri u(s);
313     auto paramsList = u.getQueryParams();
314     std::map<fbstring, fbstring> params;
315     for (auto& param : paramsList) {
316       params[param.first] = param.second;
317     }
318     EXPECT_EQ(1, params.size());
319     EXPECT_EQ("foobar", params["key2"]);
320   }
321
322   {
323     fbstring s("2http://www.facebook.com");
324
325     try {
326       Uri u(s);
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));
330     }
331   }
332
333   {
334     fbstring s("www[facebook]com");
335
336     try {
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));
341     }
342   }
343
344   {
345     fbstring s("http://[::1:8080/hello/world?query#fragment");
346
347     try {
348       Uri u(s);
349       CHECK(false) << "Control should not have reached here";
350     } catch (const std::invalid_argument&) {
351       // success
352     }
353   }
354
355   {
356     fbstring s("http://::1]:8080/hello/world?query#fragment");
357
358     try {
359       Uri u(s);
360       CHECK(false) << "Control should not have reached here";
361     } catch (const std::invalid_argument&) {
362       // success
363     }
364   }
365
366   {
367     fbstring s("http://::1:8080/hello/world?query#fragment");
368
369     try {
370       Uri u(s);
371       CHECK(false) << "Control should not have reached here";
372     } catch (const std::invalid_argument&) {
373       // success
374     }
375   }
376
377   {
378     fbstring s("http://2401:db00:20:7004:face:0:29:0/hello/world?query");
379
380     try {
381       Uri u(s);
382       CHECK(false) << "Control should not have reached here";
383     } catch (const std::invalid_argument&) {
384       // success
385     }
386   }
387
388   // No authority (no "//") is valid
389   {
390     fbstring s("this:is/a/valid/uri");
391     Uri u(s);
392     EXPECT_EQ("this", u.scheme());
393     EXPECT_EQ("is/a/valid/uri", u.path());
394     EXPECT_EQ(s, u.fbstr());
395   }
396   {
397     fbstring s("this:is:another:valid:uri");
398     Uri u(s);
399     EXPECT_EQ("this", u.scheme());
400     EXPECT_EQ("is:another:valid:uri", u.path());
401     EXPECT_EQ(s, u.fbstr());
402   }
403   {
404     fbstring s("this:is@another:valid:uri");
405     Uri u(s);
406     EXPECT_EQ("this", u.scheme());
407     EXPECT_EQ("is@another:valid:uri", u.path());
408     EXPECT_EQ(s, u.fbstr());
409   }
410 }