Tighten parameter types for markOmitted and injectDigest.
ActionMetadataHandler ignores non-Artifacts anyway. Additionally add a test utility for a throwing MetadataHandler.
RELNOTES: None.
PiperOrigin-RevId: 312686047
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/MetadataInjector.java b/src/main/java/com/google/devtools/build/lib/actions/cache/MetadataInjector.java
index e83f34a..a944cae 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/cache/MetadataInjector.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/cache/MetadataInjector.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.actions.cache;
-import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
@@ -47,10 +46,10 @@
* <p>This is used as an optimization to not download "orphaned artifacts" (=artifacts that no
* action depends on) from a remote system.
*/
- void markOmitted(ActionInput output);
+ void markOmitted(Artifact output);
/**
* Injects provided digest into the metadata handler, simultaneously caching lstat() data as well.
*/
- void injectDigest(ActionInput output, FileStatus statNoFollow, byte[] digest);
+ void injectDigest(Artifact output, FileStatus statNoFollow, byte[] digest);
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java
index 8acefb5..d3b4aad 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java
@@ -436,58 +436,53 @@
}
@Override
- public void injectDigest(ActionInput output, FileStatus statNoFollow, byte[] digest) {
+ public void injectDigest(Artifact output, FileStatus statNoFollow, byte[] digest) {
Preconditions.checkState(executionMode.get());
Preconditions.checkState(!output.isSymlink());
- // Assumption: any non-Artifact output is 'virtual' and should be ignored here.
- if (output instanceof Artifact) {
- final Artifact artifact = (Artifact) output;
- // We have to add the artifact to injectedFiles before calling constructFileArtifactValue
- // to avoid duplicate chmod calls.
- store.injectedFiles().add(artifact);
- FileArtifactValue fileMetadata;
- try {
- // This call may do an unnecessary call to Path#getFastDigest to see if the digest is
- // readily available. We cannot pass the digest in, though, because if it is not available
- // from the filesystem, this ArtifactFileMetadata will not compare equal to another one
- // created for the
- // same file, because the other one will be missing its digest.
- fileMetadata =
- constructFileArtifactValue(artifact, FileStatusWithDigestAdapter.adapt(statNoFollow));
- // Ensure the digest supplied matches the actual digest if it exists.
- byte[] fileDigest = fileMetadata.getDigest();
- if (fileDigest != null && !Arrays.equals(digest, fileDigest)) {
- BaseEncoding base16 = BaseEncoding.base16();
- String digestString = (digest != null) ? base16.encode(digest) : "null";
- String fileDigestString = base16.encode(fileDigest);
- throw new IllegalStateException(
- "Expected digest "
- + digestString
- + " for artifact "
- + artifact
- + ", but got "
- + fileDigestString
- + " ("
- + fileMetadata
- + ")");
- }
- } catch (IOException e) {
- // Do nothing - we just failed to inject metadata. Real error handling will be done later,
- // when somebody will try to access that file.
- return;
- }
- // If needed, insert additional data. Note that this can only be true if the file is empty or
- // the filesystem does not support fast digests. Since we usually only inject digests when
- // running with a filesystem that supports fast digests, this is fairly unlikely.
- try {
- maybeStoreAdditionalData(artifact, fileMetadata, digest);
- } catch (IOException e) {
+ // We have to add the artifact to injectedFiles before calling constructFileArtifactValue
+ // to avoid duplicate chmod calls.
+ store.injectedFiles().add(output);
+ FileArtifactValue fileMetadata;
+ try {
+ // This call may do an unnecessary call to Path#getFastDigest to see if the digest is readily
+ // available. We cannot pass the digest in, though, because if it is not available from the
+ // filesystem, this ArtifactFileMetadata will not compare equal to another one created for the
+ // same file, because the other one will be missing its digest.
+ fileMetadata =
+ constructFileArtifactValue(output, FileStatusWithDigestAdapter.adapt(statNoFollow));
+ // Ensure the digest supplied matches the actual digest if it exists.
+ byte[] fileDigest = fileMetadata.getDigest();
+ if (fileDigest != null && !Arrays.equals(digest, fileDigest)) {
+ BaseEncoding base16 = BaseEncoding.base16();
+ String digestString = (digest != null) ? base16.encode(digest) : "null";
+ String fileDigestString = base16.encode(fileDigest);
throw new IllegalStateException(
- "Filesystem should not have been accessed while injecting data for "
- + artifact.prettyPrint(),
- e);
+ "Expected digest "
+ + digestString
+ + " for artifact "
+ + output
+ + ", but got "
+ + fileDigestString
+ + " ("
+ + fileMetadata
+ + ")");
}
+ } catch (IOException e) {
+ // Do nothing - we just failed to inject metadata. Real error handling will be done later,
+ // when somebody will try to access that file.
+ return;
+ }
+ // If needed, insert additional data. Note that this can only be true if the file is empty or
+ // the filesystem does not support fast digests. Since we usually only inject digests when
+ // running with a filesystem that supports fast digests, this is fairly unlikely.
+ try {
+ maybeStoreAdditionalData(output, fileMetadata, digest);
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "Filesystem should not have been accessed while injecting data for "
+ + output.prettyPrint(),
+ e);
}
}
@@ -516,13 +511,10 @@
}
@Override
- public void markOmitted(ActionInput output) {
+ public void markOmitted(Artifact output) {
Preconditions.checkState(executionMode.get());
- if (output instanceof Artifact) {
- Artifact artifact = (Artifact) output;
- Preconditions.checkState(omittedOutputs.add(artifact), artifact);
- store.putArtifactData(artifact, FileArtifactValue.OMITTED_FILE_MARKER);
- }
+ Preconditions.checkState(omittedOutputs.add(output), "%s marked as omitted twice", output);
+ store.putArtifactData(output, FileArtifactValue.OMITTED_FILE_MARKER);
}
@Override
diff --git a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
index ae92ac8..29b5eb0 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
@@ -60,6 +60,7 @@
import com.google.devtools.build.lib.actions.cache.MetadataHandler;
import com.google.devtools.build.lib.actions.cache.Protos.ActionCacheStatistics.MissDetail;
import com.google.devtools.build.lib.actions.cache.Protos.ActionCacheStatistics.MissReason;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil.FakeMetadataHandlerBase;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate.OutputPathMapper;
@@ -930,10 +931,23 @@
}
/**
+ * A {@link MetadataHandler} for tests that throws {@link UnsupportedOperationException} for its
+ * operations.
+ */
+ public static final MetadataHandler THROWING_METADATA_HANDLER =
+ new FakeMetadataHandlerBase() {
+ @Override
+ public String toString() {
+ return "THROWING_METADATA_HANDLER";
+ }
+ };
+
+ /**
* A {@link MetadataHandler} all of whose operations throw an exception.
*
- * <p>This is to be used as a base class by other test programs that need to implement only a
- * few of the hooks required by the scenario under test.
+ * <p>This is to be used as a base class by other test programs that need to implement only a few
+ * of the hooks required by the scenario under test. Tests that need an instance but do not need
+ * any functionality can use {@link #THROWING_METADATA_HANDLER}.
*/
public static class FakeMetadataHandlerBase implements MetadataHandler {
@Override
@@ -957,7 +971,7 @@
}
@Override
- public void injectDigest(ActionInput output, FileStatus statNoFollow, byte[] digest) {
+ public void injectDigest(Artifact output, FileStatus statNoFollow, byte[] digest) {
throw new UnsupportedOperationException();
}
@@ -973,7 +987,7 @@
}
@Override
- public void markOmitted(ActionInput output) {
+ public void markOmitted(Artifact output) {
throw new UnsupportedOperationException();
}
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 2ab08c1..b32abdb 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
@@ -38,16 +38,15 @@
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
-import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.ArtifactPathResolver;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
-import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
import com.google.devtools.build.lib.actions.MetadataProvider;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.SimpleSpawn;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.SpawnResult.Status;
import com.google.devtools.build.lib.actions.cache.MetadataInjector;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.clock.JavaClock;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
@@ -69,7 +68,6 @@
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
-import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
@@ -81,7 +79,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.SortedMap;
import org.junit.Before;
import org.junit.Test;
@@ -177,29 +174,7 @@
@Override
public MetadataInjector getMetadataInjector() {
- return new MetadataInjector() {
- @Override
- public void injectRemoteFile(Artifact output, RemoteFileArtifactValue metadata) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void injectRemoteDirectory(
- Artifact.SpecialArtifact output,
- Map<TreeFileArtifact, RemoteFileArtifactValue> children) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void markOmitted(ActionInput output) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void injectDigest(ActionInput output, FileStatus statNoFollow, byte[] digest) {
- throw new UnsupportedOperationException();
- }
- };
+ return ActionsTestUtil.THROWING_METADATA_HANDLER;
}
@Override
diff --git a/src/test/java/com/google/devtools/build/lib/remote/util/BUILD b/src/test/java/com/google/devtools/build/lib/remote/util/BUILD
index 0ec7965..d68132c 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/util/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/remote/util/BUILD
@@ -24,6 +24,7 @@
"//src/main/java/com/google/devtools/build/lib/util/io",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+ "//src/test/java/com/google/devtools/build/lib/actions/util",
"//third_party:guava",
"//third_party/protobuf:protobuf_java",
"@remoteapis//:build_bazel_remote_execution_v2_remote_execution_java_proto",
diff --git a/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java b/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java
index 0c505bc..907ec22 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java
@@ -19,23 +19,20 @@
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
-import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.ArtifactPathResolver;
-import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
import com.google.devtools.build.lib.actions.MetadataProvider;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.cache.MetadataInjector;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.exec.SpawnInputExpander;
import com.google.devtools.build.lib.exec.SpawnRunner.ProgressStatus;
import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionContext;
import com.google.devtools.build.lib.util.io.FileOutErr;
-import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.time.Duration;
import java.util.Collection;
-import java.util.Map;
import java.util.SortedMap;
/** Execution context for tests */
@@ -130,29 +127,7 @@
@Override
public MetadataInjector getMetadataInjector() {
- return new MetadataInjector() {
- @Override
- public void injectRemoteFile(Artifact output, RemoteFileArtifactValue metadata) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void injectRemoteDirectory(
- Artifact.SpecialArtifact output,
- Map<TreeFileArtifact, RemoteFileArtifactValue> children) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void markOmitted(ActionInput output) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void injectDigest(ActionInput output, FileStatus statNoFollow, byte[] digest) {
- throw new UnsupportedOperationException();
- }
- };
+ return ActionsTestUtil.THROWING_METADATA_HANDLER;
}
@Override