@@ -52,4 +54,18 @@
* @return whether to reset container per test method
*/
boolean resetPerTest() default false;
+
+ /**
+ * Time threshold for carrier thread blocking to be considered as pinning.
+ *
+ * @return threshold in milliseconds, {@code 20} is default
+ */
+ long pinningThreshold() default DEFAULT_THRESHOLD;
+
+ /**
+ * Whether to turn on pinning detection during {@code @HelidonTest}.
+ *
+ * @return true for turning detection on, {@code false} is default
+ */
+ boolean pinningDetection() default false;
}
diff --git a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/PinnedThreadValidation.java b/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/PinnedThreadValidation.java
deleted file mode 100644
index 49f3a2f6fde..00000000000
--- a/microprofile/testing/junit5/src/main/java/io/helidon/microprofile/testing/junit5/PinnedThreadValidation.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2024 Oracle and/or its affiliates.
- *
- * 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.helidon.microprofile.testing.junit5;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.junit.jupiter.api.extension.ExtendWith;
-
-/**
- * An annotation making this test class to fail at the end if a pinned virtual thread was detected.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-@ExtendWith(HelidonPinnedThreadValidationJunitExtension.class)
-@Inherited
-public @interface PinnedThreadValidation {
-}
diff --git a/microprofile/testing/junit5/src/main/java/module-info.java b/microprofile/testing/junit5/src/main/java/module-info.java
index e20192d5d8a..398fc045b50 100644
--- a/microprofile/testing/junit5/src/main/java/module-info.java
+++ b/microprofile/testing/junit5/src/main/java/module-info.java
@@ -24,7 +24,6 @@
requires io.helidon.microprofile.cdi;
requires jakarta.inject;
requires org.junit.jupiter.api;
- requires jdk.jfr;
requires transitive jakarta.cdi;
requires transitive jakarta.ws.rs;
@@ -32,6 +31,7 @@
requires static io.helidon.microprofile.server;
requires static jersey.cdi1x;
requires static jersey.weld2.se;
+ requires io.helidon.common.testing.vitualthreads;
exports io.helidon.microprofile.testing.junit5;
diff --git a/microprofile/testing/testng/pom.xml b/microprofile/testing/testng/pom.xml
index 9f781af4fc2..f33097c9eba 100644
--- a/microprofile/testing/testng/pom.xml
+++ b/microprofile/testing/testng/pom.xml
@@ -38,6 +38,10 @@
@@ -48,4 +50,18 @@
* @return whether to reset container per test method
*/
boolean resetPerTest() default false;
+
+ /**
+ * Time threshold for carrier thread blocking to be considered as pinning.
+ *
+ * @return threshold in milliseconds, {@code 20} is default
+ */
+ long pinningThreshold() default DEFAULT_THRESHOLD;
+
+ /**
+ * Whether to turn on pinning detection during {@code @HelidonTest}.
+ *
+ * @return true for turning detection on, {@code false} is default
+ */
+ boolean pinningDetection() default false;
}
diff --git a/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java b/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java
index 66248244198..27f6049ec89 100644
--- a/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java
+++ b/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java
@@ -26,6 +26,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -36,6 +37,7 @@
import java.util.Set;
import java.util.stream.Collectors;
+import io.helidon.common.testing.virtualthreads.PinningRecorder;
import io.helidon.config.mp.MpConfigSources;
import io.helidon.microprofile.server.JaxRsCdiExtension;
import io.helidon.microprofile.server.ServerCdiExtension;
@@ -59,8 +61,6 @@
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.ws.rs.client.ClientBuilder;
-import jdk.jfr.consumer.RecordedEvent;
-import jdk.jfr.consumer.RecordingStream;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigBuilder;
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
@@ -90,29 +90,31 @@ public class HelidonTestNgListener implements IClassListener, ITestListener {
private List