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;
    }
}
