/* * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * @test * @bug 8293590 * @summary URL built-in protocol handlers should parse the URL early * to avoid constructing URLs for which openConnection * would later throw an exception, when possible. * A jdk.net.url.delayParsing property allows to switch that * behavior off to mitigate risks of regression * @run junit EarlyOrDelayedParsing * @run junit/othervm -Djdk.net.url.delayParsing EarlyOrDelayedParsing * @run junit/othervm -Djdk.net.url.delayParsing=true EarlyOrDelayedParsing * @run junit/othervm -Djdk.net.url.delayParsing=false EarlyOrDelayedParsing
*/
// Some characters that when included at the wrong place // in the authority component, without being escaped, would // cause an exception. privatestaticfinal String EXCLUDED_DELIMS = "<>\""; privatestaticfinal String UNWISE = "{}|\\^`"; privatestaticfinal String DELIMS = "[]/?#@";
// Test data used to test exceptions thrown by URL // at some point, when constructed with some illegal input.
sealed interface URLArgTest
permits OneArgTest, TwoArgsTest, ThreeArgsTest, FourArgsTest {
// Some character that is expected to cause an exception // at some point, and which this test case is built for int character();
// An URL string containing the illegal character
String url();
// Some characters are already checked at construction // time. They will cause an exception to be thrown, // whether delayed parsing is activated or not. // This method returns true if an exception is // expected at construction time for this test case, // even when delayed parsing is activated. boolean early(int c);
// The URL scheme this test case is built for. // Typically, one of "http", "https", "ftp"... default String scheme() { return scheme(url());
}
// Return the URL string of this test case, after // substituting its scheme with the given scheme. default String urlWithScheme(String scheme) {
String url = url(); int colon = url.indexOf(':');
String urlWithScheme = scheme + url.substring(colon); return urlWithScheme;
}
// Which exception to expect when parsing is delayed defaultboolean acceptDelayedException(Throwable exception) { return exception instanceof MalformedURLException
|| exception instanceof UnknownHostException;
}
// Test data for the one arg constructor // public URL(String spec) throws MalformedURLException
sealed interface OneArgTest extends URLArgTest {
// Create a new test case identical to this one but // with a different URL scheme default OneArgTest withScheme(String scheme) {
String urlWithScheme = urlWithScheme(scheme); if (thisinstanceof OfHost) { returnnew OfHost(character(), urlWithScheme);
} if (thisinstanceof OfUserInfo) { returnnew OfUserInfo(character(), urlWithScheme);
} thrownew AssertionError("unexpected subclass: " + this.getClass());
}
@Override defaultboolean early(int c) { returnthisinstanceof OfHost &&
(c < 31 || c == 127);
}
record OfHost(int character, String url) implements OneArgTest { }
record OfUserInfo(int character, String url) implements OneArgTest { }
static OneArgTest ofHost(int c) { returnnew OfHost(c, "http://local%shost/".formatted(Character.toString(c)));
} static OneArgTest ofUserInfo(int c) { returnnew OfUserInfo(c, "http://user%sinfo@localhost:9999/".formatted(Character.toString(c)));
}
}
// Test data for the two arg constructor // public URL(URL context, String spec) throws MalformedURLException
sealed interface TwoArgsTest extends URLArgTest {
// Create a new test case identical to this one but // with a different URL scheme default TwoArgsTest withScheme(String scheme) {
String urlWithScheme = urlWithScheme(scheme); if (thisinstanceof OfTwoArgsHost) { returnnew OfTwoArgsHost(character(), urlWithScheme);
} if (thisinstanceof OfTwoArgsUserInfo) { returnnew OfTwoArgsUserInfo(character(), urlWithScheme);
} thrownew AssertionError("unexpected subclass: " + this.getClass());
}
@Override defaultboolean early(int c) { returnthisinstanceof OfTwoArgsHost &&
(c < 31 || c == 127);
}
// Test data for the three args constructor // public URL(String scheme, String host, String file) // throws MalformedURLException
sealed interface ThreeArgsTest extends URLArgTest {
// the host component
String host();
// the path + query components
String file();
// Create a new test case identical to this one but // with a different URL scheme and port default ThreeArgsTest withScheme(String scheme) {
String urlWithScheme = urlWithScheme(scheme); if (thisinstanceof OfHostFile) { returnnew OfHostFile(character(), host(), file(), urlWithScheme);
} thrownew AssertionError("unexpected subclass: " + this.getClass());
}
@Override defaultboolean early(int c) { return (c < 31 || c == 127 || c == '/');
}
// Test data for the four args constructor // public URL(String scheme, String host, int port, String file) // throws MalformedURLException
sealed interface FourArgsTest extends URLArgTest {
// the host component
String host();
// the port component int port();
// the path + query components
String file();
// Create a new test case identical to this one but // with a different URL scheme and port default FourArgsTest withScheme(String scheme) {
String urlWithScheme = urlWithScheme(scheme); if (thisinstanceof OfHostFilePort) { int port = URLArgTest.port(scheme); returnnew OfHostFilePort(character(), host(), port, file(), urlWithScheme);
} thrownew AssertionError("unexpected subclass: " + this.getClass());
}
@Override defaultboolean early(int c) { return (c < 31 || c == 127 || c == '/');
}
record OfHostFilePort(int character, String host, int port, String file, String url) implements FourArgsTest {
}
static FourArgsTest ofHostPortFile(int c) {
String host = "local%shost".formatted(Character.toString(c));
String url = "http://" + host + "/"; int port = URLArgTest.port(URLArgTest.scheme(url)); returnnew OfHostFilePort(c, host, port, "/", url);
}
}
// Generate test data for the URL one arg constructor, with variations // of the host component. static Stream<OneArgTest> oneArgHostTests() {
List<OneArgTest> tests = new ArrayList<>();
List<OneArgTest> urls = new ArrayList<>();
urls.addAll((UNWISE + EXCLUDED_DELIMS).chars()
.mapToObj(OneArgTest::ofHost).toList());
urls.addAll(IntStream.concat(IntStream.range(0, 31), IntStream.of(127))
.mapToObj(OneArgTest::ofHost).toList()); for (String scheme : List.of("http", "https", "ftp")) { for (var test : urls) {
tests.add(test.withScheme(scheme));
}
} return tests.stream();
}
// Generate test data for the URL one arg constructor, with variations // of the user info component. static Stream<OneArgTest> oneArgUserInfoTests() {
List<OneArgTest> tests = new ArrayList<>();
List<OneArgTest> urls = new ArrayList<>();
urls.addAll(IntStream.concat(IntStream.range(0, 31), IntStream.of(127))
.mapToObj(OneArgTest::ofUserInfo).toList());
urls.add(OneArgTest.ofUserInfo('\\')); for (String scheme : List.of("http", "https", "ftp")) { for (var test : urls) {
tests.add(test.withScheme(scheme));
}
} return tests.stream();
}
// Test data with all variations for the URL one arg // constructor (spec) static Stream<OneArgTest> oneArgTests() { return Stream.concat(oneArgHostTests(), oneArgUserInfoTests());
}
// Test data with all variations for the URL two arg // constructor (URL, spec) static Stream<TwoArgsTest> twoArgTests() { return oneArgTests().map(TwoArgsTest::ofOneArgTest);
}
// Generate test data for the URL three arguments constructor // (scheme, host, file) static Stream<ThreeArgsTest> threeArgsTests() {
List<ThreeArgsTest> urls = new ArrayList<>();
urls.addAll((UNWISE + EXCLUDED_DELIMS + DELIMS).chars()
.mapToObj(ThreeArgsTest::ofHostFile).toList());
urls.addAll(IntStream.concat(IntStream.range(0, 31), IntStream.of(127))
.mapToObj(ThreeArgsTest::ofHostFile).toList());
List<ThreeArgsTest> tests = new ArrayList<>(); for (String scheme : List.of("http", "https", "ftp", "file")) { for (var test : urls) {
tests.add(test.withScheme(scheme));
}
} return tests.stream();
}
// Generate test data for the URL four arguments constructor // (scheme, host, port, file) static Stream<FourArgsTest> fourArgsTests() {
List<FourArgsTest> urls = new ArrayList<>();
urls.addAll((UNWISE + EXCLUDED_DELIMS + DELIMS).chars()
.mapToObj(FourArgsTest::ofHostPortFile).toList());
urls.addAll(IntStream.concat(IntStream.range(0, 31), IntStream.of(127))
.mapToObj(FourArgsTest::ofHostPortFile).toList());
List<FourArgsTest> tests = new ArrayList<>(); for (String scheme : List.of("http", "https", "ftp", "file")) { for (var test : urls) {
tests.add(test.withScheme(scheme));
}
} return tests.stream();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.