| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library uriTest; | 5 library uriTest; |
| 6 | 6 |
| 7 import "package:expect/expect.dart"; | 7 import "package:expect/expect.dart"; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 | 9 |
| 10 testUri(String uriText, bool isAbsolute) { | 10 testUri(String uriText, bool isAbsolute) { |
| 11 var uri = Uri.parse(uriText); | 11 var uri = Uri.parse(uriText); |
| 12 | 12 |
| 13 Expect.equals(isAbsolute, uri.isAbsolute); | 13 Expect.equals(isAbsolute, uri.isAbsolute); |
| 14 Expect.stringEquals(uriText, uri.toString()); | 14 Expect.stringEquals(uriText, uri.toString()); |
| 15 | 15 |
| 16 // Test equals and hashCode members. | 16 // Test equals and hashCode members. |
| 17 var uri2 = Uri.parse(uriText); | 17 var uri2 = Uri.parse(uriText); |
| 18 Expect.equals(uri, uri2); | 18 Expect.equals(uri, uri2); |
| 19 Expect.equals(uri.hashCode, uri2.hashCode); | 19 Expect.equals(uri.hashCode, uri2.hashCode); |
| 20 | 20 |
| 21 // Test that removeFragment doesn't change anything else. | 21 // Test that removeFragment doesn't change anything else. |
| 22 if (uri.hasFragment) { | 22 if (uri.hasFragment) { |
| 23 Expect.equals(Uri.parse(uriText.substring(0, uriText.indexOf('#'))), | 23 Expect.equals(Uri.parse(uriText.substring(0, uriText.indexOf('#'))), |
| 24 uri.removeFragment()); | 24 uri.removeFragment()); |
| 25 } else { | 25 } else { |
| 26 Expect.equals(uri, | 26 Expect.equals(uri, Uri.parse(uriText + "#fragment").removeFragment()); |
| 27 Uri.parse(uriText + "#fragment").removeFragment()); | |
| 28 } | 27 } |
| 29 } | 28 } |
| 30 | 29 |
| 31 testEncodeDecode(String orig, String encoded) { | 30 testEncodeDecode(String orig, String encoded) { |
| 32 var e = Uri.encodeFull(orig); | 31 var e = Uri.encodeFull(orig); |
| 33 Expect.stringEquals(encoded, e); | 32 Expect.stringEquals(encoded, e); |
| 34 var d = Uri.decodeFull(encoded); | 33 var d = Uri.decodeFull(encoded); |
| 35 Expect.stringEquals(orig, d); | 34 Expect.stringEquals(orig, d); |
| 36 } | 35 } |
| 37 | 36 |
| 38 testEncodeDecodeComponent(String orig, String encoded) { | 37 testEncodeDecodeComponent(String orig, String encoded) { |
| 39 var e = Uri.encodeComponent(orig); | 38 var e = Uri.encodeComponent(orig); |
| 40 Expect.stringEquals(encoded, e); | 39 Expect.stringEquals(encoded, e); |
| 41 var d = Uri.decodeComponent(encoded); | 40 var d = Uri.decodeComponent(encoded); |
| 42 Expect.stringEquals(orig, d); | 41 Expect.stringEquals(orig, d); |
| 43 } | 42 } |
| 44 | 43 |
| 45 testEncodeDecodeQueryComponent(String orig, | 44 testEncodeDecodeQueryComponent(String orig, String encodedUTF8, |
| 46 String encodedUTF8, | 45 String encodedLatin1, String encodedAscii) { |
| 47 String encodedLatin1, | |
| 48 String encodedAscii) { | |
| 49 var e, d; | 46 var e, d; |
| 50 e = Uri.encodeQueryComponent(orig); | 47 e = Uri.encodeQueryComponent(orig); |
| 51 Expect.stringEquals(encodedUTF8, e); | 48 Expect.stringEquals(encodedUTF8, e); |
| 52 d = Uri.decodeQueryComponent(encodedUTF8); | 49 d = Uri.decodeQueryComponent(encodedUTF8); |
| 53 Expect.stringEquals(orig, d); | 50 Expect.stringEquals(orig, d); |
| 54 | 51 |
| 55 e = Uri.encodeQueryComponent(orig, encoding: UTF8); | 52 e = Uri.encodeQueryComponent(orig, encoding: UTF8); |
| 56 Expect.stringEquals(encodedUTF8, e); | 53 Expect.stringEquals(encodedUTF8, e); |
| 57 d = Uri.decodeQueryComponent(encodedUTF8, encoding: UTF8); | 54 d = Uri.decodeQueryComponent(encodedUTF8, encoding: UTF8); |
| 58 Expect.stringEquals(orig, d); | 55 Expect.stringEquals(orig, d); |
| 59 | 56 |
| 60 e = Uri.encodeQueryComponent(orig, encoding: LATIN1); | 57 e = Uri.encodeQueryComponent(orig, encoding: LATIN1); |
| 61 Expect.stringEquals(encodedLatin1, e); | 58 Expect.stringEquals(encodedLatin1, e); |
| 62 d = Uri.decodeQueryComponent(encodedLatin1, encoding: LATIN1); | 59 d = Uri.decodeQueryComponent(encodedLatin1, encoding: LATIN1); |
| 63 Expect.stringEquals(orig, d); | 60 Expect.stringEquals(orig, d); |
| 64 | 61 |
| 65 if (encodedAscii != null) { | 62 if (encodedAscii != null) { |
| 66 e = Uri.encodeQueryComponent(orig, encoding: ASCII); | 63 e = Uri.encodeQueryComponent(orig, encoding: ASCII); |
| 67 Expect.stringEquals(encodedAscii, e); | 64 Expect.stringEquals(encodedAscii, e); |
| 68 d = Uri.decodeQueryComponent(encodedAscii, encoding: ASCII); | 65 d = Uri.decodeQueryComponent(encodedAscii, encoding: ASCII); |
| 69 Expect.stringEquals(orig, d); | 66 Expect.stringEquals(orig, d); |
| 70 } else { | 67 } else { |
| 71 Expect.throws(() => Uri.encodeQueryComponent(orig, encoding: ASCII), | 68 Expect.throws(() => Uri.encodeQueryComponent(orig, encoding: ASCII), |
| 72 (e) => e is ArgumentError); | 69 (e) => e is ArgumentError); |
| 73 } | 70 } |
| 74 } | 71 } |
| 75 | 72 |
| 76 testUriPerRFCs() { | 73 testUriPerRFCs() { |
| 77 final urisSample = "http://a/b/c/d;p?q"; | 74 final urisSample = "http://a/b/c/d;p?q"; |
| 78 Uri base = Uri.parse(urisSample); | 75 Uri base = Uri.parse(urisSample); |
| 79 testResolve(expect, relative) { | 76 testResolve(expect, relative) { |
| 80 Expect.stringEquals(expect, base.resolve(relative).toString()); | 77 Expect.stringEquals(expect, base.resolve(relative).toString()); |
| 81 } | 78 } |
| 82 | 79 |
| 83 // From RFC 3986. | 80 // From RFC 3986. |
| 84 testResolve("g:h", "g:h"); | 81 testResolve("g:h", "g:h"); |
| 85 testResolve("http://a/b/c/g", "g"); | 82 testResolve("http://a/b/c/g", "g"); |
| 86 testResolve("http://a/b/c/g", "./g"); | 83 testResolve("http://a/b/c/g", "./g"); |
| 87 testResolve("http://a/b/c/g/", "g/"); | 84 testResolve("http://a/b/c/g/", "g/"); |
| 88 testResolve("http://a/g", "/g"); | 85 testResolve("http://a/g", "/g"); |
| 89 testResolve("http://g", "//g"); | 86 testResolve("http://g", "//g"); |
| 90 testResolve("http://a/b/c/d;p?y", "?y"); | 87 testResolve("http://a/b/c/d;p?y", "?y"); |
| 91 testResolve("http://a/b/c/g?y", "g?y"); | 88 testResolve("http://a/b/c/g?y", "g?y"); |
| 92 testResolve("http://a/b/c/d;p?q#s", "#s"); | 89 testResolve("http://a/b/c/d;p?q#s", "#s"); |
| 93 testResolve("http://a/b/c/g#s", "g#s"); | 90 testResolve("http://a/b/c/g#s", "g#s"); |
| 94 testResolve("http://a/b/c/g?y#s", "g?y#s"); | 91 testResolve("http://a/b/c/g?y#s", "g?y#s"); |
| 95 testResolve("http://a/b/c/;x", ";x"); | 92 testResolve("http://a/b/c/;x", ";x"); |
| 96 testResolve("http://a/b/c/g;x", "g;x"); | 93 testResolve("http://a/b/c/g;x", "g;x"); |
| 97 testResolve("http://a/b/c/g;x?y#s", "g;x?y#s"); | 94 testResolve("http://a/b/c/g;x?y#s", "g;x?y#s"); |
| 98 testResolve("http://a/b/c/d;p?q", ""); | 95 testResolve("http://a/b/c/d;p?q", ""); |
| 99 testResolve("http://a/b/c/", "."); | 96 testResolve("http://a/b/c/", "."); |
| 100 testResolve("http://a/b/c/", "./"); | 97 testResolve("http://a/b/c/", "./"); |
| 101 testResolve("http://a/b/", ".."); | 98 testResolve("http://a/b/", ".."); |
| 102 testResolve("http://a/b/", "../"); | 99 testResolve("http://a/b/", "../"); |
| 103 testResolve("http://a/b/g", "../g"); | 100 testResolve("http://a/b/g", "../g"); |
| 104 testResolve("http://a/", "../.."); | 101 testResolve("http://a/", "../.."); |
| 105 testResolve("http://a/", "../../"); | 102 testResolve("http://a/", "../../"); |
| 106 testResolve("http://a/g", "../../g"); | 103 testResolve("http://a/g", "../../g"); |
| 107 testResolve("http://a/g", "../../../g"); | 104 testResolve("http://a/g", "../../../g"); |
| 108 testResolve("http://a/g", "../../../../g"); | 105 testResolve("http://a/g", "../../../../g"); |
| 109 testResolve("http://a/g", "/./g"); | 106 testResolve("http://a/g", "/./g"); |
| 110 testResolve("http://a/g", "/../g"); | 107 testResolve("http://a/g", "/../g"); |
| 111 testResolve("http://a/b/c/g.", "g."); | 108 testResolve("http://a/b/c/g.", "g."); |
| 112 testResolve("http://a/b/c/.g", ".g"); | 109 testResolve("http://a/b/c/.g", ".g"); |
| 113 testResolve("http://a/b/c/g..", "g.."); | 110 testResolve("http://a/b/c/g..", "g.."); |
| 114 testResolve("http://a/b/c/..g", "..g"); | 111 testResolve("http://a/b/c/..g", "..g"); |
| 115 testResolve("http://a/b/g", "./../g"); | 112 testResolve("http://a/b/g", "./../g"); |
| 116 testResolve("http://a/b/c/g/", "./g/."); | 113 testResolve("http://a/b/c/g/", "./g/."); |
| 117 testResolve("http://a/b/c/g/h", "g/./h"); | 114 testResolve("http://a/b/c/g/h", "g/./h"); |
| 118 testResolve("http://a/b/c/h", "g/../h"); | 115 testResolve("http://a/b/c/h", "g/../h"); |
| 119 testResolve("http://a/b/c/g;x=1/y", "g;x=1/./y"); | 116 testResolve("http://a/b/c/g;x=1/y", "g;x=1/./y"); |
| 120 testResolve("http://a/b/c/y", "g;x=1/../y"); | 117 testResolve("http://a/b/c/y", "g;x=1/../y"); |
| 121 testResolve("http://a/b/c/g?y/./x", "g?y/./x"); | 118 testResolve("http://a/b/c/g?y/./x", "g?y/./x"); |
| 122 testResolve("http://a/b/c/g?y/../x", "g?y/../x"); | 119 testResolve("http://a/b/c/g?y/../x", "g?y/../x"); |
| 123 testResolve("http://a/b/c/g#s/./x", "g#s/./x"); | 120 testResolve("http://a/b/c/g#s/./x", "g#s/./x"); |
| 124 testResolve("http://a/b/c/g#s/../x", "g#s/../x"); | 121 testResolve("http://a/b/c/g#s/../x", "g#s/../x"); |
| 125 testResolve("http:g", "http:g"); | 122 testResolve("http:g", "http:g"); |
| 126 | 123 |
| 127 // Additional tests (not from RFC 3986). | 124 // Additional tests (not from RFC 3986). |
| 128 testResolve("http://a/b/g;p/h;s", "../g;p/h;s"); | 125 testResolve("http://a/b/g;p/h;s", "../g;p/h;s"); |
| 129 | 126 |
| 130 // Test non-URI base (no scheme, no authority, relative path). | 127 // Test non-URI base (no scheme, no authority, relative path). |
| 131 base = Uri.parse("a/b/c?_#_"); | 128 base = Uri.parse("a/b/c?_#_"); |
| 132 testResolve("a/b/g?q#f", "g?q#f"); | 129 testResolve("a/b/g?q#f", "g?q#f"); |
| 133 testResolve("../", "../../.."); | 130 testResolve("../", "../../.."); |
| 134 testResolve("a/b/", "."); | 131 testResolve("a/b/", "."); |
| 135 testResolve("c", "../../c"); | 132 testResolve("c", "../../c"); |
| 136 | 133 |
| 137 base = Uri.parse("s:a/b"); | 134 base = Uri.parse("s:a/b"); |
| 138 testResolve("s:/c", "../c"); | 135 testResolve("s:/c", "../c"); |
| 139 } | 136 } |
| 140 | 137 |
| 141 void testResolvePath(String expected, String path) { | 138 void testResolvePath(String expected, String path) { |
| 142 Expect.equals(expected, | |
| 143 new Uri(path: '/').resolveUri(new Uri(path: path)).path); | |
| 144 Expect.equals( | 139 Expect.equals( |
| 145 "http://localhost$expected", | 140 expected, new Uri(path: '/').resolveUri(new Uri(path: path)).path); |
| 141 Expect.equals("http://localhost$expected", |
| 146 Uri.parse("http://localhost").resolveUri(new Uri(path: path)).toString()); | 142 Uri.parse("http://localhost").resolveUri(new Uri(path: path)).toString()); |
| 147 } | 143 } |
| 148 | 144 |
| 149 const ALPHA = r"abcdefghijklmnopqrstuvwxuzABCDEFGHIJKLMNOPQRSTUVWXUZ"; | 145 const ALPHA = r"abcdefghijklmnopqrstuvwxuzABCDEFGHIJKLMNOPQRSTUVWXUZ"; |
| 150 const DIGIT = r"0123456789"; | 146 const DIGIT = r"0123456789"; |
| 151 const PERCENT_ENCODED = "%00%ff"; | 147 const PERCENT_ENCODED = "%00%ff"; |
| 152 const SUBDELIM = r"!$&'()*+,;="; | 148 const SUBDELIM = r"!$&'()*+,;="; |
| 153 | 149 |
| 154 const SCHEMECHAR = "$ALPHA$DIGIT+-."; | 150 const SCHEMECHAR = "$ALPHA$DIGIT+-."; |
| 155 const UNRESERVED = "$ALPHA$DIGIT-._~"; | 151 const UNRESERVED = "$ALPHA$DIGIT-._~"; |
| 156 const REGNAMECHAR = "$UNRESERVED$SUBDELIM$PERCENT_ENCODED"; | 152 const REGNAMECHAR = "$UNRESERVED$SUBDELIM$PERCENT_ENCODED"; |
| 157 const USERINFOCHAR = "$REGNAMECHAR:"; | 153 const USERINFOCHAR = "$REGNAMECHAR:"; |
| 158 | 154 |
| 159 const PCHAR_NC = "$UNRESERVED$SUBDELIM$PERCENT_ENCODED@"; | 155 const PCHAR_NC = "$UNRESERVED$SUBDELIM$PERCENT_ENCODED@"; |
| 160 const PCHAR = "$PCHAR_NC:"; | 156 const PCHAR = "$PCHAR_NC:"; |
| 161 const QUERYCHAR = "$PCHAR/?"; | 157 const QUERYCHAR = "$PCHAR/?"; |
| 162 | 158 |
| 163 void testValidCharacters() { | 159 void testValidCharacters() { |
| 164 // test that all valid characters are accepted. | 160 // test that all valid characters are accepted. |
| 165 | 161 |
| 166 for (var scheme in ["", "$SCHEMECHAR$SCHEMECHAR:"]) { | 162 for (var scheme in ["", "$SCHEMECHAR$SCHEMECHAR:"]) { |
| 167 for (var userinfo in ["", "@", "$USERINFOCHAR$USERINFOCHAR@", | 163 for (var userinfo in [ |
| 168 "$USERINFOCHAR:$DIGIT@"]) { | 164 "", |
| 169 for (var host in ["", "$REGNAMECHAR$REGNAMECHAR", | 165 "@", |
| 170 "255.255.255.256", // valid reg-name. | 166 "$USERINFOCHAR$USERINFOCHAR@", |
| 171 "[ffff::ffff:ffff]", "[ffff::255.255.255.255]"]) { | 167 "$USERINFOCHAR:$DIGIT@" |
| 168 ]) { |
| 169 for (var host in [ |
| 170 "", "$REGNAMECHAR$REGNAMECHAR", |
| 171 "255.255.255.256", // valid reg-name. |
| 172 "[ffff::ffff:ffff]", "[ffff::255.255.255.255]" |
| 173 ]) { |
| 172 for (var port in ["", ":", ":$DIGIT$DIGIT"]) { | 174 for (var port in ["", ":", ":$DIGIT$DIGIT"]) { |
| 173 var auth = "$userinfo$host$port"; | 175 var auth = "$userinfo$host$port"; |
| 174 if (auth.isNotEmpty) auth = "//$auth"; | 176 if (auth.isNotEmpty) auth = "//$auth"; |
| 175 var paths = ["", "/", "/$PCHAR", "/$PCHAR/"]; // Absolute or empty. | 177 var paths = ["", "/", "/$PCHAR", "/$PCHAR/"]; // Absolute or empty. |
| 176 if (auth.isNotEmpty) { | 178 if (auth.isNotEmpty) { |
| 177 // Initial segment may be empty. | 179 // Initial segment may be empty. |
| 178 paths..add("//$PCHAR"); | 180 paths..add("//$PCHAR"); |
| 179 } else { | 181 } else { |
| 180 // Path may begin with non-slash. | 182 // Path may begin with non-slash. |
| 181 if (scheme.isEmpty) { | 183 if (scheme.isEmpty) { |
| 182 // Initial segment must not contain colon. | 184 // Initial segment must not contain colon. |
| 183 paths..add(PCHAR_NC) | 185 paths |
| 184 ..add("$PCHAR_NC/$PCHAR") | 186 ..add(PCHAR_NC) |
| 185 ..add("$PCHAR_NC/$PCHAR/"); | 187 ..add("$PCHAR_NC/$PCHAR") |
| 188 ..add("$PCHAR_NC/$PCHAR/"); |
| 186 } else { | 189 } else { |
| 187 paths..add(PCHAR) | 190 paths..add(PCHAR)..add("$PCHAR/$PCHAR")..add("$PCHAR/$PCHAR/"); |
| 188 ..add("$PCHAR/$PCHAR") | |
| 189 ..add("$PCHAR/$PCHAR/"); | |
| 190 } | 191 } |
| 191 } | 192 } |
| 192 for (var path in paths) { | 193 for (var path in paths) { |
| 193 for (var query in ["", "?", "?$QUERYCHAR"]) { | 194 for (var query in ["", "?", "?$QUERYCHAR"]) { |
| 194 for (var fragment in ["", "#", "#$QUERYCHAR"]) { | 195 for (var fragment in ["", "#", "#$QUERYCHAR"]) { |
| 195 var uri = "$scheme$auth$path$query$fragment"; | 196 var uri = "$scheme$auth$path$query$fragment"; |
| 196 // Should not throw. | 197 // Should not throw. |
| 197 var result = Uri.parse(uri); | 198 var result = Uri.parse(uri); |
| 198 } | 199 } |
| 199 } | 200 } |
| 200 } | 201 } |
| 201 } | 202 } |
| 202 } | 203 } |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 } | 206 } |
| 206 | 207 |
| 207 void testInvalidUrls() { | 208 void testInvalidUrls() { |
| 208 void checkInvalid(uri) { | 209 void checkInvalid(uri) { |
| 209 try { | 210 try { |
| 210 var result = Uri.parse(uri); | 211 var result = Uri.parse(uri); |
| 211 Expect.fail("Invalid URI `$uri` parsed to $result\n" + dump(result)); | 212 Expect.fail("Invalid URI `$uri` parsed to $result\n" + dump(result)); |
| 212 } on FormatException { | 213 } on FormatException { |
| 213 // Success. | 214 // Success. |
| 214 } | 215 } |
| 215 } | 216 } |
| 217 |
| 216 checkInvalid("s%41://x.x/"); // No escapes in scheme, | 218 checkInvalid("s%41://x.x/"); // No escapes in scheme, |
| 217 // and no colon before slash in path. | 219 // and no colon before slash in path. |
| 218 checkInvalid("1a://x.x/"); // Scheme must start with letter, | 220 checkInvalid("1a://x.x/"); // Scheme must start with letter, |
| 219 // and no colon before slash in path. | 221 // and no colon before slash in path. |
| 220 checkInvalid(".a://x.x/"); // Scheme must start with letter, | 222 checkInvalid(".a://x.x/"); // Scheme must start with letter, |
| 221 // and no colon before slash in path. | 223 // and no colon before slash in path. |
| 222 checkInvalid("_:"); // Character not valid in scheme, | 224 checkInvalid("_:"); // Character not valid in scheme, |
| 223 // and no colon before slash in path. | 225 // and no colon before slash in path. |
| 224 checkInvalid(":"); // Scheme must start with letter, | 226 checkInvalid(":"); // Scheme must start with letter, |
| 225 // and no colon before slash in path. | 227 // and no colon before slash in path. |
| 226 | 228 |
| 227 void checkInvalidReplaced(uri, invalid, replacement) { | 229 void checkInvalidReplaced(uri, invalid, replacement) { |
| 228 var source = uri.replaceAll('{}', invalid); | 230 var source = uri.replaceAll('{}', invalid); |
| 229 var expected = uri.replaceAll('{}', replacement); | 231 var expected = uri.replaceAll('{}', replacement); |
| 230 var result = Uri.parse(source); | 232 var result = Uri.parse(source); |
| 231 Expect.equals(expected, "$result", "Source: $source\n${dump(result)}"); | 233 Expect.equals(expected, "$result", "Source: $source\n${dump(result)}"); |
| 232 } | 234 } |
| 233 | 235 |
| 234 // Regression test for http://dartbug.com/16081 | 236 // Regression test for http://dartbug.com/16081 |
| 235 checkInvalidReplaced("http://www.example.org/red%09ros{}#red)", | 237 checkInvalidReplaced( |
| 236 "\u00e9", "%C3%A9"); | 238 "http://www.example.org/red%09ros{}#red)", "\u00e9", "%C3%A9"); |
| 237 checkInvalidReplaced("http://r{}sum\{}.example.org", "\u00E9", "%C3%A9"); | 239 checkInvalidReplaced("http://r{}sum\{}.example.org", "\u00E9", "%C3%A9"); |
| 238 | 240 |
| 239 // Invalid characters. The characters must be rejected, even if normalizing | 241 // Invalid characters. The characters must be rejected, even if normalizing |
| 240 // the input would cause them to be valid (normalization happens after | 242 // the input would cause them to be valid (normalization happens after |
| 241 // validation). | 243 // validation). |
| 242 var invalidCharsAndReplacements = [ | 244 var invalidCharsAndReplacements = [ |
| 243 "\xe7", "%C3%A7", // Arbitrary non-ASCII letter | 245 "\xe7", "%C3%A7", // Arbitrary non-ASCII letter |
| 244 " ", "%20", // Space, not allowed anywhere. | 246 " ", "%20", // Space, not allowed anywhere. |
| 245 '"', "%22", // Quote, not allowed anywhere | 247 '"', "%22", // Quote, not allowed anywhere |
| 246 "<>", "%3C%3E", // Less/greater-than, not allowed anywhere. | 248 "<>", "%3C%3E", // Less/greater-than, not allowed anywhere. |
| 247 "\x7f", "%7F", // DEL, not allowed anywhere | 249 "\x7f", "%7F", // DEL, not allowed anywhere |
| 248 "\xdf", "%C3%9F", // German lower-case scharf-S. | 250 "\xdf", "%C3%9F", // German lower-case scharf-S. |
| 249 // Becomes ASCII when upper-cased. | 251 // Becomes ASCII when upper-cased. |
| 250 "\u0130", "%C4%B0", // Latin capital dotted I, | 252 "\u0130", "%C4%B0", // Latin capital dotted I, |
| 251 // becomes ASCII lower-case in Turkish. | 253 // becomes ASCII lower-case in Turkish. |
| 252 "%\uFB03", "%25%EF%AC%83", // % + Ligature ffi, | 254 "%\uFB03", "%25%EF%AC%83", // % + Ligature ffi, |
| 253 // becomes ASCII when upper-cased, | 255 // becomes ASCII when upper-cased, |
| 254 // should not be read as "%FFI". | 256 // should not be read as "%FFI". |
| 255 "\u212a", "%E2%84%AA", // Kelvin sign. Becomes ASCII when lower-cased. | 257 "\u212a", "%E2%84%AA", // Kelvin sign. Becomes ASCII when lower-cased. |
| 256 "%1g", "%251g", // Invalid escape. | 258 "%1g", "%251g", // Invalid escape. |
| 257 "\u{10000}", "%F0%90%80%80", // Non-BMP character as surrogate pair. | 259 "\u{10000}", "%F0%90%80%80", // Non-BMP character as surrogate pair. |
| 258 ]; | 260 ]; |
| 259 for (int i = 0; i < invalidCharsAndReplacements.length; i += 2) { | 261 for (int i = 0; i < invalidCharsAndReplacements.length; i += 2) { |
| 260 var invalid = invalidCharsAndReplacements[i]; | 262 var invalid = invalidCharsAndReplacements[i]; |
| 261 var valid = invalidCharsAndReplacements[i + 1]; | 263 var valid = invalidCharsAndReplacements[i + 1]; |
| 262 checkInvalid("A{}b:///".replaceAll('{}', invalid)); | 264 checkInvalid("A{}b:///".replaceAll('{}', invalid)); |
| 263 checkInvalid("{}b:///".replaceAll('{}', invalid)); | 265 checkInvalid("{}b:///".replaceAll('{}', invalid)); |
| 264 checkInvalidReplaced("s://user{}info@x.x/", invalid, valid); | 266 checkInvalidReplaced("s://user{}info@x.x/", invalid, valid); |
| 265 checkInvalidReplaced("s://reg{}name/", invalid, valid); | 267 checkInvalidReplaced("s://reg{}name/", invalid, valid); |
| 266 checkInvalid("s://regname:12{}45/".replaceAll("{}", invalid)); | 268 checkInvalid("s://regname:12{}45/".replaceAll("{}", invalid)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 uri = Uri.parse("Z:"); | 311 uri = Uri.parse("Z:"); |
| 310 Expect.equals("z", uri.scheme); | 312 Expect.equals("z", uri.scheme); |
| 311 uri = Uri.parse("$SCHEMECHAR:"); | 313 uri = Uri.parse("$SCHEMECHAR:"); |
| 312 Expect.equals(SCHEMECHAR.toLowerCase(), uri.scheme); | 314 Expect.equals(SCHEMECHAR.toLowerCase(), uri.scheme); |
| 313 | 315 |
| 314 // Percent escape normalization. | 316 // Percent escape normalization. |
| 315 // Escapes of unreserved characters are converted to the character, | 317 // Escapes of unreserved characters are converted to the character, |
| 316 // subject to case normalization in reg-name. | 318 // subject to case normalization in reg-name. |
| 317 for (var i = 0; i < UNRESERVED.length; i++) { | 319 for (var i = 0; i < UNRESERVED.length; i++) { |
| 318 var char = UNRESERVED[i]; | 320 var char = UNRESERVED[i]; |
| 319 var escape = "%" + char.codeUnitAt(0).toRadixString(16); // all > 0xf. | 321 var escape = "%" + char.codeUnitAt(0).toRadixString(16); // all > 0xf. |
| 320 | 322 |
| 321 uri = Uri.parse("s://xX${escape}xX@yY${escape}yY/zZ${escape}zZ" | 323 uri = Uri.parse("s://xX${escape}xX@yY${escape}yY/zZ${escape}zZ" |
| 322 "?vV${escape}vV#wW${escape}wW"); | 324 "?vV${escape}vV#wW${escape}wW"); |
| 323 Expect.equals("xX${char}xX", uri.userInfo); | 325 Expect.equals("xX${char}xX", uri.userInfo); |
| 324 Expect.equals("yY${char}yY".toLowerCase(), uri.host); | 326 Expect.equals("yY${char}yY".toLowerCase(), uri.host); |
| 325 Expect.equals("/zZ${char}zZ", uri.path); | 327 Expect.equals("/zZ${char}zZ", uri.path); |
| 326 Expect.equals("vV${char}vV", uri.query); | 328 Expect.equals("vV${char}vV", uri.query); |
| 327 Expect.equals("wW${char}wW", uri.fragment); | 329 Expect.equals("wW${char}wW", uri.fragment); |
| 328 } | 330 } |
| 329 | 331 |
| 330 // Escapes of reserved characters are kept, but upper-cased. | 332 // Escapes of reserved characters are kept, but upper-cased. |
| 331 for (var escape in ["%00", "%1f", "%7F", "%fF"]) { | 333 for (var escape in ["%00", "%1f", "%7F", "%fF"]) { |
| 332 uri = Uri.parse("s://xX${escape}xX@yY${escape}yY/zZ${escape}zZ" | 334 uri = Uri.parse("s://xX${escape}xX@yY${escape}yY/zZ${escape}zZ" |
| 333 "?vV${escape}vV#wW${escape}wW"); | 335 "?vV${escape}vV#wW${escape}wW"); |
| 334 var normalizedEscape = escape.toUpperCase(); | 336 var normalizedEscape = escape.toUpperCase(); |
| 335 Expect.equals("xX${normalizedEscape}xX", uri.userInfo); | 337 Expect.equals("xX${normalizedEscape}xX", uri.userInfo); |
| 336 Expect.equals("yy${normalizedEscape}yy", uri.host); | 338 Expect.equals("yy${normalizedEscape}yy", uri.host); |
| 337 Expect.equals("/zZ${normalizedEscape}zZ", uri.path); | 339 Expect.equals("/zZ${normalizedEscape}zZ", uri.path); |
| 338 Expect.equals("vV${normalizedEscape}vV", uri.query); | 340 Expect.equals("vV${normalizedEscape}vV", uri.query); |
| 339 Expect.equals("wW${normalizedEscape}wW", uri.fragment); | 341 Expect.equals("wW${normalizedEscape}wW", uri.fragment); |
| 340 } | 342 } |
| 341 | 343 |
| 342 // Some host normalization edge cases. | 344 // Some host normalization edge cases. |
| 343 uri = Uri.parse("x://x%61X%41x%41X%61x/"); | 345 uri = Uri.parse("x://x%61X%41x%41X%61x/"); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 371 | 373 |
| 372 // File scheme noralizes to always showing authority, even if empty. | 374 // File scheme noralizes to always showing authority, even if empty. |
| 373 uri = new Uri(scheme: "file", path: "/y"); | 375 uri = new Uri(scheme: "file", path: "/y"); |
| 374 Expect.equals("file:///y", uri.toString()); | 376 Expect.equals("file:///y", uri.toString()); |
| 375 uri = new Uri(scheme: "file", path: "y"); | 377 uri = new Uri(scheme: "file", path: "y"); |
| 376 Expect.equals("file:///y", uri.toString()); | 378 Expect.equals("file:///y", uri.toString()); |
| 377 | 379 |
| 378 // Empty host/query/fragment ensures the delimiter is there. | 380 // Empty host/query/fragment ensures the delimiter is there. |
| 379 // Different from not being there. | 381 // Different from not being there. |
| 380 Expect.equals("scheme:/", Uri.parse("scheme:/").toString()); | 382 Expect.equals("scheme:/", Uri.parse("scheme:/").toString()); |
| 381 Expect.equals("scheme:/", | 383 Expect.equals("scheme:/", new Uri(scheme: "scheme", path: "/").toString()); |
| 382 new Uri(scheme: "scheme", path: "/").toString()); | |
| 383 | 384 |
| 384 Expect.equals("scheme:///?#", Uri.parse("scheme:///?#").toString()); | 385 Expect.equals("scheme:///?#", Uri.parse("scheme:///?#").toString()); |
| 385 Expect.equals("scheme:///#", | 386 Expect.equals( |
| 386 new Uri(scheme: "scheme", host: "", path: "/", | 387 "scheme:///#", |
| 387 query: "", fragment: "").toString()); | 388 new Uri(scheme: "scheme", host: "", path: "/", query: "", fragment: "") |
| 389 .toString()); |
| 388 } | 390 } |
| 389 | 391 |
| 390 void testReplace() { | 392 void testReplace() { |
| 391 var uris = [ | 393 var uris = [ |
| 392 Uri.parse(""), | 394 Uri.parse(""), |
| 393 Uri.parse("a://@:/?#"), | 395 Uri.parse("a://@:/?#"), |
| 394 Uri.parse("a://b@c:4/e/f?g#h"), | 396 Uri.parse("a://b@c:4/e/f?g#h"), |
| 395 Uri.parse("$SCHEMECHAR://$USERINFOCHAR@$REGNAMECHAR:$DIGIT/$PCHAR/$PCHAR" | 397 Uri.parse("$SCHEMECHAR://$USERINFOCHAR@$REGNAMECHAR:$DIGIT/$PCHAR/$PCHAR" |
| 396 "?$QUERYCHAR#$QUERYCHAR"), | 398 "?$QUERYCHAR#$QUERYCHAR"), |
| 397 ]; | 399 ]; |
| 398 for (var uri1 in uris) { | 400 for (var uri1 in uris) { |
| 399 for (var uri2 in uris) { | 401 for (var uri2 in uris) { |
| 400 if (identical(uri1, uri2)) continue; | 402 if (identical(uri1, uri2)) continue; |
| 401 var scheme = uri1.scheme; | 403 var scheme = uri1.scheme; |
| 402 var userInfo = uri1.hasAuthority ? uri1.userInfo : ""; | 404 var userInfo = uri1.hasAuthority ? uri1.userInfo : ""; |
| 403 var host = uri1.hasAuthority ? uri1.host : null; | 405 var host = uri1.hasAuthority ? uri1.host : null; |
| 404 var port = uri1.hasAuthority ? uri1.port : 0; | 406 var port = uri1.hasAuthority ? uri1.port : 0; |
| 405 var path = uri1.path; | 407 var path = uri1.path; |
| 406 var query = uri1.hasQuery ? uri1.query : null; | 408 var query = uri1.hasQuery ? uri1.query : null; |
| 407 var fragment = uri1.hasFragment ? uri1.fragment : null; | 409 var fragment = uri1.hasFragment ? uri1.fragment : null; |
| 408 | 410 |
| 409 var tmp1 = uri1; | 411 var tmp1 = uri1; |
| 410 | 412 |
| 411 void test() { | 413 void test() { |
| 412 var tmp2 = new Uri(scheme: scheme, userInfo: userInfo, host: host, | 414 var tmp2 = new Uri( |
| 413 port: port, path: path, | 415 scheme: scheme, |
| 414 query: query == "" ? null : query, | 416 userInfo: userInfo, |
| 415 queryParameters: query == "" ? {} : null, | 417 host: host, |
| 416 fragment: fragment); | 418 port: port, |
| 419 path: path, |
| 420 query: query == "" ? null : query, |
| 421 queryParameters: query == "" ? {} : null, |
| 422 fragment: fragment); |
| 417 Expect.equals(tmp1, tmp2); | 423 Expect.equals(tmp1, tmp2); |
| 418 } | 424 } |
| 419 | 425 |
| 420 test(); | 426 test(); |
| 421 | 427 |
| 422 scheme = uri2.scheme; | 428 scheme = uri2.scheme; |
| 423 tmp1 = tmp1.replace(scheme: scheme); | 429 tmp1 = tmp1.replace(scheme: scheme); |
| 424 test(); | 430 test(); |
| 425 | 431 |
| 426 if (uri2.hasAuthority) { | 432 if (uri2.hasAuthority) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 448 } | 454 } |
| 449 } | 455 } |
| 450 } | 456 } |
| 451 | 457 |
| 452 // Regression test, http://dartbug.com/20814 | 458 // Regression test, http://dartbug.com/20814 |
| 453 var uri = Uri.parse("/no-authorty/"); | 459 var uri = Uri.parse("/no-authorty/"); |
| 454 uri = uri.replace(fragment: "fragment"); | 460 uri = uri.replace(fragment: "fragment"); |
| 455 Expect.isFalse(uri.hasAuthority); | 461 Expect.isFalse(uri.hasAuthority); |
| 456 | 462 |
| 457 uri = new Uri(scheme: "foo", path: "bar"); | 463 uri = new Uri(scheme: "foo", path: "bar"); |
| 458 uri = uri.replace( | 464 uri = uri.replace(queryParameters: { |
| 459 queryParameters: {"x": ["42", "37"], "y": ["43", "38"]}); | 465 "x": ["42", "37"], |
| 466 "y": ["43", "38"] |
| 467 }); |
| 460 var params = uri.queryParametersAll; | 468 var params = uri.queryParametersAll; |
| 461 Expect.equals(2, params.length); | 469 Expect.equals(2, params.length); |
| 462 Expect.listEquals(["42", "37"], params["x"]); | 470 Expect.listEquals(["42", "37"], params["x"]); |
| 463 Expect.listEquals(["43", "38"], params["y"]); | 471 Expect.listEquals(["43", "38"], params["y"]); |
| 464 } | 472 } |
| 465 | 473 |
| 466 main() { | 474 main() { |
| 467 testUri("http:", true); | 475 testUri("http:", true); |
| 468 testUri("file:///", true); | 476 testUri("file:///", true); |
| 469 testUri("file", false); | 477 testUri("file", false); |
| 470 testUri("http://user@example.com:8080/fisk?query=89&hest=silas", true); | 478 testUri("http://user@example.com:8080/fisk?query=89&hest=silas", true); |
| 471 testUri("http://user@example.com:8080/fisk?query=89&hest=silas#fragment", | 479 testUri( |
| 472 false); | 480 "http://user@example.com:8080/fisk?query=89&hest=silas#fragment", false); |
| 473 Expect.stringEquals("http://user@example.com/a/b/c?query#fragment", | 481 Expect.stringEquals( |
| 474 new Uri( | 482 "http://user@example.com/a/b/c?query#fragment", |
| 475 scheme: "http", | 483 new Uri( |
| 476 userInfo: "user", | 484 scheme: "http", |
| 477 host: "example.com", | 485 userInfo: "user", |
| 478 port: 80, | 486 host: "example.com", |
| 479 path: "/a/b/c", | 487 port: 80, |
| 480 query: "query", | 488 path: "/a/b/c", |
| 481 fragment: "fragment").toString()); | 489 query: "query", |
| 482 Expect.stringEquals("/a/b/c/", | 490 fragment: "fragment") |
| 483 new Uri( | 491 .toString()); |
| 484 scheme: null, | 492 Expect.stringEquals( |
| 485 userInfo: null, | 493 "/a/b/c/", |
| 486 host: null, | 494 new Uri( |
| 487 port: 0, | 495 scheme: null, |
| 488 path: "/a/b/c/", | 496 userInfo: null, |
| 489 query: null, | 497 host: null, |
| 490 fragment: null).toString()); | 498 port: 0, |
| 499 path: "/a/b/c/", |
| 500 query: null, |
| 501 fragment: null) |
| 502 .toString()); |
| 491 Expect.stringEquals("file:///", Uri.parse("file:").toString()); | 503 Expect.stringEquals("file:///", Uri.parse("file:").toString()); |
| 492 | 504 |
| 493 testResolvePath("/a/g", "/a/b/c/./../../g"); | 505 testResolvePath("/a/g", "/a/b/c/./../../g"); |
| 494 testResolvePath("/a/g", "/a/b/c/./../../g"); | 506 testResolvePath("/a/g", "/a/b/c/./../../g"); |
| 495 testResolvePath("/mid/6", "mid/content=5/../6"); | 507 testResolvePath("/mid/6", "mid/content=5/../6"); |
| 496 testResolvePath("/a/b/e", "a/b/c/d/../../e"); | 508 testResolvePath("/a/b/e", "a/b/c/d/../../e"); |
| 497 testResolvePath("/a/b/e", "../a/b/c/d/../../e"); | 509 testResolvePath("/a/b/e", "../a/b/c/d/../../e"); |
| 498 testResolvePath("/a/b/e", "./a/b/c/d/../../e"); | 510 testResolvePath("/a/b/e", "./a/b/c/d/../../e"); |
| 499 testResolvePath("/a/b/e", "../a/b/./c/d/../../e"); | 511 testResolvePath("/a/b/e", "../a/b/./c/d/../../e"); |
| 500 testResolvePath("/a/b/e", "./a/b/./c/d/../../e"); | 512 testResolvePath("/a/b/e", "./a/b/./c/d/../../e"); |
| 501 testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/."); | 513 testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/."); |
| 502 testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/./."); | 514 testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/./."); |
| 503 testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/././."); | 515 testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/././."); |
| 504 | 516 |
| 505 testUriPerRFCs(); | 517 testUriPerRFCs(); |
| 506 | 518 |
| 507 Expect.stringEquals( | 519 Expect.stringEquals( |
| 508 "http://example.com", | 520 "http://example.com", Uri.parse("http://example.com/a/b/c").origin); |
| 509 Uri.parse("http://example.com/a/b/c").origin); | |
| 510 Expect.stringEquals( | 521 Expect.stringEquals( |
| 511 "https://example.com", | 522 "https://example.com", Uri.parse("https://example.com/a/b/c").origin); |
| 512 Uri.parse("https://example.com/a/b/c").origin); | 523 Expect.stringEquals("http://example.com:1234", |
| 513 Expect.stringEquals( | |
| 514 "http://example.com:1234", | |
| 515 Uri.parse("http://example.com:1234/a/b/c").origin); | 524 Uri.parse("http://example.com:1234/a/b/c").origin); |
| 516 Expect.stringEquals( | 525 Expect.stringEquals("https://example.com:1234", |
| 517 "https://example.com:1234", | |
| 518 Uri.parse("https://example.com:1234/a/b/c").origin); | 526 Uri.parse("https://example.com:1234/a/b/c").origin); |
| 519 Expect.throws( | 527 Expect.throws(() => Uri.parse("http:").origin, (e) { |
| 520 () => Uri.parse("http:").origin, | 528 return e is StateError; |
| 521 (e) { return e is StateError; }, | 529 }, "origin for uri with empty host should fail"); |
| 522 "origin for uri with empty host should fail"); | |
| 523 Expect.throws( | 530 Expect.throws( |
| 524 () => new Uri( | 531 () => new Uri( |
| 525 scheme: "http", | 532 scheme: "http", |
| 526 userInfo: null, | 533 userInfo: null, |
| 527 host: "", | 534 host: "", |
| 528 port: 80, | 535 port: 80, |
| 529 path: "/a/b/c", | 536 path: "/a/b/c", |
| 530 query: "query", | 537 query: "query", |
| 531 fragment: "fragment").origin, | 538 fragment: "fragment") |
| 532 (e) { return e is StateError; }, | 539 .origin, (e) { |
| 533 "origin for uri with empty host should fail"); | 540 return e is StateError; |
| 541 }, "origin for uri with empty host should fail"); |
| 534 Expect.throws( | 542 Expect.throws( |
| 535 () => new Uri( | 543 () => new Uri( |
| 536 scheme: null, | 544 scheme: null, |
| 537 userInfo: null, | 545 userInfo: null, |
| 538 host: "", | 546 host: "", |
| 539 port: 80, | 547 port: 80, |
| 540 path: "/a/b/c", | 548 path: "/a/b/c", |
| 541 query: "query", | 549 query: "query", |
| 542 fragment: "fragment").origin, | 550 fragment: "fragment") |
| 543 (e) { return e is StateError; }, | 551 .origin, (e) { |
| 544 "origin for uri with empty scheme should fail"); | 552 return e is StateError; |
| 553 }, "origin for uri with empty scheme should fail"); |
| 545 Expect.throws( | 554 Expect.throws( |
| 546 () => new Uri( | 555 () => new Uri( |
| 547 scheme: "http", | 556 scheme: "http", |
| 548 userInfo: null, | 557 userInfo: null, |
| 549 host: null, | 558 host: null, |
| 550 port: 80, | 559 port: 80, |
| 551 path: "/a/b/c", | 560 path: "/a/b/c", |
| 552 query: "query", | 561 query: "query", |
| 553 fragment: "fragment").origin, | 562 fragment: "fragment") |
| 554 (e) { return e is StateError; }, | 563 .origin, (e) { |
| 555 "origin for uri with empty host should fail"); | 564 return e is StateError; |
| 556 Expect.throws( | 565 }, "origin for uri with empty host should fail"); |
| 557 () => Uri.parse("http://:80").origin, | 566 Expect.throws(() => Uri.parse("http://:80").origin, (e) { |
| 558 (e) { return e is StateError; }, | 567 return e is StateError; |
| 559 "origin for uri with empty host should fail"); | 568 }, "origin for uri with empty host should fail"); |
| 560 Expect.throws( | 569 Expect.throws(() => Uri.parse("file://localhost/test.txt").origin, (e) { |
| 561 () => Uri.parse("file://localhost/test.txt").origin, | 570 return e is StateError; |
| 562 (e) { return e is StateError; }, | 571 }, "origin for non-http/https uri should fail"); |
| 563 "origin for non-http/https uri should fail"); | |
| 564 | 572 |
| 565 // URI encode tests | 573 // URI encode tests |
| 566 // Create a string with code point 0x10000 encoded as a surrogate pair. | 574 // Create a string with code point 0x10000 encoded as a surrogate pair. |
| 567 var s = UTF8.decode([0xf0, 0x90, 0x80, 0x80]); | 575 var s = UTF8.decode([0xf0, 0x90, 0x80, 0x80]); |
| 568 | 576 |
| 569 Expect.stringEquals("\u{10000}", s); | 577 Expect.stringEquals("\u{10000}", s); |
| 570 | 578 |
| 571 testEncodeDecode("A + B", "A%20+%20B"); | 579 testEncodeDecode("A + B", "A%20+%20B"); |
| 572 testEncodeDecode("\uFFFE", "%EF%BF%BE"); | 580 testEncodeDecode("\uFFFE", "%EF%BF%BE"); |
| 573 testEncodeDecode("\uFFFF", "%EF%BF%BF"); | 581 testEncodeDecode("\uFFFF", "%EF%BF%BF"); |
| 574 testEncodeDecode("\uFFFE", "%EF%BF%BE"); | 582 testEncodeDecode("\uFFFE", "%EF%BF%BE"); |
| 575 testEncodeDecode("\uFFFF", "%EF%BF%BF"); | 583 testEncodeDecode("\uFFFF", "%EF%BF%BF"); |
| 576 testEncodeDecode("\x7f", "%7F"); | 584 testEncodeDecode("\x7f", "%7F"); |
| 577 testEncodeDecode("\x80", "%C2%80"); | 585 testEncodeDecode("\x80", "%C2%80"); |
| 578 testEncodeDecode("\u0800", "%E0%A0%80"); | 586 testEncodeDecode("\u0800", "%E0%A0%80"); |
| 579 // All characters not escaped by encodeFull. | 587 // All characters not escaped by encodeFull. |
| 580 var unescapedFull = | 588 var unescapedFull = r"abcdefghijklmnopqrstuvwxyz" |
| 581 r"abcdefghijklmnopqrstuvwxyz" | |
| 582 r"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | 589 r"ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 583 r"0123456789!#$&'()*+,-./:;=?@_~"; | 590 r"0123456789!#$&'()*+,-./:;=?@_~"; |
| 584 // ASCII characters escaped by encodeFull: | 591 // ASCII characters escaped by encodeFull: |
| 585 var escapedFull = | 592 var escapedFull = |
| 586 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" | 593 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" |
| 587 "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" | 594 "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" |
| 588 r' "%<>[\]^`{|}' | 595 r' "%<>[\]^`{|}' |
| 589 "\x7f"; | 596 "\x7f"; |
| 590 var escapedTo = | 597 var escapedTo = "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F" |
| 591 "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F" | |
| 592 "%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F" | 598 "%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F" |
| 593 "%20%22%25%3C%3E%5B%5C%5D%5E%60%7B%7C%7D%7F"; | 599 "%20%22%25%3C%3E%5B%5C%5D%5E%60%7B%7C%7D%7F"; |
| 594 testEncodeDecode(unescapedFull, unescapedFull); | 600 testEncodeDecode(unescapedFull, unescapedFull); |
| 595 testEncodeDecode(escapedFull, escapedTo); | 601 testEncodeDecode(escapedFull, escapedTo); |
| 596 var nonAscii = | 602 var nonAscii = |
| 597 "\x80-\xff-\u{100}-\u{7ff}-\u{800}-\u{ffff}-\u{10000}-\u{10ffff}"; | 603 "\x80-\xff-\u{100}-\u{7ff}-\u{800}-\u{ffff}-\u{10000}-\u{10ffff}"; |
| 598 var nonAsciiEncoding = | 604 var nonAsciiEncoding = "%C2%80-%C3%BF-%C4%80-%DF%BF-%E0%A0%80-%EF%BF%BF-" |
| 599 "%C2%80-%C3%BF-%C4%80-%DF%BF-%E0%A0%80-%EF%BF%BF-" | |
| 600 "%F0%90%80%80-%F4%8F%BF%BF"; | 605 "%F0%90%80%80-%F4%8F%BF%BF"; |
| 601 testEncodeDecode(nonAscii, nonAsciiEncoding); | 606 testEncodeDecode(nonAscii, nonAsciiEncoding); |
| 602 testEncodeDecode(s, "%F0%90%80%80"); | 607 testEncodeDecode(s, "%F0%90%80%80"); |
| 603 testEncodeDecodeComponent("A + B", "A%20%2B%20B"); | 608 testEncodeDecodeComponent("A + B", "A%20%2B%20B"); |
| 604 testEncodeDecodeComponent("\uFFFE", "%EF%BF%BE"); | 609 testEncodeDecodeComponent("\uFFFE", "%EF%BF%BE"); |
| 605 testEncodeDecodeComponent("\uFFFF", "%EF%BF%BF"); | 610 testEncodeDecodeComponent("\uFFFF", "%EF%BF%BF"); |
| 606 testEncodeDecodeComponent("\uFFFE", "%EF%BF%BE"); | 611 testEncodeDecodeComponent("\uFFFE", "%EF%BF%BE"); |
| 607 testEncodeDecodeComponent("\uFFFF", "%EF%BF%BF"); | 612 testEncodeDecodeComponent("\uFFFF", "%EF%BF%BF"); |
| 608 testEncodeDecodeComponent("\x7f", "%7F"); | 613 testEncodeDecodeComponent("\x7f", "%7F"); |
| 609 testEncodeDecodeComponent("\x80", "%C2%80"); | 614 testEncodeDecodeComponent("\x80", "%C2%80"); |
| 610 testEncodeDecodeComponent("\u0800", "%E0%A0%80"); | 615 testEncodeDecodeComponent("\u0800", "%E0%A0%80"); |
| 611 testEncodeDecodeComponent(":/@',;?&=+\$", "%3A%2F%40'%2C%3B%3F%26%3D%2B%24"); | 616 testEncodeDecodeComponent(":/@',;?&=+\$", "%3A%2F%40'%2C%3B%3F%26%3D%2B%24"); |
| 612 testEncodeDecodeComponent(s, "%F0%90%80%80"); | 617 testEncodeDecodeComponent(s, "%F0%90%80%80"); |
| 613 testEncodeDecodeQueryComponent("A + B", "A+%2B+B", "A+%2B+B", "A+%2B+B"); | 618 testEncodeDecodeQueryComponent("A + B", "A+%2B+B", "A+%2B+B", "A+%2B+B"); |
| 614 testEncodeDecodeQueryComponent( | 619 testEncodeDecodeQueryComponent( |
| 615 "æ ø å", "%C3%A6+%C3%B8+%C3%A5", "%E6+%F8+%E5", null); | 620 "æ ø å", "%C3%A6+%C3%B8+%C3%A5", "%E6+%F8+%E5", null); |
| 616 testEncodeDecodeComponent(nonAscii, nonAsciiEncoding); | 621 testEncodeDecodeComponent(nonAscii, nonAsciiEncoding); |
| 617 | 622 |
| 618 // Invalid URI - : and @ is swapped, port ("host") should be numeric. | 623 // Invalid URI - : and @ is swapped, port ("host") should be numeric. |
| 619 Expect.throws( | 624 Expect.throws(() => Uri.parse("file://user@password:host/path"), |
| 620 () => Uri.parse("file://user@password:host/path"), | |
| 621 (e) => e is FormatException); | 625 (e) => e is FormatException); |
| 622 | 626 |
| 623 testValidCharacters(); | 627 testValidCharacters(); |
| 624 testInvalidUrls(); | 628 testInvalidUrls(); |
| 625 testNormalization(); | 629 testNormalization(); |
| 626 testReplace(); | 630 testReplace(); |
| 627 } | 631 } |
| 628 | 632 |
| 629 String dump(Uri uri) { | 633 String dump(Uri uri) { |
| 630 return "URI: $uri\n" | 634 return "URI: $uri\n" |
| 631 " Scheme: ${uri.scheme} #${uri.scheme.length}\n" | 635 " Scheme: ${uri.scheme} #${uri.scheme.length}\n" |
| 632 " User-info: ${uri.userInfo} #${uri.userInfo.length}\n" | 636 " User-info: ${uri.userInfo} #${uri.userInfo.length}\n" |
| 633 " Host: ${uri.host} #${uri.host.length}\n" | 637 " Host: ${uri.host} #${uri.host.length}\n" |
| 634 " Port: ${uri.port}\n" | 638 " Port: ${uri.port}\n" |
| 635 " Path: ${uri.path} #${uri.path.length}\n" | 639 " Path: ${uri.path} #${uri.path.length}\n" |
| 636 " Query: ${uri.query} #${uri.query.length}\n" | 640 " Query: ${uri.query} #${uri.query.length}\n" |
| 637 " Fragment: ${uri.fragment} #${uri.fragment.length}\n"; | 641 " Fragment: ${uri.fragment} #${uri.fragment.length}\n"; |
| 638 } | 642 } |
| OLD | NEW |