blob: b96d5c1ed171025dec2c805520580896e00b049a [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;
lberki812e6fe2019-07-25 07:50:55 -070017import static com.google.devtools.build.lib.actions.FileArtifactValue.createForTesting;
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;
tomlu1cdcdf92018-01-16 11:07:51 -080034import com.google.devtools.build.lib.actions.ArtifactRoot;
cparsonse2d200f2018-03-06 16:15:11 -080035import com.google.devtools.build.lib.actions.BasicActionLookupValue;
shahan602cc852018-06-06 20:09:57 -070036import com.google.devtools.build.lib.actions.FileArtifactValue;
janakre82933c2019-01-02 14:41:50 -080037import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000038import com.google.devtools.build.lib.actions.MissingInputFileException;
janakr0175ce32018-02-26 15:54:57 -080039import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
Rumou Duan73876202016-06-06 18:52:08 +000040import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000041import com.google.devtools.build.lib.actions.util.TestAction.DummyAction;
ulfjack1e1a7752019-12-10 21:17:58 -080042import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
43import com.google.devtools.build.lib.collect.nestedset.Order;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000044import 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;
lberkif225af12019-08-01 04:21:58 -070048import com.google.devtools.build.lib.vfs.FileStatusWithDigestAdapter;
janakre82933c2019-01-02 14:41:50 -080049import com.google.devtools.build.lib.vfs.FileSystem;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000050import com.google.devtools.build.lib.vfs.FileSystemUtils;
51import com.google.devtools.build.lib.vfs.Path;
52import com.google.devtools.build.lib.vfs.PathFragment;
tomluee6a6862018-01-17 14:36:26 -080053import com.google.devtools.build.lib.vfs.Root;
lberkif225af12019-08-01 04:21:58 -070054import com.google.devtools.build.lib.vfs.Symlinks;
Googler10028672018-10-25 12:14:34 -070055import com.google.devtools.build.skyframe.EvaluationContext;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000056import com.google.devtools.build.skyframe.EvaluationResult;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000057import com.google.devtools.build.skyframe.SkyFunction;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000058import com.google.devtools.build.skyframe.SkyKey;
59import com.google.devtools.build.skyframe.SkyValue;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000060import java.io.IOException;
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");
lberki36df7ed2019-06-27 06:32:03 -0700104 assertThat(evaluateArtifactValue(input)).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 {
Googlere764d562019-10-16 10:56:33 -0700109 final byte[] expectedDigest = {1, 2, 3, 4};
Michajlo Matijkiw528957e2016-01-19 21:17:45 +0000110 setupRoot(
111 new CustomInMemoryFs() {
112 @Override
ccalvarindd9f60e2018-07-23 18:16:18 -0700113 public byte[] getDigest(Path path) throws IOException {
114 return path.getBaseName().equals("unreadable") ? expectedDigest : super.getDigest(path);
Michajlo Matijkiw528957e2016-01-19 21:17:45 +0000115 }
116 });
117
118 Artifact input = createSourceArtifact("unreadable");
119 Path inputPath = input.getPath();
120 file(inputPath, "dummynotused");
121 inputPath.chmod(0);
122
lberki36df7ed2019-06-27 06:32:03 -0700123 FileArtifactValue value = (FileArtifactValue) evaluateArtifactValue(input);
Michajlo Matijkiw528957e2016-01-19 21:17:45 +0000124
125 FileStatus stat = inputPath.stat();
126 assertThat(value.getSize()).isEqualTo(stat.getSize());
127 assertThat(value.getDigest()).isEqualTo(expectedDigest);
128 }
129
130 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000131 public void testMiddlemanArtifact() throws Throwable {
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000132 Artifact output = createMiddlemanArtifact("output");
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000133 Artifact input1 = createSourceArtifact("input1");
134 Artifact input2 = createDerivedArtifact("input2");
Benjamin Peterson63748e42018-06-03 22:11:16 -0700135 SpecialArtifact tree = createDerivedTreeArtifactWithAction("treeArtifact");
buchgrd4d3d502018-08-02 06:47:19 -0700136 TreeFileArtifact treeFile1 = createFakeTreeFileArtifact(tree, "child1", "hello1");
137 TreeFileArtifact treeFile2 = createFakeTreeFileArtifact(tree, "child2", "hello2");
138 file(treeFile1.getPath(), "src1");
139 file(treeFile2.getPath(), "src2");
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000140 Action action =
141 new DummyAction(
ulfjack1e1a7752019-12-10 21:17:58 -0800142 NestedSetBuilder.create(Order.STABLE_ORDER, input1, input2, tree),
143 output,
144 MiddlemanType.AGGREGATING_MIDDLEMAN);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000145 actions.add(action);
146 file(input2.getPath(), "contents");
147 file(input1.getPath(), "source contents");
janakr8541f6d2019-06-11 14:40:21 -0700148 evaluate(
149 Iterables.toArray(
lberki36df7ed2019-06-27 06:32:03 -0700150 Artifact.keys(ImmutableSet.of(input2, input1, input2, tree)), SkyKey.class));
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000151 SkyValue value = evaluateArtifactValue(output);
buchgrd4d3d502018-08-02 06:47:19 -0700152 ArrayList<Pair<Artifact, ?>> inputs = new ArrayList<>();
153 inputs.addAll(((AggregatingArtifactValue) value).getFileArtifacts());
154 inputs.addAll(((AggregatingArtifactValue) value).getTreeArtifacts());
155 assertThat(inputs)
Benjamin Peterson63748e42018-06-03 22:11:16 -0700156 .containsExactly(
lberki812e6fe2019-07-25 07:50:55 -0700157 Pair.of(input1, createForTesting(input1)),
158 Pair.of(input2, createForTesting(input2)),
buchgrd4d3d502018-08-02 06:47:19 -0700159 Pair.of(tree, ((TreeArtifactValue) evaluateArtifactValue(tree))));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000160 }
161
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000162 /**
163 * Tests that ArtifactFunction rethrows transitive {@link IOException}s as
164 * {@link MissingInputFileException}s.
165 */
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000166 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000167 public void testIOException_EndToEnd() throws Throwable {
168 final IOException exception = new IOException("beep");
169 setupRoot(
170 new CustomInMemoryFs() {
171 @Override
fellya205ed82018-09-10 11:52:34 -0700172 public FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000173 if (path.getBaseName().equals("bad")) {
174 throw exception;
175 }
fellya205ed82018-09-10 11:52:34 -0700176 return super.statIfFound(path, followSymlinks);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000177 }
178 });
lberki36df7ed2019-06-27 06:32:03 -0700179 IOException e =
180 assertThrows(IOException.class, () -> evaluateArtifactValue(createSourceArtifact("bad")));
jcater83130f42019-04-30 14:29:28 -0700181 assertThat(e).hasMessageThat().contains(exception.getMessage());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000182 }
183
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000184 @Test
Rumou Duan73876202016-06-06 18:52:08 +0000185 public void testActionTreeArtifactOutput() throws Throwable {
cpeyserac09f0a2018-02-05 09:33:15 -0800186 SpecialArtifact artifact = createDerivedTreeArtifactWithAction("treeArtifact");
janakrefb3f152019-06-05 17:42:34 -0700187 TreeFileArtifact treeFileArtifact1 = createFakeTreeFileArtifact(artifact, "child1", "hello1");
188 TreeFileArtifact treeFileArtifact2 = createFakeTreeFileArtifact(artifact, "child2", "hello2");
Rumou Duan73876202016-06-06 18:52:08 +0000189
190 TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact);
janakr45b308a2018-06-08 12:51:58 -0700191 assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
192 assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
lberkiaea56b32017-05-30 12:35:33 +0200193 assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
194 assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
Rumou Duan73876202016-06-06 18:52:08 +0000195 }
196
197 @Test
198 public void testSpawnActionTemplate() throws Throwable {
199 // artifact1 is a tree artifact generated by normal action.
cpeyserac09f0a2018-02-05 09:33:15 -0800200 SpecialArtifact artifact1 = createDerivedTreeArtifactWithAction("treeArtifact1");
Rumou Duan73876202016-06-06 18:52:08 +0000201 createFakeTreeFileArtifact(artifact1, "child1", "hello1");
202 createFakeTreeFileArtifact(artifact1, "child2", "hello2");
203
Rumou Duan73876202016-06-06 18:52:08 +0000204 // artifact2 is a tree artifact generated by action template.
cpeyserac09f0a2018-02-05 09:33:15 -0800205 SpecialArtifact artifact2 = createDerivedTreeArtifactOnly("treeArtifact2");
janakr45b308a2018-06-08 12:51:58 -0700206 TreeFileArtifact treeFileArtifact1 =
207 createFakeTreeFileArtifact(
208 artifact2,
janakr45b308a2018-06-08 12:51:58 -0700209 "child1",
210 "hello1");
211 TreeFileArtifact treeFileArtifact2 =
212 createFakeTreeFileArtifact(
213 artifact2,
janakr45b308a2018-06-08 12:51:58 -0700214 "child2",
215 "hello2");
Rumou Duan73876202016-06-06 18:52:08 +0000216
217 actions.add(
218 ActionsTestUtil.createDummySpawnActionTemplate(artifact1, artifact2));
219
220 TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact2);
janakr45b308a2018-06-08 12:51:58 -0700221 assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
222 assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
lberkiaea56b32017-05-30 12:35:33 +0200223 assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
224 assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
Rumou Duan73876202016-06-06 18:52:08 +0000225 }
226
227 @Test
228 public void testConsecutiveSpawnActionTemplates() throws Throwable {
229 // artifact1 is a tree artifact generated by normal action.
cpeyserac09f0a2018-02-05 09:33:15 -0800230 SpecialArtifact artifact1 = createDerivedTreeArtifactWithAction("treeArtifact1");
Rumou Duan73876202016-06-06 18:52:08 +0000231 createFakeTreeFileArtifact(artifact1, "child1", "hello1");
232 createFakeTreeFileArtifact(artifact1, "child2", "hello2");
233
234 // artifact2 is a tree artifact generated by action template.
cpeyserac09f0a2018-02-05 09:33:15 -0800235 SpecialArtifact artifact2 = createDerivedTreeArtifactOnly("treeArtifact2");
Rumou Duan73876202016-06-06 18:52:08 +0000236 createFakeTreeFileArtifact(artifact2, "child1", "hello1");
237 createFakeTreeFileArtifact(artifact2, "child2", "hello2");
238 actions.add(
239 ActionsTestUtil.createDummySpawnActionTemplate(artifact1, artifact2));
240
241 // artifact3 is a tree artifact generated by action template.
cpeyserac09f0a2018-02-05 09:33:15 -0800242 SpecialArtifact artifact3 = createDerivedTreeArtifactOnly("treeArtifact3");
janakr45b308a2018-06-08 12:51:58 -0700243 TreeFileArtifact treeFileArtifact1 =
244 createFakeTreeFileArtifact(
245 artifact3,
janakr45b308a2018-06-08 12:51:58 -0700246 "child1",
247 "hello1");
248 TreeFileArtifact treeFileArtifact2 =
249 createFakeTreeFileArtifact(
250 artifact3,
janakr45b308a2018-06-08 12:51:58 -0700251 "child2",
252 "hello2");
Rumou Duan73876202016-06-06 18:52:08 +0000253 actions.add(
254 ActionsTestUtil.createDummySpawnActionTemplate(artifact2, artifact3));
255
256 TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact3);
janakr45b308a2018-06-08 12:51:58 -0700257 assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
258 assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
lberkiaea56b32017-05-30 12:35:33 +0200259 assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
260 assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
Rumou Duan73876202016-06-06 18:52:08 +0000261 }
262
janakre82933c2019-01-02 14:41:50 -0800263 @Test
264 public void actionExecutionValueSerialization() throws Exception {
janakrefb3f152019-06-05 17:42:34 -0700265 ActionLookupData dummyData = ActionLookupData.create(ALL_OWNER, 0);
266 Artifact.DerivedArtifact artifact1 = createDerivedArtifact("one");
lberkif7eee1e2019-07-31 05:49:10 -0700267 FileArtifactValue metadata1 =
268 ActionMetadataHandler.fileArtifactValueFromArtifact(artifact1, null, null);
janakre82933c2019-01-02 14:41:50 -0800269 SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly("tree");
janakrefb3f152019-06-05 17:42:34 -0700270 treeArtifact.setGeneratingActionKey(dummyData);
271 TreeFileArtifact treeFileArtifact = ActionInputHelper.treeFileArtifact(treeArtifact, "subpath");
272 Path path = treeFileArtifact.getPath();
273 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
274 writeFile(path, "contents");
janakre82933c2019-01-02 14:41:50 -0800275 TreeArtifactValue treeArtifactValue =
276 TreeArtifactValue.create(
lberki812e6fe2019-07-25 07:50:55 -0700277 ImmutableMap.of(
278 treeFileArtifact, FileArtifactValue.createForTesting(treeFileArtifact)));
janakrefb3f152019-06-05 17:42:34 -0700279 Artifact.DerivedArtifact artifact3 = createDerivedArtifact("three");
janakre82933c2019-01-02 14:41:50 -0800280 FilesetOutputSymlink filesetOutputSymlink =
281 FilesetOutputSymlink.createForTesting(
282 PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT);
283 ActionExecutionValue actionExecutionValue =
284 ActionExecutionValue.create(
lberkic35878a2019-08-01 02:28:54 -0700285 ImmutableMap.of(artifact1, metadata1, artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
janakre82933c2019-01-02 14:41:50 -0800286 ImmutableMap.of(treeArtifact, treeArtifactValue),
janakre82933c2019-01-02 14:41:50 -0800287 ImmutableList.of(filesetOutputSymlink),
288 null,
289 true);
Googlerce6ad292019-12-20 10:29:21 -0800290 new SerializationTester(actionExecutionValue)
janakre82933c2019-01-02 14:41:50 -0800291 .addDependency(FileSystem.class, root.getFileSystem())
292 .runTests();
293 }
294
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000295 private void file(Path path, String contents) throws Exception {
296 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
297 writeFile(path, contents);
298 }
299
300 private Artifact createSourceArtifact(String path) {
janakraea05602019-05-22 15:41:29 -0700301 return ActionsTestUtil.createArtifactWithExecPath(
302 ArtifactRoot.asSourceRoot(Root.fromPath(root)), PathFragment.create(path));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000303 }
304
janakrefb3f152019-06-05 17:42:34 -0700305 private Artifact.DerivedArtifact createDerivedArtifact(String path) {
nharmatab4060b62017-04-04 17:11:39 +0000306 PathFragment execPath = PathFragment.create("out").getRelative(path);
janakrefb3f152019-06-05 17:42:34 -0700307 Artifact.DerivedArtifact output =
janakraea05602019-05-22 15:41:29 -0700308 new Artifact.DerivedArtifact(
janakr3290e222019-05-29 16:34:22 -0700309 ArtifactRoot.asDerivedRoot(root, root.getRelative("out")), execPath, ALL_OWNER);
ulfjack1e1a7752019-12-10 21:17:58 -0800310 actions.add(new DummyAction(NestedSetBuilder.emptySet(Order.STABLE_ORDER), output));
janakr8541f6d2019-06-11 14:40:21 -0700311 output.setGeneratingActionKey(ActionLookupData.create(ALL_OWNER, actions.size() - 1));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000312 return output;
313 }
314
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000315 private Artifact createMiddlemanArtifact(String path) {
tomlu1cdcdf92018-01-16 11:07:51 -0800316 ArtifactRoot middlemanRoot =
317 ArtifactRoot.middlemanRoot(middlemanPath, middlemanPath.getRelative("out"));
janakraea05602019-05-22 15:41:29 -0700318 return new Artifact.DerivedArtifact(
janakr3290e222019-05-29 16:34:22 -0700319 middlemanRoot, middlemanRoot.getExecPath().getRelative(path), ALL_OWNER);
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000320 }
321
cpeyserac09f0a2018-02-05 09:33:15 -0800322 private SpecialArtifact createDerivedTreeArtifactWithAction(String path) {
323 SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly(path);
ulfjack1e1a7752019-12-10 21:17:58 -0800324 actions.add(new DummyAction(NestedSetBuilder.emptySet(Order.STABLE_ORDER), treeArtifact));
Rumou Duan73876202016-06-06 18:52:08 +0000325 return treeArtifact;
326 }
327
cpeyserac09f0a2018-02-05 09:33:15 -0800328 private SpecialArtifact createDerivedTreeArtifactOnly(String path) {
nharmatab4060b62017-04-04 17:11:39 +0000329 PathFragment execPath = PathFragment.create("out").getRelative(path);
Rumou Duan73876202016-06-06 18:52:08 +0000330 return new SpecialArtifact(
tomlu1cdcdf92018-01-16 11:07:51 -0800331 ArtifactRoot.asDerivedRoot(root, root.getRelative("out")),
Rumou Duan73876202016-06-06 18:52:08 +0000332 execPath,
janakr3290e222019-05-29 16:34:22 -0700333 ALL_OWNER,
Rumou Duan73876202016-06-06 18:52:08 +0000334 SpecialArtifactType.TREE);
335 }
336
cpeyserac09f0a2018-02-05 09:33:15 -0800337 private TreeFileArtifact createFakeTreeFileArtifact(
janakr45b308a2018-06-08 12:51:58 -0700338 SpecialArtifact treeArtifact,
janakr45b308a2018-06-08 12:51:58 -0700339 String parentRelativePath,
340 String content)
341 throws Exception {
342 TreeFileArtifact treeFileArtifact =
janakrefb3f152019-06-05 17:42:34 -0700343 ActionsTestUtil.createTreeFileArtifactWithNoGeneratingAction(
344 treeArtifact, parentRelativePath);
Rumou Duan73876202016-06-06 18:52:08 +0000345 Path path = treeFileArtifact.getPath();
346 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
347 writeFile(path, content);
348 return treeFileArtifact;
349 }
350
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000351 private void assertValueMatches(FileStatus file, byte[] digest, FileArtifactValue value)
352 throws IOException {
lberkiaea56b32017-05-30 12:35:33 +0200353 assertThat(value.getSize()).isEqualTo(file.getSize());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000354 if (digest == null) {
lberkiaea56b32017-05-30 12:35:33 +0200355 assertThat(value.getDigest()).isNull();
356 assertThat(value.getModifiedTime()).isEqualTo(file.getLastModifiedTime());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000357 } else {
lberkiaea56b32017-05-30 12:35:33 +0200358 assertThat(value.getDigest()).isEqualTo(digest);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000359 }
360 }
361
362 private FileArtifactValue evaluateFAN(Artifact artifact) throws Throwable {
363 return ((FileArtifactValue) evaluateArtifactValue(artifact));
364 }
365
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000366 private SkyValue evaluateArtifactValue(Artifact artifact) throws Throwable {
lberki36df7ed2019-06-27 06:32:03 -0700367 SkyKey key = Artifact.key(artifact);
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000368 EvaluationResult<SkyValue> result = evaluate(ImmutableList.of(key).toArray(new SkyKey[0]));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000369 if (result.hasError()) {
370 throw result.getError().getException();
371 }
janakr8541f6d2019-06-11 14:40:21 -0700372 SkyValue value = result.get(key);
373 if (value instanceof ActionExecutionValue) {
374 return ArtifactFunction.createSimpleFileArtifactValue(
375 (Artifact.DerivedArtifact) artifact, (ActionExecutionValue) value);
376 }
377 return value;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000378 }
379
janakr0175ce32018-02-26 15:54:57 -0800380 private void setGeneratingActions() throws InterruptedException, ActionConflictException {
janakr573807d2018-01-11 14:02:35 -0800381 if (evaluator.getExistingValue(ALL_OWNER) == null) {
janakr93e3eea2017-03-30 22:09:37 +0000382 differencer.inject(
383 ImmutableMap.of(
janakr573807d2018-01-11 14:02:35 -0800384 ALL_OWNER,
cparsonse2d200f2018-03-06 16:15:11 -0800385 new BasicActionLookupValue(
janakrefb3f152019-06-05 17:42:34 -0700386 Actions.assignOwnersAndFilterSharedActionsAndThrowActionConflict(
387 actionKeyContext,
388 ImmutableList.copyOf(actions),
389 ALL_OWNER,
Googlerce6ad292019-12-20 10:29:21 -0800390 /*outputFiles=*/ null))));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000391 }
392 }
393
394 private <E extends SkyValue> EvaluationResult<E> evaluate(SkyKey... keys)
janakr0175ce32018-02-26 15:54:57 -0800395 throws InterruptedException, ActionConflictException {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000396 setGeneratingActions();
Googler10028672018-10-25 12:14:34 -0700397 EvaluationContext evaluationContext =
398 EvaluationContext.newBuilder()
399 .setKeepGoing(false)
400 .setNumThreads(SkyframeExecutor.DEFAULT_THREAD_COUNT)
401 .setEventHander(NullEventHandler.INSTANCE)
402 .build();
403 return driver.evaluate(Arrays.asList(keys), evaluationContext);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000404 }
405
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000406 /** Value Builder for actions that just stats and stores the output file (which must exist). */
Rumou Duan73876202016-06-06 18:52:08 +0000407 private static class SimpleActionExecutionFunction implements SkyFunction {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000408 @Override
janakr93e3eea2017-03-30 22:09:37 +0000409 public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
lberkif7eee1e2019-07-31 05:49:10 -0700410 Map<Artifact, FileArtifactValue> artifactData = new HashMap<>();
Rumou Duan73876202016-06-06 18:52:08 +0000411 Map<Artifact, TreeArtifactValue> treeArtifactData = new HashMap<>();
janakr93e3eea2017-03-30 22:09:37 +0000412 ActionLookupData actionLookupData = (ActionLookupData) skyKey.argument();
413 ActionLookupValue actionLookupValue =
janakrbaf52ae2018-02-14 09:03:18 -0800414 (ActionLookupValue) env.getValue(actionLookupData.getActionLookupKey());
janakr93e3eea2017-03-30 22:09:37 +0000415 Action action = actionLookupValue.getAction(actionLookupData.getActionIndex());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000416 Artifact output = Iterables.getOnlyElement(action.getOutputs());
Rumou Duan73876202016-06-06 18:52:08 +0000417
418 try {
419 if (output.isTreeArtifact()) {
420 TreeFileArtifact treeFileArtifact1 = ActionInputHelper.treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800421 (SpecialArtifact) output, PathFragment.create("child1"));
Rumou Duan73876202016-06-06 18:52:08 +0000422 TreeFileArtifact treeFileArtifact2 = ActionInputHelper.treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800423 (SpecialArtifact) output, PathFragment.create("child2"));
lberki812e6fe2019-07-25 07:50:55 -0700424 TreeArtifactValue treeArtifactValue =
425 TreeArtifactValue.create(
426 ImmutableMap.of(
427 treeFileArtifact1, FileArtifactValue.createForTesting(treeFileArtifact1),
428 treeFileArtifact2, FileArtifactValue.createForTesting(treeFileArtifact2)));
Rumou Duan73876202016-06-06 18:52:08 +0000429 treeArtifactData.put(output, treeArtifactValue);
430 } else if (action.getActionType() == MiddlemanType.NORMAL) {
lberkif225af12019-08-01 04:21:58 -0700431 Path path = output.getPath();
432 FileArtifactValue noDigest =
433 ActionMetadataHandler.fileArtifactValueFromArtifact(
434 output,
435 FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW)),
436 null);
437 FileArtifactValue withDigest =
438 FileArtifactValue.createFromInjectedDigest(
439 noDigest, path.getDigest(), !output.isConstantMetadata());
440 artifactData.put(output, withDigest);
Rumou Duan73876202016-06-06 18:52:08 +0000441 } else {
lberkic35878a2019-08-01 02:28:54 -0700442 artifactData.put(output, FileArtifactValue.DEFAULT_MIDDLEMAN);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000443 }
Rumou Duan73876202016-06-06 18:52:08 +0000444 } catch (IOException e) {
445 throw new IllegalStateException(e);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000446 }
janakrb9d8d582018-06-13 21:57:19 -0700447 return ActionExecutionValue.create(
448 artifactData,
449 treeArtifactData,
janakrb9d8d582018-06-13 21:57:19 -0700450 /*outputSymlinks=*/ null,
shahanef6f4cf2018-06-26 11:24:59 -0700451 /*discoveredModules=*/ null,
janakr9f496f32018-10-24 15:08:09 -0700452 /*actionDependsOnBuildId=*/ false);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000453 }
454
455 @Override
456 public String extractTag(SkyKey skyKey) {
457 return null;
458 }
459 }
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000460}