diff options
Diffstat (limited to 'src')
20 files changed, 269 insertions, 289 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/LazyWriteExecPathsFileAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/LazyWriteExecPathsFileAction.java new file mode 100644 index 0000000000..fe8aaf95d1 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/LazyWriteExecPathsFileAction.java @@ -0,0 +1,73 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// 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. + +package com.google.devtools.build.lib.analysis.actions; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.lib.actions.ActionExecutionContext; +import com.google.devtools.build.lib.actions.ActionOwner; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.util.Fingerprint; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Lazily writes the exec path of the given files separated by newline into a specified output file. + */ +public final class LazyWriteExecPathsFileAction extends AbstractFileWriteAction { + private static final String GUID = "6be94d90-96f3-4bec-8104-1fb08abc2546"; + + private final ImmutableSet<Artifact> files; + + public LazyWriteExecPathsFileAction( + ActionOwner owner, Artifact output, ImmutableSet<Artifact> files) { + super(owner, Artifact.NO_ARTIFACTS, output, false); + this.files = files; + } + + @Override + public DeterministicWriter newDeterministicWriter(ActionExecutionContext ctx) { + return new DeterministicWriter() { + @Override + public void writeOutputFile(OutputStream out) throws IOException { + StringBuilder execPaths = new StringBuilder(); + for (Artifact file : files) { + if (file.isSourceArtifact()) { + execPaths.append(file.getExecPathString()); + execPaths.append("\n"); + } + } + out.write(execPaths.toString().getBytes(UTF_8)); + } + }; + } + + /** + * Computes the Action key for this action by computing the fingerprint for the file contents. + */ + @Override + protected String computeKey() { + Fingerprint f = new Fingerprint(); + f.addString(GUID); + f.addString(String.valueOf(makeExecutable)); + for (Artifact sourceFile : files) { + if (sourceFile.isSourceArtifact()) { + f.addPath(sourceFile.getExecPath()); + } + } + return f.hexDigestAndReset(); + } +}
\ No newline at end of file diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java index 3fd9bb9334..b596474aaf 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java @@ -246,6 +246,7 @@ public class BazelJavaSemantics implements JavaSemantics { List<String> jvmFlags, Artifact executable, String javaStartClass, + String coverageStartClass, String javaExecutable) { Preconditions.checkState(ruleContext.getConfiguration().hasFragment(Jvm.class)); @@ -296,22 +297,17 @@ public class BazelJavaSemantics implements JavaSemantics { } arguments.add(new ComputedClasspathSubstitution(classpath, workspacePrefix, isRunfilesEnabled)); - JavaCompilationArtifacts javaArtifacts = javaCommon.getJavaCompilationArtifacts(); - String path = - javaArtifacts.getInstrumentedJar() != null - ? "${JAVA_RUNFILES}/" - + workspacePrefix - + javaArtifacts.getInstrumentedJar().getRootRelativePath().getPathString() - : ""; - arguments.add( - Substitution.of( - "%set_jacoco_metadata%", - ruleContext.getConfiguration().isCodeCoverageEnabled() - ? "export JACOCO_METADATA_JAR=" + path - : "")); - - arguments.add(Substitution.of("%java_start_class%", - ShellEscaper.escapeString(javaStartClass))); + if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { + arguments.add(new JavaSemantics.ComputedJacocoSubstitution( + javaCommon.getRuntimeClasspath(), workspacePrefix)); + arguments.add(Substitution.of(JavaSemantics.JACOCO_MAIN_CLASS_PLACEHOLDER, + "export JACOCO_MAIN_CLASS=" + coverageStartClass)); + } else { + arguments.add(Substitution.of(JavaSemantics.JACOCO_METADATA_PLACEHOLDER, "")); + arguments.add(Substitution.of(JavaSemantics.JACOCO_MAIN_CLASS_PLACEHOLDER, "")); + } + + arguments.add(Substitution.of("%java_start_class%", ShellEscaper.escapeString(javaStartClass))); arguments.add(Substitution.ofSpaceSeparatedList("%jvm_flags%", ImmutableList.copyOf(jvmFlags))); ruleContext.registerAction(new TemplateExpansionAction( @@ -549,49 +545,11 @@ public class BazelJavaSemantics implements JavaSemantics { return jvmFlags.build(); } - /** - * Returns whether coverage has instrumented artifacts. - */ - public static boolean hasInstrumentationMetadata(JavaTargetAttributes.Builder attributes) { - return !attributes.getInstrumentationMetadata().isEmpty(); - } - - // TODO(yueg): refactor this (only mainClass different for now) @Override - public String addCoverageSupport( - JavaCompilationHelper helper, - JavaTargetAttributes.Builder attributes, - Artifact executable, - Artifact instrumentationMetadata, - JavaCompilationArtifacts.Builder javaArtifactsBuilder, - String mainClass) + public String addCoverageSupport(JavaCompilationHelper helper, Artifact executable) throws InterruptedException { // This method can be called only for *_binary/*_test targets. Preconditions.checkNotNull(executable); - // Add our own metadata artifact (if any). - if (instrumentationMetadata != null) { - attributes.addInstrumentationMetadataEntries(ImmutableList.of(instrumentationMetadata)); - } - - if (!hasInstrumentationMetadata(attributes)) { - return mainClass; - } - - Artifact instrumentedJar = - helper - .getRuleContext() - .getBinArtifact(helper.getRuleContext().getLabel().getName() + "_instrumented.jar"); - - // Create an instrumented Jar. This will be referenced on the runtime classpath prior - // to all other Jars. - JavaCommon.createInstrumentedJarAction( - helper.getRuleContext(), - this, - attributes.getInstrumentationMetadata(), - instrumentedJar, - mainClass); - javaArtifactsBuilder.setInstrumentedJar(instrumentedJar); - // Add the coverage runner to the list of dependencies when compiling in coverage mode. TransitiveInfoCollection runnerTarget = helper.getRuleContext().getPrerequisite("$jacocorunner", Mode.TARGET); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt index d5495c00b6..1aa259a4fb 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt @@ -245,6 +245,7 @@ export CLASSLOADER_PREFIX_PATH="${RUNPATH}" # We need to make the metadata jar with uninstrumented classes available for generating # the lcov-compatible coverage report, and we don't want it on the classpath. %set_jacoco_metadata% +%set_jacoco_main_class% if [[ -n "$JVM_DEBUG_PORT" ]]; then JVM_DEBUG_SUSPEND=${DEFAULT_JVM_DEBUG_SUSPEND:-"y"} diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index 8bd17860e6..8381d03591 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -837,7 +837,6 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { ApkProvider.create( zipAlignedApk, unsignedApk, - androidCommon.getInstrumentedJar(), applicationManifest.getManifest(), debugKeystore)) .addProvider(AndroidPreDexJarProvider.class, AndroidPreDexJarProvider.create(jarToDex)) diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java index 96d6acea15..154aabcb76 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java @@ -447,12 +447,11 @@ public class AndroidCommon { } else { Artifact outputDepsProto = javacHelper.createOutputDepsProtoArtifact(resourceClassJar, javaArtifactsBuilder); - javacHelper.createCompileActionWithInstrumentation( + javacHelper.createCompileAction( resourceClassJar, null /* manifestProtoOutput */, null /* genSourceJar */, - outputDepsProto, - javaArtifactsBuilder); + outputDepsProto); } } else { // Otherwise, it should have been the AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR. @@ -690,8 +689,7 @@ public class AndroidCommon { helper.createSourceJarAction(srcJar, genSourceJar); outputDepsProto = helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder); - helper.createCompileActionWithInstrumentation(classJar, manifestProtoOutput, genSourceJar, - outputDepsProto, javaArtifactsBuilder); + helper.createCompileAction(classJar, manifestProtoOutput, genSourceJar, outputDepsProto); if (isBinary) { generatedExtensionRegistryProvider = @@ -855,6 +853,10 @@ public class AndroidCommon { return javaCommon.getJavacOpts(); } + public Artifact getClassJar() { + return classJar; + } + public Artifact getGenClassJar() { return genClassJar; } @@ -880,10 +882,6 @@ public class AndroidCommon { return jarsProducedForRuntime; } - public Artifact getInstrumentedJar() { - return javaCommon.getJavaCompilationArtifacts().getInstrumentedJar(); - } - public NestedSet<Artifact> getTransitiveNeverLinkLibraries() { return transitiveNeverlinkLibraries; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java index fd66a26dfc..6ceafcc2a9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java @@ -125,8 +125,6 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor JavaCompilationHelper helper = getJavaCompilationHelperWithDependencies(ruleContext, javaSemantics, javaCommon, attributesBuilder); - Artifact instrumentationMetadata = - helper.createInstrumentationMetadata(classJar, javaArtifactsBuilder); Artifact executable = ruleContext.createOutputArtifact(); // the artifact for the rule itself NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder().add(classJar).add(executable); @@ -146,7 +144,7 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor javaSemantics, helper, executable, - instrumentationMetadata, + null, javaArtifactsBuilder, attributesBuilder); @@ -170,11 +168,7 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder); javaRuleOutputJarsProviderBuilder.setJdeps(outputDepsProtoArtifact); helper.createCompileAction( - classJar, - manifestProtoOutput, - genSourceJar, - outputDepsProtoArtifact, - instrumentationMetadata); + classJar, manifestProtoOutput, genSourceJar, outputDepsProtoArtifact); helper.createSourceJarAction(srcJar, genSourceJar); setUpJavaCommon(javaCommon, helper, javaArtifactsBuilder.build()); @@ -187,6 +181,7 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor getJvmFlags(ruleContext, testClass), executable, mainClass, + "com.google.testing.junit.runner.GoogleTestRunner", JavaCommon.getJavaBinSubstitution(ruleContext, launcher)); Artifact deployJar = @@ -414,13 +409,6 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor builder.addTargets(depsForRunfiles, RunfilesProvider.DEFAULT_RUNFILES); builder.addTransitiveArtifacts(transitiveAarArtifacts); - if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - Artifact instrumentedJar = javaCommon.getJavaCompilationArtifacts().getInstrumentedJar(); - if (instrumentedJar != null) { - builder.addArtifact(instrumentedJar); - } - } - builder.addArtifacts(javaCommon.getRuntimeClasspath()); // Add the JDK files if it comes from P4 (see java_stub_template.txt). diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java index d265fd3160..70676b701d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java @@ -17,7 +17,6 @@ import com.google.auto.value.AutoValue; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; -import javax.annotation.Nullable; /** A provider for targets that produce an apk file. */ @AutoValue @@ -27,10 +26,9 @@ public abstract class ApkProvider implements TransitiveInfoProvider { public static ApkProvider create( Artifact apk, Artifact unsignedApk, - @Nullable Artifact coverageMetdata, Artifact mergedManifest, Artifact keystore) { - return new AutoValue_ApkProvider(apk, unsignedApk, coverageMetdata, mergedManifest, keystore); + return new AutoValue_ApkProvider(apk, unsignedApk, mergedManifest, keystore); } /** Returns the APK file built in the transitive closure. */ @@ -39,10 +37,6 @@ public abstract class ApkProvider implements TransitiveInfoProvider { /** Returns the unsigned APK file built in the transitive closure. */ public abstract Artifact getUnsignedApk(); - /** Returns the coverage metadata artifacts generated in the transitive closure. */ - @Nullable - public abstract Artifact getCoverageMetadata(); - /** Returns the merged manifest. */ public abstract Artifact getMergedManifest(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java index 48a3afde5c..fb6830f302 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java @@ -78,7 +78,6 @@ public class JavaBinary implements RuleConfiguredTargetFactory { JavaTargetAttributes.Builder attributesBuilder = common.initCommon(); attributesBuilder.addClassPathResources( ruleContext.getPrerequisiteArtifacts("classpath_resources", Mode.TARGET).list()); - // Add Java8 timezone resource data addTimezoneResourceForJavaBinaries(ruleContext, attributesBuilder); @@ -147,8 +146,6 @@ public class JavaBinary implements RuleConfiguredTargetFactory { } JavaCompilationArtifacts.Builder javaArtifactsBuilder = new JavaCompilationArtifacts.Builder(); - Artifact instrumentationMetadata = - helper.createInstrumentationMetadata(classJar, javaArtifactsBuilder); NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder(); Artifact executableForRunfiles = null; @@ -158,14 +155,7 @@ public class JavaBinary implements RuleConfiguredTargetFactory { filesBuilder.add(classJar).add(executableForRunfiles); if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - mainClass = - semantics.addCoverageSupport( - helper, - attributesBuilder, - executableForRunfiles, - instrumentationMetadata, - javaArtifactsBuilder, - mainClass); + mainClass = semantics.addCoverageSupport(helper, executableForRunfiles); } } else { filesBuilder.add(classJar); @@ -216,8 +206,7 @@ public class JavaBinary implements RuleConfiguredTargetFactory { helper.createGenJarAction(classJar, manifestProtoOutput, genClassJar); } - helper.createCompileAction( - classJar, manifestProtoOutput, genSourceJar, outputDepsProto, instrumentationMetadata); + helper.createCompileAction(classJar, manifestProtoOutput, genSourceJar, outputDepsProto); helper.createSourceJarAction(srcJar, genSourceJar); common.setClassPathFragment( @@ -246,6 +235,7 @@ public class JavaBinary implements RuleConfiguredTargetFactory { jvmFlags, executableForRunfiles, mainClass, + originalMainClass, JavaCommon.getJavaBinSubstitution(ruleContext, launcher)); if (!executableToRun.equals(executableForRunfiles)) { filesBuilder.add(executableToRun); @@ -491,13 +481,6 @@ public class JavaBinary implements RuleConfiguredTargetFactory { builder.addTargets(runtimeDeps, RunfilesProvider.DEFAULT_RUNFILES); semantics.addDependenciesForRunfiles(ruleContext, builder); - if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - Artifact instrumentedJar = javaArtifacts.getInstrumentedJar(); - if (instrumentedJar != null) { - builder.addArtifact(instrumentedJar); - } - } - builder.addArtifacts((Iterable<Artifact>) common.getRuntimeClasspath()); // Add the JDK files if it comes from the source repository (see java_stub_template.txt). diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java index 8448232fdc..30102d4b7b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java @@ -172,28 +172,6 @@ public class JavaCommon { } } - /** - * Creates an action to aggregate all metadata artifacts into a single - * <target_name>_instrumented.jar file. - */ - public static void createInstrumentedJarAction( - RuleContext ruleContext, - JavaSemantics semantics, - List<Artifact> metadataArtifacts, - Artifact instrumentedJar, - String mainClass) - throws InterruptedException { - // In Jacoco's setup, metadata artifacts are real jars. - new DeployArchiveBuilder(semantics, ruleContext) - .setOutputJar(instrumentedJar) - // We need to save the original mainClass because we're going to run inside CoverageRunner - .setJavaStartClass(mainClass) - .setAttributes(new JavaTargetAttributes.Builder(semantics).build()) - .addRuntimeJars(ImmutableList.copyOf(metadataArtifacts)) - .setCompression(DeployArchiveBuilder.Compression.UNCOMPRESSED) - .build(); - } - public static ImmutableList<String> getConstraints(RuleContext ruleContext) { return ruleContext.getRule().isAttrDefined("constraints", Type.STRING_LIST) ? ImmutableList.copyOf(ruleContext.attributes().get("constraints", Type.STRING_LIST)) @@ -739,7 +717,6 @@ public class JavaCommon { .addTransitiveTargets(runtimeDepInfo, true, ClasspathType.RUNTIME_ONLY) .build(); attributes.addRuntimeClassPathEntries(args.getRuntimeJars()); - attributes.addInstrumentationMetadataEntries(args.getInstrumentationMetadata()); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java index 5b45b576fa..23aab664a0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java @@ -22,7 +22,6 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.util.FileType; -import java.util.Collection; /** A container of Java compilation artifacts. */ @AutoValue @@ -42,14 +41,11 @@ public abstract class JavaCompilationArgs { public static final JavaCompilationArgs EMPTY_ARGS = JavaCompilationArgs.create( NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER), - NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER), NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER)); private static JavaCompilationArgs create( - NestedSet<Artifact> runtimeJars, - NestedSet<Artifact> compileTimeJars, - NestedSet<Artifact> instrumentationMetadata) { - return new AutoValue_JavaCompilationArgs(runtimeJars, compileTimeJars, instrumentationMetadata); + NestedSet<Artifact> runtimeJars, NestedSet<Artifact> compileTimeJars) { + return new AutoValue_JavaCompilationArgs(runtimeJars, compileTimeJars); } /** Returns transitive runtime jars. */ @@ -58,9 +54,6 @@ public abstract class JavaCompilationArgs { /** Returns transitive compile-time jars. */ public abstract NestedSet<Artifact> getCompileTimeJars(); - /** Returns transitive instrumentation metadata jars. */ - public abstract NestedSet<Artifact> getInstrumentationMetadata(); - /** * Returns a new builder instance. */ @@ -76,8 +69,6 @@ public abstract class JavaCompilationArgs { NestedSetBuilder.naiveLinkOrder(); private final NestedSetBuilder<Artifact> compileTimeJarsBuilder = NestedSetBuilder.naiveLinkOrder(); - private final NestedSetBuilder<Artifact> instrumentationMetadataBuilder = - NestedSetBuilder.naiveLinkOrder(); /** * Use {@code TransitiveJavaCompilationArgs#builder()} to instantiate the builder. @@ -95,7 +86,6 @@ public abstract class JavaCompilationArgs { addRuntimeJars(other.getRuntimeJars()); } addCompileTimeJars(other.getCompileTimeJars()); - addInstrumentationMetadata(other.getInstrumentationMetadata()); return this; } @@ -137,16 +127,6 @@ public abstract class JavaCompilationArgs { return this; } - public Builder addInstrumentationMetadata(Artifact instrumentationMetadata) { - this.instrumentationMetadataBuilder.add(instrumentationMetadata); - return this; - } - - public Builder addInstrumentationMetadata(Collection<Artifact> instrumentationMetadata) { - this.instrumentationMetadataBuilder.addAll(instrumentationMetadata); - return this; - } - public Builder addTransitiveCompilationArgs( JavaCompilationArgsProvider dep, boolean recursive, ClasspathType type) { JavaCompilationArgs args = recursive @@ -239,8 +219,6 @@ public abstract class JavaCompilationArgs { if (!ClasspathType.COMPILE_ONLY.equals(type)) { runtimeJarsBuilder.addTransitive(args.getRuntimeJars()); } - instrumentationMetadataBuilder.addTransitive( - args.getInstrumentationMetadata()); return this; } @@ -248,10 +226,7 @@ public abstract class JavaCompilationArgs { * Builds a {@link JavaCompilationArgs} object. */ public JavaCompilationArgs build() { - return JavaCompilationArgs.create( - runtimeJarsBuilder.build(), - compileTimeJarsBuilder.build(), - instrumentationMetadataBuilder.build()); + return JavaCompilationArgs.create(runtimeJarsBuilder.build(), compileTimeJarsBuilder.build()); } } @@ -271,3 +246,4 @@ public abstract class JavaCompilationArgs { JavaCompilationArgs() {} } + diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArtifacts.java index e18ded353a..bd34392f35 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArtifacts.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArtifacts.java @@ -19,10 +19,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; - import java.util.LinkedHashSet; import java.util.Set; - import javax.annotation.Nullable; /** @@ -47,9 +45,7 @@ public abstract class JavaCompilationArtifacts { public abstract ImmutableList<Artifact> getRuntimeJars(); public abstract ImmutableList<Artifact> getCompileTimeJars(); - public abstract ImmutableList<Artifact> getInstrumentationMetadata(); @Nullable public abstract Artifact getCompileTimeDependencyArtifact(); - @Nullable public abstract Artifact getInstrumentedJar(); /** Returns a builder for a {@link JavaCompilationArtifacts}. */ public static Builder builder() { @@ -62,17 +58,13 @@ public abstract class JavaCompilationArtifacts { public static final class Builder { private final Set<Artifact> runtimeJars = new LinkedHashSet<>(); private final Set<Artifact> compileTimeJars = new LinkedHashSet<>(); - private final Set<Artifact> instrumentationMetadata = new LinkedHashSet<>(); private Artifact compileTimeDependencies; - private Artifact instrumentedJar; public JavaCompilationArtifacts build() { return new AutoValue_JavaCompilationArtifacts( ImmutableList.copyOf(runtimeJars), ImmutableList.copyOf(compileTimeJars), - ImmutableList.copyOf(instrumentationMetadata), - compileTimeDependencies, - instrumentedJar); + compileTimeDependencies); } public Builder addRuntimeJar(Artifact jar) { @@ -95,19 +87,9 @@ public abstract class JavaCompilationArtifacts { return this; } - public Builder addInstrumentationMetadata(Artifact instrumentationMetadata) { - this.instrumentationMetadata.add(instrumentationMetadata); - return this; - } - public Builder setCompileTimeDependencies(@Nullable Artifact compileTimeDependencies) { this.compileTimeDependencies = compileTimeDependencies; return this; } - - public Builder setInstrumentedJar(@Nullable Artifact instrumentedJar) { - this.instrumentedJar = instrumentedJar; - return this; - } } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java index b74b517feb..56eac18a53 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java @@ -168,18 +168,16 @@ public final class JavaCompilationHelper { * * @param outputJar the class jar Artifact to create with the Action * @param manifestProtoOutput the output artifact for the manifest proto emitted from JavaBuilder - * @param gensrcOutputJar the generated sources jar Artifact to create with the Action - * (null if no sources will be generated). - * @param outputDepsProto the compiler-generated jdeps file to create with the Action - * (null if not requested) - * @param outputMetadata metadata file (null if no instrumentation is needed). + * @param gensrcOutputJar the generated sources jar Artifact to create with the Action (null if no + * sources will be generated). + * @param outputDepsProto the compiler-generated jdeps file to create with the Action (null if not + * requested) */ public void createCompileAction( Artifact outputJar, Artifact manifestProtoOutput, @Nullable Artifact gensrcOutputJar, - @Nullable Artifact outputDepsProto, - @Nullable Artifact outputMetadata) { + @Nullable Artifact outputDepsProto) { JavaTargetAttributes attributes = getAttributes(); @@ -212,7 +210,7 @@ public final class JavaCompilationHelper { builder.setGensrcOutputJar(gensrcOutputJar); builder.setOutputDepsProto(outputDepsProto); builder.setAdditionalOutputs(attributes.getAdditionalOutputs()); - builder.setMetadata(outputMetadata); + builder.setFileWithPathsForCoverage(maybeCreateFileWithPathsForCoverage(outputJar)); builder.setInstrumentationJars(jacocoInstrumentation); builder.setSourceFiles(attributes.getSourceFiles()); builder.addSourceJars(attributes.getSourceJars()); @@ -257,65 +255,15 @@ public final class JavaCompilationHelper { } } - /** - * Returns the instrumentation metadata files to be generated for a given output jar. - * - * <p>Only called if the output jar actually needs to be instrumented. - */ - @Nullable - private static Artifact createInstrumentationMetadataArtifact( - RuleContext ruleContext, Artifact outputJar) { - PathFragment packageRelativePath = outputJar.getRootRelativePath().relativeTo( - ruleContext.getPackageDirectory()); - return ruleContext.getPackageRelativeArtifact( - FileSystemUtils.replaceExtension(packageRelativePath, ".em"), outputJar.getRoot()); - } - - /** - * Creates the Action that compiles Java source files and optionally instruments them for - * coverage. - * - * @param outputJar the class jar Artifact to create with the Action - * @param manifestProtoOutput the output artifact for the manifest proto emitted from JavaBuilder - * @param gensrcJar the generated sources jar Artifact to create with the Action - * @param outputDepsProto the compiler-generated jdeps file to create with the Action - * @param javaArtifactsBuilder the build to store the instrumentation metadata in - */ - public void createCompileActionWithInstrumentation( - Artifact outputJar, - Artifact manifestProtoOutput, - @Nullable Artifact gensrcJar, - @Nullable Artifact outputDepsProto, - JavaCompilationArtifacts.Builder javaArtifactsBuilder) { - createCompileAction( - outputJar, - manifestProtoOutput, - gensrcJar, - outputDepsProto, - createInstrumentationMetadata(outputJar, javaArtifactsBuilder)); - } - - /** - * Creates the instrumentation metadata artifact if needed. - * - * @return the instrumentation metadata artifact or null if instrumentation is - * disabled - */ - @Nullable - public Artifact createInstrumentationMetadata(Artifact outputJar, - JavaCompilationArtifacts.Builder javaArtifactsBuilder) { - // If we need to instrument the jar, add additional output (the coverage metadata file) to the - // JavaCompileAction. - Artifact instrumentationMetadata = null; - if (shouldInstrumentJar()) { - instrumentationMetadata = createInstrumentationMetadataArtifact( - getRuleContext(), outputJar); - - if (instrumentationMetadata != null) { - javaArtifactsBuilder.addInstrumentationMetadata(instrumentationMetadata); - } + private Artifact maybeCreateFileWithPathsForCoverage(Artifact outputJar) { + if (!shouldInstrumentJar()) { + return null; } - return instrumentationMetadata; + PathFragment packageRelativePath = + outputJar.getRootRelativePath().relativeTo(ruleContext.getPackageDirectory()); + PathFragment path = + FileSystemUtils.replaceExtension(packageRelativePath, "-paths-for-coverage.txt"); + return ruleContext.getPackageRelativeArtifact(path, outputJar.getRoot()); } private boolean shouldInstrumentJar() { diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java index a867b0cff7..f1dbe1013b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java @@ -44,6 +44,7 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.actions.CommandLine; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.CustomMultiArgv; +import com.google.devtools.build.lib.analysis.actions.LazyWriteExecPathsFileAction; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; @@ -482,7 +483,7 @@ public final class JavaCompileAction extends SpawnAction { private Artifact outputDepsProto; private Collection<Artifact> additionalOutputs; private Artifact paramFile; - private Artifact metadata; + private Artifact fileWithPathsForCoverage; private ImmutableSet<Artifact> sourceFiles = ImmutableSet.of(); private final Collection<Artifact> sourceJars = new ArrayList<>(); private BuildConfiguration.StrictDepsMode strictJavaDeps = @@ -576,7 +577,6 @@ public final class JavaCompileAction extends SpawnAction { .addAll( new ArrayList<>(Collections2.filter(Arrays.asList( outputJar, - metadata, gensrcOutputJar, manifestProtoOutput, outputDepsProto), Predicates.notNull()))); @@ -599,6 +599,11 @@ public final class JavaCompileAction extends SpawnAction { semantics.getJavaBuilderMainClass(), pathSeparator); + if (fileWithPathsForCoverage != null) { + analysisEnvironment.registerAction( + new LazyWriteExecPathsFileAction(owner, fileWithPathsForCoverage, sourceFiles)); + } + // The actual params-file-based command line executed for a compile action. CommandLine javaBuilderCommandLine = CustomCommandLine.builder() .add(spawnCommandLineBase) @@ -613,7 +618,7 @@ public final class JavaCompileAction extends SpawnAction { .addAll(instrumentationJars) .build(); - NestedSet<Artifact> inputs = + NestedSetBuilder<Artifact> inputsBuilder = NestedSetBuilder.<Artifact>stableOrder() .addTransitive(classpathEntries) .addTransitive(compileTimeDependencyArtifacts) @@ -625,8 +630,12 @@ public final class JavaCompileAction extends SpawnAction { .addAll(sourcePathEntries) .addAll(extdirInputs) .add(paramFile) - .addTransitive(tools) - .build(); + .addTransitive(tools); + if (fileWithPathsForCoverage != null) { + inputsBuilder.add(fileWithPathsForCoverage); + } + + NestedSet<Artifact> inputs = inputsBuilder.build(); return new JavaCompileAction( owner, @@ -745,9 +754,9 @@ public final class JavaCompileAction extends SpawnAction { } } } - if (metadata != null) { + if (fileWithPathsForCoverage != null) { result.add("--post_processor"); - result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, metadata); + result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, fileWithPathsForCoverage); result.addPath( configuration .getCoverageMetadataDirectory(targetLabel.getPackageIdentifier().getRepository()) @@ -857,8 +866,8 @@ public final class JavaCompileAction extends SpawnAction { return this; } - public Builder setMetadata(Artifact metadata) { - this.metadata = metadata; + public Builder setFileWithPathsForCoverage(Artifact fileWithExecPathsForCoverage) { + this.fileWithPathsForCoverage = fileWithExecPathsForCoverage; return this; } @@ -1004,3 +1013,5 @@ public final class JavaCompileAction extends SpawnAction { } } } + + diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java index b1e5ab2530..f65b2e8e5a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java @@ -126,8 +126,7 @@ public class JavaLibrary implements RuleConfiguredTargetFactory { Artifact outputDepsProto = helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder); - helper.createCompileActionWithInstrumentation(classJar, manifestProtoOutput, genSourceJar, - outputDepsProto, javaArtifactsBuilder); + helper.createCompileAction(classJar, manifestProtoOutput, genSourceJar, outputDepsProto); helper.createSourceJarAction(srcJar, genSourceJar); Artifact iJar = null; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java index 1be54d5358..8b43e9491c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java @@ -188,11 +188,7 @@ public final class JavaLibraryHelper { jacocoInstrumental); Artifact outputDepsProto = helper.createOutputDepsProtoArtifact(output, artifactsBuilder); helper.createCompileAction( - output, - null /* manifestProtoOutput */, - null /* gensrcOutputJar */, - outputDepsProto, - null /* outputMetadata */); + output, null /* manifestProtoOutput */, null /* gensrcOutputJar */, outputDepsProto); helper.createCompileTimeJarAction(output, artifactsBuilder); artifactsBuilder.addRuntimeJar(output); @@ -244,7 +240,6 @@ public final class JavaLibraryHelper { .build(); attributes.addCompileTimeClassPathEntries(args.getCompileTimeJars()); attributes.addRuntimeClassPathEntries(args.getRuntimeJars()); - attributes.addInstrumentationMetadataEntries(args.getInstrumentationMetadata()); } private NestedSet<Artifact> getNonRecursiveCompileTimeJarsFromDeps() { diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java index e6f3b9b37e..df08f401a2 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java @@ -21,6 +21,7 @@ import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fro import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Streams; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.LanguageDependentFragment.LibraryLanguage; import com.google.devtools.build.lib.analysis.OutputGroupProvider; @@ -31,8 +32,10 @@ import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.Runfiles.Builder; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; +import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.ComputedSubstitution; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; import com.google.devtools.build.lib.packages.Attribute.LateBoundLabelList; @@ -46,8 +49,10 @@ import com.google.devtools.build.lib.rules.java.proto.GeneratedExtensionRegistry import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.vfs.PathFragment; +import java.io.File; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import javax.annotation.Nullable; /** @@ -240,7 +245,33 @@ public interface JavaSemantics { } }; - String IJAR_LABEL = "//tools/defaults:ijar"; + String JACOCO_METADATA_PLACEHOLDER = "%set_jacoco_metadata%"; + String JACOCO_MAIN_CLASS_PLACEHOLDER = "%set_jacoco_main_class%"; + + /** + * Substitution for exporting the jars needed for jacoco coverage. + */ + class ComputedJacocoSubstitution extends ComputedSubstitution { + private final NestedSet<Artifact> jars; + private final String pathPrefix; + + public ComputedJacocoSubstitution(NestedSet<Artifact> jars, String workspacePrefix) { + super(JACOCO_METADATA_PLACEHOLDER); + this.jars = jars; + this.pathPrefix = "${JAVA_RUNFILES}/" + workspacePrefix; + } + + /** + * Concatenating the root relative paths of the artifacts. Each relative path entry is prepended + * with "${JAVA_RUNFILES}" and the workspace prefix. + */ + @Override + public String getValue() { + return Streams.stream(jars) + .map(artifact -> pathPrefix + "/" + artifact.getRootRelativePathString()) + .collect(Collectors.joining(File.pathSeparator, "export JACOCO_METADATA_JARS=", "")); + } + } /** * Verifies if the rule contains any errors. @@ -307,6 +338,7 @@ public interface JavaSemantics { List<String> jvmFlags, Artifact executable, String javaStartClass, + String coverageStartClass, String javaExecutable); /** @@ -346,13 +378,7 @@ public interface JavaSemantics { * * @return new main class */ - String addCoverageSupport( - JavaCompilationHelper helper, - JavaTargetAttributes.Builder attributes, - Artifact executable, - Artifact instrumentationMetadata, - JavaCompilationArtifacts.Builder javaArtifactsBuilder, - String mainClass) + String addCoverageSupport(JavaCompilationHelper helper, Artifact executable) throws InterruptedException; /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java index 0f2ec192cd..5c9d2ca666 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java @@ -82,7 +82,6 @@ public class JavaTargetAttributes { private final Map<PathFragment, Artifact> resources = new LinkedHashMap<>(); private final NestedSetBuilder<Artifact> resourceJars = NestedSetBuilder.stableOrder(); private final List<Artifact> messages = new ArrayList<>(); - private final List<Artifact> instrumentationMetadata = new ArrayList<>(); private final List<Artifact> sourceJars = new ArrayList<>(); private final List<Artifact> classPathResources = new ArrayList<>(); @@ -142,7 +141,6 @@ public class JavaTargetAttributes { Preconditions.checkArgument(!built); addCompileTimeClassPathEntries(context.getCompileTimeJars()); addRuntimeClassPathEntries(context.getRuntimeJars()); - addInstrumentationMetadataEntries(context.getInstrumentationMetadata()); return this; } @@ -256,12 +254,6 @@ public class JavaTargetAttributes { return this; } - public Builder addInstrumentationMetadataEntries(Iterable<Artifact> metadataEntries) { - Preconditions.checkArgument(!built); - Iterables.addAll(instrumentationMetadata, metadataEntries); - return this; - } - public Builder addNativeLibrary(Artifact nativeLibrary) { Preconditions.checkArgument(!built); String name = nativeLibrary.getFilename(); @@ -408,12 +400,6 @@ public class JavaTargetAttributes { return !sourceFiles.isEmpty(); } - /** @deprecated prefer {@link JavaTargetAttributes#getInstrumentationMetadata} */ - @Deprecated - public List<Artifact> getInstrumentationMetadata() { - return instrumentationMetadata; - } - /** @deprecated prefer {@link JavaTargetAttributes#hasSourceJars} */ @Deprecated public boolean hasSourceJars() { diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java index d8387a182b..ce01943d9d 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java @@ -841,10 +841,6 @@ public class JavaSkylarkApiTest extends BuildViewTestCase { args.getCompileTimeJars(), otherArgs.getCompileTimeJars())) { return false; } - if (!nestedSetsOfArtifactHaveTheSameParent( - args.getInstrumentationMetadata(), otherArgs.getInstrumentationMetadata())) { - return false; - } if (!nestedSetsOfArtifactHaveTheSameParent(args.getRuntimeJars(), otherArgs.getRuntimeJars())) { return false; } diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java index be78678e13..ce347d5d0a 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java @@ -297,7 +297,6 @@ public class SkylarkJavaLiteProtoLibraryTest extends BuildViewTestCase { " srcs = ['input1.proto', 'input2.proto'])"); JavaCompilationArgs compilationArgs = getProvider(JavaCompilationArgsProvider.class, rule).getJavaCompilationArgs(); - assertThat(compilationArgs.getInstrumentationMetadata()).isEmpty(); JavaSourceJarsProvider sourceJarsProvider = getProvider(JavaSourceJarsProvider.class, rule); assertThat(sourceJarsProvider).isNotNull(); diff --git a/src/test/shell/bazel/bazel_coverage_test.sh b/src/test/shell/bazel/bazel_coverage_test.sh index c651f50580..41c996c625 100755 --- a/src/test/shell/bazel/bazel_coverage_test.sh +++ b/src/test/shell/bazel/bazel_coverage_test.sh @@ -144,7 +144,98 @@ EOF [ -e $coverage_file_path ] || fail "Coverage output file does not exist!" cat <<EOF > result.dat -SF:com/example/Collatz.java +SF:src/main/com/example/Collatz.java +FN:3,com/example/Collatz::<init> ()V +FNDA:0,com/example/Collatz::<init> ()V +FN:6,com/example/Collatz::getCollatzFinal (I)I +FNDA:1,com/example/Collatz::getCollatzFinal (I)I +BA:6,2 +BA:6,2 +BA:9,2 +BA:9,2 +DA:3,0 +DA:6,3 +DA:7,2 +DA:9,4 +DA:10,5 +DA:12,7 +end_of_record +EOF + if ! cmp result.dat $coverage_file_path; then + fail "Coverage output file is different than the expected file" + fi +} + +function test_java_test_java_import_coverage() { + + cat <<EOF > BUILD +java_test( + name = "test", + srcs = glob(["src/test/**/*.java"]), + test_class = "com.example.TestCollatz", + deps = [":collatz-import"], +) + +java_import( + name = "collatz-import", + jars = [":libcollatz-lib.jar"], +) + +java_library( + name = "collatz-lib", + srcs = glob(["src/main/**/*.java"]), +) +EOF + + mkdir -p src/main/com/example + cat <<EOF > src/main/com/example/Collatz.java +package com.example; + +public class Collatz { + + public static int getCollatzFinal(int n) { + if (n == 1) { + return 1; + } + if (n % 2 == 0) { + return getCollatzFinal(n / 2); + } else { + return getCollatzFinal(n * 3 + 1); + } + } + +} +EOF + + mkdir -p src/test/com/example + cat <<EOF > src/test/com/example/TestCollatz.java +package com.example; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class TestCollatz { + + @Test + public void testGetCollatzFinal() { + assertEquals(Collatz.getCollatzFinal(1), 1); + assertEquals(Collatz.getCollatzFinal(5), 1); + assertEquals(Collatz.getCollatzFinal(10), 1); + assertEquals(Collatz.getCollatzFinal(21), 1); + } + +} +EOF + + bazel coverage //:test &>$TEST_log || fail "Coverage for //:test failed" + cat $TEST_log + ending_part=$(sed -n -e '/PASSED/,$p' $TEST_log) + + coverage_file_path=$(grep -Eo "/[/a-zA-Z0-9\.\_\-]+\.dat$" <<< "$ending_part") + [ -e $coverage_file_path ] || fail "Coverage output file not exists!" + + cat <<EOF > result.dat +SF:src/main/com/example/Collatz.java FN:3,com/example/Collatz::<init> ()V FNDA:0,com/example/Collatz::<init> ()V FN:6,com/example/Collatz::getCollatzFinal (I)I @@ -163,7 +254,7 @@ end_of_record EOF if ! cmp result.dat $coverage_file_path; then - fail "Coverage output file is different with expected" + fail "Coverage output file is different than the expected file" fi } |