1 package org.apache.maven.plugin.failsafe.xmlsummary;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import javax.xml.bind.annotation.XmlAccessType;
23 import javax.xml.bind.annotation.XmlAccessorType;
24 import javax.xml.bind.annotation.XmlAttribute;
25 import javax.xml.bind.annotation.XmlElement;
26 import javax.xml.bind.annotation.XmlRootElement;
27 import javax.xml.bind.annotation.XmlType;
28 import java.io.IOException;
29 import java.io.LineNumberReader;
30 import java.io.StringReader;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.regex.Pattern;
34
35 import static java.util.Collections.emptyList;
36 import static org.apache.maven.plugin.failsafe.xmlsummary.ErrorType.FAILURE;
37 import static org.apache.maven.plugin.failsafe.xmlsummary.ErrorType.NO_TESTS;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 @XmlAccessorType( XmlAccessType.FIELD )
64 @XmlType( name = "", propOrder = {
65 "completed",
66 "errors",
67 "failures",
68 "skipped",
69 "failureMessage"
70 } )
71 @XmlRootElement( name = "failsafe-summary" )
72 public class FailsafeSummary
73 {
74 private static final String ERROR_MSG_PREFIX = "org.apache.maven.surefire.booter.SurefireBooterForkException: ";
75 private static final Pattern STACK_TRACE_ELEMENT1 = Pattern.compile( "^\\tat.*\\(.*\\.java\\:[\\d]+\\)$" );
76 private static final Pattern STACK_TRACE_ELEMENT2 = Pattern.compile( "^\\tat.*\\(Native Method\\)$" );
77 private static final Pattern STACK_TRACE_ELEMENT3 = Pattern.compile( "^Caused by\\: .*" );
78
79 private int completed;
80
81 private int errors;
82
83 private int failures;
84
85 private int skipped;
86
87 @XmlElement( required = true, nillable = true )
88 private String failureMessage;
89
90 @XmlAttribute( name = "result" )
91 private ErrorType result;
92
93 @XmlAttribute( name = "timeout", required = true )
94 private boolean timeout;
95
96
97
98
99 public int getCompleted()
100 {
101 return completed;
102 }
103
104
105
106
107 public void setCompleted( int value )
108 {
109 this.completed = value;
110 }
111
112
113
114
115 public int getErrors()
116 {
117 return errors;
118 }
119
120
121
122
123 public void setErrors( int value )
124 {
125 this.errors = value;
126 }
127
128
129
130
131 public int getFailures()
132 {
133 return failures;
134 }
135
136
137
138
139 public void setFailures( int value )
140 {
141 this.failures = value;
142 }
143
144
145
146
147 public int getSkipped()
148 {
149 return skipped;
150 }
151
152
153
154
155 public void setSkipped( int value )
156 {
157 this.skipped = value;
158 }
159
160
161
162
163
164
165
166 public String getFailureMessage()
167 {
168 return failureMessage;
169 }
170
171
172
173
174
175
176
177 public void setFailureMessage( String value )
178 {
179 this.failureMessage = value;
180 }
181
182
183
184
185
186
187
188 public ErrorType getResult()
189 {
190 return result;
191 }
192
193
194
195
196
197
198
199 public void setResult( ErrorType value )
200 {
201 this.result = value;
202 }
203
204
205
206
207 public boolean isTimeout()
208 {
209 return timeout;
210 }
211
212
213
214
215 public void setTimeout( boolean value )
216 {
217 this.timeout = value;
218 }
219
220 public boolean hasNoTests()
221 {
222 return getResult() == NO_TESTS;
223 }
224
225 public boolean isFailure()
226 {
227 return getResult() == FAILURE;
228 }
229
230 public List<String> extractExceptionMessageLines() throws IOException
231 {
232 if ( getFailureMessage() == null )
233 {
234 return emptyList();
235 }
236
237 List<String> msg = new ArrayList<String>();
238 LineNumberReader reader = new LineNumberReader( new StringReader( getFailureMessage() ) );
239 for ( @SuppressWarnings( "checkstyle:innerassignment" ) String line; ( line = reader.readLine() ) != null; )
240 {
241 if ( !STACK_TRACE_ELEMENT1.matcher( line ).matches()
242 && !STACK_TRACE_ELEMENT2.matcher( line ).matches()
243 && !STACK_TRACE_ELEMENT3.matcher( line ).matches() )
244 {
245 line = line.trim();
246 msg.add( line.startsWith( ERROR_MSG_PREFIX ) ? line.substring( ERROR_MSG_PREFIX.length() ) : line );
247 }
248 else
249 {
250 break;
251 }
252 }
253 return msg;
254 }
255
256 @Override
257 public boolean equals( Object o )
258 {
259 if ( this == o )
260 {
261 return true;
262 }
263
264 if ( o == null || getClass() != o.getClass() )
265 {
266 return false;
267 }
268
269 FailsafeSummary summary = (FailsafeSummary) o;
270
271 return getCompleted() == summary.getCompleted()
272 && getErrors() == summary.getErrors()
273 && getFailures() == summary.getFailures()
274 && getSkipped() == summary.getSkipped()
275 && isTimeout() == summary.isTimeout()
276 && equal( getFailureMessage(), summary.getFailureMessage() )
277 && getResult() == summary.getResult();
278 }
279
280 @Override
281 public int hashCode()
282 {
283 int result1 = getCompleted();
284 result1 = 31 * result1 + getErrors();
285 result1 = 31 * result1 + getFailures();
286 result1 = 31 * result1 + getSkipped();
287 result1 = 31 * result1 + ( getFailureMessage() != null ? getFailureMessage().hashCode() : 0 );
288 result1 = 31 * result1 + ( getResult() != null ? getResult().hashCode() : 0 );
289 result1 = 31 * result1 + ( isTimeout() ? 1 : 0 );
290 return result1;
291 }
292
293 private boolean equal( String s1, String s2 )
294 {
295 return s1 == null ? s2 == null : s1.equals( s2 );
296 }
297 }