001 package org.junit.runner;
002
003 import java.io.IOException;
004 import java.io.ObjectInputStream;
005 import java.io.ObjectOutputStream;
006 import java.io.ObjectStreamClass;
007 import java.io.ObjectStreamField;
008 import java.io.Serializable;
009 import java.util.ArrayList;
010 import java.util.Collections;
011 import java.util.List;
012 import java.util.concurrent.CopyOnWriteArrayList;
013 import java.util.concurrent.atomic.AtomicInteger;
014 import java.util.concurrent.atomic.AtomicLong;
015
016 import org.junit.runner.notification.Failure;
017 import org.junit.runner.notification.RunListener;
018
019 /**
020 * A <code>Result</code> collects and summarizes information from running multiple tests.
021 * All tests are counted -- additional information is collected from tests that fail.
022 *
023 * @since 4.0
024 */
025 public class Result implements Serializable {
026 private static final long serialVersionUID = 1L;
027 private static final ObjectStreamField[] serialPersistentFields =
028 ObjectStreamClass.lookup(SerializedForm.class).getFields();
029 private final AtomicInteger count;
030 private final AtomicInteger ignoreCount;
031 private final AtomicInteger assumptionFailureCount;
032 private final CopyOnWriteArrayList<Failure> failures;
033 private final AtomicLong runTime;
034 private final AtomicLong startTime;
035
036 /** Only set during deserialization process. */
037 private SerializedForm serializedForm;
038
039 public Result() {
040 count = new AtomicInteger();
041 ignoreCount = new AtomicInteger();
042 assumptionFailureCount = new AtomicInteger();
043 failures = new CopyOnWriteArrayList<Failure>();
044 runTime = new AtomicLong();
045 startTime = new AtomicLong();
046 }
047
048 private Result(SerializedForm serializedForm) {
049 count = serializedForm.fCount;
050 ignoreCount = serializedForm.fIgnoreCount;
051 assumptionFailureCount = serializedForm.assumptionFailureCount;
052 failures = new CopyOnWriteArrayList<Failure>(serializedForm.fFailures);
053 runTime = new AtomicLong(serializedForm.fRunTime);
054 startTime = new AtomicLong(serializedForm.fStartTime);
055 }
056
057 /**
058 * Returns the number of tests run
059 */
060 public int getRunCount() {
061 return count.get();
062 }
063
064 /**
065 * Returns the number of tests that failed during the run
066 */
067 public int getFailureCount() {
068 return failures.size();
069 }
070
071 /**
072 * Returns the number of milliseconds it took to run the entire suite to run
073 */
074 public long getRunTime() {
075 return runTime.get();
076 }
077
078 /**
079 * Returns the {@link Failure}s describing tests that failed and the problems they encountered
080 */
081 public List<Failure> getFailures() {
082 return failures;
083 }
084
085 /**
086 * @return the number of tests ignored during the run
087 */
088 public int getIgnoreCount() {
089 return ignoreCount.get();
090 }
091
092 /**
093 * Returns the number of tests skipped because of an assumption failure
094 *
095 * @throws UnsupportedOperationException if the result was serialized in a version before JUnit 4.13
096 * @since 4.13
097 */
098 public int getAssumptionFailureCount() {
099 if (assumptionFailureCount == null) {
100 throw new UnsupportedOperationException(
101 "Result was serialized from a version of JUnit that doesn't support this method");
102 }
103 return assumptionFailureCount.get();
104 }
105
106 /**
107 * @return <code>true</code> if all tests succeeded
108 */
109 public boolean wasSuccessful() {
110 return getFailureCount() == 0;
111 }
112
113 private void writeObject(ObjectOutputStream s) throws IOException {
114 SerializedForm serializedForm = new SerializedForm(this);
115 serializedForm.serialize(s);
116 }
117
118 private void readObject(ObjectInputStream s)
119 throws ClassNotFoundException, IOException {
120 serializedForm = SerializedForm.deserialize(s);
121 }
122
123 private Object readResolve() {
124 return new Result(serializedForm);
125 }
126
127 @RunListener.ThreadSafe
128 private class Listener extends RunListener {
129 @Override
130 public void testRunStarted(Description description) throws Exception {
131 startTime.set(System.currentTimeMillis());
132 }
133
134 @Override
135 public void testRunFinished(Result result) throws Exception {
136 long endTime = System.currentTimeMillis();
137 runTime.addAndGet(endTime - startTime.get());
138 }
139
140 @Override
141 public void testFinished(Description description) throws Exception {
142 count.getAndIncrement();
143 }
144
145 @Override
146 public void testFailure(Failure failure) throws Exception {
147 failures.add(failure);
148 }
149
150 @Override
151 public void testIgnored(Description description) throws Exception {
152 ignoreCount.getAndIncrement();
153 }
154
155 @Override
156 public void testAssumptionFailure(Failure failure) {
157 assumptionFailureCount.getAndIncrement();
158 }
159 }
160
161 /**
162 * Internal use only.
163 */
164 public RunListener createListener() {
165 return new Listener();
166 }
167
168 /**
169 * Represents the serialized output of {@code Result}. The fields on this
170 * class match the files that {@code Result} had in JUnit 4.11.
171 */
172 private static class SerializedForm implements Serializable {
173 private static final long serialVersionUID = 1L;
174 private final AtomicInteger fCount;
175 private final AtomicInteger fIgnoreCount;
176 private final AtomicInteger assumptionFailureCount;
177 private final List<Failure> fFailures;
178 private final long fRunTime;
179 private final long fStartTime;
180
181 public SerializedForm(Result result) {
182 fCount = result.count;
183 fIgnoreCount = result.ignoreCount;
184 assumptionFailureCount = result.assumptionFailureCount;
185 fFailures = Collections.synchronizedList(new ArrayList<Failure>(result.failures));
186 fRunTime = result.runTime.longValue();
187 fStartTime = result.startTime.longValue();
188 }
189
190 @SuppressWarnings("unchecked")
191 private SerializedForm(ObjectInputStream.GetField fields) throws IOException {
192 fCount = (AtomicInteger) fields.get("fCount", null);
193 fIgnoreCount = (AtomicInteger) fields.get("fIgnoreCount", null);
194 assumptionFailureCount = (AtomicInteger) fields.get("assumptionFailureCount", null);
195 fFailures = (List<Failure>) fields.get("fFailures", null);
196 fRunTime = fields.get("fRunTime", 0L);
197 fStartTime = fields.get("fStartTime", 0L);
198 }
199
200 public void serialize(ObjectOutputStream s) throws IOException {
201 ObjectOutputStream.PutField fields = s.putFields();
202 fields.put("fCount", fCount);
203 fields.put("fIgnoreCount", fIgnoreCount);
204 fields.put("fFailures", fFailures);
205 fields.put("fRunTime", fRunTime);
206 fields.put("fStartTime", fStartTime);
207 fields.put("assumptionFailureCount", assumptionFailureCount);
208 s.writeFields();
209 }
210
211 public static SerializedForm deserialize(ObjectInputStream s)
212 throws ClassNotFoundException, IOException {
213 ObjectInputStream.GetField fields = s.readFields();
214 return new SerializedForm(fields);
215 }
216 }
217 }