From d19d2079b1a2b16c6de8c950b67a2daf0b8d3372 Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Mon, 24 Sep 2018 18:14:45 +0100 Subject: [PATCH] Config constraints: add more tests --- .../brooklyn/ConfigParametersYamlTest.java | 39 +++++++++ .../core/config/ConfigKeyConstraintTest.java | 42 +++++----- .../objs/ConstraintSerializationTest.java | 80 +++++++++++++++++-- .../util/collections/MutableList.java | 9 ++- 4 files changed, 140 insertions(+), 30 deletions(-) diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java index a0cd11db53..777027028a 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java @@ -1078,6 +1078,45 @@ public void testConfigParameterConstraintRegex() throws Exception { assertKeyEquals(newEntity, "testRequired", null, String.class, null, "myprefix-myVal"); } + @Test + public void testConfigParameterConstraintParsing() throws Exception { + addCatalogItems( + "brooklyn.catalog:", + " itemType: entity", + " items:", + " - id: entity-with-keys", + " item:", + " type: "+TestEntity.class.getName(), + " brooklyn.parameters:", + " - name: testRequired", + " type: String", + " constraints:", + " - or:", + " - regex: val1", + " - regex: val2"); + + String yaml = Joiner.on("\n").join( + "services:", + "- type: entity-with-keys", + " brooklyn.config:", + " testRequired: val1"); + + Entity app = createStartWaitAndLogApplication(yaml); + TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren()); + assertKeyEquals(entity, "testRequired", null, String.class, null, "val1"); + + Predicate constraint = entity.getEntityType().getConfigKey("testRequired").getConstraint(); + assertEquals(constraint.toString(), "Predicates.or(matchesRegex(\"val1\"),matchesRegex(\"val2\"))"); + + // Rebind, and then check again that the config key is listed + Entity newApp = rebind(); + TestEntity newEntity = (TestEntity) Iterables.getOnlyElement(newApp.getChildren()); + assertKeyEquals(newEntity, "testRequired", null, String.class, null, "val1"); + + Predicate newConstraint = newEntity.getEntityType().getConfigKey("testRequired").getConstraint(); + assertEquals(newConstraint.toString(), "Predicates.or(matchesRegex(\"val1\"),matchesRegex(\"val2\"))"); + } + @Test public void testConfigParameterConstraintObject() throws Exception { addCatalogItems( diff --git a/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java b/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java index a251cbc647..16f2f77044 100644 --- a/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java @@ -21,6 +21,7 @@ import static org.testng.Assert.assertFalse; +import java.util.Map; import java.util.concurrent.Callable; import org.apache.brooklyn.api.entity.Entity; @@ -43,6 +44,7 @@ import org.apache.brooklyn.core.test.entity.TestEntityImpl; import org.apache.brooklyn.core.test.policy.TestPolicy; import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.javalang.JavaClassNames; import org.apache.brooklyn.util.net.Networking; @@ -352,76 +354,74 @@ public static interface EntityForForbiddenAndRequiredConditionalConstraints exte @ImplementedBy(EntityForForbiddenAndRequiredConditionalConstraintsForbiddenIfImpl.class) public static interface EntityForForbiddenAndRequiredConditionalConstraintsForbiddenIf extends EntityForForbiddenAndRequiredConditionalConstraints { static ConfigKey FI = ConfigKeys.builder(Object.class).name("forbiddenIfX") - .constraint(ConfigConstraints.forbiddenIf("x")).build(); + .constraint(ConfigConstraints.forbiddenIf("x")).build(); } public static class EntityForForbiddenAndRequiredConditionalConstraintsForbiddenIfImpl extends TestEntityImpl implements EntityForForbiddenAndRequiredConditionalConstraintsForbiddenIf {} @ImplementedBy(EntityForForbiddenAndRequiredConditionalConstraintsForbiddenUnlessImpl.class) public static interface EntityForForbiddenAndRequiredConditionalConstraintsForbiddenUnless extends EntityForForbiddenAndRequiredConditionalConstraints { static ConfigKey FU = ConfigKeys.builder(Object.class).name("forbiddenUnlessX") - .constraint(ConfigConstraints.forbiddenUnless("x")).build(); + .constraint(ConfigConstraints.forbiddenUnless("x")).build(); } public static class EntityForForbiddenAndRequiredConditionalConstraintsForbiddenUnlessImpl extends TestEntityImpl implements EntityForForbiddenAndRequiredConditionalConstraintsForbiddenUnless {} @ImplementedBy(EntityForForbiddenAndRequiredConditionalConstraintsRequiredIfImpl.class) public static interface EntityForForbiddenAndRequiredConditionalConstraintsRequiredIf extends EntityForForbiddenAndRequiredConditionalConstraints { static ConfigKey RI = ConfigKeys.builder(Object.class).name("requiredIfX") - .constraint(ConfigConstraints.requiredIf("x")).build(); + .constraint(ConfigConstraints.requiredIf("x")).build(); } public static class EntityForForbiddenAndRequiredConditionalConstraintsRequiredIfImpl extends TestEntityImpl implements EntityForForbiddenAndRequiredConditionalConstraintsRequiredIf {} @ImplementedBy(EntityForForbiddenAndRequiredConditionalConstraintsRequiredUnlessImpl.class) public static interface EntityForForbiddenAndRequiredConditionalConstraintsRequiredUnless extends EntityForForbiddenAndRequiredConditionalConstraints { static ConfigKey RU = ConfigKeys.builder(Object.class).name("requiredUnlessX") - .constraint(ConfigConstraints.requiredUnless("x")).build(); + .constraint(ConfigConstraints.requiredUnless("x")).build(); } public static class EntityForForbiddenAndRequiredConditionalConstraintsRequiredUnlessImpl extends TestEntityImpl implements EntityForForbiddenAndRequiredConditionalConstraintsRequiredUnless {} @Test public void testForbiddenAndRequiredConditionalConstraintsForbiddenIf() { assertKeyBehaviour(EntityForForbiddenAndRequiredConditionalConstraintsForbiddenIf.class, EntityForForbiddenAndRequiredConditionalConstraintsForbiddenIf.FI, - false, true, true, true); + false, true, true, true); } @Test public void testForbiddenAndRequiredConditionalConstraintsForbiddenUnless() { assertKeyBehaviour(EntityForForbiddenAndRequiredConditionalConstraintsForbiddenUnless.class, EntityForForbiddenAndRequiredConditionalConstraintsForbiddenUnless.FU, - true, true, false, true); + true, true, false, true); } @Test public void testForbiddenAndRequiredConditionalConstraintsRequiredIf() { assertKeyBehaviour(EntityForForbiddenAndRequiredConditionalConstraintsRequiredIf.class, EntityForForbiddenAndRequiredConditionalConstraintsRequiredIf.RI, - true, false, true, true); + true, false, true, true); } @Test public void testForbiddenAndRequiredConditionalConstraintsRequiredUnlelss() { assertKeyBehaviour(EntityForForbiddenAndRequiredConditionalConstraintsRequiredUnless.class, EntityForForbiddenAndRequiredConditionalConstraintsRequiredUnless.RU, - true, true, true, false); + true, true, true, false); } private void assertKeyBehaviour(Class clazz, ConfigKey key, boolean ifBoth, boolean ifJustX, boolean ifJustThis, boolean ifNone) { - assertKeyBehaviour("both set", clazz, true, key, true, ifBoth); - assertKeyBehaviour("only other key set", clazz, true, key, false, ifJustX); - assertKeyBehaviour("only this key set", clazz, false, key, true, ifJustThis); - assertKeyBehaviour("neither key set", clazz, false, key, false, ifNone); + assertKeyBehaviour("both set", clazz, MutableMap.of("x", "myval", key, "myval"), ifBoth); + assertKeyBehaviour("only other key set", clazz, MutableMap.of("x", "myval"), ifJustX); + assertKeyBehaviour("only this key set", clazz, MutableMap.of(key, "myval"), ifJustThis); + assertKeyBehaviour("neither key set", clazz, MutableMap.of(), ifNone); } - - private void assertKeyBehaviour(String description, Class clazz, boolean isXSet, ConfigKey key, boolean isKeySet, boolean shouldSucceed) { + + private void assertKeyBehaviour(String description, Class clazz, Map config, boolean shouldSucceed) { try { - EntitySpec spec = EntitySpec.create(clazz); - if (isXSet) spec.configure(EntityForForbiddenAndRequiredConditionalConstraints.X, "set"); - if (isKeySet) spec.configure(key, "set"); - app.createAndManageChild(spec); + app.createAndManageChild(EntitySpec.create(clazz) + .configure(config)); if (!shouldSucceed) { - Asserts.shouldHaveFailedPreviously("Expected failure when testing "+key.getName()+" - "+description); + Asserts.shouldHaveFailedPreviously("Expected failure "+" - "+description); } } catch (Exception e) { if (!shouldSucceed) { - Asserts.expectedFailureOfType("Expected ConstraintViolationException when testing "+key.getName()+" - "+description, e, ConstraintViolationException.class); + Asserts.expectedFailureOfType("Expected ConstraintViolationException - "+description, e, ConstraintViolationException.class); } else { - throw new AssertionError("Expected success when testing "+key.getName()+" - "+description+"; instead got "+e, e); + throw new AssertionError("Expected success - "+description+"; instead got "+e, e); } } } diff --git a/core/src/test/java/org/apache/brooklyn/core/objs/ConstraintSerializationTest.java b/core/src/test/java/org/apache/brooklyn/core/objs/ConstraintSerializationTest.java index bdbc5adc2c..088232588e 100644 --- a/core/src/test/java/org/apache/brooklyn/core/objs/ConstraintSerializationTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/objs/ConstraintSerializationTest.java @@ -24,35 +24,94 @@ import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ResourcePredicates; import org.apache.brooklyn.util.text.StringPredicates; import org.testng.Assert; import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.gson.Gson; public class ConstraintSerializationTest extends BrooklynMgmtUnitTestSupport { @Test public void testSimple() { assertPredJsonBidi(ConfigConstraints.required(), MutableList.of("required")); + assertPredJsonBidi(Predicates.alwaysFalse(), MutableList.of("Predicates.alwaysFalse")); + assertPredJsonBidi(Predicates.alwaysTrue(), MutableList.of()); // simplified to no-op + assertPredJsonBidi(ResourcePredicates.urlExists(), MutableList.of("urlExists")); + assertPredJsonBidi(StringPredicates.isBlank(), MutableList.of("isBlank")); + assertPredJsonBidi(StringPredicates.matchesRegex("a.*b"), MutableList.of(MutableMap.of("regex", "a.*b"))); + assertPredJsonBidi(StringPredicates.matchesGlob("a?b"), MutableList.of(MutableMap.of("glob", "a?b"))); + assertPredJsonBidi(ConfigConstraints.forbiddenIf("myother"), MutableList.of(MutableMap.of("forbiddenIf", "myother"))); + assertPredJsonBidi(ConfigConstraints.forbiddenUnless("myother"), MutableList.of(MutableMap.of("forbiddenUnless", "myother"))); + assertPredJsonBidi(ConfigConstraints.requiredIf("myother"), MutableList.of(MutableMap.of("requiredIf", "myother"))); + assertPredJsonBidi(ConfigConstraints.requiredUnless("myother"), MutableList.of(MutableMap.of("requiredUnless", "myother"))); + } + + @Test + public void testSimpleEquivalents() { + Gson gson = new Gson(); + + assertPredicateFromJson(ConfigConstraints.required(), + "required", "required()", "isNonBlank"); + + assertPredicateFromJson(StringPredicates.matchesRegex("a"), + "regex(\"a\")", "matchesRegex(\"a\")"); + + assertPredicateFromJson(StringPredicates.matchesGlob("a"), + "glob(\"a\")", "matchesGlob(\"a\")"); + + assertPredicateFromJson(Predicates.and(StringPredicates.matchesRegex("a"), StringPredicates.matchesRegex("b")), + gson.fromJson("[{and: [{regex: a},{regex: b}]}]", List.class), + gson.fromJson("[{all: [{regex: a},{regex: b}]}]", List.class)); + + assertPredicateFromJson(Predicates.or(StringPredicates.matchesRegex("a"), StringPredicates.matchesRegex("b")), + gson.fromJson("[{or: [{regex: a},{regex: b}]}]", List.class), + gson.fromJson("[{any: [{regex: a},{regex: b}]}]", List.class)); } @Test public void testInteresting() { assertPredJsonBidi(Predicates.and(ConfigConstraints.required(), StringPredicates.matchesRegex(".*")), - MutableList.of("required", MutableMap.of("regex", ".*"))); + MutableList.of("required", MutableMap.of("regex", ".*"))); + } + + @Test + public void testAnd() { + Predicate p = Predicates.and( + StringPredicates.matchesRegex("my.*first"), + StringPredicates.matchesRegex("my.*second")); + List json = MutableList.of( + MutableMap.of("regex", "my.*first"), + MutableMap.of("regex", "my.*second")); + + assertPredJsonBidi(p, json); + } + + @Test + public void testOr() { + Predicate p = Predicates.or( + StringPredicates.matchesRegex("my.*first"), + StringPredicates.matchesRegex("my.*second")); + List json = MutableList.of( + MutableMap.of("any", MutableList.of( + MutableMap.of("regex", "my.*first"), + MutableMap.of("regex", "my.*second")))); + + assertPredJsonBidi(p, json); } @SuppressWarnings("unchecked") @Test - public void testNestedAnd() { + public void testNestedAndIsSimplified() { Predicate p = Predicates.and( - ConfigConstraints.required(), - Predicates.and(Predicates.alwaysTrue()), - Predicates.and(StringPredicates.matchesRegex(".*"))); + ConfigConstraints.required(), + Predicates.and(Predicates.alwaysTrue()), + Predicates.and(StringPredicates.matchesRegex(".*"))); Assert.assertEquals(ConstraintSerialization.INSTANCE.toJsonList(p), - MutableList.of("required", MutableMap.of("regex", ".*"))); + MutableList.of("required", MutableMap.of("regex", ".*"))); } @Test @@ -63,7 +122,7 @@ public void testAltName() { assertSamePredicate(ConstraintSerialization.INSTANCE.toPredicateFromJson( MutableList.of(MutableMap.of("glob", "???*"))), p); Assert.assertEquals(ConstraintSerialization.INSTANCE.toJsonList(p), - MutableList.of(MutableMap.of("glob", "???*"))); + MutableList.of(MutableMap.of("glob", "???*"))); } @Test @@ -112,10 +171,15 @@ private void assertPredJsonBidi(Predicate pred, List json) { assertSamePredicate(ConstraintSerialization.INSTANCE.toPredicateFromJson(json), pred); } + private void assertPredicateFromJson(Predicate expected, Object... inputs) { + for (Object input : inputs) { + assertSamePredicate(ConstraintSerialization.INSTANCE.toPredicateFromJson(input), expected); + } + } + private static void assertSamePredicate(Predicate p1, Predicate p2) { // some predicates don't support equals, but all (the ones we use) must support toString Assert.assertEquals(p1.toString(), p2.toString()); Assert.assertEquals(p1.getClass(), p2.getClass()); } - } diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java b/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java index 6383a09acd..5f296260b6 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java @@ -48,7 +48,14 @@ public static MutableList of(V v1) { return result; } - public static MutableList of(V v1, V v2, V ...vv) { + public static MutableList of(V v1, V v2) { + MutableList result = new MutableList(); + result.add(v1); + result.add(v2); + return result; + } + + public static MutableList of(V v1, V v2, V... vv) { MutableList result = new MutableList(); result.add(v1); result.add(v2);