| package org.apache.maven.surefire.report; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.lang.reflect.Field; |
| import java.util.List; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.FutureTask; |
| |
| import junit.framework.AssertionFailedError; |
| import junit.framework.ComparisonFailure; |
| import junit.framework.TestCase; |
| import org.apache.maven.surefire.util.internal.DaemonThreadFactory; |
| |
| import static org.apache.maven.surefire.report.SmartStackTraceParser.findTopmostWithClass; |
| import static org.apache.maven.surefire.report.SmartStackTraceParser.focusInsideClass; |
| import static org.apache.maven.surefire.report.SmartStackTraceParser.stackTraceWithFocusOnClassAsString; |
| |
| /** |
| * |
| */ |
| @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" ) |
| public class SmartStackTraceParserTest |
| extends TestCase |
| { |
| public void testGetString() |
| { |
| ATestClass aTestClass = new ATestClass(); |
| try |
| { |
| aTestClass.failInAssert(); |
| } |
| catch ( AssertionError e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass.failInAssert:33 X is not Z", res ); |
| } |
| } |
| |
| public void testGetStringFromNested() |
| { |
| OutermostClass aTestClass = new OutermostClass(); |
| try |
| { |
| aTestClass.junit(); |
| } |
| catch ( AssertionError e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass.failInAssert:33 X is not Z", res ); |
| } |
| } |
| |
| public void testGetStringWithMethod() |
| { |
| OutermostClass aTestClass = new OutermostClass(); |
| try |
| { |
| aTestClass.junit(); |
| } |
| catch ( AssertionError e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( InnerATestClass.class.getName(), e, "myMethod" ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "InnerATestClass.myMethod X is not Z", res ); |
| } |
| } |
| |
| public void testNestedFailure() |
| { |
| ATestClass aTestClass = new ATestClass(); |
| try |
| { |
| aTestClass.nestedFailInAssert(); |
| } |
| catch ( AssertionError e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass.nestedFailInAssert:38->failInAssert:33 X is not Z", res ); |
| } |
| } |
| |
| public void testNestedNpe() |
| { |
| ATestClass aTestClass = new ATestClass(); |
| try |
| { |
| aTestClass.nestedNpe(); |
| } |
| catch ( NullPointerException e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass.nestedNpe:48->npe:43 NullPointer It was null", res ); |
| } |
| } |
| |
| public void testNestedNpeOutsideTest() |
| { |
| ATestClass aTestClass = new ATestClass(); |
| try |
| { |
| aTestClass.nestedNpeOutsideTest(); |
| } |
| catch ( NullPointerException e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass.nestedNpeOutsideTest:58->npeOutsideTest:53 » NullPointer", res ); |
| } |
| } |
| |
| public void testLongMessageTruncation() |
| { |
| ATestClass aTestClass = new ATestClass(); |
| try |
| { |
| aTestClass.aLongTestErrorMessage(); |
| } |
| catch ( RuntimeException e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass.aLongTestErrorMessage:63 Runtime This message will be truncated, so...", |
| res ); |
| } |
| } |
| |
| public void testFailureInBaseClass() |
| { |
| ASubClass aTestClass = new ASubClass(); |
| try |
| { |
| aTestClass.npe(); |
| } |
| catch ( NullPointerException e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ASubClass.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ASubClass>ABaseClass.npe:29 » NullPointer It was null", res ); |
| } |
| } |
| |
| public void testClassThatWillFail() |
| { |
| CaseThatWillFail aTestClass = new CaseThatWillFail(); |
| try |
| { |
| aTestClass.testThatWillFail(); |
| } |
| catch ( ComparisonFailure e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( CaseThatWillFail.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "CaseThatWillFail.testThatWillFail:29 expected:<[abc]> but was:<[def]>", res ); |
| } |
| } |
| |
| private static Throwable getAThrownException() |
| { |
| try |
| { |
| TestClass1.InnerBTestClass.throwSomething(); |
| } |
| catch ( Throwable t ) |
| { |
| return t; |
| } |
| return null; |
| } |
| |
| public void testCollections() |
| { |
| Throwable aThrownException = getAThrownException(); |
| List<StackTraceElement> innerMost = |
| focusInsideClass( aThrownException.getCause().getStackTrace(), |
| new ClassNameStackTraceFilter( TestClass1.InnerBTestClass.class.getName() ) ); |
| assertEquals( 2, innerMost.size() ); |
| StackTraceElement inner = innerMost.get( 0 ); |
| assertEquals( TestClass1.InnerBTestClass.class.getName(), inner.getClassName() ); |
| StackTraceElement outer = innerMost.get( 1 ); |
| assertEquals( TestClass1.InnerBTestClass.class.getName(), outer.getClassName() ); |
| } |
| |
| public void testAssertionWithNoMessage() |
| { |
| try |
| { |
| new AssertionNoMessage().testThrowSomething(); |
| } |
| catch ( ComparisonFailure e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( AssertionNoMessage.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "AssertionNoMessage.testThrowSomething:29 expected:<[abc]> but was:<[xyz]>", res ); |
| } |
| } |
| |
| public void testFailWithFail() |
| { |
| try |
| { |
| new FailWithFail().testThatWillFail(); |
| } |
| catch ( AssertionFailedError e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( FailWithFail.class.getName(), e, null ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "FailWithFail.testThatWillFail:29 abc", res ); |
| } |
| } |
| |
| public void testCollectorWithNested() |
| { |
| try |
| { |
| InnerATestClass.testFake(); |
| } |
| catch ( Throwable t ) |
| { |
| List<StackTraceElement> stackTraceElements = |
| focusInsideClass( t.getStackTrace(), |
| new ClassNameStackTraceFilter( InnerATestClass.class.getName() ) ); |
| assertNotNull( stackTraceElements ); |
| assertEquals( 2, stackTraceElements.size() ); |
| StackTraceElement innerMost = stackTraceElements.get( 0 ); |
| assertEquals( InnerATestClass.class.getName(), innerMost.getClassName() ); |
| StackTraceElement outer = stackTraceElements.get( 1 ); |
| assertEquals( InnerATestClass.class.getName(), outer.getClassName() ); |
| } |
| } |
| |
| public void testNonClassNameStacktrace() |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( "Not a class name", new Throwable( "my message" ), null ); |
| assertEquals( "my message", smartStackTraceParser.getString() ); |
| } |
| |
| public void testNullElementInStackTrace() |
| throws Exception |
| { |
| ATestClass aTestClass = new ATestClass(); |
| try |
| { |
| aTestClass.failInAssert(); |
| } |
| catch ( AssertionError e ) |
| { |
| SmartStackTraceParser smartStackTraceParser = |
| new SmartStackTraceParser( ATestClass.class.getName(), e, null ); |
| Field stackTrace = SmartStackTraceParser.class.getDeclaredField( "stackTrace" ); |
| stackTrace.setAccessible( true ); |
| stackTrace.set( smartStackTraceParser, new StackTraceElement[0] ); |
| String res = smartStackTraceParser.getString(); |
| assertEquals( "ATestClass X is not Z", res ); |
| } |
| } |
| |
| public void testSingleNestedWithThread() |
| { |
| ExecutionException e = getSingleNested(); |
| String name = getClass().getName(); |
| Throwable focus = findTopmostWithClass( e, new ClassNameStackTraceFilter( name ) ); |
| assertSame( e, focus ); |
| List<StackTraceElement> stackTraceElements = |
| focusInsideClass( focus.getStackTrace(), new ClassNameStackTraceFilter( name ) ); |
| assertEquals( stackTraceElements.get( stackTraceElements.size() - 1 ).getClassName(), name ); |
| } |
| |
| public void testDoubleNestedWithThread() |
| { |
| ExecutionException e = getDoubleNestedException(); |
| |
| String name = getClass().getName(); |
| Throwable focus = findTopmostWithClass( e, new ClassNameStackTraceFilter( name ) ); |
| assertSame( e, focus ); |
| List<StackTraceElement> stackTraceElements = |
| focusInsideClass( focus.getStackTrace(), new ClassNameStackTraceFilter( name ) ); |
| assertEquals( stackTraceElements.get( stackTraceElements.size() - 1 ).getClassName(), name ); |
| |
| name = RunnableTestClass1.class.getName(); |
| focus = findTopmostWithClass( e, new ClassNameStackTraceFilter( name ) ); |
| assertSame( e.getCause(), focus ); |
| stackTraceElements = focusInsideClass( focus.getStackTrace(), new ClassNameStackTraceFilter( name ) ); |
| assertEquals( stackTraceElements.get( stackTraceElements.size() - 1 ).getClassName(), name ); |
| } |
| |
| public void testStackTraceWithFocusOnClassAsString() |
| { |
| try |
| { |
| new StackTraceFocusedOnClass.C().c(); |
| fail(); |
| } |
| catch ( Exception e ) |
| { |
| String trace = stackTraceWithFocusOnClassAsString( e, StackTraceFocusedOnClass.B.class.getName() ); |
| |
| assertEquals( |
| "java.lang.RuntimeException: java.lang.IllegalStateException: java.io.IOException: I/O error\n" |
| + "\tat org.apache.maven.surefire.report.StackTraceFocusedOnClass$B.b(StackTraceFocusedOnClass.java:65)\n" |
| + "Caused by: java.lang.IllegalStateException: java.io.IOException: I/O error\n" |
| + "\tat org.apache.maven.surefire.report.StackTraceFocusedOnClass$B.b(StackTraceFocusedOnClass.java:61)\n" |
| + "Caused by: java.io.IOException: I/O error\n" |
| + "\tat org.apache.maven.surefire.report.StackTraceFocusedOnClass$B.abs(StackTraceFocusedOnClass.java:73)\n" |
| + "\tat org.apache.maven.surefire.report.StackTraceFocusedOnClass$B.b(StackTraceFocusedOnClass.java:61)\n", |
| trace ); |
| } |
| } |
| |
| private ExecutionException getSingleNested() |
| { |
| FutureTask<Object> futureTask = new FutureTask<>( new RunnableTestClass2() ); |
| DaemonThreadFactory.newDaemonThread( futureTask ).start(); |
| try |
| { |
| futureTask.get(); |
| } |
| catch ( InterruptedException e ) |
| { |
| fail(); |
| } |
| catch ( ExecutionException e ) |
| { |
| return e; |
| } |
| fail(); |
| return null; |
| } |
| |
| private ExecutionException getDoubleNestedException() |
| { |
| FutureTask<Object> futureTask = new FutureTask<>( new RunnableTestClass1() ); |
| DaemonThreadFactory.newDaemonThread( futureTask ).start(); |
| try |
| { |
| futureTask.get(); |
| } |
| catch ( InterruptedException e ) |
| { |
| fail(); |
| } |
| catch ( ExecutionException e ) |
| { |
| return e; |
| } |
| return null; |
| } |
| } |