diff options
author | Marc R. Hoffmann <hoffmann@mountainminds.com> | 2017-05-25 00:53:18 +0200 |
---|---|---|
committer | Evgeny Mandrikov <Godin@users.noreply.github.com> | 2017-05-25 00:53:18 +0200 |
commit | 13f12d39db0b3c0ddc60124572e5d4f984be0255 (patch) | |
tree | 2e1ea16bf0675dfd83730f48ad48edf2e880df89 /org.jacoco.cli.test | |
parent | 10f3ff0dd010d647625ef5937f301126250267d0 (diff) | |
download | jacoco-13f12d39db0b3c0ddc60124572e5d4f984be0255.tar.gz |
Add Command Line Interface (#525)
Diffstat (limited to 'org.jacoco.cli.test')
14 files changed, 1076 insertions, 0 deletions
diff --git a/org.jacoco.cli.test/.classpath b/org.jacoco.cli.test/.classpath new file mode 100644 index 00000000..0ed344a5 --- /dev/null +++ b/org.jacoco.cli.test/.classpath @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry including="**/*.java" kind="src" output="target/classes" path="src"> + <attributes> + <attribute name="optional" value="true"/> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="output" path="target/classes"/> +</classpath> diff --git a/org.jacoco.cli.test/.project b/org.jacoco.cli.test/.project new file mode 100644 index 00000000..fbd366b0 --- /dev/null +++ b/org.jacoco.cli.test/.project @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.jacoco.cli.test</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.m2e.core.maven2Builder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.m2e.core.maven2Nature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> + <linkedResources> + <link> + <name>.settings</name> + <type>2</type> + <locationURI>PARENT-1-PROJECT_LOC/org.jacoco.core.test/.settings</locationURI> + </link> + </linkedResources> +</projectDescription> diff --git a/org.jacoco.cli.test/about.html b/org.jacoco.cli.test/about.html new file mode 100644 index 00000000..d31112db --- /dev/null +++ b/org.jacoco.cli.test/about.html @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html> +<head> +<title>About</title> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p> + @build.date@ +</p> + +<h3>License</h3> + +<p> + All Content in this plug-in is made available by Mountainminds GmbH & Co. + KG, Munich. Unless otherwise indicated below, the Content is provided to you + under the terms and conditions of the Eclipse Public License Version 1.0 + ("EPL"). A copy of the EPL is available at + <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content. +</p> + +</body> +</html>
\ No newline at end of file diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml new file mode 100644 index 00000000..bc3c6b7d --- /dev/null +++ b/org.jacoco.cli.test/pom.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2009, 2017 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 +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.jacoco</groupId> + <artifactId>org.jacoco.tests</artifactId> + <version>0.7.10-SNAPSHOT</version> + <relativePath>../org.jacoco.tests</relativePath> + </parent> + + <artifactId>org.jacoco.cli.test</artifactId> + + <name>JaCoCo :: Test :: Command Line Interface</name> + + <properties> + <jacoco.includes>org.jacoco.cli.*</jacoco.includes> + </properties> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>org.jacoco.cli</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + </dependencies> + +</project> diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java new file mode 100644 index 00000000..4d12a373 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +import org.junit.Before; + +/** + * Base class for command tests. + */ +public abstract class CommandTestBase { + + protected StringWriter out; + protected StringWriter err; + protected int result; + + @Before + public void before() { + out = new StringWriter(); + err = new StringWriter(); + } + + protected int execute(String... args) throws Exception { + result = new Main(args).execute(new PrintWriter(out), + new PrintWriter(err)); + return result; + } + + protected void assertOk() { + assertEquals(err.toString(), 0, result); + } + + protected void assertFailure() { + assertEquals(-1, result); + } + + protected void assertNoOutput(StringWriter buffer) { + assertEquals("", buffer.toString()); + } + + protected void assertContains(String expected, StringWriter buffer) { + final String content = buffer.toString(); + assertTrue(content, content.contains(expected)); + } + + protected String getClassPath() { + final String name = getClass().getName(); + final String res = "/" + name.replace('.', '/') + ".class"; + String loc = getClass().getResource(res).getFile(); + try { + loc = URLDecoder.decode(loc, "UTF-8"); + } catch (UnsupportedEncodingException e) { + } + return loc.substring(0, loc.length() - res.length()); + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java new file mode 100644 index 00000000..5a0d7424 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal; + +import org.junit.Test; + +/** + * Unit tests for {@link Main}. + */ +public class MainTest extends CommandTestBase { + + @Test + public void should_print_usage_when_no_arguments_given() throws Exception { + execute(); + + assertFailure(); + assertNoOutput(out); + assertContains("Argument \"<command>\" is required", err); + assertContains("Usage: java -jar jacococli.jar --help | <command>", + err); + assertContains("Command line interface for JaCoCo.", err); + } + + @Test + public void should_print_error_message_when_invalid_command_is_given() + throws Exception { + execute("foo"); + + assertFailure(); + assertNoOutput(out); + assertContains("\"foo\" is not a valid value for \"<command>\"", err); + assertContains("Usage: java -jar jacococli.jar --help | <command>", + err); + } + + @Test + public void should_print_general_usage_when_help_option_is_given() + throws Exception { + execute("--help"); + + assertOk(); + assertNoOutput(err); + assertContains("Usage: java -jar jacococli.jar --help | <command>", + out); + assertContains("<command> : dump|instrument|merge|report", out); + } + + @Test + public void should_print_command_usage_when_command_and_help_option_is_given() + throws Exception { + execute("dump", "--help"); + + assertOk(); + assertNoOutput(err); + assertContains("Usage: java -jar jacococli.jar dump", out); + assertContains( + "Request execution data from a JaCoCo agent running in 'tcpserver' output mode.", + out); + } + + @Test + public void should_not_print_any_output_when_quiet_option_is_given() + throws Exception { + execute("version", "--quiet"); + + assertOk(); + assertNoOutput(out); + assertNoOutput(err); + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java new file mode 100644 index 00000000..83f79bc9 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.w3c.dom.Document; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * Unit tests for {@link XmlDocumentation}. + */ +public class XmlDocumentationTest { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + private DocumentBuilder builder; + private XPath xpath; + + @Before + public void before() throws Exception { + final DocumentBuilderFactory builderFactory = DocumentBuilderFactory + .newInstance(); + builder = builderFactory.newDocumentBuilder(); + builder.setErrorHandler(new ErrorHandler() { + public void error(SAXParseException exception) throws SAXException { + fail(exception.getMessage()); + } + + public void fatalError(SAXParseException exception) + throws SAXException { + fail(exception.getMessage()); + } + + public void warning(SAXParseException exception) + throws SAXException { + fail(exception.getMessage()); + } + }); + + xpath = XPathFactory.newInstance().newXPath(); + } + + @Test + public void should_create_documentation() throws Exception { + File file = new File(tmp.getRoot(), "doc.xml"); + + XmlDocumentation.main(file.getAbsolutePath()); + + Document doc = parse(file); + + assertContains("java -jar jacococli.jar report", + "/documentation/command[@name='report']/usage/text()", doc); + + assertContains("Generate reports", + "/documentation/command[@name='report']/description/text()", + doc); + + assertContains("<execfiles>", + "/documentation/command[@name='report']/option[1]/usage/text()", + doc); + + assertContains("false", + "/documentation/command[@name='report']/option[1]/@required", + doc); + + assertContains("true", + "/documentation/command[@name='report']/option[1]/@multiple", + doc); + + assertContains("-classfiles <path>", + "/documentation/command[@name='report']/option[2]/usage/text()", + doc); + + assertContains("true", + "/documentation/command[@name='report']/option[2]/@multiple", + doc); + + } + + private Document parse(File file) throws Exception { + InputStream in = new FileInputStream(file); + try { + return builder.parse(new InputSource(in)); + } finally { + in.close(); + } + } + + private void assertContains(String expected, String query, Document doc) + throws XPathExpressionException { + final String actual = eval(query, doc); + assertTrue(actual, actual.contains(expected)); + } + + private String eval(String query, Document doc) + throws XPathExpressionException { + return (String) xpath.evaluate(query, doc, XPathConstants.STRING); + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java new file mode 100644 index 00000000..62934e28 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import org.jacoco.cli.internal.CommandTestBase; +import org.junit.Test; + +/** + * Unit tests for {@link ClassInfo}. + */ +public class ClassInfoTest extends CommandTestBase { + + @Test + public void should_print_usage_when_invalid_option_is_given() + throws Exception { + execute("classinfo", "--invalid"); + + assertFailure(); + assertContains("\"--invalid\" is not a valid option", err); + assertContains( + "java -jar jacococli.jar classinfo [<classlocations> ...]", + err); + } + + @Test + public void should_print_warning_when_no_class_files_are_provided() + throws Exception { + execute("classinfo"); + + assertOk(); + assertContains("[WARN] No class files provided.", out); + } + + @Test + public void should_print_class_info() throws Exception { + execute("classinfo", getClassPath()); + + assertOk(); + assertContains( + "class name: org/jacoco/cli/internal/commands/ClassInfoTest", + out); + assertContains("methods: 4", out); + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java new file mode 100644 index 00000000..3a859f52 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; + +import org.jacoco.cli.internal.CommandTestBase; +import org.jacoco.core.runtime.IRemoteCommandVisitor; +import org.jacoco.core.runtime.RemoteControlReader; +import org.jacoco.core.runtime.RemoteControlWriter; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Unit tests for {@link Dump}. + */ +public class DumpTest extends CommandTestBase { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + private ServerSocket serverSocket; + + @After + public void after() throws IOException { + if (serverSocket != null) { + serverSocket.close(); + } + } + + @Test + public void should_print_usage_when_no_argument_is_given() + throws Exception { + execute("dump"); + assertFailure(); + assertContains("Option \"--destfile\" is required", err); + assertContains("java -jar jacococli.jar dump [--address <address>]", + err); + } + + @Test + public void should_write_dump() throws Exception { + + File execfile = new File(tmp.getRoot(), "jacoco.exec"); + int port = startMockServer(); + + execute("dump", "--destfile", execfile.getAbsolutePath(), "--port", + String.valueOf(port)); + + assertOk(); + assertContains("[INFO] Connecting to ", out); + assertContains("[INFO] Writing execution data to " + + execfile.getAbsolutePath(), out); + assertTrue(execfile.exists()); + } + + @Test + public void should_log_connection_error_when_retry_is_specified() + throws Exception { + + File execfile = new File(tmp.getRoot(), "jacoco.exec"); + int port = unusedPort(); + + try { + execute("dump", "--destfile", execfile.getAbsolutePath(), "--port", + String.valueOf(port), "--retry", "1"); + fail("IOException expected"); + } catch (IOException ignore) { + } + + assertContains("[WARN] Connection refused", err); + } + + private int startMockServer() throws IOException { + serverSocket = new ServerSocket(0, 0, InetAddress.getByName(null)); + new Thread() { + @Override + public void run() { + try { + serveRequest(serverSocket.accept()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }.start(); + return serverSocket.getLocalPort(); + } + + private void serveRequest(Socket socket) throws IOException { + final RemoteControlWriter writer = new RemoteControlWriter( + socket.getOutputStream()); + final RemoteControlReader reader = new RemoteControlReader( + socket.getInputStream()); + reader.setRemoteCommandVisitor(new IRemoteCommandVisitor() { + + public void visitDumpCommand(boolean dump, boolean reset) + throws IOException { + writer.sendCmdOk(); + } + }); + while (reader.read()) { + } + } + + private int unusedPort() throws IOException { + final ServerSocket serverSocket = new ServerSocket(0, 0, + InetAddress.getByName(null)); + final int port = serverSocket.getLocalPort(); + serverSocket.close(); + return port; + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java new file mode 100644 index 00000000..54540865 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.jacoco.cli.internal.CommandTestBase; +import org.jacoco.core.data.ExecutionData; +import org.jacoco.core.data.ExecutionDataWriter; +import org.jacoco.core.data.SessionInfo; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Unit tests for {@link ExecInfo}. + */ +public class ExecInfoTest extends CommandTestBase { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Test + public void should_print_usage_when_invalid_argument_is_given() + throws Exception { + execute("execinfo", "--invalid"); + + assertFailure(); + assertContains("\"--invalid\" is not a valid option", err); + assertContains("java -jar jacococli.jar execinfo [<execfiles> ...]", + err); + } + + @Test + public void should_print_warning_when_no_exec_files_are_provided() + throws Exception { + execute("execinfo"); + + assertOk(); + assertContains("[WARN] No execution data files provided.", out); + } + + @Test + public void should_print_execution_data_info() throws Exception { + File execfile = createExecFile(); + + execute("execinfo", execfile.getAbsolutePath()); + + assertOk(); + assertContains("[INFO] Loading exec file " + execfile.getAbsolutePath(), + out); + assertContains("CLASS ID HITS/PROBES CLASS NAME", out); + assertContains("Session \"testid\":", out); + assertContains("0000000000001234 2 of 3 foo/MyClass", out); + } + + private File createExecFile() throws IOException { + File f = new File(tmp.getRoot(), "test.exec"); + final FileOutputStream out = new FileOutputStream(f); + final ExecutionDataWriter writer = new ExecutionDataWriter(out); + writer.visitSessionInfo(new SessionInfo("testid", 1, 2)); + writer.visitClassExecution(new ExecutionData(0x1234, "foo/MyClass", + new boolean[] { false, true, true })); + out.close(); + return f; + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java new file mode 100644 index 00000000..5d70b48c --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +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.HashSet; +import java.util.Set; + +import org.jacoco.cli.internal.CommandTestBase; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; + +/** + * Unit tests for {@link Instrument}. + */ +public class InstrumentTest extends CommandTestBase { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Test + public void should_print_usage_when_no_options_are_given() + throws Exception { + execute("instrument"); + assertFailure(); + assertContains("Option \"--dest\" is required", err); + assertContains( + "Usage: java -jar jacococli.jar instrument [<sourcefiles> ...]", + err); + } + + @Test + public void should_instrument_class_files_and_copy_resources() + throws Exception { + File destdir = tmp.getRoot(); + + execute("instrument", "--dest", destdir.getAbsolutePath(), + getClassPath()); + + assertOk(); + assertContains("[INFO] 14 classes instrumented to " + + destdir.getAbsolutePath(), out); + + // non class-file resources are copied: + assertTrue(new File(destdir, "about.html").isFile()); + + assertInstrumented(new File(destdir, + "org/jacoco/cli/internal/commands/InstrumentTest.class")); + } + + @Test + public void should_not_instrument_anything_when_no_source_is_given() + throws Exception { + File destdir = tmp.getRoot(); + + execute("instrument", "--dest", destdir.getAbsolutePath()); + + assertOk(); + assertArrayEquals(new String[0], destdir.list()); + } + + @Test + public void should_not_create_dest_file_when_source_class_is_broken() + throws Exception { + File srcdir = new File(tmp.getRoot(), "src"); + srcdir.mkdir(); + File destdir = new File(tmp.getRoot(), "dest"); + destdir.mkdir(); + + OutputStream out = new FileOutputStream( + new File(srcdir, "Broken.class")); + out.write((byte) 0xca); + out.write((byte) 0xfe); + out.write((byte) 0xba); + out.write((byte) 0xbe); + out.write((byte) 0x00); + out.write((byte) 0x00); + out.write((byte) 0x00); + out.write((byte) 50); + out.close(); + + try { + execute("instrument", "--dest", destdir.getAbsolutePath(), + srcdir.getAbsolutePath()); + fail("exception expected"); + } catch (IOException expected) { + } + + assertFalse(new File(destdir, "Broken.class").exists()); + } + + private void assertInstrumented(File classfile) throws IOException { + InputStream in = new FileInputStream(classfile); + ClassReader reader = new ClassReader(in); + in.close(); + final Set<String> fields = new HashSet<String>(); + reader.accept(new ClassVisitor(Opcodes.ASM5) { + @Override + public FieldVisitor visitField(int access, String name, String desc, + String signature, Object value) { + fields.add(name); + return null; + } + }, 0); + assertTrue(fields.contains("$jacocoData")); + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java new file mode 100644 index 00000000..ea534751 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.jacoco.cli.internal.CommandTestBase; +import org.jacoco.core.data.ExecutionData; +import org.jacoco.core.data.ExecutionDataWriter; +import org.jacoco.core.tools.ExecFileLoader; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Unit tests for {@link Merge}. + */ +public class MergeTest extends CommandTestBase { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Test + public void should_print_usage_when_no_options_are_given() + throws Exception { + execute("merge"); + + assertFailure(); + assertContains("Option \"--destfile\" is required", err); + assertContains("java -jar jacococli.jar merge [<execfiles> ...]", err); + } + + @Test + public void should_print_warning_when_no_exec_files_are_provided() + throws Exception { + File dest = new File(tmp.getRoot(), "merged.exec"); + execute("merge", "--destfile", dest.getAbsolutePath()); + + assertOk(); + assertContains("[WARN] No execution data files provided.", out); + Set<String> names = loadExecFile(dest); + assertEquals(Collections.emptySet(), names); + } + + @Test + public void should_merge_exec_files() throws Exception { + File a = createExecFile("a"); + File b = createExecFile("b"); + File c = createExecFile("c"); + File dest = new File(tmp.getRoot(), "merged.exec"); + + execute("merge", "--destfile", dest.getAbsolutePath(), + a.getAbsolutePath(), b.getAbsolutePath(), c.getAbsolutePath()); + + assertOk(); + Set<String> names = loadExecFile(dest); + assertEquals(new HashSet<String>(Arrays.asList("a", "b", "c")), names); + } + + private File createExecFile(String name) throws IOException { + File file = new File(tmp.getRoot(), name + ".exec"); + final FileOutputStream execout = new FileOutputStream(file); + ExecutionDataWriter writer = new ExecutionDataWriter(execout); + writer.visitClassExecution(new ExecutionData(name.hashCode(), name, + new boolean[] { true })); + execout.close(); + return file; + } + + private Set<String> loadExecFile(File file) throws IOException { + ExecFileLoader loader = new ExecFileLoader(); + loader.load(file); + Set<String> names = new HashSet<String>(); + for (ExecutionData d : loader.getExecutionDataStore().getContents()) { + names.add(d.getName()); + } + return names; + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java new file mode 100644 index 00000000..77564c8f --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileOutputStream; + +import org.jacoco.cli.internal.CommandTestBase; +import org.jacoco.core.data.ExecutionData; +import org.jacoco.core.data.ExecutionDataWriter; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Unit tests for {@link Report}. + */ +public class ReportTest extends CommandTestBase { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Test + public void should_print_usage_when_no_options_are_given() + throws Exception { + execute("report"); + + assertFailure(); + assertContains("Option \"--classfiles\" is required", err); + assertContains( + "Usage: java -jar jacococli.jar report [<execfiles> ...]", err); + } + + @Test + public void should_print_warning_when_no_exec_files_are_provided() + throws Exception { + execute("report", "--classfiles", getClassPath()); + + assertOk(); + assertContains("[WARN] No execution data files provided.", out); + } + + @Test + public void should_print_number_of_analyzed_classes() throws Exception { + execute("report", "--classfiles", getClassPath()); + + assertOk(); + assertContains("[INFO] Analyzing 14 classes.", out); + } + + @Test + public void should_print_warning_when_exec_data_does_not_match() + throws Exception { + File exec = new File(tmp.getRoot(), "jacoco.exec"); + final FileOutputStream execout = new FileOutputStream(exec); + ExecutionDataWriter writer = new ExecutionDataWriter(execout); + // Add probably invalid id for this test class: + writer.visitClassExecution( + new ExecutionData(0x123, getClass().getName().replace('.', '/'), + new boolean[] { true })); + execout.close(); + + execute("report", exec.getAbsolutePath(), "--classfiles", + getClassPath()); + + assertOk(); + assertContains("[WARN] Some classes do not match with execution data.", + out); + assertContains( + "[WARN] For report generation the same class files must be used as at runtime.", + out); + assertContains( + "[WARN] Execution data for class org/jacoco/cli/internal/commands/ReportTest does not match.", + out); + } + + @Test + public void should_create_xml_report_when_xml_option_is_provided() + throws Exception { + File xml = new File(tmp.getRoot(), "coverage.xml"); + + execute("report", "--classfiles", getClassPath(), "--xml", + xml.getAbsolutePath()); + + assertOk(); + assertTrue(xml.isFile()); + } + + @Test + public void should_create_csv_report_when_csv_option_is_provided() + throws Exception { + File csv = new File(tmp.getRoot(), "coverage.csv"); + + execute("report", "--classfiles", getClassPath(), "--csv", + csv.getAbsolutePath()); + + assertOk(); + assertTrue(csv.isFile()); + } + + @Test + public void should_create_html_report_when_html_option_is_provided() + throws Exception { + File html = new File(tmp.getRoot(), "coverage"); + + execute("report", "--classfiles", getClassPath(), "--sourcefiles", + "./src", "--html", html.getAbsolutePath()); + + assertOk(); + assertTrue(html.isDirectory()); + assertTrue(new File(html, + "org.jacoco.cli.internal.commands/ReportTest.html").isFile()); + assertTrue(new File(html, + "org.jacoco.cli.internal.commands/ReportTest.java.html") + .isFile()); + } + + @Test + public void should_use_all_values_when_multiple_classfiles_options_are_provided() + throws Exception { + File html = new File(tmp.getRoot(), "coverage"); + + final String c1 = getClassPath() + + "/org/jacoco/cli/internal/commands/ReportTest.class"; + final String c2 = getClassPath() + + "/org/jacoco/cli/internal/commands/DumpTest.class"; + + execute("report", "--classfiles", c1, "--classfiles", c2, "--html", + html.getAbsolutePath()); + + assertOk(); + assertTrue(html.isDirectory()); + assertTrue(new File(html, + "org.jacoco.cli.internal.commands/ReportTest.html").isFile()); + assertTrue( + new File(html, "org.jacoco.cli.internal.commands/DumpTest.html") + .isFile()); + } + +} diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java new file mode 100644 index 00000000..56b259a5 --- /dev/null +++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import org.jacoco.cli.internal.CommandTestBase; +import org.jacoco.core.JaCoCo; +import org.junit.Test; + +/** + * Unit tests for {@link Version}. + */ +public class VersionTest extends CommandTestBase { + + @Test + public void should_print_version() throws Exception { + execute("version"); + + assertOk(); + assertContains(JaCoCo.VERSION, out); + } + +} |