Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH
#include "mozilla/net/URLPatternGlue.h"
#include "mozilla/net/urlpattern_glue.h"
using namespace mozilla::net;
template <typename T>
using Optional = mozilla::Maybe<T>;
// pattern construction from string
TEST(TestURLPatternGlue, PatternFromString)
{
nsCString str(":café://:foo");
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
bool res = urlp_parse_pattern_from_string(&str, nullptr, options, &pattern);
ASSERT_TRUE(res);
ASSERT_TRUE(pattern._0);
}
TEST(TestURLPatternGlue, PatternFromStringOnlyPathname)
{
nsCString str("/foo/thing");
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
bool res = urlp_parse_pattern_from_string(&str, nullptr, options, &pattern);
ASSERT_FALSE(res);
ASSERT_FALSE(pattern._0);
}
bool operator==(const UrlpInnerMatcher& a, const UrlpInnerMatcher& b) {
if (a.inner_type != b.inner_type) {
return false;
}
switch (a.inner_type) {
case UrlpInnerMatcherType::Literal: {
return a.literal.Equals(b.literal);
}
case UrlpInnerMatcherType::SingleCapture: {
if (a.allow_empty == b.allow_empty &&
a.filter_exists == b.filter_exists) {
if (a.filter_exists) {
return a.filter == b.filter;
}
return true;
}
return false;
}
case UrlpInnerMatcherType::RegExp: {
return a.regexp.Equals(b.regexp);
}
default: {
return false;
}
}
}
bool operator==(const UrlpMatcher& a, const UrlpMatcher& b) {
return a.prefix.Equals(b.prefix) && a.suffix.Equals(b.suffix) &&
a.inner == b.inner;
}
UrlpInit CreateInit(const nsCString& protocol, const nsCString& username,
const nsCString& password, const nsCString& hostname,
const nsCString& port, const nsCString& pathname,
const nsCString& search, const nsCString& hash,
const nsCString& baseUrl) {
return UrlpInit{
.protocol = CreateMaybeString(protocol, !protocol.IsEmpty()),
.username = CreateMaybeString(username, !username.IsEmpty()),
.password = CreateMaybeString(password, !password.IsEmpty()),
.hostname = CreateMaybeString(hostname, !hostname.IsEmpty()),
.port = CreateMaybeString(port, !port.IsEmpty()),
.pathname = CreateMaybeString(pathname, !pathname.IsEmpty()),
.search = CreateMaybeString(search, !search.IsEmpty()),
.hash = CreateMaybeString(hash, !hash.IsEmpty()),
.base_url = CreateMaybeString(baseUrl, !baseUrl.IsEmpty()),
};
}
UrlpInit CreateSimpleInit(const nsCString& protocol, const nsCString& hostname,
const nsCString& pathname) {
return CreateInit(protocol, ""_ns, ""_ns, hostname, ""_ns, pathname, ""_ns,
""_ns, ""_ns);
}
UrlpInit CreateInit(const char* protocol, const char* username,
const char* password, const char* hostname,
const char* port, const char* pathname, const char* search,
const char* hash, const char* base = "") {
return CreateInit(nsCString(protocol), nsCString(username),
nsCString(password), nsCString(hostname), nsCString(port),
nsCString(pathname), nsCString(search), nsCString(hash),
nsCString(base));
}
// pattern construction from init
TEST(TestURLPatternGlue, PatternFromInit)
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
UrlpInit init = CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
ASSERT_TRUE(pattern._0);
auto proto = UrlpGetProtocol(pattern);
ASSERT_EQ(proto, "https"_ns);
}
TEST(TestURLPatternGlue, PatternFromInitOnlyPathname)
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
UrlpInit init = CreateSimpleInit(""_ns, ""_ns, "/foo/thing"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
ASSERT_TRUE(pattern._0);
auto proto = UrlpGetProtocol(pattern);
ASSERT_EQ(proto, nsCString("*"));
auto host = UrlpGetHostname(pattern);
ASSERT_EQ(host, nsCString("*"));
auto path = UrlpGetPathname(pattern);
ASSERT_EQ(path, nsCString("/foo/thing"));
Optional<nsAutoCString> execBaseUrl; // None
UrlpInput input = CreateUrlpInput(init);
Optional<UrlpResult> r = UrlpPatternExec(pattern, input, execBaseUrl);
ASSERT_TRUE(r.isSome());
ASSERT_TRUE(r->mProtocol.isSome());
ASSERT_EQ(r->mProtocol.value().mInput, nsCString(""));
ASSERT_TRUE(r->mPathname.isSome());
ASSERT_EQ(r->mPathname.value().mInput, "/foo/thing"_ns);
}
// pattern getters
TEST(TestURLPatternGlue, UrlPatternGetters)
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
UrlpInit init =
CreateInit("https"_ns, "user"_ns, "passw"_ns, "example.com"_ns, "66"_ns,
"/"_ns, "find"_ns, "anchor"_ns, ""_ns);
bool rv = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(rv);
ASSERT_TRUE(pattern._0);
nsAutoCString res;
res = UrlpGetProtocol(pattern);
ASSERT_EQ(res, nsCString("https"));
res = UrlpGetUsername(pattern);
ASSERT_EQ(res, nsCString("user"));
res = UrlpGetPassword(pattern);
ASSERT_EQ(res, nsCString("passw"));
res = UrlpGetHostname(pattern);
ASSERT_EQ(res, nsCString("example.com"));
res = UrlpGetPort(pattern);
ASSERT_EQ(res, nsCString("66"));
res = UrlpGetPathname(pattern);
ASSERT_EQ(res, nsCString("/"));
res = UrlpGetSearch(pattern);
ASSERT_EQ(res, nsCString("find"));
res = UrlpGetHash(pattern);
ASSERT_EQ(res, nsCString("anchor"));
// neither lib or quirks URLPattern has base_url so nothing to check
}
// UrlPattern.test() from_init
TEST(TestURLPatternGlue, UrlPatternTestInit)
{
// check basic literal matching (minimal fields)
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
UrlpInit init = CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{ // path not fixed up (?)
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, ""_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified user and password is fine
auto test = CreateUrlpInput(
CreateInit("https", "user", "pass", "example.com", "", "/", "", ""));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified port is fine
auto test = CreateUrlpInput(
CreateInit("https", "", "", "example.com", "444", "/", "", ""));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified search is fine
auto test = CreateUrlpInput(
CreateInit("https", "", "", "example.com", "", "/", "thisok", ""));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified hash is fine
auto test = CreateUrlpInput(
CreateInit("https", "", "", "example.com", "", "/", "", "thisok"));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // pathname different
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/a"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // scheme different
auto test = CreateUrlpInput(
CreateSimpleInit("http"_ns, "example.com"_ns, "/"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // domain different
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.org"_ns, "/"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
}
// check basic literal matching
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
auto init =
CreateInit("https"_ns, "user"_ns, "anything"_ns, "example.com"_ns,
"444"_ns, "/"_ns, "query"_ns, "frag"_ns, ""_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
nsCString anything("anything");
Optional<nsCString> base;
{ // exact match
auto test = CreateUrlpInput(init);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // missing protocol
auto test =
CreateUrlpInput(CreateInit("", "user", anything.get(), "example.com",
"444", "/", "query", "frag"));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing user
auto test =
CreateUrlpInput(CreateInit("https", "", anything.get(), "example.com",
"444", "/", "query", "frag"));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing password
auto test = CreateUrlpInput(CreateInit("https", "user", "", "example.com",
"444", "/", "query", "frag"));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing hostname
auto test = CreateUrlpInput(CreateInit("https", "user", anything.get(),
"", "444", "/", "query", "frag"));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing port
auto test =
CreateUrlpInput(CreateInit("https", "user", anything.get(),
"example.com", "", "/", "query", "frag"));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing query
auto test =
CreateUrlpInput(CreateInit("https", "user", anything.get(),
"example.com", "444", "/", "", "frag"));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing frag
auto test =
CreateUrlpInput(CreateInit("https", "user", anything.get(),
"example.com", "444", "/", "query", ""));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
}
// check basic url with wildcard
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
auto init = CreateSimpleInit("https"_ns, "example.com"_ns, "/*"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{ // root path matches wildcard
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // filename matches wildcard
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/thing"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // dir/filename matches wildcard
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/dir/thing"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
}
// check matching in pathname (needs to be at least two slashes)
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
auto init =
CreateSimpleInit("https"_ns, "example.com"_ns, "/:category/*"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{ // no directory and not enough slashes
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // no directory
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "//"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // not enough slashes
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/products"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // dir/ works
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/products/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // diretory/filename
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/blog/thing"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // nested directory
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/blog/thing/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
}
// check optional `s` in protocol
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
auto init = CreateSimpleInit("http{s}?"_ns, "example.com"_ns, "/"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{ // insecure matches
auto test = CreateUrlpInput(
CreateSimpleInit("http"_ns, "example.com"_ns, "/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // secure matches
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
}
// basic relative wildcard path with base domain
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
auto init = CreateInit(""_ns, ""_ns, ""_ns, ""_ns, ""_ns, "/admin/*"_ns,
""_ns, ""_ns, "https://example.com"_ns);
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/admin/"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/admin/thing"_ns));
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // incorrect relative path doesn't match
//
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/nonadmin/"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // root path not matching relative path doesn't match
auto test = CreateUrlpInput(
CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns));
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
}
}
// UrlPattern.test() from_string
TEST(TestURLPatternGlue, UrlPatternTestString)
{
// check basic literal matching (minimal fields)
{
nsCString str("https://example.com/");
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
bool res = urlp_parse_pattern_from_string(&str, nullptr, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{ // path fixed up "/"
auto test = CreateUrlpInput("https://example.com"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified user and password is fine
auto test = CreateUrlpInput("https://user:passw@example.com"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified port is empty so 444 doesn't match
auto test = CreateUrlpInput("https://example.com:444/"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified search is fine
auto test = CreateUrlpInput("https://example.com/?thisok"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // unspecified hash is fine
auto test = CreateUrlpInput("https://example.com/#thisok"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // pathname different
auto test = CreateUrlpInput("https://example.com/a"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // scheme different
auto test = CreateUrlpInput("http://example.com/"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // domain different
auto test = CreateUrlpInput("http://example.org"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
}
// check basic literal matching (all fields, except password)
// because user:pass is parsed as: `username: user:pass, password: *`
// when pattern is from_string
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
nsCString baseUrl("");
bool res =
urlp_parse_pattern_from_string(&str, &baseUrl, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{ // exact match, except password
auto test = CreateUrlpInput(
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // missing protocol
auto test =
CreateUrlpInput("user:anything@example.com:444/?query#frag"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing user
auto test =
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing password is fine
auto test =
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // missing password is fine
auto test =
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // missing hostname
auto test = CreateUrlpInput("https://user:anything@:444/?query#frag"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing port
auto test =
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing query
auto test =
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // missing frag
auto test =
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
}
// check basic url with wildcard
{
nsCString str("https://example.com/*");
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
nsCString baseUrl("");
bool res =
urlp_parse_pattern_from_string(&str, &baseUrl, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{
auto test = CreateUrlpInput("https://example.com/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/thing"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/dir/thing"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
}
// check matching in pathname (needs to be at least two slashes)
{
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
nsCString baseUrl("");
bool res =
urlp_parse_pattern_from_string(&str, &baseUrl, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{
auto test = CreateUrlpInput("https://example.com/"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{ // not enough slashes
auto test = CreateUrlpInput("https://example.com/products"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/products/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/blog/thing"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{ // 3 slashes
auto test = CreateUrlpInput("https://example.com/blog/thing/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
}
// check optional `s` in protocol
{
nsCString str("http{s}?://example.com/");
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
nsCString baseUrl("");
bool res =
urlp_parse_pattern_from_string(&str, &baseUrl, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{
auto test = CreateUrlpInput("http://example.com/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
}
// basic relative wildcard path with base domain
{
nsCString str("../admin/*");
UrlpPattern pattern{};
UrlpOptions options = {.ignore_case = false};
nsCString baseUrl("https://example.com/forum");
// MaybeString baseUrl {.string = "https://example.com/forum"_ns, .valid =
// true };
bool res =
urlp_parse_pattern_from_string(&str, &baseUrl, options, &pattern);
ASSERT_TRUE(res);
Optional<nsCString> base;
{
auto test = CreateUrlpInput("https://example.com/admin/"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/admin/thing"_ns);
ASSERT_TRUE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/nonadmin/"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
{
auto test = CreateUrlpInput("https://example.com/"_ns);
ASSERT_FALSE(UrlpPatternTest(pattern, test, base));
}
}
}
TEST(TestURLPatternGlue, MatchInputFromString)
{
{
nsCString url("https://example.com/");
UrlpMatchInputAndInputs matchInputAndInputs;
bool res = urlp_process_match_input_from_string(&url, nullptr,
&matchInputAndInputs);
ASSERT_TRUE(res);
ASSERT_EQ(matchInputAndInputs.input.protocol, "https"_ns);
ASSERT_EQ(matchInputAndInputs.input.hostname, "example.com"_ns);
ASSERT_EQ(matchInputAndInputs.input.pathname, "/"_ns);
ASSERT_EQ(matchInputAndInputs.input.username, "");
ASSERT_EQ(matchInputAndInputs.input.password, "");
ASSERT_EQ(matchInputAndInputs.input.port, "");
ASSERT_EQ(matchInputAndInputs.input.search, "");
ASSERT_EQ(matchInputAndInputs.input.hash, "");
ASSERT_EQ(matchInputAndInputs.inputs.string_or_init_type,
UrlpStringOrInitType::String);
ASSERT_EQ(matchInputAndInputs.inputs.str, url);
ASSERT_EQ(matchInputAndInputs.inputs.base.valid, false);
}
{
nsCString expected("https://example.com/some/dir");
nsCString base_url("https://example.com");
nsCString relative_url("/some/dir");
UrlpMatchInputAndInputs matchInputAndInputs;
bool res = urlp_process_match_input_from_string(&relative_url, &base_url,
&matchInputAndInputs);
ASSERT_TRUE(res);
ASSERT_EQ(matchInputAndInputs.input.protocol, "https"_ns);
ASSERT_EQ(matchInputAndInputs.input.hostname, "example.com"_ns);
ASSERT_EQ(matchInputAndInputs.input.pathname, "/some/dir"_ns);
ASSERT_EQ(matchInputAndInputs.input.username, "");
ASSERT_EQ(matchInputAndInputs.input.password, "");
ASSERT_EQ(matchInputAndInputs.input.port, "");
ASSERT_EQ(matchInputAndInputs.input.search, "");
ASSERT_EQ(matchInputAndInputs.input.hash, "");
ASSERT_EQ(matchInputAndInputs.inputs.string_or_init_type,
UrlpStringOrInitType::String);
ASSERT_EQ(matchInputAndInputs.inputs.str, relative_url);
ASSERT_EQ(matchInputAndInputs.inputs.base.string, base_url);
}
}
void assert_maybe_string_same(const MaybeString& s1, const MaybeString& s2) {
ASSERT_EQ(s1.valid, s2.valid);
if (s1.valid) {
ASSERT_EQ(s1.string, s2.string);
}
}
void assert_inits_same(const UrlpInit& i1, const UrlpInit& i2) {
assert_maybe_string_same(i1.protocol, i2.protocol);
assert_maybe_string_same(i1.username, i2.username);
assert_maybe_string_same(i1.password, i2.password);
assert_maybe_string_same(i1.hostname, i2.hostname);
assert_maybe_string_same(i1.port, i2.port);
assert_maybe_string_same(i1.pathname, i2.pathname);
assert_maybe_string_same(i1.search, i2.search);
assert_maybe_string_same(i1.hash, i2.hash);
assert_maybe_string_same(i1.base_url, i2.base_url);
}
void assert_match_inputs_same(const UrlpMatchInput& input,
const UrlpMatchInput& expected) {
ASSERT_EQ(input.protocol, expected.protocol);
ASSERT_EQ(input.hostname, expected.hostname);
ASSERT_EQ(input.pathname, expected.pathname);
ASSERT_EQ(input.username, expected.username);
ASSERT_EQ(input.password, expected.password);
ASSERT_EQ(input.port, expected.port);
ASSERT_EQ(input.search, expected.search);
ASSERT_EQ(input.hash, expected.hash);
}
UrlpMatchInput createMatchInputHelper(const nsCString& proto,
const nsCString& host,
const nsCString& path) {
return {
.protocol = proto,
.username = ""_ns,
.password = ""_ns,
.hostname = host,
.port = ""_ns,
.pathname = path,
.search = ""_ns,
.hash = ""_ns,
};
}
TEST(TestURLPatternGlue, MatchInputFromInit)
{
{ // no base init
UrlpMatchInputAndInputs matchInputAndInputs;
auto init = CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns);
auto expected = CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns);
bool res = urlp_process_match_input_from_init(&init, nullptr,
&matchInputAndInputs);
ASSERT_TRUE(res);
UrlpMatchInput expected_match_input =
createMatchInputHelper("https"_ns, "example.com"_ns, "/"_ns);
assert_match_inputs_same(matchInputAndInputs.input, expected_match_input);
ASSERT_EQ(matchInputAndInputs.inputs.string_or_init_type,
UrlpStringOrInitType::Init);
assert_inits_same(matchInputAndInputs.inputs.init, init);
ASSERT_EQ(matchInputAndInputs.inputs.str, ""_ns);
ASSERT_EQ(matchInputAndInputs.inputs.base.valid, false);
}
{ // base + relative url produces expected match input
nsCString expected_base_url("https://example.com");
auto init = CreateInit("", "", "", "", "", "/some/dir", "", "",
UrlpMatchInputAndInputs matchInputAndInputs;
bool res = urlp_process_match_input_from_init(&init, nullptr,
&matchInputAndInputs);
ASSERT_TRUE(res);
UrlpMatchInput expected_match_input =
createMatchInputHelper("https"_ns, "example.com"_ns, "/some/dir"_ns);
assert_match_inputs_same(matchInputAndInputs.input, expected_match_input);
ASSERT_EQ(matchInputAndInputs.inputs.string_or_init_type,
UrlpStringOrInitType::Init);
assert_inits_same(matchInputAndInputs.inputs.init, init);
ASSERT_EQ(matchInputAndInputs.inputs.str, ""_ns);
ASSERT_EQ(matchInputAndInputs.inputs.base.valid, false);
}
}
void assert_matcher_same(UrlpMatcher& componentMatcher, UrlpMatcher& expected) {
ASSERT_EQ(componentMatcher.prefix, expected.prefix);
ASSERT_EQ(componentMatcher.suffix, expected.suffix);
ASSERT_EQ(componentMatcher.inner.inner_type, expected.inner.inner_type);
ASSERT_EQ(componentMatcher.inner.literal, expected.inner.literal);
ASSERT_EQ(componentMatcher.inner.allow_empty, expected.inner.allow_empty);
ASSERT_EQ(componentMatcher.inner.filter_exists, expected.inner.filter_exists);
ASSERT_EQ(componentMatcher.inner.filter, expected.inner.filter);
ASSERT_EQ(componentMatcher.inner.regexp, expected.inner.regexp);
ASSERT_TRUE(componentMatcher == expected);
}
TEST(TestURLPatternGlue, UrlPatternGetComponentBasic)
{
nsCString str("http://:foo");
UrlpOptions options = {.ignore_case = false};
UrlpPattern pattern{};
bool res = urlp_parse_pattern_from_string(&str, nullptr, options, &pattern);
ASSERT_TRUE(res);
ASSERT_TRUE(pattern._0);
UrlpInnerMatcher expectedInnerMatcher = {
.inner_type = UrlpInnerMatcherType::Literal,
.literal = "http"_ns,
.allow_empty = false,
.filter_exists = false,
.filter = 'x',
.regexp = ""_ns,
};
UrlpMatcher expectedMatcher = {
.prefix = ""_ns,
.suffix = ""_ns,
.inner = expectedInnerMatcher,
};
nsCString expectedPatternString("http");
nsCString expectedRegexp("^http$");
UrlpComponent componentProtocol{};
auto protoStr = UrlpGetProtocol(pattern);
ASSERT_EQ(protoStr, expectedPatternString);
auto hostnameStr = UrlpGetHostname(pattern);
nsCString expectedHostnamePatternString(":foo");
nsCString expectedHostnameRegexp("^([^\\.]+?)$");
expectedMatcher.inner.inner_type = UrlpInnerMatcherType::SingleCapture;
expectedMatcher.inner.literal = ""_ns;
expectedMatcher.inner.filter_exists = true;
expectedMatcher.inner.filter = '.';
ASSERT_EQ(hostnameStr, expectedHostnamePatternString);
auto pathnameStr = UrlpGetPathname(pattern);
nsCString expectedPathnamePatternString("*");
nsCString expectedPathnameRegexp("^(.*)$");
expectedMatcher.inner.filter = 'x';
expectedMatcher.inner.allow_empty = true;
ASSERT_EQ(pathnameStr, expectedPathnamePatternString);
}
void assert_pattern_result(UrlpResult& res) {
ASSERT_TRUE(res.mProtocol.isSome());
ASSERT_TRUE(res.mUsername.isSome());
ASSERT_TRUE(res.mPassword.isSome());
ASSERT_TRUE(res.mHostname.isSome());
ASSERT_TRUE(res.mPort.isSome());
ASSERT_TRUE(res.mPathname.isSome());
ASSERT_TRUE(res.mSearch.isSome());
ASSERT_TRUE(res.mHash.isSome());
ASSERT_TRUE(res.mInputs.Length() == 1);
}
TEST(TestURLPatternGlue, UrlPatternExecFromString)
{
nsCString str(":café://:foo");
UrlpOptions options = {.ignore_case = false};
UrlpPattern pattern{};
bool res = urlp_parse_pattern_from_string(&str, nullptr, options, &pattern);
ASSERT_TRUE(res);
ASSERT_TRUE(pattern._0);
nsCString inputString("https://example.com/");
UrlpInput input = CreateUrlpInput(inputString);
Optional<nsAutoCString> execBaseUrl;
Optional<UrlpResult> res2 = UrlpPatternExec(pattern, input, execBaseUrl);
ASSERT_TRUE(res2.isNothing());
}
TEST(TestURLPatternGlue, UrlPatternExecFromInit)
{
UrlpPattern pattern{};
auto init = CreateSimpleInit("https"_ns, "example.com"_ns, "/"_ns);
UrlpOptions options = {.ignore_case = false};
bool res = urlp_parse_pattern_from_init(&init, options, &pattern);
ASSERT_TRUE(res);
ASSERT_TRUE(pattern._0);
UrlpInput input = CreateUrlpInput(init);
Optional<nsAutoCString> execBaseUrl;
Optional<UrlpResult> res2 = UrlpPatternExec(pattern, input, execBaseUrl);
ASSERT_TRUE(res2.isSome());
assert_pattern_result(*res2);
ASSERT_EQ(res2->mProtocol->mInput, "https");
ASSERT_EQ(res2->mUsername->mInput, ""_ns);
ASSERT_EQ(res2->mPassword->mInput, ""_ns);
ASSERT_EQ(res2->mHostname->mInput, "example.com");
ASSERT_EQ(res2->mPort->mInput, ""_ns);
ASSERT_EQ(res2->mPathname->mInput, "/"_ns);
ASSERT_EQ(res2->mSearch->mInput, ""_ns);
ASSERT_EQ(res2->mHash->mInput, ""_ns);
}