aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorJiri Vanek <[email protected]>2012-12-11 20:32:26 +0100
committerJiri Vanek <[email protected]>2012-12-11 20:32:26 +0100
commit9f073ba18f90391ac45ca8f8f8df1ae7516b90f9 (patch)
treece4654016af42b3dc4e6447c16c75ddb8ce32bab /tests
parent8bbf9daa0e72001d56ae9fd9aa50cc92e1643695 (diff)
Added jacoco code coverage support
Note - in time of this commit one needs custom build of jacoco containing the xboot.patch form approving discussion: http://mail.openjdk.java.net/pipermail/distro-pkg-dev/attachments/20121127/ba8f6a1e/xboot-0001.patch The tracking of upstraming can be found on jacoco page.
Diffstat (limited to 'tests')
-rw-r--r--tests/jacoco-operator/org/jacoco/operator/Main.java288
-rw-r--r--tests/jacoco-operator/org/jacoco/operator/MergeTask.java157
-rw-r--r--tests/jacoco-operator/org/jacoco/operator/ReportGenerator.java292
3 files changed, 737 insertions, 0 deletions
diff --git a/tests/jacoco-operator/org/jacoco/operator/Main.java b/tests/jacoco-operator/org/jacoco/operator/Main.java
new file mode 100644
index 0000000..7537ae1
--- /dev/null
+++ b/tests/jacoco-operator/org/jacoco/operator/Main.java
@@ -0,0 +1,288 @@
+/*
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.jacoco.operator;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Commandline launcher
+ */
+public class Main {
+
+ //main switches
+ private static final String MERGE = "merge";
+ private static final String REPORT = "report";
+ //switches
+ private static final String die_on_failure = "--die-soon";
+ //merge
+ private static final String output_file = "--output-file";
+ private static final String input_files = "--input-files";
+ //report
+ private static final String html_output = "--html-output";
+ private static final String xml_output = "--xml-output";
+ private static final String input_srcs = "--input-srcs";
+ private static final String input_builds = "--input-builds";
+ private static final String title = "--title";
+ private static String input_file = "--input-file";
+ /**
+ * *
+ */
+ private static boolean dieOnFailure = false;
+ private static boolean warned = false;
+
+ public static void main(String[] args) throws IOException {
+ if (args.length < 2) {
+ printHelp();
+ System.exit(0);
+ }
+
+ Runnable r = null;
+ if (args[0].equalsIgnoreCase(MERGE)) {
+ r = proceedMerge(cutFirstParam(args));
+ } else if (args[0].equalsIgnoreCase(REPORT)) {
+ r = proceedReport(cutFirstParam(args));
+ } else {
+ System.err.println("Unsuported main switch `" + args[0] + "`, use " + MERGE + " or " + REPORT);
+ printHelp();
+ System.exit(1);
+ }
+ if (dieOnFailure && warned) {
+ System.err.println(die_on_failure + " is specified and warning occured. Exiting");
+ System.exit(2);
+ }
+ r.run();
+
+ }
+
+ private static void printHelp() {
+ System.out.println("Usage: java `classpath` org.jacoco.operator.Main [" + MERGE + "|" + REPORT + "] switches/files");
+ System.out.println(" order of switches does not matter");
+ System.out.println(" Merge usage: java `classpath` org.jacoco.operator.Main " + MERGE + " " + output_file + " file " + input_files + " file file file ...");
+ System.out.println(" Report usage: java `classpath` org.jacoco.operator.Main " + REPORT + " " + html_output + " file " + xml_output + " file " + input_srcs + " file file file ... " + input_builds + " file file file " + title + " titleOfReport " + input_file + " file");
+ System.out.println("Where:");
+ System.out.println(" classpath should contain this application, and complete jacoco, and sometimes asm3 (depends on jacoco bundle)");
+ System.out.println(" " + die_on_failure + " - can be set as first parameter (after main switch), each warning then will cause exit of application");
+ System.out.println(" " + MERGE);
+ System.out.println(" " + output_file + " - is file where merged inputs will be saved");
+ System.out.println(" " + input_files + " - is list of files which will be merged into output file");
+ System.out.println(" " + REPORT);
+ System.out.println(" " + html_output + " - name of directory into which report will be generated. Should be empty or not yet exist");
+ System.out.println(" " + xml_output + " - is name of file into which xml report will be written");
+ System.out.println(" " + input_srcs + " - jars, zips or directories with java sources which will be used during report generation");
+ System.out.println(" " + input_builds + " - jars, zips or directories with compiled java classes, debug information must be present");
+ System.out.println(" " + title + " - title of report");
+ System.out.println(" " + input_file + " - input file with recorded coverage-run-session. By default jacoco saves into " + MergeTask.DEFAULT_NAME);
+
+ }
+
+ private static String[] cutFirstParam(String[] args) {
+ String[] arg = new String[args.length - 1];
+ System.arraycopy(args, 1, arg, 0, arg.length);
+ return arg;
+ }
+
+ private static Runnable proceedMerge(String[] a) throws IOException {
+ String doing = null;
+ String outputFile = null;
+ List<String> inputFiles = new ArrayList<String>(2);
+ for (String s : a) {
+ if (s.startsWith("--")) {
+ if (s.equalsIgnoreCase(die_on_failure)) {
+ doing = null;
+ dieOnFailure = true;
+ } else if (s.equalsIgnoreCase(output_file)) {
+ doing = output_file;
+ } else if (s.equalsIgnoreCase(input_files)) {
+ doing = input_files;
+ } else {
+ warnOrDie("Unknown Switch for merge " + s);
+ doing = null;
+ }
+ } else {
+ if (doing == null) {
+ warnOrDie("Missing switch during processing of " + s);
+ } else {
+ if (doing.equalsIgnoreCase(output_file)) {
+ outputFile = s;
+ } else if (doing.equalsIgnoreCase(input_files)) {
+ inputFiles.add(s);
+ } else {
+ warnOrDie("Unknown processing of switch of" + doing);
+ }
+
+ }
+ }
+ }
+ throwIfNullOrEmpty(outputFile, "empty output file");
+ File ff = new File(outputFile);
+ if (ff.exists()) {
+ warnOrDie("Warning, output file " + ff.getAbsolutePath() + " exists");
+ }
+ MergeTask m = new MergeTask(ff);
+ for (String string : inputFiles) {
+ if (checkIfNotNullOrEmpty(string)) {
+ File f = new File(string);
+ if (!f.exists()) {
+ warnOrDie("Warning, input coverage " + f.getAbsolutePath() + " does not exists!");
+ }
+ m.addInputFile(f);
+ }
+ }
+ return m;
+
+ }
+
+ private static Runnable proceedReport(String[] a) throws IOException {
+ String doing = null;
+ String htmlDir = null;
+ String xmlFile = null;
+ List<String> inputSrcs = new ArrayList<String>(1);
+ List<String> inputBuilds = new ArrayList<String>(1);
+ String titleValue = null;
+ String inputFile = null;
+ for (String s : a) {
+ if (s.startsWith("--")) {
+ if (s.equalsIgnoreCase(die_on_failure)) {
+ doing = null;
+ dieOnFailure = true;
+ } else if (s.equalsIgnoreCase(html_output)) {
+ doing = html_output;
+ } else if (s.equalsIgnoreCase(xml_output)) {
+ doing = xml_output;
+ } else if (s.equalsIgnoreCase(input_srcs)) {
+ doing = input_srcs;
+ } else if (s.equalsIgnoreCase(input_builds)) {
+ doing = input_builds;
+ } else if (s.equalsIgnoreCase(title)) {
+ doing = title;
+ } else if (s.equalsIgnoreCase(input_file)) {
+ doing = input_file;
+ } else {
+ warnOrDie("Unknown Switch for report " + s);
+ doing = null;
+ }
+ } else {
+ if (doing == null) {
+ warnOrDie("Missing switch during processing of " + s);
+ } else {
+ if (doing.equalsIgnoreCase(html_output)) {
+ htmlDir = s;
+ } else if (doing.equalsIgnoreCase(xml_output)) {
+ xmlFile = s;
+ } else if (doing.equalsIgnoreCase(input_srcs)) {
+ inputSrcs.add(s);
+ } else if (doing.equalsIgnoreCase(input_builds)) {
+ inputBuilds.add(s);
+ } else if (doing.equalsIgnoreCase(title)) {
+ titleValue = s;
+ } else if (doing.equalsIgnoreCase(input_file)) {
+ inputFile = s;
+ } else {
+ warnOrDie("Unknown processing of switch of " + doing);
+ }
+
+ }
+ }
+ }
+ File finalHtmlFile = null;
+ if (checkIfNotNullOrEmpty(htmlDir)) {
+ finalHtmlFile = new File(htmlDir);
+ if (finalHtmlFile.exists()) {
+ warnOrDie("Warning, direcotry for html report exists! " + finalHtmlFile.getAbsolutePath());
+ }
+ }
+ File finalXmlFile = null;
+ if (checkIfNotNullOrEmpty(xmlFile)) {
+ finalXmlFile = new File(xmlFile);
+ if (finalXmlFile.exists()) {
+ warnOrDie("Warning, file for xml report exists! " + finalHtmlFile.getAbsolutePath());
+ }
+ }
+ if (chckIfNUllOrEmpty(titleValue)) {
+ titleValue = "Coverage report";
+ }
+ throwIfNullOrEmpty(inputFile, "No coverage data file specified!");
+ File finalInputFile = new File(inputFile);
+
+ ReportGenerator rg = new ReportGenerator(titleValue, finalInputFile, finalHtmlFile, finalXmlFile);
+
+ for (String string : inputSrcs) {
+ if (checkIfNotNullOrEmpty(string)) {
+ File f = new File(string);
+ if (!f.exists()) {
+ warnOrDie("Warning, input source " + f.getAbsolutePath() + " does not exists!");
+ }
+ rg.addSource(f);
+ }
+ }
+ for (String string : inputBuilds) {
+ if (checkIfNotNullOrEmpty(string)) {
+ File f = new File(string);
+ if (!f.exists()) {
+ warnOrDie("Warning, input build " + f.getAbsolutePath() + " does not exists!");
+ }
+ rg.addClasses(f);
+ }
+ }
+ return rg;
+ }
+
+ private static String throwIfNullOrEmpty(String outputFile, String message) throws RuntimeException {
+ if (chckIfNUllOrEmpty(outputFile)) {
+ throw new RuntimeException(message);
+ }
+ return outputFile;
+ }
+
+ private static boolean checkIfNotNullOrEmpty(String string) {
+ return string != null && string.trim().length() != 0;
+ }
+
+ private static boolean chckIfNUllOrEmpty(String outputFile) {
+ return outputFile == null || outputFile.trim().length() == 0;
+ }
+
+ private static void warnOrDie(String string) {
+ System.err.println(string);
+ warned = true;
+
+ }
+}
diff --git a/tests/jacoco-operator/org/jacoco/operator/MergeTask.java b/tests/jacoco-operator/org/jacoco/operator/MergeTask.java
new file mode 100644
index 0000000..02c1b80
--- /dev/null
+++ b/tests/jacoco-operator/org/jacoco/operator/MergeTask.java
@@ -0,0 +1,157 @@
+/*
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package org.jacoco.operator;
+
+import java.io.BufferedOutputStream;
+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.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jacoco.core.data.ExecutionDataReader;
+import org.jacoco.core.data.ExecutionDataStore;
+import org.jacoco.core.data.ExecutionDataWriter;
+import org.jacoco.core.data.SessionInfoStore;
+
+/**
+ * Task for merging a set of execution data store files into a single file
+ *
+ * Inspired by:
+ * https://raw.github.com/jacoco/jacoco/master/org.jacoco.ant/src/org/jacoco/ant/MergeTask.java
+ */
+public class MergeTask implements Runnable {
+
+ public static final String DEFAULT_NAME = "jacoco.exec";
+ private File destfile;
+ private final List<File> files = new ArrayList<File>(1);
+
+ public MergeTask(File destfile) {
+ this.destfile = destfile;
+ }
+
+ public MergeTask(File destfile, List<File> inputs) {
+ this.destfile = destfile;
+ files.addAll(inputs);
+ }
+
+ /**
+ * Sets the location of the merged data store
+ *
+ * @param destfile Destination data store location
+ */
+ public void setDestfile(final File destfile) {
+ this.destfile = destfile;
+ }
+
+ public void addInputFile(final File input) {
+ if (input != null) {
+ files.add(input);
+ }
+ }
+
+ public void addInputFiles(final List<File> input) {
+ files.addAll(input);
+ }
+
+ public void execute() throws IOException {
+ if (destfile == null) {
+ throw new RuntimeException("Destination file must be supplied");
+ }
+
+ final SessionInfoStore infoStore = new SessionInfoStore();
+ final ExecutionDataStore dataStore = new ExecutionDataStore();
+
+ loadSourceFiles(infoStore, dataStore);
+
+ OutputStream outputStream = null;
+ try {
+
+ outputStream = new BufferedOutputStream(new FileOutputStream(
+ destfile));
+ final ExecutionDataWriter dataWriter = new ExecutionDataWriter(
+ outputStream);
+ infoStore.accept(dataWriter);
+ dataStore.accept(dataWriter);
+ } finally {
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ }
+
+ }
+
+ private void loadSourceFiles(final SessionInfoStore infoStore, final ExecutionDataStore dataStore) throws IOException {
+ if (files == null || files.isEmpty()) {
+ throw new RuntimeException("No input files");
+ }
+ final Iterator<?> resourceIterator = files.iterator();
+ while (resourceIterator.hasNext()) {
+ final File resource = (File) resourceIterator.next();
+
+ if (resource.isDirectory()) {
+ continue;
+ }
+ InputStream resourceStream = null;
+ try {
+ resourceStream = new FileInputStream(resource);
+ final ExecutionDataReader reader = new ExecutionDataReader(
+ resourceStream);
+ reader.setSessionInfoVisitor(infoStore);
+ reader.setExecutionDataVisitor(dataStore);
+ reader.read();
+ } finally {
+ if (resourceStream != null) {
+ resourceStream.close();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ execute();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+}
diff --git a/tests/jacoco-operator/org/jacoco/operator/ReportGenerator.java b/tests/jacoco-operator/org/jacoco/operator/ReportGenerator.java
new file mode 100644
index 0000000..84629f9
--- /dev/null
+++ b/tests/jacoco-operator/org/jacoco/operator/ReportGenerator.java
@@ -0,0 +1,292 @@
+/*
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.jacoco.operator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import org.jacoco.core.analysis.Analyzer;
+import org.jacoco.core.analysis.CoverageBuilder;
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.data.ExecutionDataReader;
+import org.jacoco.core.data.ExecutionDataStore;
+import org.jacoco.core.data.SessionInfoStore;
+import org.jacoco.report.DirectorySourceFileLocator;
+import org.jacoco.report.FileMultiReportOutput;
+import org.jacoco.report.IReportVisitor;
+import org.jacoco.report.MultiSourceFileLocator;
+import org.jacoco.report.html.HTMLFormatter;
+import org.jacoco.report.xml.XMLFormatter;
+
+/**
+ * This example creates a HTML report for eclipse like projects based on a
+ * single execution data store called jacoco.exec. The report contains no
+ * grouping information.
+ *
+ * The class files under test must be compiled with debug information, otherwise
+ * source highlighting will not work.
+ *
+ * Originally based on:
+ * http://www.eclemma.org/jacoco/trunk/doc/examples/java/ReportGenerator.java
+ */
+public class ReportGenerator implements Runnable {
+
+ private final String title;
+ private final File executionDataFile;
+ private final List<File> classesDirectories = new ArrayList<File>(1);
+ private final List<File> sourceDirectories = new ArrayList<File>(1);
+ private File reportDirectory;
+ private File xmlOutput;
+ private ExecutionDataStore executionDataStore;
+ private SessionInfoStore sessionInfoStore;
+ private String XML_DEF_NAME = "coverage-summary.xml";
+
+ /**
+ * Create a new generator based for the given project.
+ *
+ * @param projectDirectory
+ */
+ public ReportGenerator(final File projectDirectory) {
+ this.title = projectDirectory.getName();
+ this.executionDataFile = new File(projectDirectory, MergeTask.DEFAULT_NAME);
+ this.classesDirectories.add(new File(projectDirectory, "bin"));
+ this.sourceDirectories.add(new File(projectDirectory, "src"));
+ this.reportDirectory = new File(projectDirectory, "coveragereport");
+ this.xmlOutput = new File(projectDirectory, XML_DEF_NAME);
+ }
+
+ public ReportGenerator(String title, File exec, File classes, File sources, File htmlReport, File xmlReport) {
+ this.title = title;
+ this.executionDataFile = exec;
+ if (classes != null) {
+ this.classesDirectories.add(classes);
+ }
+ if (sources != null) {
+ this.sourceDirectories.add(sources);
+ }
+ this.reportDirectory = htmlReport;
+
+ this.xmlOutput = xmlReport;
+ }
+
+ public ReportGenerator(String title, File exec, List<File> classes, List<File> sources, File htmlReport, File xmlReport) {
+ this.title = title;
+ this.executionDataFile = exec;
+ if (classes != null) {
+ this.classesDirectories.addAll(classes);
+ }
+ if (sources != null) {
+ this.sourceDirectories.addAll(sources);
+ }
+ this.reportDirectory = htmlReport;
+ this.xmlOutput = xmlReport;
+ }
+
+ public ReportGenerator(String title, File exec, List<File> classes, List<File> sources, File report) {
+ this.title = title;
+ this.executionDataFile = exec;
+ if (classes != null) {
+ this.classesDirectories.addAll(classes);
+ }
+ if (sources != null) {
+ this.sourceDirectories.addAll(sources);
+ }
+ this.reportDirectory = report;
+ this.xmlOutput = new File(report, XML_DEF_NAME);
+ }
+
+ public ReportGenerator(String title, File exec, File htmlReport, File xmlReport) {
+ this.title = title;
+ this.executionDataFile = exec;
+ this.reportDirectory = htmlReport;
+ this.xmlOutput = xmlReport;
+ }
+
+ public ReportGenerator(String title, File exec, File report) {
+ this.title = title;
+ this.executionDataFile = exec;
+ this.reportDirectory = report;
+ this.xmlOutput = new File(report, XML_DEF_NAME);
+ }
+
+ public void addSource(File f) {
+ sourceDirectories.add(f);
+
+ }
+
+ public void addClasses(File f) {
+ classesDirectories.add(f);
+
+ }
+
+ /**
+ * Create the report.
+ *
+ * @throws IOException
+ */
+ public void execute() throws IOException {
+
+ // Read the jacoco.exec file. Multiple data stores could be merged
+ // at this point
+ loadExecutionData();
+
+ // Run the structure analyzer on a single class folder to build up
+ // the coverage model. The process would be similar if your classes
+ // were in a jar file. Typically you would create a bundle for each
+ // class folder and each jar you want in your report. If you have
+ // more than one bundle you will need to add a grouping node to your
+ // report
+ final IBundleCoverage bundleCoverage = analyzeStructure();
+
+ if (reportDirectory != null) {
+ createHtmlReport(bundleCoverage);
+ }
+ if (xmlOutput != null) {
+ createXmlReport(bundleCoverage);
+ }
+
+ }
+
+ private void createHtmlReport(final IBundleCoverage bundleCoverage)
+ throws IOException {
+
+ // Create a concrete report visitor based on some supplied
+ // configuration. In this case we use the defaults
+ final HTMLFormatter htmlFormatter = new HTMLFormatter();
+ final IReportVisitor visitor = htmlFormatter.createVisitor(new FileMultiReportOutput(reportDirectory));
+
+ // Initialize the report with all of the execution and session
+ // information. At this point the report doesn't know about the
+ // structure of the report being created
+ visitor.visitInfo(sessionInfoStore.getInfos(),
+ executionDataStore.getContents());
+
+ // Populate the report structure with the bundle coverage information.
+ // Call visitGroup if you need groups in your report.
+ MultiSourceFileLocator msf = new MultiSourceFileLocator(4);
+ for (File file : sourceDirectories) {
+ msf.add(new DirectorySourceFileLocator(
+ file, "utf-8", 4));
+ }
+
+ visitor.visitBundle(bundleCoverage, msf);
+
+ // Signal end of structure information to allow report to write all
+ // information out
+ visitor.visitEnd();
+
+ }
+
+ private void createXmlReport(final IBundleCoverage bundleCoverage)
+ throws IOException {
+
+ OutputStream fos = new FileOutputStream(xmlOutput);
+ try {
+ // Create a concrete report visitor based on some supplied
+ // configuration. In this case we use the defaults
+ final XMLFormatter htmlFormatter = new XMLFormatter();
+ final IReportVisitor visitor = htmlFormatter.createVisitor(fos);
+
+ // Initialize the report with all of the execution and session
+ // information. At this point the report doesn't know about the
+ // structure of the report being created
+ visitor.visitInfo(sessionInfoStore.getInfos(),
+ executionDataStore.getContents());
+
+ // Populate the report structure with the bundle coverage information.
+ // Call visitGroup if you need groups in your report.
+ visitor.visitBundle(bundleCoverage, null);
+
+
+ // Signal end of structure information to allow report to write all
+ // information out
+ visitor.visitEnd();
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+
+ }
+
+ private void loadExecutionData() throws IOException {
+ final FileInputStream fis = new FileInputStream(executionDataFile);
+ try {
+ final ExecutionDataReader executionDataReader = new ExecutionDataReader(
+ fis);
+ executionDataStore = new ExecutionDataStore();
+ sessionInfoStore = new SessionInfoStore();
+
+ executionDataReader.setExecutionDataVisitor(executionDataStore);
+ executionDataReader.setSessionInfoVisitor(sessionInfoStore);
+
+ while (executionDataReader.read()) {
+ }
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ }
+
+ private IBundleCoverage analyzeStructure() throws IOException {
+ final CoverageBuilder coverageBuilder = new CoverageBuilder();
+ final Analyzer analyzer = new Analyzer(executionDataStore,
+ coverageBuilder);
+ for (File file : classesDirectories) {
+ analyzer.analyzeAll(file);
+
+ }
+
+ return coverageBuilder.getBundle(title);
+ }
+
+ @Override
+ public void run() {
+ try {
+ execute();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+}