/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/java/net/httpclient/HttpRequestBuilderTest.java
540 строк
21 KB
Volkan Yazici
8380989: HttpRequest.Builder#headers() throws an exception if an empty array is passed
17 апр 2026, 11:18
17 апр 2026, 11:18
877425a
Код
Авторство
О чём код?
/* * Copyright (c) 2016, 2026, 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. */ import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpOption.Http3DiscoveryMode; import java.net.http.HttpOption; import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import java.net.http.HttpRequest; import static java.net.http.HttpRequest.BodyPublishers.ofString; import static java.net.http.HttpRequest.BodyPublishers.noBody; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; /* * @test * @bug 8170064 8276559 * @summary HttpRequest[.Builder] API and behaviour checks */ public class HttpRequestBuilderTest { static final URI TEST_URI = URI.create("http://www.foo.com/"); public static void main(String[] args) throws Exception { test0("newBuilder().build()", () -> HttpRequest.newBuilder().build(), IllegalStateException.class); test0("newBuilder(null)", () -> HttpRequest.newBuilder(null), NullPointerException.class); test0("newBuilder(URI.create(\"badScheme://www.foo.com/\")", () -> HttpRequest.newBuilder(URI.create("badScheme://www.foo.com/")), IllegalArgumentException.class); test0("newBuilder(URI.create(\"http://www.foo.com:-1/\")", () -> HttpRequest.newBuilder(URI.create("http://www.foo.com:-1/")), IllegalArgumentException.class); test0("newBuilder(URI.create(\"https://www.foo.com:-1/\")", () -> HttpRequest.newBuilder(URI.create("https://www.foo.com:-1/")), IllegalArgumentException.class); test0("newBuilder(" + TEST_URI + ").uri(null)", () -> HttpRequest.newBuilder(TEST_URI).uri(null), NullPointerException.class); test0("newBuilder(uri).build()", () -> HttpRequest.newBuilder(TEST_URI).build() /* no expected exceptions */ ); HttpRequest.Builder builder = HttpRequest.newBuilder(); builder = test1("uri", builder, builder::uri, (URI)null, NullPointerException.class); builder = test1("uri", builder, builder::uri, URI.create("http://www.foo.com:-1/"), IllegalArgumentException.class); builder = test1("uri", builder, builder::uri, URI.create("https://www.foo.com:-1/"), IllegalArgumentException.class); builder = test2("header", builder, builder::header, (String) null, "bar", NullPointerException.class); builder = test2("header", builder, builder::header, "foo", (String) null, NullPointerException.class); builder = test2("header", builder, builder::header, (String)null, (String) null, NullPointerException.class); builder = test2("header", builder, builder::header, "", "bar", IllegalArgumentException.class); builder = test2("header", builder, builder::header, "foo", "\r", IllegalArgumentException.class); builder = test1("headers", builder, builder::headers, (String[]) null, NullPointerException.class); builder = test1("headers", builder, builder::headers, new String[0] /* no expected exceptions */); builder = test1("headers", builder, builder::headers, (String[]) new String[] {null, "bar"}, NullPointerException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", null}, NullPointerException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {null, null}, NullPointerException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", null}, NullPointerException.class, IllegalArgumentException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", null, null}, NullPointerException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", "baz", null}, NullPointerException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", "\r", "baz"}, IllegalArgumentException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", "baz", "\n"}, IllegalArgumentException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", "", "baz"}, IllegalArgumentException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", null, "baz"}, NullPointerException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo", "bar", "baz"}, IllegalArgumentException.class); builder = test1("headers", builder, builder::headers, (String[]) new String[] {"foo"}, IllegalArgumentException.class); test0("DELETE", () -> HttpRequest.newBuilder(TEST_URI).DELETE().build(), null); test0("HEAD", () -> HttpRequest.newBuilder(TEST_URI).HEAD().build(), null); builder = test1("POST", builder, builder::POST, noBody(), null); builder = test1("PUT", builder, builder::PUT, noBody(), null); builder = test2("method", builder, builder::method, "GET", noBody(), null); builder = test1("POST", builder, builder::POST, (HttpRequest.BodyPublisher)null, NullPointerException.class); builder = test1("PUT", builder, builder::PUT, (HttpRequest.BodyPublisher)null, NullPointerException.class); builder = test2("method", builder, builder::method, "GET", (HttpRequest.BodyPublisher) null, NullPointerException.class); builder = test2("setHeader", builder, builder::setHeader, (String) null, "bar", NullPointerException.class); builder = test2("setHeader", builder, builder::setHeader, "foo", (String) null, NullPointerException.class); builder = test2("setHeader", builder, builder::setHeader, (String)null, (String) null, NullPointerException.class); builder = test1("timeout", builder, builder::timeout, (Duration)null, NullPointerException.class); builder = test1("version", builder, builder::version, (HttpClient.Version)null, NullPointerException.class); builder = test2("method", builder, builder::method, null, ofString("foo"), NullPointerException.class); builder = test2("setOption", builder, builder::setOption, (HttpOption<Http3DiscoveryMode>)null, (Http3DiscoveryMode) null, NullPointerException.class); builder = test2("setOption", builder, builder::setOption, (HttpOption<Http3DiscoveryMode>)null, HTTP_3_URI_ONLY, NullPointerException.class); // see JDK-8170093 // // builder = test2("method", builder, builder::method, "foo", // HttpRequest.BodyProcessor.ofString("foo"), // IllegalArgumentException.class); // // builder.build(); method("newBuilder(TEST_URI).build().method() == GET", () -> HttpRequest.newBuilder(TEST_URI), "GET"); method("newBuilder(TEST_URI).GET().build().method() == GET", () -> HttpRequest.newBuilder(TEST_URI).GET(), "GET"); method("newBuilder(TEST_URI).POST(ofString(\"\")).GET().build().method() == GET", () -> HttpRequest.newBuilder(TEST_URI).POST(ofString("")).GET(), "GET"); method("newBuilder(TEST_URI).PUT(ofString(\"\")).GET().build().method() == GET", () -> HttpRequest.newBuilder(TEST_URI).PUT(ofString("")).GET(), "GET"); method("newBuilder(TEST_URI).DELETE().GET().build().method() == GET", () -> HttpRequest.newBuilder(TEST_URI).DELETE().GET(), "GET"); method("newBuilder(TEST_URI).POST(ofString(\"\")).build().method() == POST", () -> HttpRequest.newBuilder(TEST_URI).POST(ofString("")), "POST"); method("newBuilder(TEST_URI).PUT(ofString(\"\")).build().method() == PUT", () -> HttpRequest.newBuilder(TEST_URI).PUT(ofString("")), "PUT"); method("newBuilder(TEST_URI).DELETE().build().method() == DELETE", () -> HttpRequest.newBuilder(TEST_URI).DELETE(), "DELETE"); method("newBuilder(TEST_URI).GET().POST(ofString(\"\")).build().method() == POST", () -> HttpRequest.newBuilder(TEST_URI).GET().POST(ofString("")), "POST"); method("newBuilder(TEST_URI).GET().PUT(ofString(\"\")).build().method() == PUT", () -> HttpRequest.newBuilder(TEST_URI).GET().PUT(ofString("")), "PUT"); method("newBuilder(TEST_URI).GET().DELETE().build().method() == DELETE", () -> HttpRequest.newBuilder(TEST_URI).GET().DELETE(), "DELETE"); method("newBuilder(TEST_URI).HEAD().build().method() == HEAD", () -> HttpRequest.newBuilder(TEST_URI).HEAD(), "HEAD"); // verify that the default HEAD() method implementation in HttpRequest.Builder // interface works as expected HttpRequest defaultHeadReq = new NotOverriddenHEADImpl().HEAD().uri(TEST_URI).build(); assertEquals("HEAD", defaultHeadReq.method(), "Method"); assertEquals(false, defaultHeadReq.bodyPublisher().isEmpty(), "Body publisher absence"); HttpRequest defaultReqWithoutOption = new NotOverriddenHEADImpl().HEAD().uri(TEST_URI).build(); assertEquals(Optional.empty(), defaultReqWithoutOption.getOption(H3_DISCOVERY), "default without options"); HttpRequest defaultReqWithOption = new NotOverriddenHEADImpl().HEAD().uri(TEST_URI) .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY).build(); assertEquals(Optional.empty(), defaultReqWithOption.getOption(H3_DISCOVERY), "default with options"); HttpRequest reqWithoutOption = HttpRequest.newBuilder().HEAD().uri(TEST_URI).build(); assertEquals(Optional.empty(), reqWithoutOption.getOption(H3_DISCOVERY), "req without options"); HttpRequest reqWithOption = HttpRequest.newBuilder().HEAD().uri(TEST_URI) .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY).build(); assertEquals(Optional.of(HTTP_3_URI_ONLY), reqWithOption.getOption(H3_DISCOVERY), "req with options"); HttpRequest resetReqWithOption = HttpRequest.newBuilder().HEAD().uri(TEST_URI) .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY) .setOption(H3_DISCOVERY, null).build(); assertEquals(Optional.empty(), resetReqWithOption.getOption(H3_DISCOVERY), "req with option reset"); verifyCopy(); } private static boolean shouldFail(Class<? extends Exception> ...exceptions) { return exceptions != null && exceptions.length > 0; } private static String expectedNames(Class<? extends Exception> ...exceptions) { return Stream.of(exceptions).map(Class::getSimpleName) .collect(Collectors.joining("|")); } private static boolean isExpected(Exception x, Class<? extends Exception> ...expected) { return expected != null && Stream.of(expected) .filter(c -> c.isInstance(x)) .findAny().isPresent(); } static void method(String name, Supplier<HttpRequest.Builder> supplier, String expectedMethod) { HttpRequest request = supplier.get().build(); String method = request.method(); if (request.method().equals("GET") && request.bodyPublisher().isPresent()) throw new AssertionError("failed: " + name + ". Unexpected body processor for GET: " + request.bodyPublisher().get()); assertEquals(expectedMethod, method, "Method"); } static void test0(String name, Runnable r, Class<? extends Exception> ...ex) { try { r.run(); if (!shouldFail(ex)) { System.out.println("success: " + name); return; } else { throw new AssertionError("Expected " + expectedNames(ex) + " not raised for " + name); } } catch (Exception x) { if (!isExpected(x, ex)) { throw x; } else { System.out.println("success: " + name + " - Got expected exception: " + x); } } } public static <R,P> R test1(String name, R receiver, Function<P, R> m, P arg, Class<? extends Exception> ...ex) { String argMessage = arg == null ? "null" : arg.toString(); if (arg instanceof String[]) { argMessage = Arrays.asList((String[])arg).toString(); } try { R result = m.apply(arg); if (!shouldFail(ex)) { System.out.println("success: " + name + "(" + argMessage + ")"); return result; } else { throw new AssertionError("Expected " + expectedNames(ex) + " not raised for " + name + "(" + argMessage + ")"); } } catch (Exception x) { if (!isExpected(x, ex)) { throw x; } else { System.out.println("success: " + name + "(" + argMessage + ")" + " - Got expected exception: " + x); return receiver; } } } public static <R,P1, P2> R test2(String name, R receiver, BiFunction<P1, P2, R> m, P1 arg1, P2 arg2, Class<? extends Exception> ...ex) { try { R result = m.apply(arg1, arg2); if (!shouldFail(ex)) { System.out.println("success: " + name + "(" + arg1 + ", " + arg2 + ")"); return result; } else { throw new AssertionError("Expected " + expectedNames(ex) + " not raised for " + name + "(" + arg1 +", " + arg2 + ")"); } } catch (Exception x) { if (!isExpected(x, ex)) { throw x; } else { System.out.println("success: " + name + "(" + arg1 + ", " + arg2 + ") - Got expected exception: " + x); return receiver; } } } private static void verifyCopy() { // Create the request builder HttpRequest.Builder requestBuilder = HttpRequest .newBuilder(TEST_URI) .header("X-Foo", "1") .method("GET", noBody()) .expectContinue(true) .timeout(Duration.ofSeconds(0xBEEF)) .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY) .version(HttpClient.Version.HTTP_2); // Create the original and the _copy_ requests HttpRequest request = requestBuilder.build(); HttpRequest copiedRequest = requestBuilder .copy() .header("X-Foo", "2") .header("X-Bar", "3") .build(); // Verify copied _references_ assertEquals(request.uri(), copiedRequest.uri(), "URI"); assertEquals(request.method(), copiedRequest.method(), "Method"); assertEquals(request.expectContinue(), copiedRequest.expectContinue(), "Expect continue setting"); assertEquals(request.timeout(), copiedRequest.timeout(), "Timeout"); assertEquals(request.version(), copiedRequest.version(), "Version"); assertEquals(request.getOption(H3_DISCOVERY), copiedRequest.getOption(H3_DISCOVERY), "H3_DISCOVERY option"); assertEquals(Optional.of(HTTP_3_URI_ONLY), copiedRequest.getOption(H3_DISCOVERY), "copied H3_DISCOVERY option"); // Verify headers assertEquals(request.headers().map(), Map.of("X-Foo", List.of("1")), "Request headers"); assertEquals(copiedRequest.headers().map(), Map.of("X-Foo", List.of("1", "2"), "X-Bar", List.of("3")), "Copied request headers"); } private static void assertEquals(Object expected, Object actual, Object name) { if (!Objects.equals(expected, actual)) { String message = String.format("%s mismatch!%nExpected: %s%nActual: %s", name, expected, actual); throw new AssertionError(message); } } // doesn't override the default HEAD() method private static final class NotOverriddenHEADImpl implements HttpRequest.Builder { private final HttpRequest.Builder underlying; NotOverriddenHEADImpl() { this(HttpRequest.newBuilder()); } NotOverriddenHEADImpl(HttpRequest.Builder underlying) { this.underlying = underlying; } @Override public HttpRequest.Builder uri(URI uri) { underlying.uri(uri); return this; } @Override public HttpRequest.Builder expectContinue(boolean enable) { underlying.expectContinue(enable); return this; } @Override public HttpRequest.Builder version(HttpClient.Version version) { this.underlying.version(version); return this; } @Override public HttpRequest.Builder header(String name, String value) { this.underlying.header(name, value); return this; } @Override public HttpRequest.Builder headers(String... headers) { underlying.headers(headers); return this; } @Override public HttpRequest.Builder timeout(Duration duration) { this.underlying.timeout(duration); return this; } @Override public HttpRequest.Builder setHeader(String name, String value) { underlying.setHeader(name, value); return this; } @Override public HttpRequest.Builder GET() { this.underlying.GET(); return this; } @Override public HttpRequest.Builder POST(HttpRequest.BodyPublisher bodyPublisher) { this.underlying.POST(bodyPublisher); return this; } @Override public HttpRequest.Builder PUT(HttpRequest.BodyPublisher bodyPublisher) { this.underlying.PUT(bodyPublisher); return this; } @Override public HttpRequest.Builder DELETE() { this.underlying.DELETE(); return this; } @Override public HttpRequest.Builder method(String method, HttpRequest.BodyPublisher bodyPublisher) { this.underlying.method(method, bodyPublisher); return this; } @Override public HttpRequest build() { return this.underlying.build(); } @Override public HttpRequest.Builder copy() { return new NotOverriddenHEADImpl(underlying.copy()); } } }