blob: 687ba3c057fb3036919fd7779ba08c7d8df6df05 [file] [log] [blame]
ulfjackf2b260c2018-09-28 05:09:32 -07001// Copyright 2018 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.skyframe;
15
16import static com.google.common.truth.Truth.assertThat;
michajlo660d17f2020-03-27 09:01:57 -070017import static org.junit.Assert.assertThrows;
jhorvitza68bdbb2020-07-13 16:49:20 -070018import static org.junit.Assert.fail;
ulfjackf2b260c2018-09-28 05:09:32 -070019
20import com.google.common.collect.ImmutableList;
Jakob Buchgraber1407c042019-03-11 09:35:26 -070021import com.google.common.collect.ImmutableMap;
Googler61a9f572020-06-02 10:28:24 -070022import com.google.common.collect.ImmutableSet;
jhorvitza68bdbb2020-07-13 16:49:20 -070023import com.google.common.collect.Sets;
ulfjackf2b260c2018-09-28 05:09:32 -070024import com.google.devtools.build.lib.actions.ActionInput;
25import com.google.devtools.build.lib.actions.ActionInputHelper;
26import com.google.devtools.build.lib.actions.ActionInputMap;
27import com.google.devtools.build.lib.actions.Artifact;
ulfjack9de2ea52018-10-17 09:23:23 -070028import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
ulfjack9de2ea52018-10-17 09:23:23 -070029import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
ulfjackf2b260c2018-09-28 05:09:32 -070030import com.google.devtools.build.lib.actions.ArtifactPathResolver;
31import com.google.devtools.build.lib.actions.ArtifactRoot;
32import com.google.devtools.build.lib.actions.FileArtifactValue;
Jakob Buchgraber1407c042019-03-11 09:35:26 -070033import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
Googler5284e6c2019-10-30 07:43:54 -070034import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
35import com.google.devtools.build.lib.actions.HasDigest;
36import com.google.devtools.build.lib.actions.HasDigest.ByteStringDigest;
janakraea05602019-05-22 15:41:29 -070037import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
Googlere9186eb2020-07-09 17:13:15 -070038import com.google.devtools.build.lib.testutil.ManualClock;
ulfjackf2b260c2018-09-28 05:09:32 -070039import com.google.devtools.build.lib.testutil.Scratch;
Googlere9186eb2020-07-09 17:13:15 -070040import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
jhorvitza68bdbb2020-07-13 16:49:20 -070041import com.google.devtools.build.lib.vfs.Path;
ulfjackf2b260c2018-09-28 05:09:32 -070042import com.google.devtools.build.lib.vfs.PathFragment;
43import com.google.devtools.build.lib.vfs.Root;
jhorvitza68bdbb2020-07-13 16:49:20 -070044import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
ulfjack9de2ea52018-10-17 09:23:23 -070045import java.io.FileNotFoundException;
jhorvitza68bdbb2020-07-13 16:49:20 -070046import java.io.IOException;
Jakob Buchgraber1407c042019-03-11 09:35:26 -070047import java.util.Map;
jhorvitza68bdbb2020-07-13 16:49:20 -070048import java.util.Set;
ulfjackf2b260c2018-09-28 05:09:32 -070049import org.junit.Before;
50import org.junit.Test;
51import org.junit.runner.RunWith;
52import org.junit.runners.JUnit4;
53
54/** Tests for {@link ActionMetadataHandler}. */
55@RunWith(JUnit4.class)
Googlere9186eb2020-07-09 17:13:15 -070056public final class ActionMetadataHandlerTest {
57
jhorvitza68bdbb2020-07-13 16:49:20 -070058 private final Set<Path> chmodCalls = Sets.newConcurrentHashSet();
59
60 private final Scratch scratch =
61 new Scratch(
62 new InMemoryFileSystem() {
63 @Override
64 public void chmod(Path path, int mode) throws IOException {
65 assertThat(mode).isEqualTo(0555); // Read only and executable.
66 if (!chmodCalls.add(path)) {
67 fail("chmod called on " + path + " twice");
68 }
69 super.chmod(path, mode);
70 }
71 });
72
Googlere9186eb2020-07-09 17:13:15 -070073 private final TimestampGranularityMonitor tsgm =
74 new TimestampGranularityMonitor(new ManualClock());
75
76 private final ArtifactRoot sourceRoot =
77 ArtifactRoot.asSourceRoot(Root.fromPath(scratch.resolve("/workspace")));
78 private final ArtifactRoot outputRoot =
79 ArtifactRoot.asDerivedRoot(scratch.resolve("/output"), "bin");
jhorvitz6c8f7b92020-07-15 15:02:29 -070080 private final Path execRoot = outputRoot.getRoot().asPath();
ulfjackf2b260c2018-09-28 05:09:32 -070081
82 @Before
Googlere9186eb2020-07-09 17:13:15 -070083 public void createRootDirs() throws Exception {
84 sourceRoot.getRoot().asPath().createDirectoryAndParents();
jhorvitz6c8f7b92020-07-15 15:02:29 -070085 execRoot.createDirectoryAndParents();
86 }
87
88 private ActionMetadataHandler createHandler(
89 ActionInputMap inputMap, boolean forInputDiscovery, ImmutableSet<Artifact> outputs) {
90 return ActionMetadataHandler.create(
91 inputMap,
92 forInputDiscovery,
93 outputs,
94 tsgm,
95 ArtifactPathResolver.IDENTITY,
jhorvitzc69e2682020-07-16 07:16:28 -070096 execRoot.asFragment(),
jhorvitz6c8f7b92020-07-15 15:02:29 -070097 /*expandedFilesets=*/ ImmutableMap.of());
ulfjackf2b260c2018-09-28 05:09:32 -070098 }
99
100 @Test
101 public void withNonArtifactInput() throws Exception {
102 ActionInput input = ActionInputHelper.fromPath("foo/bar");
janakr39969b12019-03-03 16:25:48 -0800103 FileArtifactValue metadata =
lberki812e6fe2019-07-25 07:50:55 -0700104 FileArtifactValue.createForNormalFile(
janakr39969b12019-03-03 16:25:48 -0800105 new byte[] {1, 2, 3}, /*proxy=*/ null, 10L, /*isShareable=*/ true);
ulfjackf2b260c2018-09-28 05:09:32 -0700106 ActionInputMap map = new ActionInputMap(1);
mschaller4c7ca322018-11-20 13:22:05 -0800107 map.putWithNoDepOwner(input, metadata);
ulfjackf2b260c2018-09-28 05:09:32 -0700108 assertThat(map.getMetadata(input)).isEqualTo(metadata);
Googler5284e6c2019-10-30 07:43:54 -0700109 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700110 createHandler(map, /*forInputDiscovery=*/ false, /*outputs=*/ ImmutableSet.of());
ulfjackf2b260c2018-09-28 05:09:32 -0700111 assertThat(handler.getMetadata(input)).isNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700112 assertThat(chmodCalls).isEmpty();
ulfjackf2b260c2018-09-28 05:09:32 -0700113 }
114
115 @Test
116 public void withArtifactInput() throws Exception {
117 PathFragment path = PathFragment.create("src/a");
janakraea05602019-05-22 15:41:29 -0700118 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(sourceRoot, path);
janakr39969b12019-03-03 16:25:48 -0800119 FileArtifactValue metadata =
lberki812e6fe2019-07-25 07:50:55 -0700120 FileArtifactValue.createForNormalFile(
janakr39969b12019-03-03 16:25:48 -0800121 new byte[] {1, 2, 3}, /*proxy=*/ null, 10L, /*isShareable=*/ true);
ulfjackf2b260c2018-09-28 05:09:32 -0700122 ActionInputMap map = new ActionInputMap(1);
mschaller4c7ca322018-11-20 13:22:05 -0800123 map.putWithNoDepOwner(artifact, metadata);
Googler5284e6c2019-10-30 07:43:54 -0700124 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700125 createHandler(map, /*forInputDiscovery=*/ false, /*outputs=*/ ImmutableSet.of());
ulfjackf2b260c2018-09-28 05:09:32 -0700126 assertThat(handler.getMetadata(artifact)).isEqualTo(metadata);
jhorvitza68bdbb2020-07-13 16:49:20 -0700127 assertThat(chmodCalls).isEmpty();
ulfjackf2b260c2018-09-28 05:09:32 -0700128 }
129
130 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700131 public void unknownSourceArtifactDisallowedOutsideOfInputDiscovery() {
ulfjackf2b260c2018-09-28 05:09:32 -0700132 PathFragment path = PathFragment.create("src/a");
janakraea05602019-05-22 15:41:29 -0700133 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(sourceRoot, path);
Googler5284e6c2019-10-30 07:43:54 -0700134 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700135 createHandler(
136 new ActionInputMap(0), /*forInputDiscovery=*/ false, /*outputs=*/ ImmutableSet.of());
Googlere9186eb2020-07-09 17:13:15 -0700137 Exception e = assertThrows(IllegalStateException.class, () -> handler.getMetadata(artifact));
138 assertThat(e).hasMessageThat().contains(artifact + " is not present in declared outputs");
jhorvitza68bdbb2020-07-13 16:49:20 -0700139 assertThat(chmodCalls).isEmpty();
ulfjackf2b260c2018-09-28 05:09:32 -0700140 }
141
142 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700143 public void unknownSourceArtifactPermittedDuringInputDiscovery() throws Exception {
ulfjackf2b260c2018-09-28 05:09:32 -0700144 PathFragment path = PathFragment.create("src/a");
janakraea05602019-05-22 15:41:29 -0700145 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(sourceRoot, path);
Googler5284e6c2019-10-30 07:43:54 -0700146 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700147 createHandler(
148 new ActionInputMap(0), /*forInputDiscovery=*/ true, /*outputs=*/ ImmutableSet.of());
ulfjackf2b260c2018-09-28 05:09:32 -0700149 assertThat(handler.getMetadata(artifact)).isNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700150 assertThat(chmodCalls).isEmpty();
ulfjackf2b260c2018-09-28 05:09:32 -0700151 }
ulfjack9de2ea52018-10-17 09:23:23 -0700152
153 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700154 public void unknownArtifactPermittedDuringInputDiscovery() throws Exception {
ulfjack9de2ea52018-10-17 09:23:23 -0700155 PathFragment path = PathFragment.create("foo/bar");
janakraea05602019-05-22 15:41:29 -0700156 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
Googler5284e6c2019-10-30 07:43:54 -0700157 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700158 createHandler(
159 new ActionInputMap(0), /*forInputDiscovery=*/ true, /*outputs=*/ ImmutableSet.of());
ulfjack9de2ea52018-10-17 09:23:23 -0700160 assertThat(handler.getMetadata(artifact)).isNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700161 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700162 }
163
164 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700165 public void withKnownOutputArtifactStatsFile() throws Exception {
ulfjack9de2ea52018-10-17 09:23:23 -0700166 scratch.file("/output/bin/foo/bar", "not empty");
janakraea05602019-05-22 15:41:29 -0700167 Artifact artifact = ActionsTestUtil.createArtifact(outputRoot, "foo/bar");
ulfjack9de2ea52018-10-17 09:23:23 -0700168 assertThat(artifact.getPath().exists()).isTrue();
Googler5284e6c2019-10-30 07:43:54 -0700169 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700170 createHandler(
171 new ActionInputMap(0),
172 /*forInputDiscovery=*/ false,
173 /*outputs=*/ ImmutableSet.of(artifact));
ulfjack9de2ea52018-10-17 09:23:23 -0700174 assertThat(handler.getMetadata(artifact)).isNotNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700175 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700176 }
177
178 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700179 public void withMissingOutputArtifactStatsFileFailsWithException() {
janakraea05602019-05-22 15:41:29 -0700180 Artifact artifact = ActionsTestUtil.createArtifact(outputRoot, "foo/bar");
ulfjack9de2ea52018-10-17 09:23:23 -0700181 assertThat(artifact.getPath().exists()).isFalse();
Googler5284e6c2019-10-30 07:43:54 -0700182 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700183 createHandler(
184 new ActionInputMap(0),
185 /*forInputDiscovery=*/ false,
186 /*outputs=*/ ImmutableSet.of(artifact));
jcater83130f42019-04-30 14:29:28 -0700187 assertThrows(FileNotFoundException.class, () -> handler.getMetadata(artifact));
jhorvitza68bdbb2020-07-13 16:49:20 -0700188 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700189 }
190
191 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700192 public void unknownArtifactDisallowedOutsideOfInputDiscovery() {
ulfjack9de2ea52018-10-17 09:23:23 -0700193 PathFragment path = PathFragment.create("foo/bar");
janakraea05602019-05-22 15:41:29 -0700194 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
Googler5284e6c2019-10-30 07:43:54 -0700195 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700196 createHandler(
197 new ActionInputMap(0), /*forInputDiscovery=*/ false, /*outputs=*/ ImmutableSet.of());
jcater83130f42019-04-30 14:29:28 -0700198 assertThrows(IllegalStateException.class, () -> handler.getMetadata(artifact));
jhorvitza68bdbb2020-07-13 16:49:20 -0700199 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700200 }
201
202 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700203 public void unknownTreeArtifactPermittedDuringInputDiscovery() throws Exception {
ulfjack9de2ea52018-10-17 09:23:23 -0700204 PathFragment path = PathFragment.create("bin/foo/bar");
janakr3290e222019-05-29 16:34:22 -0700205 SpecialArtifact treeArtifact =
Googler1d8d1382020-05-18 12:10:49 -0700206 ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, path);
207 Artifact artifact = TreeFileArtifact.createTreeOutput(treeArtifact, "baz");
Googler5284e6c2019-10-30 07:43:54 -0700208 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700209 createHandler(
210 new ActionInputMap(0), /*forInputDiscovery=*/ true, /*outputs=*/ ImmutableSet.of());
ulfjack9de2ea52018-10-17 09:23:23 -0700211 assertThat(handler.getMetadata(artifact)).isNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700212 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700213 }
214
215 @Test
216 public void withUnknownOutputArtifactStatsFileTreeArtifact() throws Exception {
217 scratch.file("/output/bin/foo/bar/baz", "not empty");
218 PathFragment path = PathFragment.create("bin/foo/bar");
janakr3290e222019-05-29 16:34:22 -0700219 SpecialArtifact treeArtifact =
Googler1d8d1382020-05-18 12:10:49 -0700220 ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, path);
221 Artifact artifact = TreeFileArtifact.createTreeOutput(treeArtifact, "baz");
ulfjack9de2ea52018-10-17 09:23:23 -0700222 assertThat(artifact.getPath().exists()).isTrue();
Googler5284e6c2019-10-30 07:43:54 -0700223 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700224 createHandler(
225 new ActionInputMap(0),
226 /*forInputDiscovery=*/ false,
227 /*outputs=*/ ImmutableSet.of(treeArtifact));
ulfjack9de2ea52018-10-17 09:23:23 -0700228 assertThat(handler.getMetadata(artifact)).isNotNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700229 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700230 }
231
232 @Test
jhorvitz6c8f7b92020-07-15 15:02:29 -0700233 public void unknownTreeArtifactDisallowedOutsideOfInputDiscovery() {
ulfjack9de2ea52018-10-17 09:23:23 -0700234 PathFragment path = PathFragment.create("bin/foo/bar");
janakr3290e222019-05-29 16:34:22 -0700235 SpecialArtifact treeArtifact =
Googler1d8d1382020-05-18 12:10:49 -0700236 ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, path);
237 Artifact artifact = TreeFileArtifact.createTreeOutput(treeArtifact, "baz");
Googler5284e6c2019-10-30 07:43:54 -0700238 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700239 createHandler(
240 new ActionInputMap(0), /*forInputDiscovery=*/ false, /*outputs=*/ ImmutableSet.of());
jcater83130f42019-04-30 14:29:28 -0700241 assertThrows(IllegalStateException.class, () -> handler.getMetadata(artifact));
jhorvitza68bdbb2020-07-13 16:49:20 -0700242 assertThat(chmodCalls).isEmpty();
ulfjack9de2ea52018-10-17 09:23:23 -0700243 }
djasperefdecce2019-02-21 08:41:22 -0800244
245 @Test
Googler974879d2020-05-27 13:25:52 -0700246 public void createsTreeArtifactValueFromFilesystem() throws Exception {
247 scratch.file("/output/bin/foo/bar/child1", "child1");
248 scratch.file("/output/bin/foo/bar/child2", "child2");
249 SpecialArtifact treeArtifact =
250 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
251 outputRoot, PathFragment.create("bin/foo/bar"));
252 TreeFileArtifact child1 = TreeFileArtifact.createTreeOutput(treeArtifact, "child1");
253 TreeFileArtifact child2 = TreeFileArtifact.createTreeOutput(treeArtifact, "child2");
254 assertThat(child1.getPath().exists()).isTrue();
255 assertThat(child2.getPath().exists()).isTrue();
256
Googler974879d2020-05-27 13:25:52 -0700257 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700258 createHandler(
259 new ActionInputMap(0),
260 /*forInputDiscovery=*/ false,
261 /*outputs=*/ ImmutableSet.of(treeArtifact));
Googler974879d2020-05-27 13:25:52 -0700262
263 FileArtifactValue treeMetadata = handler.getMetadata(treeArtifact);
264 FileArtifactValue child1Metadata = handler.getMetadata(child1);
265 FileArtifactValue child2Metadata = handler.getMetadata(child2);
jhorvitz6c8f7b92020-07-15 15:02:29 -0700266 TreeArtifactValue tree = handler.getOutputStore().getTreeArtifactData(treeArtifact);
Googler974879d2020-05-27 13:25:52 -0700267
268 assertThat(tree.getMetadata()).isEqualTo(treeMetadata);
269 assertThat(tree.getChildValues())
270 .containsExactly(child1, child1Metadata, child2, child2Metadata);
jhorvitzbda125a2020-07-16 12:12:31 -0700271 assertThat(handler.getTreeArtifactChildren(treeArtifact)).isEqualTo(tree.getChildren());
jhorvitz6c8f7b92020-07-15 15:02:29 -0700272 assertThat(handler.getOutputStore().getAllArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700273 assertThat(chmodCalls).isEmpty();
Googler974879d2020-05-27 13:25:52 -0700274 }
275
276 @Test
djasperefdecce2019-02-21 08:41:22 -0800277 public void resettingOutputs() throws Exception {
djasperefdecce2019-02-21 08:41:22 -0800278 PathFragment path = PathFragment.create("foo/bar");
janakraea05602019-05-22 15:41:29 -0700279 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
jhorvitza68bdbb2020-07-13 16:49:20 -0700280 Path outputPath = scratch.file(artifact.getPath().getPathString(), "not empty");
djasperefdecce2019-02-21 08:41:22 -0800281 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700282 createHandler(
283 new ActionInputMap(0),
284 /*forInputDiscovery=*/ true,
285 /*outputs=*/ ImmutableSet.of(artifact));
jhorvitzbda125a2020-07-16 12:12:31 -0700286 handler.prepareForActionExecution();
djasperefdecce2019-02-21 08:41:22 -0800287
288 // The handler doesn't have any info. It'll stat the file and discover that it's 10 bytes long.
289 assertThat(handler.getMetadata(artifact).getSize()).isEqualTo(10);
jhorvitza68bdbb2020-07-13 16:49:20 -0700290 assertThat(chmodCalls).containsExactly(outputPath);
djasperefdecce2019-02-21 08:41:22 -0800291
292 // Inject a remote file of size 42.
Googleref554462020-06-04 17:40:55 -0700293 handler.injectFile(
Googlerb67aaba2020-05-13 09:49:37 -0700294 artifact, new RemoteFileArtifactValue(new byte[] {1, 2, 3}, 42, 0, "ultimate-answer"));
djasperefdecce2019-02-21 08:41:22 -0800295 assertThat(handler.getMetadata(artifact).getSize()).isEqualTo(42);
296
297 // Reset this output, which will make the handler stat the file again.
298 handler.resetOutputs(ImmutableList.of(artifact));
jhorvitza68bdbb2020-07-13 16:49:20 -0700299 chmodCalls.clear(); // Permit a second chmod call for the artifact.
djasperefdecce2019-02-21 08:41:22 -0800300 assertThat(handler.getMetadata(artifact).getSize()).isEqualTo(10);
jhorvitza68bdbb2020-07-13 16:49:20 -0700301 assertThat(chmodCalls).containsExactly(outputPath);
djasperefdecce2019-02-21 08:41:22 -0800302 }
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700303
304 @Test
305 public void injectRemoteArtifactMetadata() throws Exception {
306 PathFragment path = PathFragment.create("foo/bar");
janakraea05602019-05-22 15:41:29 -0700307 Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700308 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700309 createHandler(
310 new ActionInputMap(0),
311 /*forInputDiscovery=*/ true,
312 /*outputs=*/ ImmutableSet.of(artifact));
jhorvitzbda125a2020-07-16 12:12:31 -0700313 handler.prepareForActionExecution();
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700314
315 byte[] digest = new byte[] {1, 2, 3};
316 int size = 10;
Googleref554462020-06-04 17:40:55 -0700317 handler.injectFile(
Googlerb67aaba2020-05-13 09:49:37 -0700318 artifact, new RemoteFileArtifactValue(digest, size, /*locationIndex=*/ 1, "action-id"));
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700319
320 FileArtifactValue v = handler.getMetadata(artifact);
321 assertThat(v).isNotNull();
322 assertThat(v.getDigest()).isEqualTo(digest);
323 assertThat(v.getSize()).isEqualTo(size);
jhorvitza68bdbb2020-07-13 16:49:20 -0700324 assertThat(chmodCalls).isEmpty();
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700325 }
326
327 @Test
Googler848c4ee2020-07-06 13:29:45 -0700328 public void cannotInjectTreeArtifactChildIndividually() {
Googler481bad32020-05-27 14:39:48 -0700329 SpecialArtifact treeArtifact =
330 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
331 outputRoot, PathFragment.create("bin/foo/bar"));
Googler848c4ee2020-07-06 13:29:45 -0700332 TreeFileArtifact child = TreeFileArtifact.createTreeOutput(treeArtifact, "child");
Googler481bad32020-05-27 14:39:48 -0700333
Googler481bad32020-05-27 14:39:48 -0700334 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700335 createHandler(
336 new ActionInputMap(0),
337 /*forInputDiscovery=*/ false,
338 /*outputs=*/ ImmutableSet.of(treeArtifact));
jhorvitzbda125a2020-07-16 12:12:31 -0700339 handler.prepareForActionExecution();
Googler481bad32020-05-27 14:39:48 -0700340
Googler848c4ee2020-07-06 13:29:45 -0700341 RemoteFileArtifactValue childValue = new RemoteFileArtifactValue(new byte[] {1, 2, 3}, 5, 1);
Googler481bad32020-05-27 14:39:48 -0700342
Googler848c4ee2020-07-06 13:29:45 -0700343 assertThrows(IllegalArgumentException.class, () -> handler.injectFile(child, childValue));
jhorvitz6c8f7b92020-07-15 15:02:29 -0700344 assertThat(handler.getOutputStore().getAllArtifactData()).isEmpty();
345 assertThat(handler.getOutputStore().getAllTreeArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700346 assertThat(chmodCalls).isEmpty();
Googler848c4ee2020-07-06 13:29:45 -0700347 }
Googler481bad32020-05-27 14:39:48 -0700348
Googler848c4ee2020-07-06 13:29:45 -0700349 @Test
350 public void canInjectTemplateExpansionOutput() {
351 SpecialArtifact treeArtifact =
352 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
353 outputRoot, PathFragment.create("bin/foo/bar"));
354 TreeFileArtifact output =
355 TreeFileArtifact.createTemplateExpansionOutput(
356 treeArtifact, "output", ActionsTestUtil.NULL_TEMPLATE_EXPANSION_ARTIFACT_OWNER);
Googler481bad32020-05-27 14:39:48 -0700357
Googler848c4ee2020-07-06 13:29:45 -0700358 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700359 createHandler(
360 new ActionInputMap(0),
361 /*forInputDiscovery=*/ false,
362 /*outputs=*/ ImmutableSet.of(treeArtifact));
jhorvitzbda125a2020-07-16 12:12:31 -0700363 handler.prepareForActionExecution();
Googler848c4ee2020-07-06 13:29:45 -0700364
365 RemoteFileArtifactValue value = new RemoteFileArtifactValue(new byte[] {1, 2, 3}, 5, 1);
366 handler.injectFile(output, value);
367
jhorvitz6c8f7b92020-07-15 15:02:29 -0700368 assertThat(handler.getOutputStore().getAllArtifactData()).containsExactly(output, value);
369 assertThat(handler.getOutputStore().getAllTreeArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700370 assertThat(chmodCalls).isEmpty();
Googler481bad32020-05-27 14:39:48 -0700371 }
372
373 @Test
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700374 public void injectRemoteTreeArtifactMetadata() throws Exception {
375 PathFragment path = PathFragment.create("bin/dir");
janakr3290e222019-05-29 16:34:22 -0700376 SpecialArtifact treeArtifact =
Googler1d8d1382020-05-18 12:10:49 -0700377 ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, path);
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700378 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700379 createHandler(
380 new ActionInputMap(0),
381 /*forInputDiscovery=*/ false,
382 /*outputs=*/ ImmutableSet.of(treeArtifact));
jhorvitzbda125a2020-07-16 12:12:31 -0700383 handler.prepareForActionExecution();
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700384
George Gensure3ef8fb92020-05-06 09:49:48 -0700385 RemoteFileArtifactValue fooValue =
386 new RemoteFileArtifactValue(new byte[] {1, 2, 3}, 5, 1, "foo");
387 RemoteFileArtifactValue barValue =
388 new RemoteFileArtifactValue(new byte[] {4, 5, 6}, 10, 1, "bar");
Googleref554462020-06-04 17:40:55 -0700389 Map<TreeFileArtifact, FileArtifactValue> children =
Googler04c546f2020-05-12 18:22:18 -0700390 ImmutableMap.of(
Googler1d8d1382020-05-18 12:10:49 -0700391 TreeFileArtifact.createTreeOutput(treeArtifact, "foo"), fooValue,
392 TreeFileArtifact.createTreeOutput(treeArtifact, "bar"), barValue);
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700393
Googleref554462020-06-04 17:40:55 -0700394 handler.injectDirectory(treeArtifact, children);
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700395
396 FileArtifactValue value = handler.getMetadata(treeArtifact);
397 assertThat(value).isNotNull();
jhorvitz6c8f7b92020-07-15 15:02:29 -0700398 TreeArtifactValue treeValue = handler.getOutputStore().getTreeArtifactData(treeArtifact);
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700399 assertThat(treeValue).isNotNull();
400 assertThat(treeValue.getDigest()).isEqualTo(value.getDigest());
jhorvitza68bdbb2020-07-13 16:49:20 -0700401 assertThat(chmodCalls).isEmpty();
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700402
403 assertThat(treeValue.getChildPaths())
404 .containsExactly(PathFragment.create("foo"), PathFragment.create("bar"));
405 assertThat(treeValue.getChildValues().values()).containsExactly(fooValue, barValue);
jhorvitzbda125a2020-07-16 12:12:31 -0700406 assertThat(handler.getTreeArtifactChildren(treeArtifact)).isEqualTo(treeValue.getChildren());
Googleraed41602020-06-02 12:22:53 -0700407
408 // Make sure that all children are transferred properly into the ActionExecutionValue. If any
409 // child is missing, getExistingFileArtifactValue will throw.
janakr84441232020-03-03 07:32:28 -0800410 ActionExecutionValue actionExecutionValue =
411 ActionExecutionValue.createFromOutputStore(handler.getOutputStore(), null, null, false);
Googleraed41602020-06-02 12:22:53 -0700412 treeValue.getChildren().forEach(actionExecutionValue::getExistingFileArtifactValue);
Jakob Buchgraber1407c042019-03-11 09:35:26 -0700413 }
Googler5284e6c2019-10-30 07:43:54 -0700414
415 @Test
416 public void getMetadataFromFilesetMapping() throws Exception {
417 FileArtifactValue directoryFav = FileArtifactValue.createForDirectoryWithMtime(10L);
418 FileArtifactValue regularFav =
419 FileArtifactValue.createForVirtualActionInput(new byte[] {1, 2, 3, 4}, 10L);
420 HasDigest.ByteStringDigest byteStringDigest = new ByteStringDigest(new byte[] {2, 3, 4});
421
Googlere9186eb2020-07-09 17:13:15 -0700422 ImmutableList<FilesetOutputSymlink> symlinks =
423 ImmutableList.of(
424 createFilesetOutputSymlink(directoryFav, "dir"),
425 createFilesetOutputSymlink(regularFav, "file"),
426 createFilesetOutputSymlink(byteStringDigest, "bytes"));
427
428 Artifact artifact =
429 ActionsTestUtil.createArtifactWithRootRelativePath(
430 outputRoot, PathFragment.create("foo/bar"));
jhorvitz6c8f7b92020-07-15 15:02:29 -0700431 ImmutableMap<Artifact, ImmutableList<FilesetOutputSymlink>> expandedFilesets =
Googlere9186eb2020-07-09 17:13:15 -0700432 ImmutableMap.of(artifact, symlinks);
Googler5284e6c2019-10-30 07:43:54 -0700433
434 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700435 ActionMetadataHandler.create(
Googler5284e6c2019-10-30 07:43:54 -0700436 new ActionInputMap(0),
jhorvitz6c8f7b92020-07-15 15:02:29 -0700437 /*forInputDiscovery=*/ false,
Googlere9186eb2020-07-09 17:13:15 -0700438 /*outputs=*/ ImmutableSet.of(),
439 tsgm,
jhorvitz6c8f7b92020-07-15 15:02:29 -0700440 ArtifactPathResolver.IDENTITY,
jhorvitzc69e2682020-07-16 07:16:28 -0700441 execRoot.asFragment(),
jhorvitz6c8f7b92020-07-15 15:02:29 -0700442 expandedFilesets);
Googler5284e6c2019-10-30 07:43:54 -0700443
Googlere9186eb2020-07-09 17:13:15 -0700444 // Only the regular FileArtifactValue should have its metadata stored.
445 assertThat(handler.getMetadata(createInput("dir"))).isNull();
446 assertThat(handler.getMetadata(createInput("file"))).isEqualTo(regularFav);
447 assertThat(handler.getMetadata(createInput("bytes"))).isNull();
448 assertThat(handler.getMetadata(createInput("does_not_exist"))).isNull();
jhorvitza68bdbb2020-07-13 16:49:20 -0700449 assertThat(chmodCalls).isEmpty();
Googlere9186eb2020-07-09 17:13:15 -0700450 }
451
452 private FilesetOutputSymlink createFilesetOutputSymlink(HasDigest digest, String identifier) {
453 return FilesetOutputSymlink.create(
454 PathFragment.create(identifier + "_symlink"),
455 PathFragment.create(identifier),
456 digest,
457 /*isGeneratedTarget=*/ true,
458 outputRoot.getExecPath());
459 }
460
461 private ActionInput createInput(String identifier) {
462 return ActionInputHelper.fromPath(outputRoot.getRoot().getRelative(identifier).getPathString());
Googler5284e6c2019-10-30 07:43:54 -0700463 }
464
Googler61a9f572020-06-02 10:28:24 -0700465 @Test
466 public void omitRegularArtifact() {
Googler61a9f572020-06-02 10:28:24 -0700467 Artifact omitted =
468 ActionsTestUtil.createArtifactWithRootRelativePath(
469 outputRoot, PathFragment.create("omitted"));
470 Artifact consumed =
471 ActionsTestUtil.createArtifactWithRootRelativePath(
472 outputRoot, PathFragment.create("consumed"));
473 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700474 createHandler(
475 new ActionInputMap(0),
476 /*forInputDiscovery=*/ false,
477 /*outputs=*/ ImmutableSet.of(omitted, consumed));
Googler61a9f572020-06-02 10:28:24 -0700478
jhorvitzbda125a2020-07-16 12:12:31 -0700479 handler.prepareForActionExecution();
Googler61a9f572020-06-02 10:28:24 -0700480 handler.markOmitted(omitted);
481
482 assertThat(handler.artifactOmitted(omitted)).isTrue();
483 assertThat(handler.artifactOmitted(consumed)).isFalse();
jhorvitz6c8f7b92020-07-15 15:02:29 -0700484 assertThat(handler.getOutputStore().getAllArtifactData())
Googler61a9f572020-06-02 10:28:24 -0700485 .containsExactly(omitted, FileArtifactValue.OMITTED_FILE_MARKER);
jhorvitz6c8f7b92020-07-15 15:02:29 -0700486 assertThat(handler.getOutputStore().getAllTreeArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700487 assertThat(chmodCalls).isEmpty();
Googler61a9f572020-06-02 10:28:24 -0700488 }
489
490 @Test
491 public void omitTreeArtifact() {
Googler61a9f572020-06-02 10:28:24 -0700492 SpecialArtifact omittedTree =
493 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
494 outputRoot, PathFragment.create("omitted"));
495 SpecialArtifact consumedTree =
496 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
497 outputRoot, PathFragment.create("consumed"));
498 ActionMetadataHandler handler =
jhorvitzc69e2682020-07-16 07:16:28 -0700499 createHandler(
jhorvitz6c8f7b92020-07-15 15:02:29 -0700500 new ActionInputMap(0),
501 /*forInputDiscovery=*/ false,
jhorvitzc69e2682020-07-16 07:16:28 -0700502 /*outputs=*/ ImmutableSet.of(omittedTree, consumedTree));
Googler61a9f572020-06-02 10:28:24 -0700503
jhorvitzbda125a2020-07-16 12:12:31 -0700504 handler.prepareForActionExecution();
Googler61a9f572020-06-02 10:28:24 -0700505 handler.markOmitted(omittedTree);
506 handler.markOmitted(omittedTree); // Marking a tree artifact as omitted twice is tolerated.
507
508 assertThat(handler.artifactOmitted(omittedTree)).isTrue();
509 assertThat(handler.artifactOmitted(consumedTree)).isFalse();
jhorvitz6c8f7b92020-07-15 15:02:29 -0700510 assertThat(handler.getOutputStore().getAllTreeArtifactData())
Googler61a9f572020-06-02 10:28:24 -0700511 .containsExactly(omittedTree, TreeArtifactValue.OMITTED_TREE_MARKER);
jhorvitz6c8f7b92020-07-15 15:02:29 -0700512 assertThat(handler.getOutputStore().getAllArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700513 assertThat(chmodCalls).isEmpty();
514 }
515
516 @Test
517 public void outputArtifactNotPreviouslyInjectedInExecutionMode() throws Exception {
518 Artifact output =
519 ActionsTestUtil.createArtifactWithRootRelativePath(
520 outputRoot, PathFragment.create("dir/file.out"));
521 Path outputPath = scratch.file(output.getPath().getPathString(), "contents");
jhorvitza68bdbb2020-07-13 16:49:20 -0700522 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700523 createHandler(
524 new ActionInputMap(0),
525 /*forInputDiscovery=*/ false,
526 /*outputs=*/ ImmutableSet.of(output));
jhorvitzbda125a2020-07-16 12:12:31 -0700527 handler.prepareForActionExecution();
jhorvitza68bdbb2020-07-13 16:49:20 -0700528
529 FileArtifactValue metadata = handler.getMetadata(output);
530
531 assertThat(metadata.getDigest()).isEqualTo(outputPath.getDigest());
jhorvitz6c8f7b92020-07-15 15:02:29 -0700532 assertThat(handler.getOutputStore().getAllArtifactData()).containsExactly(output, metadata);
533 assertThat(handler.getOutputStore().getAllTreeArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700534 assertThat(chmodCalls).containsExactly(outputPath);
535 }
536
537 @Test
538 public void outputTreeArtifactNotPreviouslyInjectedInExecutionMode() throws Exception {
539 SpecialArtifact treeArtifact =
540 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
541 outputRoot, PathFragment.create("bin/foo/bar"));
542 TreeFileArtifact child1 = TreeFileArtifact.createTreeOutput(treeArtifact, "child1");
543 TreeFileArtifact child2 = TreeFileArtifact.createTreeOutput(treeArtifact, "subdir/child2");
544 Path child1Path = scratch.file(child1.getPath().getPathString(), "contents1");
545 Path child2Path = scratch.file(child2.getPath().getPathString(), "contents2");
jhorvitza68bdbb2020-07-13 16:49:20 -0700546 ActionMetadataHandler handler =
jhorvitz6c8f7b92020-07-15 15:02:29 -0700547 createHandler(
548 new ActionInputMap(0),
549 /*forInputDiscovery=*/ false,
550 /*outputs=*/ ImmutableSet.of(treeArtifact));
jhorvitzbda125a2020-07-16 12:12:31 -0700551 handler.prepareForActionExecution();
jhorvitza68bdbb2020-07-13 16:49:20 -0700552
553 FileArtifactValue treeMetadata = handler.getMetadata(treeArtifact);
554 FileArtifactValue child1Metadata = handler.getMetadata(child1);
555 FileArtifactValue child2Metadata = handler.getMetadata(child2);
jhorvitz6c8f7b92020-07-15 15:02:29 -0700556 TreeArtifactValue tree = handler.getOutputStore().getTreeArtifactData(treeArtifact);
jhorvitza68bdbb2020-07-13 16:49:20 -0700557
558 assertThat(tree.getMetadata()).isEqualTo(treeMetadata);
559 assertThat(tree.getChildValues())
560 .containsExactly(child1, child1Metadata, child2, child2Metadata);
jhorvitzbda125a2020-07-16 12:12:31 -0700561 assertThat(handler.getTreeArtifactChildren(treeArtifact)).isEqualTo(tree.getChildren());
jhorvitz6c8f7b92020-07-15 15:02:29 -0700562 assertThat(handler.getOutputStore().getAllArtifactData()).isEmpty();
jhorvitza68bdbb2020-07-13 16:49:20 -0700563 assertThat(chmodCalls)
564 .containsExactly(
565 treeArtifact.getPath(), child1Path, child2Path, child2Path.getParentDirectory());
Googler61a9f572020-06-02 10:28:24 -0700566 }
jhorvitz6c8f7b92020-07-15 15:02:29 -0700567
568 @Test
569 public void transformAfterInputDiscovery() throws Exception {
570 Artifact known =
571 ActionsTestUtil.createArtifactWithRootRelativePath(
572 outputRoot, PathFragment.create("known"));
573 Artifact unknown =
574 ActionsTestUtil.createArtifactWithRootRelativePath(
575 outputRoot, PathFragment.create("unknown"));
576 ActionMetadataHandler handler =
577 createHandler(
578 new ActionInputMap(0),
579 /*forInputDiscovery=*/ true,
580 /*outputs=*/ ImmutableSet.of(known));
581
582 // Unknown artifact returns null during input discovery.
583 assertThat(handler.getMetadata(unknown)).isNull();
584
585 OutputStore newStore = new OutputStore();
586 FileArtifactValue knownMetadata = new RemoteFileArtifactValue(new byte[] {1, 2, 3}, 5, 1);
587 newStore.putArtifactData(known, knownMetadata);
588 ActionMetadataHandler newHandler = handler.transformAfterInputDiscovery(newStore);
589 assertThat(newHandler.getOutputStore()).isNotEqualTo(handler.getOutputStore());
590 assertThat(newHandler.getOutputStore()).isEqualTo(newStore);
591
592 assertThat(newHandler.getMetadata(known)).isEqualTo(knownMetadata);
593 // Unknown artifact throws outside of input discovery.
594 assertThrows(IllegalStateException.class, () -> newHandler.getMetadata(unknown));
595 // We can transform it again.
596 assertThat(newHandler.transformAfterInputDiscovery(new OutputStore())).isNotNull();
597 assertThat(chmodCalls).isEmpty();
598 }
jhorvitzbda125a2020-07-16 12:12:31 -0700599
600 @Test
601 public void getTreeArtifactChildren_noData_returnsEmptySet() {
602 SpecialArtifact treeArtifact =
603 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
604 outputRoot, PathFragment.create("bin/tree"));
605 ActionMetadataHandler handler =
606 createHandler(
607 new ActionInputMap(0),
608 /*forInputDiscovery=*/ false,
609 /*outputs=*/ ImmutableSet.of(treeArtifact));
610 assertThat(handler.getTreeArtifactChildren(treeArtifact)).isEmpty();
611 }
612
613 @Test
614 public void enteringExecutionModeClearsCachedOutputs() throws Exception {
615 Artifact artifact =
616 ActionsTestUtil.createArtifactWithRootRelativePath(
617 outputRoot, PathFragment.create("bin/output"));
618 SpecialArtifact treeArtifact =
619 ActionsTestUtil.createTreeArtifactWithGeneratingAction(
620 outputRoot, PathFragment.create("bin/tree"));
621 TreeFileArtifact child = TreeFileArtifact.createTreeOutput(treeArtifact, "child");
622 scratch.file(artifact.getPath().getPathString(), "1");
623 scratch.file(child.getPath().getPathString(), "1");
624 ActionMetadataHandler handler =
625 createHandler(
626 new ActionInputMap(0),
627 /*forInputDiscovery=*/ false,
628 /*outputs=*/ ImmutableSet.of(artifact, treeArtifact));
629 OutputStore store = handler.getOutputStore();
630
631 FileArtifactValue artifactMetadata1 = handler.getMetadata(artifact);
632 FileArtifactValue treeArtifactMetadata1 = handler.getMetadata(treeArtifact);
633 assertThat(artifactMetadata1).isNotNull();
634 assertThat(artifactMetadata1).isNotNull();
635 assertThat(store.getAllArtifactData().keySet()).containsExactly(artifact);
636 assertThat(store.getAllTreeArtifactData().keySet()).containsExactly(treeArtifact);
637
638 // Entering execution mode should clear the cached outputs.
639 handler.prepareForActionExecution();
640 assertThat(store.getAllArtifactData()).isEmpty();
641 assertThat(store.getAllTreeArtifactData()).isEmpty();
642
643 // Updated metadata should be read from the filesystem.
644 scratch.overwriteFile(artifact.getPath().getPathString(), "2");
645 scratch.overwriteFile(child.getPath().getPathString(), "2");
646 FileArtifactValue artifactMetadata2 = handler.getMetadata(artifact);
647 FileArtifactValue treeArtifactMetadata2 = handler.getMetadata(treeArtifact);
648 assertThat(artifactMetadata2).isNotNull();
649 assertThat(treeArtifactMetadata2).isNotNull();
650 assertThat(artifactMetadata2).isNotEqualTo(artifactMetadata1);
651 assertThat(treeArtifactMetadata2).isNotEqualTo(treeArtifactMetadata1);
652 }
653
654 @Test
655 public void cannotEnterExecutionModeTwice() {
656 ActionMetadataHandler handler =
657 createHandler(
658 new ActionInputMap(0), /*forInputDiscovery=*/ false, /*outputs=*/ ImmutableSet.of());
659 handler.prepareForActionExecution();
660 assertThrows(IllegalStateException.class, handler::prepareForActionExecution);
661 }
662
663 @Test
664 public void fileArtifactValueFromArtifactCompatibleWithGetMetadata_changed() throws Exception {
665 Artifact artifact =
666 ActionsTestUtil.createArtifactWithRootRelativePath(
667 outputRoot, PathFragment.create("bin/output"));
668 scratch.file(artifact.getPath().getPathString(), "1");
669 ActionMetadataHandler handler =
670 createHandler(
671 new ActionInputMap(0),
672 /*forInputDiscovery=*/ false,
673 /*outputs=*/ ImmutableSet.of(artifact));
674
675 FileArtifactValue getMetadataResult = handler.getMetadata(artifact);
676 assertThat(getMetadataResult).isNotNull();
677
678 scratch.overwriteFile(artifact.getPath().getPathString(), "2");
679 FileArtifactValue fileArtifactValueFromArtifactResult =
680 ActionMetadataHandler.fileArtifactValueFromArtifact(
681 artifact, /*statNoFollow=*/ null, /*tsgm=*/ null);
682 assertThat(fileArtifactValueFromArtifactResult).isNotNull();
683
684 assertThat(fileArtifactValueFromArtifactResult.couldBeModifiedSince(getMetadataResult))
685 .isTrue();
686 }
687
688 @Test
689 public void fileArtifactValueFromArtifactCompatibleWithGetMetadata_notChanged() throws Exception {
690 Artifact artifact =
691 ActionsTestUtil.createArtifactWithRootRelativePath(
692 outputRoot, PathFragment.create("bin/output"));
693 scratch.file(artifact.getPath().getPathString(), "contents");
694 ActionMetadataHandler handler =
695 createHandler(
696 new ActionInputMap(0),
697 /*forInputDiscovery=*/ false,
698 /*outputs=*/ ImmutableSet.of(artifact));
699
700 FileArtifactValue getMetadataResult = handler.getMetadata(artifact);
701 assertThat(getMetadataResult).isNotNull();
702
703 FileArtifactValue fileArtifactValueFromArtifactResult =
704 ActionMetadataHandler.fileArtifactValueFromArtifact(
705 artifact, /*statNoFollow=*/ null, /*tsgm=*/ null);
706 assertThat(fileArtifactValueFromArtifactResult).isNotNull();
707
708 assertThat(fileArtifactValueFromArtifactResult.couldBeModifiedSince(getMetadataResult))
709 .isFalse();
710 }
ulfjackf2b260c2018-09-28 05:09:32 -0700711}