/* * 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.core.entity.internal; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.config.BasicConfigKey; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.location.SimulatedLocation; import org.apache.brooklyn.core.sensor.DependentConfiguration; import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; import org.apache.brooklyn.core.test.entity.TestEntity; import org.apache.brooklyn.util.exceptions.Exceptions; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Callables; /** * Test that configuration properties are usable and inherited correctly. */ public class EntityConfigMapUsageTest extends BrooklynAppUnitTestSupport { private static final int EARLY_RETURN_GRACE = 10; private BasicConfigKey<Integer> intKey = new BasicConfigKey<Integer>(Integer.class, "bkey", "b key"); private ConfigKey<String> strKey = new BasicConfigKey<String>(String.class, "akey", "a key"); private ConfigKey<Integer> intKeyWithDefault = new BasicConfigKey<Integer>(Integer.class, "ckey", "c key", 1); private ConfigKey<String> strKeyWithDefault = new BasicConfigKey<String>(String.class, "strKey", "str key", "str key default"); private List<SimulatedLocation> locs; @BeforeMethod(alwaysRun=true) @Override public void setUp() throws Exception { super.setUp(); locs = ImmutableList.of(new SimulatedLocation()); } @Test public void testConfigPassedInAtConstructionIsAvailable() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKey, "aval") .configure(intKey, 2)); assertEquals(entity.getConfig(strKey), "aval"); assertEquals(entity.getConfig(intKey), (Integer)2); } @Test public void testConfigSetToGroovyTruthFalseIsAvailable() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(intKeyWithDefault, 0)); assertEquals(entity.getConfig(intKeyWithDefault), (Integer)0); } @Test public void testInheritedConfigSetToGroovyTruthFalseIsAvailable() throws Exception { TestEntity parent = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(intKeyWithDefault, 0)); TestEntity entity = parent.createAndManageChild(EntitySpec.create(TestEntity.class)); assertEquals(entity.getConfig(intKeyWithDefault), (Integer)0); } @Test public void testConfigSetToNullIsAvailable() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKeyWithDefault, (String)null)); assertEquals(entity.getConfig(strKeyWithDefault), null); } @Test public void testInheritedConfigSetToNullIsAvailable() throws Exception { TestEntity parent = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKeyWithDefault, (String)null)); TestEntity entity = parent.createAndManageChild(EntitySpec.create(TestEntity.class)); assertEquals(entity.getConfig(strKeyWithDefault), null); } @Test public void testInheritedConfigAvailableDeepInHierarchy() throws Exception { TestEntity parent = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKeyWithDefault, "customval")); TestEntity entity = parent.createAndManageChild(EntitySpec.create(TestEntity.class)); TestEntity entity2 = entity.createAndManageChild(EntitySpec.create(TestEntity.class)); TestEntity entity3 = entity2.createAndManageChild(EntitySpec.create(TestEntity.class)); assertEquals(entity.getConfig(strKeyWithDefault), "customval"); assertEquals(entity2.getConfig(strKeyWithDefault), "customval"); assertEquals(entity3.getConfig(strKeyWithDefault), "customval"); } @Test public void testConfigCanBeSetOnEntity() throws Exception { TestEntity entity = app.addChild(EntitySpec.create(TestEntity.class)); ((EntityLocal)entity).config().set(strKey, "aval"); ((EntityLocal)entity).config().set(intKey, 2); assertEquals(entity.getConfig(strKey), "aval"); assertEquals(entity.getConfig(intKey), (Integer)2); } @Test public void testConfigInheritedFromParent() throws Exception { TestEntity parent = app.addChild(EntitySpec.create(TestEntity.class) .configure(strKey, "aval")); ((EntityLocal)parent).config().set(intKey, 2); TestEntity entity = parent.createAndManageChild(EntitySpec.create(TestEntity.class)); assertEquals(entity.getConfig(strKey), "aval"); assertEquals(2, entity.getConfig(intKey), (Integer)2); } @Test public void testConfigAtConstructionOverridesParentValue() throws Exception { TestEntity parent = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKey, "aval")); TestEntity entity = parent.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKey, "diffval")); assertEquals(entity.getConfig(strKey), "diffval"); } @Test public void testConfigSetterOverridesParentValue() throws Exception { TestEntity parent = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKey, "aval")); TestEntity entity = parent.createAndManageChild(EntitySpec.create(TestEntity.class)); ((EntityLocal)entity).config().set(strKey, "diffval"); assertEquals(entity.getConfig(strKey), "diffval"); } @Test public void testConfigSetterOverridesConstructorValue() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKey, "aval")); ((EntityLocal)entity).config().set(strKey, "diffval"); assertEquals(entity.getConfig(strKey), "diffval"); } @Test public void testConfigSetOnParentInheritedByExistingChildren() throws Exception { TestEntity parent = app.addChild(EntitySpec.create(TestEntity.class)); TestEntity entity = parent.createChild(EntitySpec.create(TestEntity.class)); ((EntityLocal)parent).config().set(strKey,"aval"); assertEquals(entity.getConfig(strKey), "aval"); } @Test public void testConfigInheritedThroughManyGenerations() throws Exception { TestEntity e = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(strKey, "aval")); TestEntity e2 = e.createAndManageChild(EntitySpec.create(TestEntity.class)); TestEntity e3 = e2.createAndManageChild(EntitySpec.create(TestEntity.class)); assertEquals(e.getConfig(strKey), "aval"); assertEquals(e2.getConfig(strKey), "aval"); assertEquals(e3.getConfig(strKey), "aval"); } // This has been relaxed to a warning, with a message saying "may not be supported in future versions" @Test(enabled=false) public void testConfigCannotBeSetAfterApplicationIsStarted() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); app.start(locs); try { ((EntityLocal)app).config().set(strKey,"aval"); fail(); } catch (IllegalStateException e) { // success } assertEquals(entity.getConfig(strKey), null); } @Test public void testConfigReturnsDefaultValueIfNotSet() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); assertEquals(entity.getConfig(TestEntity.CONF_NAME), "defaultval"); } @Test public void testGetFutureConfigWhenReady() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(TestEntity.CONF_NAME, DependentConfiguration.whenDone(Callables.returning("aval")))); app.start(locs); assertEquals(entity.getConfig(TestEntity.CONF_NAME), "aval"); } @Test public void testGetFutureConfigBlocksUntilReady() throws Exception { final CountDownLatch latch = new CountDownLatch(1); TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(TestEntity.CONF_NAME, DependentConfiguration.whenDone(new Callable<String>() { public String call() { try { latch.await(); return "aval"; } catch (InterruptedException e) { throw Exceptions.propagate(e); } }}))); app.start(locs); Thread t = new Thread(new Runnable() { public void run() { try { Thread.sleep(10+EARLY_RETURN_GRACE); latch.countDown(); } catch (InterruptedException e) { throw Exceptions.propagate(e); } }}); try { long starttime = System.currentTimeMillis(); t.start(); assertEquals(entity.getConfig(TestEntity.CONF_NAME), "aval"); long endtime = System.currentTimeMillis(); assertTrue((endtime - starttime) >= 10, "starttime="+starttime+"; endtime="+endtime); } finally { t.interrupt(); } } @Test public void testGetAttributeWhenReadyConfigReturnsWhenSet() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); TestEntity entity2 = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(TestEntity.CONF_NAME, DependentConfiguration.attributeWhenReady(entity, TestEntity.NAME))); app.start(locs); ((EntityLocal)entity).sensors().set(TestEntity.NAME, "aval"); assertEquals(entity2.getConfig(TestEntity.CONF_NAME), "aval"); } @Test public void testGetAttributeWhenReadyWithPostProcessingConfigReturnsWhenSet() throws Exception { TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); TestEntity entity2 = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(TestEntity.CONF_NAME, DependentConfiguration.attributePostProcessedWhenReady(entity, TestEntity.NAME, Predicates.notNull(), new Function<String,String>() { public String apply(String input) { return input+"mysuffix"; }}))); app.start(locs); ((EntityLocal)entity).sensors().set(TestEntity.NAME, "aval"); assertEquals(entity2.getConfig(TestEntity.CONF_NAME), "avalmysuffix"); } @Test public void testGetAttributeWhenReadyConfigBlocksUntilSet() throws Exception { final TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); TestEntity entity2 = app.createAndManageChild(EntitySpec.create(TestEntity.class) .configure(TestEntity.CONF_NAME, DependentConfiguration.attributeWhenReady(entity, TestEntity.NAME))); app.start(locs); Thread t = new Thread(new Runnable() { public void run() { try { Thread.sleep(10+EARLY_RETURN_GRACE); ((EntityLocal)entity).sensors().set(TestEntity.NAME, "aval"); } catch (InterruptedException e) { throw Exceptions.propagate(e); } }}); try { long starttime = System.currentTimeMillis(); t.start(); assertEquals(entity2.getConfig(TestEntity.CONF_NAME), "aval"); long endtime = System.currentTimeMillis(); assertTrue((endtime - starttime) > 10, "starttime="+starttime+"; endtime="+endtime); } finally { t.interrupt(); } } }