package org.apache.maven.it;

/*
 * 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 org.apache.maven.it.util.ResourceExtractor;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;

import junit.framework.TestCase;

/**
 * This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-2690">MNG-2690</a>.
 * 
 * It checks, at the most basic level possible, that the plugin manager is intercepting things like
 * {@link NoClassDefFoundError} and ComponntLookupException, then throwing user-friendly errors when loading and
 * configuring a mojo.
 * 
 * @author jdcasey
 */
public class MavenITmng2690MojoLoadingErrorsTest
    extends AbstractMavenIntegrationTestCase
{

    public MavenITmng2690MojoLoadingErrorsTest()
    {
        super( "(2.1.0-M1,)" );
    }

    public void testNoClassDefFromMojoLoad()
        throws IOException, VerificationException
    {
        File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-2690/noclassdef-mojo" );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );

        try
        {
            verifier.executeGoal( "validate" );

            fail( "should throw an error during execution." );
        }
        catch ( VerificationException e )
        {
            // expected...it'd be nice if we could get the specifics of the exception right here...
        }
        finally
        {
            verifier.resetStreams();
        }

        List<String> lines = verifier.loadFile( new File( testDir, "log.txt" ), false );

        int msg = indexOf( lines, "(?i).*required class is missing.*" );
        assertTrue( "User-friendly message was not found in output.", msg >= 0 );

        int cls = lines.get( msg ).toString().replace( '/', '.' ).indexOf( TestCase.class.getName() );
        assertTrue( "Missing class name was not found in output.", cls >= 0 );
    }

    public void testNoClassDefFromMojoConfiguration()
        throws IOException, VerificationException
    {
        File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-2690/noclassdef-param" );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );

        try
        {
            verifier.executeGoal( "validate" );

            fail( "should throw an error during execution." );
        }
        catch ( VerificationException e )
        {
            // expected...it'd be nice if we could get the specifics of the exception right here...
        }
        finally
        {
            verifier.resetStreams();
        }

        List<String> lines = verifier.loadFile( new File( testDir, "log.txt" ), false );

        int msg = indexOf( lines, "(?i).*required class (i|wa)s missing( during (mojo )?configuration)?.*" );
        assertTrue( "User-friendly message was not found in output.", msg >= 0 );

        int cls = lines.get( msg ).toString().replace( '/', '.' ).indexOf( TestCase.class.getName() );
        assertTrue( "Missing class name was not found in output.", cls >= 0 );
    }

    public void testMojoComponentLookupException()
        throws IOException, VerificationException
    {
        File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-2690/mojo-complookup" );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );

        try
        {
            verifier.executeGoal( "validate" );

            fail( "should throw an error during execution." );
        }
        catch ( VerificationException e )
        {
            // expected...it'd be nice if we could get the specifics of the exception right here...
        }
        finally
        {
            verifier.resetStreams();
        }

        List<String> lines = verifier.loadFile( new File( testDir, "log.txt" ), false );

        String compLookupMsg =
            "(?i).*unable to .* mojo 'mojo-component-lookup-exception' .* plugin "
                + "'org\\.apache\\.maven\\.its\\.plugins:maven-it-plugin-error.*";

        assertTrue( "User-friendly message was not found in output.", indexOf( lines, compLookupMsg ) > 0 );
    }

    public void testMojoRequirementComponentLookupException()
        throws IOException, VerificationException
    {
        File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-2690/requirement-complookup" );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );

        try
        {
            verifier.executeGoal( "validate" );

            fail( "should throw an error during execution." );
        }
        catch ( VerificationException e )
        {
            // expected...it'd be nice if we could get the specifics of the exception right here...
        }
        finally
        {
            verifier.resetStreams();
        }

        List<String> lines = verifier.loadFile( new File( testDir, "log.txt" ), false );

        String compLookupMsg =
            "(?i).*unable to .* mojo 'requirement-component-lookup-exception' .* plugin "
                + "'org\\.apache\\.maven\\.its\\.plugins:maven-it-plugin-error.*";

        assertTrue( "User-friendly message was not found in output.", indexOf( lines, compLookupMsg ) > 0 );
    }

    private int indexOf( List<String> logLines, String regex )
    {
        Pattern pattern = Pattern.compile( regex );

        for ( int i = 0; i < logLines.size(); i++ )
        {
            String logLine = logLines.get( i );

            if ( pattern.matcher( logLine ).matches() )
            {
                return i;
            }
        }

        return -1;
    }

}
