Package org.apache.sirona.javaagent

Source Code of org.apache.sirona.javaagent.JavaAgentRunner

/*
* 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.
*/
package org.apache.sirona.javaagent;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.junit.Ignore;
import org.junit.internal.TextListener;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;

// only works with standard runner and surefire
public class JavaAgentRunner extends BlockJUnit4ClassRunner {
    public JavaAgentRunner(final Class<?> klass) throws InitializationError {
        super(klass);
    }

    // internal call to execute a single test
    public static void main(final String[] args) throws Exception {
        final Class<?> testClass = Class.forName(args[0]);

        final BlockJUnit4ClassRunner filteredRunner = new BlockJUnit4ClassRunner(testClass) {
            @Override
            protected List<FrameworkMethod> getChildren() {
                try {
                    return Arrays.asList(new FrameworkMethod(testClass.getMethod(args[1])));
                } catch (final NoSuchMethodException e) {
                    throw new IllegalArgumentException(e);
                }
            }
        };

        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final JUnitCore jUnitCore = new JUnitCore();
        jUnitCore.addListener(new TextListener(new PrintStream(baos)));
        final Result result = jUnitCore.run(filteredRunner);

        if (result.wasSuccessful()) {
            System.exit(0);
        }
        System.err.println(new String(baos.toByteArray()));
        System.exit(-1);
    }

    @Override
    protected Statement classBlock(final RunNotifier notifier) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                for (final FrameworkMethod mtd : getChildren()) {
                    if (mtd.getAnnotation(Ignore.class) != null) {
                        notifier.fireTestIgnored(describeChild(mtd));
                        continue;
                    }

                    final Description description = describeChild(mtd);
                    notifier.fireTestRunStarted(description);
                    try {
                        executeMethod(mtd, description, notifier);
                    } catch (final Exception e) {
                        notifier.fireTestFailure(new Failure(description, e));
                    } finally {
                        notifier.fireTestFinished(description);
                    }
                }
            }
        };
    }

    private void executeMethod(final FrameworkMethod mtd, final Description description, final RunNotifier notifier) throws IOException, InterruptedException {
        final Process process = Runtime.getRuntime().exec(buildProcessArgs(mtd));

        slurp(process.getInputStream()).await();
        slurp(process.getErrorStream()).await();

        Runtime.getRuntime().addShutdownHook(new Thread() { // ctrl+x during the build
            @Override
            public void run() {
                try {
                    process.exitValue();
                } catch (final IllegalStateException ise) {
                    process.destroy();
                }
            }
        });

        process.waitFor();

        if (process.exitValue() != 0) {
            notifier.fireTestFailure(new Failure(description, new RuntimeException("exit code = " + process.exitValue())));
        }
    }

    protected String[] buildProcessArgs(final FrameworkMethod mtd) throws IOException {
        final Collection<String> args = new ArrayList<String>();

        args.add( findJava() );

        AgentArgs agentArgs = mtd.getAnnotation( AgentArgs.class );

        String maxMem = agentArgs == null ? "" : agentArgs.maxMem();

        if ( maxMem.length() > 0 )
        {
            args.add( "-Xmx" + maxMem );
        }

        String minMem = agentArgs == null ? "" : agentArgs.minMem();

        if ( minMem.length() > 0 )
        {
            args.add( "-Xms" + minMem );
        }

        String javaAgentArgs =
            agentArgs == null ? null : StrSubstitutor.replace( agentArgs.value(), System.getProperties() );
        args.add( "-javaagent:" + buildJavaagent() + "=" + ( javaAgentArgs == null ? "" : javaAgentArgs ) );

        if ( Boolean.getBoolean( "test.debug.remote" ) )
        {
            args.add( "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + Integer.getInteger(
                "test.debug.remote.port", 5005 ) );
        }
        if ( agentArgs != null && agentArgs.noVerify() )
        {
            args.add( "-noverify" );
        }

        String sysProps = agentArgs == null ? "" : agentArgs.sysProps();

        if (sysProps.length() > 0){
             String[] splittedProps = StringUtils.split( sysProps, "|" );
            for (String props : splittedProps)
            {
                String[] prop = StringUtils.split( props, "=" );
                String key = prop[0];
                String value = "";
                if (prop.length>1){
                    value = prop[1];
                }
                args.add( "-D" + key + "=" + StrSubstitutor.replacevalue, System.getProperties() ) );
            }
        }

        args.add( "-cp" );
        args.add(removeAgentFromCp(System.getProperty("surefire.test.class.path", System.getProperty("java.class.path"))));
        args.add(JavaAgentRunner.class.getName());
        args.add(mtd.getMethod().getDeclaringClass().getName());
        args.add(mtd.getName());

        System.out.println("Running " + args.toString().replace(",", "").substring(1).replace("]", ""));

        return args.toArray(new String[args.size()]);
    }

    private static String removeAgentFromCp(final String property) {
        final String path = "target" + File.separator + "classes";
        final String sep = System.getProperty("path.separator");
        final String[] segments = property.split(sep);
        final StringBuilder builder = new StringBuilder(property.length());
        for (final String segment : segments) {
            if (!segment.endsWith(path)) {
                builder.append(segment).append(sep);
            }
        }
        builder.setLength(builder.length() - 1);
        return builder.toString();
    }

    private static CountDownLatch slurp(final InputStream in) {
        final CountDownLatch latch = new CountDownLatch(1);
        new Thread() {
            @Override
            public void run() {
                int i;
                try {
                    while ((i = in.read()) != -1) {
                        System.out.write(i);
                    }
                    latch.countDown();
                } catch (final Exception e) {
                    latch.countDown();
                }
            }
        }.start();
        return latch;
    }

    protected String buildJavaagent() throws IOException {
        final File[] files = new File(System.getProperty("javaagent.jar.directory", "target")).listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.startsWith( System.getProperty( "javaagent.jar.name.start", "sirona-javaagent-" )) //
                        && name.endsWith(".jar") //
                        && name.endsWith("-shaded.jar");
            }
        });
        return files[0].getAbsolutePath();
    }

    private static String findJava() {
        {
            String home = System.getProperty("java.home");
            if (home != null) {
                return new File(home, "bin/java").getAbsolutePath();
            }
        }
        for (final String env : new String[]{"JAVA_HOME", "JRE_HOME"}) {
            final String home = System.getenv(env);
            if (home != null) {
                return new File(home, "bin/java").getAbsolutePath();
            }
        }
        return "java";
    }
}
TOP

Related Classes of org.apache.sirona.javaagent.JavaAgentRunner

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.