blob: 19f586ede593a3041204c6be736c0533d426f086 [file] [log] [blame]
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001// Copyright 2015 Google Inc. 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.actions;
15
16
17import static com.google.common.truth.Truth.assertThat;
18import static com.google.devtools.build.lib.testutil.MoreAsserts.assertSameContents;
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertSame;
22import static org.junit.Assert.assertTrue;
23import static org.junit.Assert.fail;
24
25import com.google.common.collect.ImmutableList;
26import com.google.common.collect.Iterables;
27import com.google.common.collect.Lists;
28import com.google.devtools.build.lib.actions.Action.MiddlemanType;
29import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
30import com.google.devtools.build.lib.actions.util.LabelArtifactOwner;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000031import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
33import com.google.devtools.build.lib.rules.java.JavaSemantics;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import com.google.devtools.build.lib.testutil.Scratch;
35import com.google.devtools.build.lib.vfs.Path;
36import com.google.devtools.build.lib.vfs.PathFragment;
37
38import org.junit.Before;
39import org.junit.Test;
40import org.junit.runner.RunWith;
41import org.junit.runners.JUnit4;
42
43import java.io.IOException;
44import java.util.ArrayList;
45import java.util.List;
46
47@RunWith(JUnit4.class)
48public class ArtifactTest {
49 private Scratch scratch;
50 private Path execDir;
51 private Root rootDir;
52
53 @Before
54 public void setUp() throws Exception {
55 scratch = new Scratch();
56 execDir = scratch.dir("/exec");
57 rootDir = Root.asDerivedRoot(scratch.dir("/exec/root"));
58 }
59
60 @Test
61 public void testConstruction_badRootDir() throws IOException {
62 Path f1 = scratch.file("/exec/dir/file.ext");
63 Path bogusDir = scratch.file("/exec/dir/bogus");
64 try {
65 new Artifact(f1, Root.asDerivedRoot(bogusDir), f1.relativeTo(execDir));
66 fail("Expected IllegalArgumentException constructing artifact with a bad root dir");
67 } catch (IllegalArgumentException expected) {}
68 }
69
70 @Test
71 public void testEquivalenceRelation() throws Exception {
72 PathFragment aPath = new PathFragment("src/a");
73 PathFragment bPath = new PathFragment("src/b");
74 assertEquals(new Artifact(aPath, rootDir),
75 new Artifact(aPath, rootDir));
76 assertEquals(new Artifact(bPath, rootDir),
77 new Artifact(bPath, rootDir));
78 assertFalse(new Artifact(aPath, rootDir).equals(
79 new Artifact(bPath, rootDir)));
80 }
81
82 @Test
83 public void testComparison() throws Exception {
84 PathFragment aPath = new PathFragment("src/a");
85 PathFragment bPath = new PathFragment("src/b");
86 Artifact aArtifact = new Artifact(aPath, rootDir);
87 Artifact bArtifact = new Artifact(bPath, rootDir);
Lukacs Berki8ae34f12015-04-10 14:54:19 +000088 assertEquals(-1, Artifact.EXEC_PATH_COMPARATOR.compare(aArtifact, bArtifact));
89 assertEquals(0, Artifact.EXEC_PATH_COMPARATOR.compare(aArtifact, aArtifact));
90 assertEquals(0, Artifact.EXEC_PATH_COMPARATOR.compare(bArtifact, bArtifact));
91 assertEquals(1, Artifact.EXEC_PATH_COMPARATOR.compare(bArtifact, aArtifact));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010092 }
93
94 @Test
95 public void testRootPrefixedExecPath_normal() throws IOException {
96 Path f1 = scratch.file("/exec/root/dir/file.ext");
97 Artifact a1 = new Artifact(f1, rootDir, f1.relativeTo(execDir));
98 assertEquals("root:dir/file.ext", Artifact.asRootPrefixedExecPath(a1));
99 }
100
101 @Test
102 public void testRootPrefixedExecPath_noRoot() throws IOException {
103 Path f1 = scratch.file("/exec/dir/file.ext");
104 Artifact a1 = new Artifact(f1.relativeTo(execDir), Root.asDerivedRoot(execDir));
105 assertEquals(":dir/file.ext", Artifact.asRootPrefixedExecPath(a1));
106 }
107
108 @Test
109 public void testRootPrefixedExecPath_nullRootDir() throws IOException {
110 Path f1 = scratch.file("/exec/dir/file.ext");
111 try {
112 new Artifact(f1, null, f1.relativeTo(execDir));
113 fail("Expected IllegalArgumentException creating artifact with null root");
114 } catch (IllegalArgumentException expected) {}
115 }
116
117 @Test
118 public void testRootPrefixedExecPaths() throws IOException {
119 Path f1 = scratch.file("/exec/root/dir/file1.ext");
120 Path f2 = scratch.file("/exec/root/dir/dir/file2.ext");
121 Path f3 = scratch.file("/exec/root/dir/dir/dir/file3.ext");
122 Artifact a1 = new Artifact(f1, rootDir, f1.relativeTo(execDir));
123 Artifact a2 = new Artifact(f2, rootDir, f2.relativeTo(execDir));
124 Artifact a3 = new Artifact(f3, rootDir, f3.relativeTo(execDir));
125 List<String> strings = new ArrayList<>();
126 Artifact.addRootPrefixedExecPaths(Lists.newArrayList(a1, a2, a3), strings);
127 assertThat(strings).containsExactly(
128 "root:dir/file1.ext",
129 "root:dir/dir/file2.ext",
130 "root:dir/dir/dir/file3.ext").inOrder();
131 }
132
133 @Test
134 public void testGetFilename() throws Exception {
135 Root root = Root.asSourceRoot(scratch.dir("/foo"));
136 Artifact javaFile = new Artifact(scratch.file("/foo/Bar.java"), root);
137 Artifact generatedHeader = new Artifact(scratch.file("/foo/bar.proto.h"), root);
138 Artifact generatedCc = new Artifact(scratch.file("/foo/bar.proto.cc"), root);
139 Artifact aCPlusPlusFile = new Artifact(scratch.file("/foo/bar.cc"), root);
140 assertTrue(JavaSemantics.JAVA_SOURCE.matches(javaFile.getFilename()));
141 assertTrue(CppFileTypes.CPP_HEADER.matches(generatedHeader.getFilename()));
142 assertTrue(CppFileTypes.CPP_SOURCE.matches(generatedCc.getFilename()));
143 assertTrue(CppFileTypes.CPP_SOURCE.matches(aCPlusPlusFile.getFilename()));
144 }
145
146 @Test
147 public void testMangledPath() {
148 String path = "dir/sub_dir/name:end";
149 assertEquals("dir_Ssub_Udir_Sname_Cend", Actions.escapedPath(path));
150 }
151
152 private List<Artifact> getFooBarArtifacts(MutableActionGraph actionGraph, boolean collapsedList)
153 throws Exception {
154 Root root = Root.asSourceRoot(scratch.dir("/foo"));
155 Artifact aHeader1 = new Artifact(scratch.file("/foo/bar1.h"), root);
156 Artifact aHeader2 = new Artifact(scratch.file("/foo/bar2.h"), root);
157 Artifact aHeader3 = new Artifact(scratch.file("/foo/bar3.h"), root);
158 Artifact middleman = new Artifact(new PathFragment("middleman"),
159 Root.middlemanRoot(scratch.dir("/foo"), scratch.dir("/foo/out")));
160 actionGraph.registerAction(new MiddlemanAction(ActionsTestUtil.NULL_ACTION_OWNER,
161 ImmutableList.of(aHeader1, aHeader2, aHeader3), middleman, "desc",
162 MiddlemanType.AGGREGATING_MIDDLEMAN));
163 return collapsedList ? Lists.newArrayList(aHeader1, middleman) :
164 Lists.newArrayList(aHeader1, aHeader2, middleman);
165 }
166
167 @Test
168 public void testAddExecPaths() throws Exception {
169 List<String> paths = new ArrayList<>();
170 MutableActionGraph actionGraph = new MapBasedActionGraph();
171 Artifact.addExecPaths(getFooBarArtifacts(actionGraph, false), paths);
172 assertSameContents(ImmutableList.of("bar1.h", "bar2.h"), paths);
173 }
174
175 @Test
176 public void testAddExpandedExecPathStrings() throws Exception {
177 List<String> paths = new ArrayList<>();
178 MutableActionGraph actionGraph = new MapBasedActionGraph();
179 Artifact.addExpandedExecPathStrings(getFooBarArtifacts(actionGraph, true), paths,
180 ActionInputHelper.actionGraphMiddlemanExpander(actionGraph));
181 assertSameContents(ImmutableList.of("bar1.h", "bar2.h", "bar3.h"), paths);
182 }
183
184 @Test
185 public void testAddExpandedExecPaths() throws Exception {
186 List<PathFragment> paths = new ArrayList<>();
187 MutableActionGraph actionGraph = new MapBasedActionGraph();
188 Artifact.addExpandedExecPaths(getFooBarArtifacts(actionGraph, true), paths,
189 ActionInputHelper.actionGraphMiddlemanExpander(actionGraph));
190 assertSameContents(ImmutableList.of(
191 new PathFragment("bar1.h"), new PathFragment("bar2.h"), new PathFragment("bar3.h")),
192 paths);
193 }
194
195 @Test
196 public void testAddExpandedArtifacts() throws Exception {
197 List<Artifact> expanded = new ArrayList<>();
198 MutableActionGraph actionGraph = new MapBasedActionGraph();
199 List<Artifact> original = getFooBarArtifacts(actionGraph, true);
200 Artifact.addExpandedArtifacts(original, expanded,
201 ActionInputHelper.actionGraphMiddlemanExpander(actionGraph));
202
203 List<Artifact> manuallyExpanded = new ArrayList<>();
204 for (Artifact artifact : original) {
205 Action action = actionGraph.getGeneratingAction(artifact);
206 if (artifact.isMiddlemanArtifact()) {
207 Iterables.addAll(manuallyExpanded, action.getInputs());
208 } else {
209 manuallyExpanded.add(artifact);
210 }
211 }
212 assertSameContents(manuallyExpanded, expanded);
213 }
214
215 @Test
216 public void testAddExecPathsNewActionGraph() throws Exception {
217 List<String> paths = new ArrayList<>();
218 MutableActionGraph actionGraph = new MapBasedActionGraph();
219 Artifact.addExecPaths(getFooBarArtifacts(actionGraph, false), paths);
220 assertSameContents(ImmutableList.of("bar1.h", "bar2.h"), paths);
221 }
222
223 @Test
224 public void testAddExpandedExecPathStringsNewActionGraph() throws Exception {
225 List<String> paths = new ArrayList<>();
226 MutableActionGraph actionGraph = new MapBasedActionGraph();
227 Artifact.addExpandedExecPathStrings(getFooBarArtifacts(actionGraph, true), paths,
228 ActionInputHelper.actionGraphMiddlemanExpander(actionGraph));
229 assertSameContents(ImmutableList.of("bar1.h", "bar2.h", "bar3.h"), paths);
230 }
231
232 @Test
233 public void testAddExpandedExecPathsNewActionGraph() throws Exception {
234 List<PathFragment> paths = new ArrayList<>();
235 MutableActionGraph actionGraph = new MapBasedActionGraph();
236 Artifact.addExpandedExecPaths(getFooBarArtifacts(actionGraph, true), paths,
237 ActionInputHelper.actionGraphMiddlemanExpander(actionGraph));
238 assertSameContents(ImmutableList.of(
239 new PathFragment("bar1.h"), new PathFragment("bar2.h"), new PathFragment("bar3.h")),
240 paths);
241 }
242
243 @Test
244 public void testAddExpandedArtifactsNewActionGraph() throws Exception {
245 List<Artifact> expanded = new ArrayList<>();
246 MutableActionGraph actionGraph = new MapBasedActionGraph();
247 List<Artifact> original = getFooBarArtifacts(actionGraph, true);
248 Artifact.addExpandedArtifacts(original, expanded,
249 ActionInputHelper.actionGraphMiddlemanExpander(actionGraph));
250
251 List<Artifact> manuallyExpanded = new ArrayList<>();
252 for (Artifact artifact : original) {
253 Action action = actionGraph.getGeneratingAction(artifact);
254 if (artifact.isMiddlemanArtifact()) {
255 Iterables.addAll(manuallyExpanded, action.getInputs());
256 } else {
257 manuallyExpanded.add(artifact);
258 }
259 }
260 assertSameContents(manuallyExpanded, expanded);
261 }
262
263 @Test
264 public void testRootRelativePathIsSameAsExecPath() throws Exception {
265 Root root = Root.asSourceRoot(scratch.dir("/foo"));
266 Artifact a = new Artifact(scratch.file("/foo/bar1.h"), root);
267 assertSame(a.getExecPath(), a.getRootRelativePath());
268 }
269
270 @Test
271 public void testToDetailString() throws Exception {
272 Artifact a = new Artifact(scratch.file("/a/b/c"), Root.asDerivedRoot(scratch.dir("/a/b")),
273 new PathFragment("b/c"));
274 assertEquals("[[/a]b]c", a.toDetailString());
275 }
276
277 @Test
278 public void testWeirdArtifact() throws Exception {
279 try {
280 new Artifact(scratch.file("/a/b/c"), Root.asDerivedRoot(scratch.dir("/a")),
281 new PathFragment("c"));
282 fail();
283 } catch (IllegalArgumentException e) {
Ulf Adams795895a2015-03-06 15:58:35 +0000284 assertThat(e).hasMessage(
285 "c: illegal execPath doesn't end with b/c at /a/b/c with root /a[derived]");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100286 }
287 }
288
289 @Test
290 public void testSerializeToString() throws Exception {
291 assertEquals("b/c /3",
292 new Artifact(scratch.file("/a/b/c"),
293 Root.asDerivedRoot(scratch.dir("/a"))).serializeToString());
294 }
295
296 @Test
297 public void testSerializeToStringWithExecPath() throws Exception {
298 Path path = scratch.file("/aaa/bbb/ccc");
299 Root root = Root.asDerivedRoot(scratch.dir("/aaa/bbb"));
300 PathFragment execPath = new PathFragment("bbb/ccc");
301
302 assertEquals("bbb/ccc /3", new Artifact(path, root, execPath).serializeToString());
303 }
304
305 @Test
306 public void testSerializeToStringWithOwner() throws Exception {
307 assertEquals("b/c /3 //foo:bar",
308 new Artifact(scratch.file("/aa/b/c"), Root.asDerivedRoot(scratch.dir("/aa")),
309 new PathFragment("b/c"),
310 new LabelArtifactOwner(Label.parseAbsoluteUnchecked("//foo:bar"))).serializeToString());
311 }
Googler91cfbff2015-05-26 16:35:27 +0000312
313 @Test
314 public void testLongDirname() throws Exception {
315 String dirName = createDirNameArtifact().getDirname();
316
317 assertThat(dirName).isEqualTo("aaa/bbb/ccc");
318 }
319
320 @Test
321 public void testDirnameInExecutionDir() throws Exception {
322 Artifact artifact = new Artifact(scratch.file("/foo/bar.txt"),
323 Root.asDerivedRoot(scratch.dir("/foo")));
324
325 assertThat(artifact.getDirname()).isEqualTo(".");
326 }
327
328 @Test
329 public void testCanConstructPathFromDirAndFilename() throws Exception {
330 Artifact artifact = createDirNameArtifact();
331 String constructed =
332 String.format("%s/%s", artifact.getDirname(), artifact.getFilename());
333
334 assertThat(constructed).isEqualTo("aaa/bbb/ccc/ddd");
335 }
336
337 private Artifact createDirNameArtifact() throws Exception {
338 return new Artifact(scratch.file("/aaa/bbb/ccc/ddd"), Root.asDerivedRoot(scratch.dir("/")));
339 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100340}