// -*- mode: c++; c-basic-offset: 2; -*- #include "common.hh" #include "test.hh" #include #include #include #include "url.hh" namespace { bool good(std::string const& url, std::string const& scheme, char const* userinfo, std::string const& host, uint16_t port, std::string const& path, char const* query, char const* fragment) { std::unique_ptr u(Url::parse(url)); if (!u) { std::cerr << "good:" << url << ": Invalid url" << std::endl; return false; } if (scheme != u->scheme()) { std::cerr << "good:" << url << ":scheme: Expected " << scheme << " got " << u->scheme() << std::endl; return false; } if (userinfo) { if (u->userinfo()) { if (strcmp(userinfo, u->userinfo())) { std::cerr << "good:" << url << ":authority: Expected " << userinfo << " got " << u->userinfo() << std::endl; return false; } } else { std::cerr << "good:" << url << ":authority: Expected " << userinfo << " got no authority" << std::endl; return false; } } else { if (u->userinfo()) { std::cerr << "good:" << url << ":authority: Expected no authority" << " got " << u->userinfo() << std::endl; return false; } } if (host != u->host()) { std::cerr << "good:" << url << ":host: Expected " << host << " got " << u->host() << std::endl; return false; } if (port != u->port()) { std::cerr << "good:" << url << ":port: Expected " << port << " got " << u->port() << std::endl; return false; } if (path != u->path()) { std::cerr << "good:" << url << ":path: Expected " << path << " got " << u->path() << std::endl; return false; } if (query) { if (u->full_query()) { if (strcmp(query, u->full_query())) { std::cerr << "good:" << url << ":query: Expected " << query << " got " << u->full_query() << std::endl; return false; } } else { std::cerr << "good:" << url << ":query: Expected " << query << " got no query" << std::endl; return false; } } else { if (u->full_query()) { std::cerr << "good:" << url << ":query: Expected no query" << " got " << u->full_query() << std::endl; return false; } } if (fragment) { if (u->fragment()) { if (strcmp(fragment, u->fragment())) { std::cerr << "good:" << url << ":fragment: Expected " << fragment << " got " << u->fragment() << std::endl; return false; } } else { std::cerr << "good:" << url << ":fragment: Expected " << fragment << " got no fragment" << std::endl; return false; } } else { if (u->fragment()) { std::cerr << "good:" << url << ":fragment: Expected no fragment" << " got " << u->fragment() << std::endl; return false; } } return true; } bool query(std::string const& url, std::string const& name, char const* value) { std::unique_ptr u(Url::parse(url)); if (!u) { std::cerr << "query:" << url << ":" << name << ": Invalid url" << std::endl; return false; } std::string tmp; if (u->query(name, &tmp)) { if (!value) { std::cerr << "query:" << url << ":" << name << ": Expected no value got " << tmp << std::endl; return false; } if (tmp.compare(value)) { std::cerr << "query:" << url << ":" << name << ": Expected " << value << " got " << tmp << std::endl; return false; } } else { if (value) { std::cerr << "query:" << url << ":" << name << ": Expected " << value << " got no value" << std::endl; return false; } } return true; } bool bad(std::string const& url) { std::unique_ptr u(Url::parse(url)); if (u) { std::cerr << "bad:" << url << ": Expected invalid url got "; u->print(std::cerr); std::cerr << std::endl; return false; } return true; } bool relative(std::string const& url, std::string const& base, std::string const& full) { std::unique_ptr b(Url::parse(base)); if (!b) { std::cerr << "relative:" << url << ":" << base << ": Invalid base url" << std::endl; return false; } std::unique_ptr u(Url::parse(url, b.get())); if (!u) { std::cerr << "relative:" << url << ":" << base << ": Invalid url" << std::endl; return false; } std::stringstream ss; u->print(ss); if (full != ss.str()) { std::cerr << "relative:" << url << ":" << base << ": Expected " << full << " got " << ss.str() << std::endl; return false; } return true; } bool good_authority(std::string const& str, std::string const& host, uint16_t port) { std::string h; uint16_t p; if (!Url::parse_authority(str, &h, &p)) { std::cerr << "good_authority:" << str << ": Invalid authority" << std::endl; return false; } if (host != h) { std::cerr << "good_authority:" << str << ":host: Expected " << host << " got " << h << std::endl; return false; } if (port != p) { std::cerr << "good_authority:" << str << ":port: Expected " << port << " got " << p << std::endl; return false; } return true; } bool bad_authority(std::string const& str) { std::string h; uint16_t p; if (Url::parse_authority(str, &h, &p)) { std::cerr << "bad_authority:" << str << ": Expected invalid autority got " << h << ':' << p << std::endl; return false; } return true; } } // namespace int main() { BEFORE; RUN(good("http://example.org", "http", nullptr, "example.org", 0, "", nullptr, nullptr)); RUN(good("http://example.org/", "http", nullptr, "example.org", 0, "/", nullptr, nullptr)); RUN(good("http://example.org/index.htm", "http", nullptr, "example.org", 0, "/index.htm", nullptr, nullptr)); RUN(good("http://example.org:80?foo", "http", nullptr, "example.org", 80, "", "foo", nullptr)); RUN(good("http://user@example.org#foo", "http", "user", "example.org", 0, "", nullptr, "foo")); RUN(good("http://user:pw@example.org?foo#bar", "http", "user:pw", "example.org", 0, "", "foo", "bar")); RUN(good("http://%40user@example.org/foo%2fbar?a=%25+%20+%23#frag%25", "http", "@user", "example.org", 0, "/foo/bar", "a=% #", "frag%")); RUN(query("http://host?foo=bar", "foo", "bar")); RUN(query("http://host?foo=bar", "bar", nullptr)); RUN(query("http://host?foo=bar", "fo", nullptr)); RUN(query("http://host?foo=bar", "", nullptr)); RUN(query("http://host?foo=bar&foo=k", "foo", "bar")); RUN(query("http://host?foo=bar&bar=foo", "bar", "foo")); RUN(bad("")); RUN(bad("/")); RUN(bad("http")); RUN(bad("http://")); RUN(bad("http:///")); RUN(bad("http://meh@/")); RUN(bad("http://.meh@/")); RUN(bad("http://.meh@/foo#frag?q")); RUN(relative("/foo", "http://host/bar", "http://host/foo")); RUN(relative("foo", "http://host/bar", "http://host/bar/foo")); RUN(relative("foo?a=c", "http://host/?a=b", "http://host/foo?a=c")); RUN(relative("foo#c", "http://host/#b", "http://host/foo#c")); RUN(relative("foo#c", "http://host/?b", "http://host/foo#c")); RUN(relative("foo", "http://host/?b", "http://host/foo")); RUN(good_authority("www.example.org", "www.example.org", 0)); RUN(good_authority("www.example.org:80", "www.example.org", 80)); RUN(good_authority("localhost:5678", "localhost", 5678)); RUN(good_authority("[::1]:5678", "::1", 5678)); RUN(good_authority("::1:5678", "::1", 5678)); RUN(bad_authority("foo@localhost")); RUN(bad_authority("")); RUN(bad_authority(":500")); AFTER; }