support in-memory outputs in spawn result
split out from #7778
Closes #7791.
PiperOrigin-RevId: 239638546
diff --git a/src/main/java/com/google/devtools/build/lib/actions/SpawnResult.java b/src/main/java/com/google/devtools/build/lib/actions/SpawnResult.java
index c17183b..e6b56c7 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/SpawnResult.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/SpawnResult.java
@@ -18,6 +18,7 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.shell.TerminationStatus;
+import com.google.protobuf.ByteString;
import java.io.InputStream;
import java.time.Duration;
import java.util.Locale;
@@ -226,6 +227,8 @@
private final Optional<Long> numInvoluntaryContextSwitches;
private final boolean cacheHit;
private final String failureMessage;
+ private final ActionInput inMemoryOutputFile;
+ private final ByteString inMemoryContents;
SimpleSpawnResult(Builder builder) {
this.exitCode = builder.exitCode;
@@ -243,6 +246,8 @@
this.numInvoluntaryContextSwitches = builder.numInvoluntaryContextSwitches;
this.cacheHit = builder.cacheHit;
this.failureMessage = builder.failureMessage;
+ this.inMemoryOutputFile = builder.inMemoryOutputFile;
+ this.inMemoryContents = builder.inMemoryContents;
}
@Override
@@ -358,6 +363,15 @@
}
return messagePrefix + " failed" + reason + explanation;
}
+
+ @Nullable
+ @Override
+ public InputStream getInMemoryOutput(ActionInput output) {
+ if (inMemoryOutputFile != null && inMemoryOutputFile.equals(output)) {
+ return inMemoryContents.newInput();
+ }
+ return null;
+ }
}
/**
@@ -377,6 +391,9 @@
private Optional<Long> numInvoluntaryContextSwitches = Optional.empty();
private boolean cacheHit;
private String failureMessage = "";
+ /* Invariant: Either both have a value or both are null. */
+ private ActionInput inMemoryOutputFile;
+ private ByteString inMemoryContents;
public SpawnResult build() {
Preconditions.checkArgument(!runnerName.isEmpty());
@@ -470,5 +487,11 @@
this.failureMessage = failureMessage;
return this;
}
+
+ public Builder setInMemoryOutput(ActionInput outputFile, ByteString contents) {
+ this.inMemoryOutputFile = Preconditions.checkNotNull(outputFile);
+ this.inMemoryContents = Preconditions.checkNotNull(contents);
+ return this;
+ }
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/actions/SpawnResultTest.java b/src/test/java/com/google/devtools/build/lib/actions/SpawnResultTest.java
index 6dccb47..6bedfc9 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/SpawnResultTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/SpawnResultTest.java
@@ -15,6 +15,8 @@
import static com.google.common.truth.Truth.assertThat;
+import com.google.devtools.build.lib.actions.SpawnResult.Status;
+import com.google.protobuf.ByteString;
import java.time.Duration;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,4 +52,22 @@
assertThat(r.getDetailMessage("", "", false, false))
.contains("(failed due to timeout.)");
}
+
+ @Test
+ public void inMemoryContents() throws Exception {
+ ActionInput output = ActionInputHelper.fromPath("/foo/bar");
+ ByteString contents = ByteString.copyFromUtf8("hello world");
+
+ SpawnResult r =
+ new SpawnResult.Builder()
+ .setStatus(Status.SUCCESS)
+ .setExitCode(0)
+ .setRunnerName("test")
+ .setInMemoryOutput(output, contents)
+ .build();
+
+ assertThat(ByteString.readFrom(r.getInMemoryOutput(output))).isEqualTo(contents);
+ assertThat(r.getInMemoryOutput(null)).isEqualTo(null);
+ assertThat(r.getInMemoryOutput(ActionInputHelper.fromPath("/does/not/exist"))).isEqualTo(null);
+ }
}