aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2017-10-02 14:52:14 +0200
committerGravatar Klaus Aehlig <aehlig@google.com>2017-10-02 15:44:56 +0200
commit04509fafe9ab796f088660ed2580a013b2ad3cf6 (patch)
tree376ce124ba9f8089cdf95995fba1a4d1c0fb436c /src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
parentc174cc2c50215d7e7919c7cd01ee7880206df142 (diff)
Rewrite LocationExpander
Split up the functionality into separate classes, and test each independently. (Keep one integration test to make sure it still works together.) This is in preparation for adding another location function for runfiles paths. Currently we have to decide ahead of time whether to expand artifacts as exec paths or root-relative (runfiles) paths, but there are cases where we can't make that decision ahead of time and / or need both to coexist, even in the same attribute. Progress on #2475. PiperOrigin-RevId: 170691666
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java')
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
new file mode 100644
index 0000000000..676255fbd8
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
@@ -0,0 +1,189 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.analysis;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.base.Suppliers;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.analysis.LocationExpander.LocationFunction;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link LocationExpander.LocationFunction}. */
+@RunWith(JUnit4.class)
+public class LocationFunctionTest {
+ private FileSystem fs;
+
+ @Before
+ public void createFileSystem() throws Exception {
+ fs = new InMemoryFileSystem();
+ }
+
+ private Artifact makeArtifact(String path) {
+ if (path.startsWith("/exec/out")) {
+ return new Artifact(
+ fs.getPath(path), Root.asDerivedRoot(fs.getPath("/exec"), fs.getPath("/exec/out")));
+ } else {
+ return new Artifact(fs.getPath(path), Root.asSourceRoot(fs.getPath("/exec")));
+ }
+ }
+
+ @Test
+ public void absoluteAndRelativeLabels() throws Exception {
+ LocationFunction func =
+ new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/src/bar").build();
+ assertThat(func.apply("//foo")).isEqualTo("src/bar");
+ assertThat(func.apply(":foo")).isEqualTo("src/bar");
+ assertThat(func.apply("foo")).isEqualTo("src/bar");
+ }
+
+ @Test
+ public void pathUnderExecRootUsesDotSlash() throws Exception {
+ LocationFunction func =
+ new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/bar").build();
+ assertThat(func.apply("//foo")).isEqualTo("./bar");
+ }
+
+ @Test
+ public void noSuchLabel() throws Exception {
+ LocationFunction func = new LocationFunctionBuilder("//foo", false).build();
+ try {
+ func.apply("//bar");
+ fail();
+ } catch (IllegalStateException expected) {
+ assertThat(expected).hasMessageThat()
+ .isEqualTo(
+ "label '//bar:bar' in $(location) expression is not a declared prerequisite of this "
+ + "rule");
+ }
+ }
+
+ @Test
+ public void emptyList() throws Exception {
+ LocationFunction func = new LocationFunctionBuilder("//foo", false).add("//foo").build();
+ try {
+ func.apply("//foo");
+ fail();
+ } catch (IllegalStateException expected) {
+ assertThat(expected).hasMessageThat()
+ .isEqualTo("label '//foo:foo' in $(location) expression expands to no files");
+ }
+ }
+
+ @Test
+ public void tooMany() throws Exception {
+ LocationFunction func =
+ new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/1", "/exec/2").build();
+ try {
+ func.apply("//foo");
+ fail();
+ } catch (IllegalStateException expected) {
+ assertThat(expected).hasMessageThat()
+ .isEqualTo(
+ "label '//foo:foo' in $(location) expression expands to more than one file, "
+ + "please use $(locations //foo:foo) instead. Files (at most 5 shown) are: "
+ + "[./1, ./2]");
+ }
+ }
+
+ @Test
+ public void noSuchLabelMultiple() throws Exception {
+ LocationFunction func = new LocationFunctionBuilder("//foo", true).build();
+ try {
+ func.apply("//bar");
+ fail();
+ } catch (IllegalStateException expected) {
+ assertThat(expected).hasMessageThat()
+ .isEqualTo(
+ "label '//bar:bar' in $(locations) expression is not a declared prerequisite of this "
+ + "rule");
+ }
+ }
+
+ @Test
+ public void fileWithSpace() throws Exception {
+ LocationFunction func =
+ new LocationFunctionBuilder("//foo", false).add("//foo", "/exec/file/with space").build();
+ assertThat(func.apply("//foo")).isEqualTo("'file/with space'");
+ }
+
+ @Test
+ public void multipleFiles() throws Exception {
+ LocationFunction func = new LocationFunctionBuilder("//foo", true)
+ .add("//foo", "/exec/foo/bar", "/exec/out/foo/foobar")
+ .build();
+ assertThat(func.apply("//foo")).isEqualTo("foo/bar foo/foobar");
+ }
+
+ @Test
+ public void filesWithSpace() throws Exception {
+ LocationFunction func = new LocationFunctionBuilder("//foo", true)
+ .add("//foo", "/exec/file/with space", "/exec/file/with spaces ")
+ .build();
+ assertThat(func.apply("//foo")).isEqualTo("'file/with space' 'file/with spaces '");
+ }
+
+ @Test
+ public void execPath() throws Exception {
+ LocationFunction func = new LocationFunctionBuilder("//foo", true)
+ .setExecPaths(true)
+ .add("//foo", "/exec/bar", "/exec/out/foobar")
+ .build();
+ assertThat(func.apply("//foo")).isEqualTo("./bar out/foobar");
+ }
+
+ private final class LocationFunctionBuilder {
+ private final Label root;
+ private final boolean multiple;
+ private boolean execPaths;
+ private final Map<Label, Collection<Artifact>> labelMap = new HashMap<>();
+
+ LocationFunctionBuilder(String rootLabel, boolean multiple) {
+ this.root = Label.parseAbsoluteUnchecked(rootLabel);
+ this.multiple = multiple;
+ }
+
+ public LocationFunction build() {
+ return new LocationFunction(root, Suppliers.ofInstance(labelMap), execPaths, multiple);
+ }
+
+ public LocationFunctionBuilder setExecPaths(boolean execPaths) {
+ this.execPaths = execPaths;
+ return this;
+ }
+
+ public LocationFunctionBuilder add(String label, String... paths) {
+ labelMap.put(
+ Label.parseAbsoluteUnchecked(label),
+ Arrays.stream(paths)
+ .map(LocationFunctionTest.this::makeArtifact)
+ .collect(Collectors.toList()));
+ return this;
+ }
+ }
+}