Package org.mapstruct.itest.testutil.runner

Source Code of org.mapstruct.itest.testutil.runner.ProcessorSuiteRunner$ProcessorTestCase

/**
*  Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
*  and/or other contributors as indicated by the @authors tag. See the
*  copyright.txt file in the distribution for a full listing of all
*  contributors.
*
*  Licensed 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.
*/
package org.mapstruct.itest.testutil.runner;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.maven.it.Verifier;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runner.notification.StoppedByUserException;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.InitializationError;
import org.mapstruct.itest.testutil.runner.ProcessorSuite.ProcessorType;
import org.mapstruct.itest.testutil.runner.ProcessorSuiteRunner.ProcessorTestCase;

import static org.apache.maven.it.util.ResourceExtractor.extractResourceToDestination;
import static org.apache.maven.shared.utils.io.FileUtils.copyURLToFile;
import static org.apache.maven.shared.utils.io.FileUtils.deleteDirectory;

/**
* Runner for processor integration tests. Requires the annotation {@link ProcessorSuite} on the test class.
*
* @author Andreas Gudian
*/
public class ProcessorSuiteRunner extends ParentRunner<ProcessorTestCase> {

    /**
     * System property for specifying the location of the toolchains.xml file
     */
    public static final String SYS_PROP_TOOLCHAINS_FILE = "processorIntegrationTest.toolchainsFile";

    /**
     * System property to enable remote debugging of the processor execution in the integration test
     */
    public static final String SYS_PROP_DEBUG = "processorIntegrationTest.debug";

    public static final class ProcessorTestCase {
        private final String baseDir;
        private final ProcessorType processor;
        private final boolean ignored;

        public ProcessorTestCase(String baseDir, ProcessorType processor) {
            this.baseDir = baseDir;
            this.processor = processor;
            this.ignored = !TOOLCHAINS_ENABLED && processor.getToolchain() != null;
        }
    }

    private static final File SPECIFIED_TOOLCHAINS_FILE = getSpecifiedToolchainsFile();
    private static final boolean TOOLCHAINS_ENABLED = toolchainsFileExists();

    private final List<ProcessorTestCase> methods;

    /**
     * @param clazz the test class
     * @throws InitializationError in case the initialization fails
     */
    public ProcessorSuiteRunner(Class<?> clazz) throws InitializationError {
        super( clazz );

        ProcessorSuite suite = clazz.getAnnotation( ProcessorSuite.class );

        if ( null == suite ) {
            throw new InitializationError( "The test class must be annotated with " + ProcessorSuite.class.getName() );
        }

        if ( suite.processorTypes().length == 0 ) {
            throw new InitializationError( "ProcessorSuite#processorTypes must not be empty" );
        }

        methods = initializeTestCases( suite );
    }

    private List<ProcessorTestCase> initializeTestCases(ProcessorSuite suite) {
        List<ProcessorType> types = new ArrayList<ProcessorType>();

        for ( ProcessorType compiler : suite.processorTypes() ) {
            if ( compiler.getIncluded().length > 0 ) {
                types.addAll( Arrays.asList( compiler.getIncluded() ) );
            }
            else {
                types.add( compiler );
            }
        }

        List<ProcessorTestCase> result = new ArrayList<ProcessorTestCase>( types.size() );

        for ( ProcessorType type : types ) {
            result.add( new ProcessorTestCase( suite.baseDir(), type ) );
        }

        return result;
    }

    @Override
    protected List<ProcessorTestCase> getChildren() {
        return methods;
    }

    @Override
    protected Description describeChild(ProcessorTestCase child) {
        return Description.createTestDescription( getTestClass().getJavaClass(), child.processor.name().toLowerCase() );
    }

    @Override
    protected void runChild(ProcessorTestCase child, RunNotifier notifier) {
        Description description = describeChild( child );
        EachTestNotifier testNotifier = new EachTestNotifier( notifier, description );

        if ( child.ignored ) {
            testNotifier.fireTestIgnored();
        }
        else {
            try {
                testNotifier.fireTestStarted();
                doExecute( child, description );
            }
            catch ( AssumptionViolatedException e ) {
                testNotifier.fireTestIgnored();
            }
            catch ( StoppedByUserException e ) {
                throw e;
            }
            catch ( Throwable e ) {
                testNotifier.addFailure( e );
            }
            finally {
                testNotifier.fireTestFinished();
            }
        }
    }

    private void doExecute(ProcessorTestCase child, Description description) throws Exception {
        File destination = extractTest( child, description );
        PrintStream originalOut = System.out;

        final Verifier verifier;
        if ( Boolean.getBoolean( SYS_PROP_DEBUG ) ) {
            if ( child.processor.getToolchain() == null ) {
                // when not using toolchains for a test, then the compiler is executed within the Maven JVM. So make
                // sure we fork a new JVM for that, and let that new JVM use the command 'mvnDebug' instead of 'mvn'
                verifier = new Verifier( destination.getCanonicalPath(), null, true, true );
                verifier.setDebugJvm( true );
            }
            else {
                verifier = new Verifier( destination.getCanonicalPath() );
                verifier.addCliOption( "-Pdebug-forked-javac" );
            }
        }
        else {
            verifier = new Verifier( destination.getCanonicalPath() );
        }

        List<String> goals = new ArrayList<String>( 3 );

        goals.add( "clean" );

        try {
            configureToolchains( child, verifier, goals, originalOut );
            configureProcessor( child, verifier );

            verifier.addCliOption( "-Dcompiler-source-target-version=" + child.processor.getSourceTargetVersion() );

            if ( "1.8".equals( child.processor.getSourceTargetVersion() ) ) {
                verifier.addCliOption( "-Dmapstruct-artifact-id=mapstruct-jdk8" );
            }
            else {
                verifier.addCliOption( "-Dmapstruct-artifact-id=mapstruct" );
            }

            if ( Boolean.getBoolean( SYS_PROP_DEBUG ) ) {
                originalOut.print( "Processor Integration Test: " );
                originalOut.println( "Listening for transport dt_socket at address: 8000 (in some seconds)" );
            }

            goals.add( "test" );

            originalOut.println( "executing " + child.processor.name().toLowerCase() );

            verifier.executeGoals( goals );
            verifier.verifyErrorFreeLog();
        }
        finally {
            verifier.resetStreams();
        }
    }

    private void configureProcessor(ProcessorTestCase child, Verifier verifier) {
        if ( child.processor.getCompilerId() != null ) {
            verifier.addCliOption( "-Pgenerate-via-compiler-plugin" );
            verifier.addCliOption( "-Dcompiler-id=" + child.processor.getCompilerId() );
        }
        else {
            verifier.addCliOption( "-Pgenerate-via-processor-plugin" );
        }
    }

    private void configureToolchains(ProcessorTestCase child, Verifier verifier, List<String> goals,
                                     PrintStream originalOut) {
        if ( child.processor.getToolchain() != null ) {
            if ( null != SPECIFIED_TOOLCHAINS_FILE ) {
                verifier.addCliOption( "--toolchains" );
                verifier.addCliOption( SPECIFIED_TOOLCHAINS_FILE.getPath().replace( '\\', '/' ) );
            }

            String[] parts = child.processor.getToolchain().split( "-" );

            verifier.addCliOption( "-Dtoolchain-jdk-vendor=" + parts[0] );
            verifier.addCliOption( "-Dtoolchain-jdk-version=" + parts[1] );

            goals.add( "toolchains:toolchain" );
        }
    }

    private File extractTest(ProcessorTestCase child, Description description) throws IOException {
        File tempDirBase = new File( "target/tmp", description.getClassName() ).getCanonicalFile();

        if ( !tempDirBase.exists() ) {
            tempDirBase.mkdirs();
        }

        File parentPom = new File( tempDirBase, "pom.xml" );
        copyURLToFile( getClass().getResource( "/pom.xml" ), parentPom );

        File tempDir = new File( tempDirBase, description.getMethodName() );
        deleteDirectory( tempDir );

        return extractResourceToDestination( getClass(), "/" + child.baseDir, tempDir, true );
    }

    private static File getSpecifiedToolchainsFile() {
        String specifiedToolchainsFile = System.getProperty( SYS_PROP_TOOLCHAINS_FILE );
        if ( null != specifiedToolchainsFile ) {
            try {
                File canonical = new File( specifiedToolchainsFile ).getCanonicalFile();
                if ( canonical.exists() ) {
                    return canonical;
                }

                // check the path relative to the parent directory (allows specifying a path relative to the top-level
                // aggregator module)
                canonical = new File( "..", specifiedToolchainsFile ).getCanonicalFile();
                if ( canonical.exists() ) {
                    return canonical;
                }
            }
            catch ( IOException e ) {
                return null;
            }
        }

        return null;
    }

    private static boolean toolchainsFileExists() {
        if ( null != SPECIFIED_TOOLCHAINS_FILE ) {
            return SPECIFIED_TOOLCHAINS_FILE.exists();
        }

        String defaultPath = System.getProperty( "user.home" ) + System.getProperty( "file.separator" ) + ".m2";
        return new File( defaultPath, "toolchains.xml" ).exists();
    }

}
TOP

Related Classes of org.mapstruct.itest.testutil.runner.ProcessorSuiteRunner$ProcessorTestCase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.