tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestStandardURL.cpp (20985B)


      1 #include "gtest/gtest.h"
      2 #include "gtest/MozGTestBench.h"  // For MOZ_GTEST_BENCH
      3 
      4 #include "nsCOMPtr.h"
      5 #include "nsNetCID.h"
      6 #include "nsIURL.h"
      7 #include "nsIStandardURL.h"
      8 #include "nsString.h"
      9 #include "nsPrintfCString.h"
     10 #include "nsComponentManagerUtils.h"
     11 #include "nsIURIMutator.h"
     12 #include "mozilla/ipc/URIUtils.h"
     13 #include "nsSerializationHelper.h"
     14 #include "mozilla/Base64.h"
     15 #include "nsEscape.h"
     16 #include "nsURLHelper.h"
     17 #include "IPv4Parser.h"
     18 
     19 using namespace mozilla;
     20 
     21 nsresult Test_NormalizeIPv4(const nsACString& host, nsCString& result) {
     22  return net::IPv4Parser::NormalizeIPv4(host, result);
     23 }
     24 
     25 TEST(TestStandardURL, Simple)
     26 {
     27  nsCOMPtr<nsIURI> url;
     28  ASSERT_EQ(NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
     29                .SetSpec("http://example.com"_ns)
     30                .Finalize(url),
     31            NS_OK);
     32  ASSERT_TRUE(url);
     33 
     34  ASSERT_EQ(NS_MutateURI(url).SetSpec("http://example.com"_ns).Finalize(url),
     35            NS_OK);
     36 
     37  nsAutoCString out;
     38 
     39  ASSERT_EQ(url->GetSpec(out), NS_OK);
     40  ASSERT_TRUE(out == "http://example.com/"_ns);
     41 
     42  ASSERT_EQ(url->Resolve("foo.html?q=45"_ns, out), NS_OK);
     43  ASSERT_TRUE(out == "http://example.com/foo.html?q=45"_ns);
     44 
     45  ASSERT_EQ(NS_MutateURI(url).SetScheme("foo"_ns).Finalize(url), NS_OK);
     46 
     47  ASSERT_EQ(url->GetScheme(out), NS_OK);
     48  ASSERT_TRUE(out == "foo"_ns);
     49 
     50  ASSERT_EQ(url->GetHost(out), NS_OK);
     51  ASSERT_TRUE(out == "example.com"_ns);
     52  ASSERT_EQ(NS_MutateURI(url).SetHost("www.yahoo.com"_ns).Finalize(url), NS_OK);
     53  ASSERT_EQ(url->GetHost(out), NS_OK);
     54  ASSERT_TRUE(out == "www.yahoo.com"_ns);
     55 
     56  ASSERT_EQ(NS_MutateURI(url)
     57                .SetPathQueryRef(nsLiteralCString(
     58                    "/some-path/one-the-net/about.html?with-a-query#for-you"))
     59                .Finalize(url),
     60            NS_OK);
     61  ASSERT_EQ(url->GetPathQueryRef(out), NS_OK);
     62  ASSERT_TRUE(out ==
     63              nsLiteralCString(
     64                  "/some-path/one-the-net/about.html?with-a-query#for-you"));
     65 
     66  ASSERT_EQ(NS_MutateURI(url)
     67                .SetQuery(nsLiteralCString(
     68                    "a=b&d=c&what-ever-you-want-to-be-called=45"))
     69                .Finalize(url),
     70            NS_OK);
     71  ASSERT_EQ(url->GetQuery(out), NS_OK);
     72  ASSERT_TRUE(out == "a=b&d=c&what-ever-you-want-to-be-called=45"_ns);
     73 
     74  ASSERT_EQ(NS_MutateURI(url).SetRef("#some-book-mark"_ns).Finalize(url),
     75            NS_OK);
     76  ASSERT_EQ(url->GetRef(out), NS_OK);
     77  ASSERT_TRUE(out == "some-book-mark"_ns);
     78 }
     79 
     80 TEST(TestStandardURL, NormalizeGood)
     81 {
     82  nsCString result;
     83  const char* manual[] = {"0.0.0.0",
     84                          "0.0.0.0",
     85                          "0",
     86                          "0.0.0.0",
     87                          "000",
     88                          "0.0.0.0",
     89                          "0x00",
     90                          "0.0.0.0",
     91                          "10.20.100.200",
     92                          "10.20.100.200",
     93                          "255.255.255.255",
     94                          "255.255.255.255",
     95                          "0XFF.0xFF.0xff.0xFf",
     96                          "255.255.255.255",
     97                          "0x000ff.0X00FF.0x0ff.0xff",
     98                          "255.255.255.255",
     99                          "0x000fA.0X00FB.0x0fC.0xfD",
    100                          "250.251.252.253",
    101                          "0x000fE.0X00FF.0x0fC.0xfD",
    102                          "254.255.252.253",
    103                          "0x000fa.0x00fb.0x0fc.0xfd",
    104                          "250.251.252.253",
    105                          "0x000fe.0x00ff.0x0fc.0xfd",
    106                          "254.255.252.253",
    107                          "0377.0377.0377.0377",
    108                          "255.255.255.255",
    109                          "0000377.000377.00377.0377",
    110                          "255.255.255.255",
    111                          "65535",
    112                          "0.0.255.255",
    113                          "0xfFFf",
    114                          "0.0.255.255",
    115                          "0x00000ffff",
    116                          "0.0.255.255",
    117                          "0177777",
    118                          "0.0.255.255",
    119                          "000177777",
    120                          "0.0.255.255",
    121                          "0.13.65535",
    122                          "0.13.255.255",
    123                          "0.22.0xffff",
    124                          "0.22.255.255",
    125                          "0.123.0177777",
    126                          "0.123.255.255",
    127                          "65536",
    128                          "0.1.0.0",
    129                          "0200000",
    130                          "0.1.0.0",
    131                          "0x10000",
    132                          "0.1.0.0"};
    133  for (uint32_t i = 0; i < sizeof(manual) / sizeof(manual[0]); i += 2) {
    134    nsCString encHost(manual[i + 0]);
    135    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    136    ASSERT_TRUE(result.Equals(manual[i + 1]));
    137  }
    138 
    139  // Make sure we're getting the numbers correctly interpreted:
    140  for (int i = 0; i < 256; i++) {
    141    nsCString encHost = nsPrintfCString("0x%x", i);
    142    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    143    ASSERT_TRUE(result.Equals(nsPrintfCString("0.0.0.%d", i)));
    144 
    145    encHost = nsPrintfCString("0%o", i);
    146    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    147    ASSERT_TRUE(result.Equals(nsPrintfCString("0.0.0.%d", i)));
    148  }
    149 
    150  // Some random numbers in the range, mixing hex, decimal, octal
    151  for (int i = 0; i < 8; i++) {
    152    int val[4] = {i * 11 + 13, i * 18 + 22, i * 4 + 28, i * 15 + 2};
    153 
    154    nsCString encHost =
    155        nsPrintfCString("%d.%d.%d.%d", val[0], val[1], val[2], val[3]);
    156    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    157    ASSERT_TRUE(result.Equals(encHost));
    158 
    159    nsCString encHostM =
    160        nsPrintfCString("0x%x.0x%x.0x%x.0x%x", val[0], val[1], val[2], val[3]);
    161    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result));
    162    ASSERT_TRUE(result.Equals(encHost));
    163 
    164    encHostM =
    165        nsPrintfCString("0%o.0%o.0%o.0%o", val[0], val[1], val[2], val[3]);
    166    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result));
    167    ASSERT_TRUE(result.Equals(encHost));
    168 
    169    encHostM =
    170        nsPrintfCString("0x%x.%d.0%o.%d", val[0], val[1], val[2], val[3]);
    171    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result));
    172    ASSERT_TRUE(result.Equals(encHost));
    173 
    174    encHostM =
    175        nsPrintfCString("%d.0%o.0%o.0x%x", val[0], val[1], val[2], val[3]);
    176    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result));
    177    ASSERT_TRUE(result.Equals(encHost));
    178 
    179    encHostM =
    180        nsPrintfCString("0%o.0%o.0x%x.0x%x", val[0], val[1], val[2], val[3]);
    181    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result));
    182    ASSERT_TRUE(result.Equals(encHost));
    183  }
    184 }
    185 
    186 TEST(TestStandardURL, NormalizeBad)
    187 {
    188  nsAutoCString result;
    189  const char* manual[] = {
    190      "x22.232.12.32", "122..12.32",    "122.12.32.12.32",   "122.12.32..",
    191      "122.12.xx.22",  "122.12.0xx.22", "0xx.12.01.22",      "12.12.02x.22",
    192      "1q.12.2.22",    "122.01f.02.22", "12a.01.02.22",      "12.01.02.20x1",
    193      "10x2.01.02.20", "0xx.01.02.20",  "10.x.02.20",        "10.00x2.02.20",
    194      "10.13.02x2.20", "10.x13.02.20",  "10.0x134def.02.20", "\0.2.2.2",
    195      "256.2.2.2",     "2.256.2.2",     "2.2.256.2",         "2.2.2.256",
    196      "2.2.-2.3",      "+2.2.2.3",      "13.0x2x2.2.3",      "0x2x2.13.2.3"};
    197 
    198  for (auto& i : manual) {
    199    nsCString encHost(i);
    200    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost, result));
    201  }
    202 }
    203 
    204 TEST(TestStandardURL, From_test_standardurldotjs)
    205 {
    206  // These are test (success and failure) cases from test_standardurl.js
    207  nsAutoCString result;
    208 
    209  const char* localIPv4s[] = {
    210      "127.0.0.1",
    211      "127.0.1",
    212      "127.1",
    213      "2130706433",
    214      "0177.00.00.01",
    215      "0177.00.01",
    216      "0177.01",
    217      "00000000000000000000000000177.0000000.0000000.0001",
    218      "000000177.0000001",
    219      "017700000001",
    220      "0x7f.0x00.0x00.0x01",
    221      "0x7f.0x01",
    222      "0x7f000001",
    223      "0x007f.0x0000.0x0000.0x0001",
    224      "000177.0.00000.0x0001",
    225      "127.0.0.1.",
    226 
    227      "0X7F.0X00.0X00.0X01",
    228      "0X7F.0X01",
    229      "0X7F000001",
    230      "0X007F.0X0000.0X0000.0X0001",
    231      "000177.0.00000.0X0001"};
    232  for (auto& localIPv4 : localIPv4s) {
    233    nsCString encHost(localIPv4);
    234    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    235    ASSERT_TRUE(result.EqualsLiteral("127.0.0.1"));
    236  }
    237 
    238  const char* nonIPv4s[] = {"0xfffffffff", "0x100000000",
    239                            "4294967296",  "1.2.0x10000",
    240                            "1.0x1000000", "256.0.0.1",
    241                            "1.256.1",     "-1.0.0.0",
    242                            "1.2.3.4.5",   "010000000000000000",
    243                            "2+3",         "0.0.0.-1",
    244                            "1.2.3.4..",   "1..2",
    245                            ".1.2.3.4",    ".127"};
    246  for (auto& nonIPv4 : nonIPv4s) {
    247    nsCString encHost(nonIPv4);
    248    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost, result));
    249  }
    250 
    251  const char* oneOrNoDotsIPv4s[] = {"127", "127."};
    252  for (auto& localIPv4 : oneOrNoDotsIPv4s) {
    253    nsCString encHost(localIPv4);
    254    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    255    ASSERT_TRUE(result.EqualsLiteral("0.0.0.127"));
    256  }
    257 }
    258 
    259 #define TEST_COUNT 10000
    260 
    261 MOZ_GTEST_BENCH(TestStandardURL, DISABLED_Perf, [] {
    262  nsCOMPtr<nsIURI> url;
    263  ASSERT_EQ(NS_OK, NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    264                       .SetSpec("http://example.com"_ns)
    265                       .Finalize(url));
    266 
    267  nsAutoCString out;
    268  for (int i = TEST_COUNT; i; --i) {
    269    ASSERT_EQ(NS_MutateURI(url).SetSpec("http://example.com"_ns).Finalize(url),
    270              NS_OK);
    271    ASSERT_EQ(url->GetSpec(out), NS_OK);
    272    url->Resolve("foo.html?q=45"_ns, out);
    273    (void)NS_MutateURI(url).SetScheme("foo"_ns).Finalize(url);
    274    url->GetScheme(out);
    275    (void)NS_MutateURI(url).SetHost("www.yahoo.com"_ns).Finalize(url);
    276    url->GetHost(out);
    277    (void)NS_MutateURI(url)
    278        .SetPathQueryRef(nsLiteralCString(
    279            "/some-path/one-the-net/about.html?with-a-query#for-you"))
    280        .Finalize(url);
    281    url->GetPathQueryRef(out);
    282    (void)NS_MutateURI(url)
    283        .SetQuery(
    284            nsLiteralCString("a=b&d=c&what-ever-you-want-to-be-called=45"))
    285        .Finalize(url);
    286    url->GetQuery(out);
    287    (void)NS_MutateURI(url).SetRef("#some-book-mark"_ns).Finalize(url);
    288    url->GetRef(out);
    289  }
    290 });
    291 
    292 // Note the five calls in the loop, so divide by 100k
    293 MOZ_GTEST_BENCH(TestStandardURL, DISABLED_NormalizePerf, [] {
    294  nsAutoCString result;
    295  for (int i = 0; i < 20000; i++) {
    296    nsAutoCString encHost("123.232.12.32");
    297    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result));
    298    nsAutoCString encHost2("83.62.12.92");
    299    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost2, result));
    300    nsAutoCString encHost3("8.7.6.5");
    301    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost3, result));
    302    nsAutoCString encHost4("111.159.123.220");
    303    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost4, result));
    304    nsAutoCString encHost5("1.160.204.200");
    305    ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost5, result));
    306  }
    307 });
    308 
    309 // Bug 1394785 - ignore unstable test on OSX
    310 #ifndef XP_MACOSX
    311 // Note the five calls in the loop, so divide by 100k
    312 MOZ_GTEST_BENCH(TestStandardURL, DISABLED_NormalizePerfFails, [] {
    313  nsAutoCString result;
    314  for (int i = 0; i < 20000; i++) {
    315    nsAutoCString encHost("123.292.12.32");
    316    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost, result));
    317    nsAutoCString encHost2("83.62.12.0x13292");
    318    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost2, result));
    319    nsAutoCString encHost3("8.7.6.0xhello");
    320    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost3, result));
    321    nsAutoCString encHost4("111.159.notonmywatch.220");
    322    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost4, result));
    323    nsAutoCString encHost5("1.160.204.20f");
    324    ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost5, result));
    325  }
    326 });
    327 #endif
    328 
    329 TEST(TestStandardURL, Mutator)
    330 {
    331  nsAutoCString out;
    332  nsCOMPtr<nsIURI> uri;
    333  nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    334                    .SetSpec("http://example.com"_ns)
    335                    .Finalize(uri);
    336  ASSERT_EQ(rv, NS_OK);
    337 
    338  ASSERT_EQ(uri->GetSpec(out), NS_OK);
    339  ASSERT_TRUE(out == "http://example.com/"_ns);
    340 
    341  rv = NS_MutateURI(uri)
    342           .SetScheme("ftp"_ns)
    343           .SetHost("mozilla.org"_ns)
    344           .SetPathQueryRef("/path?query#ref"_ns)
    345           .Finalize(uri);
    346  ASSERT_EQ(rv, NS_OK);
    347  ASSERT_EQ(uri->GetSpec(out), NS_OK);
    348  ASSERT_TRUE(out == "ftp://mozilla.org/path?query#ref"_ns);
    349 
    350  nsCOMPtr<nsIURL> url;
    351  rv = NS_MutateURI(uri).SetScheme("https"_ns).Finalize(url);
    352  ASSERT_EQ(rv, NS_OK);
    353  ASSERT_EQ(url->GetSpec(out), NS_OK);
    354  ASSERT_TRUE(out == "https://mozilla.org/path?query#ref"_ns);
    355 }
    356 
    357 TEST(TestStandardURL, Deserialize_Bug1392739)
    358 {
    359  mozilla::ipc::StandardURLParams standard_params;
    360  standard_params.urlType() = nsIStandardURL::URLTYPE_STANDARD;
    361  standard_params.spec().Truncate();
    362  standard_params.host() = mozilla::ipc::StandardURLSegment(4294967295, 1);
    363 
    364  mozilla::ipc::URIParams params(standard_params);
    365 
    366  nsCOMPtr<nsIURIMutator> mutator =
    367      do_CreateInstance(NS_STANDARDURLMUTATOR_CID);
    368  ASSERT_EQ(mutator->Deserialize(params), NS_ERROR_FAILURE);
    369 }
    370 
    371 TEST(TestStandardURL, CorruptSerialization)
    372 {
    373  auto spec = "http://user:pass@example.com/path/to/file.ext?query#hash"_ns;
    374 
    375  nsCOMPtr<nsIURI> uri;
    376  nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    377                    .SetSpec(spec)
    378                    .Finalize(uri);
    379  ASSERT_EQ(rv, NS_OK);
    380 
    381  nsAutoCString serialization;
    382  nsCOMPtr<nsISerializable> serializable = do_QueryInterface(uri);
    383  ASSERT_TRUE(serializable);
    384 
    385  // Check that the URL is normally serializable.
    386  ASSERT_EQ(NS_OK, NS_SerializeToString(serializable, serialization));
    387  nsCOMPtr<nsISupports> deserializedObject;
    388  ASSERT_EQ(NS_OK, NS_DeserializeObject(serialization,
    389                                        getter_AddRefs(deserializedObject)));
    390 
    391  nsAutoCString canonicalBin;
    392  (void)Base64Decode(serialization, canonicalBin);
    393 
    394 // The spec serialization begins at byte 49
    395 // If the implementation of nsStandardURL::Write changes, this test will need
    396 // to be adjusted.
    397 #define SPEC_OFFSET 49
    398 
    399  ASSERT_EQ(Substring(canonicalBin, SPEC_OFFSET, 7), "http://"_ns);
    400 
    401  nsAutoCString corruptedBin = canonicalBin;
    402  // change mScheme.mPos
    403  corruptedBin.BeginWriting()[SPEC_OFFSET + spec.Length()] = 1;
    404  (void)Base64Encode(corruptedBin, serialization);
    405  ASSERT_EQ(
    406      NS_ERROR_MALFORMED_URI,
    407      NS_DeserializeObject(serialization, getter_AddRefs(deserializedObject)));
    408 
    409  corruptedBin = canonicalBin;
    410  // change mScheme.mLen
    411  corruptedBin.BeginWriting()[SPEC_OFFSET + spec.Length() + 4] = 127;
    412  (void)Base64Encode(corruptedBin, serialization);
    413  ASSERT_EQ(
    414      NS_ERROR_MALFORMED_URI,
    415      NS_DeserializeObject(serialization, getter_AddRefs(deserializedObject)));
    416 }
    417 
    418 TEST(TestStandardURL, ParseIPv4Num)
    419 {
    420  auto host = "0x.0x.0"_ns;
    421 
    422  int32_t bases[4] = {10, 10, 10, 10};
    423  bool onlyBase10 = true;  // Track this as a special case
    424  int32_t dotIndex[3];     // The positions of the dots in the string
    425  int32_t length = static_cast<int32_t>(host.Length());
    426 
    427  ASSERT_EQ(2, mozilla::net::IPv4Parser::ValidateIPv4Number(
    428                   host, bases, dotIndex, onlyBase10, length, false));
    429 
    430  nsCString result;
    431  ASSERT_EQ(NS_OK, Test_NormalizeIPv4("0x.0x.0"_ns, result));
    432 
    433  uint32_t number;
    434  mozilla::net::IPv4Parser::ParseIPv4Number("0x10"_ns, 16, number, 255);
    435  ASSERT_EQ(number, (uint32_t)16);
    436 }
    437 
    438 TEST(TestStandardURL, CoalescePath)
    439 {
    440  auto testCoalescing = [](const char* input, const char* expected,
    441                           uint32_t lastSlash, uint32_t endOfBasename) {
    442    nsAutoCString buf(input);
    443    auto resultCoalesceDirs = net_CoalesceDirs(buf.BeginWriting());
    444 
    445    ASSERT_EQ(nsCString(buf.get()), nsCString(expected));
    446 
    447    // If the path does not begin with '/', it should return Nothing().
    448    if (input[0] == '/') {
    449      ASSERT_EQ(resultCoalesceDirs->first(), lastSlash);
    450      ASSERT_EQ(resultCoalesceDirs->second(), endOfBasename);
    451    } else {
    452      ASSERT_TRUE(resultCoalesceDirs == Nothing());
    453    }
    454  };
    455 
    456 #ifndef DEBUG
    457  // invalid input
    458  testCoalescing("", "", -1, -1);
    459 #endif
    460  // end of basename is the null character's index
    461  testCoalescing("/", "/", 0, 1);
    462  testCoalescing("/.", "/", 0, 1);
    463  testCoalescing("/..", "/", 0, 1);
    464  testCoalescing("/foo/foo1/.", "/foo/foo1/", 9, 10);
    465  testCoalescing("/foo/../foo1", "/foo1", 0, 5);
    466  testCoalescing("/foo/./foo1", "/foo/foo1", 4, 9);
    467  testCoalescing("/foo/foo1/..", "/foo/", 4, 5);
    468 
    469  // Bug 1890346
    470  testCoalescing("/..?/..", "/?/..", 0, 1);
    471 
    472  testCoalescing("/.?/..", "/?/..", 0, 1);
    473  testCoalescing("/./../?", "/?", 0, 1);
    474  testCoalescing("/.abc", "/.abc", 0, 5);
    475  testCoalescing("//", "//", 1, 2);
    476  testCoalescing("/../", "/", 0, 1);
    477  testCoalescing("/./", "/", 0, 1);
    478  testCoalescing("/.../", "/.../", 4, 5);
    479 
    480  // Bug 1873915
    481  testCoalescing("/hello/%2e%2e/foo", "/foo", 0, 4);
    482  testCoalescing("/hello/%2e%2E/foo", "/foo", 0, 4);
    483  testCoalescing("/hello/%2E%2e/foo", "/foo", 0, 4);
    484  testCoalescing("/hello/%2E%2E/foo", "/foo", 0, 4);
    485  testCoalescing("/hello/%2e./foo", "/foo", 0, 4);
    486  testCoalescing("/hello/.%2e/foo", "/foo", 0, 4);
    487  testCoalescing("/hello/%2E./foo", "/foo", 0, 4);
    488  testCoalescing("/hello/.%2E/foo", "/foo", 0, 4);
    489  testCoalescing("/hello/%2e%2E/%2e", "/", 0, 1);
    490  testCoalescing("/hello/%2e/%2e%2e", "/", 0, 1);
    491  testCoalescing("/hello/%2e%2E/%#", "/%#", 0, 2);
    492  testCoalescing("/hello/%2e%2E/%?", "/%?", 0, 2);
    493  testCoalescing("/hello/%2e", "/hello/", 6, 7);
    494  testCoalescing("/hello/%2E", "/hello/", 6, 7);
    495  testCoalescing("/hello/%2e/", "/hello/", 6, 7);
    496  testCoalescing("/hello/%2E/", "/hello/", 6, 7);
    497  testCoalescing("/hello/%2e.", "/", 0, 1);
    498  testCoalescing("/hello/.%2e", "/", 0, 1);
    499  testCoalescing("/hello/%2E.", "/", 0, 1);
    500  testCoalescing("/hello/.%2E", "/", 0, 1);
    501  testCoalescing("/hello/%2E%2e/%2e/./../.", "/", 0, 1);
    502  testCoalescing("/test/%2e%2e/dir/%2E%2e/file", "/file", 0, 5);
    503 
    504  // should not convert as a character is present
    505  testCoalescing("/hello/%2E%2ea", "/hello/%2E%2ea", 6, 14);
    506  testCoalescing("/hello/a%2E%2e", "/hello/a%2E%2e", 6, 14);
    507  testCoalescing("/hello/a%2E%2ea", "/hello/a%2E%2ea", 6, 15);
    508 
    509  // Encoded sequences followed by special characters
    510  testCoalescing("/foo/%2e%2e/%2e%23/file.txt", "/%2e%23/file.txt", 7, 16);
    511  testCoalescing("/foo/%2e%2e/%2e%3f/file.txt", "/%2e%3f/file.txt", 7, 16);
    512 
    513  // Query strings and fragments with encoded sequences
    514  testCoalescing("/query/%2e%2e/path?p=%2e", "/path?p=%2e", 0, 5);
    515  testCoalescing("/frag/%2e%2e/path#q=%2e", "/path#q=%2e", 0, 5);
    516 
    517  // 3 or more "%2e" repeating should not convert to "."
    518  testCoalescing("/hello/%2E%2e%2E", "/hello/%2E%2e%2E", 6, 16);
    519  testCoalescing("/hello/%2E%2e%2E%2e", "/hello/%2E%2e%2E%2e", 6, 19);
    520  testCoalescing("/hello/%2E%2e%2E%2e.", "/hello/%2E%2e%2E%2e.", 6, 20);
    521 
    522  // Relatively long inputs
    523  testCoalescing("/foo/bar/foo/bar/foo/bar/foo/bar/foo?query#frag",
    524                 "/foo/bar/foo/bar/foo/bar/foo/bar/foo?query#frag", 32, 36);
    525 
    526  testCoalescing("/coder/coder/edit/main/docs/./enterprise.md",
    527                 "/coder/coder/edit/main/docs/enterprise.md", 27, 41);
    528 
    529  // bug 1942820
    530  testCoalescing("/foo/bar/.%2e", "/foo/", 4, 5);
    531  testCoalescing("/foo/bar/..", "/foo/", 4, 5);
    532  testCoalescing("/foo/bar/%2e%2e", "/foo/", 4, 5);
    533  testCoalescing("/foo/bar/%2e%2e#frag", "/foo/#frag", 4, 5);
    534  testCoalescing("/foo/bar/%2e%2e?query", "/foo/?query", 4, 5);
    535 }
    536 
    537 TEST(TestStandardURL, bug1904582)
    538 {
    539  auto spec = "x:///%2e%2e"_ns;
    540 
    541  nsCOMPtr<nsIURI> uri;
    542  nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    543                    .SetSpec(spec)
    544                    .Finalize(uri);
    545  ASSERT_TRUE(NS_SUCCEEDED(rv));
    546 }
    547 
    548 TEST(TestStandardURL, bug1911529)
    549 {
    550  nsCOMPtr<nsIURI> uri;
    551  nsresult rv =
    552      NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    553          .SetSpec(
    554              "https://github.com/coder/coder/edit/main/docs/./enterprise.md"_ns)
    555          .Finalize(uri);
    556  ASSERT_TRUE(NS_SUCCEEDED(rv));
    557 
    558  nsAutoCString out;
    559  ASSERT_EQ(uri->GetSpec(out), NS_OK);
    560  ASSERT_TRUE(out ==
    561              "https://github.com/coder/coder/edit/main/docs/enterprise.md"_ns);
    562 
    563  nsCOMPtr<nsIURI> uri2;
    564  rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    565           .SetSpec(
    566               "https://github.com/coder/coder/edit/main/docs/enterprise.md"_ns)
    567           .Finalize(uri2);
    568  ASSERT_TRUE(NS_SUCCEEDED(rv));
    569 
    570  bool equals = false;
    571  ASSERT_EQ(uri->Equals(uri2, &equals), NS_OK);
    572  ASSERT_TRUE(equals);
    573 
    574  rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    575           .SetSpec("https://domain.com/."_ns)
    576           .Finalize(uri);
    577  ASSERT_TRUE(NS_SUCCEEDED(rv));
    578  rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
    579           .SetSpec("https://domain.com/"_ns)
    580           .Finalize(uri2);
    581  ASSERT_TRUE(NS_SUCCEEDED(rv));
    582 
    583  ASSERT_EQ(uri->Equals(uri2, &equals), NS_OK);
    584  ASSERT_TRUE(equals);
    585 }