Repository: brooklyn-server
Updated Branches:
  refs/heads/master 923abe7b3 -> 58b1de717


Basic coverage of DSL YAML parsing and evaluation


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/2e0ee180
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/2e0ee180
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/2e0ee180

Branch: refs/heads/master
Commit: 2e0ee180db8713a8251c68538a63550c2c29a537
Parents: 7f1846c
Author: Svetoslav Neykov <svetoslav.ney...@cloudsoftcorp.com>
Authored: Thu Dec 8 11:27:04 2016 +0200
Committer: Svetoslav Neykov <svetoslav.ney...@cloudsoftcorp.com>
Committed: Tue Dec 13 09:15:34 2016 +0200

----------------------------------------------------------------------
 .../camp/brooklyn/dsl/DslYamlBlockingTest.java  | 673 +++++++++++++++++++
 1 file changed, 673 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/2e0ee180/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
----------------------------------------------------------------------
diff --git 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
new file mode 100644
index 0000000..280b060
--- /dev/null
+++ 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
@@ -0,0 +1,673 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * 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 org.apache.brooklyn.camp.brooklyn.dsl;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.entity.stock.BasicApplication;
+import org.apache.brooklyn.entity.stock.BasicEntity;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
+import org.apache.brooklyn.util.core.task.ImmediateSupplier;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+// Doesn't test executing the DSL from different contexts (i.e. fetching the 
config from children inheriting it)
+public class DslYamlBlockingTest extends AbstractYamlTest {
+    private static final ConfigKey<Object> DEST = 
ConfigKeys.newConfigKey(Object.class, "dest");
+    private static final ConfigKey<Object> DEST2 = 
ConfigKeys.newConfigKey(Object.class, "dest2");
+    private static final ConfigKey<Object> DEST3 = 
ConfigKeys.newConfigKey(Object.class, "dest3");
+
+    // See also test-referencing-entities.yaml
+
+    // No tests for entitySpec, object, formatString, external - relying on 
extensive tests elsewhere
+
+    @Test
+    public void testDslSelf() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:self()");
+        assertEquals(getConfigEventually(app, DEST), app);
+    }
+
+    @Test
+    public void testDslEntity() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:entity(\"child\")",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: child");
+        assertEquals(getConfigEventually(app, DEST), 
Iterables.getOnlyElement(app.getChildren()));
+    }
+
+    @Test
+    public void testDslParent() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    brooklyn.config:",
+                "      dest: $brooklyn:parent()");
+        final Entity child = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(getConfigEventually(child, DEST), app);
+    }
+
+    @Test
+    public void testDslChild() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:child(\"child\")",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: child",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: another-child");
+        assertEquals(getConfigEventually(app, DEST), 
app.getChildren().iterator().next());
+    }
+
+    @Test
+    public void testDslSibling() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: child",
+                "    brooklyn.config:",
+                "      dest: $brooklyn:sibling(\"another-child\")",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: another-child");
+        final Entity child1 = Iterables.get(app.getChildren(), 0);
+        final Entity child2 = Iterables.get(app.getChildren(), 1);
+        assertEquals(getConfigEventually(child1, DEST), child2);
+    }
+
+    @Test
+    public void testDslDescendant() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  id: self",
+                "  brooklyn.config:",
+                "    dest: $brooklyn:descendant(\"child\")",
+                "    dest2: $brooklyn:descendant(\"grand-child\")",
+                "    dest3: $brooklyn:descendant(\"self\")",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: child",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: another-child",
+                "    brooklyn.children:",
+                "    - type: " + BasicEntity.class.getName(),
+                "      id: grand-child");
+        final Entity child1 = Iterables.get(app.getChildren(), 0);
+        final Entity child2 = Iterables.get(app.getChildren(), 1);
+        final Entity grandChild = 
Iterables.getOnlyElement(child2.getChildren());
+        assertEquals(getConfigEventually(app, DEST), child1);
+        assertEquals(getConfigEventually(app, DEST2), grandChild);
+        try {
+            assertEquals(getConfigEventually(app, DEST3), app);
+            Asserts.shouldHaveFailedPreviously("Self not in descendant scope");
+        } catch (Exception e) {
+            Asserts.expectedFailureContains(e, "No entity matching id self");
+        }
+    }
+
+    @Test
+    public void testDslAncestor() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  id: app",
+                "  brooklyn.config:",
+                "    dest: $brooklyn:ancestor(\"app\")",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    brooklyn.config:",
+                "      dest: $brooklyn:ancestor(\"app\")",
+                "  - type: " + BasicEntity.class.getName(),
+                "    brooklyn.config:",
+                "      dest: $brooklyn:ancestor(\"app\")",
+                "    brooklyn.children:",
+                "    - type: " + BasicEntity.class.getName(),
+                "      brooklyn.config:",
+                "        dest: $brooklyn:ancestor(\"app\")");
+        final Entity child1 = Iterables.get(app.getChildren(), 0);
+        final Entity child2 = Iterables.get(app.getChildren(), 1);
+        final Entity grandChild = 
Iterables.getOnlyElement(child2.getChildren());
+        assertEquals(getConfigEventually(child1, DEST), app);
+        assertEquals(getConfigEventually(child2, DEST), app);
+        assertEquals(getConfigEventually(grandChild, DEST), app);
+        try {
+            assertEquals(getConfigEventually(app, DEST), app);
+            Asserts.shouldHaveFailedPreviously("App not in ancestor scope");
+        } catch (Exception e) {
+            Asserts.expectedFailureContains(e, "No entity matching id app");
+        }
+    }
+
+    @Test
+    public void testDslRoot() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  id: app",
+                "  brooklyn.config:",
+                "    dest: $brooklyn:root()",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    brooklyn.config:",
+                "      dest: $brooklyn:root()",
+                "  - type: " + BasicEntity.class.getName(),
+                "    brooklyn.config:",
+                "      dest: $brooklyn:root()",
+                "    brooklyn.children:",
+                "    - type: " + BasicEntity.class.getName(),
+                "      brooklyn.config:",
+                "        dest: $brooklyn:root()");
+        final Entity child1 = Iterables.get(app.getChildren(), 0);
+        final Entity child2 = Iterables.get(app.getChildren(), 1);
+        final Entity grandChild = 
Iterables.getOnlyElement(child2.getChildren());
+        assertEquals(getConfigEventually(child1, DEST), app);
+        assertEquals(getConfigEventually(child2, DEST), app);
+        assertEquals(getConfigEventually(grandChild, DEST), app);
+        assertEquals(getConfigEventually(app, DEST), app);
+    }
+
+    @Test
+    public void testDslScopeRoot() throws Exception {
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  version: " + TEST_VERSION,
+                "  items:",
+                "  - id: simple-item",
+                "    itemType: entity",
+                "    item:",
+                "      type: "+ BasicEntity.class.getName(),
+                "  - id: wrapping-plain",
+                "    itemType: entity",
+                "    item:",
+                "      type: "+ BasicEntity.class.getName(),
+                "      brooklyn.children:",
+                "      - type: " + BasicEntity.class.getName(),
+                "        brooklyn.config:",
+                "          dest: $brooklyn:scopeRoot()",
+                "  - id: wrapping-simple",
+                "    itemType: entity",
+                "    item:",
+                "      type: "+ BasicEntity.class.getName(),
+                "      brooklyn.children:",
+                "      - type: simple-item",
+                "        brooklyn.config:",
+                "          dest: $brooklyn:scopeRoot()");
+
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.children:",
+                "  - type: wrapping-plain",
+                "  - type: wrapping-simple");
+        Entity child1 = Iterables.get(app.getChildren(), 0);
+        Entity child2 = Iterables.get(app.getChildren(), 1);
+        assertScopeRoot(child1, false);
+        // TODO Not the result I'd expect - in both cases the entity argument 
should the the scopeRoot element, not its child
+        assertScopeRoot(child2, true);
+    }
+
+    private void assertScopeRoot(Entity entity, boolean isScopeBugged) throws 
Exception {
+        Entity child = Iterables.getOnlyElement(entity.getChildren());
+        if (!isScopeBugged) {
+            assertEquals(getConfigEventually(child, DEST), entity);
+        } else {
+            assertEquals(getConfigEventually(child, DEST), child);
+        }
+    }
+
+    @Test
+    public void testDslConfig() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    source: myvalue",
+                "    dest: $brooklyn:config(\"source\")");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test
+    public void testDslConfigOnEntity() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:entity(\"sourceEntity\").config(\"source\")",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: sourceEntity",
+                "    brooklyn.config:",
+                "      source: myvalue");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test(groups="WIP") // config accepts strings only, no suppliers
+    public void testDslConfigWithDeferredArg() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    source: myvalue",
+                "    configName: source",
+                "    dest: $brooklyn:config(config(\"configName\"))");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test(groups="WIP") // config accepts strings only, no suppliers
+    public void testDslConfigOnEntityWithDeferredArg() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    entityName: sourceEntity",
+                "    configName: source",
+                "    dest: 
$brooklyn:entity(config(\"entityName\")).config(config(\"configName\"))",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: sourceEntity",
+                "    brooklyn.config:",
+                "      source: myvalue");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test
+    public void testDslAttributeWhenReady() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.initializers:",
+                "  - type: org.apache.brooklyn.core.sensor.StaticSensor",
+                "    brooklyn.config:",
+                "      name: source",
+                "      static.value: myvalue",
+                "  brooklyn.config:",
+                "    dest: $brooklyn:attributeWhenReady(\"source\")");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test
+    public void testDslAttributeWhenReadyOnEntity() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:entity(\"sourceEntity\").attributeWhenReady(\"source\")",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: sourceEntity",
+                "    brooklyn.initializers:",
+                "    - type: org.apache.brooklyn.core.sensor.StaticSensor",
+                "      brooklyn.config:",
+                "        name: source",
+                "        static.value: myvalue");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test(groups="WIP") // config accepts strings only, no suppliers
+    public void testDslAttributeWhenReadyWithDeferredArg() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.initializers:",
+                "  - type: org.apache.brooklyn.core.sensor.StaticSensor",
+                "    brooklyn.config:",
+                "      name: source",
+                "      static.value: myvalue",
+                "  brooklyn.config:",
+                "    configName: source",
+                "    dest: 
$brooklyn:attributeWhenReady(config(\"configName\"))");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+
+    @Test(groups="WIP") // config accepts strings only, no suppliers
+    public void testDslAttributeWhenReadyOnEntityWithDeferredArg() throws 
Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    entityName: sourceEntity",
+                "    configName: source",
+                "    dest: 
$brooklyn:entity(config(\"entityName\")).attributeWhenReady(config(\"configName\"))",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: sourceEntity",
+                "    brooklyn.initializers:",
+                "    - type: org.apache.brooklyn.core.sensor.StaticSensor",
+                "      brooklyn.config:",
+                "        name: source",
+                "        static.value: myvalue");
+        assertEquals(getConfigEventually(app, DEST), "myvalue");
+    }
+    
+    @Test
+    public void testDslEntityId() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:entityId()");
+        assertEquals(getConfigEventually(app, DEST), app.getId());
+    }
+
+    @Test
+    public void testDslEntityIdOnEntity() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:entity(\"sourceEntity\").entityId()",
+                "  brooklyn.children:",
+                "  - type: " + BasicEntity.class.getName(),
+                "    id: sourceEntity");
+        final Entity child = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(getConfigEventually(app, DEST), child.getId());
+    }
+
+    @Test
+    public void testDslSensor() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + TestApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:sensor(\"test.myattribute\")");
+        assertEquals(getConfigEventually(app, DEST), 
TestApplication.MY_ATTRIBUTE);
+    }
+
+    @Test
+    public void testDslSensorOnEntity() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:entity(\"sourceEntity\").sensor(\"test.myattribute\")",
+                "  brooklyn.children:",
+                "  - type: " + TestApplication.class.getName(),
+                "    id: sourceEntity");
+        assertEquals(getConfigEventually(app, DEST), 
TestApplication.MY_ATTRIBUTE);
+    }
+
+    @Test
+    public void testDslSensorWithClass() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:sensor(\"org.apache.brooklyn.core.test.entity.TestApplication\", 
\"test.myattribute\")");
+        assertEquals(getConfigEventually(app, DEST), 
TestApplication.MY_ATTRIBUTE);
+    }
+
+    @Test
+    public void testDslLiteral() throws Exception {
+        final String literal = "custom(), $brooklyn:root(), invalid; syntax";
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + TestApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:literal(\"" + literal + "\")");
+        assertEquals(getConfigEventually(app, DEST), literal);
+    }
+
+    @Test
+    public void testDslRegexReplacement() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + TestApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:regexReplacement(\"Broooklyn\", \"o+\", 
\"oo\")");
+        assertEquals(getConfigEventually(app, DEST), "Brooklyn");
+    }
+
+    @Test
+    public void testDslRegexReplacementWithDeferredArg() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + TestApplication.class.getName(),
+                "  brooklyn.config:",
+                "    source: Broooklyn",
+                "    pattern: o+",
+                "    replacement: oo",
+                "    dest: $brooklyn:regexReplacement(config(\"source\"), 
config(\"pattern\"), config(\"replacement\"))");
+        assertEquals(getConfigEventually(app, DEST), "Brooklyn");
+    }
+
+    @Test
+    public void testDslFunctionRegexReplacement() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + TestApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:function.regexReplacement(\"o+\", 
\"oo\")");
+        @SuppressWarnings("unchecked")
+        Function<String, String> replacementFn = (Function<String, String>) 
getConfigEventually(app, DEST);
+        assertEquals(replacementFn.apply("Broooklyn"), "Brooklyn");
+    }
+
+    @Test
+    public void testDslFunctionRegexReplacementWithDeferredArg() throws 
Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + TestApplication.class.getName(),
+                "  brooklyn.config:",
+                "    source: Broooklyn",
+                "    pattern: o+",
+                "    replacement: oo",
+                "    dest: 
$brooklyn:function.regexReplacement(config(\"pattern\"), 
config(\"replacement\"))");
+        @SuppressWarnings("unchecked")
+        Function<String, String> replacementFn = (Function<String, String>) 
getConfigEventually(app, DEST);
+        assertEquals(replacementFn.apply("Broooklyn"), "Brooklyn");
+    }
+
+    @Test
+    public void testDeferredDslChainingOnConfig() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    targetEntity: $brooklyn:self()",
+                "    dest: $brooklyn:config(\"targetEntity\").getId()");
+        assertEquals(getConfigEventually(app, DEST), app.getId());
+    }
+
+    @Test
+    public void testDeferredDslChainingOnConfigNoFunction() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:config(\"targetValue\").getNonExistent()");
+        ConfigKey<TestDslSupplierValue> targetValueKey = 
ConfigKeys.newConfigKey(TestDslSupplierValue.class, "targetValue");
+        app.config().set(targetValueKey, new TestDslSupplierValue());
+        try {
+            assertEquals(getConfigEventually(app, DEST), app.getId());
+            Asserts.shouldHaveFailedPreviously("Expected to fail because 
method does not exist");
+        } catch (Exception e) {
+            Asserts.expectedFailureContains(e, "No such function 
'getNonExistent()'");
+        }
+    }
+
+    @Test
+    public void testDeferredDslChainingOnSensor() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:attributeWhenReady(\"targetEntity\").getId()");
+        AttributeSensor<Entity> targetEntitySensor = 
Sensors.newSensor(Entity.class, "targetEntity");
+        app.sensors().set(targetEntitySensor, app);
+        assertEquals(getConfigEventually(app, DEST), app.getId());
+    }
+
+    @Test(groups="WIP")
+    public void testDeferredDslWrapsIntermediates() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:attributeWhenReady(\"targetEntity\").attributeWhenReady(\"entity.id\")");
+        AttributeSensor<Entity> targetEntitySensor = 
Sensors.newSensor(Entity.class, "targetEntity");
+        app.sensors().set(targetEntitySensor, app);
+        assertEquals(getConfigEventually(app, DEST), app.getId());
+    }
+
+    @Test
+    public void testDeferredDslChainingOnNullConfig() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: $brooklyn:config(\"targetEntity\").getId()");
+        try {
+            assertEquals(getConfigEventually(app, DEST), app.getId());
+            Asserts.shouldHaveFailedPreviously("Expected to fail because 
targetEntity config is null");
+        } catch (Exception e) {
+            Asserts.expectedFailureContains(e, "config(\"targetEntity\") 
evaluates to null");
+        }
+    }
+
+    public static class DslTestSupplierWrapper {
+        private Object supplier;
+        
+        public DslTestSupplierWrapper(Object supplier) {
+            this.supplier = supplier;
+        }
+
+        public Object getSupplier() {
+            return supplier;
+        }
+    }
+
+    public static class TestDslSupplierValue {
+        public boolean isSupplierEvaluated() {
+            return true;
+        }
+    }
+
+    public static class TestDslSupplier implements DeferredSupplier<Object>, 
ImmediateSupplier<Object> {
+        private Object value;
+
+        public TestDslSupplier(Object value) {
+            this.value = value;
+        }
+
+        @Override
+        public Object get() {
+            return getImmediately().get();
+        }
+
+        @Override
+        public Maybe<Object> getImmediately() {
+            return Maybe.of(value);
+        }
+    }
+
+    @Test
+    public void testDeferredDslChainingWithCustomSupplier() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:config(\"customSupplierWrapper\").getSupplier().isSupplierEvaluated()");
+        ConfigKey<DslTestSupplierWrapper> customSupplierWrapperKey = 
ConfigKeys.newConfigKey(DslTestSupplierWrapper.class, "customSupplierWrapper");
+        app.config().set(customSupplierWrapperKey, new 
DslTestSupplierWrapper(new TestDslSupplier(new TestDslSupplierValue())));
+        assertEquals(getConfigEventually(app, DEST), Boolean.TRUE);
+    }
+
+    public static class DslTestCallable implements 
DeferredSupplier<TestDslSupplier>, ImmediateSupplier<TestDslSupplier> {
+
+        @Override
+        public Maybe<TestDslSupplier> getImmediately() {
+            throw new IllegalStateException("Not to be called");
+        }
+
+        @Override
+        public TestDslSupplier get() {
+            throw new IllegalStateException("Not to be called");
+        }
+
+        public boolean isSupplierCallable() {
+            return true;
+        }
+    }
+
+    @Test
+    public void testDeferredDslChainingWithCustomCallable() throws Exception {
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:config(\"customCallableWrapper\").getSupplier().isSupplierCallable()");
+        ConfigKey<DslTestSupplierWrapper> customCallableWrapperKey = 
ConfigKeys.newConfigKey(DslTestSupplierWrapper.class, "customCallableWrapper");
+        app.config().set(customCallableWrapperKey, new 
DslTestSupplierWrapper(new DslTestCallable()));
+        assertEquals(getConfigEventually(app, DEST), Boolean.TRUE);
+    }
+
+    @Test
+    public void testDeferredDslChainingWithNestedEvaluation() throws Exception 
{
+        final Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.config:",
+                "    dest: 
$brooklyn:config(\"customCallableWrapper\").getSupplier().isSupplierCallable()");
+        ConfigKey<TestDslSupplier> customCallableWrapperKey = 
ConfigKeys.newConfigKey(TestDslSupplier.class, "customCallableWrapper");
+        app.config().set(customCallableWrapperKey, new TestDslSupplier(new 
DslTestSupplierWrapper(new DslTestCallable())));
+        assertEquals(getConfigEventually(app, DEST), Boolean.TRUE);
+    }
+
+    private static <T> T getConfigEventually(final Entity entity, final 
ConfigKey<T> configKey) throws Exception {
+        Task<T> result = 
((EntityInternal)entity).getExecutionContext().submit(new Callable<T>() {
+            @Override
+            public T call() throws Exception {
+                // TODO Move the getNonBlocking call out of the task after 
#280 is merged.
+                // Currently doesn't work because no execution context 
available.
+                Maybe<T> immediateValue = 
((EntityInternal)entity).config().getNonBlocking(configKey);
+                T blockingValue = entity.config().get(configKey);
+                assertEquals(immediateValue.get(), blockingValue);
+                return blockingValue;
+            }
+        });
+        return result.get(Asserts.DEFAULT_LONG_TIMEOUT);
+    }
+}

Reply via email to