blob: 0d38158dc9466c9febd792bb76d477bb85981137 [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;
michajlo660d17f2020-03-27 09:01:57 -070018import static org.junit.Assert.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())
nharmataf93c72c2020-03-13 14:22:10 -0700292 .addDependency(
293 Root.RootCodecDependencies.class,
294 new Root.RootCodecDependencies(Root.absoluteRoot(root.getFileSystem())))
janakre82933c2019-01-02 14:41:50 -0800295 .runTests();
296 }
297
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000298 private void file(Path path, String contents) throws Exception {
299 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
300 writeFile(path, contents);
301 }
302
303 private Artifact createSourceArtifact(String path) {
janakraea05602019-05-22 15:41:29 -0700304 return ActionsTestUtil.createArtifactWithExecPath(
305 ArtifactRoot.asSourceRoot(Root.fromPath(root)), PathFragment.create(path));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000306 }
307
janakrefb3f152019-06-05 17:42:34 -0700308 private Artifact.DerivedArtifact createDerivedArtifact(String path) {
nharmatab4060b62017-04-04 17:11:39 +0000309 PathFragment execPath = PathFragment.create("out").getRelative(path);
janakrefb3f152019-06-05 17:42:34 -0700310 Artifact.DerivedArtifact output =
janakraea05602019-05-22 15:41:29 -0700311 new Artifact.DerivedArtifact(
janakr3290e222019-05-29 16:34:22 -0700312 ArtifactRoot.asDerivedRoot(root, root.getRelative("out")), execPath, ALL_OWNER);
ulfjack1e1a7752019-12-10 21:17:58 -0800313 actions.add(new DummyAction(NestedSetBuilder.emptySet(Order.STABLE_ORDER), output));
janakr8541f6d2019-06-11 14:40:21 -0700314 output.setGeneratingActionKey(ActionLookupData.create(ALL_OWNER, actions.size() - 1));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000315 return output;
316 }
317
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000318 private Artifact createMiddlemanArtifact(String path) {
tomlu1cdcdf92018-01-16 11:07:51 -0800319 ArtifactRoot middlemanRoot =
320 ArtifactRoot.middlemanRoot(middlemanPath, middlemanPath.getRelative("out"));
janakraea05602019-05-22 15:41:29 -0700321 return new Artifact.DerivedArtifact(
janakr3290e222019-05-29 16:34:22 -0700322 middlemanRoot, middlemanRoot.getExecPath().getRelative(path), ALL_OWNER);
Janak Ramakrishnana5578af2017-03-21 17:28:39 +0000323 }
324
cpeyserac09f0a2018-02-05 09:33:15 -0800325 private SpecialArtifact createDerivedTreeArtifactWithAction(String path) {
326 SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly(path);
ulfjack1e1a7752019-12-10 21:17:58 -0800327 actions.add(new DummyAction(NestedSetBuilder.emptySet(Order.STABLE_ORDER), treeArtifact));
Rumou Duan73876202016-06-06 18:52:08 +0000328 return treeArtifact;
329 }
330
cpeyserac09f0a2018-02-05 09:33:15 -0800331 private SpecialArtifact createDerivedTreeArtifactOnly(String path) {
nharmatab4060b62017-04-04 17:11:39 +0000332 PathFragment execPath = PathFragment.create("out").getRelative(path);
Rumou Duan73876202016-06-06 18:52:08 +0000333 return new SpecialArtifact(
tomlu1cdcdf92018-01-16 11:07:51 -0800334 ArtifactRoot.asDerivedRoot(root, root.getRelative("out")),
Rumou Duan73876202016-06-06 18:52:08 +0000335 execPath,
janakr3290e222019-05-29 16:34:22 -0700336 ALL_OWNER,
Rumou Duan73876202016-06-06 18:52:08 +0000337 SpecialArtifactType.TREE);
338 }
339
cpeyserac09f0a2018-02-05 09:33:15 -0800340 private TreeFileArtifact createFakeTreeFileArtifact(
janakr45b308a2018-06-08 12:51:58 -0700341 SpecialArtifact treeArtifact,
janakr45b308a2018-06-08 12:51:58 -0700342 String parentRelativePath,
343 String content)
344 throws Exception {
345 TreeFileArtifact treeFileArtifact =
janakrefb3f152019-06-05 17:42:34 -0700346 ActionsTestUtil.createTreeFileArtifactWithNoGeneratingAction(
347 treeArtifact, parentRelativePath);
Rumou Duan73876202016-06-06 18:52:08 +0000348 Path path = treeFileArtifact.getPath();
349 FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
350 writeFile(path, content);
351 return treeFileArtifact;
352 }
353
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000354 private void assertValueMatches(FileStatus file, byte[] digest, FileArtifactValue value)
355 throws IOException {
lberkiaea56b32017-05-30 12:35:33 +0200356 assertThat(value.getSize()).isEqualTo(file.getSize());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000357 if (digest == null) {
lberkiaea56b32017-05-30 12:35:33 +0200358 assertThat(value.getDigest()).isNull();
359 assertThat(value.getModifiedTime()).isEqualTo(file.getLastModifiedTime());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000360 } else {
lberkiaea56b32017-05-30 12:35:33 +0200361 assertThat(value.getDigest()).isEqualTo(digest);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000362 }
363 }
364
365 private FileArtifactValue evaluateFAN(Artifact artifact) throws Throwable {
366 return ((FileArtifactValue) evaluateArtifactValue(artifact));
367 }
368
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000369 private SkyValue evaluateArtifactValue(Artifact artifact) throws Throwable {
lberki36df7ed2019-06-27 06:32:03 -0700370 SkyKey key = Artifact.key(artifact);
Janak Ramakrishnanad77f972016-07-29 20:58:42 +0000371 EvaluationResult<SkyValue> result = evaluate(ImmutableList.of(key).toArray(new SkyKey[0]));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000372 if (result.hasError()) {
373 throw result.getError().getException();
374 }
janakr8541f6d2019-06-11 14:40:21 -0700375 SkyValue value = result.get(key);
376 if (value instanceof ActionExecutionValue) {
377 return ArtifactFunction.createSimpleFileArtifactValue(
378 (Artifact.DerivedArtifact) artifact, (ActionExecutionValue) value);
379 }
380 return value;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000381 }
382
janakr0175ce32018-02-26 15:54:57 -0800383 private void setGeneratingActions() throws InterruptedException, ActionConflictException {
janakr573807d2018-01-11 14:02:35 -0800384 if (evaluator.getExistingValue(ALL_OWNER) == null) {
janakr93e3eea2017-03-30 22:09:37 +0000385 differencer.inject(
386 ImmutableMap.of(
janakr573807d2018-01-11 14:02:35 -0800387 ALL_OWNER,
cparsonse2d200f2018-03-06 16:15:11 -0800388 new BasicActionLookupValue(
janakrefb3f152019-06-05 17:42:34 -0700389 Actions.assignOwnersAndFilterSharedActionsAndThrowActionConflict(
390 actionKeyContext,
391 ImmutableList.copyOf(actions),
392 ALL_OWNER,
Googlerce6ad292019-12-20 10:29:21 -0800393 /*outputFiles=*/ null))));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000394 }
395 }
396
397 private <E extends SkyValue> EvaluationResult<E> evaluate(SkyKey... keys)
janakr0175ce32018-02-26 15:54:57 -0800398 throws InterruptedException, ActionConflictException {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000399 setGeneratingActions();
Googler10028672018-10-25 12:14:34 -0700400 EvaluationContext evaluationContext =
401 EvaluationContext.newBuilder()
402 .setKeepGoing(false)
403 .setNumThreads(SkyframeExecutor.DEFAULT_THREAD_COUNT)
404 .setEventHander(NullEventHandler.INSTANCE)
405 .build();
406 return driver.evaluate(Arrays.asList(keys), evaluationContext);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000407 }
408
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000409 /** Value Builder for actions that just stats and stores the output file (which must exist). */
Rumou Duan73876202016-06-06 18:52:08 +0000410 private static class SimpleActionExecutionFunction implements SkyFunction {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000411 @Override
janakr93e3eea2017-03-30 22:09:37 +0000412 public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
lberkif7eee1e2019-07-31 05:49:10 -0700413 Map<Artifact, FileArtifactValue> artifactData = new HashMap<>();
Rumou Duan73876202016-06-06 18:52:08 +0000414 Map<Artifact, TreeArtifactValue> treeArtifactData = new HashMap<>();
janakr93e3eea2017-03-30 22:09:37 +0000415 ActionLookupData actionLookupData = (ActionLookupData) skyKey.argument();
416 ActionLookupValue actionLookupValue =
janakrbaf52ae2018-02-14 09:03:18 -0800417 (ActionLookupValue) env.getValue(actionLookupData.getActionLookupKey());
janakr93e3eea2017-03-30 22:09:37 +0000418 Action action = actionLookupValue.getAction(actionLookupData.getActionIndex());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000419 Artifact output = Iterables.getOnlyElement(action.getOutputs());
Rumou Duan73876202016-06-06 18:52:08 +0000420
421 try {
422 if (output.isTreeArtifact()) {
423 TreeFileArtifact treeFileArtifact1 = ActionInputHelper.treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800424 (SpecialArtifact) output, PathFragment.create("child1"));
Rumou Duan73876202016-06-06 18:52:08 +0000425 TreeFileArtifact treeFileArtifact2 = ActionInputHelper.treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800426 (SpecialArtifact) output, PathFragment.create("child2"));
lberki812e6fe2019-07-25 07:50:55 -0700427 TreeArtifactValue treeArtifactValue =
428 TreeArtifactValue.create(
429 ImmutableMap.of(
430 treeFileArtifact1, FileArtifactValue.createForTesting(treeFileArtifact1),
431 treeFileArtifact2, FileArtifactValue.createForTesting(treeFileArtifact2)));
Rumou Duan73876202016-06-06 18:52:08 +0000432 treeArtifactData.put(output, treeArtifactValue);
433 } else if (action.getActionType() == MiddlemanType.NORMAL) {
lberkif225af12019-08-01 04:21:58 -0700434 Path path = output.getPath();
435 FileArtifactValue noDigest =
436 ActionMetadataHandler.fileArtifactValueFromArtifact(
437 output,
438 FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW)),
439 null);
440 FileArtifactValue withDigest =
441 FileArtifactValue.createFromInjectedDigest(
442 noDigest, path.getDigest(), !output.isConstantMetadata());
443 artifactData.put(output, withDigest);
Rumou Duan73876202016-06-06 18:52:08 +0000444 } else {
lberkic35878a2019-08-01 02:28:54 -0700445 artifactData.put(output, FileArtifactValue.DEFAULT_MIDDLEMAN);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000446 }
Rumou Duan73876202016-06-06 18:52:08 +0000447 } catch (IOException e) {
448 throw new IllegalStateException(e);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000449 }
janakrb9d8d582018-06-13 21:57:19 -0700450 return ActionExecutionValue.create(
451 artifactData,
452 treeArtifactData,
janakrb9d8d582018-06-13 21:57:19 -0700453 /*outputSymlinks=*/ null,
shahanef6f4cf2018-06-26 11:24:59 -0700454 /*discoveredModules=*/ null,
janakr9f496f32018-10-24 15:08:09 -0700455 /*actionDependsOnBuildId=*/ false);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000456 }
457
458 @Override
459 public String extractTag(SkyKey skyKey) {
460 return null;
461 }
462 }
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000463}