diff --git a/src/main/java/io/vertx/junit5/RunTestOnContext.java b/src/main/java/io/vertx/junit5/RunTestOnContext.java index cdb0207..7c07bdc 100644 --- a/src/main/java/io/vertx/junit5/RunTestOnContext.java +++ b/src/main/java/io/vertx/junit5/RunTestOnContext.java @@ -26,6 +26,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import static io.vertx.core.ThreadingModel.EVENT_LOOP; + /** * An extension that runs tests on a Vert.x context. *

@@ -44,23 +46,43 @@ public class RunTestOnContext implements BeforeAllCallback, InvocationIntercepto private final Supplier> supplier; private final Function> shutdown; + private ThreadingModel threadingModel = EVENT_LOOP; /** * Create an instance of this extension that builds a {@link Vertx} object using default options. */ public RunTestOnContext() { - this(new VertxOptions(), false); + this(new VertxOptions(), false, EVENT_LOOP); + } + + /** + * Create an instance of this extension that builds a {@link Vertx} object using default options. + * + * @param threadingModel the threading model used to run the test + */ + public RunTestOnContext(ThreadingModel threadingModel) { + this(new VertxOptions(), false, threadingModel); } /** * Create an instance of this extension that builds a {@link Vertx} object using the specified {@code options}. - *

- * When the options hold a {@link io.vertx.core.spi.cluster.ClusterManager} instance, a clustered {@link Vertx} object is created. * * @param options the vertx options + * @param clustered indicate if a clustered {@link Vertx} object will be created */ public RunTestOnContext(VertxOptions options, boolean clustered) { - this(() -> clustered ? Vertx.clusteredVertx(options) : Future.succeededFuture(Vertx.vertx(options))); + this(() -> clustered ? Vertx.clusteredVertx(options) : Future.succeededFuture(Vertx.vertx(options)), EVENT_LOOP); + } + + /** + * Create an instance of this extension that builds a {@link Vertx} object using the specified {@code options}. + * + * @param options the vertx options + * @param clustered indicate if a clustered {@link Vertx} object will be created + * @param threadingModel the threading model used to run the test + */ + public RunTestOnContext(VertxOptions options, boolean clustered, ThreadingModel threadingModel) { + this(() -> clustered ? Vertx.clusteredVertx(options) : Future.succeededFuture(Vertx.vertx(options)), threadingModel); } /** @@ -69,7 +91,17 @@ public RunTestOnContext(VertxOptions options, boolean clustered) { * @param supplier the asynchronous supplier */ public RunTestOnContext(Supplier> supplier) { - this(supplier, Vertx::close); + this(supplier, Vertx::close, EVENT_LOOP); + } + + /** + * Create an instance of this extension that gets a {@link Vertx} object using the specified asynchronous {@code supplier}. + * + * @param supplier the asynchronous supplier + * @param threadingModel the threading model used to run the test + */ + public RunTestOnContext(Supplier> supplier, ThreadingModel threadingModel) { + this(supplier, Vertx::close, threadingModel); } /** @@ -84,6 +116,20 @@ public RunTestOnContext(Supplier> supplier, Function> supplier, Function> shutdown, ThreadingModel threadingModel) { + this.supplier = supplier; + this.shutdown = shutdown; + this.threadingModel = threadingModel; + } + /** * @return the current Vert.x instance */ @@ -143,7 +189,11 @@ private T runOnContext(Invocation invocation) throws Throwable { } else { vertxFuture = supplier.get().onSuccess(vertx -> { this.vertx = vertx; - context = ((VertxInternal) vertx).createEventLoopContext(); + if (ThreadingModel.VIRTUAL_THREAD.equals(this.threadingModel)) { + context = ((VertxInternal) vertx).createVirtualThreadContext(); + } else { + context = ((VertxInternal) vertx).createEventLoopContext(); + } }); } CompletableFuture cf = vertxFuture diff --git a/src/test/java/io/vertx/junit5/tests/CustomizedRunOnContextExtensionTest.java b/src/test/java/io/vertx/junit5/tests/CustomizedRunOnContextExtensionTest.java index cf13287..ac672fd 100644 --- a/src/test/java/io/vertx/junit5/tests/CustomizedRunOnContextExtensionTest.java +++ b/src/test/java/io/vertx/junit5/tests/CustomizedRunOnContextExtensionTest.java @@ -18,6 +18,7 @@ import io.vertx.core.Context; import io.vertx.core.Future; +import io.vertx.core.ThreadingModel; import io.vertx.core.Vertx; import io.vertx.junit5.RunTestOnContext; import org.junit.jupiter.api.AfterAll; @@ -43,7 +44,7 @@ public class CustomizedRunOnContextExtensionTest { destroyMethodInvocations.incrementAndGet(); assertSame(expectedVertx, vertx); return vertx.close(); - }); + }, ThreadingModel.EVENT_LOOP); @BeforeEach void beforeTest() { diff --git a/src/test/java/io/vertx/junit5/tests/RunOnContextExtensionThreadingModelTest.java b/src/test/java/io/vertx/junit5/tests/RunOnContextExtensionThreadingModelTest.java new file mode 100644 index 0000000..7b3f814 --- /dev/null +++ b/src/test/java/io/vertx/junit5/tests/RunOnContextExtensionThreadingModelTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.vertx.junit5.tests; + +import io.vertx.core.Context; +import io.vertx.core.ThreadingModel; +import io.vertx.core.Vertx; +import io.vertx.junit5.RunTestOnContext; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.concurrent.atomic.AtomicReference; + +import static io.vertx.junit5.tests.StaticRunOnContextExtensionTest.checkContext; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +public class RunOnContextExtensionThreadingModelTest { + + @RegisterExtension + RunTestOnContext testOnContext = new RunTestOnContext(ThreadingModel.VIRTUAL_THREAD); + + AtomicReference ctxRef = new AtomicReference<>(); + + @BeforeAll + static void beforeAll() { + assertNull(Vertx.currentContext()); + } + + public RunOnContextExtensionThreadingModelTest() { + assertNull(Vertx.currentContext()); + } + + @BeforeEach + void beforeTest() { + Context ctx = Vertx.currentContext(); + assertNotNull(ctx); + assertSame(ctx.owner(), testOnContext.vertx()); + assertNotSame(ctx, ctxRef.getAndSet(ctx)); + } + + @Test + void testMethod1() { + checkContext(testOnContext.vertx(), ctxRef.get()); + } + + @Test + void testMethod2() { + checkContext(testOnContext.vertx(), ctxRef.get()); + } + + @AfterEach + void tearDown() { + checkContext(testOnContext.vertx(), ctxRef.get()); + } + + @AfterAll + static void afterAll() { + assertNull(Vertx.currentContext()); + } +}