diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml new file mode 100644 index 0000000000..e269bf7201 --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml @@ -0,0 +1,24 @@ + + + + 4.0.0 + + + jacoco + it-offline-instrumentation + 1.0-SNAPSHOT + + + child-without-main-classes + + diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java new file mode 100644 index 0000000000..a31fd5e9bf --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +import org.junit.Test; + +public class ExampleTest { + + @Test + public void test() { + } + +} diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml new file mode 100644 index 0000000000..62a3fbd6a8 --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml @@ -0,0 +1,24 @@ + + + + 4.0.0 + + + jacoco + it-offline-instrumentation + 1.0-SNAPSHOT + + + child + + diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java new file mode 100644 index 0000000000..d51ac9eb0a --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +public class DoNotInstrument { + + public void sayHello() { + System.out.println("Hello world"); + } + +} diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java new file mode 100644 index 0000000000..630a62f2ca --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +public class Example { + + public void sayHello() { + System.out.println("Hello world"); + } + +} diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java new file mode 100644 index 0000000000..d9b78ab916 --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +import org.junit.Test; + +public class ExampleTest { + + @Test + public void test() { + new Example().sayHello(); + } + +} diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml b/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml new file mode 100644 index 0000000000..fb9ee3da0f --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml @@ -0,0 +1,86 @@ + + + + 4.0.0 + + + jacoco + setup-parent + 1.0-SNAPSHOT + + + it-offline-instrumentation + pom + + + child + child-without-main-classes + + + + + @project.groupId@ + org.jacoco.agent + runtime + @project.version@ + test + + + + + + + @project.groupId@ + jacoco-maven-plugin + + + instrument-classes + + instrument + + + + **/DoNotInstrument.class + + + + + restore-instrumented-classes + + restore-instrumented-classes + + + + report + prepare-package + + report + + + ${project.build.directory}/coverage.exec + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.build.directory}/coverage.exec + + + + + + diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh b/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh new file mode 100644 index 0000000000..89e2e303c7 --- /dev/null +++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +import java.io.*; +import org.codehaus.plexus.util.*; + +File file = new File( basedir, "child/target/generated-classes/jacoco/Example.class" ); +if ( !file.isFile() ) { + throw new RuntimeException( "Could not find backup of instrumented class: " + file ); +} +file = new File( basedir, "child/target/generated-classes/jacoco/DoNotInstrument.class" ); +if ( file.isFile() ) { + throw new RuntimeException( "Excluded file should not be instrumented: " + file ); +} + +file = new File( basedir, "child/target/coverage.exec" ); +if ( !file.isFile() ) +{ + throw new FileNotFoundException( "Could not find generated dump: " + file ); +} diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java b/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java index 99b24c92c7..81b8a4dfa7 100644 --- a/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java +++ b/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java @@ -8,15 +8,18 @@ * Contributors: * Evgeny Mandrikov - initial API and implementation * Kyle Lieber - implementation of CheckMojo - * + * *******************************************************************************/ package org.jacoco.maven; -import java.util.List; - import org.apache.commons.collections.CollectionUtils; +import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; +import java.io.File; +import java.io.IOException; +import java.util.List; + /** * A file filter using includes/excludes patterns. */ @@ -41,6 +44,20 @@ public FileFilter(final List includes, final List excludes) { this.excludes = excludes; } + /** + * Returns a list of files. + * + * @param directory + * the directory to scan + * @return a list of files + * @throws IOException + */ + @SuppressWarnings("unchecked") + public List getFileNames(final File directory) throws IOException { + return FileUtils.getFileNames(directory, getIncludes(), getExcludes(), + false); + } + /** * Get the includes pattern * diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java new file mode 100644 index 0000000000..0888b7967d --- /dev/null +++ b/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.maven; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; +import org.jacoco.core.instr.Instrumenter; +import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + +/** + * Performs offline instrumentation. Note that after execution of test you must + * restore original classes with help of "restore-instrumented-classes" goal. + *

+ * Warning: The preferred way for code coverage analysis with + * JaCoCo is on-the-fly instrumentation. Offline instrumentation has several + * drawbacks and should only be used if a specific scenario explicitly requires + * this mode. Please consult documentation about + * offline instrumentation before using this mode. + *

+ * + * @phase process-classes + * @goal instrument + * @requiresProject true + * @since 0.6.2 + */ +public class InstrumentMojo extends AbstractJacocoMojo { + + @Override + public void executeMojo() throws MojoExecutionException, + MojoFailureException { + final File originalClassesDir = new File(getProject().getBuild() + .getDirectory(), "generated-classes/jacoco"); + originalClassesDir.mkdirs(); + final File classesDir = new File(getProject().getBuild() + .getOutputDirectory()); + if (!classesDir.isDirectory()) { + getLog().info("skip non existing outputDirectory " + classesDir); + return; + } + + final List fileNames; + try { + fileNames = new FileFilter(this.getIncludes(), + this.getExcludes()).getFileNames(classesDir); + } catch (final IOException e1) { + throw new MojoExecutionException( + "Unable to get list of files to instrument.", e1); + } + + final Instrumenter instrumenter = new Instrumenter( + new OfflineInstrumentationAccessGenerator()); + for (final String fileName : fileNames) { + if (fileName.endsWith(".class")) { + final File source = new File(classesDir, fileName); + final File backup = new File(originalClassesDir, fileName); + InputStream input = null; + OutputStream output = null; + try { + FileUtils.copyFile(source, backup); + input = new FileInputStream(backup); + output = new FileOutputStream(source); + instrumenter.instrument(input, output); + } catch (final IOException e2) { + throw new MojoExecutionException( + "Unable to instrument file.", e2); + } finally { + IOUtil.close(input); + IOUtil.close(output); + } + } + } + } + +} diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java new file mode 100644 index 0000000000..f9e5ecbb98 --- /dev/null +++ b/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.maven; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.codehaus.plexus.util.FileUtils; + +import java.io.File; +import java.io.IOException; + +/** + * Restores original classes as they were before offline instrumentation. + * + * @phase prepare-package + * @goal restore-instrumented-classes + * @requiresProject true + * @since 0.6.2 + */ +public class RestoreMojo extends AbstractJacocoMojo { + + @Override + protected void executeMojo() throws MojoExecutionException, + MojoFailureException { + final File originalClassesDir = new File(getProject().getBuild() + .getDirectory(), "generated-classes/jacoco"); + final File classesDir = new File(getProject().getBuild() + .getOutputDirectory()); + try { + FileUtils.copyDirectoryStructure(originalClassesDir, classesDir); + } catch (final IOException e) { + throw new MojoFailureException("Unable to restore classes.", e); + } + } + +} diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index 5fc5c24726..d1926a79f6 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -22,7 +22,7 @@

Trunk Build @qualified.bundle.version@ (@build.date@)

New Features

    -
  • Support for offline instrumentation (GitHub #4).
  • +
  • Support for offline instrumentation (GitHub #4, #64).
  • JaCoCo agent exposes runtime API for direct integration with application under test (GitHub #61).
  • Support for parallel test execution: Different agents can now safely write diff --git a/org.jacoco.doc/docroot/doc/index.html b/org.jacoco.doc/docroot/doc/index.html index 7250e24980..323ad39ad3 100644 --- a/org.jacoco.doc/docroot/doc/index.html +++ b/org.jacoco.doc/docroot/doc/index.html @@ -41,7 +41,8 @@

    Using JaCoCo

  • Ant Usage Example - Offline Example
  • Maven Plug-in
  • -
  • Maven Usage Example
  • +
  • Maven Usage Example - + Offline Example
  • Java Agent
  • Offline Instrumentation
  • FAQ
  • diff --git a/org.jacoco.doc/docroot/doc/maven.html b/org.jacoco.doc/docroot/doc/maven.html index 2c73adcdfa..0c113116b5 100644 --- a/org.jacoco.doc/docroot/doc/maven.html +++ b/org.jacoco.doc/docroot/doc/maven.html @@ -90,6 +90,8 @@

    Goals

  • prepare-agent
  • report
  • check
  • +
  • instrument
  • +
  • restore-instrumented-classes
diff --git a/org.jacoco.examples/build/pom-offline.xml b/org.jacoco.examples/build/pom-offline.xml new file mode 100644 index 0000000000..4a08a5f328 --- /dev/null +++ b/org.jacoco.examples/build/pom-offline.xml @@ -0,0 +1,92 @@ + + + + 4.0.0 + + org.jacoco + org.jacoco.examples.maven + @project.version@ + jar + + JaCoCo Maven plug-in example with Offline Instrumentation + http://www.eclemma.org/jacoco + + + + junit + junit + 4.10 + test + + + + org.jacoco + org.jacoco.agent + runtime + @project.version@ + test + + + + + + + org.jacoco + jacoco-maven-plugin + @project.version@ + + + + instrument + restore-instrumented-classes + + + + report + prepare-package + + report + + + + check + + check + + + + 100 + 90 + 95 + 85 + 85 + 90 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.2 + + + target/jacoco.exec + + + + + + +