package org.apache.maven.surefire.booter;

/*
 * 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 junit.framework.TestCase;
import org.apache.maven.surefire.providerapi.ProviderParameters;
import org.apache.maven.surefire.providerapi.SurefireProvider;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.report.ReporterFactory;
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.suite.RunResult;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
import org.apache.maven.surefire.testset.RunOrderParameters;
import org.apache.maven.surefire.testset.TestArtifactInfo;
import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.util.RunOrder;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import static java.util.Arrays.asList;
import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG;
import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS;

/**
 *
 */
public class SurefireReflectorTest
        extends TestCase
{
    public void testShouldCreateFactoryWithoutException()
    {
        ReporterFactory factory = new ReporterFactory()
        {
            @Override
            public RunListener createReporter()
            {
                return null;
            }

            @Override
            public RunResult close()
            {
                return null;
            }
        };
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        SurefireReflector reflector = new SurefireReflector( cl );
        BaseProviderFactory bpf = (BaseProviderFactory) reflector.createBooterConfiguration( cl, true );
        bpf.setReporterFactory( factory );
        assertNotNull( bpf.getReporterFactory() );
        assertSame( factory, bpf.getReporterFactory() );
    }

    public void testSetDirectoryScannerParameters()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        DirectoryScannerParameters directoryScannerParameters =
                new DirectoryScannerParameters( new File( "ABC" ), new ArrayList<String>(), new ArrayList<String>(),
                        new ArrayList<String>(), false, "hourly" );
        surefireReflector.setDirectoryScannerParameters( foo, directoryScannerParameters );
        assertTrue( isCalled( foo ) );
        assertNotNull( ( (Foo) foo ).getDirectoryScannerParameters() );
    }

    public void testNullSetDirectoryScannerParameters()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        surefireReflector.setDirectoryScannerParameters( foo, null );
        assertTrue( isCalled( foo ) );
        assertNull( ( (Foo) foo ).getDirectoryScannerParameters() );
    }

    public void testSetIfDirScannerAware()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        DirectoryScannerParameters directoryScannerParameters =
            new DirectoryScannerParameters( new File( "ABC" ), new ArrayList<String>(), new ArrayList<String>(),
                new ArrayList<String>(), false, "hourly" );
        surefireReflector.setIfDirScannerAware( foo, directoryScannerParameters );
        assertTrue( isCalled( foo ) );
    }

    public void testRunOrderParameters()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, new File( "." ) );
        surefireReflector.setRunOrderParameters( foo, runOrderParameters );
        assertTrue( isCalled( foo ) );
    }

    public void testNullRunOrderParameters()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        surefireReflector.setRunOrderParameters( foo, null );
        assertTrue( isCalled( foo ) );
        assertNull( ( (Foo) foo ).getRunOrderCalculator() );
    }

    public void testTestSuiteDefinition()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        TestRequest testSuiteDefinition =
                new TestRequest( asList( new File( "file1" ), new File( "file2" ) ),
                        new File( "TestSOurce" ), new TestListResolver( "aUserRequestedTest#aMethodRequested" ) );
        surefireReflector.setTestSuiteDefinition( foo, testSuiteDefinition );
        assertTrue( isCalled( foo ) );
        assertNotNull( ( (Foo) foo ).getTestRequest() );
    }

    public void testNullTestSuiteDefinition()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();
        surefireReflector.setTestSuiteDefinition( foo, null );
        assertTrue( isCalled( foo ) );
        assertNull( ( (Foo) foo ).getTestRequest() );
    }

    public void testProviderProperties()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        surefireReflector.setProviderProperties( foo, new HashMap<String, String>() );
        assertTrue( isCalled( foo ) );
    }

    public void testReporterConfiguration()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        ReporterConfiguration reporterConfiguration = getReporterConfiguration();
        surefireReflector.setReporterConfigurationAware( foo, reporterConfiguration );
        assertTrue( isCalled( foo ) );
    }

    private ReporterConfiguration getReporterConfiguration()
    {
        return new ReporterConfiguration( new File( "CDE" ), true );
    }

    public void testTestClassLoader()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        surefireReflector.setTestClassLoader( foo, getClass().getClassLoader() );
        assertTrue( isCalled( foo ) );
    }

    public void testTestClassLoaderAware()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        surefireReflector.setTestClassLoaderAware( foo, getClass().getClassLoader() );
        assertTrue( isCalled( foo ) );
    }

    public void testArtifactInfo()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        TestArtifactInfo testArtifactInfo = new TestArtifactInfo( "12.3", "test" );
        surefireReflector.setTestArtifactInfo( foo, testArtifactInfo );
        assertTrue( isCalled( foo ) );
    }

    public void testNullArtifactInfo()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        surefireReflector.setTestArtifactInfo( foo, null );
        assertTrue( isCalled( foo ) );
        assertNull( ( (Foo) foo ).getTestArtifactInfo() );
    }

    public void testArtifactInfoAware()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        TestArtifactInfo testArtifactInfo = new TestArtifactInfo( "12.3", "test" );
        surefireReflector.setTestArtifactInfoAware( foo, testArtifactInfo );
        assertTrue( isCalled( foo ) );
        assertEquals( testArtifactInfo.getClassifier(), "test" );
        assertEquals( testArtifactInfo.getVersion(), "12.3" );
    }

    public void testReporterFactory()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        ReporterFactory reporterFactory = new ReporterFactory()
        {
            @Override
            public RunListener createReporter()
            {
                return null;
            }

            @Override
            public RunResult close()
            {
                return null;
            }
        };

        surefireReflector.setReporterFactory( foo, reporterFactory );
        assertTrue( isCalled( foo ) );
    }

    public void testReporterFactoryAware()
    {
        SurefireReflector surefireReflector = getReflector();
        Object foo = getFoo();

        ReporterFactory reporterFactory = new ReporterFactory()
        {
            @Override
            public RunListener createReporter()
            {
                return null;
            }

            @Override
            public RunResult close()
            {
                return null;
            }
        };

        surefireReflector.setReporterFactoryAware( foo, reporterFactory );
        assertTrue( isCalled( foo ) );
        assertSame( ( (Foo) foo ).getReporterFactory(), reporterFactory );
    }

    @SuppressWarnings( "checkstyle:magicnumber" )
    public void testConvertIfRunResult()
    {
        RunResult runResult = new RunResult( 20, 1, 2, 3, 4, "IOException", true );
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        RunResult obj = (RunResult) reflector.convertIfRunResult( runResult );
        assertEquals( obj.getCompletedCount(), 20 );
        assertEquals( obj.getErrors(), 1 );
        assertEquals( obj.getFailures(), 2 );
        assertEquals( obj.getSkipped(), 3 );
        assertFalse( obj.isErrorFree() );
        assertFalse( obj.isInternalError() );
        assertEquals( obj.getFailsafeCode(), (Integer) RunResult.FAILURE );

        assertNull( reflector.convertIfRunResult( null ) );
        assertEquals( reflector.convertIfRunResult( "" ), "" );
    }

    public void testInstantiateProvider()
    {
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        Object booterParams = getFoo();
        Object provider = reflector.instantiateProvider( DummyProvider.class.getName(), booterParams );
        assertNotNull( provider );
        assertEquals( provider.getClass(), DummyProvider.class );
    }

    public void testSetMainCliOptions()
    {
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        Object booterParams = getFoo();
        reflector.setMainCliOptions( booterParams, asList( SHOW_ERRORS, LOGGING_LEVEL_DEBUG ) );
        assertEquals( ( (BaseProviderFactory) booterParams ).getMainCliOptions().size(), 2 );
        assertEquals( ( (BaseProviderFactory) booterParams ).getMainCliOptions().get( 0 ), SHOW_ERRORS );
        assertEquals( ( (BaseProviderFactory) booterParams ).getMainCliOptions().get( 1 ), LOGGING_LEVEL_DEBUG );
    }

    public void testSetSkipAfterFailureCount()
    {
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        Foo booterParams = (Foo) getFoo();
        assertEquals( booterParams.getSkipAfterFailureCount(), 0 );
        reflector.setSkipAfterFailureCount( booterParams, 5 );
        assertEquals( booterParams.getSkipAfterFailureCount(), 5 );
    }

    @SuppressWarnings( "checkstyle:magicnumber" )
    public void testSetSystemExitTimeout()
    {
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        Foo booterParams = (Foo) getFoo();
        assertNull( booterParams.getSystemExitTimeout() );
        reflector.setSystemExitTimeout( booterParams, 60 );
        assertEquals( booterParams.getSystemExitTimeout(), (Integer) 60 );
    }

    public void testSetTestSuiteDefinitionAware()
    {
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        Foo booterParams = (Foo) getFoo();
        TestRequest request = new TestRequest( Collections.emptyList(), null, null );
        reflector.setTestSuiteDefinitionAware( booterParams, request );
        assertTrue( booterParams.isCalled() );
        assertNotNull( booterParams.getTestRequest() );
        assertTrue( booterParams.getTestRequest().getSuiteXmlFiles().isEmpty() );
        assertNull( booterParams.getTestRequest().getTestSourceDirectory() );
        assertNull( booterParams.getTestRequest().getTestListResolver() );
        assertEquals( booterParams.getTestRequest().getRerunFailingTestsCount(), 0 );
    }

    public void testSetProviderPropertiesAware()
    {
        SurefireReflector reflector = new SurefireReflector( Thread.currentThread().getContextClassLoader() );
        Foo booterParams = (Foo) getFoo();
        reflector.setProviderPropertiesAware( booterParams, Collections.singletonMap( "k", "v" ) );
        assertTrue( booterParams.isCalled() );
        assertNotNull( booterParams.getProviderProperties() );
        assertEquals( booterParams.getProviderProperties().size(), 1 );
        assertEquals( booterParams.getProviderProperties().get( "k" ), "v" );
    }

    private SurefireReflector getReflector()
    {
        return new SurefireReflector( getClass().getClassLoader() );
    }

    private Object getFoo()
    { // Todo: Setup a different classloader so we can really test crossing
        return new Foo();
    }

    private Boolean isCalled( Object foo )
    {
        final Method isCalled;
        try
        {
            isCalled = foo.getClass().getMethod( "isCalled" );
            return (Boolean) isCalled.invoke( foo );
        }
        catch ( ReflectiveOperationException e )
        {
            throw new RuntimeException( e );
        }
    }

    /**
     *
     */
    public static final class DummyProvider implements SurefireProvider
    {
        public DummyProvider( ProviderParameters providerParameters )
        {
        }

        @Override
        public Iterable<Class<?>> getSuites()
        {
            return null;
        }

        @Override
        public RunResult invoke( Object forkTestSet )
        {
            return null;
        }

        @Override
        public void cancel()
        {

        }
    }
}
