1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.surefire.common.junit4;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.Queue;
25 import java.util.concurrent.ConcurrentLinkedQueue;
26 import java.util.concurrent.atomic.AtomicInteger;
27
28 import org.junit.runner.Description;
29 import org.junit.runner.notification.Failure;
30 import org.junit.runner.notification.RunListener;
31 import org.junit.runner.notification.RunNotifier;
32 import org.junit.runner.notification.StoppedByUserException;
33
34 import static org.apache.maven.surefire.api.util.internal.ConcurrencyUtils.runIfZeroCountDown;
35 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod;
36
37
38
39
40
41
42
43
44
45 public class Notifier extends RunNotifier {
46 private final Collection<RunListener> listeners = new ArrayList<>();
47
48 private final Queue<String> testClassNames = new ConcurrentLinkedQueue<>();
49
50 private final AtomicInteger skipAfterFailureCount;
51
52 private final JUnit4RunListener reporter;
53
54 private volatile boolean failFast;
55
56 public Notifier(JUnit4RunListener reporter, int skipAfterFailureCount) {
57 addListener(reporter);
58 this.reporter = reporter;
59 this.skipAfterFailureCount = new AtomicInteger(skipAfterFailureCount);
60 }
61
62 private Notifier() {
63 reporter = null;
64 skipAfterFailureCount = null;
65 }
66
67 public static Notifier pureNotifier() {
68 return new Notifier() {
69 @Override
70 public void asFailFast(@SuppressWarnings({"unused", "checkstyle:hiddenfieldcheck"}) boolean failFast) {
71 throw new UnsupportedOperationException("pure notifier");
72 }
73 };
74 }
75
76 public void asFailFast(boolean enableFailFast) {
77 failFast = enableFailFast;
78 }
79
80 public final boolean isFailFast() {
81 return failFast;
82 }
83
84 @Override
85 @SuppressWarnings("checkstyle:redundantthrowscheck")
86 public final void fireTestStarted(Description description) throws StoppedByUserException {
87
88
89 super.fireTestStarted(description);
90 if (!testClassNames.isEmpty()) {
91 testClassNames.remove(toClassMethod(description).getClazz());
92 }
93 }
94
95 @Override
96 public final void fireTestFailure(Failure failure) {
97 if (failFast) {
98 fireStopEvent();
99 }
100 super.fireTestFailure(failure);
101 }
102
103 @Override
104 public final void addListener(RunListener listener) {
105 listeners.add(listener);
106 super.addListener(listener);
107 }
108
109 public final Notifier addListeners(Collection<RunListener> given) {
110 for (RunListener listener : given) {
111 addListener(listener);
112 }
113 return this;
114 }
115
116 @SuppressWarnings("unused")
117 public final Notifier addListeners(RunListener... given) {
118 for (RunListener listener : given) {
119 addListener(listener);
120 }
121 return this;
122 }
123
124 @Override
125 public final void removeListener(RunListener listener) {
126 listeners.remove(listener);
127 super.removeListener(listener);
128 }
129
130 public final void removeListeners() {
131 for (Iterator<RunListener> it = listeners.iterator(); it.hasNext(); ) {
132 RunListener listener = it.next();
133 it.remove();
134 super.removeListener(listener);
135 }
136 }
137
138 public final Queue<String> getRemainingTestClasses() {
139 return failFast ? testClassNames : null;
140 }
141
142 public final void copyListenersTo(Notifier copyTo) {
143 copyTo.addListeners(listeners);
144 }
145
146
147
148
149 private void fireStopEvent() {
150 runIfZeroCountDown(this::pleaseStop, skipAfterFailureCount);
151 reporter.testExecutionSkippedByUser();
152 }
153 }