From 0353cb98bb0458520599b46bd63c0f8e5f0ae57f Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Sun, 7 Jun 2026 21:27:39 +0200 Subject: [PATCH] Tests/LibURL: Consolidate public suffix tests Having these tests split across two files was annoying to work on. Move the URL Host public suffix and registrable-domain coverage into TestPublicSuffix and combine it with the PublicSuffixData coverage in one table. --- Tests/LibURL/TestPublicSuffix.cpp | 181 +++++++++++++++++++++++------- Tests/LibURL/TestURL.cpp | 108 ------------------ 2 files changed, 139 insertions(+), 150 deletions(-) diff --git a/Tests/LibURL/TestPublicSuffix.cpp b/Tests/LibURL/TestPublicSuffix.cpp index 31e9585cf0..35ce6970a0 100644 --- a/Tests/LibURL/TestPublicSuffix.cpp +++ b/Tests/LibURL/TestPublicSuffix.cpp @@ -9,56 +9,153 @@ #include #include -TEST_CASE(is_public_suffix) +TEST_CASE(public_suffix_matching_for_psl_rules) { + struct TestCase { + StringView input; + bool is_public_suffix; + Optional public_suffix; + Optional registrable_domain; + }; + + TestCase test_cases[] { + { "com"sv, true, "com"sv, OptionalNone {} }, + { "COM"sv, true, "com"sv, OptionalNone {} }, + // FIXME: Enable these dotted host cases once URL::Host handles dot + // normalization correctly. + // { ".com"sv, false, "com"sv, OptionalNone {} }, + // { "com."sv, false, "com"sv, OptionalNone {} }, + // { ".com."sv, false, "com"sv, OptionalNone {} }, + // { "..com."sv, false, "com"sv, OptionalNone {} }, + { "example.com"sv, false, "com"sv, "example.com"sv }, + { "EXAMPLE.COM"sv, false, "com"sv, "example.com"sv }, + // FIXME: Enable these dotted host cases once URL::Host handles dot + // normalization correctly. + // { ".example.com"sv, false, "com"sv, "example.com"sv }, + { "www.example.com"sv, false, "com"sv, "example.com"sv }, + { "sub.www.example.com"sv, false, "com"sv, "example.com"sv }, + // FIXME: Enable this trailing-dot case once URL::Host handles dot + // normalization correctly. + // { "www.example.com."sv, false, "com"sv, OptionalNone {} }, + { "not-a-public-suffix.com"sv, false, "com"sv, "not-a-public-suffix.com"sv }, + { "com.br"sv, true, "com.br"sv, OptionalNone {} }, + { "not-a-public-suffix.com.br"sv, false, "com.br"sv, "not-a-public-suffix.com.br"sv }, + { "co.uk"sv, true, "co.uk"sv, OptionalNone {} }, + { "ac.uk"sv, true, "ac.uk"sv, OptionalNone {} }, + { "gov.uk"sv, true, "gov.uk"sv, OptionalNone {} }, + { "com.au"sv, true, "com.au"sv, OptionalNone {} }, + { "co.jp"sv, true, "co.jp"sv, OptionalNone {} }, + { "bbc.co.uk"sv, false, "co.uk"sv, "bbc.co.uk"sv }, + { "www.bbc.co.uk"sv, false, "co.uk"sv, "bbc.co.uk"sv }, + { "github.io"sv, true, "github.io"sv, OptionalNone {} }, + { "ladybird.github.io"sv, false, "github.io"sv, "ladybird.github.io"sv }, + { "whatwg.github.io"sv, false, "github.io"sv, "whatwg.github.io"sv }, + { "公司.cn"sv, true, "xn--55qx5d.cn"sv, OptionalNone {} }, + { "www.公司.cn"sv, false, "xn--55qx5d.cn"sv, "www.xn--55qx5d.cn"sv }, + { "www.xn--55qx5d.cn"sv, false, "xn--55qx5d.cn"sv, "www.xn--55qx5d.cn"sv }, + }; + auto* public_suffix_data = URL::PublicSuffixData::the(); - EXPECT(public_suffix_data->is_matching_public_suffix("com"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("com.br"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("co.uk"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("ac.uk"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("gov.uk"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("com.au"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("co.jp"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("COM"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("公司.cn"sv)); - EXPECT(public_suffix_data->is_matching_public_suffix("xn--55qx5d.cn"sv)); + for (auto const& test_case : test_cases) { + EXPECT_EQ(public_suffix_data->is_matching_public_suffix(test_case.input), test_case.is_public_suffix); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(test_case.input), test_case.public_suffix); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(test_case.input), test_case.registrable_domain); - EXPECT(!public_suffix_data->is_matching_public_suffix(""sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("."sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix(".."sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("/"sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("not-a-public-suffix.com"sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("com."sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("com/"sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("/com"sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("not-a-public-suffix"sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix(" com"sv)); - EXPECT(!public_suffix_data->is_matching_public_suffix("com "sv)); + auto host = URL::Parser::parse_host(test_case.input); + VERIFY(host.has_value()); + EXPECT_EQ(public_suffix_data->is_matching_public_suffix(*host), test_case.is_public_suffix); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(*host), test_case.public_suffix); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(*host), test_case.registrable_domain); + EXPECT_EQ(host->public_suffix(), test_case.public_suffix); + EXPECT_EQ(host->registrable_domain(), test_case.registrable_domain); + } } -TEST_CASE(get_public_suffix) +TEST_CASE(public_suffix_matching_without_psl_rule) { + struct TestCase { + StringView input; + Optional host_public_suffix; + Optional host_registrable_domain; + }; + + TestCase test_cases[] { + { "foobar"sv, "foobar"sv, OptionalNone {} }, + { "foobar."sv, "foobar."sv, OptionalNone {} }, + { "not-a-public-suffix"sv, "not-a-public-suffix"sv, OptionalNone {} }, + { "a.example"sv, "example"sv, "a.example"sv }, + { "a.example."sv, "example."sv, "a.example."sv }, + { "b.b.example"sv, "example"sv, "b.example"sv }, + { "b.b.example."sv, "example."sv, "b.example."sv }, + { "foo.not-a-public-suffix"sv, "not-a-public-suffix"sv, "foo.not-a-public-suffix"sv }, + { "sub.foo.not-a-public-suffix"sv, "not-a-public-suffix"sv, "foo.not-a-public-suffix"sv }, + { "إختبار"sv, "xn--kgbechtv"sv, OptionalNone {} }, + { "example.إختبار"sv, "xn--kgbechtv"sv, "example.xn--kgbechtv"sv }, + { "example.إختبار."sv, "xn--kgbechtv."sv, "example.xn--kgbechtv."sv }, + { "sub.example.إختبار"sv, "xn--kgbechtv"sv, "example.xn--kgbechtv"sv }, + }; + auto* public_suffix_data = URL::PublicSuffixData::the(); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix(""sv), OptionalNone {}); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("."sv), OptionalNone {}); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix(".."sv), OptionalNone {}); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix(" "sv), OptionalNone {}); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("/"sv), OptionalNone {}); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("not-a-public-suffix"sv), OptionalNone {}); + for (auto const& test_case : test_cases) { + EXPECT(!public_suffix_data->is_matching_public_suffix(test_case.input)); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(test_case.input), OptionalNone {}); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(test_case.input), OptionalNone {}); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("com"sv), "com"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("not-a-public-suffix.com"sv), "com"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("com."sv), "com"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix(".com."sv), "com"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("..com."sv), "com"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("com.br"sv), "com.br"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("not-a-public-suffix.com.br"sv), "com.br"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("co.uk"sv), "co.uk"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("bbc.co.uk"sv), "co.uk"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("www.bbc.co.uk"sv), "co.uk"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("EXAMPLE.COM"sv), "com"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("www.公司.cn"sv), "xn--55qx5d.cn"sv); - EXPECT_EQ(public_suffix_data->find_matching_public_suffix("www.xn--55qx5d.cn"sv), "xn--55qx5d.cn"sv); + auto host = URL::Parser::parse_host(test_case.input); + VERIFY(host.has_value()); + EXPECT(!public_suffix_data->is_matching_public_suffix(*host)); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(*host), OptionalNone {}); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(*host), OptionalNone {}); + EXPECT_EQ(host->public_suffix(), test_case.host_public_suffix); + EXPECT_EQ(host->registrable_domain(), test_case.host_registrable_domain); + } +} + +TEST_CASE(invalid_hosts) +{ + StringView raw_invalid_inputs[] { + " "sv, + "/"sv, + "com/"sv, + "/com"sv, + " com"sv, + "com "sv, + }; + + // Above inputs are not valid hosts, so should not be able to be parsed or matched in the PSL. + auto* public_suffix_data = URL::PublicSuffixData::the(); + + for (auto const& input : raw_invalid_inputs) { + auto host = URL::Parser::parse_host(input); + EXPECT(!host.has_value()); + EXPECT(!public_suffix_data->is_matching_public_suffix(input)); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(input), OptionalNone {}); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(input), OptionalNone {}); + } +} + +TEST_CASE(public_suffix_matching_for_ip_addresses) +{ + StringView test_cases[] { + "127.0.0.1"sv, + "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"sv, + }; + + auto* public_suffix_data = URL::PublicSuffixData::the(); + + for (auto const& input : test_cases) { + EXPECT(!public_suffix_data->is_matching_public_suffix(input)); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(input), OptionalNone {}); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(input), OptionalNone {}); + + auto host = URL::Parser::parse_host(input); + VERIFY(host.has_value()); + EXPECT(!public_suffix_data->is_matching_public_suffix(*host)); + EXPECT_EQ(public_suffix_data->find_matching_public_suffix(*host), OptionalNone {}); + EXPECT_EQ(public_suffix_data->find_matching_registrable_domain(*host), OptionalNone {}); + EXPECT_EQ(host->public_suffix(), OptionalNone {}); + EXPECT_EQ(host->registrable_domain(), OptionalNone {}); + } } diff --git a/Tests/LibURL/TestURL.cpp b/Tests/LibURL/TestURL.cpp index 8387703806..39ea597cc5 100644 --- a/Tests/LibURL/TestURL.cpp +++ b/Tests/LibURL/TestURL.cpp @@ -9,7 +9,6 @@ #include #include -#include #include TEST_CASE(basic) @@ -631,113 +630,6 @@ TEST_CASE(invalid_domain_code_points) } } -TEST_CASE(get_registrable_domain) -{ - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain({}); - EXPECT(!domain.has_value()); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("foobar"sv); - EXPECT(!domain.has_value()); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("com"sv); - EXPECT(!domain.has_value()); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain(".com"sv); - EXPECT(!domain.has_value()); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("example.com"sv); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "example.com"sv); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain(".example.com"sv); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "example.com"sv); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("www.example.com"sv); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "example.com"sv); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("sub.www.example.com"sv); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "example.com"sv); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("github.io"sv); - EXPECT(!domain.has_value()); - } - { - auto domain = URL::PublicSuffixData::the()->find_matching_registrable_domain("ladybird.github.io"sv); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "ladybird.github.io"sv); - } - { - auto domain = URL::Parser::parse_host("a.example"sv)->registrable_domain(); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "a.example"sv); - } - { - auto domain = URL::Parser::parse_host("b.b.example"sv)->registrable_domain(); - VERIFY(domain.has_value()); - EXPECT_EQ(*domain, "b.example"sv); - } -} - -TEST_CASE(public_suffix) -{ - { - auto domain = URL::Parser::parse_host("com"sv); - EXPECT_EQ(domain->public_suffix(), "com"sv); - } - { - auto domain = URL::Parser::parse_host("example.com"sv); - EXPECT_EQ(domain->public_suffix(), "com"sv); - } - { - auto domain = URL::Parser::parse_host("www.example.com"sv); - EXPECT_EQ(domain->public_suffix(), "com"sv); - } - { - auto domain = URL::Parser::parse_host("EXAMPLE.COM"sv); - EXPECT_EQ(domain->public_suffix(), "com"sv); - } - { - auto domain = URL::Parser::parse_host("www.example.com."sv); - EXPECT_EQ(domain->public_suffix(), "com."sv); - } - { - auto domain = URL::Parser::parse_host("github.io"sv); - EXPECT_EQ(domain->public_suffix(), "github.io"sv); - } - { - auto domain = URL::Parser::parse_host("whatwg.github.io"sv); - EXPECT_EQ(domain->public_suffix(), "github.io"sv); - } - { - auto domain = URL::Parser::parse_host("إختبار"sv); - EXPECT_EQ(domain->public_suffix(), "xn--kgbechtv"sv); - } - { - auto domain = URL::Parser::parse_host("example.إختبار"sv); - EXPECT_EQ(domain->public_suffix(), "xn--kgbechtv"sv); - } - { - auto domain = URL::Parser::parse_host("sub.example.إختبار"sv); - EXPECT_EQ(domain->public_suffix(), "xn--kgbechtv"sv); - } - { - auto domain = URL::Parser::parse_host("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"sv); - EXPECT_EQ(domain->public_suffix(), OptionalNone {}); - } -} - TEST_CASE(same_site) { auto opaque_origin = URL::Origin::create_opaque();