/* * Copyright 2014 NAVER Corp. * * 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 com.navercorp.pinpoint.test.plugin; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import org.junit.runner.Description; import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.Runner; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import org.junit.runners.model.InitializationError; import static com.navercorp.pinpoint.test.plugin.PinpointPluginTestConstants.*; public class ForkedPinpointPluginTest { private static boolean forked = false; private static PluginTestLogger logger = PluginTestLogger.getLogger(ForkedPinpointPluginTest.class.getName()); public static boolean isForked() { return forked; } public static void main(String[] args) throws Exception { forked = true; final String testClassName = args[0]; final String agentType = getAgentType(args); final ClassLoader classLoader = getClassLoader(agentType); final String testId = System.getProperty(PINPOINT_TEST_ID, ""); if (logger.isDebugEnabled()){ logger.debug("testId:" + testId); } final Callable<Result> testCaseCallable = new Callable<Result>() { @Override public Result call() throws Exception { Class<?> testClass = classLoader.loadClass(testClassName); return runTests(testClass, testId); } }; Result result = null; try { result = executeTestCase(testCaseCallable, classLoader); } catch (Throwable e) { logger.info("testcase run error:" + e.getMessage()); System.exit(-1); } System.exit(getFailureCount(result)); } private static String getAgentType(String[] args) { if (args == null) { return ""; } if (args.length >= 2) { return args[1]; } return ""; } private static int getFailureCount(Result result) { if (result == null) { return -1; } return result.getFailureCount(); } private static ClassLoader getClassLoader(String agentType) throws MalformedURLException { if (agentType.startsWith(CHILD_CLASS_PATH_PREFIX)) { String jars = agentType.substring(CHILD_CLASS_PATH_PREFIX.length()); List<URL> urls = getJarUrls(jars); for (URL url : urls) { if (logger.isDebugEnabled()) { logger.debug("child-runner lib:" + url); } } return new PluginTestClassLoader(urls.toArray(new URL[urls.size()]), ClassLoader.getSystemClassLoader()); } return ClassLoader.getSystemClassLoader(); } private static Result executeTestCase(Callable<Result> callable, ClassLoader classLoader) throws Exception { final Thread currentThread = Thread.currentThread(); ClassLoader old = currentThread.getContextClassLoader(); currentThread.setContextClassLoader(classLoader); try { return callable.call(); } finally { currentThread.setContextClassLoader(old); } } private static Result runTests(Class<?> testClass, String testId) throws InitializationError { JUnitCore junit = new JUnitCore(); junit.addListener(new PrintListener()); Runner runner = new ForkedPinpointPluginTestRunner(testClass, testId); Result result = junit.run(runner); return result; } private static List<URL> getJarUrls(String jars) throws MalformedURLException { String[] tokens = jars.split(File.pathSeparator); List<URL> urls = new ArrayList<URL>(tokens.length); for (String token : tokens) { File file = new File(token); urls.add(file.toURI().toURL()); } return urls; } private static class PrintListener extends RunListener { @Override public void testRunStarted(Description description) throws Exception { System.out.println(JUNIT_OUTPUT_DELIMITER + "testRunStarted"); } @Override public void testRunFinished(Result result) throws Exception { System.out.println(JUNIT_OUTPUT_DELIMITER + "testRunFinished"); } @Override public void testStarted(Description description) throws Exception { System.out.println(JUNIT_OUTPUT_DELIMITER + "testStarted" + JUNIT_OUTPUT_DELIMITER + description.getDisplayName()); } @Override public void testFinished(Description description) throws Exception { System.out.println(JUNIT_OUTPUT_DELIMITER + "testFinished" + JUNIT_OUTPUT_DELIMITER + description.getDisplayName()); } @Override public void testFailure(Failure failure) throws Exception { System.out.println(JUNIT_OUTPUT_DELIMITER + "testFailure" + JUNIT_OUTPUT_DELIMITER + failureToString(failure)); } @Override public void testAssumptionFailure(Failure failure) { System.out.println(JUNIT_OUTPUT_DELIMITER + "testAssumptionFailure" + JUNIT_OUTPUT_DELIMITER + failureToString(failure)); } @Override public void testIgnored(Description description) throws Exception { System.out.println(JUNIT_OUTPUT_DELIMITER + "testIgnored" + JUNIT_OUTPUT_DELIMITER + description.getDisplayName()); } private String failureToString(Failure failure) { StringBuilder builder = new StringBuilder(); builder.append(failure.getTestHeader()); builder.append(JUNIT_OUTPUT_DELIMITER); Throwable t = failure.getException(); while (true) { builder.append(t.getClass().getName()); builder.append(JUNIT_OUTPUT_DELIMITER); builder.append(t.getMessage()); builder.append(JUNIT_OUTPUT_DELIMITER); for (StackTraceElement e : failure.getException().getStackTrace()) { builder.append(e.getClassName()); builder.append(','); builder.append(e.getMethodName()); builder.append(','); builder.append(e.getFileName()); builder.append(','); builder.append(e.getLineNumber()); builder.append(JUNIT_OUTPUT_DELIMITER); } Throwable cause = t.getCause(); if (cause == null || t == cause) { break; } t = cause; builder.append("$CAUSE$"); builder.append(JUNIT_OUTPUT_DELIMITER); } return builder.toString(); } } }