diff --git a/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java b/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java index ddd9c52fc58..1e8bc461d7f 100644 --- a/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java +++ b/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -22,7 +22,7 @@ */ -/** +/* * This is not a test. Actual tests are implemented by concrete subclasses. * The abstract class AbstractThrowingPushPromises provides a base framework * to test what happens when push promise handlers and their @@ -62,7 +62,6 @@ import java.net.http.HttpResponse.BodySubscriber; import java.net.http.HttpResponse.PushPromiseHandler; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -104,7 +103,6 @@ import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestWatcher; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) public abstract class AbstractThrowingPushPromises implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); @@ -193,14 +191,9 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters @AfterAll - static final void printFailedTests() { + static void printFailedTests() { out.println("\n========================="); try { - // Exceptions should already have been added to FAILURES - // var failed = context.getFailedTests().getAllResults().stream() - // .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - // FAILURES.putAll(failed); - out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); if (FAILURES.isEmpty()) return; @@ -339,7 +332,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters HttpRequest req = request(uri); BodyHandler> handler = - new ThrowingBodyHandler((w) -> {}, + new ThrowingBodyHandler<>((w) -> {}, BodyHandlers.ofLines()); Map>>> pushPromises = new ConcurrentHashMap<>(); @@ -387,9 +380,9 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters } // @Test(dataProvider = "variants") - protected void testThrowingAsStringImpl(String uri, - boolean sameClient, - Thrower thrower) + void testThrowingAsStringImpl(String uri, + boolean sameClient, + Thrower thrower) throws Exception { String test = format("testThrowingAsString(%s, %b, %s)", @@ -399,7 +392,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters } //@Test(dataProvider = "variants") - protected void testThrowingAsLinesImpl(String uri, + void testThrowingAsLinesImpl(String uri, boolean sameClient, Thrower thrower) throws Exception @@ -411,9 +404,9 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters } //@Test(dataProvider = "variants") - protected void testThrowingAsInputStreamImpl(String uri, - boolean sameClient, - Thrower thrower) + void testThrowingAsInputStreamImpl(String uri, + boolean sameClient, + Thrower thrower) throws Exception { String test = format("testThrowingAsInputStream(%s, %b, %s)", @@ -424,7 +417,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters private void testThrowing(String name, String uri, boolean sameClient, Supplier> handlers, - Finisher finisher, Thrower thrower) + Finisher finisher, Thrower thrower) throws Exception { out.printf("%n%s%s%n", now(), name); @@ -438,7 +431,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters private void testThrowing(String uri, boolean sameClient, Supplier> handlers, - Finisher finisher, Thrower thrower) + Finisher finisher, Thrower thrower) throws Exception { HttpClient client = null; @@ -452,7 +445,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters ConcurrentMap>> promiseMap = new ConcurrentHashMap<>(); Supplier> throwing = () -> - new ThrowingBodyHandler(where.select(thrower), handlers.get()); + new ThrowingBodyHandler<>(where.select(thrower), handlers.get()); PushPromiseHandler pushHandler = new ThrowingPromiseHandler<>( where.select(thrower), PushPromiseHandler.of((r) -> throwing.get(), promiseMap)); @@ -540,7 +533,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters return check(w, reqURI, resp, thrower, promises, extractor); } - private final List check(Where w, URI reqURI, + private List check(Where w, URI reqURI, HttpResponse resp, Thrower thrower, Map>> promises, @@ -697,7 +690,7 @@ public abstract class AbstractThrowingPushPromises implements HttpServerAdapters public BodySubscriber apply(HttpResponse.ResponseInfo rinfo) { throwing.accept(Where.BODY_HANDLER); BodySubscriber subscriber = bodyHandler.apply(rinfo); - return new ThrowingBodySubscriber(throwing, subscriber); + return new ThrowingBodySubscriber<>(throwing, subscriber); } } diff --git a/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java b/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java index 608b6489181..175e860c229 100644 --- a/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java +++ b/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,7 +27,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.HttpServerAdapters * ReferenceTracker AggregateRequestBodyTest - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors,headers,frames * AggregateRequestBodyTest * @summary Tests HttpRequest.BodyPublishers::concat @@ -41,7 +41,6 @@ import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -70,40 +69,43 @@ import javax.net.ssl.SSLContext; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import org.testng.Assert; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class AggregateRequestBodyTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer http1TestServer; // HTTP/1.1 ( http ) - HttpTestServer https1TestServer; // HTTPS/1.1 ( https ) - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - URI http1URI; - URI https1URI; - URI http2URI; - URI https2URI; - URI http3URI; + private static HttpTestServer http1TestServer; // HTTP/1.1 ( http ) + private static HttpTestServer https1TestServer; // HTTPS/1.1 ( https ) + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static URI http1URI; + private static URI https1URI; + private static URI http2URI; + private static URI https2URI; + private static URI http3URI; static final int RESPONSE_CODE = 200; static final int ITERATION_COUNT = 4; @@ -123,8 +125,8 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -150,40 +152,40 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static void printFailedTests() { out.println("\n========================="); try { - var failed = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - FAILURES.putAll(failed); - out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); if (FAILURES.isEmpty()) return; @@ -201,7 +203,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { } } - private URI[] uris() { + private static URI[] uris() { return new URI[] { http1URI, https1URI, @@ -211,13 +213,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { }; } - static AtomicLong URICOUNT = new AtomicLong(); - - @DataProvider(name = "variants") - public Object[][] variants(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - return new Object[0][]; - } + public static Object[][] variants() { URI[] uris = uris(); Object[][] result = new Object[uris.length * 2][]; int i = 0; @@ -285,8 +281,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { return s; } - @DataProvider(name = "sparseContent") - Object[][] nulls() { + static Object[][] nulls() { return new Object[][] { {"null array", null}, {"null element", strings((String)null)}, @@ -304,8 +299,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { .collect(Collectors.toList()); } - @DataProvider(name = "contentLengths") - Object[][] contentLengths() { + static Object[][] contentLengths() { return new Object[][] { {-1, lengths(-1)}, {-42, lengths(-42)}, @@ -332,8 +326,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { }; } - @DataProvider(name="negativeRequests") - Object[][] negativeRequests() { + static Object[][] negativeRequests() { return new Object[][] { {0L}, {-1L}, {-2L}, {Long.MIN_VALUE + 1L}, {Long.MIN_VALUE} }; @@ -492,31 +485,33 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { () -> new AssertionError("Should not happen!")); } - @Test(dataProvider = "sparseContent") // checks that NPE is thrown + @ParameterizedTest // checks that NPE is thrown + @MethodSource("nulls") public void testNullPointerException(String description, String[] content) { - checkSkip(); + out.printf("%n%s-- testNullPointerException %s%n%n", now(), description); BodyPublisher[] publishers = publishers(content); - Assert.assertThrows(NullPointerException.class, () -> BodyPublishers.concat(publishers)); + Assertions.assertThrows(NullPointerException.class, () -> BodyPublishers.concat(publishers)); } // Verifies that an empty array creates a "noBody" publisher @Test public void testEmpty() { - checkSkip(); + out.printf("%n%s-- testEmpty%n%n", now()); BodyPublisher publisher = BodyPublishers.concat(); RequestSubscriber subscriber = new RequestSubscriber(); - assertEquals(publisher.contentLength(), 0); + assertEquals(0, publisher.contentLength()); publisher.subscribe(subscriber); subscriber.subscriptionCF.thenAccept(s -> s.request(1)); List result = subscriber.resultCF.join(); - assertEquals(result, List.of()); + assertEquals(List.of(), result); assertTrue(subscriber.items.isEmpty()); } // verifies that error emitted by upstream publishers are propagated downstream. - @Test(dataProvider = "sparseContent") // nulls are replaced with error publisher + @ParameterizedTest // nulls are replaced with error publisher + @MethodSource("nulls") public void testOnError(String description, String[] content) { - checkSkip(); + out.printf("%n%s-- testOnError %s%n%n", now(), description); final RequestSubscriber subscriber = new RequestSubscriber(); final PublishWithError errorPublisher; final BodyPublisher[] publishers; @@ -556,13 +551,13 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { publisher.subscribe(subscriber); subscriber.subscriptionCF.thenAccept(s -> s.request(Long.MAX_VALUE)); if (errorPublisher.hasErrors()) { - CompletionException ce = expectThrows(CompletionException.class, + CompletionException ce = Assertions.assertThrows(CompletionException.class, () -> subscriber.resultCF.join()); out.println(description + ": got expected " + ce); - assertEquals(ce.getCause().getClass(), Exception.class); - assertEquals(stringFromBytes(subscriber.items.stream()) + "", result); + assertEquals(Exception.class, ce.getCause().getClass()); + assertEquals(result, stringFromBytes(subscriber.items.stream()) + ""); } else { - assertEquals(stringFromBytes(subscriber.resultCF.join().stream()), result); + assertEquals(result, stringFromBytes(subscriber.resultCF.join().stream())); out.println(description + ": got expected result: " + result); } } @@ -570,9 +565,10 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { // Verifies that if an upstream publisher has an unknown length, the // aggregate publisher will have an unknown length as well. Otherwise // the length should be known. - @Test(dataProvider = "sparseContent") // nulls are replaced with unknown length + @ParameterizedTest // nulls are replaced with unknown length + @MethodSource("nulls") public void testUnknownContentLength(String description, String[] content) { - checkSkip(); + out.printf("%n%s-- testUnknownContentLength %s%n%n", now(), description); if (content == null) { content = BODIES.toArray(String[]::new); description = "BODIES (known length)"; @@ -598,9 +594,9 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { length += content[i].length(); } } - out.printf("testUnknownContentLength(%s): %d%n", description, length); + out.printf("%stestUnknownContentLength(%s): %d%n", now(), description, length); BodyPublisher publisher = BodyPublishers.concat(publishers); - assertEquals(publisher.contentLength(), length, + assertEquals(length, publisher.contentLength(), description.replace("null", "length(-1)")); } @@ -611,9 +607,10 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { return x.getCause(); } - @Test(dataProvider = "negativeRequests") + @ParameterizedTest + @MethodSource("negativeRequests") public void testNegativeRequest(long n) { - checkSkip(); + out.printf("%n%s-- testNegativeRequest %s%n%n", now(), n); assert n <= 0 : "test for negative request called with n > 0 : " + n; BodyPublisher[] publishers = ContentLengthPublisher.of(List.of(1L, 2L, 3L)); BodyPublisher publisher = BodyPublishers.concat(publishers); @@ -621,7 +618,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { publisher.subscribe(subscriber); Subscription subscription = subscriber.subscriptionCF.join(); subscription.request(n); - CompletionException expected = expectThrows(CE, () -> subscriber.resultCF.join()); + CompletionException expected = Assertions.assertThrows(CE, () -> subscriber.resultCF.join()); Throwable cause = completionCause(expected); if (cause instanceof IllegalArgumentException) { System.out.printf("Got expected IAE for %d: %s%n", n, cause); @@ -637,7 +634,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { @Test public void testPositiveRequests() { - checkSkip(); + out.printf("%n%s-- testPositiveRequests%n%n", now()); // A composite array of publishers BodyPublisher[] publishers = Stream.of( Stream.of(ofStrings("Lorem", " ", "ipsum", " ")), @@ -657,7 +654,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { List list1 = requestSubscriber1.resultCF().join(); assertTrue(requestSubscriber1.resultCF().isDone()); String result1 = stringFromBytes(list1.stream()); - assertEquals(result1, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."); + assertEquals("Lorem ipsum dolor sit amet, consectetur adipiscing elit.", result1); System.out.println("Got expected sentence with one request: \"%s\"".formatted(result1)); // Test that we can split our requests call any which way we want @@ -675,16 +672,17 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { List list2 = requestSubscriber2.resultCF().join(); assertTrue(requestSubscriber2.resultCF().isDone()); String result2 = stringFromBytes(list2.stream()); - assertEquals(result2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."); + assertEquals("Lorem ipsum dolor sit amet, consectetur adipiscing elit.", result2); System.out.println("Got expected sentence with 4 requests: \"%s\"".formatted(result1)); } - @Test(dataProvider = "contentLengths") + @ParameterizedTest + @MethodSource("contentLengths") public void testContentLength(long expected, List lengths) { - checkSkip(); + out.printf("%n%s-- testContentLength expected=%s %s%n%n", now(), expected, lengths); BodyPublisher[] publishers = ContentLengthPublisher.of(lengths); BodyPublisher aggregate = BodyPublishers.concat(publishers); - assertEquals(aggregate.contentLength(), expected, + assertEquals(expected, aggregate.contentLength(), "Unexpected result for %s".formatted(lengths)); } @@ -692,14 +690,13 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { // publishers are no longer subscribed etc... @Test public void testCancel() { - checkSkip(); + out.printf("%n%s-- testCancel%n%n", now()); BodyPublisher[] publishers = BODIES.stream() .map(BodyPublishers::ofString) .toArray(BodyPublisher[]::new); BodyPublisher publisher = BodyPublishers.concat(publishers); - assertEquals(publisher.contentLength(), - BODIES.stream().mapToInt(String::length).sum()); + assertEquals(BODIES.stream().mapToInt(String::length).sum(), publisher.contentLength()); Map subscribers = new LinkedHashMap<>(); for (int n=0; n < BODIES.size(); n++) { @@ -731,7 +728,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { // subscription was cancelled, so nothing should be received... try { - TimeoutException x = Assert.expectThrows(TimeoutException.class, + TimeoutException x = Assertions.assertThrows(TimeoutException.class, () -> any.get(5, TimeUnit.SECONDS)); out.println("Got expected " + x); } finally { @@ -742,8 +739,8 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { subscribers.get(rs), rs.resultCF)); } Consumer check = (rs) -> { - Assert.assertTrue(rs.items.isEmpty(), subscribers.get(rs) + " has items"); - Assert.assertFalse(rs.resultCF.isDone(), subscribers.get(rs) + " was not cancelled"); + assertTrue(rs.items.isEmpty(), subscribers.get(rs) + " has items"); + assertFalse(rs.resultCF.isDone(), subscribers.get(rs) + " was not cancelled"); out.println(subscribers.get(rs) + ": PASSED"); }; subscribers.keySet().stream().forEach(check); @@ -752,13 +749,12 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { // Verifies that cancelling the subscription is propagated downstream @Test public void testCancelSubscription() { - checkSkip(); + out.printf("%n%s-- testCancelSubscription%n%n", now()); PublishWithError upstream = new PublishWithError(BODIES, BODIES.size(), () -> new AssertionError("should not come here")); BodyPublisher publisher = BodyPublishers.concat(upstream); - assertEquals(publisher.contentLength(), - BODIES.stream().mapToInt(String::length).sum()); + assertEquals(BODIES.stream().mapToInt(String::length).sum(), publisher.contentLength()); Map subscribers = new LinkedHashMap<>(); for (int n=0; n < BODIES.size(); n++) { @@ -793,7 +789,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { // subscription was cancelled, so nothing should be received... try { - TimeoutException x = Assert.expectThrows(TimeoutException.class, + TimeoutException x = Assertions.assertThrows(TimeoutException.class, () -> any.get(5, TimeUnit.SECONDS)); out.println("Got expected " + x); } finally { @@ -804,17 +800,19 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { subscribers.get(rs), rs.resultCF)); } Consumer check = (rs) -> { - Assert.assertTrue(rs.items.isEmpty(), subscribers.get(rs) + " has items"); - Assert.assertFalse(rs.resultCF.isDone(), subscribers.get(rs) + " was not cancelled"); + assertTrue(rs.items.isEmpty(), subscribers.get(rs) + " has items"); + assertFalse(rs.resultCF.isDone(), subscribers.get(rs) + " was not cancelled"); out.println(subscribers.get(rs) + ": PASSED"); }; subscribers.keySet().stream().forEach(check); } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void test(URI uri, HttpClient.Version version, boolean sameClient) throws Exception { - checkSkip(); + out.printf("%n%s-- test sameClient=%s, version=%s, uri=%s%n%n", + now(), sameClient, version, uri); System.out.printf("Request to %s (sameClient: %s)%n", uri, sameClient); System.err.printf("Request to %s (sameClient: %s)%n", uri, sameClient); @@ -838,13 +836,13 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { int expectedResponse = RESPONSE_CODE; if (response.statusCode() != expectedResponse) throw new RuntimeException("wrong response code " + Integer.toString(response.statusCode())); - assertEquals(response.body(), BODIES.stream().collect(Collectors.joining())); + assertEquals(BODIES.stream().collect(Collectors.joining()), response.body()); } if (!sameClient) client.close(); System.out.println("test: DONE"); } - private URI buildURI(String scheme, String path, int port) { + private static URI buildURI(String scheme, String path, int port) { return URIBuilder.newBuilder() .scheme(scheme) .loopback() @@ -853,8 +851,8 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { .buildUnchecked(); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { HttpTestHandler handler = new HttpTestEchoHandler(); http1TestServer = HttpTestServer.create(HTTP_1_1); http1TestServer.addHandler(handler, "/http1/echo/"); @@ -884,8 +882,8 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { String sharedClientName = sharedClient == null ? null : sharedClient.toString(); sharedClient.close(); diff --git a/test/jdk/java/net/httpclient/BasicHTTP2Test.java b/test/jdk/java/net/httpclient/BasicHTTP2Test.java index 586673d62ab..4175aceea3d 100644 --- a/test/jdk/java/net/httpclient/BasicHTTP2Test.java +++ b/test/jdk/java/net/httpclient/BasicHTTP2Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,7 +27,7 @@ * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * ReferenceTracker - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * BasicHTTP2Test * @summary Basic HTTP/2 test when HTTP/3 is requested @@ -44,37 +44,40 @@ import java.net.http.HttpRequest; import java.net.http.HttpRequest.Builder; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import java.time.Duration; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import javax.net.ssl.SSLContext; import jdk.test.lib.net.SimpleSSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; -import org.testng.ITestContext; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; public class BasicHTTP2Test implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - String https2URI; - DatagramSocket udp; + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static String https2URI; + private static DatagramSocket udp; // a shared executor helps reduce the amount of threads created by the test static final Executor executor = new TestExecutor(Executors.newCachedThreadPool()); @@ -91,8 +94,7 @@ public class BasicHTTP2Test implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -118,20 +120,37 @@ public class BasicHTTP2Test implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - var x = new SkipException("Skipping: some test failed"); - x.setStackTrace(new StackTraceElement[0]); - throw x; + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + } + } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); } } - @AfterClass + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll static final void printFailedTests() { out.println("\n========================="); try { @@ -152,14 +171,6 @@ public class BasicHTTP2Test implements HttpServerAdapters { } } - private String[] uris() { - return new String[] { - https2URI, - }; - } - - static AtomicLong URICOUNT = new AtomicLong(); - private HttpClient makeNewClient() { clientCount.incrementAndGet(); HttpClient client = HttpClient.newBuilder() @@ -170,37 +181,6 @@ public class BasicHTTP2Test implements HttpServerAdapters { return TRACKER.track(client); } - HttpClient newHttpClient(boolean share) { - if (!share) return makeNewClient(); - HttpClient shared = sharedClient; - if (shared != null) return shared; - synchronized (this) { - shared = sharedClient; - if (shared == null) { - shared = sharedClient = makeNewClient(); - } - return shared; - } - } - - - static void checkStatus(int expected, int found) throws Exception { - if (expected != found) { - System.err.printf ("Test failed: wrong status code %d/%d\n", - expected, found); - throw new RuntimeException("Test failed"); - } - } - - static void checkStrings(String expected, String found) throws Exception { - if (!expected.equals(found)) { - System.err.printf ("Test failed: wrong string %s/%s\n", - expected, found); - throw new RuntimeException("Test failed"); - } - } - - @Test public void testH2() throws Exception { @@ -220,8 +200,8 @@ public class BasicHTTP2Test implements HttpServerAdapters { HttpResponse response = client.send(request, BodyHandlers.ofString()); out.println("Response #1: " + response); out.println("Version #1: " + response.version()); - assertEquals(response.statusCode(), 200, "first response status"); - assertEquals(response.version(), HTTP_2, "first response version"); + assertEquals(200, response.statusCode(), "first response status"); + assertEquals(HTTP_2, response.version(), "first response version"); Thread.sleep(1000); @@ -232,16 +212,15 @@ public class BasicHTTP2Test implements HttpServerAdapters { response = client.send(request, BodyHandlers.ofString()); out.println("Response #2: " + response); out.println("Version #2: " + response.version()); - assertEquals(response.statusCode(), 200, "second response status"); - assertEquals(response.version(), HTTP_2, "second response version"); + assertEquals(200, response.statusCode(), "second response status"); + assertEquals(HTTP_2, response.version(), "second response version"); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { // HTTP/2 HttpTestHandler handler = new Handler(); - HttpTestHandler h3Handler = new Handler(); https2TestServer = HttpTestServer.create(HTTP_2, sslContext); https2TestServer.addHandler(handler, "/https2/test204/"); @@ -259,11 +238,8 @@ public class BasicHTTP2Test implements HttpServerAdapters { https2TestServer.start(); } - @AfterTest - public void teardown() throws Exception { - String sharedClientName = - sharedClient == null ? null : sharedClient.toString(); - sharedClient = null; + @AfterAll + public static void teardown() throws Exception { Thread.sleep(100); AssertionError fail = TRACKER.check(500); try { @@ -271,10 +247,7 @@ public class BasicHTTP2Test implements HttpServerAdapters { https2TestServer.stop(); } finally { if (fail != null) { - if (sharedClientName != null) { - System.err.println("Shared client name is: " + sharedClientName); - } - throw fail; + throw fail; } } } diff --git a/test/jdk/java/net/httpclient/BasicHTTP3Test.java b/test/jdk/java/net/httpclient/BasicHTTP3Test.java index 4508b32e544..aec21e421f9 100644 --- a/test/jdk/java/net/httpclient/BasicHTTP3Test.java +++ b/test/jdk/java/net/httpclient/BasicHTTP3Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -31,7 +31,6 @@ import java.net.http.HttpRequest; import java.net.http.HttpRequest.Builder; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import java.time.Duration; import java.util.List; import java.util.Optional; import java.util.Set; @@ -40,28 +39,32 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.internal.net.quic.QuicVersion; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; import static java.lang.System.out; import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /* * @test @@ -70,7 +73,7 @@ import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; * jdk.httpclient.test.lib.common.HttpServerAdapters * ReferenceTracker * jdk.httpclient.test.lib.quic.QuicStandaloneServer - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * -Djavax.net.debug=all * BasicHTTP3Test @@ -79,20 +82,20 @@ import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; public class BasicHTTP3Test implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - String https2URI; - HttpTestServer h3TestServer; // HTTP/2 ( h2 + h3) - String h3URI; - HttpTestServer h3qv2TestServer; // HTTP/2 ( h2 + h3 on Quic v2, incompatible nego) - String h3URIQv2; - HttpTestServer h3qv2CTestServer; // HTTP/2 ( h2 + h3 on Quic v2, compatible nego) - String h3URIQv2C; - HttpTestServer h3mtlsTestServer; // HTTP/2 ( h2 + h3), h3 requires client cert - String h3mtlsURI; - HttpTestServer h3TestServerWithRetry; // h3 - String h3URIRetry; - HttpTestServer h3TestServerWithTLSHelloRetry; // h3 - String h3URITLSHelloRetry; + static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + static String https2URI; + static HttpTestServer h3TestServer; // HTTP/2 ( h2 + h3) + static String h3URI; + static HttpTestServer h3qv2TestServer; // HTTP/2 ( h2 + h3 on Quic v2, incompatible nego) + static String h3URIQv2; + static HttpTestServer h3qv2CTestServer; // HTTP/2 ( h2 + h3 on Quic v2, compatible nego) + static String h3URIQv2C; + static HttpTestServer h3mtlsTestServer; // HTTP/2 ( h2 + h3), h3 requires client cert + static String h3mtlsURI; + static HttpTestServer h3TestServerWithRetry; // h3 + static String h3URIRetry; + static HttpTestServer h3TestServerWithTLSHelloRetry; // h3 + static String h3URITLSHelloRetry; static final int ITERATION_COUNT = 4; // a shared executor helps reduce the amount of threads created by the test @@ -109,8 +112,8 @@ public class BasicHTTP3Test implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -136,21 +139,38 @@ public class BasicHTTP3Test implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - var x = new SkipException("Skipping: some test failed"); - x.setStackTrace(new StackTraceElement[0]); - throw x; + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + } + } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); } } - @AfterClass - static final void printFailedTests() { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static void printFailedTests() { out.println("\n========================="); try { out.printf("%n%sCreated %d clients%n", @@ -170,18 +190,14 @@ public class BasicHTTP3Test implements HttpServerAdapters { } } - private String[] uris() { + private static String[] uris() { return new String[] { https2URI, h3URI }; } - @DataProvider(name = "variants") - public Object[][] variants(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - return new Object[0][]; - } + public static Object[][] variants() { String[] uris = uris(); Object[][] result = new Object[uris.length * 2 * 2][]; int i = 0; @@ -196,11 +212,7 @@ public class BasicHTTP3Test implements HttpServerAdapters { return result; } - @DataProvider(name = "h3URIs") - public Object[][] versions(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - return new Object[0][]; - } + public static Object[][] versions() { Object[][] result = { {h3URI}, {h3URIRetry}, {h3URIQv2}, {h3URIQv2C}, @@ -233,9 +245,11 @@ public class BasicHTTP3Test implements HttpServerAdapters { } } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void test(String uri, boolean sameClient, Optional version) throws Exception { - System.out.println("Request to " + uri); + System.out.printf("%n%s-- test version=%s, sameClient=%s, uri=%s%n%n", + now(), version, sameClient, uri); HttpClient client = newHttpClient(sameClient); @@ -267,8 +281,10 @@ public class BasicHTTP3Test implements HttpServerAdapters { System.out.println("test: DONE"); } - @Test(dataProvider = "h3URIs") + @ParameterizedTest + @MethodSource("versions") public void testH3(final String h3URI) throws Exception { + System.out.printf("%n%s-- testH3 h3URI=%s%n%n", now(), h3URI); HttpClient client = makeNewClient(); URI uri = URI.create(h3URI); Builder builder = HttpRequest.newBuilder(uri) @@ -278,17 +294,17 @@ public class BasicHTTP3Test implements HttpServerAdapters { HttpResponse response = client.send(request, BodyHandlers.ofString()); out.println("Response #1: " + response); out.println("Version #1: " + response.version()); - assertEquals(response.statusCode(), 200, "first response status"); - assertEquals(response.version(), HTTP_2, "first response version"); + assertEquals(200, response.statusCode(), "first response status"); + assertEquals(HTTP_2, response.version(), "first response version"); request = builder.version(Version.HTTP_3).build(); response = client.send(request, BodyHandlers.ofString()); out.println("Response #2: " + response); out.println("Version #2: " + response.version()); - assertEquals(response.statusCode(), 200, "second response status"); - assertEquals(response.version(), Version.HTTP_3, "second response version"); + assertEquals(200, response.statusCode(), "second response status"); + assertEquals(Version.HTTP_3, response.version(), "second response version"); - if (h3URI == h3mtlsURI) { + if (h3URI.equals(h3mtlsURI)) { assertNotNull(response.sslSession().get().getLocalCertificates()); } else { assertNull(response.sslSession().get().getLocalCertificates()); @@ -303,6 +319,7 @@ public class BasicHTTP3Test implements HttpServerAdapters { // verify that the client handles HTTP/3 reset stream correctly @Test public void testH3Reset() throws Exception { + System.out.printf("%n%s-- testH3Reset uri=%s%n%n", now(), h3URI); HttpClient client = makeNewClient(); URI uri = URI.create(h3URI); Builder builder = HttpRequest.newBuilder(uri) @@ -312,8 +329,8 @@ public class BasicHTTP3Test implements HttpServerAdapters { HttpResponse response = client.send(request, BodyHandlers.ofString()); out.println("Response #1: " + response); out.println("Version #1: " + response.version()); - assertEquals(response.statusCode(), 200, "first response status"); - assertEquals(response.version(), HTTP_2, "first response version"); + assertEquals(200, response.statusCode(), "first response status"); + assertEquals(HTTP_2, response.version(), "first response version"); // instruct the server side handler to throw an exception // that then causes the test server to reset the stream @@ -341,8 +358,8 @@ public class BasicHTTP3Test implements HttpServerAdapters { if (error != null) throw error; } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { https2TestServer = HttpTestServer.create(HTTP_2, sslContext); https2TestServer.addHandler(new Handler(), "/https2/test/"); https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/test/x"; @@ -360,7 +377,7 @@ public class BasicHTTP3Test implements HttpServerAdapters { .enableH3AltServiceOnEphemeralPortWithVersion(QuicVersion.QUIC_V2, false); h3qv2TestServer = HttpTestServer.of(h2q2Server); h3qv2TestServer.addHandler(h3Handler, "/h3/testH3/"); - h3URIQv2 = "https://" + h3qv2TestServer.serverAuthority() + "/h3/testH3/h3qv2";; + h3URIQv2 = "https://" + h3qv2TestServer.serverAuthority() + "/h3/testH3/h3qv2"; assertTrue(h3qv2TestServer.canHandle(HTTP_2, Version.HTTP_3), "Server was expected" + " to handle both HTTP2 and HTTP3, but doesn't"); @@ -369,7 +386,7 @@ public class BasicHTTP3Test implements HttpServerAdapters { .enableH3AltServiceOnEphemeralPortWithVersion(QuicVersion.QUIC_V2, true); h3qv2CTestServer = HttpTestServer.of(h2q2CServer); h3qv2CTestServer.addHandler(h3Handler, "/h3/testH3/"); - h3URIQv2C = "https://" + h3qv2CTestServer.serverAuthority() + "/h3/testH3/h3qv2c";; + h3URIQv2C = "https://" + h3qv2CTestServer.serverAuthority() + "/h3/testH3/h3qv2c"; assertTrue(h3qv2CTestServer.canHandle(HTTP_2, Version.HTTP_3), "Server was expected" + " to handle both HTTP2 and HTTP3, but doesn't"); @@ -411,8 +428,8 @@ public class BasicHTTP3Test implements HttpServerAdapters { h3TestServerWithTLSHelloRetry.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { System.err.println("======================================================="); System.err.println(" Tearing down test"); System.err.println("======================================================="); diff --git a/test/jdk/java/net/httpclient/CancelRequestTest.java b/test/jdk/java/net/httpclient/CancelRequestTest.java index 2a0ec19a0ed..df808ad2dab 100644 --- a/test/jdk/java/net/httpclient/CancelRequestTest.java +++ b/test/jdk/java/net/httpclient/CancelRequestTest.java @@ -29,7 +29,7 @@ * @key randomness * @build jdk.httpclient.test.lib.common.HttpServerAdapters jdk.test.lib.net.SimpleSSLContext * ReferenceTracker CancelRequestTest - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.enableAllMethodRetry=true * CancelRequestTest */ @@ -38,15 +38,6 @@ import jdk.internal.net.http.common.OperationTrackers.Tracker; import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -61,7 +52,6 @@ import java.net.http.HttpOption.Http3DiscoveryMode; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandler; import java.net.http.HttpResponse.BodyHandlers; -import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -76,7 +66,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import jdk.httpclient.test.lib.common.HttpServerAdapters; import static java.lang.System.out; @@ -85,10 +74,21 @@ import static java.net.http.HttpClient.Version.*; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class CancelRequestTest implements HttpServerAdapters { @@ -97,19 +97,19 @@ public class CancelRequestTest implements HttpServerAdapters { = new ConcurrentHashMap<>(); private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer h2h3TestServer; // HTTP/3 ( h2 + h3 ) - HttpTestServer h3TestServer; // HTTP/3 ( h3 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String h2h3URI; - String h2h3Head; - String h3URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer h2h3TestServer; // HTTP/3 ( h2 + h3 ) + private static HttpTestServer h3TestServer; // HTTP/3 ( h3 ) + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String h2h3URI; + private static String h2h3Head; + private static String h3URI; static final long SERVER_LATENCY = 75; static final int MAX_CLIENT_DELAY = 75; @@ -130,8 +130,8 @@ public class CancelRequestTest implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -157,38 +157,39 @@ public class CancelRequestTest implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static void printFailedTests() { out.println("\n========================="); - var failed = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(CancelRequestTest::name, ITestResult::getThrowable)); - FAILURES.putAll(failed); try { out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); @@ -206,7 +207,7 @@ public class CancelRequestTest implements HttpServerAdapters { } } - private String[] uris() { + private static String[] uris() { return new String[] { httpURI, httpsURI, @@ -217,8 +218,7 @@ public class CancelRequestTest implements HttpServerAdapters { }; } - @DataProvider(name = "asyncurls") - public Object[][] asyncurls() { + public static Object[][] asyncurls() { String[] uris = uris(); Object[][] result = new Object[uris.length * 2 * 3][]; //Object[][] result = new Object[uris.length][]; @@ -238,8 +238,7 @@ public class CancelRequestTest implements HttpServerAdapters { return result; } - @DataProvider(name = "urls") - public Object[][] alltests() { + public static Object[][] alltests() { String[] uris = uris(); Object[][] result = new Object[uris.length * 2][]; //Object[][] result = new Object[uris.length][]; @@ -327,7 +326,7 @@ public class CancelRequestTest implements HttpServerAdapters { .HEAD() .build(); var resp = client.send(request, BodyHandlers.discarding()); - assertEquals(resp.statusCode(), 200); + assertEquals(200, resp.statusCode()); } private static void releaseLatches() { @@ -348,10 +347,10 @@ public class CancelRequestTest implements HttpServerAdapters { return latch; } - @Test(dataProvider = "asyncurls") + @ParameterizedTest + @MethodSource("asyncurls") public void testGetSendAsync(String uri, boolean sameClient, boolean mayInterruptIfRunning) throws Exception { - checkSkip(); HttpClient client = null; uri = uri + "/get"; out.printf("%n%s testGetSendAsync(%s, %b, %b)%n", now(), uri, sameClient, mayInterruptIfRunning); @@ -386,7 +385,7 @@ public class CancelRequestTest implements HttpServerAdapters { out.println("cf2 after cancel: " + cf2); try { String body = cf2.get().body(); - assertEquals(body, String.join("", BODY.split("\\|"))); + assertEquals(String.join("", BODY.split("\\|")), body); throw new AssertionError("Expected CancellationException not received"); } catch (ExecutionException x) { out.println(now() + "Got expected exception: " + x); @@ -409,7 +408,7 @@ public class CancelRequestTest implements HttpServerAdapters { // completed yet - so wait for it here... try { String body = response.get().body(); - assertEquals(body, String.join("", BODY.split("\\|"))); + assertEquals(String.join("", BODY.split("\\|")), body); if (mayInterruptIfRunning) { // well actually - this could happen... In which case we'll need to // increase the latency in the server handler... @@ -448,10 +447,10 @@ public class CancelRequestTest implements HttpServerAdapters { assertTrue(response.isDone()); assertFalse(response.isCancelled()); - assertEquals(cf1.isCancelled(), hasCancellationException); + assertEquals(hasCancellationException, cf1.isCancelled()); assertTrue(cf2.isDone()); assertFalse(cf2.isCancelled()); - assertEquals(latch.getCount(), 0); + assertEquals(0, latch.getCount()); var error = TRACKER.check(tracker, 1000, (t) -> t.getOutstandingOperations() > 0 || t.getOutstandingSubscribers() > 0, @@ -464,10 +463,10 @@ public class CancelRequestTest implements HttpServerAdapters { if (!sameClient) client.close(); } - @Test(dataProvider = "asyncurls") + @ParameterizedTest + @MethodSource("asyncurls") public void testPostSendAsync(String uri, boolean sameClient, boolean mayInterruptIfRunning) throws Exception { - checkSkip(); uri = uri + "/post"; HttpClient client = null; out.printf("%n%s testPostSendAsync(%s, %b, %b)%n", now(), uri, sameClient, mayInterruptIfRunning); @@ -521,7 +520,7 @@ public class CancelRequestTest implements HttpServerAdapters { out.println("cf2 after cancel: " + cf2); try { String body = cf2.get().body(); - assertEquals(body, String.join("", BODY.split("\\|"))); + assertEquals(String.join("", BODY.split("\\|")), body); throw new AssertionError("Expected CancellationException not received"); } catch (ExecutionException x) { out.println(now() + "Got expected exception: " + x); @@ -544,7 +543,7 @@ public class CancelRequestTest implements HttpServerAdapters { // completed yet - so wait for it here... try { String body = response.get().body(); - assertEquals(body, String.join("", BODY.split("\\|"))); + assertEquals(String.join("", BODY.split("\\|")), body); if (mayInterruptIfRunning) { // well actually - this could happen... In which case we'll need to // increase the latency in the server handler... @@ -577,10 +576,10 @@ public class CancelRequestTest implements HttpServerAdapters { assertTrue(response.isDone()); assertFalse(response.isCancelled()); - assertEquals(cf1.isCancelled(), hasCancellationException); + assertEquals(hasCancellationException, cf1.isCancelled()); assertTrue(cf2.isDone()); assertFalse(cf2.isCancelled()); - assertEquals(latch.getCount(), 0); + assertEquals(0, latch.getCount()); var error = TRACKER.check(tracker, 1000, (t) -> t.getOutstandingOperations() > 0 || t.getOutstandingSubscribers() > 0, @@ -593,10 +592,10 @@ public class CancelRequestTest implements HttpServerAdapters { if (!sameClient) client.close(); } - @Test(dataProvider = "urls") + @ParameterizedTest + @MethodSource("alltests") public void testPostInterrupt(String uri, boolean sameClient) throws Exception { - checkSkip(); HttpClient client = null; out.printf("%n%s testPostInterrupt(%s, %b)%n", now(), uri, sameClient); for (int i=0; i< ITERATION_COUNT; i++) { @@ -661,7 +660,7 @@ public class CancelRequestTest implements HttpServerAdapters { } else { assert failed == null; out.println(now() + req.uri() + ": got body: " + body); - assertEquals(body, String.join("", BODY.split("\\|"))); + assertEquals(String.join("", BODY.split("\\|")), body); } out.println(now() + "next iteration"); @@ -678,8 +677,8 @@ public class CancelRequestTest implements HttpServerAdapters { - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { // HTTP/1.1 HttpTestHandler h1_chunkHandler = new HTTPSlowHandler(); httpTestServer = HttpTestServer.create(HTTP_1_1); @@ -721,8 +720,8 @@ public class CancelRequestTest implements HttpServerAdapters { h3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { String sharedClientName = sharedClient == null ? null : sharedClient.toString(); sharedClient = null; diff --git a/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java b/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java index 0035a3f4302..48f23ebf370 100644 --- a/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java +++ b/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,19 +29,10 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.common.HttpServerAdapters jdk.test.lib.net.SimpleSSLContext * ReferenceTracker CancelStreamedBodyTest - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * CancelStreamedBodyTest */ import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -53,7 +44,6 @@ import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpResponse.BodyHandlers; -import java.util.Arrays; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -61,7 +51,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.httpclient.test.lib.common.HttpServerAdapters; @@ -72,23 +61,34 @@ import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class CancelStreamedBodyTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String https3URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String https3URI; static final long SERVER_LATENCY = 75; static final int ITERATION_COUNT = 3; @@ -108,8 +108,8 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -135,38 +135,40 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + + @AfterAll + static void printFailedTests() { out.println("\n========================="); - var failed = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - FAILURES.putAll(failed); try { out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); @@ -184,7 +186,7 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { } } - private String[] uris() { + private static String[] uris() { return new String[] { https3URI, httpURI, @@ -195,8 +197,7 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { } - @DataProvider(name = "urls") - public Object[][] alltests() { + public static Object[][] alltests() { String[] uris = uris(); Object[][] result = new Object[uris.length * 2][]; int i = 0; @@ -265,10 +266,10 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { final static String BODY = "Some string |\n that ?\n can |\n be split ?\n several |\n ways."; - @Test(dataProvider = "urls") + @ParameterizedTest + @MethodSource("alltests") public void testAsLines(String uri, boolean sameClient) throws Exception { - checkSkip(); HttpClient client = null; uri = uri + "/testAsLines"; out.printf("%n%s testAsLines(%s, %b)%n", now(), uri, sameClient); @@ -284,8 +285,8 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { for (int j = 0; j < 2; j++) { try (Stream body = client.send(req, BodyHandlers.ofLines()).body()) { lines = body.limit(j).toList(); - assertEquals(lines, BODY.replaceAll("\\||\\?", "") - .lines().limit(j).toList()); + assertEquals(BODY.replaceAll("\\||\\?", "") + .lines().limit(j).toList(), lines); } // Only check our still alive client for outstanding operations // and outstanding subscribers here: it should have none. @@ -306,10 +307,10 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { } } - @Test(dataProvider = "urls") + @ParameterizedTest + @MethodSource("alltests") public void testInputStream(String uri, boolean sameClient) throws Exception { - checkSkip(); HttpClient client = null; uri = uri + "/testInputStream"; out.printf("%n%s testInputStream(%s, %b)%n", now(), uri, sameClient); @@ -326,7 +327,7 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { try (InputStream is = client.send(req, BodyHandlers.ofInputStream()).body()) { for (int k = 0; k < j; k++) { read = is.read(); - assertEquals(read, BODY.charAt(k)); + assertEquals(BODY.charAt(k), read); } } // Only check our still alive client for outstanding operations @@ -350,8 +351,8 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { // HTTP/1.1 HttpTestHandler h1_chunkHandler = new HTTPSlowHandler(); httpTestServer = HttpTestServer.create(HTTP_1_1); @@ -385,8 +386,8 @@ public class CancelStreamedBodyTest implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { String sharedClientName = sharedClient == null ? null : sharedClient.toString(); sharedClient = null; diff --git a/test/jdk/java/net/httpclient/ForbiddenHeadTest.java b/test/jdk/java/net/httpclient/ForbiddenHeadTest.java index 57fd627b2b0..f2011766b2b 100644 --- a/test/jdk/java/net/httpclient/ForbiddenHeadTest.java +++ b/test/jdk/java/net/httpclient/ForbiddenHeadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -28,7 +28,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build DigestEchoServer ForbiddenHeadTest jdk.httpclient.test.lib.common.HttpServerAdapters * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm + * @run junit/othervm * -Djdk.http.auth.tunneling.disabledSchemes * -Djdk.httpclient.HttpClient.log=headers,requests * -Djdk.internal.httpclient.debug=true @@ -36,15 +36,6 @@ */ import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -61,7 +52,6 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -81,27 +71,40 @@ import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; + +import static jdk.httpclient.test.lib.common.HttpServerAdapters.createClientBuilderForH3; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class ForbiddenHeadTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - DigestEchoServer.TunnelingProxy proxy; - DigestEchoServer.TunnelingProxy authproxy; - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String https3URI; - HttpClient authClient; - HttpClient noAuthClient; + private static HttpTestServer httpTestServer; // HTTP/1.1 + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static DigestEchoServer.TunnelingProxy proxy; + private static DigestEchoServer.TunnelingProxy authproxy; + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String https3URI; + private static HttpClient authClient; + private static HttpClient noAuthClient; - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; static final long SLEEP_AFTER_TEST = 0; // milliseconds static final int ITERATIONS = 3; static final Executor executor = new TestExecutor(Executors.newCachedThreadPool()); @@ -142,34 +145,39 @@ public class ForbiddenHeadTest implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + + @AfterAll + static void printFailedTests() { out.println("\n========================="); try { // Exceptions should already have been added to FAILURES @@ -201,8 +209,7 @@ public class ForbiddenHeadTest implements HttpServerAdapters { static final String MESSAGE = "Unauthorized"; - @DataProvider(name = "all") - public Object[][] allcases() { + public static Object[][] allcases() { List result = new ArrayList<>(); for (boolean useAuth : List.of(true, false)) { for (boolean async : List.of(true, false)) { @@ -226,8 +233,6 @@ public class ForbiddenHeadTest implements HttpServerAdapters { return result.toArray(new Object[0][0]); } - static final AtomicLong requestCounter = new AtomicLong(); - static final Authenticator authenticator = new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { @@ -237,9 +242,9 @@ public class ForbiddenHeadTest implements HttpServerAdapters { static final AtomicLong sleepCount = new AtomicLong(); - @Test(dataProvider = "all") + @ParameterizedTest + @MethodSource("allcases") void test(String uriString, int code, boolean async, boolean useAuth) throws Throwable { - checkSkip(); HttpClient client = useAuth ? authClient : noAuthClient; var name = String.format("test(%s, %d, %s, %s)", uriString, code, async ? "async" : "sync", client.authenticator().isPresent() ? "authClient" : "noAuthClient"); @@ -318,23 +323,23 @@ public class ForbiddenHeadTest implements HttpServerAdapters { out.println(" Got response: " + response); - assertEquals(response.statusCode(), forbidden? FORBIDDEN : code); - assertEquals(response.body(), expectedValue == null ? null : ""); - assertEquals(response.headers().firstValue("X-value"), Optional.ofNullable(expectedValue)); + assertEquals(forbidden? FORBIDDEN : code, response.statusCode()); + assertEquals(expectedValue == null ? null : "", response.body()); + assertEquals(Optional.ofNullable(expectedValue), response.headers().firstValue("X-value")); // when the CONNECT request fails, its body is discarded - but // the response header may still contain its content length. // don't check content length in that case. if (expectedValue != null) { String clen = String.valueOf(expectedValue.getBytes(UTF_8).length); - assertEquals(response.headers().firstValue("Content-Length"), Optional.of(clen)); + assertEquals(Optional.of(clen), response.headers().firstValue("Content-Length")); } } // -- Infrastructure - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { httpTestServer = HttpTestServer.create(HTTP_1_1); httpTestServer.addHandler(new UnauthorizedHandler(), "/http1/"); httpTestServer.addHandler(new UnauthorizedHandler(), "/http2/proxy/"); @@ -357,7 +362,7 @@ public class ForbiddenHeadTest implements HttpServerAdapters { proxy = DigestEchoServer.createHttpsProxyTunnel(DigestEchoServer.HttpAuthSchemeType.NONE); authproxy = DigestEchoServer.createHttpsProxyTunnel(DigestEchoServer.HttpAuthSchemeType.BASIC); - authClient = TRACKER.track(newClientBuilderForH3() + authClient = TRACKER.track(createClientBuilderForH3() .proxy(TestProxySelector.of(proxy, authproxy, httpTestServer)) .sslContext(sslContext) .executor(executor) @@ -365,7 +370,7 @@ public class ForbiddenHeadTest implements HttpServerAdapters { .build()); clientCount.incrementAndGet(); - noAuthClient = TRACKER.track(newClientBuilderForH3() + noAuthClient = TRACKER.track(createClientBuilderForH3() .proxy(TestProxySelector.of(proxy, authproxy, httpTestServer)) .sslContext(sslContext) .executor(executor) @@ -384,8 +389,8 @@ public class ForbiddenHeadTest implements HttpServerAdapters { serverCount.incrementAndGet(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { authClient = noAuthClient = null; Thread.sleep(100); AssertionError fail = TRACKER.check(1500); diff --git a/test/jdk/java/net/httpclient/HeadersLowerCaseTest.java b/test/jdk/java/net/httpclient/HeadersLowerCaseTest.java index b1e4e569010..00a709a3387 100644 --- a/test/jdk/java/net/httpclient/HeadersLowerCaseTest.java +++ b/test/jdk/java/net/httpclient/HeadersLowerCaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -43,7 +43,6 @@ import jdk.internal.net.http.common.Utils; import jdk.test.lib.net.SimpleSSLContext; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -63,19 +62,18 @@ import static org.junit.jupiter.api.Assertions.assertThrows; * jdk.httpclient.test.lib.common.HttpServerAdapters * @run junit/othervm -Djdk.internal.httpclient.debug=true HeadersLowerCaseTest */ -@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class HeadersLowerCaseTest implements HttpServerAdapters { private static Set REQUEST_HEADERS; - private HttpTestServer h2server; - private HttpTestServer h3server; - private String h2ReqURIBase; - private String h3ReqURIBase; + private static HttpTestServer h2server; + private static HttpTestServer h3server; + private static String h2ReqURIBase; + private static String h3ReqURIBase; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); @BeforeAll - public void beforeAll() throws Exception { + public static void beforeAll() throws Exception { h2server = HttpTestServer.create(HTTP_2, sslContext); h2server.start(); h2ReqURIBase = "https://" + h2server.serverAuthority(); @@ -100,7 +98,7 @@ public class HeadersLowerCaseTest implements HttpServerAdapters { } @AfterAll - public void afterAll() throws Exception { + public static void afterAll() throws Exception { if (h2server != null) { h2server.stop(); } @@ -157,14 +155,14 @@ public class HeadersLowerCaseTest implements HttpServerAdapters { } } - private Stream params() throws Exception { + private static Stream params() throws Exception { return Stream.of( Arguments.of(HTTP_2, new URI(h2ReqURIBase + "/h2verifyReqHeaders")), Arguments.of(Version.HTTP_3, new URI(h3ReqURIBase + "/h3verifyReqHeaders"))); } /** - * Issues a HTTP/2 or HTTP/3 request with header names of varying case (some in lower, + * Issues an HTTP/2 or HTTP/3 request with header names of varying case (some in lower, * some mixed, some upper case) and expects that the client internally converts them * to lower case before encoding and sending to the server. The server side handler verifies * that it receives the header names in lower case and if it doesn't then it returns a diff --git a/test/jdk/java/net/httpclient/HttpInputStreamAvailableTest.java b/test/jdk/java/net/httpclient/HttpInputStreamAvailableTest.java index 5cca88716b6..99897a69a8c 100644 --- a/test/jdk/java/net/httpclient/HttpInputStreamAvailableTest.java +++ b/test/jdk/java/net/httpclient/HttpInputStreamAvailableTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -21,7 +21,7 @@ * questions. */ -/** +/* * @test * @bug 8306040 * @summary HttpResponseInputStream.available() returns 1 on empty stream @@ -47,19 +47,17 @@ import java.net.http.HttpResponse; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import static org.junit.jupiter.api.Assertions.assertEquals; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class HttpInputStreamAvailableTest { - private HttpServer server; - private int port; - static final String TEST_MESSAGE = "This is test message"; - static final int ZERO = 0; + private static HttpServer server; + private static int port; + private static final String TEST_MESSAGE = "This is test message"; + private static final int ZERO = 0; @BeforeAll - void setup() throws Exception { + static void setup() throws Exception { InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress(loopback, 0); server = HttpServer.create(addr, 0); @@ -72,69 +70,71 @@ public class HttpInputStreamAvailableTest { } @AfterAll - void teardown() throws Exception { + static void teardown() throws Exception { server.stop(0); } @Test public void test() throws Exception { - HttpClient client = HttpClient + try (HttpClient client = HttpClient .newBuilder() .proxy(HttpClient.Builder.NO_PROXY) - .build(); + .build()) { - URI uri = URIBuilder.newBuilder() - .scheme("http") - .loopback() - .port(port) - .path("/NonZeroResponse/") - .build(); + URI uri = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .path("/NonZeroResponse/") + .build(); - HttpRequest request = HttpRequest - .newBuilder(uri) - .GET() - .build(); + HttpRequest request = HttpRequest + .newBuilder(uri) + .GET() + .build(); - // Send a httpRequest and assert the bytes available - HttpResponse response = client.send(request, - HttpResponse.BodyHandlers.ofInputStream()); - try ( InputStream in = response.body()) { - in.readNBytes(2); - // this is not guaranteed, but a failure here would be surprising - assertEquals(TEST_MESSAGE.length() - 2, in.available()); - //read the remaining data - in.readAllBytes(); - //available should return 0 - assertEquals(ZERO, in.available()); + // Send a httpRequest and assert the bytes available + HttpResponse response = client.send(request, + HttpResponse.BodyHandlers.ofInputStream()); + try (InputStream in = response.body()) { + in.readNBytes(2); + // this is not guaranteed, but a failure here would be surprising + assertEquals(TEST_MESSAGE.length() - 2, in.available()); + //read the remaining data + in.readAllBytes(); + //available should return 0 + assertEquals(ZERO, in.available()); + } } } @Test public void test1() throws Exception { - HttpClient client = HttpClient + try (HttpClient client = HttpClient .newBuilder() .proxy(HttpClient.Builder.NO_PROXY) - .build(); + .build()) { - URI uri = URIBuilder.newBuilder() - .scheme("http") - .loopback() - .port(port) - .path("/ZeroResponse/") - .build(); + URI uri = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .path("/ZeroResponse/") + .build(); - HttpRequest request = HttpRequest - .newBuilder(uri) - .GET() - .build(); + HttpRequest request = HttpRequest + .newBuilder(uri) + .GET() + .build(); - // Send a httpRequest and assert the bytes available - HttpResponse response = client.send(request, - HttpResponse.BodyHandlers.ofInputStream()); - try ( InputStream in = response.body()) { - assertEquals(ZERO, in.available()); - in.readAllBytes(); - assertEquals(ZERO, in.available()); + // Send a httpRequest and assert the bytes available + HttpResponse response = client.send(request, + HttpResponse.BodyHandlers.ofInputStream()); + try (InputStream in = response.body()) { + assertEquals(ZERO, in.available()); + in.readAllBytes(); + assertEquals(ZERO, in.available()); + } } } diff --git a/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java b/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java index 6468175ab59..3b955b8feb7 100644 --- a/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java +++ b/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -35,7 +35,6 @@ import jdk.test.lib.net.URIBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import java.io.IOException; import java.io.InputStream; @@ -53,18 +52,17 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class HttpResponseInputStreamInterruptTest { - HttpServer server; - int port; - private final CountDownLatch interruptReadyLatch = new CountDownLatch(2); - private final CountDownLatch interruptDoneLatch = new CountDownLatch(1); + private static HttpServer server; + private static int port; + private static final CountDownLatch interruptReadyLatch = new CountDownLatch(2); + private static final CountDownLatch interruptDoneLatch = new CountDownLatch(1); static final String FIRST_MESSAGE = "Should be received"; static final String SECOND_MESSAGE = "Shouldn't be received"; @BeforeAll - void before() throws Exception { + static void before() throws Exception { InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress(loopback, 0); server = HttpServer.create(addr, 0); @@ -75,7 +73,7 @@ public class HttpResponseInputStreamInterruptTest { } @AfterAll - void after() throws Exception { + static void after() throws Exception { server.stop(0); } diff --git a/test/jdk/java/net/httpclient/ISO_8859_1_Test.java b/test/jdk/java/net/httpclient/ISO_8859_1_Test.java index d629a6f3105..103284c9d54 100644 --- a/test/jdk/java/net/httpclient/ISO_8859_1_Test.java +++ b/test/jdk/java/net/httpclient/ISO_8859_1_Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,7 +27,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.common.HttpServerAdapters jdk.test.lib.net.SimpleSSLContext * ReferenceTracker - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * ISO_8859_1_Test * @summary Tests that a client is able to receive ISO-8859-1 encoded header values. @@ -48,7 +48,6 @@ import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -60,21 +59,11 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.net.http.HttpClient.Version.HTTP_1_1; @@ -82,30 +71,38 @@ import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class ISO_8859_1_Test implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - DummyServer http1DummyServer; - HttpTestServer http1TestServer; // HTTP/1.1 ( http ) - HttpTestServer https1TestServer; // HTTPS/1.1 ( https ) - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String http1Dummy; - String http1URI; - String https1URI; - String http2URI; - String https2URI; - String http3URI; + private static DummyServer http1DummyServer; + private static HttpTestServer http1TestServer; // HTTP/1.1 ( http ) + private static HttpTestServer https1TestServer; // HTTPS/1.1 ( https ) + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String http1Dummy; + private static String http1URI; + private static String https1URI; + private static String http2URI; + private static String https2URI; + private static String http3URI; - static final int RESPONSE_CODE = 200; static final int ITERATION_COUNT = 4; - static final Class IAE = IllegalArgumentException.class; - static final Class CE = CompletionException.class; // a shared executor helps reduce the amount of threads created by the test static final Executor executor = new TestExecutor(Executors.newCachedThreadPool()); static final ConcurrentMap FAILURES = new ConcurrentHashMap<>(); @@ -121,8 +118,8 @@ public class ISO_8859_1_Test implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -148,40 +145,40 @@ public class ISO_8859_1_Test implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static void printFailedTests() { out.println("\n========================="); try { - var failed = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - FAILURES.putAll(failed); - out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); if (FAILURES.isEmpty()) return; @@ -199,7 +196,7 @@ public class ISO_8859_1_Test implements HttpServerAdapters { } } - private String[] uris() { + private static String[] uris() { return new String[] { http3URI, http1Dummy, @@ -210,13 +207,7 @@ public class ISO_8859_1_Test implements HttpServerAdapters { }; } - static AtomicLong URICOUNT = new AtomicLong(); - - @DataProvider(name = "variants") - public Object[][] variants(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - return new Object[0][]; - } + public static Object[][] variants() { String[] uris = uris(); Object[][] result = new Object[uris.length * 2][]; int i = 0; @@ -265,7 +256,7 @@ public class ISO_8859_1_Test implements HttpServerAdapters { } } - private static final Exception completionCause(CompletionException x) { + private static Exception completionCause(CompletionException x) { Throwable c = x; while (c instanceof CompletionException || c instanceof ExecutionException) { @@ -285,10 +276,11 @@ public class ISO_8859_1_Test implements HttpServerAdapters { return builder; } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void test(String uri, boolean sameClient) throws Exception { - checkSkip(); - System.out.println("Request to " + uri); + + System.out.printf("%n%s-- test sameClient=%s uri=%s%n%n", now(), sameClient, uri); HttpClient client = newHttpClient(uri, sameClient); @@ -307,7 +299,7 @@ public class ISO_8859_1_Test implements HttpServerAdapters { var response = cf.get(); System.out.println("Got: " + response); var value = response.headers().firstValue("Header8859").orElse(null); - assertEquals(value, "U\u00ffU"); + assertEquals("U\u00ffU", value); } System.out.println("HttpClient: PASSED"); if (uri.contains("http1")) { @@ -317,10 +309,10 @@ public class ISO_8859_1_Test implements HttpServerAdapters { conn.connect(); conn.getInputStream().readAllBytes(); var value = conn.getHeaderField("Header8859"); - assertEquals(value, "U\u00ffU", "legacy stack failed"); + assertEquals("U\u00ffU", value, "legacy stack failed"); System.out.println("URLConnection: PASSED"); } - System.out.println("test: DONE"); + System.out.println(now() + "test: DONE"); } static final class DummyServer extends Thread implements AutoCloseable { @@ -335,8 +327,8 @@ public class ISO_8859_1_Test implements HttpServerAdapters { static final InetSocketAddress LOOPBACK = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); final ServerSocket socket; - final CopyOnWriteArrayList accepted = new CopyOnWriteArrayList(); - final CompletableFuture done = new CompletableFuture(); + final CopyOnWriteArrayList accepted = new CopyOnWriteArrayList<>(); + final CompletableFuture done = new CompletableFuture<>(); volatile boolean closed; DummyServer() throws IOException { socket = new ServerSocket(); @@ -387,11 +379,11 @@ public class ISO_8859_1_Test implements HttpServerAdapters { } } - final void close(AutoCloseable toclose) { + void close(AutoCloseable toclose) { try { toclose.close(); } catch (Exception x) {}; } - final public void close() { + public void close() { closed = true; close(socket); accepted.forEach(this::close); @@ -410,8 +402,8 @@ public class ISO_8859_1_Test implements HttpServerAdapters { } } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { HttpServerAdapters.HttpTestHandler handler = new ISO88591Handler(); InetSocketAddress loopback = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); @@ -448,8 +440,8 @@ public class ISO_8859_1_Test implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { String sharedClientName = sharedClient == null ? null : sharedClient.toString(); sharedClient = null; diff --git a/test/jdk/java/net/httpclient/ProxySelectorTest.java b/test/jdk/java/net/httpclient/ProxySelectorTest.java index bf63e5a77b5..bb339e91bdc 100644 --- a/test/jdk/java/net/httpclient/ProxySelectorTest.java +++ b/test/jdk/java/net/httpclient/ProxySelectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,34 +27,20 @@ * @summary checks that a different proxy returned for * the same host:port is taken into account * @library /test/lib /test/jdk/java/net/httpclient/lib - * @build DigestEchoServer ProxySelectorTest jdk.httpclient.test.lib.http2.Http2TestServer + * @build DigestEchoServer ProxySelectorTest * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm + * @run junit/othervm * -Djdk.http.auth.tunneling.disabledSchemes * -Djdk.httpclient.HttpClient.log=headers,requests * -Djdk.internal.httpclient.debug=true * ProxySelectorTest */ -import com.sun.net.httpserver.HttpServer; -import com.sun.net.httpserver.HttpsConfigurator; -import com.sun.net.httpserver.HttpsServer; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.SocketAddress; @@ -63,7 +49,6 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -73,37 +58,44 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.httpclient.test.lib.http2.Http2TestServer; import static java.lang.System.err; import static java.lang.System.out; import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpClient.Version.HTTP_2; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; public class ProxySelectorTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 - HttpTestServer proxyHttpTestServer; // HTTP/1.1 - HttpTestServer authProxyHttpTestServer; // HTTP/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - DigestEchoServer.TunnelingProxy proxy; - DigestEchoServer.TunnelingProxy authproxy; - String httpURI; - String httpsURI; - String proxyHttpURI; - String authProxyHttpURI; - String http2URI; - String https2URI; - HttpClient client; + private static HttpTestServer httpTestServer; // HTTP/1.1 + private static HttpTestServer proxyHttpTestServer; // HTTP/1.1 + private static HttpTestServer authProxyHttpTestServer; // HTTP/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static DigestEchoServer.TunnelingProxy proxy; + private static DigestEchoServer.TunnelingProxy authproxy; + private static String httpURI; + private static String httpsURI; + private static String proxyHttpURI; + private static String http2URI; + private static String https2URI; + private static HttpClient client; - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; static final long SLEEP_AFTER_TEST = 0; // milliseconds static final int ITERATIONS = 3; static final Executor executor = new TestExecutor(Executors.newCachedThreadPool()); @@ -144,34 +136,38 @@ public class ProxySelectorTest implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests() { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static void printFailedTests() { out.println("\n========================="); try { // Exceptions should already have been added to FAILURES @@ -204,12 +200,10 @@ public class ProxySelectorTest implements HttpServerAdapters { static final int UNAUTHORIZED = 401; static final int PROXY_UNAUTHORIZED = 407; static final int HTTP_OK = 200; - static final String MESSAGE = "Unauthorized"; enum Schemes { HTTP, HTTPS } - @DataProvider(name = "all") - public Object[][] positive() { + public static Object[][] positive() { return new Object[][] { { Schemes.HTTP, HTTP_1_1, httpURI, true}, { Schemes.HTTP, HttpClient.Version.HTTP_2, http2URI, true}, @@ -222,15 +216,13 @@ public class ProxySelectorTest implements HttpServerAdapters { }; } - static final AtomicLong requestCounter = new AtomicLong(); - static final AtomicLong sleepCount = new AtomicLong(); - @Test(dataProvider = "all") + @ParameterizedTest + @MethodSource("positive") void test(Schemes scheme, HttpClient.Version version, String uri, boolean async) throws Throwable { - checkSkip(); var name = String.format("test(%s, %s, %s)", scheme, version, async); out.printf("%n---- starting %s ----%n", name); @@ -260,7 +252,7 @@ public class ProxySelectorTest implements HttpServerAdapters { HttpRequest request = requestBuilder.build(); out.println("Sending request: " + request.uri()); - HttpResponse response = null; + HttpResponse response; if (async) { response = client.send(request, handler); } else { @@ -288,9 +280,11 @@ public class ProxySelectorTest implements HttpServerAdapters { // A plain server or https server should serve it, and we should get 200 OK response = send(client, uri1, BodyHandlers.ofString(), async); out.println("Got response from plain server: " + response); - assertEquals(response.statusCode(), HTTP_OK); - assertEquals(response.headers().firstValue("X-value"), - scheme == Schemes.HTTPS ? Optional.of("https-server") : Optional.of("plain-server")); + assertEquals(HTTP_OK, response.statusCode()); + assertEquals(scheme == Schemes.HTTPS + ? Optional.of("https-server") + : Optional.of("plain-server"), + response.headers().firstValue("X-value")); // Second request should go through a non authenticating proxy. // For a clear connection - a proxy-server should serve it, and we should get 200 OK @@ -298,9 +292,11 @@ public class ProxySelectorTest implements HttpServerAdapters { // authenticating proxy - and we should receive 200 OK from an https-server response = send(client, uri2, BodyHandlers.ofString(), async); out.println("Got response through noauth proxy: " + response); - assertEquals(response.statusCode(), HTTP_OK); - assertEquals(response.headers().firstValue("X-value"), - scheme == Schemes.HTTPS ? Optional.of("https-server") : Optional.of("proxy-server")); + assertEquals(HTTP_OK, response.statusCode()); + assertEquals(scheme == Schemes.HTTPS + ? Optional.of("https-server") + : Optional.of("proxy-server"), + response.headers().firstValue("X-value")); // Third request should go through an authenticating proxy. // For a clear connection - an auth-proxy-server should serve it, and we @@ -310,16 +306,18 @@ public class ProxySelectorTest implements HttpServerAdapters { // proxy - so the X-value header will be absent response = send(client, uri3, BodyHandlers.ofString(), async); out.println("Got response through auth proxy: " + response); - assertEquals(response.statusCode(), PROXY_UNAUTHORIZED); - assertEquals(response.headers().firstValue("X-value"), - scheme == Schemes.HTTPS ? Optional.empty() : Optional.of("auth-proxy-server")); + assertEquals(PROXY_UNAUTHORIZED, response.statusCode()); + assertEquals(scheme == Schemes.HTTPS + ? Optional.empty() + : Optional.of("auth-proxy-server"), + response.headers().firstValue("X-value")); } // -- Infrastructure - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { httpTestServer = HttpTestServer.create(HTTP_1_1); httpTestServer.addHandler(new PlainServerHandler("plain-server"), "/http1/"); httpURI = "http://" + httpTestServer.serverAuthority() + "/http1"; @@ -368,8 +366,8 @@ public class ProxySelectorTest implements HttpServerAdapters { serverCount.incrementAndGet(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { client = null; Thread.sleep(100); AssertionError fail = TRACKER.check(1500); @@ -387,7 +385,7 @@ public class ProxySelectorTest implements HttpServerAdapters { } } - class TestProxySelector extends ProxySelector { + static final class TestProxySelector extends ProxySelector { @Override public List select(URI uri) { String path = uri.getPath(); @@ -426,11 +424,8 @@ public class ProxySelectorTest implements HttpServerAdapters { String path = t.getRequestURI().getPath(); HttpTestRequestHeaders reqh = t.getRequestHeaders(); HttpTestResponseHeaders rsph = t.getResponseHeaders(); - - String xValue = serverType; rsph.addHeader("X-value", serverType); - t.getResponseHeaders().addHeader("X-value", xValue); byte[] body = "RESPONSE".getBytes(UTF_8); t.sendResponseHeaders(HTTP_OK, body.length); try (var out = t.getResponseBody()) { @@ -449,20 +444,16 @@ public class ProxySelectorTest implements HttpServerAdapters { @Override public void handle(HttpTestExchange t) throws IOException { readAllRequestData(t); // shouldn't be any - String method = t.getRequestMethod(); String path = t.getRequestURI().getPath(); - HttpTestRequestHeaders reqh = t.getRequestHeaders(); HttpTestResponseHeaders rsph = t.getResponseHeaders(); - String xValue = serverType; - String srv = path.contains("/proxy/") ? "proxy" : "server"; String prefix = path.contains("/proxy/") ? "Proxy-" : "WWW-"; int code = path.contains("/proxy/") ? PROXY_UNAUTHORIZED : UNAUTHORIZED; String resp = prefix + "Unauthorized"; rsph.addHeader(prefix + "Authenticate", "Basic realm=\"earth\", charset=\"UTF-8\""); byte[] body = resp.getBytes(UTF_8); - t.getResponseHeaders().addHeader("X-value", xValue); + rsph.addHeader("X-value", serverType); t.sendResponseHeaders(code, body.length); try (var out = t.getResponseBody()) { out.write(body); diff --git a/test/jdk/java/net/httpclient/Response204V2Test.java b/test/jdk/java/net/httpclient/Response204V2Test.java index c9dbd8eccf9..835f7aa65f7 100644 --- a/test/jdk/java/net/httpclient/Response204V2Test.java +++ b/test/jdk/java/net/httpclient/Response204V2Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -27,7 +27,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * ReferenceTracker jdk.httpclient.test.lib.common.HttpServerAdapters - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * Response204V2Test * @summary Tests that streams are closed after receiving a 204 response. @@ -44,7 +44,6 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import java.util.Arrays; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -52,19 +51,9 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; @@ -74,15 +63,25 @@ import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class Response204V2Test implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String http2URI; - String https2URI; - String http3URI; + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String http2URI; + private static String https2URI; + private static String http3URI; static final int RESPONSE_CODE = 204; static final int ITERATION_COUNT = 4; @@ -101,8 +100,8 @@ public class Response204V2Test implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -128,40 +127,40 @@ public class Response204V2Test implements HttpServerAdapters { } } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static final void printFailedTests() { out.println("\n========================="); try { - var failed = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - FAILURES.putAll(failed); - out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); if (FAILURES.isEmpty()) return; @@ -179,7 +178,7 @@ public class Response204V2Test implements HttpServerAdapters { } } - private String[] uris() { + private static String[] uris() { return new String[] { http3URI, http2URI, @@ -187,13 +186,7 @@ public class Response204V2Test implements HttpServerAdapters { }; } - static AtomicLong URICOUNT = new AtomicLong(); - - @DataProvider(name = "variants") - public Object[][] variants(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - return new Object[0][]; - } + public static Object[][] variants() { String[] uris = uris(); Object[][] result = new Object[uris.length * 2][]; int i = 0; @@ -232,23 +225,6 @@ public class Response204V2Test implements HttpServerAdapters { } } - - static void checkStatus(int expected, int found) throws Exception { - if (expected != found) { - System.err.printf ("Test failed: wrong status code %d/%d\n", - expected, found); - throw new RuntimeException("Test failed"); - } - } - - static void checkStrings(String expected, String found) throws Exception { - if (!expected.equals(found)) { - System.err.printf ("Test failed: wrong string %s/%s\n", - expected, found); - throw new RuntimeException("Test failed"); - } - } - private HttpRequest.Builder newRequestBuilder(URI uri) { var builder = HttpRequest.newBuilder(uri); if (uri.getRawPath().contains("/http3/")) { @@ -258,10 +234,10 @@ public class Response204V2Test implements HttpServerAdapters { return builder; } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void test(String uri, boolean sameClient) throws Exception { - checkSkip(); - out.println("Request to " + uri); + out.printf("%n%s-- test sameClient=%s, uri=%s%n%n", now(), sameClient, uri); HttpClient client = newHttpClient(uri, sameClient); @@ -282,8 +258,8 @@ public class Response204V2Test implements HttpServerAdapters { out.println("test: DONE"); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { // HTTP/2 HttpTestHandler handler204 = new Handler204(); @@ -305,8 +281,8 @@ public class Response204V2Test implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { String sharedClientName = sharedClient == null ? null : sharedClient.toString(); sharedClient = null; diff --git a/test/jdk/java/net/httpclient/ShortResponseBody.java b/test/jdk/java/net/httpclient/ShortResponseBody.java index b4fd83585ee..5f931cd1ed3 100644 --- a/test/jdk/java/net/httpclient/ShortResponseBody.java +++ b/test/jdk/java/net/httpclient/ShortResponseBody.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -36,24 +36,16 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.Arrays; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLServerSocketFactory; @@ -64,28 +56,40 @@ import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpResponse.BodyHandlers.ofString; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.util.stream.Collectors.toList; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public abstract class ShortResponseBody { - Server closeImmediatelyServer; - Server closeImmediatelyHttpsServer; - Server variableLengthServer; - Server variableLengthHttpsServer; - Server fixedLengthServer; + private static Server closeImmediatelyServer; + private static Server closeImmediatelyHttpsServer; + private static Server variableLengthServer; + private static Server variableLengthHttpsServer; + private static Server fixedLengthServer; - String httpURIClsImed; - String httpsURIClsImed; - String httpURIVarLen; - String httpsURIVarLen; - String httpURIFixLen; + private static String httpURIClsImed; + private static String httpsURIClsImed; + private static String httpURIVarLen; + private static String httpsURIVarLen; + private static String httpURIFixLen; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - SSLParameters sslParameters; - HttpClient client; - int numberOfRequests; + private static SSLParameters sslParameters; + protected static HttpClient client; + private static int numberOfRequests; static final int REQUESTS_PER_CLIENT = 10; // create new client every 10 requests static final long PAUSE_FOR_GC = 5; // 5ms to let gc work @@ -99,7 +103,7 @@ public abstract class ShortResponseBody { static final AtomicLong reqnb = new AtomicLong(); static final AtomicLong ids = new AtomicLong(); - final ThreadFactory factory = new ThreadFactory() { + private static final ThreadFactory factory = new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, "HttpClient-Worker-" + ids.incrementAndGet()); @@ -107,21 +111,49 @@ public abstract class ShortResponseBody { return thread; } }; - final ExecutorService service = Executors.newCachedThreadPool(factory); - - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); + private static final ExecutorService service = Executors.newCachedThreadPool(factory); + static final ConcurrentMap FAILURES = new ConcurrentHashMap<>(); + static final long start = System.nanoTime(); + public static String now() { + long now = System.nanoTime() - start; + long secs = now / 1000_000_000; + long mill = (now % 1000_000_000) / 1000_000; + long nan = now % 1000_000; + return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - @BeforeMethod - void beforeMethod(ITestContext context) { + private static boolean stopAfterFirstFailure() { + return Boolean.getBoolean("jdk.internal.httpclient.debug"); + } + + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + } + } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } + } + + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @BeforeEach + void beforeMethod() { if (client == null || numberOfRequests == REQUESTS_PER_CLIENT) { numberOfRequests = 0; out.println("--- new client"); @@ -134,22 +166,12 @@ public abstract class ShortResponseBody { } } numberOfRequests++; - if (context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); - } - } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @AfterAll + static void printFailedTests() { out.println("\n=========================\n"); try { - var FAILURES = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - if (FAILURES.isEmpty()) return; out.println("Failed tests: "); FAILURES.entrySet().forEach((e) -> { @@ -162,8 +184,7 @@ public abstract class ShortResponseBody { } } - @DataProvider(name = "sanity") - public Object[][] sanity() { + public static Object[][] sanity() { return new Object[][]{ { httpURIVarLen + "?length=all" }, { httpsURIVarLen + "?length=all" }, @@ -175,22 +196,22 @@ public abstract class ShortResponseBody { return url.replace("%reqnb%", String.valueOf(reqnb.incrementAndGet())); } - @Test(dataProvider = "sanity") + @ParameterizedTest + @MethodSource("sanity") void sanity(String url) throws Exception { url = uniqueURL(url); HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); out.println("Request: " + request); HttpResponse response = client.send(request, ofString()); String body = response.body(); - assertEquals(body, EXPECTED_RESPONSE_BODY); + assertEquals(EXPECTED_RESPONSE_BODY, body); client.sendAsync(request, ofString()) .thenApply(resp -> resp.body()) - .thenAccept(b -> assertEquals(b, EXPECTED_RESPONSE_BODY)) + .thenAccept(b -> assertEquals(EXPECTED_RESPONSE_BODY, b)) .join(); } - @DataProvider(name = "sanityBadRequest") - public Object[][] sanityBadRequest() { + public static Object[][] sanityBadRequest() { return new Object[][]{ { httpURIVarLen }, // no query string { httpsURIVarLen }, @@ -198,18 +219,18 @@ public abstract class ShortResponseBody { }; } - @Test(dataProvider = "sanityBadRequest") + @ParameterizedTest + @MethodSource("sanityBadRequest") void sanityBadRequest(String url) throws Exception { url = uniqueURL(url); HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); out.println("Request: " + request); HttpResponse response = client.send(request, ofString()); - assertEquals(response.statusCode(), 400); - assertEquals(response.body(), ""); + assertEquals(400, response.statusCode()); + assertEquals("", response.body()); } - @DataProvider(name = "uris") - public Object[][] variants(ITestContext context) { + public static Object[][] variants() { String[][] cases = new String[][] { // The length query string is the total number of bytes in the reply, // including headers, before the server closes the connection. The @@ -268,13 +289,6 @@ public abstract class ShortResponseBody { { httpsURIClsImed, "no bytes"}, }; - if (context.getFailedTests().size() > 0) { - // Shorten the log output by preventing useless - // skip traces to be printed for subsequent methods - // if one of the previous @Test method has failed. - return new Object[0][]; - } - return cases; } @@ -618,7 +632,7 @@ public abstract class ShortResponseBody { String response( ) { return RESPONSE; } } - /** A server that issues a, possibly-partial, chunked reply over SSL. */ + /** A server that issues a possibly-partial, chunked reply over SSL. */ static final class SSLVariableLengthServer extends PlainVariableLengthServer { SSLVariableLengthServer() throws IOException { super("SSLVariableLengthServer"); @@ -655,8 +669,8 @@ public abstract class ShortResponseBody { + server.getPort(); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { SSLContext.setDefault(sslContext); sslParameters = new SSLParameters(); @@ -682,8 +696,8 @@ public abstract class ShortResponseBody { + "/http1/fixed/req=%reqnb%/baz"; } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { closeImmediatelyServer.close(); closeImmediatelyHttpsServer.close(); variableLengthServer.close(); diff --git a/test/jdk/java/net/httpclient/ShortResponseBodyGet.java b/test/jdk/java/net/httpclient/ShortResponseBodyGet.java index 0a9041020a5..47be508c8c1 100644 --- a/test/jdk/java/net/httpclient/ShortResponseBodyGet.java +++ b/test/jdk/java/net/httpclient/ShortResponseBodyGet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -28,7 +28,7 @@ * received before a socket exception or eof. * @library /test/lib * @build jdk.test.lib.net.SimpleSSLContext ShortResponseBody ShortResponseBodyGet - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=headers,errors,channel * ShortResponseBodyGet */ @@ -38,21 +38,24 @@ import java.net.URI; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.concurrent.ExecutionException; -import org.testng.annotations.Test; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import static java.lang.System.out; import static java.net.http.HttpResponse.BodyHandlers.ofString; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; public class ShortResponseBodyGet extends ShortResponseBody { - @Test(dataProvider = "uris") + @ParameterizedTest + @MethodSource("variants") void testSynchronousGET(String urlp, String expectedMsg) throws Exception { - checkSkip(); String url = uniqueURL(urlp); HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); - out.println("Request: " + request); + out.printf("%n%s-- testSynchronousGET Request: %s%n%n", now(), request); try { HttpResponse response = client.send(request, ofString()); String body = response.body(); @@ -67,14 +70,14 @@ public class ShortResponseBodyGet extends ShortResponseBody { } } - @Test(dataProvider = "uris") + @ParameterizedTest + @MethodSource("variants") void testAsynchronousGET(String urlp, String expectedMsg) throws Exception { - checkSkip(); String url = uniqueURL(urlp); HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); - out.println("Request: " + request); + out.printf("%n%s-- testAsynchronousGET Request: %s%n%n", now(), request); try { HttpResponse response = client.sendAsync(request, ofString()).get(); String body = response.body(); diff --git a/test/jdk/java/net/httpclient/ShortResponseBodyPost.java b/test/jdk/java/net/httpclient/ShortResponseBodyPost.java index c72540c5990..60d2796b34f 100644 --- a/test/jdk/java/net/httpclient/ShortResponseBodyPost.java +++ b/test/jdk/java/net/httpclient/ShortResponseBodyPost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -28,7 +28,7 @@ * received before a socket exception or eof. * @library /test/lib * @build jdk.test.lib.net.SimpleSSLContext ShortResponseBody ShortResponseBodyPost - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=headers,errors,channel * -Djdk.internal.httpclient.debug=true * ShortResponseBodyPost @@ -42,10 +42,14 @@ import java.net.http.HttpResponse; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; -import org.testng.annotations.Test; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import static java.lang.System.out; import static java.net.http.HttpResponse.BodyHandlers.ofString; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; + public class ShortResponseBodyPost extends ShortResponseBody { // POST tests are racy in what may be received before writing may cause a @@ -56,16 +60,16 @@ public class ShortResponseBodyPost extends ShortResponseBody { List.of("no bytes", "status line", "header"); - @Test(dataProvider = "uris") + @ParameterizedTest + @MethodSource("variants") void testSynchronousPOST(String urlp, String expectedMsg) throws Exception { - checkSkip(); String url = uniqueURL(urlp); HttpRequest request = HttpRequest.newBuilder(URI.create(url)) .POST(BodyPublishers.ofInputStream(() -> new InfiniteInputStream())) .build(); - out.println("Request: " + request); + out.printf("%n%s-- testSynchronousPOST Request: %s%n%n", now(), request); try { HttpResponse response = client.send(request, ofString()); String body = response.body(); @@ -86,16 +90,16 @@ public class ShortResponseBodyPost extends ShortResponseBody { } } - @Test(dataProvider = "uris") + @ParameterizedTest + @MethodSource("variants") void testAsynchronousPOST(String urlp, String expectedMsg) throws Exception { - checkSkip(); String url = uniqueURL(urlp); HttpRequest request = HttpRequest.newBuilder(URI.create(url)) .POST(BodyPublishers.ofInputStream(() -> new InfiniteInputStream())) .build(); - out.println("Request: " + request); + out.printf("%n%s-- testAsynchronousPOST Request: %s%n%n", now(), request); try { HttpResponse response = client.sendAsync(request, ofString()).get(); String body = response.body(); diff --git a/test/jdk/java/net/httpclient/ShortResponseBodyPostWithRetry.java b/test/jdk/java/net/httpclient/ShortResponseBodyPostWithRetry.java index bd234690526..0ab404e556a 100644 --- a/test/jdk/java/net/httpclient/ShortResponseBodyPostWithRetry.java +++ b/test/jdk/java/net/httpclient/ShortResponseBodyPostWithRetry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -27,7 +27,7 @@ * @library /test/lib * @build jdk.test.lib.net.SimpleSSLContext * @build ShortResponseBody ShortResponseBodyPost - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=headers,errors,channel * -Djdk.httpclient.enableAllMethodRetry * -Djdk.internal.httpclient.debug=true diff --git a/test/jdk/java/net/httpclient/SpecialHeadersTest.java b/test/jdk/java/net/httpclient/SpecialHeadersTest.java index d33135dd4ce..d4d5f2a85e2 100644 --- a/test/jdk/java/net/httpclient/SpecialHeadersTest.java +++ b/test/jdk/java/net/httpclient/SpecialHeadersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -31,35 +31,22 @@ * jdk.httpclient.test.lib.http2.Http2TestServer * jdk.test.lib.net.SimpleSSLContext * @requires (vm.compMode != "Xcomp") - * @run testng/othervm/timeout=480 + * @run junit/othervm/timeout=480 * -Djdk.httpclient.HttpClient.log=requests,headers,errors * SpecialHeadersTest - * @run testng/othervm/timeout=480 -Djdk.httpclient.allowRestrictedHeaders=Host + * @run junit/othervm/timeout=480 -Djdk.httpclient.allowRestrictedHeaders=Host * -Djdk.httpclient.HttpClient.log=requests,headers,errors * SpecialHeadersTest */ -import com.sun.net.httpserver.HttpServer; -import com.sun.net.httpserver.HttpsConfigurator; -import com.sun.net.httpserver.HttpsServer; import jdk.internal.net.http.common.OperationTrackers.Tracker; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.ITestContext; -import org.testng.ITestResult; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpHeaders; @@ -83,9 +70,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; -import java.util.stream.Collectors; import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.httpclient.test.lib.http2.Http2TestServer; import static java.lang.System.err; import static java.lang.System.out; @@ -93,22 +78,37 @@ import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; +import static java.net.http.HttpOption.H3_DISCOVERY; +import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.nio.charset.StandardCharsets.US_ASCII; -import org.testng.Assert; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class SpecialHeadersTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String https3URI; static final String[][] headerNamesAndValues = new String[][]{ {"User-Agent: "}, @@ -132,8 +132,7 @@ public class SpecialHeadersTest implements HttpServerAdapters { {"hoSt: mixed"} }; - @DataProvider(name = "variants") - public Object[][] variants() { + public static Object[][] variants() { String prop = System.getProperty("jdk.httpclient.allowRestrictedHeaders"); boolean hostTest = prop != null && prop.equalsIgnoreCase("host"); final String[][] testInput = hostTest ? headerNamesAndValues1 : headerNamesAndValues; @@ -153,6 +152,9 @@ public class SpecialHeadersTest implements HttpServerAdapters { Arrays.asList(testInput).stream() .map(e -> new Object[] {https2URI, e[0], sameClient}) .forEach(list::add); + Arrays.asList(testInput).stream() + .map(e -> new Object[] {https3URI, e[0], sameClient}) + .forEach(list::add); } return list.stream().toArray(Object[][]::new); } @@ -173,8 +175,8 @@ public class SpecialHeadersTest implements HttpServerAdapters { return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan); } - final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - private volatile HttpClient sharedClient; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static volatile HttpClient sharedClient; static class TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong(); @@ -209,38 +211,39 @@ public class SpecialHeadersTest implements HttpServerAdapters { } - protected boolean stopAfterFirstFailure() { + private static boolean stopAfterFirstFailure() { return Boolean.getBoolean("jdk.internal.httpclient.debug"); } - final AtomicReference skiptests = new AtomicReference<>(); - void checkSkip() { - var skip = skiptests.get(); - if (skip != null) throw skip; - } - static String name(ITestResult result) { - var params = result.getParameters(); - return result.getName() - + (params == null ? "()" : Arrays.toString(result.getParameters())); - } - - @BeforeMethod - void beforeMethod(ITestContext context) { - if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) { - if (skiptests.get() == null) { - SkipException skip = new SkipException("some tests failed"); - skip.setStackTrace(new StackTraceElement[0]); - skiptests.compareAndSet(null, skip); + static final class TestStopper implements TestWatcher, BeforeEachCallback { + final AtomicReference failed = new AtomicReference<>(); + TestStopper() { } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + if (stopAfterFirstFailure()) { + String msg = "Aborting due to: " + cause; + failed.compareAndSet(null, msg); + FAILURES.putIfAbsent(context.getDisplayName(), cause); + System.out.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); + System.err.printf("%nTEST FAILED: %s%s%n\tAborting due to %s%n%n", + now(), context.getDisplayName(), cause); } } + + @Override + public void beforeEach(ExtensionContext context) { + String msg = failed.get(); + Assumptions.assumeTrue(msg == null, msg); + } } - @AfterClass - static final void printFailedTests(ITestContext context) { + @RegisterExtension + static final TestStopper stopper = new TestStopper(); + + @AfterAll + static void printFailedTests() { out.println("\n========================="); - var failed = context.getFailedTests().getAllResults().stream() - .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable)); - FAILURES.putAll(failed); try { out.printf("%n%sCreated %d servers and %d clients%n", now(), serverCount.get(), clientCount.get()); @@ -260,7 +263,7 @@ public class SpecialHeadersTest implements HttpServerAdapters { private HttpClient makeNewClient() { clientCount.incrementAndGet(); - return HttpClient.newBuilder() + return newClientBuilderForH3() .proxy(NO_PROXY) .executor(executor) .sslContext(sslContext) @@ -307,7 +310,8 @@ public class SpecialHeadersTest implements HttpServerAdapters { if (throwable instanceof Error e) throw e; } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void test(String uriString, String headerNameAndValue, boolean sameClient) @@ -335,6 +339,10 @@ public class SpecialHeadersTest implements HttpServerAdapters { } HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri); + if (uriString.contains("/http3")) { + requestBuilder.version(HTTP_3); + requestBuilder.setOption(H3_DISCOVERY, HTTP_3_URI_ONLY); + } if (!useDefault) { requestBuilder.header(name, value); } @@ -343,7 +351,7 @@ public class SpecialHeadersTest implements HttpServerAdapters { out.println("Got response: " + resp); out.println("Got body: " + resp.body()); - assertEquals(resp.statusCode(), 200, + assertEquals(200, resp.statusCode(), "Expected 200, got:" + resp.statusCode()); boolean isInitialRequest = i == 0; @@ -366,10 +374,10 @@ public class SpecialHeadersTest implements HttpServerAdapters { : resp.headers().firstValue("X-" + key).get(); out.println("Got X-" + key + ": " + resp.headers().allValues("X-" + key)); if (value != null) { - assertEquals(receivedHeaderString, value); - assertEquals(resp.headers().allValues("X-" + key), List.of(value)); + assertEquals(value, receivedHeaderString); + assertEquals(List.of(value), resp.headers().allValues("X-" + key)); } else { - assertEquals(resp.headers().allValues("X-" + key).size(), 0); + assertEquals(0, resp.headers().allValues("X-" + key).size()); } } } catch (Throwable x) { @@ -389,7 +397,8 @@ public class SpecialHeadersTest implements HttpServerAdapters { } } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void testHomeMadeIllegalHeader(String uriString, String headerNameAndValue, boolean sameClient) @@ -443,7 +452,7 @@ public class SpecialHeadersTest implements HttpServerAdapters { try { HttpResponse response = client.send(req, BodyHandlers.ofString()); - Assert.fail("Unexpected reply: " + response); + Assertions.fail("Unexpected reply: " + response); } catch (IllegalArgumentException ee) { out.println("Got IAE as expected"); } @@ -465,7 +474,8 @@ public class SpecialHeadersTest implements HttpServerAdapters { - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void testAsync(String uriString, String headerNameAndValue, boolean sameClient) throws Exception { @@ -490,6 +500,10 @@ public class SpecialHeadersTest implements HttpServerAdapters { } HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri); + if (uriString.contains("/http3")) { + requestBuilder.version(HTTP_3); + requestBuilder.setOption(H3_DISCOVERY, HTTP_3_URI_ONLY); + } if (!useDefault) { requestBuilder.header(name, value); } @@ -504,7 +518,7 @@ public class SpecialHeadersTest implements HttpServerAdapters { .thenApply(response -> { out.println("Got response: " + response); out.println("Got body: " + response.body()); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); return response; }) .thenAccept(resp -> { @@ -522,10 +536,10 @@ public class SpecialHeadersTest implements HttpServerAdapters { : resp.headers().firstValue("X-" + key).orElse(null); out.println("Got X-" + key + ": " + resp.headers().allValues("X-" + key)); if (value != null) { - assertEquals(receivedHeaderString, value); - assertEquals(resp.headers().allValues("X-" + key), List.of(value)); + assertEquals(value, receivedHeaderString); + assertEquals(List.of(value), resp.headers().allValues("X-" + key)); } else { - assertEquals(resp.headers().allValues("X-" + key).size(), 1); + assertEquals(1, resp.headers().allValues("X-" + key).size()); } } }) @@ -552,8 +566,8 @@ public class SpecialHeadersTest implements HttpServerAdapters { + server.getAddress().getPort(); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { out.println("--- Starting setup " + now()); HttpTestHandler handler = new HttpUriStringHandler(); @@ -573,14 +587,19 @@ public class SpecialHeadersTest implements HttpServerAdapters { https2TestServer.addHandler(handler, "/https2"); https2URI = "https://" + https2TestServer.serverAuthority() + "/https2"; + http3TestServer = HttpTestServer.create(HTTP_3_URI_ONLY, sslContext); + http3TestServer.addHandler(handler, "/http3"); + https3URI = "https://" + http3TestServer.serverAuthority() + "/http3"; + httpTestServer.start(); httpsTestServer.start(); http2TestServer.start(); https2TestServer.start(); + http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { out.println("\n--- Teardown " + now()); HttpClient shared = sharedClient; String sharedClientName = @@ -595,6 +614,7 @@ public class SpecialHeadersTest implements HttpServerAdapters { httpsTestServer.stop(); http2TestServer.stop(); https2TestServer.stop(); + http3TestServer.start(); executor.shutdown(); } finally { if (fail != null) { diff --git a/test/jdk/java/net/httpclient/StreamingBody.java b/test/jdk/java/net/httpclient/StreamingBody.java index 3fb4f29208e..d0577596038 100644 --- a/test/jdk/java/net/httpclient/StreamingBody.java +++ b/test/jdk/java/net/httpclient/StreamingBody.java @@ -72,20 +72,19 @@ import org.junit.jupiter.api.extension.TestWatcher; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class StreamingBody implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String http3URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String http3URI; static final AtomicLong clientCount = new AtomicLong(); static final AtomicLong serverCount = new AtomicLong(); @@ -186,7 +185,7 @@ public class StreamingBody implements HttpServerAdapters { static final String MESSAGE = "StreamingBody message body"; static final int ITERATIONS = 100; - public Object[][] positive() { + public static Object[][] positive() { return new Object[][] { { http3URI, }, { httpURI, }, @@ -253,7 +252,7 @@ public class StreamingBody implements HttpServerAdapters { // -- Infrastructure @BeforeAll - public void setup() throws Exception { + public static void setup() throws Exception { httpTestServer = HttpTestServer.create(HTTP_1_1); httpTestServer.addHandler(new MessageHandler(), "/http1/streamingbody/"); httpURI = "http://" + httpTestServer.serverAuthority() + "/http1/streamingbody/w"; @@ -290,7 +289,7 @@ public class StreamingBody implements HttpServerAdapters { } @AfterAll - public void teardown() throws Exception { + public static void teardown() throws Exception { try { httpTestServer.stop(); httpsTestServer.stop(); @@ -303,7 +302,7 @@ public class StreamingBody implements HttpServerAdapters { } } - static final void printFailedTests() { + static void printFailedTests() { out.println("\n========================="); try { out.printf("%n%sCreated %s servers and %s clients%n",