diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/analysis/stringtemplate/TemplateExpanderTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/analysis/stringtemplate/TemplateExpanderTest.java | 219 |
1 files changed, 140 insertions, 79 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/stringtemplate/TemplateExpanderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/stringtemplate/TemplateExpanderTest.java index fa61f091b3..d2740b6465 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/stringtemplate/TemplateExpanderTest.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/stringtemplate/TemplateExpanderTest.java @@ -18,132 +18,193 @@ import static org.junit.Assert.fail; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** - * Unit tests for the {@link - * com.google.devtools.build.lib.analysis.stringtemplate.TemplateExpander}, which expands variable - * references of the form <code>"$x"</code> and <code>"$(foo)"</code> into their corresponding - * values. + * Unit tests for the {@link TemplateExpander}. */ @RunWith(JUnit4.class) public class TemplateExpanderTest { + private static final class TemplateContextImpl implements TemplateContext { + private final Map<String, String> vars = new HashMap<>(); + private final Map<String, Function<String, String>> functions = new HashMap<>(); + + @Override + public String lookupVariable(String name) + throws ExpansionException { + // Not a Make variable. Let the shell handle the expansion. + if (name.startsWith("$")) { + return name; + } + if (!vars.containsKey(name)) { + throw new ExpansionException(String.format("$(%s) not defined", name)); + } + return vars.get(name); + } - private TemplateContext context; + @Override + public String lookupFunction(String name, String param) throws ExpansionException { + if (!functions.containsKey(name)) { + throw new ExpansionException(String.format("$(%s) not defined", name)); + } + return functions.get(name).apply(param); + } + } - private Map<String, String> vars = new HashMap<>(); + private TemplateContextImpl context; @Before public final void createContext() throws Exception { - context = new TemplateContext() { - @Override - public String lookupVariable(String name) - throws ExpansionException { - // Not a Make variable. Let the shell handle the expansion. - if (name.startsWith("$")) { - return name; - } - if (!vars.containsKey(name)) { - throw new ExpansionException(String.format("$(%s) not defined", name)); - } - return vars.get(name); - } - }; - - vars.put("SRCS", "src1 src2"); + context = new TemplateContextImpl(); } - private void assertExpansionEquals(String expected, String cmd) - throws ExpansionException { - assertThat(TemplateExpander.expand(cmd, context)).isEqualTo(expected); + private String expand(String value) throws ExpansionException { + return TemplateExpander.expand(value, context); } - private void assertExpansionFails(String expectedErrorSuffix, String cmd) { + private ExpansionException expansionFailure(String cmd) { try { - TemplateExpander.expand(cmd, context); + expand(cmd); fail("Expansion of " + cmd + " didn't fail as expected"); - } catch (Exception e) { - assertThat(e).hasMessageThat().isEqualTo(expectedErrorSuffix); + throw new AssertionError(); + } catch (ExpansionException e) { + return e; } } @Test - public void testExpansion() throws Exception { - vars.put("<", "src1"); - vars.put("OUTS", "out1 out2"); - vars.put("@", "out1"); - vars.put("^", "src1 src2 dep1 dep2"); - vars.put("@D", "outdir"); - vars.put("BINDIR", "bindir"); - - assertExpansionEquals("src1 src2", "$(SRCS)"); - assertExpansionEquals("src1", "$<"); - assertExpansionEquals("out1 out2", "$(OUTS)"); - assertExpansionEquals("out1", "$(@)"); - assertExpansionEquals("out1", "$@"); - assertExpansionEquals("out1,", "$@,"); - - assertExpansionEquals("src1 src2 out1 out2", "$(SRCS) $(OUTS)"); - - assertExpansionEquals("cmd", "cmd"); - assertExpansionEquals("cmd src1 src2,", "cmd $(SRCS),"); - assertExpansionEquals("label1 src1 src2,", "label1 $(SRCS),"); - assertExpansionEquals(":label1 src1 src2,", ":label1 $(SRCS),"); + public void testVariableExpansion() throws Exception { + context.vars.put("SRCS", "src1 src2"); + context.vars.put("<", "src1"); + context.vars.put("OUTS", "out1 out2"); + context.vars.put("@", "out1"); + context.vars.put("^", "src1 src2 dep1 dep2"); + context.vars.put("@D", "outdir"); + context.vars.put("BINDIR", "bindir"); + + assertThat(expand("$(SRCS)")).isEqualTo("src1 src2"); + assertThat(expand("$<")).isEqualTo("src1"); + assertThat(expand("$(OUTS)")).isEqualTo("out1 out2"); + assertThat(expand("$(@)")).isEqualTo("out1"); + assertThat(expand("$@")).isEqualTo("out1"); + assertThat(expand("$@,")).isEqualTo("out1,"); + + assertThat(expand("$(SRCS) $(OUTS)")).isEqualTo("src1 src2 out1 out2"); + + assertThat(expand("cmd")).isEqualTo("cmd"); + assertThat(expand("cmd $(SRCS),")).isEqualTo("cmd src1 src2,"); + assertThat(expand("label1 $(SRCS),")).isEqualTo("label1 src1 src2,"); + assertThat(expand(":label1 $(SRCS),")).isEqualTo(":label1 src1 src2,"); + } + + @Test + public void testUndefinedVariableExpansion() throws Exception { + assertThat(expansionFailure("$(foo)")) + .hasMessageThat().isEqualTo("$(foo) not defined"); + } + + @Test + public void testFunctionExpansion() throws Exception { + context.functions.put("foo", (String p) -> "FOO(" + p + ")"); + context.vars.put("bar", "bar"); + + assertThat(expand("$(foo baz)")).isEqualTo("FOO(baz)"); + assertThat(expand("$(bar) $(foo baz)")).isEqualTo("bar FOO(baz)"); + assertThat(expand("xyz$(foo baz)zyx")).isEqualTo("xyzFOO(baz)zyx"); + } + + @Test + public void testFunctionExpansionThrows() throws Exception { + try { + TemplateExpander.expand("$(foo baz)", new TemplateContext() { + @Override + public String lookupVariable(String name) throws ExpansionException { + throw new ExpansionException(name); + } + + @Override + public String lookupFunction(String name, String param) throws ExpansionException { + throw new ExpansionException(name + "(" + param + ")"); + } + }); + fail(); + } catch (ExpansionException e) { + assertThat(e).hasMessageThat().isEqualTo("foo(baz)"); + } + } + @Test + public void testUndefinedFunctionExpansion() throws Exception { // Note: $(location x) is considered an undefined variable; - assertExpansionFails("$(location label1) not defined", - "$(location label1), $(SRCS),"); + assertThat(expansionFailure("$(location label1), $(SRCS),")) + .hasMessageThat().isEqualTo("$(location) not defined"); + assertThat(expansionFailure("$(basename file)")) + .hasMessageThat().isEqualTo("$(basename) not defined"); } @Test public void testRecursiveExpansion() throws Exception { // Expansion is recursive: $(recursive) -> $(SRCS) -> "src1 src2" - vars.put("recursive", "$(SRCS)"); - assertExpansionEquals("src1 src2", "$(recursive)"); + context.vars.put("SRCS", "src1 src2"); + context.vars.put("recursive", "$(SRCS)"); + assertThat(expand("$(recursive)")).isEqualTo("src1 src2"); + } + @Test + public void testRecursiveExpansionDoesNotSpanExpansionBoundaries() throws Exception { // Recursion does not span expansion boundaries: // $(recur2a)$(recur2b) --> "$" + "(SRCS)" --/--> "src1 src2" - vars.put("recur2a", "$$"); - vars.put("recur2b", "(SRCS)"); - assertExpansionEquals("$(SRCS)", "$(recur2a)$(recur2b)"); + context.vars.put("SRCS", "src1 src2"); + context.vars.put("recur2a", "$$"); + context.vars.put("recur2b", "(SRCS)"); + assertThat(expand("$(recur2a)$(recur2b)")).isEqualTo("$(SRCS)"); } @Test - public void testInfiniteRecursionFailsGracefully() throws Exception { - vars.put("infinite", "$(infinite)"); - assertExpansionFails("potentially unbounded recursion during expansion " - + "of '$(infinite)'", - "$(infinite)"); + public void testSelfInfiniteExpansionFailsGracefully() throws Exception { + context.vars.put("infinite", "$(infinite)"); + assertThat(expansionFailure("$(infinite)")).hasMessageThat() + .isEqualTo("potentially unbounded recursion during expansion of '$(infinite)'"); + } - vars.put("black", "$(white)"); - vars.put("white", "$(black)"); - assertExpansionFails("potentially unbounded recursion during expansion " - + "of '$(black)'", - "$(white) is the new $(black)"); + @Test + public void testMutuallyInfiniteExpansionFailsGracefully() throws Exception { + context.vars.put("black", "$(white)"); + context.vars.put("white", "$(black)"); + assertThat(expansionFailure("$(white) is the new $(black)")).hasMessageThat() + .isEqualTo("potentially unbounded recursion during expansion of '$(black)'"); } @Test public void testErrors() throws Exception { - assertExpansionFails("unterminated variable reference", "$(SRCS"); - assertExpansionFails("unterminated $", "$"); + assertThat(expansionFailure("$(SRCS")).hasMessageThat() + .isEqualTo("unterminated variable reference"); + assertThat(expansionFailure("$")).hasMessageThat().isEqualTo("unterminated $"); String suffix = "instead for \"Make\" variables, or escape the '$' as '$$' if you intended " + "this for the shell"; - assertExpansionFails("'$file' syntax is not supported; use '$(file)' " + suffix, - "for file in a b c;do echo $file;done"); - assertExpansionFails("'${file%:.*8}' syntax is not supported; use '$(file%:.*8)' " + suffix, - "${file%:.*8}"); + assertThat(expansionFailure("for file in a b c;do echo $file;done")).hasMessageThat() + .isEqualTo("'$file' syntax is not supported; use '$(file)' " + suffix); + assertThat(expansionFailure("${file%:.*8}")).hasMessageThat() + .isEqualTo("'${file%:.*8}' syntax is not supported; use '$(file%:.*8)' " + suffix); + } + + @Test + public void testDollarDollar() throws Exception { + assertThat(expand("for file in a b c;do echo $$file;done")) + .isEqualTo("for file in a b c;do echo $file;done"); + assertThat(expand("$${file%:.*8}")).isEqualTo("${file%:.*8}"); + assertThat(expand("$$(basename file)")).isEqualTo("$(basename file)"); } + // Regression test: check that the parameter is trimmed before expanding. @Test - public void testShellVariables() throws Exception { - assertExpansionEquals("for file in a b c;do echo $file;done", - "for file in a b c;do echo $$file;done"); - assertExpansionEquals("${file%:.*8}", "$${file%:.*8}"); - assertExpansionFails("$(basename file) not defined", "$(basename file)"); - assertExpansionEquals("$(basename file)", "$$(basename file)"); + public void testFunctionExpansionIsTrimmed() throws Exception { + context.functions.put("foo", (String p) -> "FOO(" + p + ")"); + assertThat(expand("$(foo baz )")).isEqualTo("FOO(baz)"); } } |