View Javadoc
1   package org.apache.maven.plugin.failsafe.xmlsummary;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * <p>Java class for anonymous complex type.
42   * <p/>
43   * <p>The following schema fragment specifies the expected content contained within this class.
44   * <p/>
45   * <pre>
46   * &lt;complexType>
47   *   &lt;complexContent>
48   *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
49   *       &lt;sequence>
50   *         &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}int"/>
51   *         &lt;element name="errors" type="{http://www.w3.org/2001/XMLSchema}int"/>
52   *         &lt;element name="failures" type="{http://www.w3.org/2001/XMLSchema}int"/>
53   *         &lt;element name="skipped" type="{http://www.w3.org/2001/XMLSchema}int"/>
54   *         &lt;element name="failureMessage" type="{http://www.w3.org/2001/XMLSchema}string"/>
55   *       &lt;/sequence>
56   *       &lt;attribute name="result" type="{}errorType" />
57   *       &lt;attribute name="timeout" use="required" type="{http://www.w3.org/2001/XMLSchema}boolean" />
58   *     &lt;/restriction>
59   *   &lt;/complexContent>
60   * &lt;/complexType>
61   * </pre>
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       * Gets the value of the completed property.
98       */
99      public int getCompleted()
100     {
101         return completed;
102     }
103 
104     /**
105      * Sets the value of the completed property.
106      */
107     public void setCompleted( int value )
108     {
109         this.completed = value;
110     }
111 
112     /**
113      * Gets the value of the errors property.
114      */
115     public int getErrors()
116     {
117         return errors;
118     }
119 
120     /**
121      * Sets the value of the errors property.
122      */
123     public void setErrors( int value )
124     {
125         this.errors = value;
126     }
127 
128     /**
129      * Gets the value of the failures property.
130      */
131     public int getFailures()
132     {
133         return failures;
134     }
135 
136     /**
137      * Sets the value of the failures property.
138      */
139     public void setFailures( int value )
140     {
141         this.failures = value;
142     }
143 
144     /**
145      * Gets the value of the skipped property.
146      */
147     public int getSkipped()
148     {
149         return skipped;
150     }
151 
152     /**
153      * Sets the value of the skipped property.
154      */
155     public void setSkipped( int value )
156     {
157         this.skipped = value;
158     }
159 
160     /**
161      * Gets the value of the failureMessage property.
162      *
163      * @return possible object is
164      * {@link String }
165      */
166     public String getFailureMessage()
167     {
168         return failureMessage;
169     }
170 
171     /**
172      * Sets the value of the failureMessage property.
173      *
174      * @param value allowed object is
175      *              {@link String }
176      */
177     public void setFailureMessage( String value )
178     {
179         this.failureMessage = value;
180     }
181 
182     /**
183      * Gets the value of the result property.
184      *
185      * @return possible object is
186      * {@link ErrorType }
187      */
188     public ErrorType getResult()
189     {
190         return result;
191     }
192 
193     /**
194      * Sets the value of the result property.
195      *
196      * @param value allowed object is
197      *              {@link ErrorType }
198      */
199     public void setResult( ErrorType value )
200     {
201         this.result = value;
202     }
203 
204     /**
205      * Gets the value of the timeout property.
206      */
207     public boolean isTimeout()
208     {
209         return timeout;
210     }
211 
212     /**
213      * Sets the value of the timeout property.
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 }