From 49d2754b2b2e89c84463b4c912e58d58fda5e6ef Mon Sep 17 00:00:00 2001 From: Julien Viet Date: Wed, 18 Sep 2024 10:16:19 +0200 Subject: [PATCH] Expose some of the implementation to internals required by MQTT. Also update the tests jar for more reusability in projects relying on it for their testing. --- .../src/main/java/io/vertx/core/MultiMap.java | 2 +- .../datagram/impl/DatagramSocketImpl.java | 6 +-- .../http/impl/Http1xClientConnection.java | 2 +- .../http/impl/Http1xServerConnection.java | 2 +- .../http/impl/headers/HeadersMultiMap.java | 6 +-- .../core/internal/buffer/BufferInternal.java | 12 +++++ .../internal/http/HttpHeadersInternal.java | 37 +++++++++++++++ .../io/vertx/core/net/impl/NetSocketImpl.java | 4 +- .../io/vertx/core/net/impl/VertxHandler.java | 26 ++++------ vertx-core/src/main/java/module-info.java | 42 ++++++++--------- .../core/FileDescriptorLeakDetectorRule.java | 4 +- .../io/vertx/test/core/VertxTestBase.java | 3 ++ .../eventbus/CustomNodeSelectorTest.java | 5 +- .../MessageQueueOnWorkerThreadTest.java | 3 +- .../WriteHandlerLookupFailureTest.java | 6 ++- .../tests/metrics/MetricsContextTest.java | 2 + .../vertx/tests/vertx/VertxBootstrapTest.java | 1 + vertx-core/src/test/java/module-info.java | 47 +++++++++++++------ 18 files changed, 140 insertions(+), 70 deletions(-) create mode 100644 vertx-core/src/main/java/io/vertx/core/internal/http/HttpHeadersInternal.java diff --git a/vertx-core/src/main/java/io/vertx/core/MultiMap.java b/vertx-core/src/main/java/io/vertx/core/MultiMap.java index 65b020956f9..2b6d9c2b556 100644 --- a/vertx-core/src/main/java/io/vertx/core/MultiMap.java +++ b/vertx-core/src/main/java/io/vertx/core/MultiMap.java @@ -43,7 +43,7 @@ public interface MultiMap extends Iterable> { * @return the multi-map */ static MultiMap caseInsensitiveMultiMap() { - return HeadersMultiMap.headers(); + return HeadersMultiMap.caseInsensitive(); } @GenIgnore(GenIgnore.PERMITTED_TYPE) diff --git a/vertx-core/src/main/java/io/vertx/core/datagram/impl/DatagramSocketImpl.java b/vertx-core/src/main/java/io/vertx/core/datagram/impl/DatagramSocketImpl.java index c4b82ccdbe3..2a014ed69ad 100644 --- a/vertx-core/src/main/java/io/vertx/core/datagram/impl/DatagramSocketImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/datagram/impl/DatagramSocketImpl.java @@ -378,10 +378,8 @@ public void handleMessage(Object msg) { if (msg instanceof DatagramPacket) { DatagramPacket packet = (DatagramPacket) msg; ByteBuf content = packet.content(); - if (content.isDirect()) { - content = VertxHandler.safeBuffer(content); - } - handlePacket(new DatagramPacketImpl(packet.sender(), BufferInternal.buffer(content))); + Buffer buffer = BufferInternal.safeBuffer(content); + handlePacket(new DatagramPacketImpl(packet.sender(), buffer)); } } diff --git a/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java b/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java index 55468727faa..a92a076409c 100644 --- a/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java +++ b/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java @@ -858,7 +858,7 @@ private void removeChannelHandlers() { } private void handleResponseChunk(Stream stream, ByteBuf chunk) { - Buffer buff = BufferInternal.buffer(VertxHandler.safeBuffer(chunk)); + Buffer buff = BufferInternal.safeBuffer(chunk); int len = buff.length(); stream.bytesRead += len; stream.handleChunk(buff); diff --git a/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java b/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java index 959f0e7ccc7..274cd1f4288 100644 --- a/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java +++ b/vertx-core/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java @@ -180,7 +180,7 @@ private void onContent(Object msg) { handleError(content); return; } - Buffer buffer = BufferInternal.buffer(VertxHandler.safeBuffer(content.content())); + Buffer buffer = BufferInternal.safeBuffer(content.content()); Http1xServerRequest request = requestInProgress; request.handleContent(buffer); //TODO chunk trailers diff --git a/vertx-core/src/main/java/io/vertx/core/http/impl/headers/HeadersMultiMap.java b/vertx-core/src/main/java/io/vertx/core/http/impl/headers/HeadersMultiMap.java index 47dfe2c0a94..bed07b1fd8d 100644 --- a/vertx-core/src/main/java/io/vertx/core/http/impl/headers/HeadersMultiMap.java +++ b/vertx-core/src/main/java/io/vertx/core/http/impl/headers/HeadersMultiMap.java @@ -68,16 +68,16 @@ private static CharSequence toValidCharSequence(Object value) { } /** - * @return a case insensitive multi-map suited for HTTP header validation + * @return a case-insensitive multimap suited for HTTP header validation */ public static HeadersMultiMap httpHeaders() { return new HeadersMultiMap(HTTP_VALIDATOR); } /** - * @return a all-purpose case insensitive multi-map that does not perform validation + * @return a all-purpose case-insensitive multimap that does not perform validation */ - public static HeadersMultiMap headers() { + public static HeadersMultiMap caseInsensitive() { return new HeadersMultiMap(); } diff --git a/vertx-core/src/main/java/io/vertx/core/internal/buffer/BufferInternal.java b/vertx-core/src/main/java/io/vertx/core/internal/buffer/BufferInternal.java index 16f4f7cf091..a5e41944a9a 100644 --- a/vertx-core/src/main/java/io/vertx/core/internal/buffer/BufferInternal.java +++ b/vertx-core/src/main/java/io/vertx/core/internal/buffer/BufferInternal.java @@ -3,12 +3,24 @@ import io.netty.buffer.ByteBuf; import io.vertx.core.buffer.Buffer; import io.vertx.core.buffer.impl.BufferImpl; +import io.vertx.core.net.impl.VertxHandler; import java.nio.ByteBuffer; import java.util.Objects; public interface BufferInternal extends Buffer { + /** + * Create a new Vert.x buffer from a Netty {@code ByteBuf}. Pooled {@code byteBuf} are copied and released, + * otherwise it is wrapped. + * + * @param byteBuf the buffer + * @return a Vert.x buffer to use + */ + static BufferInternal safeBuffer(ByteBuf byteBuf) { + return buffer(VertxHandler.safeBuffer(byteBuf)); + } + /** *

* Create a new buffer from a Netty {@code ByteBuf}. diff --git a/vertx-core/src/main/java/io/vertx/core/internal/http/HttpHeadersInternal.java b/vertx-core/src/main/java/io/vertx/core/internal/http/HttpHeadersInternal.java new file mode 100644 index 00000000000..e2c9ec43888 --- /dev/null +++ b/vertx-core/src/main/java/io/vertx/core/internal/http/HttpHeadersInternal.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + */ +package io.vertx.core.internal.http; + +import io.netty.handler.codec.http2.Http2Headers; +import io.vertx.core.MultiMap; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.impl.headers.HeadersAdaptor; +import io.vertx.core.http.impl.headers.Http2HeadersAdaptor; + +/** + * HTTP multimap implementations. + */ +public interface HttpHeadersInternal extends HttpHeaders { + + /** + * @return a multimap wrapping Netty HTTP {code header} instance + */ + static MultiMap headers(io.netty.handler.codec.http.HttpHeaders headers) { + return new HeadersAdaptor(headers); + } + + /** + * @return a multimap wrapping Netty HTTP/2 {code header} instance + */ + static MultiMap headers(Http2Headers headers) { + return new Http2HeadersAdaptor(headers); + } +} diff --git a/vertx-core/src/main/java/io/vertx/core/net/impl/NetSocketImpl.java b/vertx-core/src/main/java/io/vertx/core/net/impl/NetSocketImpl.java index bc98edd6b61..cd9d251113e 100644 --- a/vertx-core/src/main/java/io/vertx/core/net/impl/NetSocketImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/net/impl/NetSocketImpl.java @@ -393,9 +393,7 @@ private class DataMessageHandler implements Handler { @Override public void handle(Object msg) { if (msg instanceof ByteBuf) { - msg = VertxHandler.safeBuffer((ByteBuf) msg); - ByteBuf byteBuf = (ByteBuf) msg; - Buffer buffer = BufferInternal.buffer(byteBuf); + Buffer buffer = BufferInternal.safeBuffer((ByteBuf) msg); pending.write(buffer); } else { handleInvalid(msg); diff --git a/vertx-core/src/main/java/io/vertx/core/net/impl/VertxHandler.java b/vertx-core/src/main/java/io/vertx/core/net/impl/VertxHandler.java index 12585e3020e..728f03231ff 100644 --- a/vertx-core/src/main/java/io/vertx/core/net/impl/VertxHandler.java +++ b/vertx-core/src/main/java/io/vertx/core/net/impl/VertxHandler.java @@ -43,32 +43,26 @@ private VertxHandler(Function connectionFactory) { } /** - * Copy and release the {@code buf} when necessary. + * Pooled {@code byteBuf} are copied and released, otherwise it is returned as is. * - *

This methods assuming the has full ownership of the buffer. - * - *

This method assumes that pooled buffers are allocated by {@code PooledByteBufAllocator} - * - *

The returned buffer will not need to be released and can be wrapped by a {@link io.vertx.core.buffer.Buffer}. - * - * @param buf the buffer - * @return a safe buffer to use + * @param byteBuf the buffer + * @return a buffer safe */ - public static ByteBuf safeBuffer(ByteBuf buf) { - if (buf != Unpooled.EMPTY_BUFFER && (buf.alloc() instanceof PooledByteBufAllocator || buf instanceof CompositeByteBuf)) { + public static ByteBuf safeBuffer(ByteBuf byteBuf) { + if (byteBuf != Unpooled.EMPTY_BUFFER && (byteBuf.alloc() instanceof PooledByteBufAllocator || byteBuf instanceof CompositeByteBuf)) { try { - if (buf.isReadable()) { - ByteBuf buffer = VertxByteBufAllocator.DEFAULT.heapBuffer(buf.readableBytes()); - buffer.writeBytes(buf, buf.readerIndex(), buf.readableBytes()); + if (byteBuf.isReadable()) { + ByteBuf buffer = VertxByteBufAllocator.DEFAULT.heapBuffer(byteBuf.readableBytes()); + buffer.writeBytes(byteBuf, byteBuf.readerIndex(), byteBuf.readableBytes()); return buffer; } else { return Unpooled.EMPTY_BUFFER; } } finally { - buf.release(); + byteBuf.release(); } } - return buf; + return byteBuf; } /** diff --git a/vertx-core/src/main/java/module-info.java b/vertx-core/src/main/java/module-info.java index 17910304da2..45f58c61515 100644 --- a/vertx-core/src/main/java/module-info.java +++ b/vertx-core/src/main/java/module-info.java @@ -94,26 +94,26 @@ // Testing - exports io.vertx.core.impl to io.vertx.tests; - exports io.vertx.core.impl.cpu to io.vertx.tests; - exports io.vertx.core.impl.future to io.vertx.tests; - exports io.vertx.core.impl.utils to io.vertx.tests; - exports io.vertx.core.net.impl to io.vertx.tests; - exports io.vertx.core.shareddata.impl to io.vertx.tests; - exports io.vertx.core.buffer.impl to io.vertx.tests; - exports io.vertx.core.streams.impl to io.vertx.tests; - exports io.vertx.core.eventbus.impl to io.vertx.tests; - exports io.vertx.core.eventbus.impl.clustered to io.vertx.tests; - exports io.vertx.core.spi.cluster.impl to io.vertx.tests; - exports io.vertx.core.file.impl to io.vertx.tests; - exports io.vertx.core.http.impl to io.vertx.tests; - exports io.vertx.core.http.impl.headers to io.vertx.tests; - exports io.vertx.core.http.impl.ws to io.vertx.tests; - exports io.vertx.core.json.pointer.impl to io.vertx.tests; - exports io.vertx.core.impl.transports to io.vertx.tests; - exports io.vertx.core.net.impl.pkcs1 to io.vertx.tests; - exports io.vertx.core.spi.cluster.impl.selector to io.vertx.tests; - exports io.vertx.core.impl.verticle to io.vertx.tests; - exports io.vertx.core.impl.deployment to io.vertx.tests; + exports io.vertx.core.impl to io.vertx.core.tests; + exports io.vertx.core.impl.cpu to io.vertx.core.tests; + exports io.vertx.core.impl.future to io.vertx.core.tests; + exports io.vertx.core.impl.utils to io.vertx.core.tests; + exports io.vertx.core.net.impl to io.vertx.core.tests; + exports io.vertx.core.shareddata.impl to io.vertx.core.tests; + exports io.vertx.core.buffer.impl to io.vertx.core.tests; + exports io.vertx.core.streams.impl to io.vertx.core.tests; + exports io.vertx.core.eventbus.impl to io.vertx.core.tests; + exports io.vertx.core.eventbus.impl.clustered to io.vertx.core.tests; + exports io.vertx.core.spi.cluster.impl to io.vertx.core.tests; + exports io.vertx.core.file.impl to io.vertx.core.tests; + exports io.vertx.core.http.impl to io.vertx.core.tests; + exports io.vertx.core.http.impl.headers to io.vertx.core.tests; + exports io.vertx.core.http.impl.ws to io.vertx.core.tests; + exports io.vertx.core.json.pointer.impl to io.vertx.core.tests; + exports io.vertx.core.impl.transports to io.vertx.core.tests; + exports io.vertx.core.net.impl.pkcs1 to io.vertx.core.tests; + exports io.vertx.core.spi.cluster.impl.selector to io.vertx.core.tests; + exports io.vertx.core.impl.verticle to io.vertx.core.tests; + exports io.vertx.core.impl.deployment to io.vertx.core.tests; } diff --git a/vertx-core/src/test/java/io/vertx/test/core/FileDescriptorLeakDetectorRule.java b/vertx-core/src/test/java/io/vertx/test/core/FileDescriptorLeakDetectorRule.java index d079df54d72..bc77a8562dc 100644 --- a/vertx-core/src/test/java/io/vertx/test/core/FileDescriptorLeakDetectorRule.java +++ b/vertx-core/src/test/java/io/vertx/test/core/FileDescriptorLeakDetectorRule.java @@ -25,7 +25,7 @@ import java.util.List; import java.util.stream.Stream; -import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; public class FileDescriptorLeakDetectorRule implements TestRule { @@ -93,7 +93,7 @@ public void evaluate() throws Throwable { long averageEvaluations = getAverage(iterations); System.out.println("*** Open file descriptor open file descriptors average " + averageEvaluations); - assertThat(averageEvaluations).isLessThanOrEqualTo(maxBaseLine); + assertTrue(averageEvaluations <= maxBaseLine); } }; } diff --git a/vertx-core/src/test/java/io/vertx/test/core/VertxTestBase.java b/vertx-core/src/test/java/io/vertx/test/core/VertxTestBase.java index e8209c052dc..c8f39f03fe7 100644 --- a/vertx-core/src/test/java/io/vertx/test/core/VertxTestBase.java +++ b/vertx-core/src/test/java/io/vertx/test/core/VertxTestBase.java @@ -175,6 +175,9 @@ protected Future clusteredVertx(VertxOptions options, ClusterManager clus if (created == null) { created = Collections.synchronizedList(new ArrayList<>()); } + if (clusterManager == null) { + clusterManager = new FakeClusterManager(); + } return createVertxBuilder(options) .withClusterManager(clusterManager) .buildClustered().andThen(event -> { diff --git a/vertx-core/src/test/java/io/vertx/tests/eventbus/CustomNodeSelectorTest.java b/vertx-core/src/test/java/io/vertx/tests/eventbus/CustomNodeSelectorTest.java index 6217fdc2465..f3ba654e9ed 100644 --- a/vertx-core/src/test/java/io/vertx/tests/eventbus/CustomNodeSelectorTest.java +++ b/vertx-core/src/test/java/io/vertx/tests/eventbus/CustomNodeSelectorTest.java @@ -20,6 +20,7 @@ import io.vertx.core.spi.cluster.NodeInfo; import io.vertx.core.spi.cluster.impl.NodeSelector; import io.vertx.test.core.VertxTestBase; +import io.vertx.test.fakecluster.FakeClusterManager; import org.junit.Test; import java.util.*; @@ -45,7 +46,9 @@ public void test() throws Exception { return vertxOptions; }) .map(options -> { - VertxBootstrap factory = ((VertxBootstrapImpl)VertxBootstrap.create().options(options).init()).clusterNodeSelector(new CustomNodeSelector()); + VertxBootstrap factory = ((VertxBootstrapImpl)VertxBootstrap.create().options(options).init()) + .clusterManager(new FakeClusterManager()) + .clusterNodeSelector(new CustomNodeSelector()); return factory.clusteredVertx(); }) .collect(collectingAndThen(toList(), Future::all)); diff --git a/vertx-core/src/test/java/io/vertx/tests/eventbus/MessageQueueOnWorkerThreadTest.java b/vertx-core/src/test/java/io/vertx/tests/eventbus/MessageQueueOnWorkerThreadTest.java index ce0a98998f8..afc87b2244b 100644 --- a/vertx-core/src/test/java/io/vertx/tests/eventbus/MessageQueueOnWorkerThreadTest.java +++ b/vertx-core/src/test/java/io/vertx/tests/eventbus/MessageQueueOnWorkerThreadTest.java @@ -17,6 +17,7 @@ import io.vertx.core.spi.cluster.ClusterManager; import io.vertx.core.spi.cluster.impl.NodeSelector; import io.vertx.test.core.VertxTestBase; +import io.vertx.test.fakecluster.FakeClusterManager; import org.junit.Test; import java.util.Collections; @@ -37,7 +38,7 @@ public class MessageQueueOnWorkerThreadTest extends VertxTestBase { public void setUp() throws Exception { super.setUp(); CustomNodeSelector selector = new CustomNodeSelector(); - VertxBootstrapImpl factory = new VertxBootstrapImpl().init().clusterNodeSelector(selector); + VertxBootstrapImpl factory = new VertxBootstrapImpl().init().clusterManager(new FakeClusterManager()).clusterNodeSelector(selector); Future fut = factory.clusteredVertx(); vertx = fut.await(); } diff --git a/vertx-core/src/test/java/io/vertx/tests/eventbus/WriteHandlerLookupFailureTest.java b/vertx-core/src/test/java/io/vertx/tests/eventbus/WriteHandlerLookupFailureTest.java index 65126a0e4b8..5adf4d92d09 100644 --- a/vertx-core/src/test/java/io/vertx/tests/eventbus/WriteHandlerLookupFailureTest.java +++ b/vertx-core/src/test/java/io/vertx/tests/eventbus/WriteHandlerLookupFailureTest.java @@ -20,6 +20,7 @@ import io.vertx.core.spi.cluster.impl.NodeSelector; import io.vertx.core.spi.cluster.impl.DefaultNodeSelector; import io.vertx.test.core.VertxTestBase; +import io.vertx.test.fakecluster.FakeClusterManager; import org.junit.Test; import java.util.Collections; @@ -49,7 +50,10 @@ public void selectForPublish(String address, Promise> promise) promise.fail("Not implemented"); } }; - ((VertxBootstrapImpl)VertxBootstrap.create().options(options).init()).clusterNodeSelector(nodeSelector).clusteredVertx().onComplete(onSuccess(node -> { + ((VertxBootstrapImpl)VertxBootstrap.create().options(options).init()) + .clusterManager(new FakeClusterManager()) + .clusterNodeSelector(nodeSelector) + .clusteredVertx().onComplete(onSuccess(node -> { vertx = node; MessageProducer sender = vertx.eventBus().sender("foo"); sender.write("the_string").onComplete(onFailure(err -> { diff --git a/vertx-core/src/test/java/io/vertx/tests/metrics/MetricsContextTest.java b/vertx-core/src/test/java/io/vertx/tests/metrics/MetricsContextTest.java index 56bae9e8ccb..26f2f91f824 100644 --- a/vertx-core/src/test/java/io/vertx/tests/metrics/MetricsContextTest.java +++ b/vertx-core/src/test/java/io/vertx/tests/metrics/MetricsContextTest.java @@ -27,6 +27,7 @@ import io.vertx.core.spi.observability.HttpResponse; import io.vertx.test.core.TestUtils; import io.vertx.test.core.VertxTestBase; +import io.vertx.test.fakecluster.FakeClusterManager; import io.vertx.test.http.HttpTestBase; import org.junit.Ignore; import org.junit.Test; @@ -77,6 +78,7 @@ public void testFactoryInCluster() throws Exception { .withClusterManager(getClusterManager()) .withMetrics(factory); builder + .withClusterManager(new FakeClusterManager()) .buildClustered() .onComplete(onSuccess(vertx -> { assertSame(testThread, metricsThread.get()); diff --git a/vertx-core/src/test/java/io/vertx/tests/vertx/VertxBootstrapTest.java b/vertx-core/src/test/java/io/vertx/tests/vertx/VertxBootstrapTest.java index e25fdc5a468..5f071381574 100644 --- a/vertx-core/src/test/java/io/vertx/tests/vertx/VertxBootstrapTest.java +++ b/vertx-core/src/test/java/io/vertx/tests/vertx/VertxBootstrapTest.java @@ -63,6 +63,7 @@ public void testCreateClustered() throws Exception { VertxBootstrap factory = VertxBootstrap.create().init(); CompletableFuture fut = new CompletableFuture<>(); factory.init(); + factory.clusterManager(new FakeClusterManager()); factory.clusteredVertx().onComplete(ar -> { if (ar.succeeded()) { fut.complete(ar.result()); diff --git a/vertx-core/src/test/java/module-info.java b/vertx-core/src/test/java/module-info.java index 9494b45ea51..302313f20c0 100644 --- a/vertx-core/src/test/java/module-info.java +++ b/vertx-core/src/test/java/module-info.java @@ -1,27 +1,34 @@ import io.vertx.core.spi.VerticleFactory; -import io.vertx.core.spi.VertxServiceProvider; -import io.vertx.test.fakecluster.FakeClusterManager; import io.vertx.tests.deployment.ClasspathVerticleFactory; -open module io.vertx.tests { +open module io.vertx.core.tests { + requires io.vertx.codegen.api; requires io.vertx.core; requires io.vertx.core.logging; - requires assertj.core; - requires org.hamcrest; + + requires static assertj.core; + requires static org.hamcrest; + requires junit; requires java.management; requires java.logging; requires org.slf4j; - requires apacheds.protocol.dns; - requires apacheds.i18n; - requires mina.core; - requires apacheds.protocol.shared; - requires com.fasterxml.jackson.annotation; - requires com.fasterxml.jackson.core; - requires com.fasterxml.jackson.databind; + requires static apacheds.protocol.dns; + requires static apacheds.i18n; + requires static mina.core; + requires static apacheds.protocol.shared; + + requires static org.apache.logging.log4j.core; + + requires static jmh.core; + + requires transitive com.fasterxml.jackson.core; + requires static com.fasterxml.jackson.annotation; + requires static com.fasterxml.jackson.databind; + requires io.netty.common; requires io.netty.buffer; requires io.netty.transport; @@ -32,10 +39,20 @@ requires io.netty.codec.haproxy; requires io.netty.codec.http2; requires io.netty.resolver.dns; - requires jmh.core; - requires org.apache.logging.log4j.core; - provides VertxServiceProvider with FakeClusterManager; provides VerticleFactory with ClasspathVerticleFactory, io.vertx.tests.vertx.AccessEventBusFromInitVerticleFactory; + exports io.vertx.test.core; + exports io.vertx.test.fakecluster; + exports io.vertx.test.fakedns; + exports io.vertx.test.fakeloadbalancer; + exports io.vertx.test.fakemetrics; + exports io.vertx.test.fakeresolver; + exports io.vertx.test.fakestream; + exports io.vertx.test.faketracer; + exports io.vertx.test.http; + exports io.vertx.test.netty; + exports io.vertx.test.proxy; + exports io.vertx.test.tls; + }