| // 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.runtime; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.io.BaseEncoding; |
| import com.google.devtools.build.lib.flags.CommandNameCache; |
| import com.google.devtools.build.lib.flags.InvocationPolicyEnforcer; |
| import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy; |
| import com.google.devtools.common.options.Option; |
| import com.google.devtools.common.options.OptionsBase; |
| import com.google.devtools.common.options.OptionsParser; |
| import com.google.devtools.common.options.OptionsParsingException; |
| |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.util.List; |
| |
| @RunWith(JUnit4.class) |
| public class InvocationPolicyEnforcerTest { |
| |
| public static final String STRING_FLAG_DEFAULT = "test string default"; |
| |
| public static class TestOptions extends OptionsBase { |
| |
| /* |
| * Basic types |
| */ |
| |
| @Option(name = "test_string", defaultValue = STRING_FLAG_DEFAULT) |
| public String testString; |
| |
| /* |
| * Repeated flags |
| */ |
| |
| @Option( |
| name = "test_multiple_string", |
| defaultValue = "", // default value is ignored when allowMultiple = true. |
| allowMultiple = true) |
| public List<String> testMultipleString; |
| |
| /* |
| * Expansion flags |
| */ |
| |
| @Option( |
| name = "test_expansion", |
| defaultValue = "null", |
| expansion = { |
| "--notest_expansion_a", |
| "--test_expansion_b=false", |
| "--test_expansion_c", "42", |
| "--test_expansion_d", "bar" |
| }) |
| public Void testExpansion; |
| |
| @Option( |
| name = "test_recursive_expansion_top_level", |
| defaultValue = "null", |
| expansion = { |
| "--test_recursive_expansion_middle1", |
| "--test_recursive_expansion_middle2", |
| }) |
| public Void testRecursiveExpansionTopLevel; |
| |
| @Option( |
| name = "test_recursive_expansion_middle1", |
| defaultValue = "null", |
| expansion = { |
| "--test_expansion_a=false", |
| "--test_expansion_c=56", |
| }) |
| public Void testRecursiveExpansionMiddle1; |
| |
| @Option( |
| name = "test_recursive_expansion_middle2", |
| defaultValue = "null", |
| expansion = { |
| "--test_expansion_b=false", |
| "--test_expansion_d=baz", |
| }) |
| public Void testRecursiveExpansionMiddle2; |
| |
| @Option(name = "test_expansion_a", defaultValue = "true") |
| public boolean testExpansionA; |
| |
| @Option(name = "test_expansion_b", defaultValue = "true") |
| public boolean testExpansionB; |
| |
| @Option(name = "test_expansion_c", defaultValue = "12") |
| public int testExpansionC; |
| |
| @Option(name = "test_expansion_d", defaultValue = "foo") |
| public String testExpansionD; |
| |
| /* |
| * Implicit requirement flags |
| */ |
| |
| @Option( |
| name = "test_implicit_requirement", |
| defaultValue = "test implicit requirement default", |
| implicitRequirements = {"--an_implicit_requirement=foo"}) |
| public String testImplicitRequirement; |
| |
| @Option( |
| name = "an_implicit_requirement", |
| defaultValue = "implicit default") |
| public String anImplicitRequirement; |
| |
| @Option( |
| name = "test_recursive_implicit_requirement", |
| defaultValue = "test recursive implicit requirement default", |
| implicitRequirements = {"--test_implicit_requirement=bar"}) |
| public String testRecursiveImplicitRequirement; |
| |
| } |
| |
| private static InvocationPolicyEnforcer createOptionsPolicyEnforcer( |
| InvocationPolicy.Builder invocationPolicyBuilder) throws Exception { |
| InvocationPolicy policyProto = invocationPolicyBuilder.build(); |
| |
| // An OptionsPolicyEnforcer could be constructed in the test directly from the InvocationPolicy |
| // proto, however Blaze will actually take the policy as another flag with a Base64 encoded |
| // binary proto and parse that, so exercise that code path in the test. |
| |
| ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| policyProto.writeTo(out); |
| String policyBase64 = BaseEncoding.base64().encode(out.toByteArray()); |
| |
| OptionsParser startupOptionsParser = OptionsParser.newOptionsParser( |
| BlazeServerStartupOptions.class); |
| String policyOption = "--invocation_policy=" + policyBase64; |
| startupOptionsParser.parse(policyOption); |
| |
| return InvocationPolicyEnforcer.create( |
| startupOptionsParser.getOptions(BlazeServerStartupOptions.class).invocationPolicy); |
| } |
| |
| private OptionsParser parser; |
| |
| @Before |
| public final void setParser() throws Exception { |
| parser = OptionsParser.newOptionsParser(TestOptions.class); |
| } |
| |
| @BeforeClass |
| public static void setCommandNameCache() throws Exception { |
| CommandNameCache.CommandNameCacheInstance.INSTANCE.setCommandNameCache( |
| new CommandNameCache() { |
| @Override |
| public ImmutableSet<String> get(String commandName) { |
| return ImmutableSet.of(commandName); |
| } |
| }); |
| } |
| |
| private TestOptions getTestOptions() { |
| return parser.getOptions(TestOptions.class); |
| } |
| |
| /************************************************************************************************* |
| * Tests for SetValue |
| ************************************************************************************************/ |
| |
| /** |
| * Tests that policy overrides a value when that value is from the user. |
| */ |
| @Test |
| public void testSetValueOverridesUser() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Get the options again after policy enforcement. |
| testOptions = getTestOptions(); |
| assertEquals("policy value", testOptions.testString); |
| } |
| |
| /** |
| * Tests that policy overrides a value when the user doesn't specify the value (i.e., the value |
| * is from the flag's default from its definition). |
| */ |
| @Test |
| public void testSetValueOverridesDefault() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value"); |
| |
| // No user value. |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // All the flags should be their default value. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Get the options again after policy enforcement. |
| testOptions = getTestOptions(); |
| assertEquals("policy value", testOptions.testString); |
| } |
| |
| /** |
| * Tests that SetValue overrides the user's value when the flag allows multiple values. |
| */ |
| @Test |
| public void testSetValueWithMultipleValuesOverridesUser() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value 1") |
| .addFlagValue("policy value 2"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_multiple_string=user value 1", "--test_multiple_string=user value 2"); |
| |
| // Options should not be modified by running the parser through OptionsPolicyEnforcer.create(). |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString) |
| .containsExactly("user value 1", "user value 2").inOrder(); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Get the options again after policy enforcement. |
| testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString) |
| .containsExactly("policy value 1", "policy value 2").inOrder(); |
| } |
| |
| /** |
| * Tests that policy overrides the default value when the flag allows multiple values and the user |
| * doesn't provide a value. |
| */ |
| @Test |
| public void testSetValueWithMultipleValuesOverridesDefault() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value 1") |
| .addFlagValue("policy value 2"); |
| |
| // No user value. |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // Repeatable flags always default to the empty list. |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString).isEmpty(); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Options should now be the values from the policy. |
| testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString) |
| .containsExactly("policy value 1", "policy value 2").inOrder(); |
| } |
| |
| @Test |
| public void testSetValueHasMultipleValuesButFlagIsNotMultiple() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") // Not repeatable flag. |
| .getSetValueBuilder() |
| .addFlagValue("policy value 1") // Has multiple values. |
| .addFlagValue("policy value 2"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected. |
| } |
| } |
| |
| @Test |
| public void testSetValueAppendsToMultipleValuedFlag() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value 1") |
| .addFlagValue("policy value 2") |
| .setAppend(true); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_multiple_string=user value 1", "--test_multiple_string=user value 2"); |
| |
| // Options should not be modified by running the parser through OptionsPolicyEnforcer.create(). |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString) |
| .containsExactly("user value 1", "user value 2").inOrder(); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Get the options again after policy enforcement. |
| testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString) |
| .containsExactly( |
| "user value 1", |
| "user value 2", |
| "policy value 1", |
| "policy value 2").inOrder(); |
| } |
| |
| @Test |
| public void testSetValueWithExpansionFlags() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_expansion") |
| .getSetValueBuilder() |
| .addFlagValue("true"); // this value is arbitrary, the value for a Void flag is ignored |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| // Unrelated flag, but --test_expansion is not set |
| parser.parse("--test_string=foo"); |
| |
| // The flags that --test_expansion expands into should still be their default values |
| TestOptions testOptions = getTestOptions(); |
| assertTrue(testOptions.testExpansionA); |
| assertTrue(testOptions.testExpansionB); |
| assertEquals(12, testOptions.testExpansionC); |
| assertEquals("foo", testOptions.testExpansionD); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // After policy enforcement, the flags should be the values from --test_expansion |
| testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertFalse(testOptions.testExpansionB); |
| assertEquals(42, testOptions.testExpansionC); |
| assertEquals("bar", testOptions.testExpansionD); |
| } |
| |
| @Test |
| public void testSetValueWithExpandedFlags() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_expansion_c") |
| .getSetValueBuilder() |
| .addFlagValue("64"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_expansion"); |
| |
| // --test_expansion should set the values from its expansion |
| TestOptions testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertFalse(testOptions.testExpansionB); |
| assertEquals(42, testOptions.testExpansionC); |
| assertEquals("bar", testOptions.testExpansionD); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // After policy enforcement, test_expansion_c should be set to 64 from the policy, but the |
| // flags should remain the same from the expansion of --test_expansion. |
| testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertFalse(testOptions.testExpansionB); |
| assertEquals(64, testOptions.testExpansionC); |
| assertEquals("bar", testOptions.testExpansionD); |
| } |
| |
| @Test |
| public void testSetValueWithImplicitlyRequiredFlags() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("an_implicit_requirement") |
| .getSetValueBuilder() |
| .addFlagValue("policy value"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_implicit_requirement=user value"); |
| |
| // test_implicit_requirement sets an_implicit_requirement to "foo" |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testImplicitRequirement); |
| assertEquals("foo", testOptions.anImplicitRequirement); |
| |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testImplicitRequirement); |
| assertEquals("policy value", testOptions.anImplicitRequirement); |
| } |
| |
| @Test |
| public void testSetValueOverridable() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value") |
| .setOverridable(true); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Even though the policy sets the value for test_string, the policy is overridable and the |
| // user set the value, so it should be the user's value. |
| testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| } |
| |
| @Test |
| public void testSetValueWithNoValueThrows() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getSetValueBuilder(); // No value. |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected. |
| } |
| } |
| |
| /************************************************************************************************* |
| * Tests for UseDefault |
| ************************************************************************************************/ |
| |
| @Test |
| public void testUseDefault() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| // Options should be the user specified value before enforcing policy. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Get the options again after policy enforcement: The flag should now be back to its default |
| // value |
| testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| } |
| |
| /** |
| * Tests UseDefault when the user never actually specified the flag. |
| */ |
| @Test |
| public void testUseDefaultWhenFlagWasntSet() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // Options should be the default since the user never specified it. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Still the default. |
| testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| } |
| |
| @Test |
| public void testUseDefaultWithExpansionFlags() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_expansion") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_expansion"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertFalse(testOptions.testExpansionB); |
| assertEquals(42, testOptions.testExpansionC); |
| assertEquals("bar", testOptions.testExpansionD); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // After policy enforcement, all the flags that --test_expansion expanded into should be back |
| // to their default values. |
| testOptions = getTestOptions(); |
| assertTrue(testOptions.testExpansionA); |
| assertTrue(testOptions.testExpansionB); |
| assertEquals(12, testOptions.testExpansionC); |
| assertEquals("foo", testOptions.testExpansionD); |
| } |
| |
| @Test |
| public void testUseDefaultWithRecursiveExpansionFlags() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_expansion") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_recursive_expansion_top_level"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertFalse(testOptions.testExpansionB); |
| assertEquals(56, testOptions.testExpansionC); |
| assertEquals("baz", testOptions.testExpansionD); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // After policy enforcement, all the flags that --test_recursive_expansion_top_level and its |
| // recursive expansions set should be back to their default values. |
| testOptions = getTestOptions(); |
| assertTrue(testOptions.testExpansionA); |
| assertTrue(testOptions.testExpansionB); |
| assertEquals(12, testOptions.testExpansionC); |
| assertEquals("foo", testOptions.testExpansionD); |
| } |
| |
| @Test |
| public void testUseDefaultWithExpandedFlags() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_expansion_b") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_expansion"); |
| |
| // --test_expansion should turn set the values from its expansion |
| TestOptions testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertFalse(testOptions.testExpansionB); |
| assertEquals(42, testOptions.testExpansionC); |
| assertEquals("bar", testOptions.testExpansionD); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // After policy enforcement, test_expansion_b should be back to its default (true), but the |
| // rest should remain the same. |
| testOptions = getTestOptions(); |
| assertFalse(testOptions.testExpansionA); |
| assertTrue(testOptions.testExpansionB); |
| assertEquals(42, testOptions.testExpansionC); |
| assertEquals("bar", testOptions.testExpansionD); |
| } |
| |
| @Test |
| public void testUseDefaultWithFlagWithImplicitRequirements() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_implicit_requirement") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_implicit_requirement=user value"); |
| |
| // test_implicit_requirement sets an_implicit_requirement to "foo", which ignores the user's |
| // value because the parser processes implicit values last. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testImplicitRequirement); |
| assertEquals("foo", testOptions.anImplicitRequirement); |
| |
| // Then policy puts test_implicit_requirement and its implicit requirements back to its default. |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| assertEquals("test implicit requirement default", testOptions.testImplicitRequirement); |
| assertEquals("implicit default", testOptions.anImplicitRequirement); |
| } |
| |
| @Test |
| public void testUseDefaultWithImplicitlyRequiredFlag() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("an_implicit_requirement") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_implicit_requirement=user value", |
| "--an_implicit_requirement=implicit user value"); |
| |
| // test_implicit_requirement sets an_implicit_requirement to "foo", which ignores the user's |
| // value because the parser processes implicit values last. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testImplicitRequirement); |
| assertEquals("foo", testOptions.anImplicitRequirement); |
| |
| // Then policy puts an_implicit_requirement back to its default. |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testImplicitRequirement); |
| assertEquals("implicit default", testOptions.anImplicitRequirement); |
| } |
| |
| @Test |
| public void testUseDefaultWithFlagWithRecursiveImplicitRequirements() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_recursive_implicit_requirement") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_recursive_implicit_requirement=user value"); |
| |
| // test_recursive_implicit_requirement gets its value from the command line, |
| // test_implicit_requirement gets its value from test_recursive_implicit_requirement, and |
| // an_implicit_requirement gets its value from test_implicit_requirement. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testRecursiveImplicitRequirement); |
| assertEquals("bar", testOptions.testImplicitRequirement); |
| assertEquals("foo", testOptions.anImplicitRequirement); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Policy enforcement should set everything back to its default value. |
| testOptions = getTestOptions(); |
| assertEquals("test recursive implicit requirement default", |
| testOptions.testRecursiveImplicitRequirement); |
| assertEquals("test implicit requirement default", testOptions.testImplicitRequirement); |
| assertEquals("implicit default", testOptions.anImplicitRequirement); |
| } |
| |
| /************************************************************************************************* |
| * Tests for AllowValues |
| ************************************************************************************************/ |
| |
| /** |
| * Tests that AllowValues works in the normal case where the value the user specified is allowed |
| * by the policy. |
| */ |
| @Test |
| public void testAllowValuesAllowsValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getAllowValuesBuilder() |
| .addAllowedValues(STRING_FLAG_DEFAULT) |
| .addAllowedValues("foo") |
| .addAllowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=foo"); |
| |
| // Option should be "foo" as specified by the user. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("foo", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Still "foo" since "foo" is allowed by the policy. |
| testOptions = getTestOptions(); |
| assertEquals("foo", testOptions.testString); |
| } |
| |
| @Test |
| public void testAllowValuesDisallowsValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getAllowValuesBuilder() |
| // no foo! |
| .addAllowedValues(STRING_FLAG_DEFAULT) |
| .addAllowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=foo"); |
| |
| // Option should be "foo" as specified by the user. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("foo", testOptions.testString); |
| |
| try { |
| // Should throw because "foo" is not allowed. |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testAllowValuesDisallowsMultipleValues() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getAllowValuesBuilder() |
| .addAllowedValues("foo") |
| .addAllowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_multiple_string=baz", "--test_multiple_string=bar"); |
| |
| // Option should be "baz" and "bar" as specified by the user. |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString).containsExactly("baz", "bar").inOrder(); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected, since baz is not allowed. |
| } |
| } |
| |
| @Test |
| public void testAllowValuesSetsNewValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getAllowValuesBuilder() |
| .addAllowedValues("foo") |
| .addAllowedValues("bar") |
| .setNewValue("foo"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=baz"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("baz", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| assertEquals("foo", testOptions.testString); |
| } |
| |
| @Test |
| public void testAllowValuesSetsDefaultValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getAllowValuesBuilder() |
| .addAllowedValues("foo") |
| .addAllowedValues(STRING_FLAG_DEFAULT) |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=bar"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("bar", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| } |
| |
| @Test |
| public void testAllowValuesSetsDefaultValueForRepeatableFlag() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getAllowValuesBuilder() |
| .addAllowedValues("foo") |
| .addAllowedValues("bar") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_multiple_string=foo", "--test_multiple_string=baz"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString).containsExactly("foo", "baz").inOrder(); |
| |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| // Default value for repeatable flags is always empty. |
| assertThat(testOptions.testMultipleString).isEmpty(); |
| } |
| |
| /** |
| * Tests that AllowValues sets its default value when the user doesn't provide a value and the |
| * flag's default value is disallowed. |
| */ |
| @Test |
| public void testAllowValuesSetsNewDefaultWhenFlagDefaultIsDisallowed() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getAllowValuesBuilder() |
| // default value from flag's definition is not allowed |
| .addAllowedValues("foo") |
| .addAllowedValues("bar") |
| .setNewValue("new default"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // Option should be its default |
| TestOptions testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Flag's value should be the default value from the policy. |
| testOptions = getTestOptions(); |
| assertEquals("new default", testOptions.testString); |
| } |
| |
| @Test |
| public void testAllowValuesDisallowsFlagDefaultButNoPolicyDefault() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getAllowValuesBuilder() |
| // default value from flag's definition is not allowed, and no alternate default |
| // is given. |
| .addAllowedValues("foo") |
| .addAllowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // Option should be its default |
| TestOptions testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected. |
| } |
| } |
| |
| /************************************************************************************************* |
| * Tests for DisallowValues |
| ************************************************************************************************/ |
| |
| @Test |
| public void testDisallowValuesAllowsValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues("foo") |
| .addDisallowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=baz"); |
| |
| // Option should be "baz" as specified by the user. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("baz", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Still "baz" since "baz" is allowed by the policy. |
| testOptions = getTestOptions(); |
| assertEquals("baz", testOptions.testString); |
| } |
| |
| @Test |
| public void testDisallowValuesDisallowsValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues("foo") |
| .addDisallowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=foo"); |
| |
| // Option should be "foo" as specified by the user. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("foo", testOptions.testString); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected, since foo is disallowed. |
| } |
| } |
| |
| @Test |
| public void testDisallowValuesDisallowsMultipleValues() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues("foo") |
| .addDisallowedValues("bar"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_multiple_string=baz", "--test_multiple_string=bar"); |
| |
| // Option should be "baz" and "bar" as specified by the user. |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString).containsExactly("baz", "bar").inOrder(); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected, since bar is disallowed. |
| } |
| } |
| |
| @Test |
| public void testDisallowValuesSetsNewValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues("user value") |
| .setNewValue("baz"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Should now be "baz" because the policy forces disallowed values to "baz" |
| testOptions = getTestOptions(); |
| assertEquals("baz", testOptions.testString); |
| } |
| |
| @Test |
| public void testDisallowValuesSetsDefaultValue() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues("user value") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| } |
| |
| @Test |
| public void testDisallowValuesSetsDefaultValueForRepeatableFlag() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_multiple_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues("user value") |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_multiple_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertThat(testOptions.testMultipleString).containsExactly("user value"); |
| |
| enforcer.enforce(parser, "build"); |
| |
| testOptions = getTestOptions(); |
| // Default for repeatable flags is always empty. |
| assertThat(testOptions.testMultipleString).isEmpty(); |
| } |
| |
| @Test |
| public void testDisallowValuesRaisesErrorIfDefaultIsDisallowedAndSetsUseDefault() |
| throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues(STRING_FLAG_DEFAULT) |
| .getUseDefaultBuilder(); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| assertThat(e.getMessage()).contains("but also specifies to use the default value"); |
| } |
| } |
| |
| @Test |
| public void testDisallowValuesSetsNewValueWhenDefaultIsDisallowed() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| .addDisallowedValues(STRING_FLAG_DEFAULT) |
| .setNewValue("baz"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // Option should be the default since the use didn't specify a value. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| |
| enforcer.enforce(parser, "build"); |
| |
| // Should now be "baz" because the policy set the new default to "baz" |
| testOptions = getTestOptions(); |
| assertEquals("baz", testOptions.testString); |
| } |
| |
| @Test |
| public void testDisallowValuesDisallowsFlagDefaultButNoPolicyDefault() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getDisallowValuesBuilder() |
| // No new default is set |
| .addDisallowedValues(STRING_FLAG_DEFAULT); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| |
| // Option should be the default since the use didn't specify a value. |
| TestOptions testOptions = getTestOptions(); |
| assertEquals(STRING_FLAG_DEFAULT, testOptions.testString); |
| |
| try { |
| enforcer.enforce(parser, "build"); |
| fail(); |
| } catch (OptionsParsingException e) { |
| // expected. |
| } |
| } |
| |
| /************************************************************************************************* |
| * Other tests |
| ************************************************************************************************/ |
| |
| @Test |
| public void testFlagPolicyDoesNotApply() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .addCommands("build") |
| .getSetValueBuilder() |
| .addFlagValue("policy value"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "test"); |
| |
| // Still user value. |
| testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| } |
| |
| @Test |
| public void testNonExistantFlagFromPolicy() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("i_do_not_exist") |
| .getSetValueBuilder() |
| .addFlagValue("policy value 1"); |
| invocationPolicyBuilder.addFlagPoliciesBuilder() |
| .setFlagName("test_string") |
| .getSetValueBuilder() |
| .addFlagValue("policy value 2"); |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| enforcer.enforce(parser, "test"); |
| |
| // Still user value. |
| testOptions = getTestOptions(); |
| assertEquals("policy value 2", testOptions.testString); |
| } |
| |
| @Test |
| public void testOperationNotSet() throws Exception { |
| InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder(); |
| invocationPolicyBuilder.addFlagPoliciesBuilder(); |
| // No operations added to the flag policy |
| |
| InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder); |
| parser.parse("--test_string=user value"); |
| |
| TestOptions testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| |
| // Shouldn't throw. |
| enforcer.enforce(parser, "test"); |
| |
| // Still user value. |
| testOptions = getTestOptions(); |
| assertEquals("user value", testOptions.testString); |
| } |
| } |