blob: 311ae2e61cffe559b5328d53b1f79ea4b4f974da [file] [log] [blame]
ulfjack04509fa2017-10-02 14:52:14 +02001// Copyright 2017 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.
14
15package com.google.devtools.build.lib.analysis;
16
17import static com.google.common.truth.Truth.assertThat;
michajlo660d17f2020-03-27 09:01:57 -070018import static org.junit.Assert.assertThrows;
ulfjack04509fa2017-10-02 14:52:14 +020019
20import com.google.common.base.Suppliers;
dannarkc7c5ab12018-06-21 14:40:46 -070021import com.google.common.collect.ImmutableMap;
ulfjack04509fa2017-10-02 14:52:14 +020022import com.google.devtools.build.lib.actions.Artifact;
tomlu1cdcdf92018-01-16 11:07:51 -080023import com.google.devtools.build.lib.actions.ArtifactRoot;
Googlerf0b0c392021-01-27 17:56:52 -080024import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
janakraea05602019-05-22 15:41:29 -070025import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
ulfjack04509fa2017-10-02 14:52:14 +020026import com.google.devtools.build.lib.analysis.LocationExpander.LocationFunction;
27import com.google.devtools.build.lib.cmdline.Label;
dannarkc7c5ab12018-06-21 14:40:46 -070028import com.google.devtools.build.lib.cmdline.RepositoryName;
janakr97c0bd12020-09-08 13:19:03 -070029import com.google.devtools.build.lib.vfs.DigestHashFunction;
ulfjack04509fa2017-10-02 14:52:14 +020030import com.google.devtools.build.lib.vfs.FileSystem;
tomluee6a6862018-01-17 14:36:26 -080031import com.google.devtools.build.lib.vfs.Root;
ulfjack04509fa2017-10-02 14:52:14 +020032import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
33import java.util.Arrays;
34import java.util.Collection;
35import java.util.HashMap;
36import java.util.Map;
37import java.util.stream.Collectors;
ulfjack04509fa2017-10-02 14:52:14 +020038import org.junit.Test;
39import org.junit.runner.RunWith;
40import org.junit.runners.JUnit4;
41
42/** Unit tests for {@link LocationExpander.LocationFunction}. */
43@RunWith(JUnit4.class)
44public class LocationFunctionTest {
ulfjack04509fa2017-10-02 14:52:14 +020045
46 @Test
47 public void absoluteAndRelativeLabels() throws Exception {
48 LocationFunction func =
49 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/src/bar").build();
dannarkc7c5ab12018-06-21 14:40:46 -070050 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("src/bar");
51 assertThat(func.apply(":foo", ImmutableMap.of())).isEqualTo("src/bar");
52 assertThat(func.apply("foo", ImmutableMap.of())).isEqualTo("src/bar");
ulfjack04509fa2017-10-02 14:52:14 +020053 }
54
55 @Test
56 public void pathUnderExecRootUsesDotSlash() throws Exception {
57 LocationFunction func =
58 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/bar").build();
dannarkc7c5ab12018-06-21 14:40:46 -070059 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("./bar");
ulfjack04509fa2017-10-02 14:52:14 +020060 }
61
62 @Test
63 public void noSuchLabel() throws Exception {
64 LocationFunction func = new LocationFunctionBuilder("//foo", false).build();
jcater42edea62019-05-01 08:46:18 -070065 IllegalStateException expected =
66 assertThrows(IllegalStateException.class, () -> func.apply("//bar", ImmutableMap.of()));
67 assertThat(expected)
68 .hasMessageThat()
69 .isEqualTo(
70 "label '//bar:bar' in $(location) expression is not a declared prerequisite of this "
71 + "rule");
ulfjack04509fa2017-10-02 14:52:14 +020072 }
73
74 @Test
75 public void emptyList() throws Exception {
76 LocationFunction func = new LocationFunctionBuilder("//foo", false).add("//foo").build();
jcater42edea62019-05-01 08:46:18 -070077 IllegalStateException expected =
78 assertThrows(IllegalStateException.class, () -> func.apply("//foo", ImmutableMap.of()));
79 assertThat(expected)
80 .hasMessageThat()
81 .isEqualTo("label '//foo:foo' in $(location) expression expands to no files");
ulfjack04509fa2017-10-02 14:52:14 +020082 }
83
84 @Test
85 public void tooMany() throws Exception {
86 LocationFunction func =
87 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/1", "/exec/2").build();
jcater42edea62019-05-01 08:46:18 -070088 IllegalStateException expected =
89 assertThrows(IllegalStateException.class, () -> func.apply("//foo", ImmutableMap.of()));
90 assertThat(expected)
91 .hasMessageThat()
92 .isEqualTo(
93 "label '//foo:foo' in $(location) expression expands to more than one file, "
94 + "please use $(locations //foo:foo) instead. Files (at most 5 shown) are: "
95 + "[./1, ./2]");
ulfjack04509fa2017-10-02 14:52:14 +020096 }
97
98 @Test
99 public void noSuchLabelMultiple() throws Exception {
100 LocationFunction func = new LocationFunctionBuilder("//foo", true).build();
jcater42edea62019-05-01 08:46:18 -0700101 IllegalStateException expected =
102 assertThrows(IllegalStateException.class, () -> func.apply("//bar", ImmutableMap.of()));
103 assertThat(expected)
104 .hasMessageThat()
105 .isEqualTo(
106 "label '//bar:bar' in $(locations) expression is not a declared prerequisite of this "
107 + "rule");
ulfjack04509fa2017-10-02 14:52:14 +0200108 }
109
110 @Test
111 public void fileWithSpace() throws Exception {
112 LocationFunction func =
113 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/file/with space").build();
dannarkc7c5ab12018-06-21 14:40:46 -0700114 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("'file/with space'");
ulfjack04509fa2017-10-02 14:52:14 +0200115 }
116
117 @Test
118 public void multipleFiles() throws Exception {
119 LocationFunction func = new LocationFunctionBuilder("//foo", true)
120 .add("//foo", "/exec/foo/bar", "/exec/out/foo/foobar")
121 .build();
dannarkc7c5ab12018-06-21 14:40:46 -0700122 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("foo/bar foo/foobar");
ulfjack04509fa2017-10-02 14:52:14 +0200123 }
124
125 @Test
126 public void filesWithSpace() throws Exception {
127 LocationFunction func = new LocationFunctionBuilder("//foo", true)
128 .add("//foo", "/exec/file/with space", "/exec/file/with spaces ")
129 .build();
dannarkc7c5ab12018-06-21 14:40:46 -0700130 assertThat(func.apply("//foo", ImmutableMap.of()))
131 .isEqualTo("'file/with space' 'file/with spaces '");
ulfjack04509fa2017-10-02 14:52:14 +0200132 }
133
134 @Test
135 public void execPath() throws Exception {
136 LocationFunction func = new LocationFunctionBuilder("//foo", true)
137 .setExecPaths(true)
138 .add("//foo", "/exec/bar", "/exec/out/foobar")
139 .build();
dannarkc7c5ab12018-06-21 14:40:46 -0700140 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("./bar out/foobar");
141 }
142
143 @Test
144 public void locationFunctionWithMappingReplace() throws Exception {
145 RepositoryName a = RepositoryName.create("@a");
146 RepositoryName b = RepositoryName.create("@b");
147 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(a, b);
148 LocationFunction func =
149 new LocationFunctionBuilder("//foo", false).add("@b//foo", "/exec/src/bar").build();
150 assertThat(func.apply("@a//foo", repositoryMapping)).isEqualTo("src/bar");
151 }
152
153 @Test
154 public void locationFunctionWithMappingIgnoreRepo() throws Exception {
155 RepositoryName a = RepositoryName.create("@a");
156 RepositoryName b = RepositoryName.create("@b");
157 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(a, b);
158 LocationFunction func =
159 new LocationFunctionBuilder("//foo", false).add("@potato//foo", "/exec/src/bar").build();
160 assertThat(func.apply("@potato//foo", repositoryMapping)).isEqualTo("src/bar");
ulfjack04509fa2017-10-02 14:52:14 +0200161 }
dannark25d5efc2018-04-30 09:27:58 -0700162}
ulfjack04509fa2017-10-02 14:52:14 +0200163
dannark25d5efc2018-04-30 09:27:58 -0700164final class LocationFunctionBuilder {
165 private final Label root;
166 private final boolean multiple;
167 private boolean execPaths;
Googler181bd1a2020-11-12 08:15:06 -0800168 private boolean legacyExternalRunfiles;
dannark25d5efc2018-04-30 09:27:58 -0700169 private final Map<Label, Collection<Artifact>> labelMap = new HashMap<>();
ulfjack04509fa2017-10-02 14:52:14 +0200170
dannark25d5efc2018-04-30 09:27:58 -0700171 LocationFunctionBuilder(String rootLabel, boolean multiple) {
172 this.root = Label.parseAbsoluteUnchecked(rootLabel);
173 this.multiple = multiple;
174 }
ulfjack04509fa2017-10-02 14:52:14 +0200175
dannark25d5efc2018-04-30 09:27:58 -0700176 public LocationFunction build() {
Googler181bd1a2020-11-12 08:15:06 -0800177 return new LocationFunction(
178 root, Suppliers.ofInstance(labelMap), execPaths, legacyExternalRunfiles, multiple);
dannark25d5efc2018-04-30 09:27:58 -0700179 }
ulfjack04509fa2017-10-02 14:52:14 +0200180
dannark25d5efc2018-04-30 09:27:58 -0700181 public LocationFunctionBuilder setExecPaths(boolean execPaths) {
182 this.execPaths = execPaths;
183 return this;
184 }
ulfjack04509fa2017-10-02 14:52:14 +0200185
Googler181bd1a2020-11-12 08:15:06 -0800186 public LocationFunctionBuilder setLegacyExternalRunfiles(boolean legacyExternalRunfiles) {
187 this.legacyExternalRunfiles = legacyExternalRunfiles;
188 return this;
189 }
190
dannark25d5efc2018-04-30 09:27:58 -0700191 public LocationFunctionBuilder add(String label, String... paths) {
192 labelMap.put(
193 Label.parseAbsoluteUnchecked(label),
194 Arrays.stream(paths)
195 .map(LocationFunctionBuilder::makeArtifact)
196 .collect(Collectors.toList()));
197 return this;
198 }
199
200 private static Artifact makeArtifact(String path) {
janakr97c0bd12020-09-08 13:19:03 -0700201 FileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);
dannark25d5efc2018-04-30 09:27:58 -0700202 if (path.startsWith("/exec/out")) {
janakraea05602019-05-22 15:41:29 -0700203 return ActionsTestUtil.createArtifact(
Googlerf0b0c392021-01-27 17:56:52 -0800204 ArtifactRoot.asDerivedRoot(fs.getPath("/exec"), RootType.Output, "out"),
Googler660f5b22021-01-25 09:40:17 -0800205 fs.getPath(path));
dannark25d5efc2018-04-30 09:27:58 -0700206 } else {
janakraea05602019-05-22 15:41:29 -0700207 return ActionsTestUtil.createArtifact(
208 ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/exec"))), fs.getPath(path));
ulfjack04509fa2017-10-02 14:52:14 +0200209 }
210 }
211}