aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar olaola <olaola@google.com>2017-09-18 23:04:33 +0200
committerGravatar László Csomor <laszlocsomor@google.com>2017-09-19 09:32:25 +0200
commit7744b86e9c7950da62e87bfff3967c67477a1620 (patch)
treea6eaa8ca42c7df294ca2c2035b12d41e59a88e21 /src
parent8f9ace9bb6794e23ecac28ff70a9afebfc33ee12 (diff)
Uploading failed action outputs to the remote cache, because even if the tests fails, we still want to be able to download the logs and other outputs from CAS.
This fixes a bug introduced by https://github.com/bazelbuild/bazel/commit/562fcf9f5dfd14daea718f77da95b43b1400689b. To reproduce: run a failing test vs a BES service, the test log would not be uploaded. TESTED=unit tests PiperOrigin-RevId: 169143428
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/GrpcRemoteCache.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java14
-rw-r--r--src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteCacheTest.java38
-rw-r--r--src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java25
-rw-r--r--src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java44
8 files changed, 110 insertions, 44 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/remote/GrpcRemoteCache.java b/src/main/java/com/google/devtools/build/lib/remote/GrpcRemoteCache.java
index ee7ef666e3..b49a103b5c 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/GrpcRemoteCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/GrpcRemoteCache.java
@@ -281,10 +281,18 @@ public class GrpcRemoteCache implements RemoteActionCache {
}
@Override
- public void upload(ActionKey actionKey, Path execRoot, Collection<Path> files, FileOutErr outErr)
+ public void upload(
+ ActionKey actionKey,
+ Path execRoot,
+ Collection<Path> files,
+ FileOutErr outErr,
+ boolean uploadAction)
throws IOException, InterruptedException {
ActionResult.Builder result = ActionResult.newBuilder();
upload(execRoot, files, outErr, result);
+ if (!uploadAction) {
+ return;
+ }
try {
retrier.execute(
() ->
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java
index 4c7cf7408a..d480a93b38 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java
@@ -75,9 +75,15 @@ interface RemoteActionCache {
/**
* Upload the result of a locally executed action to the cache by uploading any necessary files,
- * stdin / stdout, as well as adding an entry for the given action key to the cache.
+ * stdin / stdout, as well as adding an entry for the given action key to the cache if
+ * uploadAction is true.
*/
- void upload(ActionKey actionKey, Path execRoot, Collection<Path> files, FileOutErr outErr)
+ void upload(
+ ActionKey actionKey,
+ Path execRoot,
+ Collection<Path> files,
+ FileOutErr outErr,
+ boolean uploadAction)
throws IOException, InterruptedException;
/** Release resources associated with the cache. The cache may not be used after calling this. */
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java
index 2b74e88b3f..774a5802a7 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java
@@ -128,11 +128,9 @@ final class RemoteSpawnCache implements SpawnCache {
@Override
public void store(SpawnResult result, Collection<Path> files)
throws InterruptedException, IOException {
- if (result.status() != Status.SUCCESS || result.exitCode() != 0) {
- return;
- }
try {
- remoteCache.upload(actionKey, execRoot, files, policy.getFileOutErr());
+ boolean uploadAction = Status.SUCCESS.equals(result.status()) && result.exitCode() == 0;
+ remoteCache.upload(actionKey, execRoot, files, policy.getFileOutErr(), uploadAction);
} catch (IOException e) {
if (verboseFailures) {
report(Event.debug("Upload to remote cache failed: " + e.getMessage()));
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java
index a5990ff683..b4d28cd995 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnRunner.java
@@ -329,10 +329,6 @@ class RemoteSpawnRunner implements SpawnRunner {
ActionKey actionKey) throws ExecException, IOException, InterruptedException {
Map<Path, Long> ctimesBefore = getInputCtimes(inputMap);
SpawnResult result = fallbackRunner.exec(spawn, policy);
- if (!Status.SUCCESS.equals(result.status()) || result.exitCode() != 0) {
- // Don't upload failed actions.
- return result;
- }
Map<Path, Long> ctimesAfter = getInputCtimes(inputMap);
for (Map.Entry<Path, Long> e : ctimesBefore.entrySet()) {
// Skip uploading to remote cache, because an input was modified during execution.
@@ -342,7 +338,8 @@ class RemoteSpawnRunner implements SpawnRunner {
}
List<Path> outputFiles = listExistingOutputFiles(execRoot, spawn);
try {
- remoteCache.upload(actionKey, execRoot, outputFiles, policy.getFileOutErr());
+ boolean uploadAction = Status.SUCCESS.equals(result.status()) && result.exitCode() == 0;
+ remoteCache.upload(actionKey, execRoot, outputFiles, policy.getFileOutErr(), uploadAction);
} catch (IOException e) {
if (verboseFailures) {
report(Event.debug("Upload to remote cache failed: " + e.getMessage()));
diff --git a/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java b/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java
index 6fef48f178..0a435fabed 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/SimpleBlobStoreActionCache.java
@@ -170,8 +170,12 @@ public final class SimpleBlobStoreActionCache implements RemoteActionCache {
@Override
public void upload(
- ActionKey actionKey, Path execRoot, Collection<Path> files, FileOutErr outErr)
- throws IOException, InterruptedException {
+ ActionKey actionKey,
+ Path execRoot,
+ Collection<Path> files,
+ FileOutErr outErr,
+ boolean uploadAction)
+ throws IOException, InterruptedException {
ActionResult.Builder result = ActionResult.newBuilder();
upload(result, execRoot, files);
if (outErr.getErrorPath().exists()) {
@@ -182,8 +186,10 @@ public final class SimpleBlobStoreActionCache implements RemoteActionCache {
Digest stdout = uploadFileContents(outErr.getOutputPath());
result.setStdoutDigest(stdout);
}
- blobStore.putActionResult(
- actionKey.getDigest().getHash(), new ByteArrayInputStream(result.build().toByteArray()));
+ if (uploadAction) {
+ blobStore.putActionResult(
+ actionKey.getDigest().getHash(), new ByteArrayInputStream(result.build().toByteArray()));
+ }
}
public void upload(ActionResult.Builder result, Path execRoot, Collection<Path> files)
diff --git a/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteCacheTest.java b/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteCacheTest.java
index 96b74d2a5b..fe31aa729d 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteCacheTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteCacheTest.java
@@ -38,6 +38,7 @@ import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.common.options.Options;
+import com.google.devtools.remoteexecution.v1test.Action;
import com.google.devtools.remoteexecution.v1test.ActionCacheGrpc.ActionCacheImplBase;
import com.google.devtools.remoteexecution.v1test.ActionResult;
import com.google.devtools.remoteexecution.v1test.ContentAddressableStorageGrpc.ContentAddressableStorageImplBase;
@@ -413,6 +414,40 @@ public class GrpcRemoteCacheTest {
}
@Test
+ public void testUploadUploadsOnlyOutputs() throws Exception {
+ final GrpcRemoteCache client = newClient();
+ final Digest fooDigest =
+ fakeFileCache.createScratchInput(ActionInputHelper.fromPath("a/foo"), "xyz");
+ final Digest barDigest =
+ fakeFileCache.createScratchInput(ActionInputHelper.fromPath("bar"), "x");
+ serviceRegistry.addService(
+ new ContentAddressableStorageImplBase() {
+ @Override
+ public void findMissingBlobs(
+ FindMissingBlobsRequest request,
+ StreamObserver<FindMissingBlobsResponse> responseObserver) {
+ // This checks we will try to upload the actual outputs.
+ assertThat(request.getBlobDigestsList()).containsExactly(fooDigest, barDigest);
+ responseObserver.onNext(FindMissingBlobsResponse.getDefaultInstance());
+ responseObserver.onCompleted();
+ }
+ });
+ serviceRegistry.addService(
+ new ActionCacheImplBase() {
+ @Override
+ public void updateActionResult(
+ UpdateActionResultRequest request, StreamObserver<ActionResult> responseObserver) {
+ fail("Update action result was expected to not be called.");
+ }
+ });
+
+ ActionKey emptyKey = Digests.computeActionKey(Action.getDefaultInstance());
+ Path fooFile = execRoot.getRelative("a/foo");
+ Path barFile = execRoot.getRelative("bar");
+ client.upload(emptyKey, execRoot, ImmutableList.<Path>of(fooFile, barFile), outErr, false);
+ }
+
+ @Test
public void testUploadCacheMissesWithRetries() throws Exception {
final GrpcRemoteCache client = newClient();
final Digest fooDigest =
@@ -526,7 +561,8 @@ public class GrpcRemoteCacheTest {
};
}
});
- client.upload(actionKey, execRoot, ImmutableList.<Path>of(fooFile, barFile, bazFile), outErr);
+ client.upload(
+ actionKey, execRoot, ImmutableList.<Path>of(fooFile, barFile, bazFile), outErr, true);
// 4 times for the errors, 3 times for the successful uploads.
Mockito.verify(mockByteStreamImpl, Mockito.times(7))
.write(Mockito.<StreamObserver<WriteResponse>>anyObject());
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
index 43e4de4f54..160c20fa6d 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
@@ -189,7 +189,11 @@ public class RemoteSpawnCacheTest {
any(Command.class));
verify(remoteCache, never())
.upload(
- any(ActionKey.class), any(Path.class), any(Collection.class), any(FileOutErr.class));
+ any(ActionKey.class),
+ any(Path.class),
+ any(Collection.class),
+ any(FileOutErr.class),
+ any(Boolean.class));
assertThat(result.setupSuccess()).isTrue();
assertThat(result.exitCode()).isEqualTo(0);
// We expect the CachedLocalSpawnRunner to _not_ write to outErr at all.
@@ -205,11 +209,7 @@ public class RemoteSpawnCacheTest {
ImmutableList<Path> outputFiles = ImmutableList.of(fs.getPath("/random/file"));
entry.store(result, outputFiles);
verify(remoteCache)
- .upload(
- any(ActionKey.class),
- any(Path.class),
- eq(outputFiles),
- eq(outErr));
+ .upload(any(ActionKey.class), any(Path.class), eq(outputFiles), eq(outErr), eq(true));
}
@Test
@@ -219,18 +219,13 @@ public class RemoteSpawnCacheTest {
SpawnResult result = new SpawnResult.Builder().setExitCode(0).setStatus(Status.SUCCESS).build();
ImmutableList<Path> outputFiles = ImmutableList.of(fs.getPath("/random/file"));
- doThrow(new IOException("cache down")).when(remoteCache).upload(any(ActionKey.class),
- any(Path.class),
- eq(outputFiles),
- eq(outErr));
+ doThrow(new IOException("cache down"))
+ .when(remoteCache)
+ .upload(any(ActionKey.class), any(Path.class), eq(outputFiles), eq(outErr), eq(true));
entry.store(result, outputFiles);
verify(remoteCache)
- .upload(
- any(ActionKey.class),
- any(Path.class),
- eq(outputFiles),
- eq(outErr));
+ .upload(any(ActionKey.class), any(Path.class), eq(outputFiles), eq(outErr), eq(true));
assertThat(eventHandler.getEvents()).hasSize(1);
Event evt = eventHandler.getEvents().get(0);
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
index a6c8218f01..940c9d3afd 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
@@ -147,8 +147,13 @@ public class RemoteSpawnRunnerTest {
verify(cache, never())
.getCachedActionResult(any(ActionKey.class));
- verify(cache, never()).upload(any(ActionKey.class), any(Path.class), any(Collection.class),
- any(FileOutErr.class));
+ verify(cache, never())
+ .upload(
+ any(ActionKey.class),
+ any(Path.class),
+ any(Collection.class),
+ any(FileOutErr.class),
+ any(Boolean.class));
verifyZeroInteractions(localRunner);
}
@@ -187,15 +192,20 @@ public class RemoteSpawnRunnerTest {
verify(cache, never())
.getCachedActionResult(any(ActionKey.class));
- verify(cache, never()).upload(any(ActionKey.class), any(Path.class), any(Collection.class),
- any(FileOutErr.class));
+ verify(cache, never())
+ .upload(
+ any(ActionKey.class),
+ any(Path.class),
+ any(Collection.class),
+ any(FileOutErr.class),
+ any(Boolean.class));
}
@Test
@SuppressWarnings("unchecked")
- public void failedActionShouldNotBeUploaded() throws Exception {
- // Test that the outputs of a failed locally executed action are not uploaded to a remote
- // cache.
+ public void failedActionShouldOnlyUploadOutputs() throws Exception {
+ // Test that the outputs of a failed locally executed action are uploaded to a remote cache,
+ // but the action result itself is not.
RemoteOptions options = Options.getDefaults(RemoteOptions.class);
options.remoteUploadLocalResults = true;
@@ -217,8 +227,13 @@ public class RemoteSpawnRunnerTest {
verify(localRunner).exec(eq(spawn), eq(policy));
verify(runner).execLocallyAndUpload(eq(spawn), eq(policy), any(SortedMap.class), eq(cache),
any(ActionKey.class));
- verify(cache, never()).upload(any(ActionKey.class), any(Path.class), any(Collection.class),
- any(FileOutErr.class));
+ verify(cache)
+ .upload(
+ any(ActionKey.class),
+ any(Path.class),
+ any(Collection.class),
+ any(FileOutErr.class),
+ eq(false));
}
@Test
@@ -267,9 +282,14 @@ public class RemoteSpawnRunnerTest {
when(cache.getCachedActionResult(any(ActionKey.class)))
.thenThrow(new IOException("cache down"));
- doThrow(new IOException("cache down")).when(cache)
- .upload(any(ActionKey.class), any(Path.class), any(Collection.class),
- any(FileOutErr.class));
+ doThrow(new IOException("cache down"))
+ .when(cache)
+ .upload(
+ any(ActionKey.class),
+ any(Path.class),
+ any(Collection.class),
+ any(FileOutErr.class),
+ eq(true));
SpawnResult res = new SpawnResult.Builder().setStatus(Status.SUCCESS).setExitCode(0).build();
when(localRunner.exec(eq(spawn), eq(policy))).thenReturn(res);