mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-29 01:00:29 +00:00
8374706: HttpClient: Ensure that request body publishers support multiple subscriptions
Reviewed-by: dfuchs, jpai
This commit is contained in:
parent
00ee63e99e
commit
2a64074a8b
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -61,7 +61,7 @@ public final class ByteBufferUtils {
|
||||
|
||||
private static byte[] bytes(ByteBuffer buffer) {
|
||||
byte[] bytes = new byte[buffer.limit()];
|
||||
buffer.get(bytes);
|
||||
buffer.get(buffer.position(), bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -25,10 +25,13 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import static java.net.http.HttpRequest.BodyPublishers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@ -37,16 +40,18 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
* @test
|
||||
* @bug 8364733
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::fromPublisher` behavior
|
||||
* @build RecordingSubscriber
|
||||
* @run junit FromPublisherTest
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* ReplayTestSupport
|
||||
* @run junit ${test.main.class}
|
||||
*/
|
||||
|
||||
class FromPublisherTest {
|
||||
class FromPublisherTest extends ReplayTestSupport {
|
||||
|
||||
@Test
|
||||
void testNullPublisher() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.fromPublisher(null));
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.fromPublisher(null, 1));
|
||||
assertThrows(NullPointerException.class, () -> fromPublisher(null));
|
||||
assertThrows(NullPointerException.class, () -> fromPublisher(null, 1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ -54,7 +59,7 @@ class FromPublisherTest {
|
||||
void testInvalidContentLength(long contentLength) {
|
||||
IllegalArgumentException exception = assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> HttpRequest.BodyPublishers.fromPublisher(null, contentLength));
|
||||
() -> fromPublisher(null, contentLength));
|
||||
String exceptionMessage = exception.getMessage();
|
||||
assertTrue(
|
||||
exceptionMessage.contains("non-positive contentLength"),
|
||||
@ -64,29 +69,26 @@ class FromPublisherTest {
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = {1, 2, 3, 4})
|
||||
void testValidContentLength(long contentLength) {
|
||||
HttpRequest.BodyPublisher publisher =
|
||||
HttpRequest.BodyPublishers.fromPublisher(HttpRequest.BodyPublishers.noBody(), contentLength);
|
||||
BodyPublisher publisher = fromPublisher(noBody(), contentLength);
|
||||
assertEquals(contentLength, publisher.contentLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoContentLength() {
|
||||
HttpRequest.BodyPublisher publisher =
|
||||
HttpRequest.BodyPublishers.fromPublisher(HttpRequest.BodyPublishers.noBody());
|
||||
BodyPublisher publisher = fromPublisher(noBody());
|
||||
assertEquals(-1, publisher.contentLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullSubscriber() {
|
||||
HttpRequest.BodyPublisher publisher =
|
||||
HttpRequest.BodyPublishers.fromPublisher(HttpRequest.BodyPublishers.noBody());
|
||||
BodyPublisher publisher = fromPublisher(noBody());
|
||||
assertThrows(NullPointerException.class, () -> publisher.subscribe(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDelegation() throws InterruptedException {
|
||||
BlockingQueue<Object> publisherInvocations = new LinkedBlockingQueue<>();
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.fromPublisher(subscriber -> {
|
||||
BodyPublisher publisher = fromPublisher(subscriber -> {
|
||||
publisherInvocations.add("subscribe");
|
||||
publisherInvocations.add(subscriber);
|
||||
});
|
||||
@ -97,4 +99,13 @@ class FromPublisherTest {
|
||||
assertTrue(subscriber.invocations.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
byte[] content = ByteBufferUtils.byteArrayOfLength(10);
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(content);
|
||||
BodyPublisher delegatePublisher = ofByteArray(content);
|
||||
BodyPublisher publisher = fromPublisher(delegatePublisher, delegatePublisher.contentLength());
|
||||
return List.of(new ReplayTarget(expectedBuffer, publisher));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -23,7 +23,10 @@
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -32,17 +35,19 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
* @test
|
||||
* @bug 8364733
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::noBody` behavior
|
||||
* @build RecordingSubscriber
|
||||
* @run junit NoBodyTest
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* ReplayTestSupport
|
||||
* @run junit ${test.main.class}
|
||||
*/
|
||||
|
||||
class NoBodyTest {
|
||||
class NoBodyTest extends ReplayTestSupport {
|
||||
|
||||
@Test
|
||||
void test() throws InterruptedException {
|
||||
|
||||
// Create the publisher
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.noBody();
|
||||
BodyPublisher publisher = BodyPublishers.noBody();
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -54,4 +59,11 @@ class NoBodyTest {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(new byte[0]);
|
||||
BodyPublisher publisher = BodyPublishers.noBody();
|
||||
return List.of(new ReplayTarget(expectedBuffer, publisher));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -25,7 +25,8 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -39,30 +40,34 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
* @test
|
||||
* @bug 8364733
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::ofByteArray` behavior
|
||||
* @build RecordingSubscriber
|
||||
* @run junit OfByteArrayTest
|
||||
*
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* ReplayTestSupport
|
||||
*
|
||||
* @run junit ${test.main.class}
|
||||
*
|
||||
* @comment Using `main/othervm` to initiate tests that depend on a custom-configured JVM
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking "" 0 0 ""
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking a 0 0 ""
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking a 1 0 ""
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking a 0 1 a
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking ab 0 1 a
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking ab 1 1 b
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking ab 0 2 ab
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=1 OfByteArrayTest testChunking abc 0 3 a:b:c
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=2 OfByteArrayTest testChunking abc 0 3 ab:c
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=2 OfByteArrayTest testChunking abcdef 2 4 cd:ef
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking "" 0 0 ""
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking a 0 0 ""
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking a 1 0 ""
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking a 0 1 a
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking ab 0 1 a
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking ab 1 1 b
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=3 ${test.main.class} testChunking ab 0 2 ab
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=1 ${test.main.class} testChunking abc 0 3 a:b:c
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=2 ${test.main.class} testChunking abc 0 3 ab:c
|
||||
* @run main/othervm -Djdk.httpclient.bufsize=2 ${test.main.class} testChunking abcdef 2 4 cd:ef
|
||||
*/
|
||||
|
||||
public class OfByteArrayTest {
|
||||
public class OfByteArrayTest extends ReplayTestSupport {
|
||||
|
||||
private static final Charset CHARSET = StandardCharsets.US_ASCII;
|
||||
|
||||
@Test
|
||||
void testNullContent() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofByteArray(null));
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofByteArray(null, 1, 2));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofByteArray(null));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofByteArray(null, 1, 2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ -78,7 +83,15 @@ public class OfByteArrayTest {
|
||||
byte[] content = contentText.getBytes(CHARSET);
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> HttpRequest.BodyPublishers.ofByteArray(content, offset, length));
|
||||
() -> BodyPublishers.ofByteArray(content, offset, length));
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
byte[] content = "this content needs to be replayed again and again".getBytes(CHARSET);
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(content);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArray(content);
|
||||
return List.of(new ReplayTarget(expectedBuffer, publisher));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,7 +118,7 @@ public class OfByteArrayTest {
|
||||
|
||||
// Create the publisher
|
||||
byte[] content = contentText.getBytes(CHARSET);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArray(content, offset, length);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArray(content, offset, length);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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,8 @@ import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -46,15 +47,18 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
* @test
|
||||
* @bug 8226303 8364733
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::ofByteArrays` behavior
|
||||
*
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* ReplayTestSupport
|
||||
*
|
||||
* @run junit OfByteArraysTest
|
||||
*
|
||||
* @comment Using `main/othervm` to initiate tests that depend on a custom-configured JVM
|
||||
* @run main/othervm -Xmx64m OfByteArraysTest testOOM
|
||||
*/
|
||||
|
||||
public class OfByteArraysTest {
|
||||
public class OfByteArraysTest extends ReplayTestSupport {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1, 2, 3})
|
||||
@ -65,7 +69,7 @@ public class OfByteArraysTest {
|
||||
.range(0, length)
|
||||
.mapToObj(i -> new byte[]{(byte) i})
|
||||
.toList();
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(buffers::iterator);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(buffers::iterator);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -95,7 +99,7 @@ public class OfByteArraysTest {
|
||||
case 2 -> List.of(buffer2).iterator();
|
||||
default -> throw new AssertionError();
|
||||
};
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(iterable);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(iterable);
|
||||
|
||||
// Subscribe twice (to force two `Iterable::iterator` invocations)
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -112,14 +116,14 @@ public class OfByteArraysTest {
|
||||
|
||||
@Test
|
||||
void testNullIterable() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofByteArrays(null));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofByteArrays(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullIterator() throws InterruptedException {
|
||||
|
||||
// Create the publisher
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(() -> null);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(() -> null);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -138,7 +142,7 @@ public class OfByteArraysTest {
|
||||
// Create the publisher
|
||||
List<byte[]> iterable = new ArrayList<>();
|
||||
iterable.add(null);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(iterable);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(iterable);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -156,7 +160,7 @@ public class OfByteArraysTest {
|
||||
|
||||
// Create the publisher
|
||||
RuntimeException exception = new RuntimeException("failure for `testIteratorCreationException`");
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(() -> {
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(() -> {
|
||||
throw exception;
|
||||
});
|
||||
|
||||
@ -192,7 +196,7 @@ public class OfByteArraysTest {
|
||||
// Create the publisher
|
||||
IteratorThrowingAtEnd iterator =
|
||||
new IteratorThrowingAtEnd(exceptionIndex, hasNextException, nextException);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(() -> iterator);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(() -> iterator);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -257,6 +261,14 @@ public class OfByteArraysTest {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
byte[] byteArray = ByteBufferUtils.byteArrayOfLength(9);
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(byteArray);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(List.of(byteArray));
|
||||
return List.of(new ReplayTarget(expectedBuffer, -1, publisher, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates tests that depend on a custom-configured JVM.
|
||||
*/
|
||||
@ -273,7 +285,7 @@ public class OfByteArraysTest {
|
||||
// Create the publisher
|
||||
int length = ByteBufferUtils.findLengthExceedingMaxMemory();
|
||||
Iterable<byte[]> iterable = createIterableOfLength(length);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofByteArrays(iterable);
|
||||
BodyPublisher publisher = BodyPublishers.ofByteArrays(iterable);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -26,9 +26,12 @@
|
||||
* @summary Verifies `HttpRequest.BodyPublishers::ofFileChannel`
|
||||
* @library /test/lib
|
||||
* /test/jdk/java/net/httpclient/lib
|
||||
* @build jdk.httpclient.test.lib.common.HttpServerAdapters
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* ReplayTestSupport
|
||||
* jdk.httpclient.test.lib.common.HttpServerAdapters
|
||||
* jdk.test.lib.net.SimpleSSLContext
|
||||
* @run junit FileChannelPublisherTest
|
||||
* @run junit ${test.main.class}
|
||||
*/
|
||||
|
||||
import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler;
|
||||
@ -52,8 +55,10 @@ import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpClient.Version;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
@ -82,9 +87,9 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class FileChannelPublisherTest {
|
||||
class OfFileChannelTest extends ReplayTestSupport {
|
||||
|
||||
private static final String CLASS_NAME = FileChannelPublisherTest.class.getSimpleName();
|
||||
private static final String CLASS_NAME = OfFileChannelTest.class.getSimpleName();
|
||||
|
||||
private static final Logger LOGGER = Utils.getDebugLogger(CLASS_NAME::toString, Utils.DEBUG);
|
||||
|
||||
@ -650,6 +655,22 @@ class FileChannelPublisherTest {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
int fileLength = 42;
|
||||
byte[] fileBytes = generateFileBytes(fileLength);
|
||||
Path filePath = Path.of("replayTarget.txt");
|
||||
try {
|
||||
Files.write(filePath, fileBytes, StandardOpenOption.CREATE);
|
||||
FileChannel fileChannel = FileChannel.open(filePath);
|
||||
BodyPublisher publisher = BodyPublishers.ofFileChannel(fileChannel, 0, fileLength);
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(fileBytes);
|
||||
return List.of(new ReplayTarget(expectedBuffer, fileLength, publisher, fileChannel));
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the initial {@code HEAD} request to the specified server. This
|
||||
* effectively admits a connection to the client's pool, where all protocol
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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,8 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
@ -51,15 +52,18 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
* @test
|
||||
* @bug 8226303 8235459 8358688 8364733
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::ofFile` behavior
|
||||
*
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* @run junit OfFileTest
|
||||
* ReplayTestSupport
|
||||
*
|
||||
* @run junit ${test.main.class}
|
||||
*
|
||||
* @comment Using `main/othervm` to initiate tests that depend on a custom-configured JVM
|
||||
* @run main/othervm -Xmx64m OfFileTest testOOM
|
||||
* @run main/othervm -Xmx64m ${test.main.class} testOOM
|
||||
*/
|
||||
|
||||
public class OfFileTest {
|
||||
public class OfFileTest extends ReplayTestSupport {
|
||||
|
||||
private static final Path DEFAULT_FS_DIR = Path.of(System.getProperty("user.dir", "."));
|
||||
|
||||
@ -89,14 +93,14 @@ public class OfFileTest {
|
||||
|
||||
@Test
|
||||
void testNullPath() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofFile(null));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofFile(null));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parentDirs")
|
||||
void testNonExistentPath(Path parentDir) {
|
||||
Path nonExistentPath = createFilePath(parentDir, "testNonExistentPath");
|
||||
assertThrows(FileNotFoundException.class, () -> HttpRequest.BodyPublishers.ofFile(nonExistentPath));
|
||||
assertThrows(FileNotFoundException.class, () -> BodyPublishers.ofFile(nonExistentPath));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ -106,7 +110,7 @@ public class OfFileTest {
|
||||
// Create the publisher
|
||||
byte[] fileBytes = ByteBufferUtils.byteArrayOfLength(3);
|
||||
Path filePath = createFile(parentDir, "testNonExistentPathAtSubscribe", fileBytes);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofFile(filePath);
|
||||
BodyPublisher publisher = BodyPublishers.ofFile(filePath);
|
||||
|
||||
// Delete the file
|
||||
Files.delete(filePath);
|
||||
@ -131,7 +135,7 @@ public class OfFileTest {
|
||||
void testIrregularFile(Path parentDir) throws Exception {
|
||||
|
||||
// Create the publisher
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofFile(parentDir);
|
||||
BodyPublisher publisher = BodyPublishers.ofFile(parentDir);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -167,7 +171,7 @@ public class OfFileTest {
|
||||
// Create the publisher
|
||||
byte[] fileBytes = ByteBufferUtils.byteArrayOfLength(BIG_FILE_LENGTH);
|
||||
Path filePath = createFile(parentDir, "testFileModificationWhileReading", fileBytes);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofFile(filePath);
|
||||
BodyPublisher publisher = BodyPublishers.ofFile(filePath);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -210,7 +214,7 @@ public class OfFileTest {
|
||||
// Create the publisher
|
||||
byte[] fileBytes = ByteBufferUtils.byteArrayOfLength(fileLength);
|
||||
Path filePath = createFile(parentDir, "testFileOfLength", fileBytes);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofFile(filePath);
|
||||
BodyPublisher publisher = BodyPublishers.ofFile(filePath);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -222,6 +226,24 @@ public class OfFileTest {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
byte[] fileBytes = ByteBufferUtils.byteArrayOfLength(3);
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(fileBytes);
|
||||
return parentDirs()
|
||||
.stream()
|
||||
.map(parentDir -> {
|
||||
try {
|
||||
Path filePath = createFile(parentDir, "replayTest", fileBytes);
|
||||
BodyPublisher publisher = BodyPublishers.ofFile(filePath);
|
||||
return new ReplayTarget(expectedBuffer, publisher);
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates tests that depend on a custom-configured JVM.
|
||||
*/
|
||||
@ -248,7 +270,7 @@ public class OfFileTest {
|
||||
// Create the publisher
|
||||
int fileLength = ByteBufferUtils.findLengthExceedingMaxMemory();
|
||||
Path filePath = createFileOfLength(parentDir, "testOOM", fileLength);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofFile(filePath);
|
||||
BodyPublisher publisher = BodyPublishers.ofFile(filePath);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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,9 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.function.Supplier;
|
||||
@ -41,19 +43,22 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
* @test
|
||||
* @bug 8364733
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::ofInputStream` behavior
|
||||
*
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* @run junit OfInputStreamTest
|
||||
* ReplayTestSupport
|
||||
*
|
||||
* @run junit ${test.main.class}
|
||||
*
|
||||
* @comment Using `main/othervm` to initiate tests that depend on a custom-configured JVM
|
||||
* @run main/othervm -Xmx64m OfInputStreamTest testOOM
|
||||
* @run main/othervm -Xmx64m ${test.main.class} testOOM
|
||||
*/
|
||||
|
||||
public class OfInputStreamTest {
|
||||
public class OfInputStreamTest extends ReplayTestSupport {
|
||||
|
||||
@Test
|
||||
void testNullInputStreamSupplier() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofInputStream(null));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofInputStream(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -61,7 +66,7 @@ public class OfInputStreamTest {
|
||||
|
||||
// Create the publisher
|
||||
RuntimeException exception = new RuntimeException();
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofInputStream(() -> { throw exception; });
|
||||
BodyPublisher publisher = BodyPublishers.ofInputStream(() -> { throw exception; });
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -80,7 +85,7 @@ public class OfInputStreamTest {
|
||||
void testNullInputStream() throws InterruptedException {
|
||||
|
||||
// Create the publisher
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofInputStream(() -> null);
|
||||
BodyPublisher publisher = BodyPublishers.ofInputStream(() -> null);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -107,7 +112,7 @@ public class OfInputStreamTest {
|
||||
case 2 -> new ByteArrayInputStream(buffer2);
|
||||
default -> throw new AssertionError();
|
||||
};
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofInputStream(inputStreamSupplier);
|
||||
BodyPublisher publisher = BodyPublishers.ofInputStream(inputStreamSupplier);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -129,7 +134,7 @@ public class OfInputStreamTest {
|
||||
// Create the publisher
|
||||
byte[] content = ByteBufferUtils.byteArrayOfLength(length);
|
||||
InputStream inputStream = new ByteArrayInputStream(content);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofInputStream(() -> inputStream);
|
||||
BodyPublisher publisher = BodyPublishers.ofInputStream(() -> inputStream);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -148,7 +153,7 @@ public class OfInputStreamTest {
|
||||
// Create the publisher
|
||||
RuntimeException exception = new RuntimeException("failure for `read`");
|
||||
InputStream inputStream = new InputStreamThrowingOnCompletion(exceptionIndex, exception);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofInputStream(() -> inputStream);
|
||||
BodyPublisher publisher = BodyPublishers.ofInputStream(() -> inputStream);
|
||||
|
||||
// Subscribe
|
||||
RecordingSubscriber subscriber = new RecordingSubscriber();
|
||||
@ -185,6 +190,14 @@ public class OfInputStreamTest {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
byte[] content = ByteBufferUtils.byteArrayOfLength(10);
|
||||
ByteBuffer expectedBuffer = ByteBuffer.wrap(content);
|
||||
BodyPublisher publisher = BodyPublishers.ofInputStream(() -> new ByteArrayInputStream(content));
|
||||
return List.of(new ReplayTarget(expectedBuffer, -1, publisher, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates tests that depend on a custom-configured JVM.
|
||||
*/
|
||||
@ -200,8 +213,8 @@ public class OfInputStreamTest {
|
||||
|
||||
// Create the publisher using an `InputStream` that emits content exceeding the maximum memory
|
||||
int length = ByteBufferUtils.findLengthExceedingMaxMemory();
|
||||
HttpRequest.BodyPublisher publisher =
|
||||
HttpRequest.BodyPublishers.ofInputStream(() -> new InputStream() {
|
||||
BodyPublisher publisher =
|
||||
BodyPublishers.ofInputStream(() -> new InputStream() {
|
||||
|
||||
private int position;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, 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
|
||||
@ -26,10 +26,12 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -41,10 +43,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
* @summary Verify all specified `HttpRequest.BodyPublishers::ofString` behavior
|
||||
* @build ByteBufferUtils
|
||||
* RecordingSubscriber
|
||||
* @run junit OfStringTest
|
||||
* ReplayTestSupport
|
||||
* @run junit ${test.main.class}
|
||||
*/
|
||||
|
||||
class OfStringTest {
|
||||
class OfStringTest extends ReplayTestSupport {
|
||||
|
||||
private static final Charset CHARSET = StandardCharsets.US_ASCII;
|
||||
|
||||
@ -58,7 +61,7 @@ class OfStringTest {
|
||||
contentChars[i] = (char) ('a' + i);
|
||||
}
|
||||
String content = new String(contentChars);
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofString(content, CHARSET);
|
||||
BodyPublisher publisher = BodyPublishers.ofString(content, CHARSET);
|
||||
|
||||
// Subscribe
|
||||
assertEquals(length, publisher.contentLength());
|
||||
@ -87,7 +90,7 @@ class OfStringTest {
|
||||
void testCharset(String content, Charset charset) throws InterruptedException {
|
||||
|
||||
// Create the publisher
|
||||
HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofString(content, charset);
|
||||
BodyPublisher publisher = BodyPublishers.ofString(content, charset);
|
||||
|
||||
// Subscribe
|
||||
ByteBuffer expectedBuffer = charset.encode(content);
|
||||
@ -108,12 +111,20 @@ class OfStringTest {
|
||||
|
||||
@Test
|
||||
void testNullContent() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofString(null, CHARSET));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofString(null, CHARSET));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullCharset() {
|
||||
assertThrows(NullPointerException.class, () -> HttpRequest.BodyPublishers.ofString("foo", null));
|
||||
assertThrows(NullPointerException.class, () -> BodyPublishers.ofString("foo", null));
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterable<ReplayTarget> createReplayTargets() {
|
||||
String content = "this content needs to be replayed again and again";
|
||||
ByteBuffer expectedBuffer = CHARSET.encode(content);
|
||||
BodyPublisher publisher = BodyPublishers.ofString(content, CHARSET);
|
||||
return List.of(new ReplayTarget(expectedBuffer, publisher));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.net.http.HttpRequest.BodyPublisher;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Flow;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for verifying that a request body publisher supports multiple subscriptions, aka. replayable.
|
||||
*/
|
||||
public abstract class ReplayTestSupport {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
// 2 subscriptions
|
||||
"subscribe-cancel-subscribe-cancel",
|
||||
"subscribe-cancel-subscribe-request",
|
||||
"subscribe-request-subscribe-cancel",
|
||||
"subscribe-request-subscribe-request",
|
||||
// 3 subscriptions
|
||||
"subscribe-cancel-subscribe-cancel-subscribe-request",
|
||||
"subscribe-cancel-subscribe-request-subscribe-cancel",
|
||||
"subscribe-cancel-subscribe-request-subscribe-request",
|
||||
"subscribe-request-subscribe-cancel-subscribe-cancel",
|
||||
"subscribe-request-subscribe-cancel-subscribe-request",
|
||||
"subscribe-request-subscribe-request-subscribe-cancel",
|
||||
"subscribe-request-subscribe-request-subscribe-request",
|
||||
})
|
||||
void testReplay(String opSequence) throws Exception {
|
||||
for (ReplayTarget replayTarget : createReplayTargets()) {
|
||||
try (replayTarget) {
|
||||
System.err.printf("Executing test for replay target: %s%n", replayTarget);
|
||||
testReplay(opSequence, replayTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testReplay(String opSequence, ReplayTarget replayTarget) throws InterruptedException {
|
||||
|
||||
// Create the publisher
|
||||
ByteBuffer expectedBuffer = replayTarget.expectedBuffer;
|
||||
BodyPublisher publisher = replayTarget.publisher;
|
||||
assertEquals(replayTarget.expectedContentLength, publisher.contentLength());
|
||||
|
||||
// Execute the specified operations
|
||||
RecordingSubscriber subscriber = null;
|
||||
Flow.Subscription subscription = null;
|
||||
String[] ops = opSequence.split("-");
|
||||
for (int opIndex = 0; opIndex < ops.length; opIndex++) {
|
||||
String op = ops[opIndex];
|
||||
System.err.printf("Executing operation at index %s: %s%n", opIndex, op);
|
||||
switch (op) {
|
||||
|
||||
case "subscribe": {
|
||||
subscriber = new RecordingSubscriber();
|
||||
publisher.subscribe(subscriber);
|
||||
assertEquals("onSubscribe", subscriber.invocations.take());
|
||||
subscription = (Flow.Subscription) subscriber.invocations.take();
|
||||
break;
|
||||
}
|
||||
|
||||
case "request": {
|
||||
assert subscription != null;
|
||||
subscription.request(Long.MAX_VALUE);
|
||||
if (expectedBuffer.hasRemaining()) {
|
||||
assertEquals("onNext", subscriber.invocations.take());
|
||||
ByteBuffer actualBuffer = (ByteBuffer) subscriber.invocations.take();
|
||||
ByteBufferUtils.assertEquals(expectedBuffer, actualBuffer, null);
|
||||
}
|
||||
assertEquals("onComplete", subscriber.invocations.take());
|
||||
break;
|
||||
}
|
||||
|
||||
case "cancel": {
|
||||
assert subscription != null;
|
||||
subscription.cancel();
|
||||
break;
|
||||
}
|
||||
|
||||
default: throw new IllegalArgumentException("Unknown operation: " + op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract Iterable<ReplayTarget> createReplayTargets();
|
||||
|
||||
public record ReplayTarget(
|
||||
ByteBuffer expectedBuffer,
|
||||
int expectedContentLength,
|
||||
BodyPublisher publisher,
|
||||
AutoCloseable resource)
|
||||
implements AutoCloseable {
|
||||
|
||||
public ReplayTarget(ByteBuffer expectedBuffer, BodyPublisher publisher) {
|
||||
this(expectedBuffer, expectedBuffer.limit(), publisher, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (resource != null) {
|
||||
resource.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user