Coverage Report - org.apache.maven.surefire.report.SmartStackTraceParser
 
Classes in this File Line Coverage Branch Coverage Complexity
SmartStackTraceParser
95%
96/101
85%
53/62
3,786
 
 1  
 package org.apache.maven.surefire.report;
 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 java.util.ArrayList;
 23  
 import java.util.Collections;
 24  
 import java.util.List;
 25  
 import org.apache.maven.shared.utils.StringUtils;
 26  
 
 27  
 /**
 28  
  * @author Kristian Rosenvold
 29  
  */
 30  
 @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" )
 31  
 public class SmartStackTraceParser
 32  
 {
 33  
 
 34  
     private final SafeThrowable throwable;
 35  
 
 36  
     private final StackTraceElement[] stackTrace;
 37  
 
 38  
     private final String simpleName;
 39  
 
 40  
     private String testClassName;
 41  
 
 42  
     private final Class testClass;
 43  
 
 44  
     public SmartStackTraceParser( Class testClass, Throwable throwable )
 45  
     {
 46  10
         this( testClass.getName(), throwable );
 47  10
     }
 48  
 
 49  
     public SmartStackTraceParser( String testClassName, Throwable throwable )
 50  11
     {
 51  11
         this.testClassName = testClassName;
 52  11
         this.testClass = getClass( testClassName );
 53  11
         this.simpleName = this.testClassName.substring( this.testClassName.lastIndexOf( "." ) + 1 );
 54  11
         this.throwable = new SafeThrowable( throwable );
 55  11
         stackTrace = throwable.getStackTrace();
 56  11
     }
 57  
 
 58  
     private static Class getClass( String name )
 59  
     {
 60  
         try
 61  
         {
 62  11
             return Thread.currentThread().getContextClassLoader().loadClass( name );
 63  
         }
 64  1
         catch ( ClassNotFoundException e )
 65  
         {
 66  1
             return null;
 67  
         }
 68  
     }
 69  
 
 70  
     private static String getSimpleName( String className )
 71  
     {
 72  1
         int i = className.lastIndexOf( "." );
 73  1
         return className.substring( i + 1 );
 74  
     }
 75  
 
 76  
     @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" )
 77  
     public String getString()
 78  
     {
 79  11
         if ( testClass == null )
 80  
         {
 81  1
             return throwable.getLocalizedMessage();
 82  
         }
 83  
 
 84  10
         StringBuilder result = new StringBuilder();
 85  10
         List<StackTraceElement> stackTraceElements = focusOnClass( stackTrace, testClass );
 86  10
         Collections.reverse( stackTraceElements );
 87  
         StackTraceElement stackTraceElement;
 88  10
         if (stackTrace.length == 0)
 89  
         {
 90  1
             result.append( simpleName );
 91  1
             result.append("XX");
 92  
         }
 93  22
         for ( int i = 0; i < stackTraceElements.size(); i++ )
 94  
         {
 95  12
             stackTraceElement = stackTraceElements.get( i );
 96  12
             if ( i == 0 )
 97  
             {
 98  9
                 result.append( simpleName );
 99  9
                 if ( !stackTraceElement.getClassName().equals( testClassName ) )
 100  
                 {
 101  1
                     result.append( ">" );
 102  
                 }
 103  
                 else
 104  
                 {
 105  8
                     result.append( "." );
 106  
                 }
 107  
 
 108  
             }
 109  12
             if ( !stackTraceElement.getClassName().equals( testClassName ) )
 110  
             {
 111  1
                 result.append( getSimpleName( stackTraceElement.getClassName() ) ); // Add the name of the superclas
 112  1
                 result.append( "." );
 113  
             }
 114  12
             result.append( stackTraceElement.getMethodName() ).append( ":" ).append( stackTraceElement.getLineNumber() );
 115  12
             result.append( "->" );
 116  
         }
 117  
 
 118  10
         if ( result.length() >= 2 )
 119  
         {
 120  10
             result.deleteCharAt( result.length() - 1 );
 121  10
             result.deleteCharAt( result.length() - 1 );
 122  
         }
 123  
 
 124  10
         Throwable target = throwable.getTarget();
 125  10
         if ( target instanceof AssertionError )
 126  
         {
 127  3
             result.append( " " );
 128  3
             result.append( throwable.getMessage() );
 129  
         }
 130  7
         else if ( "junit.framework.AssertionFailedError".equals( target.getClass().getName() )
 131  
             || "junit.framework.ComparisonFailure".equals( target.getClass().getName() ) )
 132  
         {
 133  3
             result.append( " " );
 134  3
             result.append( throwable.getMessage() );
 135  
         }
 136  
         else
 137  
         {
 138  4
             result.append( rootIsInclass() ? " " : " ยป " );
 139  4
             result.append( getMinimalThrowableMiniMessage( target ) );
 140  4
             result.append( getTruncatedMessage( 77 - result.length() ) );
 141  
         }
 142  10
         return result.toString();
 143  
     }
 144  
 
 145  
     private String getMinimalThrowableMiniMessage( Throwable throwable )
 146  
     {
 147  4
         String name = throwable.getClass().getSimpleName();
 148  4
         if ( name.endsWith( "Exception" ) )
 149  
         {
 150  4
             return StringUtils.chompLast( name, "Exception" );
 151  
         }
 152  0
         if ( name.endsWith( "Error" ) )
 153  
         {
 154  0
             return StringUtils.chompLast( name, "Error" );
 155  
         }
 156  0
         return name;
 157  
     }
 158  
 
 159  
     private String getTruncatedMessage( int i )
 160  
     {
 161  4
         if ( i < 0 )
 162  
         {
 163  0
             return "";
 164  
         }
 165  4
         String msg = throwable.getMessage();
 166  4
         if ( msg == null )
 167  
         {
 168  1
             return "";
 169  
         }
 170  3
         String substring = msg.substring( 0, Math.min( i, msg.length() ) );
 171  3
         if ( i < msg.length() )
 172  
         {
 173  1
             return " " + substring + "...";
 174  
         }
 175  
         else
 176  
         {
 177  2
             return " " + substring;
 178  
         }
 179  
     }
 180  
 
 181  
     private boolean rootIsInclass()
 182  
     {
 183  4
         return  stackTrace.length > 0 && stackTrace[0].getClassName().equals( testClassName );
 184  
     }
 185  
 
 186  
     static List<StackTraceElement> focusOnClass( StackTraceElement[] stackTrace, Class clazz )
 187  
     {
 188  10
         List<StackTraceElement> result = new ArrayList<StackTraceElement>();
 189  289
         for ( StackTraceElement element : stackTrace )
 190  
         {
 191  279
             if ( element != null && isInSupers( clazz, element.getClassName() ) )
 192  
             {
 193  12
                 result.add( element );
 194  
             }
 195  
         }
 196  10
         return result;
 197  
     }
 198  
 
 199  
     private static boolean isInSupers( Class testClass, String lookFor )
 200  
     {
 201  279
         if ( lookFor.startsWith( "junit.framework." ) )
 202  
         {
 203  77
             return false;
 204  
         }
 205  540
         while ( !testClass.getName().equals( lookFor ) && testClass.getSuperclass() != null )
 206  
         {
 207  338
             testClass = testClass.getSuperclass();
 208  
         }
 209  202
         return testClass.getName().equals( lookFor );
 210  
     }
 211  
 
 212  
     private static Throwable findInnermost( Throwable t )
 213  
     {
 214  1
         Throwable real = t;
 215  1
         while ( real.getCause() != null )
 216  
         {
 217  0
             real = real.getCause();
 218  
         }
 219  1
         return real;
 220  
     }
 221  
 
 222  
     public static String innerMostWithFocusOnClass( Throwable t, String className )
 223  
     {
 224  1
         List<StackTraceElement> stackTraceElements = focusInsideClass( findInnermost( t ).getStackTrace(), className );
 225  1
         return toString( t, stackTraceElements );
 226  
     }
 227  
 
 228  
     static List<StackTraceElement> focusInsideClass( StackTraceElement[] stackTrace, String className )
 229  
     {
 230  3
         List<StackTraceElement> result = new ArrayList<StackTraceElement>();
 231  3
         boolean found = false;
 232  12
         for ( StackTraceElement element : stackTrace )
 233  
         {
 234  12
             if ( !found )
 235  
             {
 236  7
                 result.add( element );
 237  
             }
 238  
 
 239  12
             if ( className.equals( element.getClassName() ) )
 240  
             {
 241  5
                 if ( found )
 242  
                 {
 243  2
                     result.add( element );
 244  
                 }
 245  5
                 found = true;
 246  
             }
 247  
             else
 248  
             {
 249  7
                 if ( found )
 250  
                 {
 251  3
                     break;
 252  
                 }
 253  
             }
 254  
         }
 255  3
         return result;
 256  
     }
 257  
 
 258  
     public static String toString( Throwable t, List<StackTraceElement> elements )
 259  
     {
 260  1
         StringBuilder result = new StringBuilder();
 261  1
         result.append( t.getClass().getName() );
 262  1
         result.append( ": " );
 263  1
         result.append( t.getMessage() );
 264  1
         result.append( "\n" );
 265  
 
 266  1
         for ( StackTraceElement element : elements )
 267  
         {
 268  1
             result.append( "\tat " ).append( element.toString() );
 269  1
             result.append( "\n" );
 270  
         }
 271  1
         return result.toString();
 272  
     }
 273  
 }