60
60
import jakarta .inject .Singleton ;
61
61
import jakarta .ws .rs .client .ClientBuilder ;
62
62
import jdk .jfr .consumer .RecordedEvent ;
63
- import jdk .jfr .consumer .RecordedFrame ;
64
63
import jdk .jfr .consumer .RecordingStream ;
65
64
import org .eclipse .microprofile .config .Config ;
66
65
import org .eclipse .microprofile .config .spi .ConfigBuilder ;
73
72
import org .testng .ITestResult ;
74
73
import org .testng .annotations .Test ;
75
74
76
- import static org .testng .Assert .fail ;
77
-
78
75
/**
79
76
* TestNG extension to support Helidon CDI container in tests.
80
77
*/
@@ -93,7 +90,6 @@ public class HelidonTestNgListener implements IClassListener, ITestListener {
93
90
private List <AddExtension > classLevelExtensions = new ArrayList <>();
94
91
private List <AddBean > classLevelBeans = new ArrayList <>();
95
92
private ConfigMeta classLevelConfigMeta = new ConfigMeta ();
96
- private List <EventWrapper > jfrVTPinned ;
97
93
private RecordingStream recordingStream ;
98
94
private boolean classLevelDisableDiscovery = false ;
99
95
private boolean resetPerTest ;
@@ -104,6 +100,7 @@ public class HelidonTestNgListener implements IClassListener, ITestListener {
104
100
private ConfigProviderResolver configProviderResolver ;
105
101
private Config config ;
106
102
private SeContainer container ;
103
+ private PinningException pinningException ;
107
104
108
105
@ Override
109
106
public void onBeforeClass (ITestClass iTestClass ) {
@@ -371,12 +368,9 @@ private <T extends Annotation> T getAnnotation(Class<?> testClass, Class<T> anno
371
368
372
369
private void startRecordingStream () {
373
370
if (pinnedThreadValidation ) {
374
- jfrVTPinned = new ArrayList <>();
375
371
recordingStream = new RecordingStream ();
376
372
recordingStream .enable ("jdk.VirtualThreadPinned" ).withStackTrace ();
377
- recordingStream .onEvent ("jdk.VirtualThreadPinned" , event -> {
378
- jfrVTPinned .add (new EventWrapper (event ));
379
- });
373
+ recordingStream .onEvent ("jdk.VirtualThreadPinned" , this ::record );
380
374
recordingStream .startAsync ();
381
375
}
382
376
}
@@ -386,8 +380,8 @@ private void closeRecordingStream() {
386
380
try {
387
381
// Flush ending events
388
382
recordingStream .stop ();
389
- if (! jfrVTPinned . isEmpty () ) {
390
- fail ( "Some pinned virtual threads were detected: \n " + jfrVTPinned ) ;
383
+ if (pinningException != null ) {
384
+ throw pinningException ;
391
385
}
392
386
} finally {
393
387
recordingStream .close ();
@@ -468,6 +462,15 @@ private static boolean hasAnnotation(AnnotatedElement element, Set<Class<? exten
468
462
return false ;
469
463
}
470
464
465
+ void record (RecordedEvent event ) {
466
+ PinningException e = new PinningException (event );
467
+ if (pinningException == null ) {
468
+ pinningException = e ;
469
+ } else {
470
+ pinningException .addSuppressed (e );
471
+ }
472
+ }
473
+
471
474
@ SuppressWarnings ("CdiManagedBeanInconsistencyInspection" )
472
475
private record TestInstanceExtension (Object testInstance , Class <?> testClass ) implements Extension {
473
476
@@ -683,28 +686,26 @@ private static final class SingletonLiteral extends AnnotationLiteral<Singleton>
683
686
static final SingletonLiteral INSTANCE = new SingletonLiteral ();
684
687
}
685
688
686
- private static class EventWrapper {
687
-
689
+ private static class PinningException extends AssertionError {
688
690
private final RecordedEvent recordedEvent ;
689
691
690
- private EventWrapper (RecordedEvent recordedEvent ) {
692
+ PinningException (RecordedEvent recordedEvent ) {
691
693
this .recordedEvent = recordedEvent ;
694
+ if (recordedEvent .getStackTrace () != null ) {
695
+ StackTraceElement [] stackTraceElements = recordedEvent .getStackTrace ().getFrames ().stream ()
696
+ .map (f -> new StackTraceElement (f .getMethod ().getType ().getName (),
697
+ f .getMethod ().getName (),
698
+ f .getMethod ().getType ().getName () + ".java" ,
699
+ f .getLineNumber ()))
700
+ .toArray (StackTraceElement []::new );
701
+ super .setStackTrace (stackTraceElements );
702
+ }
692
703
}
693
704
694
705
@ Override
695
- public String toString () {
696
- StringBuilder builder = new StringBuilder (recordedEvent .toString ());
697
- if (recordedEvent .getStackTrace () != null ) {
698
- builder .append ("full-stackTrace = [" );
699
- List <RecordedFrame > frames = recordedEvent .getStackTrace ().getFrames ();
700
- for (RecordedFrame frame : frames ) {
701
- builder .append ("\n \t " ).append (frame .getMethod ().getType ().getName ())
702
- .append ("#" ).append (frame .getMethod ().getName ())
703
- .append ("(" ).append (frame .getLineNumber ()).append (")" );
704
- }
705
- builder .append ("\n ]" );
706
- }
707
- return builder .toString ();
706
+ public String getMessage () {
707
+ return "Pinned virtual threads were detected:\n "
708
+ + recordedEvent .toString ();
708
709
}
709
710
}
710
711
0 commit comments