View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.api.suite;
20  
21  import java.io.ByteArrayOutputStream;
22  import java.io.PrintWriter;
23  
24  /**
25   * Represents a test-run-result; this may be from a single test run or an aggregated result.
26   * <br>
27   * In the case of timeout==true, the run-counts reflect the state of the test-run at the time
28   * of the timeout.
29   *
30   * @author Kristian Rosenvold
31   */
32  public class RunResult {
33      private final int completedCount;
34  
35      private final int errors;
36  
37      private final int failures;
38  
39      private final int skipped;
40  
41      private final int flakes;
42  
43      private final String failure;
44  
45      private final boolean timeout;
46  
47      public static final int SUCCESS = 0;
48  
49      public static final int FAILURE = 255;
50  
51      private static final int NO_TESTS = 254;
52  
53      public static RunResult timeout(RunResult accumulatedAtTimeout) {
54          return errorCode(accumulatedAtTimeout, accumulatedAtTimeout.getFailure(), true);
55      }
56  
57      public static RunResult failure(RunResult accumulatedAtTimeout, Exception cause) {
58          return errorCode(accumulatedAtTimeout, getStackTrace(cause), accumulatedAtTimeout.isTimeout());
59      }
60  
61      private static RunResult errorCode(RunResult other, String failure, boolean timeout) {
62          return new RunResult(
63                  other.getCompletedCount(),
64                  other.getErrors(),
65                  other.getFailures(),
66                  other.getSkipped(),
67                  failure,
68                  timeout);
69      }
70  
71      public RunResult(int completedCount, int errors, int failures, int skipped) {
72          this(completedCount, errors, failures, skipped, null, false);
73      }
74  
75      public RunResult(int completedCount, int errors, int failures, int skipped, int flakes) {
76          this(completedCount, errors, failures, skipped, flakes, null, false);
77      }
78  
79      public RunResult(int completedCount, int errors, int failures, int skipped, String failure, boolean timeout) {
80          this(completedCount, errors, failures, skipped, 0, failure, timeout);
81      }
82  
83      public RunResult(
84              int completedCount, int errors, int failures, int skipped, int flakes, String failure, boolean timeout) {
85          this.completedCount = completedCount;
86          this.errors = errors;
87          this.failures = failures;
88          this.skipped = skipped;
89          this.failure = failure;
90          this.timeout = timeout;
91          this.flakes = flakes;
92      }
93  
94      private static String getStackTrace(Exception e) {
95          if (e == null) {
96              return null;
97          }
98          ByteArrayOutputStream out = new ByteArrayOutputStream();
99          try (PrintWriter pw = new PrintWriter(out)) {
100             e.printStackTrace(pw);
101         }
102         return new String(out.toByteArray());
103     }
104 
105     public int getCompletedCount() {
106         return completedCount;
107     }
108 
109     public int getErrors() {
110         return errors;
111     }
112 
113     public int getFlakes() {
114         return flakes;
115     }
116 
117     public int getFailures() {
118         return failures;
119     }
120 
121     public int getSkipped() {
122         return skipped;
123     }
124 
125     public Integer getFailsafeCode() // Only used for compatibility reasons.
126             {
127         if (completedCount == 0) {
128             return NO_TESTS;
129         }
130         if (!isErrorFree()) {
131             return FAILURE;
132         }
133         return null;
134     }
135 
136     /* Indicates if the tests are error free */
137     public boolean isErrorFree() {
138         return getFailures() == 0 && getErrors() == 0 && !isFailure();
139     }
140 
141     public boolean isInternalError() {
142         return getFailures() == 0 && getErrors() == 0 && isFailure();
143     }
144 
145     /* Indicates test timeout or technical failure */
146     public boolean isFailureOrTimeout() {
147         return isTimeout() || isFailure();
148     }
149 
150     public boolean isFailure() {
151         return failure != null;
152     }
153 
154     public String getFailure() {
155         return failure;
156     }
157 
158     public boolean isTimeout() {
159         return timeout;
160     }
161 
162     public RunResult aggregate(RunResult other) {
163         String failureMessage = getFailure() != null ? getFailure() : other.getFailure();
164         boolean timeout = isTimeout() || other.isTimeout();
165         int completed = getCompletedCount() + other.getCompletedCount();
166         int fail = getFailures() + other.getFailures();
167         int ign = getSkipped() + other.getSkipped();
168         int err = getErrors() + other.getErrors();
169         int flakes = getFlakes() + other.getFlakes();
170         return new RunResult(completed, err, fail, ign, flakes, failureMessage, timeout);
171     }
172 
173     public static RunResult noTestsRun() {
174         return new RunResult(0, 0, 0, 0);
175     }
176 
177     @Override
178     @SuppressWarnings("RedundantIfStatement")
179     public boolean equals(Object o) {
180         if (this == o) {
181             return true;
182         }
183         if (o == null || getClass() != o.getClass()) {
184             return false;
185         }
186 
187         RunResult runResult = (RunResult) o;
188 
189         if (completedCount != runResult.completedCount) {
190             return false;
191         }
192         if (errors != runResult.errors) {
193             return false;
194         }
195         if (failures != runResult.failures) {
196             return false;
197         }
198         if (skipped != runResult.skipped) {
199             return false;
200         }
201         if (timeout != runResult.timeout) {
202             return false;
203         }
204         if (failure != null ? !failure.equals(runResult.failure) : runResult.failure != null) {
205             return false;
206         }
207 
208         return true;
209     }
210 
211     @Override
212     public int hashCode() {
213         int result = completedCount;
214         result = 31 * result + errors;
215         result = 31 * result + failures;
216         result = 31 * result + skipped;
217         result = 31 * result + (failure != null ? failure.hashCode() : 0);
218         result = 31 * result + (timeout ? 1 : 0);
219         return result;
220     }
221 }