diff --git a/aswb/src/com/google/idea/blaze/android/run/deployinfo/BlazeApkDeployInfoProtoHelper.java b/aswb/src/com/google/idea/blaze/android/run/deployinfo/BlazeApkDeployInfoProtoHelper.java index da8e08529dc..6d4c243422c 100644 --- a/aswb/src/com/google/idea/blaze/android/run/deployinfo/BlazeApkDeployInfoProtoHelper.java +++ b/aswb/src/com/google/idea/blaze/android/run/deployinfo/BlazeApkDeployInfoProtoHelper.java @@ -49,8 +49,8 @@ public AndroidDeployInfo readDeployInfoProtoForTarget( throws GetDeployInfoException { ImmutableList outputArtifacts; ParsedBepOutput bepOutput; - try { - bepOutput = buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING); + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + bepOutput = buildResultHelper.getBuildOutput(bepStream, Interners.STRING); outputArtifacts = bepOutput.getDirectArtifactsForTarget(target, pathFilter).asList(); } catch (GetArtifactsException e) { throw new GetDeployInfoException(e.getMessage()); diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestLaunchTask.java b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestLaunchTask.java index dc7dd974c06..af47aa4c869 100644 --- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestLaunchTask.java +++ b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestLaunchTask.java @@ -211,8 +211,10 @@ public void run(@NotNull BlazeLaunchContext launchContext) if (retVal != 0) { context.setHasError(); } else { - testResultsHolder.setTestResults( - buildResultHelper.getTestResults(Optional.empty())); + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + testResultsHolder.setTestResults( + buildResultHelper.getTestResults(bepStream)); + } } ListenableFuture unusedFuture = FileCaches.refresh( diff --git a/base/src/com/google/idea/blaze/base/buildview/BazelExecService.kt b/base/src/com/google/idea/blaze/base/buildview/BazelExecService.kt index 221378b3184..fe552f0466b 100644 --- a/base/src/com/google/idea/blaze/base/buildview/BazelExecService.kt +++ b/base/src/com/google/idea/blaze/base/buildview/BazelExecService.kt @@ -175,7 +175,7 @@ class BazelExecService(private val project: Project) : Disposable { LOG.assertTrue(cmdBuilder.name == BlazeCommandName.BUILD) return executionScope(ctx) { provider -> - cmdBuilder.addBlazeFlags(provider.getBuildFlags()) + cmdBuilder.addBlazeFlags(provider.buildFlags) val parseJob = parseEvents(ctx, provider) @@ -185,11 +185,13 @@ class BazelExecService(private val project: Project) : Disposable { parseJob.cancelAndJoin() if (result.status == BuildResult.Status.FATAL_ERROR) { - BlazeBuildOutputs.noOutputs(result) - } else { + return@executionScope BlazeBuildOutputs.noOutputs(result) + } + + provider.getBepStream(Optional.empty()).use { bepStream -> BlazeBuildOutputs.fromParsedBepOutput( result, - provider.getBuildOutput(Optional.empty(), Interners.STRING), + provider.getBuildOutput(bepStream, Interners.STRING), ) } } diff --git a/base/src/com/google/idea/blaze/base/command/CommandLineBlazeCommandRunner.java b/base/src/com/google/idea/blaze/base/command/CommandLineBlazeCommandRunner.java index d9eabc3538a..d9bd6663875 100644 --- a/base/src/com/google/idea/blaze/base/command/CommandLineBlazeCommandRunner.java +++ b/base/src/com/google/idea/blaze/base/command/CommandLineBlazeCommandRunner.java @@ -94,7 +94,10 @@ public BlazeBuildOutputs run( Optional.ofNullable(context.getScope(SharedStringPoolScope.class)) .map(SharedStringPoolScope::getStringInterner) .orElse(null); - ParsedBepOutput buildOutput = buildResultHelper.getBuildOutput(Optional.empty(), stringInterner); + ParsedBepOutput buildOutput; + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + buildOutput = buildResultHelper.getBuildOutput(bepStream, stringInterner); + } context.output(PrintOutput.log("BEP outputs retrieved (%s).", StringUtilRt.formatFileSize(buildOutput.getBepBytesConsumed()))); return BlazeBuildOutputs.fromParsedBepOutput(buildResult, buildOutput); } catch (GetArtifactsException e) { @@ -128,8 +131,8 @@ public BlazeTestResults runTest( return BlazeTestResults.NO_RESULTS; } context.output(PrintOutput.log("Build command finished. Retrieving BEP outputs...")); - try { - return buildResultHelper.getTestResults(Optional.empty()); + try(final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + return buildResultHelper.getTestResults(bepStream); } catch (GetArtifactsException e) { context.output(PrintOutput.log("Failed to get build outputs: " + e.getMessage())); context.setHasError(); diff --git a/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReader.java b/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReader.java index e6c516e4c7e..8c7c70901a7 100644 --- a/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReader.java +++ b/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReader.java @@ -43,11 +43,6 @@ public final class BuildEventProtocolOutputReader { private BuildEventProtocolOutputReader() {} - /** Returns all test results from a BEP-formatted {@link InputStream}. */ - public static BlazeTestResults parseTestResults(InputStream inputStream) - throws BuildEventStreamException { - return parseTestResults(BuildEventStreamProvider.fromInputStream(inputStream)); - } /** * Returns all test results from {@link BuildEventStreamProvider}. * diff --git a/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventStreamProvider.java b/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventStreamProvider.java index 8cc55a8633c..c58ff226d9c 100644 --- a/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventStreamProvider.java +++ b/base/src/com/google/idea/blaze/base/command/buildresult/BuildEventStreamProvider.java @@ -21,10 +21,11 @@ import com.google.idea.blaze.exception.BuildException; import java.io.IOException; import java.io.InputStream; +import java.util.Optional; import javax.annotation.Nullable; /** Provides {@link BuildEventStreamProtos.BuildEvent} */ -public interface BuildEventStreamProvider { +public interface BuildEventStreamProvider extends AutoCloseable { /** An exception parsing a stream of build events. */ class BuildEventStreamException extends BuildException { @@ -47,9 +48,29 @@ static BuildEventStreamProtos.BuildEvent parseNextEventFromStream(InputStream st } } + /** + * Creates a {@link BuildEventStreamProvider} from the given {@code stream}. + * + *

Note: takes ownership of the {@code stream} and closes it when is being closed. + */ static BuildEventStreamProvider fromInputStream(InputStream stream) { CountingInputStream countingStream = new CountingInputStream(stream); return new BuildEventStreamProvider() { + @Override + public void close() { + try { + stream.close(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public Object getId() { + return Optional.empty(); + } + @Nullable @Override public BuildEvent getNext() throws BuildEventStreamException { @@ -63,9 +84,17 @@ public long getBytesConsumed() { }; } + /** + * @return an object that represents the identity of the build to the user. + */ + Object getId(); + /** Returns the next build event in the stream, or null if there are none remaining. */ @Nullable BuildEventStreamProtos.BuildEvent getNext() throws BuildEventStreamException; long getBytesConsumed(); + + @Override + void close(); } diff --git a/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelper.java b/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelper.java index c5b1248478d..05766dec7bf 100644 --- a/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelper.java +++ b/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelper.java @@ -16,6 +16,7 @@ package com.google.idea.blaze.base.command.buildresult; import com.google.common.collect.Interner; +import com.google.errorprone.annotations.MustBeClosed; import com.google.idea.blaze.base.run.testlogs.BlazeTestResults; import com.google.idea.blaze.base.scope.BlazeContext; import com.google.idea.blaze.exception.BuildException; @@ -34,31 +35,38 @@ public interface BuildResultHelper extends AutoCloseable { */ List getBuildFlags(); + + /** + * Gets the BEP stream for the build. May only be called once. May only be called after the build is complete. + */ + @MustBeClosed + BuildEventStreamProvider getBepStream(Optional completionBuildId) throws GetArtifactsException; + /** - * Parses the BEP output data and returns the corresponding {@link ParsedBepOutput}. May only be - * called once, after the build is complete. + * Parses the BEP stream and returns the corresponding {@link ParsedBepOutput}. May only be + * called once on a given stream. * *

As BEP retrieval can be memory-intensive for large projects, implementations of * getBuildOutput may restrict parallelism for cases in which many builds are executed in parallel * (e.g. remote builds). */ ParsedBepOutput getBuildOutput( - Optional completionBuildId, Interner stringInterner) + BuildEventStreamProvider bepStream, Interner stringInterner) throws GetArtifactsException; /** - * Retrieves test results, parses them and returns the corresponding {@link BlazeTestResults}. May - * only be called once, after the build is complete. + * Parses BEP stream and returns the corresponding {@link BlazeTestResults}. May + * only be called once on a given stream. */ - BlazeTestResults getTestResults(Optional completedBuildId) throws GetArtifactsException; + BlazeTestResults getTestResults(BuildEventStreamProvider bepStream) throws GetArtifactsException; /** Deletes the local BEP output file associated with the test results */ default void deleteTemporaryOutputFiles() {} /** - * Parses the BEP output data to collect all build flags used. Return all flags that pass filters + * Parses the BEP stream and collects all build flags used. Return all flags that pass filters */ - BuildFlags getBlazeFlags(Optional completedBuildId) throws GetFlagsException; + BuildFlags getBlazeFlags(BuildEventStreamProvider bepStream) throws GetFlagsException; /** * Parses the BEP output data to collect message on stdout. diff --git a/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelperBep.java b/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelperBep.java index 3796670d6c0..fe8df99d770 100644 --- a/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelperBep.java +++ b/base/src/com/google/idea/blaze/base/command/buildresult/BuildResultHelperBep.java @@ -17,15 +17,13 @@ import com.google.common.collect.Interner; import com.google.idea.blaze.base.command.buildresult.BuildEventStreamProvider.BuildEventStreamException; -import com.google.idea.blaze.base.io.InputStreamProvider; import com.google.idea.blaze.base.run.testlogs.BlazeTestResults; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.FileNotFoundException; import java.util.List; import java.util.Optional; import org.jetbrains.annotations.VisibleForTesting; @@ -56,22 +54,32 @@ public List getBuildFlags() { } @Override - public ParsedBepOutput getBuildOutput(Optional completedBuildId, Interner stringInterner) + public BuildEventStreamProvider getBepStream(Optional completionBuildId) throws GetArtifactsException { + try { + return BuildEventStreamProvider.fromInputStream(new BufferedInputStream(new FileInputStream(outputFile))); + } + catch (FileNotFoundException e) { + logger.error(e); + throw new GetArtifactsException(e.getMessage()); + } + } + + @Override + public ParsedBepOutput getBuildOutput(BuildEventStreamProvider bepStream, Interner stringInterner) throws GetArtifactsException { - try (InputStream inputStream = new BufferedInputStream(new FileInputStream(outputFile))) { - return ParsedBepOutput.parseBepArtifacts(inputStream); - } catch (IOException | BuildEventStreamException e) { + try { + return ParsedBepOutput.parseBepArtifacts(bepStream, stringInterner); + } catch (BuildEventStreamException e) { logger.error(e); throw new GetArtifactsException(e.getMessage()); } } @Override - public BlazeTestResults getTestResults(Optional completedBuildId) { - try (InputStream inputStream = - new BufferedInputStream(InputStreamProvider.getInstance().forFile(outputFile))) { - return BuildEventProtocolOutputReader.parseTestResults(inputStream); - } catch (IOException | BuildEventStreamException e) { + public BlazeTestResults getTestResults(BuildEventStreamProvider bepStream) { + try { + return BuildEventProtocolOutputReader.parseTestResults(bepStream); + } catch (BuildEventStreamException e) { logger.warn(e); return BlazeTestResults.NO_RESULTS; } @@ -85,10 +93,10 @@ public void deleteTemporaryOutputFiles() { } @Override - public BuildFlags getBlazeFlags(Optional completedBuildId) throws GetFlagsException { - try (InputStream inputStream = new BufferedInputStream(new FileInputStream(outputFile))) { - return BuildFlags.parseBep(inputStream); - } catch (IOException | BuildEventStreamException e) { + public BuildFlags getBlazeFlags(BuildEventStreamProvider bepStream) throws GetFlagsException { + try { + return BuildFlags.parseBep(bepStream); + } catch (BuildEventStreamException e) { throw new GetFlagsException(e); } } diff --git a/base/src/com/google/idea/blaze/base/command/buildresult/ParsedBepOutput.java b/base/src/com/google/idea/blaze/base/command/buildresult/ParsedBepOutput.java index 5ebf702c0fd..c595afef892 100644 --- a/base/src/com/google/idea/blaze/base/command/buildresult/ParsedBepOutput.java +++ b/base/src/com/google/idea/blaze/base/command/buildresult/ParsedBepOutput.java @@ -110,12 +110,6 @@ public void end() { 0, ImmutableSet.of()); - /** Parses BEP events into {@link ParsedBepOutput} */ - public static ParsedBepOutput parseBepArtifacts(InputStream bepStream) - throws BuildEventStreamException { - return parseBepArtifacts(BuildEventStreamProvider.fromInputStream(bepStream)); - } - /** Parses BEP events into {@link ParsedBepOutput} */ public static ParsedBepOutput parseBepArtifacts(BuildEventStreamProvider stream) throws BuildEventStreamException { diff --git a/base/src/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategy.java b/base/src/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategy.java index 1d7bd7138f4..c0fdf9d5411 100644 --- a/base/src/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategy.java +++ b/base/src/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategy.java @@ -34,7 +34,9 @@ public LocalBuildEventProtocolTestFinderStrategy(BuildResultHelper buildResultHe @Override public BlazeTestResults findTestResults() throws GetArtifactsException { - return buildResultHelper.getTestResults(Optional.empty()); + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + return buildResultHelper.getTestResults(bepStream); + } } @Override diff --git a/base/tests/unittests/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReaderTest.java b/base/tests/unittests/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReaderTest.java index 2604d3bdca0..c0bb2c637c8 100644 --- a/base/tests/unittests/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReaderTest.java +++ b/base/tests/unittests/com/google/idea/blaze/base/command/buildresult/BuildEventProtocolOutputReaderTest.java @@ -113,7 +113,7 @@ public void parseAllOutputs_singleTargetEvents_returnsAllOutputs() throws Except ImmutableList.of(outputGroup("name", ImmutableList.of("set-id"))))); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getAllOutputArtifacts(path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -137,7 +137,7 @@ public void parseAllOutputsWithFilter_singleFileEvent_returnsFilteredOutputs() t ImmutableList.of(outputGroup("name", ImmutableList.of("set-id"))))); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)).getAllOutputArtifacts(filter); + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))).getAllOutputArtifacts(filter); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) .containsExactly(new File("/usr/local/lib/File.py")); @@ -150,7 +150,7 @@ public void parseAllOutputs_nonFileEvent_returnsEmptyList() throws Exception { .setCompleted(BuildEventStreamProtos.TargetComplete.getDefaultInstance()); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(targetFinishedEvent)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(targetFinishedEvent))) .getAllOutputArtifacts(path -> true); assertThat(parsedFilenames).isEmpty(); @@ -177,7 +177,7 @@ public void parseAllOutputs_singleTargetEventsPlusExtras_returnsAllOutputs() thr ImmutableList.of(outputGroup("name", ImmutableList.of("set-id"))))); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getAllOutputArtifacts(path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -222,7 +222,7 @@ public void parseAllOutputs_singleTargetWithMultipleFileSets_returnsAllOutputs() .collect(toImmutableList()); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getAllOutputArtifacts(path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -259,7 +259,7 @@ public void parseAllOutputs_streamWithDuplicateFiles_returnsUniqueOutputs() thro .collect(toImmutableList()); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getAllOutputArtifacts(path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -291,7 +291,7 @@ public void parseArtifactsForTarget_singleTarget_returnsTargetOutputs() throws E .collect(toImmutableList()); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getDirectArtifactsForTarget(Label.create("//some:target"), path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -331,7 +331,7 @@ public void parseArtifactsForTarget_twoTargets_returnsCorrectTargetOutputs() thr .collect(toImmutableList()); ImmutableSet parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getDirectArtifactsForTarget(Label.create("//some:target"), path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -377,7 +377,7 @@ public void parseAllArtifactsInOutputGroups_oneGroup_returnsAllOutputs() throws .collect(toImmutableList()); ImmutableList parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getOutputGroupArtifacts("group-name", path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -418,7 +418,7 @@ public void parseAllArtifactsInOutputGroups_oneOfTwoGroups_returnsCorrectOutputs .collect(toImmutableList()); ImmutableList parsedFilenames = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)) + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))) .getOutputGroupArtifacts("group-1", path -> true); assertThat(LocalFileArtifact.getLocalFiles(parsedFilenames)) @@ -454,7 +454,7 @@ public void getFullArtifactData_returnsTransitiveOutputs() throws Exception { .collect(toImmutableList()); ImmutableMap outputData = - ParsedBepOutput.parseBepArtifacts(asInputStream(events)).getFullArtifactData(); + ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))).getFullArtifactData(); ImmutableList outputs = outputData.values().stream().map(d -> d.artifact).collect(toImmutableList()); @@ -482,7 +482,7 @@ public void parseTestResults_singleEvent_returnsTestResults() throws Exception { BuildEvent.Builder event = testResultEvent(label.toString(), status, filePaths); BlazeTestResults results = - BuildEventProtocolOutputReader.parseTestResults(asInputStream(event)); + BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(asInputStream(event))); assertThat(results.perTargetResults.keySet()).containsExactly(label); assertThat(results.perTargetResults.get(label)).hasSize(1); @@ -503,7 +503,7 @@ public void parseTestResults_singleTestEventWithTargetConfigured_resultsIncludeT targetConfiguredEvent(label.toString(), "sh_test rule"), testResultEvent(label.toString(), status, filePaths)); - BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(events); + BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(events)); assertThat(results.perTargetResults.keySet()).containsExactly(label); assertThat(results.perTargetResults.get(label)).hasSize(1); @@ -525,7 +525,7 @@ public void parseTestResults_singleTestEventWithTargetCompleted_resultsIncludeTa targetCompletedEvent(label.toString(), "sh_test rule"), testResultEvent(label.toString(), status, filePaths)); - BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(events); + BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(events)); assertThat(results.perTargetResults.keySet()).containsExactly(label); assertThat(results.perTargetResults.get(label)).hasSize(1); @@ -548,7 +548,7 @@ public void parseTestResults_multipleTargetKindSources_resultsIncludeCorrectTarg targetCompletedEvent(label.toString(), "sh_test rule"), testResultEvent(label.toString(), status, filePaths)); - BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(events); + BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(events)); assertThat(results.perTargetResults.keySet()).containsExactly(label); assertThat(results.perTargetResults.get(label)).hasSize(1); @@ -571,7 +571,7 @@ public void parseTestResults_singleEvent_ignoresNonXmlOutputFiles() throws Excep BuildEvent.Builder event = testResultEvent(label.toString(), status, filePaths); BlazeTestResults results = - BuildEventProtocolOutputReader.parseTestResults(asInputStream(event)); + BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(asInputStream(event))); BlazeTestResult result = results.perTargetResults.get(label).iterator().next(); assertThat(getOutputXmlFiles(result)) @@ -597,7 +597,7 @@ public void parseTestResults_singleTargetWithMultipleEvents_returnsTestResults() ImmutableList.of("/usr/local/tmp/_cache/shard2_of_2.xml"))); BlazeTestResults results = - BuildEventProtocolOutputReader.parseTestResults(asInputStream(events)); + BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(asInputStream(events))); ImmutableCollection targetResults = results.perTargetResults.get(label); assertThat(targetResults).hasSize(2); @@ -628,7 +628,7 @@ public void parseTestResults_multipleEvents_returnsAllResults() throws Exception ImmutableList.of("/usr/local/tmp/_cache/second_result.xml")); BlazeTestResults results = - BuildEventProtocolOutputReader.parseTestResults(asInputStream(test1, test2)); + BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream(asInputStream(test1, test2))); assertThat(results.perTargetResults).hasSize(2); assertThat(results.perTargetResults.get(Label.create("//java/com/google:Test1"))).hasSize(1); diff --git a/base/tests/unittests/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategyTest.java b/base/tests/unittests/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategyTest.java index 36f383c4aef..da95d06bdf0 100644 --- a/base/tests/unittests/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategyTest.java +++ b/base/tests/unittests/com/google/idea/blaze/base/run/testlogs/LocalBuildEventProtocolTestFinderStrategyTest.java @@ -23,47 +23,36 @@ import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.TestResultId; import com.google.idea.blaze.base.BlazeTestCase; import com.google.idea.blaze.base.command.buildresult.BuildEventProtocolOutputReader; +import com.google.idea.blaze.base.command.buildresult.BuildEventStreamProvider; import com.google.idea.blaze.base.command.buildresult.BuildEventStreamProvider.BuildEventStreamException; import com.google.idea.blaze.base.command.buildresult.BuildResultHelper; import com.google.idea.blaze.base.command.buildresult.BuildResultHelper.GetArtifactsException; import com.google.idea.blaze.base.command.buildresult.BuildResultHelperBep; -import com.google.idea.blaze.base.io.InputStreamProvider; -import com.google.idea.blaze.base.io.MockInputStreamProvider; import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.testFramework.rules.TempDirectory; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; +import java.nio.file.Files; import java.util.HashSet; import java.util.List; import java.util.Set; import org.junit.After; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mockito; /** Unit tests for {@link LocalBuildEventProtocolTestFinderStrategy}. */ @RunWith(JUnit4.class) public class LocalBuildEventProtocolTestFinderStrategyTest extends BlazeTestCase { - private MockInputStreamProvider inputStreamProvider; - private final Set deletedFiles = new HashSet<>(); - - @After - public void clearState() { - deletedFiles.clear(); - } - - @Override - protected void initTest(Container applicationServices, Container projectServices) { - inputStreamProvider = new MockInputStreamProvider(); - applicationServices.register(InputStreamProvider.class, inputStreamProvider); - } + @Rule + public TempDirectory tempDirectory = new TempDirectory(); @Test public void testFinder_fileDeletedAfterCleanup() throws GetArtifactsException { - File file = createMockFile("/tmp/bep_output.txt", new byte[0]); + File file = tempDirectory.newFile("tmp/bep_output.txt", new byte[0]); LocalBuildEventProtocolTestFinderStrategy testFinder = new LocalBuildEventProtocolTestFinderStrategy(new BuildResultHelperBep(file)); @@ -73,7 +62,7 @@ public void testFinder_fileDeletedAfterCleanup() throws GetArtifactsException { testFinder.deleteTemporaryOutputFiles(); } - assertThat(deletedFiles).contains(file); + assertThat(file.exists()).isFalse(); } @Test @@ -90,31 +79,18 @@ public void findTestResults_shouldMatchBuildEventProtocolOutputReader() BuildEventStreamProtos.TestStatus.INCOMPLETE, ImmutableList.of("/usr/local/tmp/_cache/second_result.xml")); File bepOutputFile = - createMockFile("/tmp/bep_output.txt", asByteArray(ImmutableList.of(test1, test2))); + tempDirectory.newFile("tmp/bep_output.txt", asByteArray(ImmutableList.of(test1, test2))); LocalBuildEventProtocolTestFinderStrategy strategy = new LocalBuildEventProtocolTestFinderStrategy(new BuildResultHelperBep(bepOutputFile)); - InputStream inputStream = inputStreamProvider.forFile(bepOutputFile); - BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(inputStream); + BlazeTestResults results = BuildEventProtocolOutputReader.parseTestResults(BuildEventStreamProvider.fromInputStream( + Files.newInputStream(bepOutputFile.toPath()))); BlazeTestResults finderStrategyResults = strategy.findTestResults(); assertThat(finderStrategyResults.perTargetResults.entries()) .containsExactlyElementsIn(results.perTargetResults.entries()); } - private File createMockFile(String path, byte[] contents) { - File org = new File(path); - File spy = Mockito.spy(org); - inputStreamProvider.addFile(path, contents); - Mockito.when(spy.delete()) - .then( - invocationOnMock -> { - deletedFiles.add(spy); - return true; - }); - return spy; - } - private static byte[] asByteArray(Iterable events) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); diff --git a/base/tests/utils/unit/com/google/idea/blaze/base/bazel/BepUtils.java b/base/tests/utils/unit/com/google/idea/blaze/base/bazel/BepUtils.java index fce73590b31..62cdde027f6 100644 --- a/base/tests/utils/unit/com/google/idea/blaze/base/bazel/BepUtils.java +++ b/base/tests/utils/unit/com/google/idea/blaze/base/bazel/BepUtils.java @@ -31,6 +31,7 @@ import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.NamedSetOfFiles; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.OutputGroup; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TargetComplete; +import com.google.idea.blaze.base.command.buildresult.BuildEventStreamProvider; import com.google.idea.blaze.base.command.buildresult.BuildEventStreamProvider.BuildEventStreamException; import com.google.idea.blaze.base.command.buildresult.ParsedBepOutput; import java.io.ByteArrayInputStream; @@ -127,6 +128,6 @@ public static BuildEvent setOfFiles(List filePaths, String id, Lis public static ParsedBepOutput parsedBep(List events) throws IOException, BuildEventStreamException { - return ParsedBepOutput.parseBepArtifacts(asInputStream(events)); + return ParsedBepOutput.parseBepArtifacts(BuildEventStreamProvider.fromInputStream(asInputStream(events))); } } diff --git a/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBlazeCommandRunner.java b/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBlazeCommandRunner.java index 8693265016b..c56b98fd5c8 100644 --- a/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBlazeCommandRunner.java +++ b/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBlazeCommandRunner.java @@ -52,9 +52,12 @@ public interface BuildFunction { public FakeBlazeCommandRunner() { this( - buildResultHelper -> - BlazeBuildOutputs.fromParsedBepOutput( - BuildResult.SUCCESS, buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING))); + buildResultHelper -> { + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + return BlazeBuildOutputs.fromParsedBepOutput( + BuildResult.SUCCESS, buildResultHelper.getBuildOutput(bepStream, Interners.STRING)); + } + }); } public FakeBlazeCommandRunner(BuildFunction buildFunction) { diff --git a/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBuildResultHelperBep.java b/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBuildResultHelperBep.java index 8aa9bfb1408..d6e0ad7251e 100644 --- a/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBuildResultHelperBep.java +++ b/base/tests/utils/unit/com/google/idea/blaze/base/bazel/FakeBuildResultHelperBep.java @@ -17,6 +17,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Interner; +import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos; +import com.google.idea.blaze.base.command.buildresult.BuildEventStreamProvider; import com.google.idea.blaze.base.command.buildresult.BuildFlags; import com.google.idea.blaze.base.command.buildresult.BuildResultHelper; import com.google.idea.blaze.base.command.buildresult.ParsedBepOutput; @@ -49,8 +51,36 @@ public List getBuildFlags() { return ImmutableList.of(); } + + @Override + public BuildEventStreamProvider getBepStream(Optional completionBuildId) + throws GetArtifactsException { + return new BuildEventStreamProvider() { + @Override + public Object getId() { + return Optional.empty(); + } + + @Nullable + @Override + public BuildEventStreamProtos.BuildEvent getNext() throws BuildEventStreamException { + return null; + } + + @Override + public long getBytesConsumed() { + return 0; + } + + @Override + public void close() { + + } + }; + } + @Override - public ParsedBepOutput getBuildOutput(Optional completedBuildId, Interner stringInterner) + public ParsedBepOutput getBuildOutput(BuildEventStreamProvider bepStream, Interner stringInterner) throws GetArtifactsException { if (parsedBepOutput == null) { throw new GetArtifactsException("Could not get artifacts from null bep"); @@ -60,12 +90,12 @@ public ParsedBepOutput getBuildOutput(Optional completedBuildId, Interne } @Override - public BlazeTestResults getTestResults(Optional completedBuildId) { + public BlazeTestResults getTestResults(BuildEventStreamProvider bepStream) { return BlazeTestResults.NO_RESULTS; } @Override - public BuildFlags getBlazeFlags(Optional completedBuildId) throws GetFlagsException { + public BuildFlags getBlazeFlags(BuildEventStreamProvider bepStream) throws GetFlagsException { return new BuildFlags(startupOptions.build(), cmdlineOptions.build()); } diff --git a/clwb/src/com/google/idea/blaze/clwb/run/BlazeCidrRunConfigurationRunner.java b/clwb/src/com/google/idea/blaze/clwb/run/BlazeCidrRunConfigurationRunner.java index 3e32b7d8c98..be86b2635c6 100644 --- a/clwb/src/com/google/idea/blaze/clwb/run/BlazeCidrRunConfigurationRunner.java +++ b/clwb/src/com/google/idea/blaze/clwb/run/BlazeCidrRunConfigurationRunner.java @@ -166,10 +166,10 @@ private File getExecutableToDebug(ExecutionEnvironment env) throws ExecutionExce throw new ExecutionException(e); } List candidateFiles; - try { + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { candidateFiles = LocalFileArtifact.getLocalFiles( - buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING) + buildResultHelper.getBuildOutput(bepStream, Interners.STRING) .getDirectArtifactsForTarget(target, file -> true)) .stream() .filter(File::canExecute) diff --git a/golang/src/com/google/idea/blaze/golang/run/BlazeGoRunConfigurationRunner.java b/golang/src/com/google/idea/blaze/golang/run/BlazeGoRunConfigurationRunner.java index b43f9edc87c..0cf0a402582 100644 --- a/golang/src/com/google/idea/blaze/golang/run/BlazeGoRunConfigurationRunner.java +++ b/golang/src/com/google/idea/blaze/golang/run/BlazeGoRunConfigurationRunner.java @@ -368,10 +368,10 @@ private static ExecutableInfo getExecutableToDebug(ExecutionEnvironment env) return parseScriptPathFile(workspaceRoot, blazeInfo.getExecutionRoot(), scriptPath.get()); } else { List candidateFiles; - try { + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { candidateFiles = LocalFileArtifact.getLocalFiles( - buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING) + buildResultHelper.getBuildOutput(bepStream, Interners.STRING) .getDirectArtifactsForTarget(label, file -> true)) .stream() .filter(File::canExecute) diff --git a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildServiceImpl.java b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildServiceImpl.java index f80f565bc01..2bfaebf8db0 100644 --- a/java/src/com/google/idea/blaze/java/fastbuild/FastBuildServiceImpl.java +++ b/java/src/com/google/idea/blaze/java/fastbuild/FastBuildServiceImpl.java @@ -321,33 +321,39 @@ private FastBuildState.BuildOutput buildDeployJar( throw new FastBuildTunnelException(new BlazeBuildError("Blaze failure building deploy jar")); } Predicate jarPredicate = file -> file.endsWith(deployJarLabel.targetName().toString()); - try { + + File deployJar; + try (final var bepStream = resultHelper.getBepStream(Optional.empty())) { ImmutableList deployJarArtifacts = LocalFileArtifact.getLocalFiles( - resultHelper.getBuildOutput(Optional.empty(), Interners.STRING) + resultHelper.getBuildOutput(bepStream, Interners.STRING) .getDirectArtifactsForTarget( deployJarStrategy.deployJarOwnerLabel(label, blazeVersionData), jarPredicate)); checkState(deployJarArtifacts.size() == 1); - File deployJar = deployJarArtifacts.get(0); + deployJar = deployJarArtifacts.get(0); + } catch (GetArtifactsException e) { + throw new RuntimeException("Blaze failure building deploy jar: " + e.getMessage()); + } + ImmutableList ideInfoFiles; + try (final var bepStream = resultHelper.getBepStream(Optional.empty())) { Predicate filePredicate = file -> aspectStrategy.getAspectOutputFilePredicate().test(file); - ImmutableList ideInfoFiles = - LocalFileArtifact.getLocalFiles( - resultHelper.getBuildOutput(Optional.empty(), Interners.STRING) - .getOutputGroupArtifacts( - aspectStrategy.getAspectOutputGroup(), filePredicate)); - - // if targets are built with multiple configurations, just take the first one - // TODO(brendandouglas): choose a consistent configuration instead - ImmutableMap blazeData = - ideInfoFiles.stream() - .map(aspectStrategy::readFastBuildBlazeData) - .collect(toImmutableMap(FastBuildBlazeData::label, i -> i, (i, j) -> i)); - return BuildOutput.create(deployJar, blazeData, blazeInfo); + ideInfoFiles = LocalFileArtifact.getLocalFiles( + resultHelper.getBuildOutput(bepStream, Interners.STRING) + .getOutputGroupArtifacts( + aspectStrategy.getAspectOutputGroup(), filePredicate)); } catch (GetArtifactsException e) { - throw new RuntimeException("Blaze failure building deploy jar: " + e.getMessage()); + throw new RuntimeException("Blaze failure building ide info files: " + e.getMessage()); } + + // if targets are built with multiple configurations, just take the first one + // TODO(brendandouglas): choose a consistent configuration instead + ImmutableMap blazeData = + ideInfoFiles.stream() + .map(aspectStrategy::readFastBuildBlazeData) + .collect(toImmutableMap(FastBuildBlazeData::label, i -> i, (i, j) -> i)); + return BuildOutput.create(deployJar, blazeData, blazeInfo); } private BlazeInfo getBlazeInfo(BlazeContext context, FastBuildParameters buildParameters) { diff --git a/java/src/com/google/idea/blaze/java/run/hotswap/ClassFileManifestBuilder.java b/java/src/com/google/idea/blaze/java/run/hotswap/ClassFileManifestBuilder.java index 12a12e8c91c..175cd7ecb42 100644 --- a/java/src/com/google/idea/blaze/java/run/hotswap/ClassFileManifestBuilder.java +++ b/java/src/com/google/idea/blaze/java/run/hotswap/ClassFileManifestBuilder.java @@ -132,10 +132,10 @@ public static ClassFileManifest.Diff buildManifest( throw new ExecutionException(e); } ImmutableList jars; - try { + try(final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { jars = LocalFileArtifact.getLocalFiles( - buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING) + buildResultHelper.getBuildOutput(bepStream, Interners.STRING) .getOutputGroupArtifacts(JavaClasspathAspectStrategy.OUTPUT_GROUP, file -> true)) .stream() .filter(f -> f.getName().endsWith(".jar")) diff --git a/python/src/com/google/idea/blaze/python/run/BlazePyRunConfigurationRunner.java b/python/src/com/google/idea/blaze/python/run/BlazePyRunConfigurationRunner.java index d71c360c0fb..6e386c70187 100644 --- a/python/src/com/google/idea/blaze/python/run/BlazePyRunConfigurationRunner.java +++ b/python/src/com/google/idea/blaze/python/run/BlazePyRunConfigurationRunner.java @@ -341,10 +341,10 @@ private static PyExecutionInfo getExecutableToDebug(ExecutionEnvironment env) throw new ExecutionException(e); } List candidateFiles; - try { + try(final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { candidateFiles = LocalFileArtifact.getLocalFiles( - buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING) + buildResultHelper.getBuildOutput(bepStream, Interners.STRING) .getDirectArtifactsForTarget(target, file -> true).asList()) .stream() .filter(File::canExecute) diff --git a/scala/src/com/google/idea/blaze/scala/run/producers/GenerateDeployableJarTaskProvider.java b/scala/src/com/google/idea/blaze/scala/run/producers/GenerateDeployableJarTaskProvider.java index a0d4ad8eac7..8ea857c9938 100644 --- a/scala/src/com/google/idea/blaze/scala/run/producers/GenerateDeployableJarTaskProvider.java +++ b/scala/src/com/google/idea/blaze/scala/run/producers/GenerateDeployableJarTaskProvider.java @@ -187,11 +187,14 @@ private static File getDeployableJar( throw new ExecutionException(e); } - List outputs = - LocalFileArtifact.getLocalFiles( - buildResultHelper.getBuildOutput(Optional.empty(), Interners.STRING) - .getDirectArtifactsForTarget( - target.withTargetName(target.targetName() + "_deploy.jar"), file -> true)); + List outputs; + try (final var bepStream = buildResultHelper.getBepStream(Optional.empty())) { + outputs = LocalFileArtifact.getLocalFiles( + buildResultHelper.getBuildOutput(bepStream, Interners.STRING) + .getDirectArtifactsForTarget( + target.withTargetName(target.targetName() + "_deploy.jar"), file -> true)); + } + if (outputs.isEmpty()) { throw new ExecutionException( String.format("Failed to find deployable jar when building %s", target));