| // 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.actions; | |
| import static com.google.common.truth.Truth.assertThat; | |
| import static com.google.devtools.build.lib.analysis.actions.CustomCommandLine.builder; | |
| import static org.junit.Assert.assertThrows; | |
| import static org.junit.Assert.fail; | |
| import com.google.common.base.Joiner; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact; | |
| import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType; | |
| import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact; | |
| import com.google.devtools.build.lib.actions.util.ActionsTestUtil; | |
| import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; | |
| import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; | |
| import com.google.devtools.build.lib.cmdline.Label; | |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; | |
| import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; | |
| import com.google.devtools.build.lib.collect.nestedset.Order; | |
| import com.google.devtools.build.lib.testutil.Scratch; | |
| import com.google.devtools.build.lib.util.Fingerprint; | |
| import com.google.devtools.build.lib.util.LazyString; | |
| import com.google.devtools.build.lib.vfs.PathFragment; | |
| import java.util.Arrays; | |
| import java.util.HashMap; | |
| import java.util.Map; | |
| import java.util.function.Consumer; | |
| import org.junit.Before; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| /** | |
| * Tests for CustomCommandLine. | |
| */ | |
| @RunWith(JUnit4.class) | |
| public class CustomCommandLineTest { | |
| private ArtifactRoot rootDir; | |
| private Artifact artifact1; | |
| private Artifact artifact2; | |
| @Before | |
| public void createArtifacts() throws Exception { | |
| Scratch scratch = new Scratch(); | |
| rootDir = ArtifactRoot.asDerivedRoot(scratch.dir("/exec/root"), "dir"); | |
| artifact1 = ActionsTestUtil.createArtifact(rootDir, scratch.file("/exec/root/dir/file1.txt")); | |
| artifact2 = ActionsTestUtil.createArtifact(rootDir, scratch.file("/exec/root/dir/file2.txt")); | |
| } | |
| @Test | |
| public void testScalarAdds() throws Exception { | |
| assertThat(builder().add("--arg").build().arguments()).containsExactly("--arg").inOrder(); | |
| assertThat(builder().addDynamicString("--arg").build().arguments()) | |
| .containsExactly("--arg") | |
| .inOrder(); | |
| assertThat( | |
| builder().addLabel(Label.parseAbsolute("//a:b", ImmutableMap.of())).build().arguments()) | |
| .containsExactly("//a:b") | |
| .inOrder(); | |
| assertThat(builder().addPath(PathFragment.create("path")).build().arguments()) | |
| .containsExactly("path") | |
| .inOrder(); | |
| assertThat(builder().addExecPath(artifact1).build().arguments()) | |
| .containsExactly("dir/file1.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addLazyString( | |
| new LazyString() { | |
| @Override | |
| public String toString() { | |
| return "foo"; | |
| } | |
| }) | |
| .build() | |
| .arguments()) | |
| .containsExactly("foo") | |
| .inOrder(); | |
| assertThat(builder().add("--arg", "val").build().arguments()) | |
| .containsExactly("--arg", "val") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addLabel("--arg", Label.parseAbsolute("//a:b", ImmutableMap.of())) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "//a:b") | |
| .inOrder(); | |
| assertThat(builder().addPath("--arg", PathFragment.create("path")).build().arguments()) | |
| .containsExactly("--arg", "path") | |
| .inOrder(); | |
| assertThat(builder().addExecPath("--arg", artifact1).build().arguments()) | |
| .containsExactly("--arg", "dir/file1.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addLazyString( | |
| "--arg", | |
| new LazyString() { | |
| @Override | |
| public String toString() { | |
| return "foo"; | |
| } | |
| }) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "foo") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddFormatted() throws Exception { | |
| assertThat(builder().addFormatted("%s%s", "hello", "world").build().arguments()) | |
| .containsExactly("helloworld") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddPrefixed() throws Exception { | |
| assertThat(builder().addPrefixed("prefix-", "foo").build().arguments()) | |
| .containsExactly("prefix-foo") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPrefixedLabel("prefix-", Label.parseAbsolute("//a:b", ImmutableMap.of())) | |
| .build() | |
| .arguments()) | |
| .containsExactly("prefix-//a:b") | |
| .inOrder(); | |
| assertThat( | |
| builder().addPrefixedPath("prefix-", PathFragment.create("path")).build().arguments()) | |
| .containsExactly("prefix-path") | |
| .inOrder(); | |
| assertThat(builder().addPrefixedExecPath("prefix-", artifact1).build().arguments()) | |
| .containsExactly("prefix-dir/file1.txt") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testVectorAdds() throws Exception { | |
| assertThat(builder().addAll(list("val1", "val2")).build().arguments()) | |
| .containsExactly("val1", "val2") | |
| .inOrder(); | |
| assertThat(builder().addAll(nestedSet("val1", "val2")).build().arguments()) | |
| .containsExactly("val1", "val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths(list(PathFragment.create("path1"), PathFragment.create("path2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("path1", "path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths(nestedSet(PathFragment.create("path1"), PathFragment.create("path2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("path1", "path2") | |
| .inOrder(); | |
| assertThat(builder().addExecPaths(list(artifact1, artifact2)).build().arguments()) | |
| .containsExactly("dir/file1.txt", "dir/file2.txt") | |
| .inOrder(); | |
| assertThat(builder().addExecPaths(nestedSet(artifact1, artifact2)).build().arguments()) | |
| .containsExactly("dir/file1.txt", "dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.of(list(foo("1"), foo("2"))).mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("1", "2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.of(nestedSet(foo("1"), foo("2"))).mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("1", "2") | |
| .inOrder(); | |
| assertThat(builder().addAll("--arg", list("val1", "val2")).build().arguments()) | |
| .containsExactly("--arg", "val1", "val2") | |
| .inOrder(); | |
| assertThat(builder().addAll("--arg", nestedSet("val1", "val2")).build().arguments()) | |
| .containsExactly("--arg", "val1", "val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths("--arg", list(PathFragment.create("path1"), PathFragment.create("path2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "path1", "path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", nestedSet(PathFragment.create("path1"), PathFragment.create("path2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "path1", "path2") | |
| .inOrder(); | |
| assertThat(builder().addExecPaths("--arg", list(artifact1, artifact2)).build().arguments()) | |
| .containsExactly("--arg", "dir/file1.txt", "dir/file2.txt") | |
| .inOrder(); | |
| assertThat(builder().addExecPaths("--arg", nestedSet(artifact1, artifact2)).build().arguments()) | |
| .containsExactly("--arg", "dir/file1.txt", "dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.of(list(foo("1"), foo("2"))).mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "1", "2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", VectorArg.of(nestedSet(foo("1"), foo("2"))).mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "1", "2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddJoined() throws Exception { | |
| assertThat(builder().addAll(VectorArg.join(":").each(list("val1", "val2"))).build().arguments()) | |
| .containsExactly("val1:val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.join(":").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("val1:val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.join(":") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("path1:path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.join(":") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("path1:path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.join(":").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("dir/file1.txt:dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.join(":").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("dir/file1.txt:dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.join(":").each(list(foo("1"), foo("2"))).mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("1:2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.join(":") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("1:2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.join(":").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "val1:val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.join(":").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "val1:val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", | |
| VectorArg.join(":") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "path1:path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", | |
| VectorArg.join(":") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "path1:path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths("--arg", VectorArg.join(":").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "dir/file1.txt:dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths("--arg", VectorArg.join(":").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "dir/file1.txt:dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", | |
| VectorArg.join(":").each(list(foo("1"), foo("2"))).mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "1:2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", | |
| VectorArg.join(":") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "1:2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddFormatEach() throws Exception { | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.format("-D%s").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dval1", "-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.format("-D%s").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dval1", "-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.format("-D%s") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dpath1", "-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.format("-D%s") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dpath1", "-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.format("-D%s").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Ddir/file1.txt", "-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.format("-D%s").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Ddir/file1.txt", "-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.format("-D%s") | |
| .each(list(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D1", "-D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.format("-D%s") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D1", "-D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.format("-D%s").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dval1", "-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.format("-D%s").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dval1", "-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dpath1", "-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dpath1", "-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths("--arg", VectorArg.format("-D%s").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Ddir/file1.txt", "-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths( | |
| "--arg", VectorArg.format("-D%s").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Ddir/file1.txt", "-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .each(list(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-D1", "-D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-D1", "-D2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddFormatEachJoined() throws Exception { | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.format("-D%s").join(":").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dval1:-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.format("-D%s").join(":").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dval1:-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dpath1:-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Dpath1:-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.format("-D%s").join(":").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Ddir/file1.txt:-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths( | |
| VectorArg.format("-D%s").join(":").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-Ddir/file1.txt:-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each(list(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D1:-D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D1:-D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.format("-D%s").join(":").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dval1:-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll("--arg", VectorArg.format("-D%s").join(":").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dval1:-Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dpath1:-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Dpath1:-Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths( | |
| "--arg", VectorArg.format("-D%s").join(":").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Ddir/file1.txt:-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths( | |
| "--arg", | |
| VectorArg.format("-D%s").join(":").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-Ddir/file1.txt:-Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each(list(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-D1:-D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| "--arg", | |
| VectorArg.format("-D%s") | |
| .join(":") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("--arg", "-D1:-D2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddBeforeEach() throws Exception { | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.addBefore("-D").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "val1", "-D", "val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.addBefore("-D").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "val1", "-D", "val2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.addBefore("-D") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "path1", "-D", "path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.addBefore("-D") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "path1", "-D", "path2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.addBefore("-D").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "dir/file1.txt", "-D", "dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths(VectorArg.addBefore("-D").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "dir/file1.txt", "-D", "dir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.addBefore("-D") | |
| .each(list(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "1", "-D", "2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.addBefore("-D") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "1", "-D", "2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddBeforeEachFormatted() throws Exception { | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.addBefore("-D").format("D%s").each(list("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "Dval1", "-D", "Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll(VectorArg.addBefore("-D").format("D%s").each(nestedSet("val1", "val2"))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "Dval1", "-D", "Dval2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.addBefore("-D") | |
| .format("D%s") | |
| .each(list(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "Dpath1", "-D", "Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addPaths( | |
| VectorArg.addBefore("-D") | |
| .format("D%s") | |
| .each( | |
| nestedSet(PathFragment.create("path1"), PathFragment.create("path2")))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "Dpath1", "-D", "Dpath2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths( | |
| VectorArg.addBefore("-D").format("D%s").each(list(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "Ddir/file1.txt", "-D", "Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addExecPaths( | |
| VectorArg.addBefore("-D").format("D%s").each(nestedSet(artifact1, artifact2))) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "Ddir/file1.txt", "-D", "Ddir/file2.txt") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.addBefore("-D") | |
| .format("D%s") | |
| .each(list(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "D1", "-D", "D2") | |
| .inOrder(); | |
| assertThat( | |
| builder() | |
| .addAll( | |
| VectorArg.addBefore("-D") | |
| .format("D%s") | |
| .each(nestedSet(foo("1"), foo("2"))) | |
| .mapped(Foo::expandToStr)) | |
| .build() | |
| .arguments()) | |
| .containsExactly("-D", "D1", "-D", "D2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testCombinedArgs() { | |
| CustomCommandLine cl = | |
| builder() | |
| .add("--arg") | |
| .addAll("--args", ImmutableList.of("abc")) | |
| .addExecPaths("--path1", ImmutableList.of(artifact1)) | |
| .addExecPath("--path2", artifact2) | |
| .build(); | |
| assertThat(cl.arguments()) | |
| .containsExactly( | |
| "--arg", "--args", "abc", "--path1", "dir/file1.txt", "--path2", "dir/file2.txt") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testAddNulls() throws Exception { | |
| Artifact treeArtifact = createTreeArtifact("myTreeArtifact"); | |
| assertThat(treeArtifact).isNotNull(); | |
| CustomCommandLine cl = | |
| builder() | |
| .addDynamicString(null) | |
| .addLabel(null) | |
| .addPath(null) | |
| .addExecPath(null) | |
| .addLazyString(null) | |
| .add("foo", null) | |
| .addLabel("foo", null) | |
| .addPath("foo", null) | |
| .addExecPath("foo", null) | |
| .addLazyString("foo", null) | |
| .addPrefixed("prefix", null) | |
| .addPrefixedLabel("prefix", null) | |
| .addPrefixedPath("prefix", null) | |
| .addPrefixedExecPath("prefix", null) | |
| .addAll((ImmutableList<String>) null) | |
| .addAll(ImmutableList.of()) | |
| .addPaths((ImmutableList<PathFragment>) null) | |
| .addPaths(ImmutableList.of()) | |
| .addExecPaths((ImmutableList<Artifact>) null) | |
| .addExecPaths(ImmutableList.of()) | |
| .addAll((NestedSet<String>) null) | |
| .addAll(NestedSetBuilder.emptySet(Order.STABLE_ORDER)) | |
| .addPaths((NestedSet<PathFragment>) null) | |
| .addPaths(NestedSetBuilder.emptySet(Order.STABLE_ORDER)) | |
| .addExecPaths((NestedSet<Artifact>) null) | |
| .addExecPaths(NestedSetBuilder.emptySet(Order.STABLE_ORDER)) | |
| .addAll(VectorArg.of((NestedSet<String>) null)) | |
| .addAll(VectorArg.of(NestedSetBuilder.<String>emptySet(Order.STABLE_ORDER))) | |
| .addAll("foo", (ImmutableList<String>) null) | |
| .addAll("foo", ImmutableList.of()) | |
| .addPaths("foo", (ImmutableList<PathFragment>) null) | |
| .addPaths("foo", ImmutableList.of()) | |
| .addExecPaths("foo", (ImmutableList<Artifact>) null) | |
| .addExecPaths("foo", ImmutableList.of()) | |
| .addAll("foo", (NestedSet<String>) null) | |
| .addAll("foo", NestedSetBuilder.emptySet(Order.STABLE_ORDER)) | |
| .addPaths("foo", (NestedSet<PathFragment>) null) | |
| .addPaths("foo", NestedSetBuilder.emptySet(Order.STABLE_ORDER)) | |
| .addExecPaths("foo", (NestedSet<Artifact>) null) | |
| .addExecPaths("foo", NestedSetBuilder.emptySet(Order.STABLE_ORDER)) | |
| .addAll("foo", VectorArg.of((NestedSet<String>) null)) | |
| .addAll("foo", VectorArg.of(NestedSetBuilder.<String>emptySet(Order.STABLE_ORDER))) | |
| .addPlaceholderTreeArtifactExecPath("foo", null) | |
| .build(); | |
| assertThat(cl.arguments()).isEmpty(); | |
| } | |
| @Test | |
| public void testTreeFileArtifactExecPathArgs() { | |
| SpecialArtifact treeArtifactOne = createTreeArtifact("myArtifact/treeArtifact1"); | |
| SpecialArtifact treeArtifactTwo = createTreeArtifact("myArtifact/treeArtifact2"); | |
| CustomCommandLine commandLineTemplate = | |
| builder() | |
| .addPlaceholderTreeArtifactExecPath("--argOne", treeArtifactOne) | |
| .addPlaceholderTreeArtifactExecPath("--argTwo", treeArtifactTwo) | |
| .build(); | |
| TreeFileArtifact treeFileArtifactOne = | |
| ActionsTestUtil.createTreeFileArtifactWithNoGeneratingAction( | |
| treeArtifactOne, "children/child1"); | |
| TreeFileArtifact treeFileArtifactTwo = | |
| ActionsTestUtil.createTreeFileArtifactWithNoGeneratingAction( | |
| treeArtifactTwo, "children/child2"); | |
| CustomCommandLine commandLine = commandLineTemplate.evaluateTreeFileArtifacts( | |
| ImmutableList.of(treeFileArtifactOne, treeFileArtifactTwo)); | |
| assertThat(commandLine.arguments()) | |
| .containsExactly( | |
| "--argOne", | |
| "dir/myArtifact/treeArtifact1/children/child1", | |
| "--argTwo", | |
| "dir/myArtifact/treeArtifact2/children/child2") | |
| .inOrder(); | |
| } | |
| @Test | |
| public void testKeyComputation() { | |
| NestedSet<String> values = NestedSetBuilder.<String>stableOrder().add("a").add("b").build(); | |
| ImmutableList<CustomCommandLine> commandLines = | |
| ImmutableList.<CustomCommandLine>builder() | |
| .add(builder().add("arg").build()) | |
| .add(builder().addFormatted("--foo=%s", "arg").build()) | |
| .add(builder().addPrefixed("--foo=%s", "arg").build()) | |
| .add(builder().addAll(values).build()) | |
| .add(builder().addAll(VectorArg.addBefore("--foo=%s").each(values)).build()) | |
| .add(builder().addAll(VectorArg.join("--foo=%s").each(values)).build()) | |
| .add(builder().addAll(VectorArg.format("--foo=%s").each(values)).build()) | |
| .add( | |
| builder() | |
| .addAll(VectorArg.of(values).mapped((s, args) -> args.accept(s + "_mapped"))) | |
| .build()) | |
| .build(); | |
| // Ensure all these command lines have distinct keys | |
| ActionKeyContext actionKeyContext = new ActionKeyContext(); | |
| Map<String, CustomCommandLine> digests = new HashMap<>(); | |
| for (CustomCommandLine commandLine : commandLines) { | |
| Fingerprint fingerprint = new Fingerprint(); | |
| commandLine.addToFingerprint(actionKeyContext, fingerprint); | |
| String digest = fingerprint.hexDigestAndReset(); | |
| CustomCommandLine previous = digests.putIfAbsent(digest, commandLine); | |
| if (previous != null) { | |
| fail( | |
| String.format( | |
| "Found two command lines with identical digest %s: '%s' and '%s'", | |
| digest, | |
| Joiner.on(' ').join(previous.arguments()), | |
| Joiner.on(' ').join(commandLine.arguments()))); | |
| } | |
| } | |
| } | |
| @Test | |
| public void testTreeFileArtifactArgThrowWithoutSubstitution() { | |
| Artifact treeArtifactOne = createTreeArtifact("myArtifact/treeArtifact1"); | |
| Artifact treeArtifactTwo = createTreeArtifact("myArtifact/treeArtifact2"); | |
| CustomCommandLine commandLineTemplate = | |
| builder() | |
| .addPlaceholderTreeArtifactExecPath("--argOne", treeArtifactOne) | |
| .addPlaceholderTreeArtifactExecPath("--argTwo", treeArtifactTwo) | |
| .build(); | |
| assertThrows(NullPointerException.class, () -> commandLineTemplate.arguments()); | |
| } | |
| private SpecialArtifact createTreeArtifact(String rootRelativePath) { | |
| PathFragment relpath = PathFragment.create(rootRelativePath); | |
| return new SpecialArtifact( | |
| rootDir, | |
| rootDir.getExecPath().getRelative(relpath), | |
| ActionsTestUtil.NULL_ACTION_LOOKUP_DATA.getActionLookupKey(), | |
| SpecialArtifactType.TREE); | |
| } | |
| private static <T> ImmutableList<T> list(T... objects) { | |
| return ImmutableList.<T>builder().addAll(Arrays.asList(objects)).build(); | |
| } | |
| private static <T> NestedSet<T> nestedSet(T... objects) { | |
| return NestedSetBuilder.<T>stableOrder().addAll(Arrays.asList(objects)).build(); | |
| } | |
| private static Foo foo(String str) { | |
| return new Foo(str); | |
| } | |
| private static class Foo { | |
| private final String str; | |
| Foo(String str) { | |
| this.str = str; | |
| } | |
| static void expandToStr(Foo foo, Consumer<String> args) { | |
| args.accept(foo.str); | |
| } | |
| } | |
| } |