brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject [2/3] brooklyn-server git commit: Add YAML config tests
Date Thu, 02 Jun 2016 09:19:25 GMT
Add YAML config tests


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

Branch: refs/heads/master
Commit: bf84acc4696a3b14e8f16e9769395a500309de24
Parents: c046587
Author: Aled Sage <aled.sage@gmail.com>
Authored: Thu May 26 11:01:30 2016 +0100
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Wed Jun 1 20:56:51 2016 +0100

----------------------------------------------------------------------
 .../brooklyn/ConfigInheritanceYamlTest.java     | 316 +++++++++++++++++++
 .../camp/brooklyn/ConfigParametersYamlTest.java |  76 +++++
 .../brooklyn/camp/brooklyn/ConfigYamlTest.java  | 302 ++++++++++++++++++
 3 files changed, 694 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bf84acc4/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
new file mode 100644
index 0000000..a9bbcb0
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.api.client.repackaged.com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class ConfigInheritanceYamlTest extends AbstractYamlTest {
+    
+    // TOOD Add tests similar to testEntityTypeInheritanceOptions, for locations, policies
and enrichers.
+    
+    @SuppressWarnings("unused")
+    private static final Logger LOG = LoggerFactory.getLogger(ConfigInheritanceYamlTest.class);
+
+    private Path emptyFile;
+    private Path emptyFile2;
+    
+    private ExecutorService executor;
+
+    @BeforeMethod(alwaysRun = true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        executor = Executors.newCachedThreadPool();
+        
+        emptyFile = Files.createTempFile("ConfigInheritanceYamlTest", ".txt");
+        emptyFile2 = Files.createTempFile("ConfigInheritanceYamlTest2", ".txt");
+        
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: EmptySoftwareProcess-with-conf",
+                "  itemType: entity",
+                "  item:",
+                "    type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess",
+                "    brooklyn.config:",
+                "      shell.env:",
+                "        ENV1: myEnv1",
+                "      templates.preinstall:",
+                "        "+emptyFile.toUri()+": myfile",
+                "      files.preinstall:",
+                "        "+emptyFile.toUri()+": myfile",
+                "      templates.install:",
+                "        "+emptyFile.toUri()+": myfile",
+                "      files.install:",
+                "        "+emptyFile.toUri()+": myfile",
+                "      templates.runtime:",
+                "        "+emptyFile.toUri()+": myfile",
+                "      files.runtime:",
+                "        "+emptyFile.toUri()+": myfile",
+                "      provisioning.properties:",
+                "        mykey: myval",
+                "        templateOptions:",
+                "          myOptionsKey: myOptionsVal");
+        
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: localhost-stub",
+                "  name: Localhost (stubbed-SSH)",
+                "  itemType: location",
+                "  item:",
+                "    type: localhost",
+                "    brooklyn.config:",
+                "      sshToolClass: "+RecordingSshTool.class.getName());
+    }
+
+    @AfterMethod(alwaysRun = true)
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        if (executor != null) executor.shutdownNow();
+        if (emptyFile != null) Files.delete(emptyFile);
+        if (emptyFile2 != null) Files.delete(emptyFile2);
+    }
+    
+    @Test
+    public void testInheritsSuperTypeConfig() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "location: localhost-stub",
+                "services:",
+                "- type: EmptySoftwareProcess-with-conf");
+        
+        Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+        
+        assertEmptySoftwareProcessConfig(
+                entity,
+                ImmutableMap.of("ENV1", "myEnv1"),
+                ImmutableMap.of(emptyFile.toUri().toString(), "myfile"),
+                ImmutableMap.of("mykey", "myval", "templateOptions", ImmutableMap.of("myOptionsKey",
"myOptionsVal")));
+    }
+    
+    @Test
+    public void testInheritsParentConfig() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "location: localhost-stub",
+                "services:",
+                "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+                "  brooklyn.config:",
+                "    shell.env:",
+                "      ENV1: myEnv1",
+                "    templates.preinstall:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    files.preinstall:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    templates.install:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    files.install:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    templates.runtime:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    files.runtime:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    provisioning.properties:",
+                "      mykey: myval",
+                "      templateOptions:",
+                "        myOptionsKey: myOptionsVal", 
+                "  brooklyn.children:",
+                "  - type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess");
+
+        Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+        
+        assertEmptySoftwareProcessConfig(
+                entity,
+                ImmutableMap.of("ENV1", "myEnv1"),
+                ImmutableMap.of(emptyFile.toUri().toString(), "myfile"),
+                ImmutableMap.of("mykey", "myval", "templateOptions", ImmutableMap.of("myOptionsKey",
"myOptionsVal")));
+    }
+    
+    /**
+     * TODO This hangs because the attributeWhenReady self-reference is resolved against
the entity
+     * looking up the config value (i.e. the child). Therefore it waits for the TestEntity
to have
+     * a value for that sensor, but this never happens. The way to avoid this is to explicitly
set
+     * the component that the attributeWhenReady should apply to (e.g. see {@link #testInheritsParentConfigTask()}.
+     * 
+     * Do we want to just exclude this test? Or do we want to "fix" it? Which entity should
the
+     * attributeWhenReady apply to?
+     */
+    @Test(groups={"Broken", "WIP"}, enabled=false)
+    public void testInheritsParentConfigTask() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+                "  brooklyn.config:",
+                "    test.confName: $brooklyn:config(\"myOtherConf\")",
+                "    test.confObject: $brooklyn:attributeWhenReady(\"myOtherSensor\")",
+                "    myOtherConf: myOther",
+                "  brooklyn.children:",
+                "  - type: org.apache.brooklyn.core.test.entity.TestEntity");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        // Task that resolves quickly
+        assertEquals(entity.config().get(TestEntity.CONF_NAME), "myOther");
+        
+        // Task that resolves slowly
+        executor.submit(new Callable<Object>() {
+            public Object call() {
+                return app.sensors().set(Sensors.newStringSensor("myOtherSensor"), "myObject");
+            }});
+        assertEquals(entity.config().get(TestEntity.CONF_OBJECT), "myObject");
+    }
+    
+    @Test
+    public void testInheritsParentConfigOfTypeMapWithIndividualKeys() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+                "  brooklyn.config:",
+                "    test.confMapThing.mykey: myval",
+                "    test.confMapThing.mykey2: $brooklyn:config(\"myOtherConf\")",
+                "    myOtherConf: myOther",
+                "  brooklyn.children:",
+                "  - type: org.apache.brooklyn.core.test.entity.TestEntity");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mykey",
"myval", "mykey2", "myOther"));
+    }
+    
+    @Test
+    public void testInheritsParentConfigOfTypeMapWithOneBigVal() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+                "  brooklyn.config:",
+                "    test.confMapThing:",
+                "      mykey: myval",
+                "      mykey2: $brooklyn:config(\"myOtherConf\")",
+                "    myOtherConf: myOther",
+                "  brooklyn.children:",
+                "  - type: org.apache.brooklyn.core.test.entity.TestEntity");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mykey",
"myval", "mykey2", "myOther"));
+    }
+    
+    @Test
+    public void testOverridesParentConfig() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "location: localhost-stub",
+                "services:",
+                "- type: org.apache.brooklyn.entity.stock.BasicApplication",
+                "  brooklyn.config:",
+                "    shell.env:",
+                "      ENV1: myEnv1",
+                "    templates.preinstall:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    files.preinstall:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    templates.install:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    files.install:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    templates.runtime:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    files.runtime:",
+                "      "+emptyFile.toUri()+": myfile",
+                "    provisioning.properties:",
+                "      mykey: myval",
+                "      templateOptions:",
+                "        myOptionsKey: myOptionsVal", 
+                "  brooklyn.children:",
+                "  - type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess",
+                "    brooklyn.config:",
+                "      shell.env:",
+                "        ENV2: myEnv2",
+                "      templates.preinstall:",
+                "        "+emptyFile2.toUri()+": myfile2",
+                "      files.preinstall:",
+                "        "+emptyFile2.toUri()+": myfile2",
+                "      templates.install:",
+                "        "+emptyFile2.toUri()+": myfile2",
+                "      files.install:",
+                "        "+emptyFile2.toUri()+": myfile2",
+                "      templates.runtime:",
+                "        "+emptyFile2.toUri()+": myfile2",
+                "      files.runtime:",
+                "        "+emptyFile2.toUri()+": myfile2",
+                "      provisioning.properties:",
+                "        mykey2: myval2",
+                "        templateOptions:",
+                "          myOptionsKey2: myOptionsVal2");
+        
+        Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+        
+        assertEmptySoftwareProcessConfig(
+                entity,
+                ImmutableMap.of("ENV2", "myEnv2"),
+                ImmutableMap.of(emptyFile2.toUri().toString(), "myfile2"),
+                ImmutableMap.of("mykey2", "myval2", "templateOptions", ImmutableMap.of("myOptionsKey2",
"myOptionsVal2")));
+    }
+    
+    protected void assertEmptySoftwareProcessConfig(Entity entity, Map<String, ?> expectedEnv,
Map<String, String> expectedFiles, Map<String, ?> expectedProvisioningProps) {
+        EntityAsserts.assertConfigEquals(entity, EmptySoftwareProcess.SHELL_ENVIRONMENT,
MutableMap.<String, Object>copyOf(expectedEnv));
+        
+        List<ConfigKey<Map<String,String>>> keys = ImmutableList.of(EmptySoftwareProcess.PRE_INSTALL_TEMPLATES,

+                EmptySoftwareProcess.PRE_INSTALL_FILES, EmptySoftwareProcess.INSTALL_TEMPLATES,

+                EmptySoftwareProcess.INSTALL_FILES, EmptySoftwareProcess.RUNTIME_TEMPLATES,

+                EmptySoftwareProcess.RUNTIME_FILES);
+        for (ConfigKey<Map<String,String>> key : keys) {
+            EntityAsserts.assertConfigEquals(entity, key, expectedFiles);
+        }
+        
+        EntityAsserts.assertConfigEquals(entity, EmptySoftwareProcess.PROVISIONING_PROPERTIES,
MutableMap.<String, Object>copyOf(expectedProvisioningProps));
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bf84acc4/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..0dce749
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.StringReader;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import com.google.api.client.repackaged.com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class ConfigParametersYamlTest extends AbstractYamlTest {
+    @SuppressWarnings("unused")
+    private static final Logger LOG = LoggerFactory.getLogger(ConfigParametersYamlTest.class);
+
+    @Test
+    public void testConfigParametersListedInType() throws Exception {
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  itemType: entity",
+                "  items:",
+                "  - id: entity-with-keys",
+                "    item:",
+                "      type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "      brooklyn.parameters:",
+                "      - name: testConfigParametersListedInType.mykey",
+                "        description: myDescription",
+                "        type: java.util.Map",
+                "        inheritance.type: merge",
+                "        default: {myDefaultKey: myDefaultVal}");
+        
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys");
+        
+        Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+
+        // Check config key is listed
+        ConfigKey<?> key = entity.getEntityType().getConfigKey("testConfigParametersListedInType.mykey");
+        assertNotNull(key);
+        assertEquals(key.getName(), "testConfigParametersListedInType.mykey");
+        assertEquals(key.getDescription(), "myDescription");
+        assertEquals(key.getType(), Map.class);
+        assertEquals(key.getDefaultValue(), ImmutableMap.of("myDefaultKey", "myDefaultVal"));
+        
+        // Check get default value
+        assertEquals(entity.config().get(key), ImmutableMap.of("myDefaultKey", "myDefaultVal"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bf84acc4/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigYamlTest.java
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigYamlTest.java
new file mode 100644
index 0000000..569f90a
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigYamlTest.java
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.StringReader;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.api.client.repackaged.com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class ConfigYamlTest extends AbstractYamlTest {
+    
+    @SuppressWarnings("unused")
+    private static final Logger LOG = LoggerFactory.getLogger(ConfigYamlTest.class);
+
+    private ExecutorService executor;
+
+    @BeforeMethod(alwaysRun = true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        executor = Executors.newCachedThreadPool();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        if (executor != null) executor.shutdownNow();
+    }
+
+    @Test
+    public void testPlainCollections() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confMapPlain:",
+                "      mykey: myval",
+                "    test.confListPlain:",
+                "    - myval",
+                "    test.confSetPlain:",
+                "    - myval");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        // Task that resolves quickly
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_PLAIN), ImmutableMap.of("mykey",
"myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_PLAIN), ImmutableList.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_PLAIN), ImmutableSet.of("myval"));
+    }
+    
+    /**
+     * This tests config keys of type {@link org.apache.brooklyn.core.config.MapConfigKey},
etc.
+     * It sets the value all in one go (as opposed to explicit sub-keys).
+     */
+    @Test
+    public void testSpecialTypeCollections() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confMapThing:",
+                "      mykey: myval",
+                "    test.confMapObjThing:",
+                "      mykey: myval",
+                "    test.confListThing:",
+                "    - myval",
+                "    test.confListObjThing:",
+                "    - myval",
+                "    test.confSetThing:",
+                "    - myval",
+                "    test.confSetObjThing:",
+                "    - myval");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        // Task that resolves quickly
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mykey",
"myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_OBJ_THING), ImmutableMap.of("mykey",
"myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_THING), ImmutableList.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_OBJ_THING), ImmutableList.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_THING), ImmutableSet.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_OBJ_THING), ImmutableSet.of("myval"));
+    }
+    
+    /**
+     * This tests config keys of type {@link org.apache.brooklyn.core.config.MapConfigKey},
etc.
+     * It sets the value of each sub-key explicitly, rather than all in one go.
+     */
+    @Test
+    public void testSpecialTypeCollectionsWithExplicitSubkeys() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confMapThing.mykey: myval",
+                "    test.confMapObjThing.mykey: myval",
+                "    test.confListThing.mysubkey: myval",
+                "    test.confListObjThing.mysubkey: myval",
+                "    test.confSetThing.mysubkey: myval",
+                "    test.confSetObjThing.mysubkey: myval");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        // Task that resolves quickly
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mykey",
"myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_OBJ_THING), ImmutableMap.of("mykey",
"myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_THING), ImmutableList.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_OBJ_THING), ImmutableList.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_THING), ImmutableSet.of("myval"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_OBJ_THING), ImmutableSet.of("myval"));
+    }
+    
+    @Test
+    public void testDeferredSupplierToConfig() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confName: $brooklyn:config(\"myOtherConf\")",
+                "    test.confMapThing:",
+                "      mykey: $brooklyn:config(\"myOtherConf\")",
+                "    myOtherConf: myOther",
+                "    test.confMapPlain:",
+                "      mykey: $brooklyn:config(\"myOtherConf\")",
+                "    test.confListThing:",
+                "    - $brooklyn:config(\"myOtherConf\")",
+                "    test.confListPlain:",
+                "    - $brooklyn:config(\"myOtherConf\")",
+                "    test.confSetThing:",
+                "    - $brooklyn:config(\"myOtherConf\")",
+                "    test.confSetPlain:",
+                "    - $brooklyn:config(\"myOtherConf\")",
+                "    myOtherConf: myOther");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+     
+        assertEquals(entity.config().get(TestEntity.CONF_NAME), "myOther");
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mykey",
"myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_THING), ImmutableList.of("myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_THING), ImmutableSet.of("myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_PLAIN), ImmutableMap.of("mykey",
"myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_PLAIN), ImmutableList.of("myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_PLAIN), ImmutableSet.of("myOther"));
+    }
+    
+    @Test
+    public void testDeferredSupplierToAttributeWhenReady() throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confName: $brooklyn:attributeWhenReady(\"myOtherSensor\")");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        final TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+
+        // Attribute not yet set; non-blocking will return promptly without the value
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_NAME).isAbsent());
+
+        // Now set the attribute: get will return once that has happened
+        executor.submit(new Callable<Object>() {
+            public Object call() {
+                return entity.sensors().set(Sensors.newStringSensor("myOtherSensor"), "myOther");
+            }});
+        assertEquals(entity.config().get(TestEntity.CONF_NAME), "myOther");
+
+        // Non-blocking calls will now return with the value
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_NAME).get(), "myOther");
+    }
+    
+    /**
+     * This tests config keys of type {@link org.apache.brooklyn.core.config.MapConfigKey},
etc.
+     * For plain maps, see {@link #testDeferredSupplierToAttributeWhenReadyInPlainCollections()}.
+     */
+    @Test
+    public void testDeferredSupplierToAttributeWhenReadyInSpecialTypes() throws Exception
{
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confName: $brooklyn:attributeWhenReady(\"myOtherSensor\")",
+                "    test.confMapThing:",
+                "      mykey: $brooklyn:attributeWhenReady(\"myOtherSensor\")",
+                "    test.confListThing:",
+                "    - $brooklyn:attributeWhenReady(\"myOtherSensor\")",
+                "    test.confSetThing:",
+                "    - $brooklyn:attributeWhenReady(\"myOtherSensor\")");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        final TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+
+        // Attribute not yet set; non-blocking will return promptly without the value
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_NAME).isAbsent());
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING).isAbsent());
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_LIST_THING).isAbsent());
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_SET_THING).isAbsent());
+
+        // Now set the attribute: get will return once that has happened
+        executor.submit(new Callable<Object>() {
+            public Object call() {
+                return entity.sensors().set(Sensors.newStringSensor("myOtherSensor"), "myOther");
+            }});
+        assertEquals(entity.config().get(TestEntity.CONF_NAME), "myOther");
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_THING), ImmutableMap.of("mykey",
"myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_THING), ImmutableList.of("myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_THING), ImmutableSet.of("myOther"));
+
+        // Non-blocking calls will now return with the value
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_NAME).get(), "myOther");
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_THING).get(), ImmutableMap.of("mykey",
"myOther"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_LIST_THING).get(), ImmutableList.of("myOther"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_SET_THING).get(), ImmutableSet.of("myOther"));
+    }
+    
+    /**
+     * This tests config keys of type {@link java.util.Map}, etc.
+     * For special types (e.g. {@link org.apache.brooklyn.core.config.MapConfigKey}), see

+     * {@link #testDeferredSupplierToAttributeWhenReadyInPlainCollections()}.
+     * 
+     * TODO test doesn't work because getNonBlocking returns even when no value.
+     *      For example, we get back: Present[value={mykey=attributeWhenReady("myOtherSensor")}].
+     *      However, the `config().get()` does behave as desired.
+     * 
+     * Including the "WIP" group because this test would presumably have never worked!
+     * Added to demonstrate the short-coming.
+     */
+    @Test(groups={"Broken", "WIP"})
+    public void testDeferredSupplierToAttributeWhenReadyInPlainCollections() throws Exception
{
+        String yaml = Joiner.on("\n").join(
+                "services:",
+                "- type: org.apache.brooklyn.core.test.entity.TestEntity",
+                "  brooklyn.config:",
+                "    test.confMapPlain:",
+                "      mykey: $brooklyn:attributeWhenReady(\"myOtherSensor\")",
+                "    test.confListPlain:",
+                "    - $brooklyn:attributeWhenReady(\"myOtherSensor\")",
+                "    test.confSetPlain:",
+                "    - $brooklyn:attributeWhenReady(\"myOtherSensor\")");
+
+        final Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        final TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+
+        // Attribute not yet set; non-blocking will return promptly without the value
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_MAP_PLAIN).isAbsent());
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_LIST_PLAIN).isAbsent());
+        assertTrue(entity.config().getNonBlocking(TestEntity.CONF_SET_PLAIN).isAbsent());
+
+        // Now set the attribute: get will return once that has happened
+        executor.submit(new Callable<Object>() {
+            public Object call() {
+                return entity.sensors().set(Sensors.newStringSensor("myOtherSensor"), "myOther");
+            }});
+        assertEquals(entity.config().get(TestEntity.CONF_MAP_PLAIN), ImmutableMap.of("mykey",
"myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_LIST_PLAIN), ImmutableList.of("myOther"));
+        assertEquals(entity.config().get(TestEntity.CONF_SET_PLAIN), ImmutableSet.of("myOther"));
+
+        // Non-blocking calls will now return with the value
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_MAP_PLAIN).get(), ImmutableMap.of("mykey",
"myOther"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_LIST_PLAIN).get(), ImmutableList.of("myOther"));
+        assertEquals(entity.config().getNonBlocking(TestEntity.CONF_SET_PLAIN).get(), ImmutableSet.of("myOther"));
+    }
+}


Mime
View raw message