From 3b2ac8e731f6e523e96ddcd4886164d9e0acffa6 Mon Sep 17 00:00:00 2001 From: Ulf Adams Date: Thu, 23 Apr 2015 19:09:50 +0000 Subject: Open source more analysis tests. -- MOS_MIGRATED_REVID=91909389 --- .../build/lib/analysis/LabelExpanderTest.java | 257 +++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 src/test/java/com/google/devtools/build/lib/analysis/LabelExpanderTest.java (limited to 'src/test/java/com/google/devtools/build/lib/analysis/LabelExpanderTest.java') diff --git a/src/test/java/com/google/devtools/build/lib/analysis/LabelExpanderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/LabelExpanderTest.java new file mode 100644 index 0000000000..708408f9d9 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/analysis/LabelExpanderTest.java @@ -0,0 +1,257 @@ +// Copyright 2010-2015 Google Inc. 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 com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; +import com.google.devtools.build.lib.syntax.Label; +import com.google.devtools.build.lib.syntax.Label.SyntaxException; +import com.google.devtools.build.lib.testutil.Suite; +import com.google.devtools.build.lib.testutil.TestSpec; +import com.google.devtools.build.lib.vfs.PathFragment; + +import java.util.Map; + +/** + * Tests for {@link LabelExpander}. + */ +@TestSpec(size = Suite.SMALL_TESTS) +public class LabelExpanderTest extends BuildViewTestCase { + /** + * A dummy target that resolves labels and receives errors. + */ + private ConfiguredTarget dummyTarget; + + /** + * Artifacts generated by {@code dummyTarget} identified by their + * root-relative paths; to be used for mock label-to-artifact mappings. + */ + private Map artifactsByName; + + /** + * All characters that the heuristic considers to be part of a target. + * This is a subset of the allowed label characters. The ones left out may + * have a special meaning during expression expansion: + * + * + */ + private static final String allowedChars = "_/.-+" + PathFragment.SEPARATOR_CHAR + + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + // Helper methods ----------------------------------------------------------- + + private void setupDummy() throws Exception { + dummyTarget = scratchConfiguredTarget( + "foo", "foo", + "filegroup(name = 'foo',", + " srcs = ['x1','x2','bar/x3', '" + allowedChars + "', 'xx11', 'x11', 'xx1'])"); + collectArtifacts(); + } + + /** + * Collects all generated mock artifacts for {@code dummyTarget} and assigns + * the result to {@code artifactsByName}. + */ + private void collectArtifacts() { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Artifact artifact : getFilesToBuild(dummyTarget)) { + builder.put(artifact.getRootRelativePath().toString(), artifact); + } + artifactsByName = builder.build(); + } + + /** + * Gets a generated artifact object for a target in package "foo" from {@code + * artifactsByName}. + */ + private Artifact artifactFor(String targetName) { + return artifactsByName.get("foo/" + targetName); + } + + /** + * Creates fake label in package "foo". + */ + private static Label labelFor(String targetName) throws SyntaxException { + return Label.create("foo", targetName); + } + + /** + * Asserts that an expansion with a given mapping produces the expected + * results. + */ + private void assertExpansion(String expectedResult, String expressionToExpand, + Map> mapping) throws Exception { + assertEquals(expectedResult, + LabelExpander.expand(expressionToExpand, mapping, dummyTarget.getLabel())); + } + + /** + * Asserts that an expansion with an empty mapping produces the expected + * results. + */ + private void assertExpansion(String expected, String original) throws Exception { + assertExpansion(expected, original, ImmutableMap.>of()); + } + + // Actual tests ------------------------------------------------------------- + + /** + * Tests that if no mapping is specified, then strings expand to themselves. + */ + public void testStringExpandsToItselfWhenNoMappingSpecified() throws Exception { + setupDummy(); + assertExpansion("", null); + assertExpansion("cmd", "cmd"); + assertExpansion("//x:y,:z,w", "//x:y,:z,w"); + assertExpansion(allowedChars, allowedChars); + } + + /** + * Tests that in case of a one-to-one label-to-artifact mapping the expansion + * produces the expected results. + */ + public void testExpansion() throws Exception { + setupDummy(); + assertExpansion("foo/x1", "x1", ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + + assertExpansion("foo/x1", ":x1", ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + + assertExpansion("foo/x1", "//foo:x1", ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + } + + /** + * Tests that label extraction works as expected - disallowed label characters + * are resolved to themselves. + */ + public void testLabelExtraction() throws Exception { + setupDummy(); + assertExpansion("(foo/" + allowedChars + ")", "(//foo:" + allowedChars + ")", + ImmutableMap.>of( + labelFor(allowedChars), ImmutableList.of(artifactFor(allowedChars)))); + + assertExpansion("foo/x1,foo/x2=foo/bar/x3", "x1,x2=bar/x3", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x2"), ImmutableList.of(artifactFor("x2")), + labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3")))); + } + + /** + * Tests that an exception is thrown when the mapping is not one-to-one. + */ + public void testThrowsWhenMappingIsNotOneToOne() throws Exception { + setupDummy(); + try { + LabelExpander.expand("x1", ImmutableMap.>of( + labelFor("x1"), ImmutableList.of()), dummyTarget.getLabel()); + + fail("Expected an exception."); + } catch (LabelExpander.NotUniqueExpansionException nuee) { + // was expected + } + + try { + LabelExpander.expand("x1", ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1"), artifactFor("x2"))), + dummyTarget.getLabel()); + + fail("Expected an exception."); + } catch (LabelExpander.NotUniqueExpansionException nuee) { + // was expected + } + } + + /** + * Tests expanding labels that result in a SyntaxException. + */ + public void testIllFormedLabels() throws Exception { + setupDummy(); + assertExpansion("x1:x2:x3", "x1:x2:x3", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x2"), ImmutableList.of(artifactFor("x2")), + labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3")))); + + assertExpansion("foo://x1 x1/../x2", "foo://x1 x1/../x2", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x2"), ImmutableList.of(artifactFor("x2")), + labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3")))); + + assertExpansion("//foo:/x1", "//foo:/x1", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + + assertExpansion("//foo:../x1", "//foo:../x1", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + + assertExpansion("//foo:x1/../x2", "//foo:x1/../x2", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x2"), ImmutableList.of(artifactFor("x2")))); + + assertExpansion("//foo:x1/./x2", "//foo:x1/./x2", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x2"), ImmutableList.of(artifactFor("x2")))); + + assertExpansion("//foo:x1//x2", "//foo:x1//x2", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x2"), ImmutableList.of(artifactFor("x2")))); + + assertExpansion("//foo:x1/..", "//foo:x1/..", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + + assertExpansion("//foo:x1/", "//foo:x1/", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + + assertExpansion(":", ":"); + } + + /** + * Tests that label parsing is greedy (always extracting the longest + * possible label). This means that if a label is a substring of another + * label, it should not be expanded but be treated as part of the longer one. + */ + public void testLabelIsSubstringOfValidLabel() throws Exception { + setupDummy(); + assertExpansion("x3=foo/bar/x3", "x3=bar/x3", + ImmutableMap.>of( + labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3")))); + + assertExpansion("foo/x1,foo/x11,foo/xx1,foo/xx11", "x1,x11,xx1,xx11", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")), + labelFor("x11"), ImmutableList.of(artifactFor("x11")), + labelFor("xx1"), ImmutableList.of(artifactFor("xx1")), + labelFor("xx11"), ImmutableList.of(artifactFor("xx11")))); + + assertExpansion("//x1", "//x1", + ImmutableMap.>of( + labelFor("x1"), ImmutableList.of(artifactFor("x1")))); + } +} -- cgit v1.2.3