| // Copyright 2015 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.packages; | |
| import static com.google.common.truth.Truth.assertThat; | |
| import com.google.common.base.Preconditions; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.AttributeValueGetter; | |
| import com.google.devtools.build.lib.testutil.Suite; | |
| import com.google.devtools.build.lib.testutil.TestSpec; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.LinkedHashSet; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Set; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| /** | |
| * Tests for {@link ImplicitOutputsFunction}. | |
| */ | |
| @TestSpec(size = Suite.SMALL_TESTS) | |
| @RunWith(JUnit4.class) | |
| public final class ImplicitOutputsFunctionTest { | |
| private void assertPlaceholderCollection( | |
| String template, String expectedTemplate, String... expectedPlaceholders) throws Exception { | |
| List<String> actualPlaceholders = new ArrayList<>(); | |
| assertThat( | |
| ImplicitOutputsFunction.createPlaceholderSubstitutionFormatString( | |
| template, actualPlaceholders)) | |
| .isEqualTo(expectedTemplate); | |
| assertThat(actualPlaceholders) | |
| .containsExactlyElementsIn(Arrays.asList(expectedPlaceholders)) | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testNoPlaceholder() throws Exception { | |
| assertPlaceholderCollection("foo", "foo"); | |
| } | |
| @Test | |
| public void testJustPlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{foo}", "%s", "foo"); | |
| } | |
| @Test | |
| public void testPrefixedPlaceholder() throws Exception { | |
| assertPlaceholderCollection("foo%{bar}", "foo%s", "bar"); | |
| } | |
| @Test | |
| public void testSuffixedPlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{foo}bar", "%sbar", "foo"); | |
| } | |
| @Test | |
| public void testMultiplePlaceholdersPrefixed() throws Exception { | |
| assertPlaceholderCollection("foo%{bar}baz%{qux}", "foo%sbaz%s", "bar", "qux"); | |
| } | |
| @Test | |
| public void testMultiplePlaceholdersSuffixed() throws Exception { | |
| assertPlaceholderCollection("%{foo}bar%{baz}qux", "%sbar%squx", "foo", "baz"); | |
| } | |
| @Test | |
| public void testTightlyPackedPlaceholders() throws Exception { | |
| assertPlaceholderCollection("%{foo}%{bar}%{baz}", "%s%s%s", "foo", "bar", "baz"); | |
| } | |
| @Test | |
| public void testIncompletePlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{foo", "%%{foo"); | |
| } | |
| @Test | |
| public void testCompleteAndIncompletePlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{foo}%{bar", "%s%%{bar", "foo"); | |
| } | |
| @Test | |
| public void testPlaceholderLooksLikeNestedIncompletePlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{%{foo", "%%{%%{foo"); | |
| } | |
| @Test | |
| public void testPlaceholderLooksLikeNestedPlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{%{foo}", "%s", "%{foo"); | |
| } | |
| @Test | |
| public void testEscapesJustPercentSign() throws Exception { | |
| assertPlaceholderCollection("%", "%%"); | |
| } | |
| @Test | |
| public void testEscapesPrintfPlaceholder() throws Exception { | |
| assertPlaceholderCollection("%{x}%s%{y}", "%s%%s%s", "x", "y"); | |
| } | |
| @Test | |
| public void testEscapesPercentSign() throws Exception { | |
| assertPlaceholderCollection("foo%{bar}%baz", "foo%s%%baz", "bar"); | |
| } | |
| private static AttributeValueGetter attrs( | |
| final Map<String, ? extends Collection<String>> values) { | |
| return new AttributeValueGetter() { | |
| @Override | |
| public Set<String> get(AttributeMap ignored, String attr) { | |
| return new LinkedHashSet<>(Preconditions.checkNotNull(values.get(attr))); | |
| } | |
| }; | |
| } | |
| private void assertPlaceholderSubtitution( | |
| String template, | |
| AttributeValueGetter attrValues, | |
| String[] expectedSubstitutions, | |
| String[] expectedFoundPlaceholders) | |
| throws Exception { | |
| // Directly call into ParsedTemplate in order to access the attribute names. | |
| ImplicitOutputsFunction.ParsedTemplate parsedTemplate = | |
| ImplicitOutputsFunction.ParsedTemplate.parse(template); | |
| assertThat(parsedTemplate.attributeNames()) | |
| .containsExactlyElementsIn(Arrays.asList(expectedFoundPlaceholders)) | |
| .inOrder(); | |
| // Test the actual substitution code. | |
| List<String> substitutions = | |
| ImplicitOutputsFunction.substitutePlaceholderIntoTemplate(template, null, attrValues); | |
| assertThat(substitutions) | |
| .containsExactlyElementsIn(Arrays.asList(expectedSubstitutions)); | |
| } | |
| @Test | |
| public void testSingleScalarElementSubstitution() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "%{x}", | |
| attrs(ImmutableMap.of("x", ImmutableList.of("a"))), | |
| new String[] {"a"}, | |
| new String[] {"x"}); | |
| } | |
| @Test | |
| public void testSingleVectorElementSubstitution() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "%{x}", | |
| attrs(ImmutableMap.of("x", ImmutableList.of("a", "b", "c"))), | |
| new String[] {"a", "b", "c"}, | |
| new String[] {"x"}); | |
| } | |
| @Test | |
| public void testMultipleElementsSubstitution() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "%{x}-%{y}-%{z}", | |
| attrs( | |
| ImmutableMap.of( | |
| "x", ImmutableList.of("foo", "bar", "baz"), | |
| "y", ImmutableList.of("meow"), | |
| "z", ImmutableList.of("1", "2"))), | |
| new String[] { | |
| "foo-meow-1", "foo-meow-2", "bar-meow-1", "bar-meow-2", "baz-meow-1", "baz-meow-2" | |
| }, | |
| new String[] {"x", "y", "z"}); | |
| } | |
| @Test | |
| public void testEmptyElementSubstitution() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "a-%{x}", | |
| attrs(ImmutableMap.of("x", ImmutableList.<String>of())), | |
| new String[0], | |
| new String[] {"x"}); | |
| } | |
| @Test | |
| public void testSamePlaceholderMultipleTimes() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "%{x}-%{y}-%{x}", | |
| attrs(ImmutableMap.of("x", ImmutableList.of("a", "b"), "y", ImmutableList.of("1", "2"))), | |
| new String[] {"a-1-a", "a-1-b", "a-2-a", "a-2-b", "b-1-a", "b-1-b", "b-2-a", "b-2-b"}, | |
| new String[] {"x", "y", "x"}); | |
| } | |
| @Test | |
| public void testRepeatingPlaceholderValue() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "%{x}", | |
| attrs(ImmutableMap.of("x", ImmutableList.of("a", "a"))), | |
| new String[] {"a"}, | |
| new String[] {"x"}); | |
| } | |
| @Test | |
| public void testIncompletePlaceholderTreatedAsText() throws Exception { | |
| assertPlaceholderSubtitution( | |
| "%{x}-%{y-%{z", | |
| attrs(ImmutableMap.of("x", ImmutableList.of("a", "b"))), | |
| new String[] {"a-%{y-%{z", "b-%{y-%{z"}, | |
| new String[] {"x"}); | |
| } | |
| } |