uri_ut.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. #include "uri_ut.h"
  2. #include "other.h"
  3. #include "qargs.h"
  4. #include <library/cpp/html/entity/htmlentity.h>
  5. #include <util/system/maxlen.h>
  6. namespace NUri {
  7. Y_UNIT_TEST_SUITE(URLTest) {
  8. static const char* urls[] = {
  9. "http://a/b/c/d;p?q#r",
  10. "g", "http://a/b/c/g",
  11. "./g", "http://a/b/c/g",
  12. "g/", "http://a/b/c/g/",
  13. "/g", "http://a/g",
  14. "//g", "http://g/",
  15. "?y", "http://a/b/c/d;p?y",
  16. "g?y", "http://a/b/c/g?y",
  17. "#s", "http://a/b/c/d;p?q#s",
  18. "g#s", "http://a/b/c/g#s",
  19. "g?y#s", "http://a/b/c/g?y#s",
  20. ";x", "http://a/b/c/;x",
  21. "g;x", "http://a/b/c/g;x",
  22. "g;x?y#s", "http://a/b/c/g;x?y#s",
  23. ".", "http://a/b/c/",
  24. "./", "http://a/b/c/",
  25. "./.", "http://a/b/c/",
  26. "././", "http://a/b/c/",
  27. "././.", "http://a/b/c/",
  28. "..", "http://a/b/",
  29. "../", "http://a/b/",
  30. "../.", "http://a/b/",
  31. "../g", "http://a/b/g",
  32. "../..", "http://a/",
  33. "../../", "http://a/",
  34. "../../.", "http://a/",
  35. "../../g", "http://a/g",
  36. "../../../g", "http://a/g",
  37. "../../../../g", "http://a/g",
  38. "/./g", "http://a/g",
  39. "g.", "http://a/b/c/g.",
  40. ".g", "http://a/b/c/.g",
  41. "g..", "http://a/b/c/g..",
  42. "..g", "http://a/b/c/..g",
  43. "./../g", "http://a/b/g",
  44. "./g/.", "http://a/b/c/g/",
  45. "g/./h", "http://a/b/c/g/h",
  46. "g/../h", "http://a/b/c/h",
  47. "g;x=1/./y", "http://a/b/c/g;x=1/y",
  48. "g;x=1/../y", "http://a/b/c/y",
  49. "g?y/./x", "http://a/b/c/g?y/./x",
  50. "g?y/../x", "http://a/b/c/g?y/../x",
  51. "g#s/./x", "http://a/b/c/g#s/./x",
  52. "g#s/../x", "http://a/b/c/g#s/../x",
  53. "?", "http://a/b/c/d;p?",
  54. "/?", "http://a/?",
  55. "x?", "http://a/b/c/x?",
  56. "x%20y", "http://a/b/c/x%20y",
  57. "%20y", "http://a/b/c/%20y",
  58. // "%2zy", "http://a/b/c/%2zy",
  59. nullptr};
  60. Y_UNIT_TEST(test_httpURL) {
  61. TUri rel, base, abs;
  62. TState::EParsed er = base.Parse(urls[0]);
  63. UNIT_ASSERT_VALUES_EQUAL(er, TState::ParsedOK);
  64. UNIT_ASSERT(base.IsValidAbs());
  65. UNIT_ASSERT_VALUES_EQUAL(base.PrintS(), urls[0]);
  66. TString errbuf;
  67. TStringOutput out(errbuf);
  68. const long mflag = TFeature::FeaturesAll;
  69. for (int i = 1; urls[i]; i += 2) {
  70. er = rel.Parse(urls[i]);
  71. UNIT_ASSERT_VALUES_EQUAL_C(er, TState::ParsedOK, urls[i]);
  72. rel.Merge(base);
  73. UNIT_ASSERT_VALUES_EQUAL_C(rel.PrintS(), urls[i + 1], urls[i]);
  74. // try the same thing differently
  75. er = rel.Parse(urls[i], mflag, urls[0]);
  76. UNIT_ASSERT_VALUES_EQUAL_C(er, TState::ParsedOK, urls[i]);
  77. UNIT_ASSERT_VALUES_EQUAL_C(rel.PrintS(), urls[i + 1], urls[i]);
  78. // lastly...
  79. er = abs.Parse(urls[i + 1], mflag);
  80. UNIT_ASSERT_VALUES_EQUAL(er, TState::ParsedOK);
  81. errbuf.clear();
  82. out << '[' << rel.PrintS()
  83. << "] != [" << abs.PrintS() << ']';
  84. UNIT_ASSERT_EQUAL_C(rel, abs, errbuf);
  85. }
  86. }
  87. Y_UNIT_TEST(test_Schemes) {
  88. TUri url;
  89. UNIT_ASSERT_VALUES_EQUAL(url.Parse("www.ya.ru/index.html"), TState::ParsedOK);
  90. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeEmpty);
  91. UNIT_ASSERT_VALUES_EQUAL(url.Parse("http://www.ya.ru"), TState::ParsedOK);
  92. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeHTTP);
  93. UNIT_ASSERT_VALUES_EQUAL(url.Parse("https://www.ya.ru"), TState::ParsedBadScheme);
  94. UNIT_ASSERT_VALUES_EQUAL(url.Parse("https://www.ya.ru", TFeature::FeaturesDefault | TFeature::FeatureSchemeKnown), TState::ParsedOK);
  95. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeHTTPS);
  96. UNIT_ASSERT_VALUES_EQUAL(url.Parse("httpwhatever://www.ya.ru"), TState::ParsedBadScheme);
  97. UNIT_ASSERT_VALUES_EQUAL(url.Parse("httpwhatever://www.ya.ru", TFeature::FeaturesDefault | TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  98. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeUnknown);
  99. UNIT_ASSERT_VALUES_EQUAL(url.Parse("httpswhatever://www.ya.ru"), TState::ParsedBadScheme);
  100. UNIT_ASSERT_VALUES_EQUAL(url.Parse("httpswhatever://www.ya.ru", TFeature::FeaturesDefault | TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  101. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeUnknown);
  102. UNIT_ASSERT_VALUES_EQUAL(url.Parse("ftp://www.ya.ru"), TState::ParsedBadScheme);
  103. UNIT_ASSERT_VALUES_EQUAL(url.Parse("ftp://www.ya.ru", TFeature::FeaturesDefault | TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  104. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeFTP);
  105. UNIT_ASSERT_VALUES_EQUAL(url.Parse("httpsssss://www.ya.ru"), TState::ParsedBadScheme);
  106. UNIT_ASSERT_VALUES_EQUAL(url.Parse("httpsssss://www.ya.ru", TFeature::FeaturesDefault | TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  107. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeUnknown);
  108. }
  109. struct Link4Norm {
  110. const char* const base;
  111. const char* const link;
  112. const char* const result;
  113. TUri::TLinkType ltype;
  114. };
  115. static const Link4Norm link4Norm[] = {
  116. {"http://www.alltest.ru/all.php?a=aberporth", "http://www.alltest.ru/all.php?a=domestic jobs", "", TUri::LinkIsBad},
  117. {"http://www.alltest.ru/all.php?a=aberporth", "http://www.alltest.ru/all.php?a=domestic%20jobs", "http://www.alltest.ru/all.php?a=domestic%20jobs", TUri::LinkIsLocal},
  118. {"http://president.rf/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8", "http://president.rf/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8/1024", "http://president.rf/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8/1024", TUri::LinkIsLocal},
  119. {nullptr, nullptr, nullptr, TUri::LinkIsBad},
  120. };
  121. Y_UNIT_TEST(test_httpURLNormalize) {
  122. TUri normalizedLink;
  123. for (int i = 0; link4Norm[i].link; i++) {
  124. TUri base;
  125. TState::EParsed er = base.Parse(link4Norm[i].base);
  126. UNIT_ASSERT_VALUES_EQUAL_C(er, TState::ParsedOK, link4Norm[i].base);
  127. TUri::TLinkType ltype = normalizedLink.Normalize(base, link4Norm[i].link);
  128. UNIT_ASSERT_VALUES_EQUAL_C(ltype, link4Norm[i].ltype, link4Norm[i].link);
  129. TString s = TUri::LinkIsBad == ltype ? "" : normalizedLink.PrintS();
  130. UNIT_ASSERT_VALUES_EQUAL_C(s, link4Norm[i].result, link4Norm[i].link);
  131. }
  132. }
  133. static const char* urlsWithMultipleSlash[] = {
  134. "http://a/http://b", "http://a/http://b",
  135. "http://a/https://b", "http://a/https://b",
  136. "http://a/b://c", "http://a/b:/c",
  137. "http://a/b//c", "http://a/b/c",
  138. nullptr, nullptr};
  139. Y_UNIT_TEST(test_httpURLPathOperation) {
  140. char copyUrl[URL_MAXLEN];
  141. for (int i = 0; urlsWithMultipleSlash[i]; i += 2) {
  142. const TStringBuf url(urlsWithMultipleSlash[i]);
  143. const TStringBuf normurl(urlsWithMultipleSlash[i + 1]);
  144. memcpy(copyUrl, url.data(), url.length());
  145. char* p = copyUrl;
  146. char* e = copyUrl + url.length();
  147. TUri::PathOperation(p, e, 1);
  148. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(p, e), normurl);
  149. TUri uri;
  150. UNIT_ASSERT_VALUES_EQUAL(TState::ParsedOK, uri.Parse(url));
  151. UNIT_ASSERT_VALUES_EQUAL_C(uri.PrintS(), normurl, url);
  152. }
  153. }
  154. static const char* hostsForCheckHost[] = {
  155. "simplehost.ru",
  156. "third_level.host.ru",
  157. "_ok.somewhere.ru",
  158. "a.b",
  159. "second_level.ru",
  160. "_bad.ru",
  161. "_",
  162. "yandex.ru:443",
  163. nullptr};
  164. static TState::EParsed answersForCheckHost[] = {
  165. TState::ParsedOK,
  166. TState::ParsedOK,
  167. TState::ParsedOK,
  168. TState::ParsedOK,
  169. TState::ParsedBadHost,
  170. TState::ParsedBadHost,
  171. TState::ParsedBadHost,
  172. TState::ParsedBadHost,
  173. };
  174. Y_UNIT_TEST(test_httpURLCheckHost) {
  175. for (size_t index = 0; hostsForCheckHost[index]; ++index) {
  176. TState::EParsed state = TUri::CheckHost(hostsForCheckHost[index]);
  177. UNIT_ASSERT_VALUES_EQUAL(state, answersForCheckHost[index]);
  178. }
  179. }
  180. Y_UNIT_TEST(test_httpURLSet) {
  181. // set port
  182. {
  183. TUri parsedUrl;
  184. parsedUrl.Parse("http://www.host.com/script.cgi?param1=value1&param2=value2");
  185. parsedUrl.FldMemSet(TField::FieldPort, "8080");
  186. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.GetPort(), 8080);
  187. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.PrintS(), "http://www.host.com:8080/script.cgi?param1=value1&param2=value2");
  188. }
  189. // clear port
  190. {
  191. TUri parsedUrl;
  192. parsedUrl.Parse("http://www.host.com:8080/script.cgi?param1=value1&param2=value2");
  193. parsedUrl.FldMemSet(TField::FieldPort, nullptr);
  194. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.GetPort(), 80);
  195. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.PrintS(), "http://www.host.com/script.cgi?param1=value1&param2=value2");
  196. }
  197. // change scheme with default port
  198. {
  199. TUri parsedUrl;
  200. parsedUrl.Parse("http://www.host.com/script.cgi?param1=value1&param2=value2");
  201. parsedUrl.FldMemSet(TField::FieldScheme, "https");
  202. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.GetPort(), 443);
  203. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.PrintS(), "https://www.host.com/script.cgi?param1=value1&param2=value2");
  204. }
  205. // change scheme with non-default port
  206. {
  207. TUri parsedUrl;
  208. parsedUrl.Parse("http://www.host.com:8080/script.cgi?param1=value1&param2=value2");
  209. parsedUrl.FldMemSet(TField::FieldScheme, "https");
  210. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.GetPort(), 8080);
  211. UNIT_ASSERT_VALUES_EQUAL(parsedUrl.PrintS(), "https://www.host.com:8080/script.cgi?param1=value1&param2=value2");
  212. }
  213. }
  214. Y_UNIT_TEST(test_httpURLAuth) {
  215. {
  216. TUri parsedUrl;
  217. TState::EParsed st = parsedUrl.Parse("http://@www.host.com/path", TFeature::FeaturesRobot);
  218. UNIT_ASSERT_VALUES_EQUAL(st, TState::ParsedBadAuth);
  219. }
  220. {
  221. TUri parsedUrl;
  222. TState::EParsed st = parsedUrl.Parse("http://loginwithnopass@www.host.com/path", TFeature::FeatureAuthSupported);
  223. UNIT_ASSERT_VALUES_EQUAL(st, TState::ParsedOK);
  224. UNIT_ASSERT_EQUAL(parsedUrl.GetField(TField::FieldHost), "www.host.com");
  225. UNIT_ASSERT_EQUAL(parsedUrl.GetField(TField::FieldUser), "loginwithnopass");
  226. UNIT_ASSERT_EQUAL(parsedUrl.GetField(TField::FieldPass), "");
  227. }
  228. {
  229. TUri parsedUrl;
  230. TState::EParsed st = parsedUrl.Parse("http://login:pass@www.host.com/path", TFeature::FeatureAuthSupported);
  231. UNIT_ASSERT_VALUES_EQUAL(st, TState::ParsedOK);
  232. UNIT_ASSERT_EQUAL(parsedUrl.GetField(TField::FieldHost), "www.host.com");
  233. UNIT_ASSERT_EQUAL(parsedUrl.GetField(TField::FieldUser), "login");
  234. UNIT_ASSERT_EQUAL(parsedUrl.GetField(TField::FieldPass), "pass");
  235. }
  236. }
  237. Y_UNIT_TEST(test01) {
  238. TTest test = {
  239. "user:pass@host:8080", TFeature::FeaturesAll, TState::ParsedRootless, "user", "", "", "", 0, "", "", "", ""};
  240. TUri url;
  241. URL_TEST(url, test);
  242. }
  243. Y_UNIT_TEST(test02) {
  244. TTest test = {
  245. "http://host", TFeature::FeaturesAll, TState::ParsedOK, "http", "", "", "host", 80, "/", "", "", ""};
  246. TUri url;
  247. URL_TEST(url, test);
  248. }
  249. Y_UNIT_TEST(test03) {
  250. TTest test = {
  251. "https://host", TFeature::FeatureSchemeFlexible | TFeature::FeatureAllowHostIDN, TState::ParsedOK, "https", "", "", "host", 443, "/", "", "", ""};
  252. TUri url;
  253. URL_TEST(url, test);
  254. }
  255. Y_UNIT_TEST(test04) {
  256. TTest test = {
  257. "user:pass@host:8080", TFeature::FeaturesAll | TFeature::FeatureNoRelPath | TFeature::FeatureAllowRootless, TState::ParsedOK, "user", "", "", "", 0, "pass@host:8080", "", "", ""};
  258. TUri url;
  259. URL_TEST(url, test);
  260. TUri url2(url);
  261. CMP_URL(url2, test);
  262. URL_EQ(url, url2);
  263. }
  264. Y_UNIT_TEST(test05) {
  265. TTest test = {
  266. "host:8080", TFeature::FeaturesAll | TFeature::FeatureNoRelPath | TFeature::FeatureAllowRootless, TState::ParsedOK, "host", "", "", "", 0, "8080", "", "", ""};
  267. TUri url;
  268. URL_TEST(url, test);
  269. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "host:8080");
  270. }
  271. Y_UNIT_TEST(test06) {
  272. TTest test = {
  273. "http://user:pass@host?q", TFeature::FeaturesAll, TState::ParsedOK, "http", "user", "pass", "host", 80, "/", "q", "", ""};
  274. TUri url;
  275. URL_TEST(url, test);
  276. url.FldMemSet(TField::FieldScheme, "https");
  277. UNIT_ASSERT(!url.FldIsDirty());
  278. UNIT_ASSERT_VALUES_EQUAL(url.GetField(TField::FieldScheme), "https");
  279. UNIT_ASSERT_VALUES_EQUAL(url.GetPort(), 443);
  280. // test copying
  281. TUri url2(url);
  282. // make sure strings are equal...
  283. UNIT_ASSERT_VALUES_EQUAL(
  284. url.GetField(TField::FieldUser),
  285. url2.GetField(TField::FieldUser));
  286. // ... and memory locations are the same
  287. UNIT_ASSERT_EQUAL(
  288. url.GetField(TField::FieldUser),
  289. url2.GetField(TField::FieldUser));
  290. // and urls compare the same
  291. URL_EQ(url, url2);
  292. // cause a dirty field
  293. url.FldMemSet(TField::FieldUser, "use"); // it is now shorter
  294. UNIT_ASSERT(!url.FldIsDirty());
  295. url.FldMemSet(TField::FieldUser, TStringBuf("user"));
  296. UNIT_ASSERT(url.FldIsDirty());
  297. // copy again
  298. url2 = url;
  299. UNIT_ASSERT(url.FldIsDirty());
  300. UNIT_ASSERT(!url2.FldIsDirty());
  301. URL_EQ(url, url2);
  302. // make sure strings are equal...
  303. UNIT_ASSERT_VALUES_EQUAL(
  304. url.GetField(TField::FieldUser),
  305. url2.GetField(TField::FieldUser));
  306. // ... but memory locations are different
  307. UNIT_ASSERT_UNEQUAL(
  308. url.GetField(TField::FieldUser).data(),
  309. url2.GetField(TField::FieldUser).data());
  310. URL_EQ(url, url2);
  311. // make query empty
  312. url.FldMemSet(TField::FieldQuery, "");
  313. url2 = url;
  314. URL_EQ(url, url2);
  315. // set query to null value (should clear it)
  316. url2.FldMemSet(TField::FieldQuery, TStringBuf());
  317. // make sure they are no longer equal
  318. URL_NEQ(url, url2);
  319. // reset query
  320. url.FldClr(TField::FieldQuery);
  321. // equal again
  322. URL_EQ(url, url2);
  323. // reset port and set the other to default
  324. url.FldClr(TField::FieldPort);
  325. url2.FldMemSet(TField::FieldPort, "443");
  326. URL_EQ(url, url2);
  327. }
  328. Y_UNIT_TEST(test07) {
  329. {
  330. TTest test = {
  331. "http://host/path//", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "http", "", "", "host", 80, "/path/", "", "", ""};
  332. TUri url;
  333. URL_TEST(url, test);
  334. url.FldMemSet(TField::FieldScheme, "HTTPs");
  335. UNIT_ASSERT_EQUAL(TScheme::SchemeHTTPS, url.GetScheme());
  336. UNIT_ASSERT_EQUAL("https", url.GetField(TField::FieldScheme));
  337. url.FldMemSet(TField::FieldScheme, "HtTP");
  338. UNIT_ASSERT_EQUAL(TScheme::SchemeHTTP, url.GetScheme());
  339. UNIT_ASSERT_EQUAL("http", url.GetField(TField::FieldScheme));
  340. }
  341. {
  342. const TString scheme = "http";
  343. const TString host = "host.com";
  344. const TString urlstr = scheme + "://" + host;
  345. TTest test = {
  346. urlstr, TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, scheme, "", "", host, 80, "/", "", "", ""};
  347. TUri url;
  348. URL_TEST(url, test);
  349. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), urlstr + "/");
  350. }
  351. }
  352. Y_UNIT_TEST(test08) {
  353. {
  354. TTest test = {
  355. "mailto://user@host.com", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "mailto", "user", "", "host.com", 0, "", "", "", ""};
  356. TUri url;
  357. URL_TEST(url, test);
  358. }
  359. {
  360. TTest test = {
  361. "host:/path/.path/.", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "host", "", "", "", 0, "/path/.path/", "", "", ""};
  362. TUri url;
  363. URL_TEST(url, test);
  364. }
  365. {
  366. TTest test = {
  367. "host:1/path/.path/.", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "", "", "", "host", 1, "/path/.path/", "", "", ""};
  368. TUri url;
  369. URL_TEST(url, test);
  370. }
  371. {
  372. TTest test = {
  373. "host:1/path/.path/.", TFeature::FeaturesAll | TFeature::FeatureAllowRootless, TState::ParsedOK, "host", "", "", "", 0, "1/path/.path/.", "", "", ""};
  374. TUri url;
  375. URL_TEST(url, test);
  376. }
  377. {
  378. TTest test = {
  379. "/[foo]:bar", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "", "", "", "", 0, "/[foo]:bar", "", "", ""};
  380. TUri url;
  381. URL_TEST(url, test);
  382. }
  383. {
  384. TTest test = {
  385. ".", TFeature::FeaturesAll, TState::ParsedOK, "", "", "", "", 0, "", "", "", ""};
  386. TUri url;
  387. URL_TEST(url, test);
  388. }
  389. {
  390. TTest test = {
  391. ".", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "", "", "", "", 0, "", "", "", ""};
  392. TUri url;
  393. URL_TEST(url, test);
  394. }
  395. {
  396. TTest test = {
  397. "././.", TFeature::FeaturesAll, TState::ParsedOK, "", "", "", "", 0, "", "", "", ""};
  398. TUri url;
  399. URL_TEST(url, test);
  400. }
  401. {
  402. TTest test = {
  403. "././.", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "", "", "", "", 0, "", "", "", ""};
  404. TUri url;
  405. URL_TEST(url, test);
  406. }
  407. {
  408. TTest test = {
  409. "./path", TFeature::FeaturesAll, TState::ParsedOK, "", "", "", "", 0, "path", "", "", ""};
  410. TUri url;
  411. URL_TEST(url, test);
  412. }
  413. {
  414. TTest test = {
  415. "./path", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "", "", "", "", 0, "path", "", "", ""};
  416. TUri url;
  417. URL_TEST(url, test);
  418. }
  419. {
  420. TTest test = {
  421. "../path", TFeature::FeaturesAll, TState::ParsedOK, "", "", "", "", 0, "../path", "", "", ""};
  422. TUri url;
  423. URL_TEST(url, test);
  424. }
  425. {
  426. TTest test = {
  427. "../path", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "", "", "", "", 0, "../path", "", "", ""};
  428. TUri url;
  429. URL_TEST(url, test);
  430. }
  431. {
  432. TTest test = {
  433. "/../path", TFeature::FeaturesAll, TState::ParsedOK, "", "", "", "", 0, "/path", "", "", ""};
  434. TUri url;
  435. URL_TEST(url, test);
  436. }
  437. }
  438. Y_UNIT_TEST(test09) {
  439. {
  440. TTest test = {
  441. "mailto:user@host.com", TFeature::FeaturesAll | TFeature::FeatureAllowRootless, TState::ParsedOK, "mailto", "", "", "", 0, "user@host.com", "", "", ""};
  442. TUri url;
  443. URL_TEST(url, test);
  444. }
  445. {
  446. TTest test = {
  447. "scheme:", TFeature::FeaturesAll | TFeature::FeatureNoRelPath | TFeature::FeatureAllowRootless, TState::ParsedOK, "scheme", "", "", "", 0, "", "", "", ""};
  448. TUri url;
  449. URL_TEST(url, test);
  450. }
  451. {
  452. TTest test = {
  453. "scheme:", TFeature::FeaturesAll | TFeature::FeatureAllowRootless, TState::ParsedOK, "scheme", "", "", "", 0, "", "", "", ""};
  454. TUri url;
  455. URL_TEST(url, test);
  456. }
  457. }
  458. Y_UNIT_TEST(test10) {
  459. // test some escaping madness, note the ehost vs host
  460. {
  461. TString host = "президент.рф";
  462. TString ehost = "%D0%BF%D1%80%D0%B5%D0%B7%D0%B8%D0%B4%D0%B5%D0%BD%D1%82.%D1%80%D1%84";
  463. const TString urlstr = TString::Join("http://", host, "/");
  464. TTest test = {
  465. urlstr, TFeature::FeatureEncodeExtendedASCII | TFeature::FeaturesDefault | TFeature::FeatureCheckHost, TState::ParsedBadHost, "http", "", "", ehost, 80, "/", "", "", ""};
  466. TUri url;
  467. URL_TEST(url, test);
  468. }
  469. {
  470. TString host = "%D0%BF%D1%80%D0%B5%D0%B7%D0%B8%D0%B4%D0%B5%D0%BD%D1%82.%D1%80%D1%84";
  471. const TString urlstr = TString::Join("http://", host, "/");
  472. TTest test = {
  473. urlstr, TFeature::FeatureEncodeExtendedASCII | TFeature::FeaturesDefault | TFeature::FeatureCheckHost, TState::ParsedBadHost, "http", "", "", host, 80, "/", "", "", ""};
  474. TUri url;
  475. URL_TEST(url, test);
  476. }
  477. {
  478. TString host = "Фilip.ru";
  479. TString ehost = "%D0%A4ilip.ru";
  480. const TString urlstr = TString::Join("http://", host);
  481. TTest test = {
  482. urlstr, TFeature::FeatureEncodeExtendedASCII | TFeature::FeaturesDefault, TState::ParsedBadHost, "http", "", "", ehost, 80, "/", "", "", ""};
  483. TUri url;
  484. URL_TEST(url, test);
  485. }
  486. {
  487. TString host = "%D0%A4ilip.ru";
  488. const TString urlstr = TString::Join("http://", host);
  489. TTest test = {
  490. urlstr, TFeature::FeatureEncodeExtendedASCII | TFeature::FeaturesDefault, TState::ParsedBadHost, "http", "", "", host, 80, "/", "", "", ""};
  491. TUri url;
  492. URL_TEST(url, test);
  493. }
  494. {
  495. TString host = "Filip%90.rЯ";
  496. TString ehost = "Filip%90.r%D0%AF";
  497. const TString urlstr = TString::Join(host, ":8080");
  498. TTest test = {
  499. urlstr, TFeature::FeatureEncodeExtendedASCII | TFeature::FeatureDecodeAllowed | TFeature::FeaturesDefault | TFeature::FeatureNoRelPath, TState::ParsedBadHost, "", "", "", ehost, 8080, "", "", "", ""};
  500. TUri url;
  501. URL_TEST(url, test);
  502. }
  503. {
  504. TString host = "Filip%90.r%D0%AF";
  505. const TString urlstr = TString::Join(host, ":8080");
  506. TTest test = {
  507. urlstr, TFeature::FeatureEncodeExtendedASCII | TFeature::FeatureDecodeAllowed | TFeature::FeaturesDefault | TFeature::FeatureNoRelPath, TState::ParsedBadHost, "", "", "", host, 8080, "", "", "", ""};
  508. TUri url;
  509. URL_TEST(url, test);
  510. }
  511. }
  512. Y_UNIT_TEST(test11) {
  513. {
  514. TTest test = {
  515. "HtTp://HoSt/%50aTh/?Query#Frag", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedOK, "http", "", "", "host", 80, "/PaTh/", "Query", "Frag", ""};
  516. TUri url;
  517. URL_TEST(url, test);
  518. }
  519. {
  520. TTest test = {
  521. "HtTp://HoSt/%50a%54h/?Query#Frag", TParseFlags(TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TFeature::FeatureToLower), TState::ParsedOK, "http", "", "", "host", 80, "/path/", "query", "frag", ""};
  522. TUri url;
  523. URL_TEST(url, test);
  524. }
  525. }
  526. Y_UNIT_TEST(test12) {
  527. // test characters which are not always safe
  528. {
  529. #define RAW "/:"
  530. #define DEC "%2F:"
  531. #define ENC "%2F%3A"
  532. TTest test = {
  533. "http://" ENC ":" ENC "@host/" ENC "?" ENC "#" ENC, TFeature::FeaturesAll, TState::ParsedOK, "http", RAW, RAW, "host", 80, "/" DEC, RAW, RAW, ""};
  534. TUri url;
  535. URL_TEST(url, test);
  536. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" ENC ":" ENC "@host/" DEC "?" RAW "#" RAW);
  537. #undef RAW
  538. #undef DEC
  539. #undef ENC
  540. }
  541. {
  542. #define RAW "?@"
  543. #define DEC "%3F@"
  544. #define ENC "%3F%40"
  545. TTest test = {
  546. "http://" ENC ":" ENC "@host/" ENC "?" ENC "#" ENC, TFeature::FeaturesAll, TState::ParsedOK, "http", RAW, RAW, "host", 80, "/" DEC, RAW, RAW, ""};
  547. TUri url;
  548. URL_TEST(url, test);
  549. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" ENC ":" ENC "@host/" DEC "?" RAW "#" RAW);
  550. #undef RAW
  551. #undef DEC
  552. #undef ENC
  553. }
  554. {
  555. #define RAW "%&;="
  556. #define DEC "%25&;="
  557. #define ENC "%25%26%3B%3D"
  558. TTest test = {
  559. "http://" ENC ":" ENC "@host/" ENC "?" ENC "#" ENC, TFeature::FeaturesAll, TState::ParsedOK, "http", RAW, RAW, "host", 80, "/" ENC, ENC, ENC, ""};
  560. TUri url;
  561. URL_TEST(url, test);
  562. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" ENC ":" ENC "@host/" ENC "?" ENC "#" ENC);
  563. #undef RAW
  564. #undef DEC
  565. #undef ENC
  566. }
  567. {
  568. #define RAW "!$'()*,"
  569. #define DEC "!$%27()*,"
  570. #define ENC "%21%24%27%28%29%2A%2C"
  571. TTest test = {
  572. "http://" ENC ":" ENC "@host/" ENC "?" ENC "#" ENC, TFeature::FeaturesAll, TState::ParsedOK, "http", RAW, RAW, "host", 80, "/" ENC, DEC, DEC, ""};
  573. TUri url;
  574. URL_TEST(url, test);
  575. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" ENC ":" ENC "@host/" ENC "?" DEC "#" DEC);
  576. #undef RAW
  577. #undef DEC
  578. #undef ENC
  579. }
  580. {
  581. #define DEC "Череповец。рф"
  582. #define ENC "%D0%A7%D0%B5%D1%80%D0%B5%D0%BF%D0%BE%D0%B2%D0%B5%D1%86%E3%80%82%D1%80%D1%84"
  583. // punycode corresponds to lowercase
  584. #define PNC "xn--b1afab7bff7cb.xn--p1ai"
  585. TTest test = {
  586. "http://" ENC "/" ENC "?" ENC "#" ENC, TParseFlags(TFeature::FeaturesAll | TFeature::FeatureAllowHostIDN, TFeature::FeatureDecodeExtendedASCII), TState::ParsedOK, "http", "", "", DEC, 80, "/" ENC, ENC, ENC, ""};
  587. TUri url;
  588. URL_TEST(url, test);
  589. UNIT_ASSERT_VALUES_EQUAL(url.GetField(TField::FieldHostAscii), PNC);
  590. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" DEC "/" ENC "?" ENC "#" ENC);
  591. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(TField::FlagHostAscii), "http://" PNC "/" ENC "?" ENC "#" ENC);
  592. #undef PNC
  593. #undef DEC
  594. #undef ENC
  595. }
  596. {
  597. #define DEC "Череповец。рф"
  598. #define ENC "%D0%A7%D0%B5%D1%80%D0%B5%D0%BF%D0%BE%D0%B2%D0%B5%D1%86%E3%80%82%D1%80%D1%84"
  599. // punycode corresponds to lowercase
  600. #define PNC "xn--b1afab7bff7cb.xn--p1ai"
  601. TTest test = {
  602. "http://" DEC "/" DEC "?" DEC "#" DEC, TParseFlags(TFeature::FeaturesRobot | TFeature::FeatureEncodeExtendedASCII), TState::ParsedOK, "http", "", "", PNC, 80, "/" ENC, ENC, ENC, ""};
  603. TUri url;
  604. URL_TEST(url, test);
  605. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" PNC "/" ENC "?" ENC "#" ENC);
  606. #undef PNC
  607. #undef DEC
  608. #undef ENC
  609. }
  610. {
  611. #define DEC "независимая-экспертиза-оценка-ущерба-авто-дтп.рф"
  612. #define PNC "xn--------3veabbbbjgk5abecc3afsad2cg8bvq2alouolqf5brd3a4jzftgqd.xn--p1ai"
  613. TTest test = {
  614. "http://" DEC "/", TParseFlags(TFeature::FeaturesRobot), TState::ParsedOK, "http", "", "", PNC, 80, "/", "", "", ""};
  615. TUri url;
  616. URL_TEST(url, test);
  617. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" PNC "/");
  618. #undef PNC
  619. #undef DEC
  620. }
  621. }
  622. Y_UNIT_TEST(testFlexibleAuthority) {
  623. TUri uri;
  624. UNIT_ASSERT_EQUAL(uri.Parse("http://hello_world", TFeature::FeatureCheckHost), TState::ParsedBadHost);
  625. UNIT_ASSERT_EQUAL(uri.Parse("http://hello_world", TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  626. UNIT_ASSERT_VALUES_EQUAL(uri.GetHost(), "hello_world");
  627. UNIT_ASSERT_EQUAL(uri.Parse("httpzzzzz://)(*&^$!\\][';<>`~,q?./index.html", TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  628. UNIT_ASSERT_VALUES_EQUAL(uri.GetHost(), ")(*&^$!\\][';<>`~,q");
  629. UNIT_ASSERT_VALUES_EQUAL(uri.GetField(TField::FieldPath), "");
  630. UNIT_ASSERT_VALUES_EQUAL(uri.GetField(TField::FieldQuery), "./index.html");
  631. UNIT_ASSERT_EQUAL(uri.Parse("htttttttp://)(*&^%45$!\\][';<>`~,.q/index.html", TFeature::FeatureSchemeFlexible), TState::ParsedOK);
  632. UNIT_ASSERT_VALUES_EQUAL(uri.GetHost(), ")(*&^e$!\\][';<>`~,.q");
  633. UNIT_ASSERT_VALUES_EQUAL(uri.GetField(TField::FieldPath), "/index.html");
  634. UNIT_ASSERT_VALUES_EQUAL(uri.GetField(TField::FieldQuery), "");
  635. }
  636. Y_UNIT_TEST(testSpecialChar) {
  637. // test characters which are not always allowed
  638. {
  639. TTest test = {
  640. "http://host/pa th", TFeature::FeaturesAll | TFeature::FeatureEncodeSpace, TState::ParsedOK, "http", "", "", "host", 80, "/pa%20th", "", "", ""};
  641. TUri url;
  642. URL_TEST(url, test);
  643. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host/pa%20th");
  644. }
  645. {
  646. TTest test = {
  647. "http://host/pa th", TFeature::FeaturesAll, TState::ParsedBadFormat, "http", "", "", "host", 80, "/pa th", "", "", ""};
  648. TUri url;
  649. URL_TEST(url, test);
  650. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host/pa th");
  651. }
  652. {
  653. TTest test = {
  654. "http://host/pa%th%41", TFeature::FeaturesAll | TFeature::FeatureEncodePercent, TState::ParsedOK, "http", "", "", "host", 80, "/pa%25thA", "", "", ""};
  655. TUri url;
  656. URL_TEST(url, test);
  657. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host/pa%25thA");
  658. }
  659. {
  660. TTest test = {
  661. "http://host/invalid_second_char%az%1G", TFeature::FeaturesAll | TFeature::FeatureEncodePercent, TState::ParsedOK, "http", "", "", "host", 80, "/invalid_second_char%25az%251G", "", "", ""};
  662. TUri url;
  663. URL_TEST(url, test);
  664. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host/invalid_second_char%25az%251G");
  665. }
  666. {
  667. TTest test = {
  668. "http://host/border%2", TFeature::FeaturesAll | TFeature::FeatureEncodePercent, TState::ParsedOK, "http", "", "", "host", 80, "/border%252", "", "", ""};
  669. TUri url;
  670. URL_TEST(url, test);
  671. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host/border%252");
  672. }
  673. {
  674. TTest test = {
  675. "http://host/pa%th%41", TFeature::FeaturesAll, TState::ParsedBadFormat, "http", "", "", "host", 80, "/pa%thA", "", "", ""};
  676. TUri url;
  677. URL_TEST(url, test);
  678. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host/pa%thA");
  679. }
  680. }
  681. Y_UNIT_TEST(testIPv6) {
  682. {
  683. #define RAW "[1080:0:0:0:8:800:200C:417A]"
  684. #define DEC "[1080:0:0:0:8:800:200c:417a]"
  685. TTest test = {
  686. "http://" RAW "/" RAW "?" RAW "#" RAW, TParseFlags(TFeature::FeaturesAll), TState::ParsedOK, "http", "", "", DEC, 80, "/" RAW, RAW, RAW, ""};
  687. TUri url;
  688. URL_TEST(url, test);
  689. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://" DEC "/" RAW "?" RAW "#" RAW);
  690. #undef DEC
  691. #undef RAW
  692. }
  693. }
  694. Y_UNIT_TEST(testEscapedFragment) {
  695. {
  696. TTest test = {
  697. "http://host.com#!a=b&c=d#e+g%41%25", TParseFlags(TFeature::FeaturesAll | TFeature::FeatureHashBangToEscapedFragment), TState::ParsedOK, "http", "", "", "host.com", 80, "/", "_escaped_fragment_=a=b%26c=d%23e%2BgA%2525", "", ""};
  698. TUri url;
  699. URL_TEST(url, test);
  700. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host.com/?_escaped_fragment_=a=b%26c=d%23e%2BgA%2525");
  701. }
  702. {
  703. TTest test = {
  704. "http://host.com?_escaped_fragment_=a=b%26c=d%23e%2bg%2525", TParseFlags(TFeature::FeaturesAll | TFeature::FeatureEscapedToHashBangFragment), TState::ParsedOK, "http", "", "", "host.com", 80, "/", "", "!a=b&c=d#e+g%25", ""};
  705. TUri url;
  706. URL_TEST(url, test);
  707. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host.com/#!a=b&c=d#e+g%25");
  708. }
  709. }
  710. Y_UNIT_TEST(testHashBang) {
  711. {
  712. TTest test = {
  713. "http://host.com#!?a=b&c=d#e+g%41%25", TParseFlags(TFeature::FeaturesAll | TFeature::FeatureFragmentToHashBang), TState::ParsedOK, "http", "", "", "host.com", 80, "/", "", "", "%3Fa=b%26c=d%23e%2BgA%25"};
  714. TUri url;
  715. URL_TEST(url, test);
  716. UNIT_ASSERT_VALUES_EQUAL(url.PrintS(), "http://host.com/#!%3Fa=b%26c=d%23e%2BgA%25");
  717. }
  718. }
  719. Y_UNIT_TEST(testReEncode) {
  720. {
  721. TStringStream out;
  722. TUri::ReEncode(out, "foo bar");
  723. UNIT_ASSERT_VALUES_EQUAL(out.Str(), "foo%20bar");
  724. }
  725. }
  726. static const TStringBuf NonRfcUrls[] = {
  727. "http://deshevle.ru/price/price=&SrchTp=1&clID=24&BL=SrchTp=0|clID=24&frmID=75&SortBy=P&PreSort=&NmDir=0&VndDir=0&PrDir=0&SPP=44",
  728. "http://secure.rollerwarehouse.com/skates/aggressive/skates/c/11[03]/tx/$$$+11[03][a-z]",
  729. "http://secure.rollerwarehouse.com/skates/aggressive/skates/tx/$$$+110[a-z]",
  730. "http://translate.google.com/translate_t?langpair=en|ru",
  731. "http://www.garnier.com.ru/_ru/_ru/our_products/products_trade.aspx?tpcode=OUR_PRODUCTS^PRD_BODYCARE^EXTRA_SKIN^EXTRA_SKIN_BENEFITS",
  732. "http://www.km.ru/magazin/view_print.asp?id={1846295A-223B-41DC-9F51-90D5D6236C49}",
  733. "http://www.manutd.com/default.sps?pagegid={78F24B85-702C-4DC8-A5D4-2F67252C28AA}&itype=12977&pagebuildpageid=2716&bg=1",
  734. "http://www.pokupay.ru/price/price=&SrchTp=1&clID=24&BL=SrchTp=0|clID=24&frmID=75&SPP=35&SortBy=N&PreSort=V&NmDir=0&VndDir=1&PrDir=0",
  735. "http://www.rodnoyspb.ru/rest/plager/page[0].html",
  736. "http://www.trinity.by/?section_id=46,47,48&cat=1&filters[]=2^_^Sony",
  737. "http://translate.yandex.net/api/v1/tr.json/translate?lang=en-ru&text=>",
  738. nullptr};
  739. Y_UNIT_TEST(test_NonRfcUrls) {
  740. TUri url;
  741. const long flags = TFeature::FeaturesRobot;
  742. for (size_t i = 0;; ++i) {
  743. const TStringBuf& buf = NonRfcUrls[i];
  744. if (!buf.IsInited())
  745. break;
  746. UNIT_ASSERT_VALUES_EQUAL(TState::ParsedOK, url.Parse(buf, flags));
  747. }
  748. }
  749. static const TStringBuf CheckParseException[] = {
  750. "http://www.'>'.com/?.net/",
  751. nullptr};
  752. Y_UNIT_TEST(test_CheckParseException) {
  753. TUri url;
  754. const long flags = TFeature::FeaturesRobot | TFeature::FeaturesEncode;
  755. for (size_t i = 0;; ++i) {
  756. const TStringBuf& buf = CheckParseException[i];
  757. if (!buf.IsInited())
  758. break;
  759. TString what;
  760. try {
  761. // we care only about exceptions, not whether it parses correctly
  762. url.Parse(buf, flags);
  763. continue;
  764. } catch (const std::exception& exc) {
  765. what = exc.what();
  766. } catch (...) {
  767. what = "exception thrown";
  768. }
  769. ythrow yexception() << "failed to parse URL [" << buf << "]: " << what;
  770. }
  771. }
  772. Y_UNIT_TEST(test_PrintPort) {
  773. TUri uri;
  774. {
  775. uri.Parse("http://srv.net:9100/print", TFeature::FeaturesRecommended);
  776. TString s = uri.PrintS(TUri::FlagPort);
  777. Cdbg << uri.PrintS() << ',' << uri.PrintS(TUri::FlagPort) << Endl;
  778. UNIT_ASSERT_VALUES_EQUAL(9100, FromString<ui32>(s));
  779. }
  780. {
  781. uri.Parse("http://srv.net:80/print", TFeature::FeaturesRecommended);
  782. TString s = uri.PrintS(TUri::FlagPort);
  783. Cdbg << uri.PrintS() << ',' << uri.PrintS(TUri::FlagPort) << Endl;
  784. UNIT_ASSERT(s.Empty());
  785. }
  786. }
  787. Y_UNIT_TEST(test_ParseFailures) {
  788. {
  789. TTest test = {
  790. "http://host:port", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedBadFormat, "", "", "", "", Max<ui16>(), "", "", "", ""};
  791. TUri url(-1);
  792. URL_TEST(url, test);
  793. }
  794. {
  795. TTest test = {
  796. "http://javascript:alert(hi)", TFeature::FeaturesRobot, TState::ParsedBadFormat, "", "", "", "", Max<ui16>(), "", "", "", ""};
  797. TUri url(-1);
  798. URL_TEST(url, test);
  799. }
  800. {
  801. TTest test = {
  802. "http://host::0", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedBadFormat, "", "", "", "", Max<ui16>(), "", "", "", ""};
  803. TUri url(-1);
  804. URL_TEST(url, test);
  805. }
  806. {
  807. TTest test = {
  808. "http://host ", TFeature::FeaturesAll, TState::ParsedBadFormat, "", "", "", "", Max<ui16>(), "", "", "", ""};
  809. TUri url(-1);
  810. URL_TEST(url, test);
  811. }
  812. {
  813. TTest test = {
  814. "http:00..03", TFeature::FeaturesAll | TFeature::FeatureNoRelPath, TState::ParsedBadFormat, "", "", "", "", Max<ui16>(), "", "", "", ""};
  815. TUri url(-1);
  816. URL_TEST(url, test);
  817. }
  818. {
  819. TTest test = {
  820. "host:00..03", TFeature::FeaturesAll, TState::ParsedRootless, "host", "", "", "", 0, "", "", "", ""};
  821. TUri url(-1);
  822. URL_TEST(url, test);
  823. }
  824. {
  825. TTest test = {
  826. "http://roduct;isbn,0307371549;at,aid4c00179ab018www.mcnamarasband.wordpress.com/", TFeature::FeaturesAll, TState::ParsedBadHost, "http", "", "", "roduct;isbn,0307371549;at,aid4c00179ab018www.mcnamarasband.wordpress.com", 80, "/", "", "", ""};
  827. TUri url(-1);
  828. URL_TEST(url, test);
  829. }
  830. {
  831. TTest test = {
  832. "invalid url", TFeature::FeaturesDefault, TState::ParsedBadFormat, "", "", "", "", 0, "invalid url", "", "", ""};
  833. TUri url(-1);
  834. URL_TEST(url, test);
  835. }
  836. }
  837. Y_UNIT_TEST(test_scheme_related_url) {
  838. TUri url;
  839. UNIT_ASSERT_VALUES_EQUAL(url.Parse("//www.hostname.ru/path", TFeature::FeaturesRobot), TState::ParsedOK);
  840. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeEmpty);
  841. UNIT_ASSERT_VALUES_EQUAL(url.GetHost(), "www.hostname.ru");
  842. UNIT_ASSERT_VALUES_EQUAL(url.GetField(TField::FieldPath), "/path");
  843. TUri baseUrl;
  844. UNIT_ASSERT_VALUES_EQUAL(baseUrl.Parse("https://trololo.com", TFeature::FeaturesRobot), TState::ParsedOK);
  845. UNIT_ASSERT_EQUAL(baseUrl.GetScheme(), TScheme::SchemeHTTPS);
  846. url.Merge(baseUrl);
  847. UNIT_ASSERT_EQUAL(url.GetScheme(), TScheme::SchemeHTTPS);
  848. UNIT_ASSERT_VALUES_EQUAL(url.GetHost(), "www.hostname.ru");
  849. UNIT_ASSERT_VALUES_EQUAL(url.GetField(TField::FieldPath), "/path");
  850. }
  851. }
  852. Y_UNIT_TEST_SUITE(TInvertDomainTest) {
  853. Y_UNIT_TEST(TestInvert) {
  854. TString a;
  855. UNIT_ASSERT_EQUAL(InvertDomain(a), "");
  856. TString aa(".:/foo");
  857. UNIT_ASSERT_EQUAL(InvertDomain(aa), ".:/foo");
  858. TString aaa("/foo.bar:");
  859. UNIT_ASSERT_EQUAL(InvertDomain(aaa), "/foo.bar:");
  860. TString b("ru");
  861. UNIT_ASSERT_EQUAL(InvertDomain(b), "ru");
  862. TString c(".ru");
  863. UNIT_ASSERT_EQUAL(InvertDomain(c), "ru.");
  864. TString d("ru.");
  865. UNIT_ASSERT_EQUAL(InvertDomain(d), ".ru");
  866. TString e("www.yandex.ru:80/yandsearch?text=foo");
  867. UNIT_ASSERT_EQUAL(InvertDomain(e), "ru.yandex.www:80/yandsearch?text=foo");
  868. TString f("www.yandex.ru:80/yandsearch?text=foo");
  869. InvertDomain(f.begin(), f.begin() + 10);
  870. UNIT_ASSERT_EQUAL(f, "yandex.www.ru:80/yandsearch?text=foo");
  871. TString g("https://www.yandex.ru:80//");
  872. UNIT_ASSERT_EQUAL(InvertDomain(g), "https://ru.yandex.www:80//");
  873. TString h("www.yandex.ru:8080/redir.pl?url=https://google.com/");
  874. UNIT_ASSERT_EQUAL(InvertDomain(h), "ru.yandex.www:8080/redir.pl?url=https://google.com/");
  875. }
  876. }
  877. TQueryArg::EProcessed ProcessQargs(TString url, TString& processed, TQueryArgFilter filter = 0, void* filterData = 0) {
  878. TUri uri;
  879. uri.Parse(url, NUri::TFeature::FeaturesRecommended);
  880. TQueryArgProcessing processing(TQueryArg::FeatureSortByName | (filter ? TQueryArg::FeatureFilter : 0) | TQueryArg::FeatureRewriteDirty, filter, filterData);
  881. auto result = processing.Process(uri);
  882. processed = uri.PrintS();
  883. return result;
  884. }
  885. TString SortQargs(TString url) {
  886. TString r;
  887. ProcessQargs(url, r);
  888. return r;
  889. }
  890. bool QueryArgsFilter(const TQueryArg& arg, void* filterData) {
  891. const char* skipName = static_cast<const char*>(filterData);
  892. return arg.Name != skipName;
  893. }
  894. TString FilterQargs(TString url, const char* name) {
  895. TString r;
  896. ProcessQargs(url, r, &QueryArgsFilter, const_cast<char*>(name));
  897. return r;
  898. }
  899. Y_UNIT_TEST_SUITE(QargsTest) {
  900. Y_UNIT_TEST(TestSorting) {
  901. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/"), "http://ya.ru/");
  902. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?"), "http://ya.ru/?");
  903. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?some=value"), "http://ya.ru/?some=value");
  904. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?b=1&a=2"), "http://ya.ru/?a=2&b=1");
  905. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?b=1&a=2&a=3"), "http://ya.ru/?a=2&a=3&b=1");
  906. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?aaa=3&b=b&a=1&aa=2"), "http://ya.ru/?a=1&aa=2&aaa=3&b=b");
  907. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?a=1&b=1&c=1"), "http://ya.ru/?a=1&b=1&c=1");
  908. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?b=1&a=1&c=1"), "http://ya.ru/?a=1&b=1&c=1");
  909. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?c=1&a=1&b=1"), "http://ya.ru/?a=1&b=1&c=1");
  910. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?c=1&a=1&a=1&b=1&c=1&b=1"), "http://ya.ru/?a=1&a=1&b=1&b=1&c=1&c=1");
  911. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?b==&a=&&c="), "http://ya.ru/?a=&b==&c=");
  912. }
  913. Y_UNIT_TEST(TestParsingCorners) {
  914. TString s;
  915. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?=", s), TQueryArg::ProcessedOK);
  916. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?some", s), TQueryArg::ProcessedOK);
  917. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?some=", s), TQueryArg::ProcessedOK);
  918. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/", s), TQueryArg::ProcessedOK);
  919. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?&", s), TQueryArg::ProcessedOK);
  920. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?&&", s), TQueryArg::ProcessedOK);
  921. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?some=", s), TQueryArg::ProcessedOK);
  922. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?some==", s), TQueryArg::ProcessedOK);
  923. UNIT_ASSERT_EQUAL(ProcessQargs("http://ya.ru/?some=&&", s), TQueryArg::ProcessedOK);
  924. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?="), "http://ya.ru/?=");
  925. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?some=="), "http://ya.ru/?some==");
  926. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?&&"), "http://ya.ru/?&&");
  927. UNIT_ASSERT_STRINGS_EQUAL(SortQargs("http://ya.ru/?a"), "http://ya.ru/?a");
  928. }
  929. Y_UNIT_TEST(TestFiltering) {
  930. UNIT_ASSERT_STRINGS_EQUAL(FilterQargs("http://ya.ru/?some=value", "missing"), "http://ya.ru/?some=value");
  931. UNIT_ASSERT_STRINGS_EQUAL(FilterQargs("http://ya.ru/?b=1&a=2", "b"), "http://ya.ru/?a=2");
  932. UNIT_ASSERT_STRINGS_EQUAL(FilterQargs("http://ya.ru/?b=1&a=2&a=3", "a"), "http://ya.ru/?b=1");
  933. UNIT_ASSERT_STRINGS_EQUAL(FilterQargs("http://ya.ru/?some=&another=", "another"), "http://ya.ru/?some=");
  934. }
  935. Y_UNIT_TEST(TestRemoveEmptyFeature) {
  936. TUri uri;
  937. uri.Parse("http://ya.ru/?", NUri::TFeature::FeaturesRecommended);
  938. TQueryArgProcessing processing(TQueryArg::FeatureRemoveEmptyQuery | TQueryArg::FeatureRewriteDirty);
  939. auto result = processing.Process(uri);
  940. UNIT_ASSERT_EQUAL(result, TQueryArg::ProcessedOK);
  941. UNIT_ASSERT_STRINGS_EQUAL(uri.PrintS(), "http://ya.ru/");
  942. }
  943. Y_UNIT_TEST(TestNoRemoveEmptyFeature) {
  944. TUri uri;
  945. uri.Parse("http://ya.ru/?", NUri::TFeature::FeaturesRecommended);
  946. TQueryArgProcessing processing(0);
  947. auto result = processing.Process(uri);
  948. UNIT_ASSERT_EQUAL(result, TQueryArg::ProcessedOK);
  949. UNIT_ASSERT_STRINGS_EQUAL(uri.PrintS(), "http://ya.ru/?");
  950. }
  951. }
  952. }