From d83d5f3fcc9cd296a587951a0aa291fe19cc642b Mon Sep 17 00:00:00 2001 From: Aidan Skinner Date: Thu, 24 Apr 2008 00:07:14 +0000 Subject: QPID-832 copy from M2.x git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@651119 13f79535-47bb-0310-9956-ffa450edef68 --- java/junit-toolkit-maven-plugin/pom.xml | 79 ++++++ .../qpid/junit/maven/IsolatedClassLoader.java | 113 +++++++++ .../apache/qpid/junit/maven/TKTestRunnerMojo.java | 274 +++++++++++++++++++++ .../qpid/junit/maven/TKTestScriptGenMojo.java | 148 +++++++++++ 4 files changed, 614 insertions(+) create mode 100644 java/junit-toolkit-maven-plugin/pom.xml create mode 100644 java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java create mode 100644 java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java create mode 100644 java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java (limited to 'java') diff --git a/java/junit-toolkit-maven-plugin/pom.xml b/java/junit-toolkit-maven-plugin/pom.xml new file mode 100644 index 0000000000..8b8ab6d2f7 --- /dev/null +++ b/java/junit-toolkit-maven-plugin/pom.xml @@ -0,0 +1,79 @@ + + + + 4.0.0 + + org.apache.qpid + junit-toolkit-maven-plugin + junit-toolkit-maven-plugin + 1.0-incubating-M2.1-SNAPSHOT + + maven-plugin + + + org.apache.qpid + qpid + 1.0-incubating-M2.1-SNAPSHOT + ../pom.xml + + + + + + + + + + junit + junit + 3.8.1 + + + + log4j + log4j + 1.2.12 + + + + + + + + + org.apache.qpid + junit-toolkit + 1.0-incubating-M2.1-SNAPSHOT + + + + org.apache.maven + maven-plugin-api + 2.0.4 + + + + + + src/main + src/unittests + + + diff --git a/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java b/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java new file mode 100644 index 0000000000..dc74590f60 --- /dev/null +++ b/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java @@ -0,0 +1,113 @@ +/* + * + * 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.qpid.junit.maven; + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashSet; +import java.util.Set; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ * + * @author Rupert Smith + * + * @noinspection CustomClassloader + */ +public class IsolatedClassLoader extends URLClassLoader +{ + + private static final URL[] EMPTY_URL_ARRAY = new URL[0]; + private ClassLoader parent = ClassLoader.getSystemClassLoader(); + + private Set urls = new HashSet(); + + private boolean childDelegation = true; + + public IsolatedClassLoader() + { + super(EMPTY_URL_ARRAY, null); + } + + public IsolatedClassLoader(ClassLoader parent, boolean childDelegation) + { + super(EMPTY_URL_ARRAY, parent); + + this.childDelegation = childDelegation; + } + + public IsolatedClassLoader(ClassLoader parent) + { + super(EMPTY_URL_ARRAY, parent); + } + + public void addURL(URL url) + { + // avoid duplicates + if (!urls.contains(url)) + { + super.addURL(url); + urls.add(url); + } + } + + public synchronized Class loadClass(String name) throws ClassNotFoundException + { + Class c; + + if (childDelegation) + { + c = findLoadedClass(name); + + ClassNotFoundException ex = null; + + if (c == null) + { + try + { + c = findClass(name); + } + catch (ClassNotFoundException e) + { + ex = e; + + if (parent != null) + { + c = parent.loadClass(name); + } + } + } + + if (c == null) + { + throw ex; + } + } + else + { + c = super.loadClass(name); + } + + return c; + } +} diff --git a/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java b/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java new file mode 100644 index 0000000000..442529b609 --- /dev/null +++ b/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java @@ -0,0 +1,274 @@ +/* + * + * 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.qpid.junit.maven; + +import org.apache.maven.plugin.AbstractMojo; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; + +/** + * TKTestRunnerMojo is a JUnit test runner plugin for Maven 2. It is intended to be compatible with the surefire + * plugin (though not all features of that are yet implemented), with some extended capabilities. + * + *

This plugin adds the ability to use different JUnit test runners, and to pass arbitrary options to them. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
+ * + * @author Rupert Smith + * + * @goal tktest + * @phase test + * @requiresDependencyResolution test + */ +public class TKTestRunnerMojo extends AbstractMojo +{ + private static final BitSet UNRESERVED = new BitSet(256); + + /** + * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion. + * + * @parameter expression="${maven.test.skip}" + */ + private boolean skip; + + /** + * The TKTest runner command lines. There are passed directly to the TKTestRunner main method. + * + * @parameter + */ + private Map commands = new LinkedHashMap(); + + /** + * The base directory of the project being tested. This can be obtained in your unit test by + * System.getProperty("basedir"). + * + * @parameter expression="${basedir}" + * @required + */ + private File basedir; + + /** + * The directory containing generated classes of the project being tested. + * + * @parameter expression="${project.build.outputDirectory}" + * @required + */ + private File classesDirectory; + + /** + * The directory containing generated test classes of the project being tested. + * + * @parameter expression="${project.build.testOutputDirectory}" + * @required + */ + private File testClassesDirectory; + + /** + * The classpath elements of the project being tested. + * + * @parameter expression="${project.testClasspathElements}" + * @required + * @readonly + */ + private List classpathElements; + + /** + * List of System properties to pass to the tests. + * + * @parameter + */ + private Properties systemProperties; + + /** + * Map of of plugin artifacts. + * + * @parameter expression="${plugin.artifactMap}" + * @required + * @readonly + */ + private Map pluginArtifactMap; + + /** + * Map of of project artifacts. + * + * @parameter expression="${project.artifactMap}" + * @required + * @readonly + */ + private Map projectArtifactMap; + + /** + * Option to specify the forking mode. Can be "never" (default), "once" or "always". + * "none" and "pertest" are also accepted for backwards compatibility. + * + * @parameter expression="${forkMode}" default-value="once" + */ + private String forkMode; + + /** + * Option to specify the jvm (or path to the java executable) to use with + * the forking options. For the default we will assume that java is in the path. + * + * @parameter expression="${jvm}" + * default-value="java" + */ + private String jvm; + + /** + * The test runner to use. + * + * @parameter + */ + private String testrunner; + + /** + * The additional properties to append to the test runner invocation command line. + * + * @parameter + */ + private Properties testrunnerproperties; + + /** + * The options to pass to all test runner invocation command lines. + * + * @parameter + */ + private String[] testrunneroptions; + + /** + * Implementation of the tktest goal. + */ + public void execute() + { + // Skip these tests if test skipping is turned on. + if (skip) + { + getLog().info("Skipping Tests."); + + return; + } + + // Log out the classpath if debugging is on. + if (getLog().isDebugEnabled()) + { + getLog().info("Test Classpath :"); + + for (Object classpathElement1 : classpathElements) + { + String classpathElement = (String) classpathElement1; + getLog().info(" " + classpathElement); + } + } + + try + { + // Create a class loader to load the test runner with. This also gets set as the context loader for this + // thread, so that all subsequent class loading activity by the test runner or the test code, has the + // test classes available to it. The system loader is set up for the maven build, which is why a seperate + // loader needs to be created; in order to inject the test dependencies into it. + ClassLoader runnerClassLoader = createClassLoader(classpathElements, ClassLoader.getSystemClassLoader(), true); + Thread.currentThread().setContextClassLoader(runnerClassLoader); + + // Load the test runner implementation that will be used to run the tests. + if ((testrunner == null) || "".equals(testrunner)) + { + testrunner = "org.apache.qpid.junit.extensions.TKTestRunner"; + } + + Class testRunnerClass = Class.forName(testrunner, false, runnerClassLoader); + Method run = testRunnerClass.getMethod("main", String[].class); + + // Concatenate all of the options to pass on the command line to the test runner. + String preOptions = ""; + + for (String option : testrunneroptions) + { + preOptions += option + " "; + } + + // Concatenate all of the additional properties as name=value pairs on the command line. + String nvPairs = ""; + + if (testrunnerproperties != null) + { + for (Object objKey : testrunnerproperties.keySet()) + { + String key = (String) objKey; + String value = testrunnerproperties.getProperty(key); + + nvPairs = key + "=" + value + " "; + } + } + + // Pass each of the test runner command lines in turn to the toolkit test runner. + // The command line is made up of the options, the command specific command line, then the trailing + // name=value pairs. + for (String testName : commands.keySet()) + { + String commandLine = preOptions + " " + commands.get(testName) + " " + nvPairs; + getLog().info("commandLine = " + commandLine); + + // Tokenize the command line on white space, into an array of string components. + String[] tokenizedCommandLine = commandLine.split("\\s+"); + + // Run the tests. + run.invoke(testRunnerClass, new Object[] { tokenizedCommandLine }); + } + } + catch (Exception e) + { + getLog().error("There was an exception: " + e.getMessage(), e); + } + } + + private static ClassLoader createClassLoader(List classPathUrls, ClassLoader parent, boolean childDelegation) + throws MalformedURLException + { + List urls = new ArrayList(); + + for (Iterator i = classPathUrls.iterator(); i.hasNext();) + { + String url = (String) i.next(); + + if (url != null) + { + File f = new File(url); + urls.add(f.toURL()); + } + } + + IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation); + + for (Iterator iter = urls.iterator(); iter.hasNext();) + { + URL url = (URL) iter.next(); + classLoader.addURL(url); + } + + return classLoader; + } +} diff --git a/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java b/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java new file mode 100644 index 0000000000..5c7669e069 --- /dev/null +++ b/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java @@ -0,0 +1,148 @@ +/* + * + * 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.qpid.junit.maven; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ * + * @author Rupert Smith + * @goal tkscriptgen + * @phase test + * @execute phase="test" + * @requiresDependencyResolution test + */ +public class TKTestScriptGenMojo extends AbstractMojo +{ + private static final String _scriptLanguage = "#!/bin/bash\n\n"; + + private static final String _javaOptArgParser = + "# Parse arguements taking all - prefixed args as JAVA_OPTS\n" + "for arg in \"$@\"; do\n" + + " if [[ $arg == -java:* ]]; then\n" + " JAVA_OPTS=\"${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` \"\n" + + " else\n" + " ARGS=\"${ARGS}$arg \"\n" + " fi\n" + "done\n\n"; + + /** + * Where to write out the scripts. + * + * @parameter + */ + private String scriptOutDirectory; + + /** + * The all-in-one test jar location. + * + * @parameter + */ + private String testJar; + + /** + * The system properties to pass to java runtime. + * + * @parameter + */ + private Properties systemproperties; + + /** + * The TKTest runner command lines. There are passed directly to the TKTestRunner main method. + * + * @parameter + */ + private Map commands = new LinkedHashMap(); + + /** + * Implementation of the tkscriptgen goal. + * + * @throws MojoExecutionException + */ + public void execute() throws MojoExecutionException + { + // Turn each of the test runner command lines into a script. + for (String testName : commands.keySet()) + { + String testOptions = commands.get(testName); + String commandLine = "java "; + + String logdir = null; + + for (Object key : systemproperties.keySet()) + { + String keyString = (String) key; + String value = systemproperties.getProperty(keyString); + + if (keyString.equals("logdir")) + { + logdir = value; + } + else + { + if (keyString.startsWith("-X")) + { + commandLine += keyString + value + " "; + } + else + { + commandLine += "-D" + keyString + "=" + value + " "; + } + } + } + + commandLine += + "${JAVA_OPTS} -cp " + testJar + " org.apache.qpid.junit.extensions.TKTestRunner " + testOptions + " ${ARGS}"; + + getLog().info("Generating Script for test: " + testName); + getLog().debug(commandLine); + + String fileName = scriptOutDirectory + "/" + testName + ".sh"; + + try + { + File scriptFile = new File(fileName); + Writer scriptWriter = new FileWriter(scriptFile); + scriptWriter.write(_scriptLanguage); + scriptWriter.write(_javaOptArgParser); + if (logdir != null) + { + scriptWriter.write("mkdir -p " + logdir + "\n"); + } + + scriptWriter.write(commandLine); + scriptWriter.flush(); + scriptWriter.close(); + } + catch (IOException e) + { + getLog().error("Failed to write: " + fileName); + } + } + } +} -- cgit v1.2.1