1
1
package datadog .trace .instrumentation .junit4 ;
2
2
3
3
import datadog .trace .api .civisibility .config .SkippableTest ;
4
+ import datadog .trace .util .MethodHandles ;
4
5
import datadog .trace .util .Strings ;
5
6
import java .lang .annotation .Annotation ;
6
7
import java .lang .invoke .MethodHandle ;
7
- import java .lang .invoke .MethodHandles ;
8
- import java .lang .reflect .Field ;
9
8
import java .lang .reflect .Method ;
10
9
import java .util .ArrayList ;
11
10
import java .util .Collection ;
12
11
import java .util .List ;
13
12
import java .util .regex .Matcher ;
14
13
import java .util .regex .Pattern ;
15
14
import javax .annotation .Nullable ;
15
+ import junit .framework .TestCase ;
16
16
import org .junit .Test ;
17
17
import org .junit .experimental .categories .Category ;
18
18
import org .junit .runner .Description ;
19
19
import org .junit .runner .notification .RunListener ;
20
20
import org .junit .runner .notification .RunNotifier ;
21
21
import org .junit .runners .ParentRunner ;
22
- import org .slf4j .Logger ;
23
- import org .slf4j .LoggerFactory ;
24
22
25
23
public abstract class JUnit4Utils {
26
24
27
- private static final Logger log = LoggerFactory .getLogger (JUnit4Utils .class );
28
25
private static final String SYNCHRONIZED_LISTENER =
29
26
"org.junit.runner.notification.SynchronizedRunListener" ;
30
27
@@ -34,91 +31,37 @@ public abstract class JUnit4Utils {
34
31
private static final Pattern METHOD_AND_CLASS_NAME_PATTERN =
35
32
Pattern .compile ("([\\ s\\ S]*)\\ ((.*)\\ )" );
36
33
37
- private static final MethodHandle PARENT_RUNNER_DESCRIBE_CHILD ;
38
- private static final MethodHandle RUN_NOTIFIER_LISTENERS ;
39
- private static final MethodHandle INNER_SYNCHRONIZED_LISTENER ;
40
- private static final MethodHandle DESCRIPTION_UNIQUE_ID ;
41
-
42
- static {
43
- MethodHandles .Lookup lookup = MethodHandles .lookup ();
44
- PARENT_RUNNER_DESCRIBE_CHILD = accessDescribeChildMethodInParentRunner (lookup );
45
- RUN_NOTIFIER_LISTENERS = accessListenersFieldInRunNotifier (lookup );
46
- INNER_SYNCHRONIZED_LISTENER = accessListenerFieldInSynchronizedListener (lookup );
47
- DESCRIPTION_UNIQUE_ID = accessUniqueIdInDescription (lookup );
48
- }
49
-
50
- private static MethodHandle accessDescribeChildMethodInParentRunner (MethodHandles .Lookup lookup ) {
51
- try {
52
- Method describeChild = ParentRunner .class .getDeclaredMethod ("describeChild" , Object .class );
53
- describeChild .setAccessible (true );
54
- return lookup .unreflect (describeChild );
55
- } catch (Exception e ) {
56
- return null ;
57
- }
58
- }
59
-
60
- private static MethodHandle accessListenersFieldInRunNotifier (MethodHandles .Lookup lookup ) {
61
- try {
62
- Field listeners ;
63
- try {
64
- // Since JUnit 4.12, the field is called "listeners"
65
- listeners = RunNotifier .class .getDeclaredField ("listeners" );
66
- } catch (final NoSuchFieldException e ) {
67
- // Before JUnit 4.12, the field is called "fListeners"
68
- listeners = RunNotifier .class .getDeclaredField ("fListeners" );
69
- }
70
-
71
- listeners .setAccessible (true );
72
- return lookup .unreflectGetter (listeners );
73
- } catch (final Throwable e ) {
74
- log .debug ("Could not get runListeners for JUnit4Advice" , e );
75
- return null ;
34
+ private static final MethodHandles METHOD_HANDLES =
35
+ new MethodHandles (ParentRunner .class .getClassLoader ());
36
+ private static final MethodHandle PARENT_RUNNER_DESCRIBE_CHILD =
37
+ METHOD_HANDLES .method (ParentRunner .class , "describeChild" , Object .class );
38
+ private static final MethodHandle RUN_NOTIFIER_LISTENERS = accessListenersFieldInRunNotifier ();
39
+ private static final MethodHandle INNER_SYNCHRONIZED_LISTENER =
40
+ accessListenerFieldInSynchronizedListener ();
41
+ private static final MethodHandle DESCRIPTION_UNIQUE_ID =
42
+ METHOD_HANDLES .privateFieldGetter (Description .class , "fUniqueId" );
43
+
44
+ private static MethodHandle accessListenersFieldInRunNotifier () {
45
+ MethodHandle listeners = METHOD_HANDLES .privateFieldGetter (RunNotifier .class , "listeners" );
46
+ if (listeners != null ) {
47
+ return listeners ;
76
48
}
49
+ // Before JUnit 4.12, the field is called "fListeners"
50
+ return METHOD_HANDLES .privateFieldGetter (RunNotifier .class , "fListeners" );
77
51
}
78
52
79
- private static MethodHandle accessListenerFieldInSynchronizedListener (
80
- MethodHandles .Lookup lookup ) {
81
- ClassLoader classLoader = RunListener .class .getClassLoader ();
82
- MethodHandle handle = accessListenerFieldInSynchronizedListener (lookup , classLoader );
53
+ private static MethodHandle accessListenerFieldInSynchronizedListener () {
54
+ MethodHandle handle = METHOD_HANDLES .privateFieldGetter (SYNCHRONIZED_LISTENER , "listener" );
83
55
if (handle != null ) {
84
56
return handle ;
85
- } else {
86
- ClassLoader contextClassLoader = Thread .currentThread ().getContextClassLoader ();
87
- return accessListenerFieldInSynchronizedListener (lookup , contextClassLoader );
88
- }
89
- }
90
-
91
- private static MethodHandle accessListenerFieldInSynchronizedListener (
92
- MethodHandles .Lookup lookup , ClassLoader classLoader ) {
93
- try {
94
- Class <?> synchronizedListenerClass = classLoader .loadClass (SYNCHRONIZED_LISTENER );
95
- final Field innerListenerField = synchronizedListenerClass .getDeclaredField ("listener" );
96
- innerListenerField .setAccessible (true );
97
- return lookup .unreflectGetter (innerListenerField );
98
- } catch (Exception e ) {
99
- return null ;
100
- }
101
- }
102
-
103
- private static MethodHandle accessUniqueIdInDescription (MethodHandles .Lookup lookup ) {
104
- try {
105
- final Field uniqueIdField = Description .class .getDeclaredField ("fUniqueId" );
106
- uniqueIdField .setAccessible (true );
107
- return lookup .unreflectGetter (uniqueIdField );
108
- } catch (Throwable throwable ) {
109
- return null ;
110
57
}
58
+ ClassLoader contextClassLoader = Thread .currentThread ().getContextClassLoader ();
59
+ return new MethodHandles (contextClassLoader )
60
+ .privateFieldGetter (SYNCHRONIZED_LISTENER , "listeners" );
111
61
}
112
62
113
63
public static List <RunListener > runListenersFromRunNotifier (final RunNotifier runNotifier ) {
114
- try {
115
- if (RUN_NOTIFIER_LISTENERS != null ) {
116
- return (List <RunListener >) RUN_NOTIFIER_LISTENERS .invoke (runNotifier );
117
- }
118
- } catch (final Throwable e ) {
119
- log .debug ("Could not get runListeners for JUnit4Advice" , e );
120
- }
121
- return null ;
64
+ return METHOD_HANDLES .invoke (RUN_NOTIFIER_LISTENERS , runNotifier );
122
65
}
123
66
124
67
public static TracingListener toTracingListener (final RunListener listener ) {
@@ -128,15 +71,9 @@ public static TracingListener toTracingListener(final RunListener listener) {
128
71
129
72
// Since JUnit 4.12, the RunListener are wrapped by a SynchronizedRunListener object.
130
73
if (SYNCHRONIZED_LISTENER .equals (listener .getClass ().getName ())) {
131
- try {
132
- if (INNER_SYNCHRONIZED_LISTENER != null ) {
133
- Object innerListener = INNER_SYNCHRONIZED_LISTENER .invoke (listener );
134
- if (innerListener instanceof TracingListener ) {
135
- return (TracingListener ) innerListener ;
136
- }
137
- }
138
- } catch (final Throwable e ) {
139
- log .debug ("Could not get inner listener from SynchronizedRunListener" , e );
74
+ RunListener innerListener = METHOD_HANDLES .invoke (INNER_SYNCHRONIZED_LISTENER , listener );
75
+ if (innerListener instanceof TracingListener ) {
76
+ return (TracingListener ) innerListener ;
140
77
}
141
78
}
142
79
return null ;
@@ -301,18 +238,11 @@ public static boolean isSuiteContainingChildren(final Description description) {
301
238
return true ;
302
239
}
303
240
}
304
- return false ;
241
+ return TestCase . class . isAssignableFrom ( testClass ) ;
305
242
}
306
243
307
244
public static Object getUniqueId (final Description description ) {
308
- try {
309
- if (DESCRIPTION_UNIQUE_ID != null ) {
310
- return DESCRIPTION_UNIQUE_ID .invoke (description );
311
- }
312
- } catch (Throwable e ) {
313
- log .error ("Could not get unique ID from descriptions: " + description , e );
314
- }
315
- return null ;
245
+ return METHOD_HANDLES .invoke (DESCRIPTION_UNIQUE_ID , description );
316
246
}
317
247
318
248
public static String getSuiteName (final Class <?> testClass , final Description description ) {
@@ -332,14 +262,7 @@ public static List<Method> getTestMethods(final Class<?> testClass) {
332
262
}
333
263
334
264
public static Description getDescription (ParentRunner <?> runner , Object child ) {
335
- try {
336
- if (PARENT_RUNNER_DESCRIBE_CHILD != null ) {
337
- return (Description ) PARENT_RUNNER_DESCRIBE_CHILD .invokeWithArguments (runner , child );
338
- }
339
- } catch (Throwable e ) {
340
- log .error ("Could not describe child: " + child , e );
341
- }
342
- return null ;
265
+ return METHOD_HANDLES .invoke (PARENT_RUNNER_DESCRIBE_CHILD , runner , child );
343
266
}
344
267
345
268
public static Description getSkippedDescription (Description description ) {
0 commit comments