Upgrade jacoco to v0.8.4
Test: None
Change-Id: I4ca05dd439b98fabd6054bee728d85e3aa11486d
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..0689525
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,107 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Build jacoco-agent from sources for the platform
+//
+// Note: this is only intended to be used for the platform development. This is *not* intended
+// to be used in the SDK where apps can use the official jacoco release.
+java_library {
+ name: "jacocoagent",
+ installable: true,
+
+ srcs: [
+ "org.jacoco.core/src/**/*.java",
+ "org.jacoco.agent/src/**/*.java",
+ "org.jacoco.agent.rt/src/**/*.java",
+ ],
+
+ // Some Jacoco source files depend on classes that do not exist in Android.
+ // While these classes are not executed at runtime (because we use offline
+ // instrumentation), they will cause issues when compiling them with ART
+ // during dex pre-opting. Therefore, it would prevent from applying code
+ // coverage on classes in the bootclasspath (frameworks, services, ...) or
+ // system apps.
+ // Note: we still may need to update the source code to cut dependencies in
+ // mandatory jacoco classes.
+ exclude_srcs: [
+ "org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java",
+ "org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/PreMain.java",
+ "org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java",
+ "org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/JmxRegistration.java",
+ ],
+
+ // In order to include Jacoco in core libraries, we cannot depend on
+ // anything in the bootclasspath (or we would create dependency cycle).
+ // Therefore we compile against the SDK android.jar which gives the same
+ // APIs Jacoco depends on.
+ sdk_version: "9",
+
+ // TODO(b/69671801): there's no bytecode on the device, so these shouldn't
+ // be necessary.
+ static_libs: [
+ "asm-7.0",
+ "asm-commons-7.0",
+ "asm-tree-7.0",
+ ],
+}
+
+// Generates stubs containing the classes that will be referenced by instrumented bytecode.
+droidstubs {
+ name: "jacoco-stubs-gen",
+ srcs: ["org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java"],
+}
+
+// A stubs target containing the parts of JaCoCo that we need to add to the hidden API whitelist.
+java_library {
+ name: "jacoco-stubs",
+ compile_dex: true,
+ srcs: [":jacoco-stubs-gen"],
+}
+
+// Build jacoco-cli from sources for the platform
+
+// TODO(jeffrygaston) it'd be nice to keep the build process and/or list of source files in sync with
+// what is defined in the pom.xml files, although it's probably much more trouble than it's worth
+java_library_host {
+ name: "jacoco-cli",
+
+ manifest: "org.jacoco.cli/src/MANIFEST.MF",
+
+ srcs: [
+ "org.jacoco.core/src/**/*.java",
+ "org.jacoco.report/src/**/*.java",
+ "org.jacoco.cli/src/**/*.java",
+ ],
+
+ java_resource_dirs: [
+ "org.jacoco.core/src",
+ "org.jacoco.report/src",
+ ],
+
+ static_libs: [
+ "asm-7.0",
+ "asm-commons-7.0",
+ "asm-tree-7.0",
+ "args4j-2.0.28",
+ ],
+
+ dist: {
+ targets: [
+ "dist_files",
+ "apps_only",
+ ],
+ },
+}
diff --git a/FETCH_HEAD b/FETCH_HEAD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/FETCH_HEAD
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..43947c9
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,18 @@
+name: "jacoco"
+description: "JaCoCo is a free Java code coverage library."
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://www.jacoco.org/"
+ }
+ url {
+ type: GIT
+ value: "https://github.com/jacoco/jacoco.git"
+ }
+ version: "v0.8.4"
+ last_upgrade_date {
+ year: 2019
+ month: 5
+ day: 13
+ }
+}
diff --git a/MODULE_LICENSE_EPL b/MODULE_LICENSE_EPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_EPL
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..54fc346
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,14 @@
+License
+=======
+
+Copyright (c) 2009, 2015 Mountainminds GmbH & Co. KG and Contributors
+
+The JaCoCo Java Code Coverage Library and all included documentation is made
+available by Mountainminds GmbH & Co. KG, Munich. Except 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
+[http://www.eclipse.org/legal/epl-v10.html](http://www.eclipse.org/legal/epl-v10.html).
+
+Please visit
+[http://www.eclemma.org/jacoco/trunk/doc/license.html](http://www.eclemma.org/jacoco/trunk/doc/license.html)
+for the complete license information including third party licenses and trademarks.
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..607b5c3
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+# Default code reviewers picked from top 3 or more developers.
+# Please update this list if you find better candidates.
+allenhair@google.com
diff --git a/README.android b/README.android
new file mode 100644
index 0000000..8fa2b90
--- /dev/null
+++ b/README.android
@@ -0,0 +1,23 @@
+We build an equivalent of the jacoco-agent.jar which contains classes from org.jacoco.core,
+org.jacoco.agent and org.jacoco.agent.rt packages but also classes from asm 5.0.1.
+
+However, Jacoco depends on classes that do not exist in Android (java.lang.instrument.* or
+javax.management.*) for runtime instrumentation only. The ART compiler would reject those classes
+when they are either in the bootclasspath (core, frameworks, ...) or system apps.
+
+Since we only use offline instrumentation for code coverage (using Jack) and do not execute these
+classes at runtime, we simply not compile them here.
+
+We also need to modify the source code to cut dependencies to the classes that we exclude from the
+compilation. The changes are surrounded by "BEGIN android-change" and "END android-change". Here
+is the list of the changes:
+
+1) Remove the creation of JmxRegistration in org.jacoco.agent.rt.internal.Agent.
+2) Change default OutputMode to none in org.jacoco.core.runtime.AgentOptions
+3) Change the runtime to reduce dependencies on core libraries.
+ Previously, Offline's static initializer would eagerly create an
+ Agent, a process which has lots of dependencies. With this change,
+ Offline only eagerly creates a Map<Long, ExecutionData>, which is much
+ more lightweight. The Agent is only created when it's actually
+ needed. This makes it possible to instrument a lot of more core
+ libraries without creating a circular dependency at runtime.
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..d645621
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,16 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+JACOCO_PACKAGE_NAME := org.jacoco.agent.rt.internal
+
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java
index 8cc19a7..f21968c 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java
@@ -37,6 +37,7 @@
import org.jacoco.core.runtime.RuntimeData;
import org.jacoco.core.tools.ExecFileLoader;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
/**
@@ -132,6 +133,9 @@
}
@Test
+ // BEGIN android-change
+ @Ignore
+ // END android-change
public void startup_should_register_mbean_when_enabled() throws Exception {
options.setJmx(true);
Agent agent = createAgent();
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
index fb5cf5f..b6debe1 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
@@ -45,8 +45,26 @@
* @return global instance
*/
public static synchronized Agent getInstance(final AgentOptions options) {
+ // BEGIN android-change
+ return getInstance(options, new RuntimeData());
+ // END android-change
+ }
+
+ // BEGIN android-change
+ /**
+ * Returns a global instance which is already started, reusing an existing set of runtime
+ * data. If the method is called the first time the instance is created with the given
+ * options.
+ *
+ * @param options
+ * options to configure the instance
+ * @param data
+ * the runtime data to reuse
+ * @return global instance
+ */
+ public static synchronized Agent getInstance(final AgentOptions options, RuntimeData data) {
if (singleton == null) {
- final Agent agent = new Agent(options, IExceptionLogger.SYSTEM_ERR);
+ final Agent agent = new Agent(options, IExceptionLogger.SYSTEM_ERR, data);
agent.startup();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
@@ -58,18 +76,26 @@
}
return singleton;
}
+ // END android-change
+ // BEGIN android-change
/**
- * Returns a global instance which is already started. If a agent has not
- * been initialized before this method will fail.
+ * Returns a global instance which is already started. If an agent has not
+ * been initialized then one will be created via {@link Offline#createAgent()}.
+ * This will capture any data written via {@link Offline#getProbes} prior to
+ * this call, but not subsequently.
*
* @return global instance
* @throws IllegalStateException
* if no Agent has been started yet
*/
+ // END android-change
public static synchronized Agent getInstance() throws IllegalStateException {
if (singleton == null) {
- throw new IllegalStateException("JaCoCo agent not started.");
+ // BEGIN android-change
+ // throw new IllegalStateException("JaCoCo agent not started.");
+ singleton = Offline.createAgent();
+ // END android-change
}
return singleton;
}
@@ -93,10 +119,28 @@
* logger used by this agent
*/
Agent(final AgentOptions options, final IExceptionLogger logger) {
+ // BEGIN android-change
+ this(options, logger, new RuntimeData());
+ // END android-change
+ }
+
+ // BEGIN android-change
+ /**
+ * Creates a new agent with the given agent options, reusing the given runtime data.
+ *
+ * @param options
+ * agent options
+ * @param logger
+ * logger used by this agent
+ * @param data
+ * the runtime data to reuse
+ */
+ private Agent(final AgentOptions options, final IExceptionLogger logger, RuntimeData data) {
this.options = options;
this.logger = logger;
- this.data = new RuntimeData();
+ this.data = data;
}
+ // END android-change
/**
* Returns the runtime data object created by this agent
@@ -121,7 +165,9 @@
output = createAgentOutput();
output.startup(options, data);
if (options.getJmx()) {
- jmxRegistration = new JmxRegistration(this);
+// BEGIN android-change
+// jmxRegistration = new JmxRegistration(this);
+// END android-change
}
} catch (final Exception e) {
logger.logExeption(e);
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
index cadf606..69a9909 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
@@ -11,8 +11,12 @@
*******************************************************************************/
package org.jacoco.agent.rt.internal;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
+import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.runtime.AgentOptions;
import org.jacoco.core.runtime.RuntimeData;
@@ -22,14 +26,19 @@
*/
public final class Offline {
- private static final RuntimeData DATA;
+ // BEGIN android-change
+ // private static final RuntimeData DATA;
+ private static final Map<Long, ExecutionData> DATA = new HashMap<Long, ExecutionData>();
+ // END android-change
private static final String CONFIG_RESOURCE = "/jacoco-agent.properties";
- static {
- final Properties config = ConfigLoader.load(CONFIG_RESOURCE,
- System.getProperties());
- DATA = Agent.getInstance(new AgentOptions(config)).getData();
- }
+ // BEGIN android-change
+ // static {
+ // final Properties config = ConfigLoader.load(CONFIG_RESOURCE,
+ // System.getProperties());
+ // DATA = Agent.getInstance(new AgentOptions(config)).getData();
+ // }
+ // END android-change
private Offline() {
// no instances
@@ -48,8 +57,41 @@
*/
public static boolean[] getProbes(final long classid,
final String classname, final int probecount) {
- return DATA.getExecutionData(Long.valueOf(classid), classname,
- probecount).getProbes();
+ // BEGIN android-change
+ // return DATA.getExecutionData(Long.valueOf(classid), classname,
+ // probecount).getProbes();
+ synchronized (DATA) {
+ ExecutionData entry = DATA.get(classid);
+ if (entry == null) {
+ entry = new ExecutionData(classid, classname, probecount);
+ DATA.put(classid, entry);
+ } else {
+ entry.assertCompatibility(classid, classname, probecount);
+ }
+ return entry.getProbes();
+ }
+ // END android-change
}
+ // BEGIN android-change
+ /**
+ * Creates a default agent, using config loaded from the classpath resource and the system
+ * properties, and a runtime data instance populated with the execution data accumulated by
+ * the probes up until this call is made (subsequent probe updates will not be reflected in
+ * this agent).
+ *
+ * @return the new agent
+ */
+ static Agent createAgent() {
+ final Properties config = ConfigLoader.load(CONFIG_RESOURCE,
+ System.getProperties());
+ synchronized (DATA) {
+ ExecutionDataStore store = new ExecutionDataStore();
+ for (ExecutionData data : DATA.values()) {
+ store.put(data);
+ }
+ return Agent.getInstance(new AgentOptions(config), new RuntimeData(store));
+ }
+ }
+ // END android-change
}
diff --git a/org.jacoco.cli/src/MANIFEST.MF b/org.jacoco.cli/src/MANIFEST.MF
new file mode 100644
index 0000000..bae94d5
--- /dev/null
+++ b/org.jacoco.cli/src/MANIFEST.MF
@@ -0,0 +1,2 @@
+Main-Class: org.jacoco.cli.internal.Main
+
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
index 0fb7a2e..b811b52 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
@@ -47,7 +47,10 @@
assertFalse(options.getInclNoLocationClasses());
assertNull(options.getSessionId());
assertTrue(options.getDumpOnExit());
- assertEquals(AgentOptions.OutputMode.file, options.getOutput());
+ // BEGIN android-change
+ // assertEquals(AgentOptions.OutputMode.file, options.getOutput());
+ assertEquals(AgentOptions.OutputMode.none, options.getOutput());
+ // END android-change
assertEquals(AgentOptions.DEFAULT_ADDRESS, options.getAddress());
assertEquals(AgentOptions.DEFAULT_PORT, options.getPort());
assertNull(options.getClassDumpDir());
diff --git a/org.jacoco.core/src/org/jacoco/core/jacoco.properties b/org.jacoco.core/src/org/jacoco/core/jacoco.properties
index 0949337..e2f9aca 100644
--- a/org.jacoco.core/src/org/jacoco/core/jacoco.properties
+++ b/org.jacoco.core/src/org/jacoco/core/jacoco.properties
@@ -1,3 +1,6 @@
-VERSION=$qualified.bundle.version$
-HOMEURL=$jacoco.home.url$
-RUNTIMEPACKAGE=$jacoco.runtime.package.name$
\ No newline at end of file
+#This file is supposed to be processed by Maven, but Android doesn't run Maven
+#So in Android we've filled in the resulting values below
+VERSION=0.7.10.201704181138.android
+HOMEURL=http://www.jacoco.org/jacoco
+RUNTIMEPACKAGE=org.jacoco.agent.rt.internal
+
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
index 583371a..60f03c0 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
@@ -494,7 +494,10 @@
*/
public OutputMode getOutput() {
final String value = options.get(OUTPUT);
- return value == null ? OutputMode.file : OutputMode.valueOf(value);
+// BEGIN android-change
+// return value == null ? OutputMode.file : OutputMode.valueOf(value);
+ return value == null ? OutputMode.none : OutputMode.valueOf(value);
+// END android-change
}
/**
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
index 7f6fe31..afb5b7f 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
@@ -37,10 +37,24 @@
* Creates a new runtime.
*/
public RuntimeData() {
- store = new ExecutionDataStore();
+ // BEGIN android-change
+ this(new ExecutionDataStore());
+ // END android-change
+ }
+
+ // BEGIN android-change
+ /**
+ * Creates a new runtime, reusing an existing {@link ExecutionDataStore}.
+ *
+ * @param store
+ * the store to reuse
+ */
+ public RuntimeData(ExecutionDataStore store) {
+ this.store = store;
sessionId = "<none>";
startTimeStamp = System.currentTimeMillis();
}
+ // END android-change
/**
* Sets a session identifier for this runtime. The identifier is used when