package org.apache.maven.plugins.enforcer;

/*
 * 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 static org.junit.jupiter.api.Assertions.*;

import org.apache.maven.enforcer.rule.api.EnforcerRule;
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

/**
 * Exhaustively check the enforcer mojo.
 * 
 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
 */
@ExtendWith( MockitoExtension.class )
@MockitoSettings( strictness = Strictness.LENIENT )
public class TestEnforceMojo
{

    @InjectMocks
    EnforceMojo mojo;

    @Test
    public void testEnforceMojo()
        throws MojoExecutionException
    {
        setupBasics( false );

        Log logSpy = setupLogSpy();

        try
        {
            mojo.execute();
            fail( "Expected a Mojo Execution Exception." );
        }
        catch ( MojoExecutionException e )
        {
            System.out.println( "Caught Expected Exception:" + e.getLocalizedMessage() );
        }

        EnforcerRule[] rules = new EnforcerRule[10];
        rules[0] = new MockEnforcerRule( true );
        rules[1] = new MockEnforcerRule( true );
        mojo.setRules( rules );

        mojo.execute();

        Mockito.verify( logSpy, Mockito.times(2) ).info( Mockito.contains("Executing rule: " + MockEnforcerRule.class.getName()) );

        try
        {
            mojo.setFailFast( false );
            mojo.setFail( true );
            mojo.execute();
            fail( "Expected a Mojo Execution Exception." );
        }
        catch ( MojoExecutionException e )
        {
            System.out.println( "Caught Expected Exception:" + e.getLocalizedMessage() );
        }

        try
        {
            mojo.setFailFast( true );
            mojo.setFail( true );
            mojo.execute();
            fail( "Expected a Mojo Execution Exception." );
        }
        catch ( MojoExecutionException e )
        {
            System.out.println( "Caught Expected Exception:" + e.getLocalizedMessage() );
        }

        ( (MockEnforcerRule) rules[0] ).setFailRule( false );
        ( (MockEnforcerRule) rules[1] ).setFailRule( false );
        mojo.execute();

    }

    @Test
    public void testCaching()
        throws MojoExecutionException
    {
        setupBasics( true );

        MockEnforcerRule[] rules = new MockEnforcerRule[10];

        // check that basic caching works.
        rules[0] = new MockEnforcerRule( false, "", true, true );
        rules[1] = new MockEnforcerRule( false, "", true, true );
        mojo.setRules( rules );

        EnforceMojo.cache.clear();
        mojo.execute();

        assertTrue( rules[0].executed, "Expected this rule to be executed." );
        assertFalse( rules[1].executed, "Expected this rule not to be executed." );

        // check that skip caching works.
        rules[0] = new MockEnforcerRule( false, "", true, true );
        rules[1] = new MockEnforcerRule( false, "", true, true );
        mojo.setRules( rules );

        EnforceMojo.cache.clear();
        mojo.ignoreCache = true;
        mojo.execute();

        assertTrue( rules[0].executed, "Expected this rule to be executed." );
        assertTrue( rules[1].executed, "Expected this rule to be executed." );

        mojo.ignoreCache = false;

        // check that different ids are compared.
        rules[0] = new MockEnforcerRule( false, "1", true, true );
        rules[1] = new MockEnforcerRule( false, "2", true, true );
        rules[2] = new MockEnforcerRule( false, "2", true, true );
        mojo.setRules( rules );

        EnforceMojo.cache.clear();
        mojo.execute();

        assertTrue( rules[0].executed, "Expected this rule to be executed." );
        assertTrue( rules[1].executed, "Expected this rule to be executed." );
        assertFalse( rules[2].executed, "Expected this rule not to be executed." );

        // check that future overrides are working
        rules[0] = new MockEnforcerRule( false, "1", true, true );
        rules[1] = new MockEnforcerRule( false, "1", false, true );
        rules[2] = null;
        mojo.setRules( rules );

        EnforceMojo.cache.clear();
        mojo.execute();

        assertTrue( rules[0].executed, "Expected this rule to be executed." );
        assertTrue( rules[1].executed, "Expected this rule to be executed." );

        // check that future isResultValid is used
        rules[0] = new MockEnforcerRule( false, "1", true, true );
        rules[1] = new MockEnforcerRule( false, "1", true, false );
        rules[2] = null;
        mojo.setRules( rules );

        EnforceMojo.cache.clear();
        mojo.execute();

        assertTrue( rules[0].executed, "Expected this rule to be executed." );
        assertTrue( rules[1].executed, "Expected this rule to be executed." );

    }

    @Test
    public void testCachePersistence1()
        throws MojoExecutionException
    {
        setupBasics( true );

        MockEnforcerRule[] rules = new MockEnforcerRule[10];

        // check that basic caching works.
        rules[0] = new MockEnforcerRule( false, "", true, true );
        rules[1] = new MockEnforcerRule( false, "", true, true );
        mojo.setRules( rules );

        EnforceMojo.cache.clear();
        mojo.execute();

        assertTrue( rules[0].executed, "Expected this rule to be executed." );
        assertFalse( rules[1].executed, "Expected this rule not to be executed." );

    }

    @Test
    public void testCachePersistence2()
        throws MojoExecutionException
    {
        setupBasics( true );

        MockEnforcerRule[] rules = new MockEnforcerRule[10];

        // check that basic caching works.
        rules[0] = new MockEnforcerRule( false, "", true, true );
        rules[1] = new MockEnforcerRule( false, "", true, true );
        mojo.setRules( rules );

        mojo.execute();

        assertFalse( rules[0].executed, "Expected this rule not to be executed." );
        assertFalse( rules[1].executed, "Expected this rule not to be executed." );

    }

    @Test
    public void testCachePersistence3()
        throws MojoExecutionException
    {
        System.gc();

        try
        {
            Thread.sleep( 1000 );
        }
        catch ( InterruptedException e )
        {
        }

        setupBasics( true );

        MockEnforcerRule[] rules = new MockEnforcerRule[10];

        // check that basic caching works.
        rules[0] = new MockEnforcerRule( false, "", true, true );
        rules[1] = new MockEnforcerRule( false, "", true, true );
        mojo.setRules( rules );

        mojo.execute();

        assertFalse( rules[0].executed, "Expected this rule not to be executed." );
        assertFalse( rules[1].executed, "Expected this rule not to be executed." );

    }

    @Test
    public void testLoggingOnEnforcerRuleExceptionWithMessage()
        throws MojoExecutionException, EnforcerRuleException
    {
        // fail=false because this is out of scope here (also allows for cleaner test code without catch block)
        setupBasics( false );

        // the regular kind of EnforcerRuleException:
        EnforcerRuleException ruleException = new EnforcerRuleException( "testMessage" );

        EnforcerRule ruleMock = Mockito.mock( EnforcerRule.class );
        Mockito.doThrow( ruleException ).when( ruleMock ).execute( Mockito.any( EnforcerRuleHelper.class ) );

        mojo.setRules( new EnforcerRule[] { ruleMock } );

        Log logSpy = setupLogSpy();

        mojo.execute();

        Mockito.verify( logSpy ).debug( Mockito.anyString(), Mockito.same( ruleException ) );

        Mockito.verify( logSpy, Mockito.never() ).warn( Mockito.anyString(), Mockito.any( Throwable.class ) );

        Mockito.verify( logSpy ).warn( Mockito.matches( ".* failed with message:" + System.lineSeparator()
            + ruleException.getMessage() ) );
    }

    @Test
    public void testLoggingOnEnforcerRuleExceptionWithoutMessage()
        throws MojoExecutionException, EnforcerRuleException
    {
        // fail=false because this is out of scope here (also allows for cleaner test code without catch block)
        setupBasics( false );

        // emulate behaviour of various rules that just catch Exception and wrap into EnforcerRuleException:
        NullPointerException npe = new NullPointerException();
        EnforcerRuleException enforcerRuleException = new EnforcerRuleException( npe.getLocalizedMessage(), npe );

        EnforcerRule ruleMock = Mockito.mock( EnforcerRule.class );
        Mockito.doThrow( enforcerRuleException ).when( ruleMock ).execute( Mockito.any( EnforcerRuleHelper.class ) );

        mojo.setRules( new EnforcerRule[] { ruleMock } );

        Log logSpy = setupLogSpy();

        mojo.execute();

        Mockito.verify( logSpy ).warn( Mockito.contains( "failed without a message" ),
                                       Mockito.same( enforcerRuleException ) );

        Mockito.verify( logSpy ).warn( Mockito.matches( ".* failed with message:" + System.lineSeparator() + "null" ) );
    }

    private void setupBasics( boolean fail )
    {
        mojo.setFail( fail );
        mojo.setSession( EnforcerTestUtils.getMavenSession() );
        mojo.setProject( new MockProject() );
    }

    private Log setupLogSpy()
    {
        Log spy = Mockito.spy( mojo.getLog() );
        mojo.setLog( spy );
        return spy;
    }
}
