blob: 1ab683537a70acbbc712cb99c941deb9136612c4 [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;
janakraea05602019-05-22 15:41:29 -070024import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
ulfjack04509fa2017-10-02 14:52:14 +020025import com.google.devtools.build.lib.analysis.LocationExpander.LocationFunction;
26import com.google.devtools.build.lib.cmdline.Label;
dannarkc7c5ab12018-06-21 14:40:46 -070027import com.google.devtools.build.lib.cmdline.RepositoryName;
ulfjack04509fa2017-10-02 14:52:14 +020028import com.google.devtools.build.lib.vfs.FileSystem;
tomluee6a6862018-01-17 14:36:26 -080029import com.google.devtools.build.lib.vfs.Root;
ulfjack04509fa2017-10-02 14:52:14 +020030import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
31import java.util.Arrays;
32import java.util.Collection;
33import java.util.HashMap;
34import java.util.Map;
35import java.util.stream.Collectors;
ulfjack04509fa2017-10-02 14:52:14 +020036import org.junit.Test;
37import org.junit.runner.RunWith;
38import org.junit.runners.JUnit4;
39
40/** Unit tests for {@link LocationExpander.LocationFunction}. */
41@RunWith(JUnit4.class)
42public class LocationFunctionTest {
ulfjack04509fa2017-10-02 14:52:14 +020043
44 @Test
45 public void absoluteAndRelativeLabels() throws Exception {
46 LocationFunction func =
47 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/src/bar").build();
dannarkc7c5ab12018-06-21 14:40:46 -070048 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("src/bar");
49 assertThat(func.apply(":foo", ImmutableMap.of())).isEqualTo("src/bar");
50 assertThat(func.apply("foo", ImmutableMap.of())).isEqualTo("src/bar");
ulfjack04509fa2017-10-02 14:52:14 +020051 }
52
53 @Test
54 public void pathUnderExecRootUsesDotSlash() throws Exception {
55 LocationFunction func =
56 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/bar").build();
dannarkc7c5ab12018-06-21 14:40:46 -070057 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("./bar");
ulfjack04509fa2017-10-02 14:52:14 +020058 }
59
60 @Test
61 public void noSuchLabel() throws Exception {
62 LocationFunction func = new LocationFunctionBuilder("//foo", false).build();
jcater42edea62019-05-01 08:46:18 -070063 IllegalStateException expected =
64 assertThrows(IllegalStateException.class, () -> func.apply("//bar", ImmutableMap.of()));
65 assertThat(expected)
66 .hasMessageThat()
67 .isEqualTo(
68 "label '//bar:bar' in $(location) expression is not a declared prerequisite of this "
69 + "rule");
ulfjack04509fa2017-10-02 14:52:14 +020070 }
71
72 @Test
73 public void emptyList() throws Exception {
74 LocationFunction func = new LocationFunctionBuilder("//foo", false).add("//foo").build();
jcater42edea62019-05-01 08:46:18 -070075 IllegalStateException expected =
76 assertThrows(IllegalStateException.class, () -> func.apply("//foo", ImmutableMap.of()));
77 assertThat(expected)
78 .hasMessageThat()
79 .isEqualTo("label '//foo:foo' in $(location) expression expands to no files");
ulfjack04509fa2017-10-02 14:52:14 +020080 }
81
82 @Test
83 public void tooMany() throws Exception {
84 LocationFunction func =
85 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/1", "/exec/2").build();
jcater42edea62019-05-01 08:46:18 -070086 IllegalStateException expected =
87 assertThrows(IllegalStateException.class, () -> func.apply("//foo", ImmutableMap.of()));
88 assertThat(expected)
89 .hasMessageThat()
90 .isEqualTo(
91 "label '//foo:foo' in $(location) expression expands to more than one file, "
92 + "please use $(locations //foo:foo) instead. Files (at most 5 shown) are: "
93 + "[./1, ./2]");
ulfjack04509fa2017-10-02 14:52:14 +020094 }
95
96 @Test
97 public void noSuchLabelMultiple() throws Exception {
98 LocationFunction func = new LocationFunctionBuilder("//foo", true).build();
jcater42edea62019-05-01 08:46:18 -070099 IllegalStateException expected =
100 assertThrows(IllegalStateException.class, () -> func.apply("//bar", ImmutableMap.of()));
101 assertThat(expected)
102 .hasMessageThat()
103 .isEqualTo(
104 "label '//bar:bar' in $(locations) expression is not a declared prerequisite of this "
105 + "rule");
ulfjack04509fa2017-10-02 14:52:14 +0200106 }
107
108 @Test
109 public void fileWithSpace() throws Exception {
110 LocationFunction func =
111 new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/file/with space").build();
dannarkc7c5ab12018-06-21 14:40:46 -0700112 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("'file/with space'");
ulfjack04509fa2017-10-02 14:52:14 +0200113 }
114
115 @Test
116 public void multipleFiles() throws Exception {
117 LocationFunction func = new LocationFunctionBuilder("//foo", true)
118 .add("//foo", "/exec/foo/bar", "/exec/out/foo/foobar")
119 .build();
dannarkc7c5ab12018-06-21 14:40:46 -0700120 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("foo/bar foo/foobar");
ulfjack04509fa2017-10-02 14:52:14 +0200121 }
122
123 @Test
124 public void filesWithSpace() throws Exception {
125 LocationFunction func = new LocationFunctionBuilder("//foo", true)
126 .add("//foo", "/exec/file/with space", "/exec/file/with spaces ")
127 .build();
dannarkc7c5ab12018-06-21 14:40:46 -0700128 assertThat(func.apply("//foo", ImmutableMap.of()))
129 .isEqualTo("'file/with space' 'file/with spaces '");
ulfjack04509fa2017-10-02 14:52:14 +0200130 }
131
132 @Test
133 public void execPath() throws Exception {
134 LocationFunction func = new LocationFunctionBuilder("//foo", true)
135 .setExecPaths(true)
136 .add("//foo", "/exec/bar", "/exec/out/foobar")
137 .build();
dannarkc7c5ab12018-06-21 14:40:46 -0700138 assertThat(func.apply("//foo", ImmutableMap.of())).isEqualTo("./bar out/foobar");
139 }
140
141 @Test
142 public void locationFunctionWithMappingReplace() throws Exception {
143 RepositoryName a = RepositoryName.create("@a");
144 RepositoryName b = RepositoryName.create("@b");
145 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(a, b);
146 LocationFunction func =
147 new LocationFunctionBuilder("//foo", false).add("@b//foo", "/exec/src/bar").build();
148 assertThat(func.apply("@a//foo", repositoryMapping)).isEqualTo("src/bar");
149 }
150
151 @Test
152 public void locationFunctionWithMappingIgnoreRepo() throws Exception {
153 RepositoryName a = RepositoryName.create("@a");
154 RepositoryName b = RepositoryName.create("@b");
155 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(a, b);
156 LocationFunction func =
157 new LocationFunctionBuilder("//foo", false).add("@potato//foo", "/exec/src/bar").build();
158 assertThat(func.apply("@potato//foo", repositoryMapping)).isEqualTo("src/bar");
ulfjack04509fa2017-10-02 14:52:14 +0200159 }
dannark25d5efc2018-04-30 09:27:58 -0700160}
ulfjack04509fa2017-10-02 14:52:14 +0200161
dannark25d5efc2018-04-30 09:27:58 -0700162final class LocationFunctionBuilder {
163 private final Label root;
164 private final boolean multiple;
165 private boolean execPaths;
166 private final Map<Label, Collection<Artifact>> labelMap = new HashMap<>();
ulfjack04509fa2017-10-02 14:52:14 +0200167
dannark25d5efc2018-04-30 09:27:58 -0700168 LocationFunctionBuilder(String rootLabel, boolean multiple) {
169 this.root = Label.parseAbsoluteUnchecked(rootLabel);
170 this.multiple = multiple;
171 }
ulfjack04509fa2017-10-02 14:52:14 +0200172
dannark25d5efc2018-04-30 09:27:58 -0700173 public LocationFunction build() {
174 return new LocationFunction(root, Suppliers.ofInstance(labelMap), execPaths, multiple);
175 }
ulfjack04509fa2017-10-02 14:52:14 +0200176
dannark25d5efc2018-04-30 09:27:58 -0700177 public LocationFunctionBuilder setExecPaths(boolean execPaths) {
178 this.execPaths = execPaths;
179 return this;
180 }
ulfjack04509fa2017-10-02 14:52:14 +0200181
dannark25d5efc2018-04-30 09:27:58 -0700182 public LocationFunctionBuilder add(String label, String... paths) {
183 labelMap.put(
184 Label.parseAbsoluteUnchecked(label),
185 Arrays.stream(paths)
186 .map(LocationFunctionBuilder::makeArtifact)
187 .collect(Collectors.toList()));
188 return this;
189 }
190
191 private static Artifact makeArtifact(String path) {
ccalvarinc9efd062018-07-27 12:46:46 -0700192 FileSystem fs = new InMemoryFileSystem();
dannark25d5efc2018-04-30 09:27:58 -0700193 if (path.startsWith("/exec/out")) {
janakraea05602019-05-22 15:41:29 -0700194 return ActionsTestUtil.createArtifact(
195 ArtifactRoot.asDerivedRoot(fs.getPath("/exec"), fs.getPath("/exec/out")),
196 fs.getPath(path));
dannark25d5efc2018-04-30 09:27:58 -0700197 } else {
janakraea05602019-05-22 15:41:29 -0700198 return ActionsTestUtil.createArtifact(
199 ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/exec"))), fs.getPath(path));
ulfjack04509fa2017-10-02 14:52:14 +0200200 }
201 }
202}