blob: 7d4f3c76cdd7e35dd1813fde06a6f2e2dc9e84b8 [file] [log] [blame]
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +00001// Copyright 2015 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;
Janak Ramakrishnana5578af2017-03-21 17:28:39 +000015
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000016import static com.google.common.truth.Truth.assertThat;
shahan602cc852018-06-06 20:09:57 -070017import static com.google.devtools.build.lib.actions.FileArtifactValue.create;
jcater83130f42019-04-30 14:29:28 -070018import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000019
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000020import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableMap;
22import com.google.common.collect.ImmutableSet;
23import com.google.common.collect.Iterables;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000024import com.google.devtools.build.lib.actions.Action;
Rumou Duan33bab462016-04-25 17:55:12 +000025import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
Rumou Duan73876202016-06-06 18:52:08 +000026import com.google.devtools.build.lib.actions.ActionInputHelper;
janakr93e3eea2017-03-30 22:09:37 +000027import com.google.devtools.build.lib.actions.ActionLookupData;
28import com.google.devtools.build.lib.actions.ActionLookupValue;
janakr0175ce32018-02-26 15:54:57 -080029import com.google.devtools.build.lib.actions.Actions;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000030import com.google.devtools.build.lib.actions.Artifact;
Rumou Duan73876202016-06-06 18:52:08 +000031import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
32import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
33import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
janakr0c42fc82018-09-14 10:37:25 -070034import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
tomlu1cdcdf92018-01-16 11:07:51 -080035import com.google.devtools.build.lib.actions.ArtifactRoot;
shahane35e8cf2018-06-18 08:14:01 -070036import com.google.devtools.build.lib.actions.ArtifactSkyKey;
cparsonse2d200f2018-03-06 16:15:11 -080037import com.google.devtools.build.lib.actions.BasicActionLookupValue;
shahan602cc852018-06-06 20:09:57 -070038import com.google.devtools.build.lib.actions.FileArtifactValue;
janakre82933c2019-01-02 14:41:50 -080039import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000040import com.google.devtools.build.lib.actions.MissingInputFileException;
janakr0175ce32018-02-26 15:54:57 -080041import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
Rumou Duan73876202016-06-06 18:52:08 +000042import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000043import com.google.devtools.build.lib.actions.util.TestAction.DummyAction;
44import com.google.devtools.build.lib.events.NullEventHandler;
janakre82933c2019-01-02 14:41:50 -080045import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000046import com.google.devtools.build.lib.util.Pair;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000047import com.google.devtools.build.lib.vfs.FileStatus;
janakre82933c2019-01-02 14:41:50 -080048import com.google.devtools.build.lib.vfs.FileSystem;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000049import com.google.devtools.build.lib.vfs.FileSystemUtils;
50import com.google.devtools.build.lib.vfs.Path;
51import com.google.devtools.build.lib.vfs.PathFragment;
tomluee6a6862018-01-17 14:36:26 -080052import com.google.devtools.build.lib.vfs.Root;
Googler10028672018-10-25 12:14:34 -070053import com.google.devtools.build.skyframe.EvaluationContext;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000054import com.google.devtools.build.skyframe.EvaluationResult;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000055import com.google.devtools.build.skyframe.SkyFunction;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000056import com.google.devtools.build.skyframe.SkyKey;
57import com.google.devtools.build.skyframe.SkyValue;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000058import java.io.IOException;
Michajlo Matijkiw528957e2016-01-19 21:17:45 +000059import java.nio.charset.StandardCharsets;
60import java.security.MessageDigest;
buchgrd4d3d502018-08-02 06:47:19 -070061import java.util.ArrayList;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000062import java.util.Arrays;
63import java.util.HashMap;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000064import java.util.Map;
Janak Ramakrishnanad77f972016-07-29 20:58:42 +000065import org.junit.Before;
66import org.junit.Test;
67import org.junit.runner.RunWith;
68import org.junit.runners.JUnit4;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000069
70/**
71 * Tests for {@link ArtifactFunction}.
72 */
73// Doesn't actually need any particular Skyframe, but is only relevant to Skyframe full mode.
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000074@RunWith(JUnit4.class)
Michael Thvedt8d5a7bb2016-02-09 03:06:34 +000075public class ArtifactFunctionTest extends ArtifactFunctionTestCase {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000076
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000077 @Before
Florian Weikert92b22362015-12-03 10:17:18 +000078 public final void setUp() throws Exception {
Michael Thvedt8d5a7bb2016-02-09 03:06:34 +000079 delegateActionExecutionFunction = new SimpleActionExecutionFunction();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000080 }
81
82 private void assertFileArtifactValueMatches(boolean expectDigest) throws Throwable {
83 Artifact output = createDerivedArtifact("output");
84 Path path = output.getPath();
85 file(path, "contents");
olaolabfd1d332017-06-19 16:55:24 -040086 assertValueMatches(path.stat(), expectDigest ? path.getDigest() : null, evaluateFAN(output));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000087 }
88
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000089 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000090 public void testBasicArtifact() throws Throwable {
91 fastDigest = false;
92 assertFileArtifactValueMatches(/*expectDigest=*/ true);
93 }
94
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000095 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000096 public void testBasicArtifactWithXattr() throws Throwable {
97 fastDigest = true;
98 assertFileArtifactValueMatches(/*expectDigest=*/ true);
99 }
100
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000101 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000102 public void testMissingNonMandatoryArtifact() throws Throwable {
103 Artifact input = createSourceArtifact("input1");
lberkie355e772017-05-31 14:34:53 +0200104 assertThat(evaluateArtifactValue(input, /*mandatory=*/ false)).isNotNull();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000105 }
106
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000107 @Test
Michajlo Matijkiw528957e2016-01-19 21:17:45 +0000108 public void testUnreadableInputWithFsWithAvailableDigest() throws Throwable {
109 final byte[] expectedDigest = MessageDigest.getInstance("md5").digest(
110 "someunreadablecontent".getBytes(StandardCharsets.UTF_8));
111 setupRoot(
112 new CustomInMemoryFs() {
113 @Override
ccalvarindd9f60e2018-07-23 18:16:18 -0700114 public byte[] getDigest(Path path) throws IOException {
115 return path.getBaseName().equals("unreadable") ? expectedDigest : super.getDigest(path);
Michajlo Matijkiw528957e2016-01-19 21:17:45 +0000116 }
117 });
118
119 Artifact input = createSourceArtifact("unreadable");
120 Path inputPath = input.getPath();
121 file(inputPath, "dummynotused");
122 inputPath.chmod(0);
123
124 FileArtifactValue value =
125 (FileArtifactValue) evaluateArtifactValue(input, /*mandatory=*/ true);
126
127 FileStatus stat = inputPath.stat();
128 assertThat(value.getSize()).isEqualTo(stat.getSize());
129 assertThat(value.getDigest()).isEqualTo(expectedDigest);
130 }
131
132 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000133 public void testMissingMandatoryArtifact() throws Throwable {
134 Artifact input = createSourceArtifact("input1");
jcater83130f42019-04-30 14:29:28 -0700135 assertThrows(
136 MissingInputFileException.class, () -> evaluateArtifactValue(input, /*mandatory=*/ true));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000137 }
138
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000139 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000140 public void testMiddlemanArtifact() throws Throwable {
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000141 Artifact output = createMiddlemanArtifact("output");
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000142 Artifact input1 = createSourceArtifact("input1");
143 Artifact input2 = createDerivedArtifact("input2");
Benjamin Peterson63748e42018-06-03 22:11:16 -0700144 SpecialArtifact tree = createDerivedTreeArtifactWithAction("treeArtifact");
buchgrd4d3d502018-08-02 06:47:19 -0700145 TreeFileArtifact treeFile1 = createFakeTreeFileArtifact(tree, "child1", "hello1");
146 TreeFileArtifact treeFile2 = createFakeTreeFileArtifact(tree, "child2", "hello2");
147 file(treeFile1.getPath(), "src1");
148 file(treeFile2.getPath(), "src2");
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000149 Action action =
150 new DummyAction(
Benjamin Peterson63748e42018-06-03 22:11:16 -0700151 ImmutableList.of(input1, input2, tree), output, MiddlemanType.AGGREGATING_MIDDLEMAN);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000152 actions.add(action);
153 file(input2.getPath(), "contents");
154 file(input1.getPath(), "source contents");
janakr8541f6d2019-06-11 14:40:21 -0700155 evaluate(
156 Iterables.toArray(
157 ArtifactSkyKey.mandatoryKeys(ImmutableSet.of(input2, input1, input2, tree)),
158 SkyKey.class));
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000159 SkyValue value = evaluateArtifactValue(output);
buchgrd4d3d502018-08-02 06:47:19 -0700160 ArrayList<Pair<Artifact, ?>> inputs = new ArrayList<>();
161 inputs.addAll(((AggregatingArtifactValue) value).getFileArtifacts());
162 inputs.addAll(((AggregatingArtifactValue) value).getTreeArtifacts());
163 assertThat(inputs)
Benjamin Peterson63748e42018-06-03 22:11:16 -0700164 .containsExactly(
165 Pair.of(input1, create(input1)),
166 Pair.of(input2, create(input2)),
buchgrd4d3d502018-08-02 06:47:19 -0700167 Pair.of(tree, ((TreeArtifactValue) evaluateArtifactValue(tree))));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000168 }
169
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000170 /**
171 * Tests that ArtifactFunction rethrows transitive {@link IOException}s as
172 * {@link MissingInputFileException}s.
173 */
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000174 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000175 public void testIOException_EndToEnd() throws Throwable {
176 final IOException exception = new IOException("beep");
177 setupRoot(
178 new CustomInMemoryFs() {
179 @Override
fellya205ed82018-09-10 11:52:34 -0700180 public FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000181 if (path.getBaseName().equals("bad")) {
182 throw exception;
183 }
fellya205ed82018-09-10 11:52:34 -0700184 return super.statIfFound(path, followSymlinks);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000185 }
186 });
jcater83130f42019-04-30 14:29:28 -0700187 MissingInputFileException e =
188 assertThrows(
189 MissingInputFileException.class,
190 () -> evaluateArtifactValue(createSourceArtifact("bad")));
191 assertThat(e).hasMessageThat().contains(exception.getMessage());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000192 }
193
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000194 @Test
Rumou Duan73876202016-06-06 18:52:08 +0000195 public void testActionTreeArtifactOutput() throws Throwable {
cpeyserac09f0a2018-02-05 09:33:15 -0800196 SpecialArtifact artifact = createDerivedTreeArtifactWithAction("treeArtifact");
janakrefb3f152019-06-05 17:42:34 -0700197 TreeFileArtifact treeFileArtifact1 = createFakeTreeFileArtifact(artifact, "child1", "hello1");
198 TreeFileArtifact treeFileArtifact2 = createFakeTreeFileArtifact(artifact, "child2", "hello2");
Rumou Duan73876202016-06-06 18:52:08 +0000199
200 TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact);
janakr45b308a2018-06-08 12:51:58 -0700201 assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
202 assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
lberkiaea56b32017-05-30 12:35:33 +0200203 assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
204 assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
Rumou Duan73876202016-06-06 18:52:08 +0000205 }
206
207 @Test
208 public void testSpawnActionTemplate() throws Throwable {
209 // artifact1 is a tree artifact generated by normal action.
cpeyserac09f0a2018-02-05 09:33:15 -0800210 SpecialArtifact artifact1 = createDerivedTreeArtifactWithAction("treeArtifact1");
Rumou Duan73876202016-06-06 18:52:08 +0000211 createFakeTreeFileArtifact(artifact1, "child1", "hello1");
212 createFakeTreeFileArtifact(artifact1, "child2", "hello2");
213
Rumou Duan73876202016-06-06 18:52:08 +0000214 // artifact2 is a tree artifact generated by action template.
cpeyserac09f0a2018-02-05 09:33:15 -0800215 SpecialArtifact artifact2 = createDerivedTreeArtifactOnly("treeArtifact2");
janakr45b308a2018-06-08 12:51:58 -0700216 TreeFileArtifact treeFileArtifact1 =
217 createFakeTreeFileArtifact(
218 artifact2,
janakr45b308a2018-06-08 12:51:58 -0700219 "child1",
220 "hello1");
221 TreeFileArtifact treeFileArtifact2 =
222 createFakeTreeFileArtifact(
223 artifact2,
janakr45b308a2018-06-08 12:51:58 -0700224 "child2",
225 "hello2");
Rumou Duan73876202016-06-06 18:52:08 +0000226
227 actions.add(
228 ActionsTestUtil.createDummySpawnActionTemplate(artifact1, artifact2));
229
230 TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact2);
janakr45b308a2018-06-08 12:51:58 -0700231 assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
232 assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
lberkiaea56b32017-05-30 12:35:33 +0200233 assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
234 assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
Rumou Duan73876202016-06-06 18:52:08 +0000235 }
236
237 @Test
238 public void testConsecutiveSpawnActionTemplates() throws Throwable {
239 // artifact1 is a tree artifact generated by normal action.
cpeyserac09f0a2018-02-05 09:33:15 -0800240 SpecialArtifact artifact1 = createDerivedTreeArtifactWithAction("treeArtifact1");
Rumou Duan73876202016-06-06 18:52:08 +0000241 createFakeTreeFileArtifact(artifact1, "child1", "hello1");
242 createFakeTreeFileArtifact(artifact1, "child2", "hello2");
243
244 // artifact2 is a tree artifact generated by action template.
cpeyserac09f0a2018-02-05 09:33:15 -0800245 SpecialArtifact artifact2 = createDerivedTreeArtifactOnly("treeArtifact2");
Rumou Duan73876202016-06-06 18:52:08 +0000246 createFakeTreeFileArtifact(artifact2, "child1", "hello1");
247 createFakeTreeFileArtifact(artifact2, "child2", "hello2");
248 actions.add(
249 ActionsTestUtil.createDummySpawnActionTemplate(artifact1, artifact2));
250
251 // artifact3 is a tree artifact generated by action template.
cpeyserac09f0a2018-02-05 09:33:15 -0800252 SpecialArtifact artifact3 = createDerivedTreeArtifactOnly("treeArtifact3");
janakr45b308a2018-06-08 12:51:58 -0700253 TreeFileArtifact treeFileArtifact1 =
254 createFakeTreeFileArtifact(
255 artifact3,
janakr45b308a2018-06-08 12:51:58 -0700256 "child1",
257 "hello1");
258 TreeFileArtifact treeFileArtifact2 =
259 createFakeTreeFileArtifact(
260 artifact3,
janakr45b308a2018-06-08 12:51:58 -0700261 "child2",
262 "hello2");
Rumou Duan73876202016-06-06 18:52:08 +0000263 actions.add(
264 ActionsTestUtil.createDummySpawnActionTemplate(artifact2, artifact3));
265
266 TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact3);
janakr45b308a2018-06-08 12:51:58 -0700267 assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
268 assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
lberkiaea56b32017-05-30 12:35:33 +0200269 assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
270 assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
Rumou Duan73876202016-06-06 18:52:08 +0000271 }
272
janakre82933c2019-01-02 14:41:50 -0800273 @Test
274 public void actionExecutionValueSerialization() throws Exception {
janakrefb3f152019-06-05 17:42:34 -0700275 ActionLookupData dummyData = ActionLookupData.create(ALL_OWNER, 0);
276 Artifact.DerivedArtifact artifact1 = createDerivedArtifact("one");
janakrefb3f152019-06-05 17:42:34 -0700277 Artifact.DerivedArtifact artifact2 = createDerivedArtifact("two");
janakre82933c2019-01-02 14:41:50 -0800278 ArtifactFileMetadata metadata1 =
279 ActionMetadataHandler.fileMetadataFromArtifact(artifact1, null, null);
280 SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly("tree");
janakrefb3f152019-06-05 17:42:34 -0700281 treeArtifact.setGeneratingActionKey(dummyData);
282 TreeFileArtifact treeFileArtifact = ActionInputHelper.treeFileArtifact(treeArtifact, "subpath");
283 Path path = treeFileArtifact.getPath();
284 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
285 writeFile(path, "contents");
janakre82933c2019-01-02 14:41:50 -0800286 TreeArtifactValue treeArtifactValue =
287 TreeArtifactValue.create(
288 ImmutableMap.of(treeFileArtifact, FileArtifactValue.create(treeFileArtifact)));
janakrefb3f152019-06-05 17:42:34 -0700289 Artifact.DerivedArtifact artifact3 = createDerivedArtifact("three");
janakre82933c2019-01-02 14:41:50 -0800290 FilesetOutputSymlink filesetOutputSymlink =
291 FilesetOutputSymlink.createForTesting(
292 PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT);
293 ActionExecutionValue actionExecutionValue =
294 ActionExecutionValue.create(
295 ImmutableMap.of(artifact1, metadata1, artifact2, ArtifactFileMetadata.PLACEHOLDER),
296 ImmutableMap.of(treeArtifact, treeArtifactValue),
297 ImmutableMap.of(artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
298 ImmutableList.of(filesetOutputSymlink),
299 null,
300 true);
301 ActionExecutionValue valueWithFingerprint =
302 ActionExecutionValue.create(
303 ImmutableMap.of(artifact1, metadata1, artifact2, ArtifactFileMetadata.PLACEHOLDER),
304 ImmutableMap.of(treeArtifact, treeArtifactValue),
305 ImmutableMap.of(artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
306 ImmutableList.of(filesetOutputSymlink),
307 null,
308 true);
309 valueWithFingerprint.getValueFingerprint();
310 new SerializationTester(actionExecutionValue, valueWithFingerprint)
311 .addDependency(FileSystem.class, root.getFileSystem())
312 .runTests();
313 }
314
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000315 private void file(Path path, String contents) throws Exception {
316 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
317 writeFile(path, contents);
318 }
319
320 private Artifact createSourceArtifact(String path) {
janakraea05602019-05-22 15:41:29 -0700321 return ActionsTestUtil.createArtifactWithExecPath(
322 ArtifactRoot.asSourceRoot(Root.fromPath(root)), PathFragment.create(path));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000323 }
324
janakrefb3f152019-06-05 17:42:34 -0700325 private Artifact.DerivedArtifact createDerivedArtifact(String path) {
nharmatab4060b62017-04-04 17:11:39 +0000326 PathFragment execPath = PathFragment.create("out").getRelative(path);
janakrefb3f152019-06-05 17:42:34 -0700327 Artifact.DerivedArtifact output =
janakraea05602019-05-22 15:41:29 -0700328 new Artifact.DerivedArtifact(
janakr3290e222019-05-29 16:34:22 -0700329 ArtifactRoot.asDerivedRoot(root, root.getRelative("out")), execPath, ALL_OWNER);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000330 actions.add(new DummyAction(ImmutableList.<Artifact>of(), output));
janakr8541f6d2019-06-11 14:40:21 -0700331 output.setGeneratingActionKey(ActionLookupData.create(ALL_OWNER, actions.size() - 1));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000332 return output;
333 }
334
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000335 private Artifact createMiddlemanArtifact(String path) {
tomlu1cdcdf92018-01-16 11:07:51 -0800336 ArtifactRoot middlemanRoot =
337 ArtifactRoot.middlemanRoot(middlemanPath, middlemanPath.getRelative("out"));
janakraea05602019-05-22 15:41:29 -0700338 return new Artifact.DerivedArtifact(
janakr3290e222019-05-29 16:34:22 -0700339 middlemanRoot, middlemanRoot.getExecPath().getRelative(path), ALL_OWNER);
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000340 }
341
cpeyserac09f0a2018-02-05 09:33:15 -0800342 private SpecialArtifact createDerivedTreeArtifactWithAction(String path) {
343 SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly(path);
Rumou Duan73876202016-06-06 18:52:08 +0000344 actions.add(new DummyAction(ImmutableList.<Artifact>of(), treeArtifact));
345 return treeArtifact;
346 }
347
cpeyserac09f0a2018-02-05 09:33:15 -0800348 private SpecialArtifact createDerivedTreeArtifactOnly(String path) {
nharmatab4060b62017-04-04 17:11:39 +0000349 PathFragment execPath = PathFragment.create("out").getRelative(path);
Rumou Duan73876202016-06-06 18:52:08 +0000350 return new SpecialArtifact(
tomlu1cdcdf92018-01-16 11:07:51 -0800351 ArtifactRoot.asDerivedRoot(root, root.getRelative("out")),
Rumou Duan73876202016-06-06 18:52:08 +0000352 execPath,
janakr3290e222019-05-29 16:34:22 -0700353 ALL_OWNER,
Rumou Duan73876202016-06-06 18:52:08 +0000354 SpecialArtifactType.TREE);
355 }
356
cpeyserac09f0a2018-02-05 09:33:15 -0800357 private TreeFileArtifact createFakeTreeFileArtifact(
janakr45b308a2018-06-08 12:51:58 -0700358 SpecialArtifact treeArtifact,
janakr45b308a2018-06-08 12:51:58 -0700359 String parentRelativePath,
360 String content)
361 throws Exception {
362 TreeFileArtifact treeFileArtifact =
janakrefb3f152019-06-05 17:42:34 -0700363 ActionsTestUtil.createTreeFileArtifactWithNoGeneratingAction(
364 treeArtifact, parentRelativePath);
Rumou Duan73876202016-06-06 18:52:08 +0000365 Path path = treeFileArtifact.getPath();
366 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
367 writeFile(path, content);
368 return treeFileArtifact;
369 }
370
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000371 private void assertValueMatches(FileStatus file, byte[] digest, FileArtifactValue value)
372 throws IOException {
lberkiaea56b32017-05-30 12:35:33 +0200373 assertThat(value.getSize()).isEqualTo(file.getSize());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000374 if (digest == null) {
lberkiaea56b32017-05-30 12:35:33 +0200375 assertThat(value.getDigest()).isNull();
376 assertThat(value.getModifiedTime()).isEqualTo(file.getLastModifiedTime());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000377 } else {
lberkiaea56b32017-05-30 12:35:33 +0200378 assertThat(value.getDigest()).isEqualTo(digest);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000379 }
380 }
381
382 private FileArtifactValue evaluateFAN(Artifact artifact) throws Throwable {
383 return ((FileArtifactValue) evaluateArtifactValue(artifact));
384 }
385
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000386 private SkyValue evaluateArtifactValue(Artifact artifact) throws Throwable {
cushon03e70182017-09-15 09:33:27 +0200387 return evaluateArtifactValue(artifact, /* mandatory= */ true);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000388 }
389
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000390 private SkyValue evaluateArtifactValue(Artifact artifact, boolean mandatory) throws Throwable {
391 SkyKey key = ArtifactSkyKey.key(artifact, mandatory);
392 EvaluationResult<SkyValue> result = evaluate(ImmutableList.of(key).toArray(new SkyKey[0]));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000393 if (result.hasError()) {
394 throw result.getError().getException();
395 }
janakr8541f6d2019-06-11 14:40:21 -0700396 SkyValue value = result.get(key);
397 if (value instanceof ActionExecutionValue) {
398 return ArtifactFunction.createSimpleFileArtifactValue(
399 (Artifact.DerivedArtifact) artifact, (ActionExecutionValue) value);
400 }
401 return value;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000402 }
403
janakr0175ce32018-02-26 15:54:57 -0800404 private void setGeneratingActions() throws InterruptedException, ActionConflictException {
janakr573807d2018-01-11 14:02:35 -0800405 if (evaluator.getExistingValue(ALL_OWNER) == null) {
janakr93e3eea2017-03-30 22:09:37 +0000406 differencer.inject(
407 ImmutableMap.of(
janakr573807d2018-01-11 14:02:35 -0800408 ALL_OWNER,
cparsonse2d200f2018-03-06 16:15:11 -0800409 new BasicActionLookupValue(
janakrefb3f152019-06-05 17:42:34 -0700410 Actions.assignOwnersAndFilterSharedActionsAndThrowActionConflict(
411 actionKeyContext,
412 ImmutableList.copyOf(actions),
413 ALL_OWNER,
414 /*outputFiles=*/ null),
janakra81bb952019-01-28 17:30:06 -0800415 /*nonceVersion=*/ null)));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000416 }
417 }
418
419 private <E extends SkyValue> EvaluationResult<E> evaluate(SkyKey... keys)
janakr0175ce32018-02-26 15:54:57 -0800420 throws InterruptedException, ActionConflictException {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000421 setGeneratingActions();
Googler10028672018-10-25 12:14:34 -0700422 EvaluationContext evaluationContext =
423 EvaluationContext.newBuilder()
424 .setKeepGoing(false)
425 .setNumThreads(SkyframeExecutor.DEFAULT_THREAD_COUNT)
426 .setEventHander(NullEventHandler.INSTANCE)
427 .build();
428 return driver.evaluate(Arrays.asList(keys), evaluationContext);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000429 }
430
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000431 /** Value Builder for actions that just stats and stores the output file (which must exist). */
Rumou Duan73876202016-06-06 18:52:08 +0000432 private static class SimpleActionExecutionFunction implements SkyFunction {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000433 @Override
janakr93e3eea2017-03-30 22:09:37 +0000434 public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
janakr0c42fc82018-09-14 10:37:25 -0700435 Map<Artifact, ArtifactFileMetadata> artifactData = new HashMap<>();
Rumou Duan73876202016-06-06 18:52:08 +0000436 Map<Artifact, TreeArtifactValue> treeArtifactData = new HashMap<>();
437 Map<Artifact, FileArtifactValue> additionalOutputData = new HashMap<>();
janakr93e3eea2017-03-30 22:09:37 +0000438 ActionLookupData actionLookupData = (ActionLookupData) skyKey.argument();
439 ActionLookupValue actionLookupValue =
janakrbaf52ae2018-02-14 09:03:18 -0800440 (ActionLookupValue) env.getValue(actionLookupData.getActionLookupKey());
janakr93e3eea2017-03-30 22:09:37 +0000441 Action action = actionLookupValue.getAction(actionLookupData.getActionIndex());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000442 Artifact output = Iterables.getOnlyElement(action.getOutputs());
Rumou Duan73876202016-06-06 18:52:08 +0000443
444 try {
445 if (output.isTreeArtifact()) {
446 TreeFileArtifact treeFileArtifact1 = ActionInputHelper.treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800447 (SpecialArtifact) output, PathFragment.create("child1"));
Rumou Duan73876202016-06-06 18:52:08 +0000448 TreeFileArtifact treeFileArtifact2 = ActionInputHelper.treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800449 (SpecialArtifact) output, PathFragment.create("child2"));
Rumou Duan73876202016-06-06 18:52:08 +0000450 TreeArtifactValue treeArtifactValue = TreeArtifactValue.create(ImmutableMap.of(
451 treeFileArtifact1, FileArtifactValue.create(treeFileArtifact1),
452 treeFileArtifact2, FileArtifactValue.create(treeFileArtifact2)));
453 treeArtifactData.put(output, treeArtifactValue);
454 } else if (action.getActionType() == MiddlemanType.NORMAL) {
janakr0c42fc82018-09-14 10:37:25 -0700455 ArtifactFileMetadata fileValue =
456 ActionMetadataHandler.fileMetadataFromArtifact(output, null, null);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000457 artifactData.put(output, fileValue);
Rumou Duan73876202016-06-06 18:52:08 +0000458 additionalOutputData.put(output, FileArtifactValue.create(output, fileValue));
459 } else {
460 additionalOutputData.put(output, FileArtifactValue.DEFAULT_MIDDLEMAN);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000461 }
Rumou Duan73876202016-06-06 18:52:08 +0000462 } catch (IOException e) {
463 throw new IllegalStateException(e);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000464 }
janakrb9d8d582018-06-13 21:57:19 -0700465 return ActionExecutionValue.create(
466 artifactData,
467 treeArtifactData,
468 additionalOutputData,
469 /*outputSymlinks=*/ null,
shahanef6f4cf2018-06-26 11:24:59 -0700470 /*discoveredModules=*/ null,
janakr9f496f32018-10-24 15:08:09 -0700471 /*actionDependsOnBuildId=*/ false);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000472 }
473
474 @Override
475 public String extractTag(SkyKey skyKey) {
476 return null;
477 }
478 }
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000479}