From ead88f556ee3b73dfc0fef0589e2713a57422c52 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Sun, 16 Apr 2023 09:13:33 +0200 Subject: [PATCH] Add tests --- .../common/options/OptionsParserTest.java | 90 +++++++- src/test/py/bazel/BUILD | 4 +- src/test/py/bazel/options_test.py | 205 ++++++++++++++++++ src/test/py/bazel/starlark_options_test.py | 82 ------- 4 files changed, 292 insertions(+), 89 deletions(-) create mode 100644 src/test/py/bazel/options_test.py delete mode 100644 src/test/py/bazel/starlark_options_test.py diff --git a/src/test/java/com/google/devtools/common/options/OptionsParserTest.java b/src/test/java/com/google/devtools/common/options/OptionsParserTest.java index 5927b1faf5be67..f23afb2ea4c115 100644 --- a/src/test/java/com/google/devtools/common/options/OptionsParserTest.java +++ b/src/test/java/com/google/devtools/common/options/OptionsParserTest.java @@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap; import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter; import com.google.devtools.common.options.OptionPriority.PriorityCategory; +import com.google.devtools.common.options.OptionsParser.ConstructionException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -209,20 +210,74 @@ public static class ExampleInternalOptions extends OptionsBase { public boolean privateBoolean; @Option( - name = "internal_string", - metadataTags = {OptionMetadataTag.INTERNAL}, - documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, - effectTags = {OptionEffectTag.NO_OP}, - defaultValue = "super secret" + name = "internal_string", + metadataTags = {OptionMetadataTag.INTERNAL}, + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "super secret" ) public String privateString; } + public static class ExampleEquivalentWithFoo extends OptionsBase { + + @Option( + name = "foo", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "differentDefault" + ) + public String foo; + + @Option( + name = "bar", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "differentDefault" + ) + public String bar; + + @Option( + name = "not_foo", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "differentDefault" + ) + public String notFoo; + + @Option( + name = "not_bar", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "differentDefault" + ) + public String notBar; + } + + public static class ExampleIncompatibleWithFoo extends OptionsBase { + + @Option( + name = "foo", + category = "one", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.NO_OP}, + defaultValue = "true" + ) + public boolean foo; + } + + public static class StringConverter extends Converter.Contextless { + @Override public String convert(String input) { return input; } + @Override public String getTypeDescription() { return "a string"; @@ -2401,6 +2456,31 @@ public void negativeExternalTargetPatternsInOptions_failsDistinctively() { .contains("Flags corresponding to Starlark-defined build settings always start with '--'"); } + @Test + public void fallbackOptions_optionsParsingEquivalently() + throws OptionsParsingException { + OpaqueOptionsData fallbackData = OptionsParser.getFallbackOptionsData( + ImmutableList.of(ExampleFoo.class, ExampleEquivalentWithFoo.class)); + OptionsParser parser = OptionsParser.builder().optionsClasses(ExampleFoo.class).build(); + parser.parseWithSourceFunction(PriorityCategory.RC_FILE, o -> ".bazelrc", + ImmutableList.of("--foo=bar", "--not_foo=baz", "--bar", "1", "--not_bar", "baz"), + fallbackData); + + assertThat(parser.getOptions(ExampleFoo.class)).isNotNull(); + assertThat(parser.getOptions(ExampleFoo.class).foo).isEqualTo("bar"); + assertThat(parser.getOptions(ExampleFoo.class).bar).isEqualTo(1); + + assertThat(parser.getOptions(ExampleEquivalentWithFoo.class)).isNull(); + } + + @Test + public void fallbackOptions_optionsParsingDifferently() { + Exception e = assertThrows(ConstructionException.class, + () -> OptionsParser.getFallbackOptionsData( + ImmutableList.of(ExampleFoo.class, ExampleIncompatibleWithFoo.class))); + assertThat(e).hasCauseThat().isInstanceOf(DuplicateOptionDeclarationException.class); + } + private static OptionInstanceOrigin createInvocationPolicyOrigin() { return createInvocationPolicyOrigin(/*implicitDependent=*/ null, /*expandedFrom=*/ null); } diff --git a/src/test/py/bazel/BUILD b/src/test/py/bazel/BUILD index 7940ac228f6243..dab163035b3d29 100644 --- a/src/test/py/bazel/BUILD +++ b/src/test/py/bazel/BUILD @@ -331,8 +331,8 @@ py_test( ) py_test( - name = "starlark_options_test", - srcs = ["starlark_options_test.py"], + name = "options_test", + srcs = ["options_test.py"], deps = [":test_base"], ) diff --git a/src/test/py/bazel/options_test.py b/src/test/py/bazel/options_test.py new file mode 100644 index 00000000000000..58c47c71a4814f --- /dev/null +++ b/src/test/py/bazel/options_test.py @@ -0,0 +1,205 @@ +# Copyright 2022 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. + +import unittest + +from src.test.py.bazel import test_base + + +class OptionsTest(test_base.TestBase): + + def testCanOverrideStarlarkFlagInBazelrcConfigStanza(self): + self.ScratchFile("WORKSPACE.bazel") + self.ScratchFile("bazelrc", [ + "build:red --//f:color=red", + ]) + self.ScratchFile("f/BUILD.bazel", [ + 'load(":f.bzl", "color", "r")', + "color(", + ' name = "color",', + ' build_setting_default = "white",', + ")", + 'r(name = "r")', + ]) + self.ScratchFile("f/f.bzl", [ + 'ColorValue = provider("color")', + "def _color_impl(ctx):", + " return [ColorValue(color = ctx.build_setting_value)]", + "color = rule(", + " implementation = _color_impl,", + "build_setting = config.string(flag = True),", + ")", + "def _r_impl(ctx):", + " print(ctx.attr._color[ColorValue].color)", + " return [DefaultInfo()]", + "r = rule(", + " implementation = _r_impl,", + ' attrs = {"_color": attr.label(default = "//f:color")},', + ")", + ]) + + exit_code, _, stderr = self.RunBazel([ + "--bazelrc=bazelrc", + "build", + "--nobuild", + "//f:r", + "--config=red", + "--//f:color=green", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertTrue( + any("/f/f.bzl:9:10: green" in line for line in stderr), + "\n".join(stderr), + ) + + exit_code, _, stderr = self.RunBazel([ + "--bazelrc=bazelrc", + "build", + "--nobuild", + "//f:r", + "--//f:color=green", + "--config=red", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertTrue( + any("/f/f.bzl:9:10: red" in line for line in stderr), + "\n".join(stderr), + ) + + def testAllSupportedPseudoCommand(self): + self.ScratchFile("WORKSPACE.bazel") + self.ScratchFile(".bazelrc", [ + "all-supported --copt=-Dfoo", + "all-supported --copt -Dbar", + "all-supported --force_pic", + "all-supported:my-config --copt=-Dbaz", + "all-supported:my-config --copt -Dquz", + "all-supported:my-config --noforce_pic", + ]) + self.ScratchFile("pkg/BUILD.bazel", [ + "cc_binary(name='main',srcs=['main.cc'])", + ]) + self.ScratchFile("pkg/main.cc", [ + "#include ", + "int main() {", + "#ifdef foo", + " printf(\"foo\\n\");", + "#endif", + "#ifdef bar", + " printf(\"bar\\n\");", + "#endif", + "#ifdef baz", + " printf(\"baz\\n\");", + "#endif", + "#ifdef quz", + " printf(\"quz\\n\");", + "#endif", + " return 0;", + "}", + ]) + + # Check that run honors the all-supported flags. + exit_code, stdout, stderr = self.RunBazel([ + "run", + "//pkg:main", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertEquals( + ["foo", "bar"], + stdout, + ) + + exit_code, stdout, stderr = self.RunBazel([ + "run", + "--config=my-config", + "//pkg:main", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertEquals( + ["foo", "bar", "baz", "quz"], + stdout, + ) + + # Check that aquery honors the all-supported flags. + exit_code, stdout, stderr = self.RunBazel([ + "aquery", + "mnemonic(CppLink, //pkg:main)", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertTrue( + any("-pie" in line for line in stdout), + stdout, + ) + + exit_code, stdout, stderr = self.RunBazel([ + "aquery", + "--config=my-config", + "mnemonic(CppLink, //pkg:main)", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertFalse( + any("-pie" in line for line in stdout), + stdout, + ) + + # Check that query ignores the unsupported all-supported flags. + exit_code, stdout, stderr = self.RunBazel([ + "query", + "//pkg:main", + ]) + self.AssertExitCode(exit_code, 0, stderr) + + exit_code, stdout, stderr = self.RunBazel([ + "query", + "--config=my-config", + "//pkg:main", + ]) + self.AssertExitCode(exit_code, 0, stderr) + + def testAllSupportedPseudoCommand_unsupportedOptionValue(self): + self.ScratchFile("WORKSPACE.bazel") + self.ScratchFile(".bazelrc", [ + "all-supported --output=starlark", + ]) + self.ScratchFile("pkg/BUILD.bazel", [ + "cc_binary(name='main',srcs=['main.cc'])", + ]) + + # Check that cquery honors the all-supported flag. + exit_code, stdout, stderr = self.RunBazel([ + "cquery", + "--starlark:expr=target.label.name", + "//pkg:main", + ]) + self.AssertExitCode(exit_code, 0, stderr) + self.assertEquals( + ["main"], + stdout, + ) + + # Check that query fails as it supports the --output flag, but not its + # value. + exit_code, stdout, stderr = self.RunBazel([ + "query", + "//pkg:main", + ]) + self.AssertExitCode(exit_code, 2, stderr) + self.assertTrue( + any("ERROR: Invalid output format 'starlark'." in line for line in stderr), + stderr, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/test/py/bazel/starlark_options_test.py b/src/test/py/bazel/starlark_options_test.py deleted file mode 100644 index f6433b5cc577f9..00000000000000 --- a/src/test/py/bazel/starlark_options_test.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2022 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. - -import unittest - -from src.test.py.bazel import test_base - - -class StarlarkOptionsTest(test_base.TestBase): - - def testCanOverrideStarlarkFlagInBazelrcConfigStanza(self): - self.ScratchFile("WORKSPACE.bazel") - self.ScratchFile("bazelrc", [ - "build:red --//f:color=red", - ]) - self.ScratchFile("f/BUILD.bazel", [ - 'load(":f.bzl", "color", "r")', - "color(", - ' name = "color",', - ' build_setting_default = "white",', - ")", - 'r(name = "r")', - ]) - self.ScratchFile("f/f.bzl", [ - 'ColorValue = provider("color")', - "def _color_impl(ctx):", - " return [ColorValue(color = ctx.build_setting_value)]", - "color = rule(", - " implementation = _color_impl,", - "build_setting = config.string(flag = True),", - ")", - "def _r_impl(ctx):", - " print(ctx.attr._color[ColorValue].color)", - " return [DefaultInfo()]", - "r = rule(", - " implementation = _r_impl,", - ' attrs = {"_color": attr.label(default = "//f:color")},', - ")", - ]) - - exit_code, _, stderr = self.RunBazel([ - "--bazelrc=bazelrc", - "build", - "--nobuild", - "//f:r", - "--config=red", - "--//f:color=green", - ]) - self.AssertExitCode(exit_code, 0, stderr) - self.assertTrue( - any("/f/f.bzl:9:10: green" in line for line in stderr), - "\n".join(stderr), - ) - - exit_code, _, stderr = self.RunBazel([ - "--bazelrc=bazelrc", - "build", - "--nobuild", - "//f:r", - "--//f:color=green", - "--config=red", - ]) - self.AssertExitCode(exit_code, 0, stderr) - self.assertTrue( - any("/f/f.bzl:9:10: red" in line for line in stderr), - "\n".join(stderr), - ) - - -if __name__ == "__main__": - unittest.main()