Skip to content

Commit 2031914

Browse files
authored
Merge pull request #51 from Nordstrom/pr/fix-npe
Pr/fix npe
2 parents 9f03652 + 5a35270 commit 2031914

File tree

5 files changed

+57
-64
lines changed

5 files changed

+57
-64
lines changed

src/main/java/com/nordstrom/automation/junit/AtomicTest.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.junit.Ignore;
1212
import org.junit.Test;
1313
import org.junit.runner.Description;
14-
import org.junit.runners.model.FrameworkMethod;
1514
import org.junit.runners.model.TestClass;
1615

1716
/**
@@ -21,14 +20,14 @@
2120
*/
2221
@Ignore
2322
@SuppressWarnings("all")
24-
public class AtomicTest {
23+
public class AtomicTest<T> {
2524
private final Object runner;
2625
private final Description description;
27-
private final FrameworkMethod identity;
28-
private final List<FrameworkMethod> particles;
26+
private final T identity;
27+
private final List<T> particles;
2928
private Throwable thrown;
3029

31-
public AtomicTest(Object runner, FrameworkMethod identity) {
30+
public AtomicTest(Object runner, T identity) {
3231
this.runner = runner;
3332
this.identity = identity;
3433
this.description = invoke(runner, "describeChild", identity);
@@ -58,7 +57,7 @@ public Description getDescription() {
5857
*
5958
* @return core method associated with this atomic test
6059
*/
61-
public FrameworkMethod getIdentity() {
60+
public T getIdentity() {
6261
return identity;
6362
}
6463

@@ -67,7 +66,7 @@ public FrameworkMethod getIdentity() {
6766
*
6867
* @return list of methods that compose this atomic test
6968
*/
70-
public List<FrameworkMethod> getParticles() {
69+
public List<T> getParticles() {
7170
return particles;
7271
}
7372

@@ -101,10 +100,10 @@ public Throwable getThrowable() {
101100
/**
102101
* Determine if this atomic test includes the specified method.
103102
*
104-
* @param method {@link FrameworkMethod} object
103+
* @param method method object
105104
* @return {@code true} if this atomic test includes the specified method; otherwise {@code false}
106105
*/
107-
public boolean includes(FrameworkMethod method) {
106+
public boolean includes(T method) {
108107
return particles.contains(method);
109108
}
110109

src/main/java/com/nordstrom/automation/junit/LifecycleHooks.java

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
import java.lang.instrument.Instrumentation;
77
import java.lang.reflect.Field;
88
import java.lang.reflect.InvocationTargetException;
9-
import java.lang.reflect.Method;
109
import java.util.Arrays;
1110
import java.util.ServiceLoader;
1211
import java.util.concurrent.Callable;
1312
import java.util.concurrent.ConcurrentMap;
1413

14+
import org.apache.commons.lang3.reflect.MethodUtils;
1515
import org.junit.runner.Description;
1616
import org.junit.runner.notification.RunListener;
1717
import org.junit.runners.model.TestClass;
@@ -194,7 +194,7 @@ public static TestClass getTestClassOf(Object runner) {
194194
* @param runner JUnit class runner
195195
* @return {@link AtomicTest} object (may be {@code null})
196196
*/
197-
public static AtomicTest getAtomicTestOf(Object runner) {
197+
public static <T> AtomicTest<T> getAtomicTestOf(Object runner) {
198198
return RunAnnouncer.getAtomicTestOf(runner);
199199
}
200200

@@ -258,27 +258,11 @@ static String getSubclassName(Object testObj) {
258258
*/
259259
@SuppressWarnings("unchecked")
260260
static <T> T invoke(Object target, String methodName, Object... parameters) {
261-
Class<?>[] parameterTypes = new Class<?>[parameters.length];
262-
for (int i = 0; i < parameters.length; i++) {
263-
parameterTypes[i] = parameters[i].getClass();
264-
}
265-
266-
Throwable thrown = null;
267-
for (Class<?> current = target.getClass(); current != null; current = current.getSuperclass()) {
268-
try {
269-
Method method = current.getDeclaredMethod(methodName, parameterTypes);
270-
method.setAccessible(true);
271-
return (T) method.invoke(target, parameters);
272-
} catch (NoSuchMethodException e) {
273-
thrown = e;
274-
} catch (SecurityException | IllegalAccessException | IllegalArgumentException
275-
| InvocationTargetException e) {
276-
thrown = e;
277-
break;
278-
}
261+
try {
262+
return (T) MethodUtils.invokeMethod(target, true, methodName, parameters);
263+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
264+
throw UncheckedThrow.throwUnchecked(e);
279265
}
280-
281-
throw UncheckedThrow.throwUnchecked(thrown);
282266
}
283267

284268
/**

src/main/java/com/nordstrom/automation/junit/RunAnnouncer.java

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
import org.junit.runner.Description;
99
import org.junit.runner.notification.Failure;
1010
import org.junit.runner.notification.RunListener;
11-
import org.junit.runners.model.FrameworkMethod;
1211
import org.slf4j.Logger;
1312
import org.slf4j.LoggerFactory;
1413

1514
import com.google.common.base.Optional;
1615

17-
public class RunAnnouncer extends RunListener {
16+
public class RunAnnouncer<T> extends RunListener {
1817

18+
@SuppressWarnings("rawtypes")
1919
private static final ServiceLoader<RunWatcher> runWatcherLoader;
20-
private static final Map<Object, AtomicTest> RUNNER_TO_ATOMICTEST = new ConcurrentHashMap<>();
20+
private static final Map<Object, AtomicTest<?>> RUNNER_TO_ATOMICTEST = new ConcurrentHashMap<>();
2121
private static final Logger LOGGER = LoggerFactory.getLogger(RunAnnouncer.class);
2222

2323
static {
@@ -28,11 +28,12 @@ public class RunAnnouncer extends RunListener {
2828
* {@inheritDoc}
2929
*/
3030
@Override
31+
@SuppressWarnings("unchecked")
3132
public void testStarted(Description description) throws Exception {
3233
LOGGER.debug("testStarted: {}", description);
33-
AtomicTest atomicTest = getAtomicTestOf(description);
34+
AtomicTest<T> atomicTest = getAtomicTestOf(description);
3435
synchronized(runWatcherLoader) {
35-
for (RunWatcher watcher : runWatcherLoader) {
36+
for (RunWatcher<T> watcher : runWatcherLoader) {
3637
watcher.testStarted(atomicTest);
3738
}
3839
}
@@ -42,11 +43,12 @@ public void testStarted(Description description) throws Exception {
4243
* {@inheritDoc}
4344
*/
4445
@Override
46+
@SuppressWarnings("unchecked")
4547
public void testFinished(Description description) throws Exception {
4648
LOGGER.debug("testFinished: {}", description);
47-
AtomicTest atomicTest = getAtomicTestOf(description);
49+
AtomicTest<T> atomicTest = getAtomicTestOf(description);
4850
synchronized(runWatcherLoader) {
49-
for (RunWatcher watcher : runWatcherLoader) {
51+
for (RunWatcher<T> watcher : runWatcherLoader) {
5052
watcher.testFinished(atomicTest);
5153
}
5254
}
@@ -56,11 +58,12 @@ public void testFinished(Description description) throws Exception {
5658
* {@inheritDoc}
5759
*/
5860
@Override
61+
@SuppressWarnings("unchecked")
5962
public void testFailure(Failure failure) throws Exception {
6063
LOGGER.debug("testFailure: {}", failure);
61-
AtomicTest atomicTest = setTestFailure(failure);
64+
AtomicTest<T> atomicTest = setTestFailure(failure);
6265
synchronized(runWatcherLoader) {
63-
for (RunWatcher watcher : runWatcherLoader) {
66+
for (RunWatcher<T> watcher : runWatcherLoader) {
6467
watcher.testFailure(atomicTest, failure.getException());
6568
}
6669
}
@@ -70,11 +73,12 @@ public void testFailure(Failure failure) throws Exception {
7073
* {@inheritDoc}
7174
*/
7275
@Override
76+
@SuppressWarnings("unchecked")
7377
public void testAssumptionFailure(Failure failure) {
7478
LOGGER.debug("testAssumptionFailure: {}", failure);
75-
AtomicTest atomicTest = setTestFailure(failure);
79+
AtomicTest<T> atomicTest = setTestFailure(failure);
7680
synchronized(runWatcherLoader) {
77-
for (RunWatcher watcher : runWatcherLoader) {
81+
for (RunWatcher<T> watcher : runWatcherLoader) {
7882
watcher.testAssumptionFailure(atomicTest, (AssumptionViolatedException) failure.getException());
7983
}
8084
}
@@ -84,24 +88,27 @@ public void testAssumptionFailure(Failure failure) {
8488
* {@inheritDoc}
8589
*/
8690
@Override
91+
@SuppressWarnings("unchecked")
8792
public void testIgnored(Description description) throws Exception {
8893
LOGGER.debug("testIgnored: {}", description);
89-
AtomicTest atomicTest = getAtomicTestOf(description);
94+
AtomicTest<T> atomicTest = getAtomicTestOf(description);
9095
synchronized(runWatcherLoader) {
91-
for (RunWatcher watcher : runWatcherLoader) {
96+
for (RunWatcher<T> watcher : runWatcherLoader) {
9297
watcher.testIgnored(atomicTest);
9398
}
9499
}
95100
}
96101

97102
/**
98-
* Create new atomic test object for the specified description.
103+
* Create new atomic test object for the specified runner/child pair.
99104
*
100-
* @param description {@link Description} object
105+
* @param <T> type of children associated with the specified runner
106+
* @param runner parent runner
107+
* @param identity identity for this atomic test
101108
* @return {@link AtomicTest} object
102109
*/
103-
static AtomicTest newAtomicTest(Object runner, FrameworkMethod method) {
104-
AtomicTest atomicTest = new AtomicTest(runner, method);
110+
static <T> AtomicTest<T> newAtomicTest(Object runner, T identity) {
111+
AtomicTest<T> atomicTest = new AtomicTest<>(runner, identity);
105112
RUNNER_TO_ATOMICTEST.put(runner, atomicTest);
106113
RUNNER_TO_ATOMICTEST.put(atomicTest.getDescription(), atomicTest);
107114
return atomicTest;
@@ -113,8 +120,9 @@ static AtomicTest newAtomicTest(Object runner, FrameworkMethod method) {
113120
* @param testKey JUnit class runner or method description
114121
* @return {@link AtomicTest} object (may be {@code null})
115122
*/
116-
static AtomicTest getAtomicTestOf(Object testKey) {
117-
return RUNNER_TO_ATOMICTEST.get(testKey);
123+
@SuppressWarnings("unchecked")
124+
static <T> AtomicTest<T> getAtomicTestOf(Object testKey) {
125+
return (AtomicTest<T>) RUNNER_TO_ATOMICTEST.get(testKey);
118126
}
119127

120128
/**
@@ -123,26 +131,26 @@ static AtomicTest getAtomicTestOf(Object testKey) {
123131
* @param failure {@link Failure} object
124132
* @return {@link AtomicTest} object
125133
*/
126-
private static AtomicTest setTestFailure(Failure failure) {
127-
AtomicTest atomicTest = getAtomicTestOf(Run.getThreadRunner());
134+
private static <T> AtomicTest<T> setTestFailure(Failure failure) {
135+
AtomicTest<T> atomicTest = getAtomicTestOf(Run.getThreadRunner());
128136
atomicTest.setThrowable(failure.getException());
129137
return atomicTest;
130138
}
131139

132140
/**
133141
* Get reference to an instance of the specified watcher type.
134142
*
135-
* @param <T> watcher type
143+
* @param <W> watcher type
136144
* @param watcherType watcher type
137145
* @return optional watcher instance
138146
*/
139147
@SuppressWarnings("unchecked")
140-
static <T extends JUnitWatcher> Optional<T> getAttachedWatcher(Class<T> watcherType) {
148+
static <W extends JUnitWatcher> Optional<W> getAttachedWatcher(Class<W> watcherType) {
141149
if (RunWatcher.class.isAssignableFrom(watcherType)) {
142150
synchronized(runWatcherLoader) {
143-
for (RunWatcher watcher : runWatcherLoader) {
151+
for (RunWatcher<?> watcher : runWatcherLoader) {
144152
if (watcher.getClass() == watcherType) {
145-
return Optional.of((T) watcher);
153+
return Optional.of((W) watcher);
146154
}
147155
}
148156
}

src/main/java/com/nordstrom/automation/junit/RunChild.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ public static void intercept(@This final Object runner, @SuperCall final Callabl
4949

5050
try {
5151
Run.pushThreadRunner(runner);
52+
RunAnnouncer.newAtomicTest(runner, child);
53+
5254
if (child instanceof FrameworkMethod) {
5355
FrameworkMethod method = (FrameworkMethod) child;
5456

5557
applyTimeout(method);
5658
int count = RetryHandler.getMaxRetry(runner, method);
5759
boolean isIgnored = (null != method.getAnnotation(Ignore.class));
5860

59-
RunAnnouncer.newAtomicTest(runner, method);
60-
6161
if (count == 0) {
6262
LifecycleHooks.callProxy(proxy);
6363
} else if (!isIgnored) {
@@ -66,6 +66,8 @@ public static void intercept(@This final Object runner, @SuperCall final Callabl
6666
} else {
6767
LifecycleHooks.callProxy(proxy);
6868
}
69+
} catch (NoSuchMethodException e) {
70+
LifecycleHooks.callProxy(proxy);
6971
} finally {
7072
Run.popThreadRunner();
7173
}

src/main/java/com/nordstrom/automation/junit/RunWatcher.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,43 @@
55
/**
66
* This interface defines the methods implemented by JUnit run watchers.
77
*/
8-
public interface RunWatcher extends JUnitWatcher {
8+
public interface RunWatcher<T> extends JUnitWatcher {
99

1010
/**
1111
* Called when an atomic test is about to be started.
1212
*
1313
* @param atomicTest {@link AtomicTest} object for this atomic test
1414
*/
15-
public void testStarted(AtomicTest atomicTest);
15+
public void testStarted(AtomicTest<T> atomicTest);
1616

1717
/**
1818
* Called when an atomic test has finished, whether the test succeeds or fails.
1919
*
2020
* @param atomicTest {@link AtomicTest} object for this atomic test
2121
*/
22-
public void testFinished(AtomicTest atomicTest);
22+
public void testFinished(AtomicTest<T> atomicTest);
2323

2424
/**
2525
* Called when an atomic test fails.
2626
*
2727
* @param atomicTest {@link AtomicTest} object for this atomic test
2828
* @param thrown exception thrown by method
2929
*/
30-
public void testFailure(AtomicTest atomicTest, Throwable thrown);
30+
public void testFailure(AtomicTest<T> atomicTest, Throwable thrown);
3131

3232
/**
3333
* Called when an atomic test flags that it assumes a condition that is false
3434
*
3535
* @param atomicTest {@link AtomicTest} object for this atomic test
3636
* @param thrown {@link AssumptionViolatedException} thrown by method
3737
*/
38-
public void testAssumptionFailure(AtomicTest atomicTest, AssumptionViolatedException thrown);
38+
public void testAssumptionFailure(AtomicTest<T> atomicTest, AssumptionViolatedException thrown);
3939

4040
/**
4141
* Called when a test will not be run, generally because a test method is annotated with {@link org.junit.Ignore}.
4242
*
4343
* @param atomicTest {@link AtomicTest} object for this atomic test
4444
*/
45-
public void testIgnored(AtomicTest atomicTest);
45+
public void testIgnored(AtomicTest<T> atomicTest);
4646

4747
}

0 commit comments

Comments
 (0)