Partially revert 207805 after resolution in URL spec issue 87
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 29 Oct 2016 00:20:38 +0000 (00:20 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 29 Oct 2016 00:20:38 +0000 (00:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164142

Reviewed by Andy Estes.

LayoutTests/imported/w3c:

* web-platform-tests/url/a-element-expected.txt:
* web-platform-tests/url/a-element-xhtml-expected.txt:
* web-platform-tests/url/url-constructor-expected.txt:

Source/WebCore:

Covered by updated layout tests and API tests.

* platform/URLParser.cpp:
(WebCore::URLParser::isSingleDotPathSegment):
(WebCore::URLParser::isDoubleDotPathSegment):
(WebCore::URLParser::consumeSingleDotPathSegment):
(WebCore::URLParser::consumeDoubleDotPathSegment):
Treat %2e%2e as .. and %2e as . but only if it is entirety of the path segment.
There are tests for URLs like http://host/abc%2edef which have not changed because
the %2e is not the entirety of the path segment.

Tools:

* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::TEST_F):

LayoutTests:

* fast/url/path-expected.txt:
* fetch/fetch-url-serialization-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208087 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/url/path-expected.txt
LayoutTests/fetch/fetch-url-serialization-expected.txt
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/url/a-element-expected.txt
LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml-expected.txt
LayoutTests/imported/w3c/web-platform-tests/url/url-constructor-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/platform/URLParser.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp

index 7d2514c..b1a0822 100644 (file)
@@ -1,3 +1,13 @@
+2016-10-28  Alex Christensen  <achristensen@webkit.org>
+
+        Partially revert 207805 after resolution in URL spec issue 87
+        https://bugs.webkit.org/show_bug.cgi?id=164142
+
+        Reviewed by Andy Estes.
+
+        * fast/url/path-expected.txt:
+        * fetch/fetch-url-serialization-expected.txt:
+
 2016-10-28  Chris Dumez  <cdumez@apple.com>
 
         DOMStringMap reports properties as non-enumerable
index e9b357d..b13e858 100644 (file)
@@ -14,9 +14,9 @@ PASS canonicalize('http://example.com/foo/bar/../ton') is 'http://example.com/fo
 PASS canonicalize('http://example.com/foo/bar/../ton/../../a') is 'http://example.com/a'
 PASS canonicalize('http://example.com/foo/../../..') is 'http://example.com/'
 PASS canonicalize('http://example.com/foo/../../../ton') is 'http://example.com/ton'
-FAIL canonicalize('http://example.com/foo/%2e') should be http://example.com/foo/. Was http://example.com/foo/%2e.
+PASS canonicalize('http://example.com/foo/%2e') is 'http://example.com/foo/'
 FAIL canonicalize('http://example.com/foo/%2e%2') should be http://example.com/foo/.%2. Was http://example.com/foo/%2e%2.
-FAIL canonicalize('http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar') should be http://example.com/..bar. Was http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar.
+FAIL canonicalize('http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar') should be http://example.com/..bar. Was http://example.com/%2e.bar.
 PASS canonicalize('http://example.com////../..') is 'http://example.com//'
 PASS canonicalize('http://example.com/foo/bar//../..') is 'http://example.com/foo/'
 PASS canonicalize('http://example.com/foo/bar//..') is 'http://example.com/foo/bar/'
index fb01f6a..0df8fe0 100644 (file)
@@ -123,9 +123,9 @@ PASS Testing Request url 'http://example.com/foo/bar/../ton' with base 'about:bl
 PASS Testing Request url 'http://example.com/foo/bar/../ton/../../a' with base 'about:blank' 
 PASS Testing Request url 'http://example.com/foo/../../..' with base 'about:blank' 
 PASS Testing Request url 'http://example.com/foo/../../../ton' with base 'about:blank' 
-FAIL Testing Request url 'http://example.com/foo/%2e' with base 'about:blank' assert_equals: expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+PASS Testing Request url 'http://example.com/foo/%2e' with base 'about:blank' 
 FAIL Testing Request url 'http://example.com/foo/%2e%2' with base 'about:blank' assert_equals: expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
-FAIL Testing Request url 'http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar' with base 'about:blank' assert_equals: expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+FAIL Testing Request url 'http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar' with base 'about:blank' assert_equals: expected "http://example.com/..bar" but got "http://example.com/%2e.bar"
 PASS Testing Request url 'http://example.com////../..' with base 'about:blank' 
 PASS Testing Request url 'http://example.com/foo/bar//../..' with base 'about:blank' 
 PASS Testing Request url 'http://example.com/foo/bar//..' with base 'about:blank' 
@@ -155,7 +155,7 @@ PASS Testing Request url 'http://[www.google.com]/' with base 'about:blank'
 PASS Testing Request url 'http://www.google.com' with base 'about:blank' 
 PASS Testing Request url 'http://192.0x00A80001' with base 'about:blank' 
 FAIL Testing Request url 'http://www/foo%2Ehtml' with base 'about:blank' assert_equals: expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
-FAIL Testing Request url 'http://www/foo/%2E/html' with base 'about:blank' assert_equals: expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Testing Request url 'http://www/foo/%2E/html' with base 'about:blank' 
 PASS Testing Request url 'http://user:pass@/' with base 'about:blank' 
 PASS Testing Request url 'http://%25DOMAIN:foobar@foodomain.com/' with base 'about:blank' 
 PASS Testing Request url 'http:\\www.google.com\foo' with base 'about:blank' 
index 7f0a3c9..4965311 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-28  Alex Christensen  <achristensen@webkit.org>
+
+        Partially revert 207805 after resolution in URL spec issue 87
+        https://bugs.webkit.org/show_bug.cgi?id=164142
+
+        Reviewed by Andy Estes.
+
+        * web-platform-tests/url/a-element-expected.txt:
+        * web-platform-tests/url/a-element-xhtml-expected.txt:
+        * web-platform-tests/url/url-constructor-expected.txt:
+
 2016-10-28  Youenn Fablet  <youenn@apple.com>
 
         Expose RTCPeerConnection unprefixed
index 200fd28..d098d7d 100644 (file)
@@ -126,9 +126,9 @@ PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
 PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> 
 PASS Parsing: <http://example.com/foo/../../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> 
-FAIL Parsing: <http://example.com/foo/%2e> against <about:blank> assert_equals: href expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+PASS Parsing: <http://example.com/foo/%2e> against <about:blank> 
 FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/%2e.bar"
 PASS Parsing: <http://example.com////../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> 
@@ -158,7 +158,7 @@ PASS Parsing: <http://[www.google.com]/> against <about:blank>
 PASS Parsing: <http://www.google.com> against <about:blank> 
 PASS Parsing: <http://192.0x00A80001> against <about:blank> 
 FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
-FAIL Parsing: <http://www/foo/%2E/html> against <about:blank> assert_equals: href expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Parsing: <http://www/foo/%2E/html> against <about:blank> 
 PASS Parsing: <http://user:pass@/> against <about:blank> 
 PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> 
 PASS Parsing: <http:\\www.google.com\foo> against <about:blank> 
index 200fd28..d098d7d 100644 (file)
@@ -126,9 +126,9 @@ PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
 PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> 
 PASS Parsing: <http://example.com/foo/../../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> 
-FAIL Parsing: <http://example.com/foo/%2e> against <about:blank> assert_equals: href expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+PASS Parsing: <http://example.com/foo/%2e> against <about:blank> 
 FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/%2e.bar"
 PASS Parsing: <http://example.com////../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> 
@@ -158,7 +158,7 @@ PASS Parsing: <http://[www.google.com]/> against <about:blank>
 PASS Parsing: <http://www.google.com> against <about:blank> 
 PASS Parsing: <http://192.0x00A80001> against <about:blank> 
 FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
-FAIL Parsing: <http://www/foo/%2E/html> against <about:blank> assert_equals: href expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Parsing: <http://www/foo/%2E/html> against <about:blank> 
 PASS Parsing: <http://user:pass@/> against <about:blank> 
 PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> 
 PASS Parsing: <http:\\www.google.com\foo> against <about:blank> 
index b5c7aee..5b1b3e1 100644 (file)
@@ -130,9 +130,9 @@ PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
 PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> 
 PASS Parsing: <http://example.com/foo/../../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> 
-FAIL Parsing: <http://example.com/foo/%2e> against <about:blank> assert_equals: href expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+PASS Parsing: <http://example.com/foo/%2e> against <about:blank> 
 FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/%2e.bar"
 PASS Parsing: <http://example.com////../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> 
 PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> 
@@ -162,7 +162,7 @@ PASS Parsing: <http://[www.google.com]/> against <about:blank>
 PASS Parsing: <http://www.google.com> against <about:blank> 
 PASS Parsing: <http://192.0x00A80001> against <about:blank> 
 FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
-FAIL Parsing: <http://www/foo/%2E/html> against <about:blank> assert_equals: href expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Parsing: <http://www/foo/%2E/html> against <about:blank> 
 PASS Parsing: <http://user:pass@/> against <about:blank> 
 PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> 
 PASS Parsing: <http:\\www.google.com\foo> against <about:blank> 
index 367187b..5ff11d4 100644 (file)
@@ -1,5 +1,23 @@
 2016-10-28  Alex Christensen  <achristensen@webkit.org>
 
+        Partially revert 207805 after resolution in URL spec issue 87
+        https://bugs.webkit.org/show_bug.cgi?id=164142
+
+        Reviewed by Andy Estes.
+
+        Covered by updated layout tests and API tests.
+
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::isSingleDotPathSegment):
+        (WebCore::URLParser::isDoubleDotPathSegment):
+        (WebCore::URLParser::consumeSingleDotPathSegment):
+        (WebCore::URLParser::consumeDoubleDotPathSegment):
+        Treat %2e%2e as .. and %2e as . but only if it is entirety of the path segment.
+        There are tests for URLs like http://host/abc%2edef which have not changed because
+        the %2e is not the entirety of the path segment.
+
+2016-10-28  Alex Christensen  <achristensen@webkit.org>
+
         URLParser should not try to interpret host of URLs with unrecognized schemes as IPv4 address
         https://bugs.webkit.org/show_bug.cgi?id=164154
 
index ca06d09..9acccc1 100644 (file)
@@ -891,6 +891,8 @@ void URLParser::copyURLPartsUntil(const URL& base, URLPart part, const CodePoint
     ASSERT_NOT_REACHED();
 }
 
+static const char dotASCIICode[2] = {'2', 'e'};
+
 template<typename CharacterType>
 ALWAYS_INLINE bool URLParser::isSingleDotPathSegment(CodePointIterator<CharacterType> c)
 {
@@ -900,6 +902,18 @@ ALWAYS_INLINE bool URLParser::isSingleDotPathSegment(CodePointIterator<Character
         advance<CharacterType, ReportSyntaxViolation::No>(c);
         return c.atEnd() || isSlashQuestionOrHash(*c);
     }
+    if (*c != '%')
+        return false;
+    advance<CharacterType, ReportSyntaxViolation::No>(c);
+    if (c.atEnd() || *c != dotASCIICode[0])
+        return false;
+    advance<CharacterType, ReportSyntaxViolation::No>(c);
+    if (c.atEnd())
+        return false;
+    if (toASCIILower(*c) == dotASCIICode[1]) {
+        advance<CharacterType, ReportSyntaxViolation::No>(c);
+        return c.atEnd() || isSlashQuestionOrHash(*c);
+    }
     return false;
 }
 
@@ -912,6 +926,18 @@ ALWAYS_INLINE bool URLParser::isDoubleDotPathSegment(CodePointIterator<Character
         advance<CharacterType, ReportSyntaxViolation::No>(c);
         return isSingleDotPathSegment(c);
     }
+    if (*c != '%')
+        return false;
+    advance<CharacterType, ReportSyntaxViolation::No>(c);
+    if (c.atEnd() || *c != dotASCIICode[0])
+        return false;
+    advance<CharacterType, ReportSyntaxViolation::No>(c);
+    if (c.atEnd())
+        return false;
+    if (toASCIILower(*c) == dotASCIICode[1]) {
+        advance<CharacterType, ReportSyntaxViolation::No>(c);
+        return isSingleDotPathSegment(c);
+    }
     return false;
 }
 
@@ -919,12 +945,27 @@ template<typename CharacterType>
 void URLParser::consumeSingleDotPathSegment(CodePointIterator<CharacterType>& c)
 {
     ASSERT(isSingleDotPathSegment(c));
-    advance(c);
-    if (!c.atEnd()) {
-        if (*c == '/' || *c == '\\')
-            advance(c);
-        else
-            ASSERT(*c == '?' || *c == '#');
+    if (*c == '.') {
+        advance(c);
+        if (!c.atEnd()) {
+            if (*c == '/' || *c == '\\')
+                advance(c);
+            else
+                ASSERT(*c == '?' || *c == '#');
+        }
+    } else {
+        ASSERT(*c == '%');
+        advance(c);
+        ASSERT(*c == dotASCIICode[0]);
+        advance(c);
+        ASSERT(toASCIILower(*c) == dotASCIICode[1]);
+        advance(c);
+        if (!c.atEnd()) {
+            if (*c == '/' || *c == '\\')
+                advance(c);
+            else
+                ASSERT(*c == '?' || *c == '#');
+        }
     }
 }
 
@@ -932,7 +973,16 @@ template<typename CharacterType>
 void URLParser::consumeDoubleDotPathSegment(CodePointIterator<CharacterType>& c)
 {
     ASSERT(isDoubleDotPathSegment(c));
-    advance(c);
+    if (*c == '.')
+        advance(c);
+    else {
+        ASSERT(*c == '%');
+        advance(c);
+        ASSERT(*c == dotASCIICode[0]);
+        advance(c);
+        ASSERT(toASCIILower(*c) == dotASCIICode[1]);
+        advance(c);
+    }
     consumeSingleDotPathSegment(c);
 }
 
index dcb23bb..2436f43 100644 (file)
@@ -1,5 +1,15 @@
 2016-10-28  Alex Christensen  <achristensen@webkit.org>
 
+        Partially revert 207805 after resolution in URL spec issue 87
+        https://bugs.webkit.org/show_bug.cgi?id=164142
+
+        Reviewed by Andy Estes.
+
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::TEST_F):
+
+2016-10-28  Alex Christensen  <achristensen@webkit.org>
+
         URLParser should not try to interpret host of URLs with unrecognized schemes as IPv4 address
         https://bugs.webkit.org/show_bug.cgi?id=164154
 
index da993aa..47cd072 100644 (file)
@@ -596,18 +596,43 @@ TEST_F(URLParserTest, ParserDifferences)
     checkURLDifferences("http://127.0.0.01/",
         {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
         {"http", "", "", "127.0.0.01", 0, "/", "", "", "http://127.0.0.01/"});
-    checkURL("http://example.com/path1/.%2e", {"http", "", "", "example.com", 0, "/path1/.%2e", "", "", "http://example.com/path1/.%2e"});
-    checkURL("http://example.com/path1/.%2E", {"http", "", "", "example.com", 0, "/path1/.%2E", "", "", "http://example.com/path1/.%2E"});
-    checkURL("http://example.com/path1/.%2E/", {"http", "", "", "example.com", 0, "/path1/.%2E/", "", "", "http://example.com/path1/.%2E/"});
-    checkURL("http://example.com/path1/%2e.", {"http", "", "", "example.com", 0, "/path1/%2e.", "", "", "http://example.com/path1/%2e."});
-    checkURL("http://example.com/path1/%2E%2e", {"http", "", "", "example.com", 0, "/path1/%2E%2e", "", "", "http://example.com/path1/%2E%2e"});
-    checkURL("http://example.com/path1/%2e", {"http", "", "", "example.com", 0, "/path1/%2e", "", "", "http://example.com/path1/%2e"});
-    checkURL("http://example.com/path1/%2E", {"http", "", "", "example.com", 0, "/path1/%2E", "", "", "http://example.com/path1/%2E"});
-    checkURL("http://example.com/path1/%2E/", {"http", "", "", "example.com", 0, "/path1/%2E/", "", "", "http://example.com/path1/%2E/"});
-    checkURL("http://example.com/path1/path2/%2e?query", {"http", "", "", "example.com", 0, "/path1/path2/%2e", "query", "", "http://example.com/path1/path2/%2e?query"});
-    checkURL("http://example.com/path1/path2/%2e%2e?query", {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "query", "", "http://example.com/path1/path2/%2e%2e?query"});
-    checkURL("http://example.com/path1/path2/%2e#fragment", {"http", "", "", "example.com", 0, "/path1/path2/%2e", "", "fragment", "http://example.com/path1/path2/%2e#fragment"});
-    checkURL("http://example.com/path1/path2/%2e%2e#fragment", {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "", "fragment", "http://example.com/path1/path2/%2e%2e#fragment"});
+    checkURLDifferences("http://example.com/path1/.%2e",
+        {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+        {"http", "", "", "example.com", 0, "/path1/.%2e", "", "", "http://example.com/path1/.%2e"});
+    checkURLDifferences("http://example.com/path1/.%2E",
+        {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+        {"http", "", "", "example.com", 0, "/path1/.%2E", "", "", "http://example.com/path1/.%2E"});
+    checkURLDifferences("http://example.com/path1/.%2E/",
+        {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+        {"http", "", "", "example.com", 0, "/path1/.%2E/", "", "", "http://example.com/path1/.%2E/"});
+    checkURLDifferences("http://example.com/path1/%2e.",
+        {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+        {"http", "", "", "example.com", 0, "/path1/%2e.", "", "", "http://example.com/path1/%2e."});
+    checkURLDifferences("http://example.com/path1/%2E%2e",
+        {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+        {"http", "", "", "example.com", 0, "/path1/%2E%2e", "", "", "http://example.com/path1/%2E%2e"});
+    checkURLDifferences("http://example.com/path1/%2e",
+        {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
+        {"http", "", "", "example.com", 0, "/path1/%2e", "", "", "http://example.com/path1/%2e"});
+    checkURLDifferences("http://example.com/path1/%2E",
+        {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
+        {"http", "", "", "example.com", 0, "/path1/%2E", "", "", "http://example.com/path1/%2E"});
+    checkURLDifferences("http://example.com/path1/%2E/",
+        {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
+        {"http", "", "", "example.com", 0, "/path1/%2E/", "", "", "http://example.com/path1/%2E/"});
+    checkURLDifferences("http://example.com/path1/path2/%2e?query",
+        {"http", "", "", "example.com", 0, "/path1/path2/", "query", "", "http://example.com/path1/path2/?query"},
+        {"http", "", "", "example.com", 0, "/path1/path2/%2e", "query", "", "http://example.com/path1/path2/%2e?query"});
+    checkURLDifferences("http://example.com/path1/path2/%2e%2e?query",
+        {"http", "", "", "example.com", 0, "/path1/", "query", "", "http://example.com/path1/?query"},
+        {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "query", "", "http://example.com/path1/path2/%2e%2e?query"});
+    checkURLDifferences("http://example.com/path1/path2/%2e#fragment",
+        {"http", "", "", "example.com", 0, "/path1/path2/", "", "fragment", "http://example.com/path1/path2/#fragment"},
+        {"http", "", "", "example.com", 0, "/path1/path2/%2e", "", "fragment", "http://example.com/path1/path2/%2e#fragment"});
+    checkURLDifferences("http://example.com/path1/path2/%2e%2e#fragment",
+        {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"},
+        {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "", "fragment", "http://example.com/path1/path2/%2e%2e#fragment"});
+    checkURL("http://example.com/path1/path2/A%2e%2e#fragment", {"http", "", "", "example.com", 0, "/path1/path2/A%2e%2e", "", "fragment", "http://example.com/path1/path2/A%2e%2e#fragment"});
     checkURLDifferences("file://[0:a:0:0:b:c:0:0]/path",
         {"file", "", "", "[0:a::b:c:0:0]", 0, "/path", "", "", "file://[0:a::b:c:0:0]/path"},
         {"file", "", "", "[0:a:0:0:b:c:0:0]", 0, "/path", "", "", "file://[0:a:0:0:b:c:0:0]/path"});