aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Ulf Adams <ulfjack@google.com>2017-05-31 20:37:57 +0200
committerGravatar László Csomor <laszlocsomor@google.com>2017-06-01 14:08:13 +0200
commit7e0cc9e72f2e7dfbcebdbe49af74ed42d0e8f33a (patch)
treefbe9743942dfa37b95f14070e5d4e219e135c4b2 /src
parent22b85a2a3c79c6f3aef1e0a61e485bb135be4551 (diff)
Remote caching: don't crash for actions with no inputs
Fixes #3004. Change-Id: I6dcef92e9f23df574e0874a81b2901754042cf9a Closes #3085. Change-Id: I6dcef92e9f23df574e0874a81b2901754042cf9a PiperOrigin-RevId: 157612661
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/remote/TreeNodeRepository.java9
-rw-r--r--src/test/java/com/google/devtools/build/lib/remote/TreeNodeRepositoryTest.java10
-rwxr-xr-xsrc/test/shell/bazel/remote_execution_test.sh27
3 files changed, 46 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/remote/TreeNodeRepository.java b/src/main/java/com/google/devtools/build/lib/remote/TreeNodeRepository.java
index fa9eb7d6ee..8272295a84 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/TreeNodeRepository.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/TreeNodeRepository.java
@@ -68,6 +68,7 @@ public final class TreeNodeRepository extends TreeTraverser<TreeNodeRepository.T
/** A pair of path segment, TreeNode. */
@Immutable
public static final class ChildEntry {
+
private final String segment;
private final TreeNode child;
@@ -176,6 +177,8 @@ public final class TreeNodeRepository extends TreeTraverser<TreeNodeRepository.T
}
}
+ private static final TreeNode EMPTY_NODE = new TreeNode(ImmutableList.<TreeNode.ChildEntry>of());
+
// Keep only one canonical instance of every TreeNode in the repository.
private final Interner<TreeNode> interner = BlazeInterners.newWeakInterner();
// Merkle hashes are computed and cached by the repository, therefore execRoot must
@@ -264,6 +267,12 @@ public final class TreeNodeRepository extends TreeTraverser<TreeNodeRepository.T
int inputsStart,
int inputsEnd,
int segmentIndex) {
+ if (segments.isEmpty()) {
+ // We sometimes have actions with no inputs (e.g., echo "xyz" > $@), so we need to handle that
+ // case here.
+ Preconditions.checkState(inputs.isEmpty());
+ return EMPTY_NODE;
+ }
if (segmentIndex == segments.get(inputsStart).size()) {
// Leaf node reached. Must be unique.
Preconditions.checkArgument(
diff --git a/src/test/java/com/google/devtools/build/lib/remote/TreeNodeRepositoryTest.java b/src/test/java/com/google/devtools/build/lib/remote/TreeNodeRepositoryTest.java
index 4bb8883269..f9ef9111a6 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/TreeNodeRepositoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/TreeNodeRepositoryTest.java
@@ -152,4 +152,14 @@ public class TreeNodeRepositoryTest {
.containsExactly(
rootDigest, aDigest, barDigest, barContentsDigest, fooDigest, fooContentsDigest);
}
+
+ @Test
+ public void testEmptyTree() throws Exception {
+ SortedMap<PathFragment, ActionInput> inputs = new TreeMap<>();
+ TreeNodeRepository repo = createTestTreeNodeRepository();
+ TreeNode root = repo.buildFromActionInputs(inputs);
+ repo.computeMerkleDigests(root);
+
+ assertThat(root.getChildEntries()).isEmpty();
+ }
}
diff --git a/src/test/shell/bazel/remote_execution_test.sh b/src/test/shell/bazel/remote_execution_test.sh
index 1a8748da02..e460bff30e 100755
--- a/src/test/shell/bazel/remote_execution_test.sh
+++ b/src/test/shell/bazel/remote_execution_test.sh
@@ -224,6 +224,33 @@ EOF
|| fail "Failed to run //a:test with remote execution"
}
+function test_noinput_action() {
+ mkdir -p a
+ cat > a/rule.bzl <<'EOF'
+def _impl(ctx):
+ output = ctx.outputs.out
+ ctx.action(
+ outputs=[output],
+ command="echo 'Hello World' > %s" % (output.path))
+
+empty = rule(
+ implementation=_impl,
+ outputs={"out": "%{name}.txt"},
+)
+EOF
+ cat > a/BUILD <<'EOF'
+load("//a:rule.bzl", "empty")
+package(default_visibility = ["//visibility:public"])
+empty(name = 'test')
+EOF
+ bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
+ --spawn_strategy=remote \
+ --remote_cache=localhost:${worker_port} \
+ --test_output=errors \
+ //a:test >& $TEST_log \
+ || fail "Failed to run //a:test with remote execution"
+}
+
# TODO(alpha): Add a test that fails remote execution when remote worker
# supports sandbox.