/*
* 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.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.time.Time;
import org.testng.annotations.Test;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
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.core.test.entity.TestEntityImpl;
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.
*
* Uses legacy mechanism of calling entity constructors.
*/
public class EntityConfigMapUsageLegacyTest extends BrooklynAppUnitTestSupport {
private ConfigKey<Integer> intKey = ConfigKeys.newIntegerConfigKey("bkey", "b key");
private ConfigKey<String> strKey = ConfigKeys.newStringConfigKey("akey", "a key");
private ConfigKey<Integer> intKeyWithDefault = ConfigKeys.newIntegerConfigKey("ckey", "c key", 1);
private ConfigKey<String> strKeyWithDefault = ConfigKeys.newStringConfigKey("strKey", "str key", "str key default");
@Test
public void testConfigPassedInAtConstructorIsAvailable() throws Exception {
TestEntity entity = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKey, "aval", intKey, 2)), app);
Entities.manage(entity);
assertEquals(entity.getConfig(strKey), "aval");
assertEquals(entity.getConfig(intKey), Integer.valueOf(2));
}
@Test
public void testConfigSetToGroovyTruthFalseIsAvailable() throws Exception {
TestEntity entity = new TestEntityImpl(MutableMap.of("config", MutableMap.of(intKeyWithDefault, 0)), app);
Entities.manage(entity);
assertEquals(entity.getConfig(intKeyWithDefault), (Integer)0);
}
@Test
public void testInheritedConfigSetToGroovyTruthFalseIsAvailable() throws Exception {
TestEntity parent = new TestEntityImpl(MutableMap.of("config", MutableMap.of(intKeyWithDefault, 0)), app);
TestEntity entity = new TestEntityImpl(parent);
Entities.manage(parent);
assertEquals(entity.getConfig(intKeyWithDefault), (Integer)0);
}
@Test
public void testConfigSetToNullIsAvailable() throws Exception {
TestEntity entity = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKeyWithDefault, null)), app);
Entities.manage(entity);
assertEquals(entity.getConfig(strKeyWithDefault), null);
}
@Test
public void testInheritedConfigSetToNullIsAvailable() throws Exception {
TestEntity parent = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKeyWithDefault, null)), app);
TestEntity entity = new TestEntityImpl(parent);
Entities.manage(parent);
assertEquals(entity.getConfig(strKeyWithDefault), null);
}
@Test
public void testConfigCanBeSetOnEntity() throws Exception {
TestEntity entity = new TestEntityImpl(app);
entity.config().set(strKey, "aval");
entity.config().set(intKey, 2);
Entities.manage(entity);
assertEquals(entity.getConfig(strKey), "aval");
assertEquals(entity.getConfig(intKey), (Integer)2);
}
@Test
public void testConfigInheritedFromParent() throws Exception {
TestEntity parent = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKey, "aval")), app);
parent.config().set(intKey, 2);
TestEntity entity = new TestEntityImpl(parent);
Entities.manage(parent);
assertEquals(entity.getConfig(strKey), "aval");
assertEquals(entity.getConfig(intKey), (Integer)2);
}
@Test
public void testConfigInConstructorOverridesParentValue() throws Exception {
TestEntity parent = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKey, "aval")), app);
TestEntity entity = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKey, "diffval")), parent);
Entities.manage(parent);
assertEquals("diffval", entity.getConfig(strKey));
}
@Test
public void testConfigSetterOverridesParentValue() throws Exception {
TestEntity parent = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKey, "aval")), app);
TestEntity entity = new TestEntityImpl(parent);
entity.config().set(strKey, "diffval");
Entities.manage(parent);
assertEquals("diffval", entity.getConfig(strKey));
}
@Test
public void testConfigSetterOverridesConstructorValue() throws Exception {
TestEntity entity = new TestEntityImpl(MutableMap.of("config", MutableMap.of(strKey, "aval")), app);
entity.config().set(strKey, "diffval");
Entities.manage(entity);
assertEquals("diffval", entity.getConfig(strKey));
}
@Test
public void testConfigSetOnParentInheritedByExistingChildrenBeforeStarted() throws Exception {
TestEntity entity = new TestEntityImpl(app);
app.config().set(strKey,"aval");
Entities.manage(entity);
assertEquals("aval", entity.getConfig(strKey));
}
@Test
public void testConfigInheritedThroughManyGenerations() throws Exception {
TestEntity e = new TestEntityImpl(app);
TestEntity e2 = new TestEntityImpl(e);
app.config().set(strKey,"aval");
Entities.manage(e);
assertEquals("aval", app.getConfig(strKey));
assertEquals("aval", e.getConfig(strKey));
assertEquals("aval", e2.getConfig(strKey));
}
@Test(enabled=false)
public void testConfigCannotBeSetAfterApplicationIsStarted() throws Exception {
TestEntity entity = new TestEntityImpl(app);
Entities.manage(entity);
app.start(ImmutableList.of(new SimulatedLocation()));
try {
app.config().set(strKey,"aval");
fail();
} catch (IllegalStateException e) {
// success
}
assertEquals(null, entity.getConfig(strKey));
}
@Test
public void testConfigReturnsDefaultValueIfNotSet() throws Exception {
TestEntity entity = new TestEntityImpl(app);
Entities.manage(entity);
assertEquals(entity.getConfig(TestEntity.CONF_NAME), "defaultval");
}
@Test
public void testGetFutureConfigWhenReady() throws Exception {
TestEntity entity = new TestEntityImpl(app);
entity.config().set(TestEntity.CONF_NAME, DependentConfiguration.whenDone(Callables.returning("aval")));
Entities.manage(entity);
app.start(ImmutableList.of(new SimulatedLocation()));
assertEquals(entity.getConfig(TestEntity.CONF_NAME), "aval");
}
@Test
public void testGetFutureConfigBlocksUntilReady() throws Exception {
TestEntity entity = new TestEntityImpl(app);
final CountDownLatch latch = new CountDownLatch(1);
entity.config().set(TestEntity.CONF_NAME, DependentConfiguration.whenDone(new Callable<String>() {
@Override public String call() throws Exception {
latch.await();
return "aval";
}}));
Entities.manage(entity);
app.start(ImmutableList.of(new SimulatedLocation()));
Thread t = new Thread(new Runnable() {
public void run() {
Time.sleep(10);
latch.countDown();
}});
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 = new TestEntityImpl(app);
TestEntity entity2 = new TestEntityImpl(app);
entity.config().set(TestEntity.CONF_NAME, DependentConfiguration.attributeWhenReady(entity2, TestEntity.NAME));
Entities.manage(entity);
Entities.manage(entity2);
app.start(ImmutableList.of(new SimulatedLocation()));
entity2.sensors().set(TestEntity.NAME, "aval");
assertEquals(entity.getConfig(TestEntity.CONF_NAME), "aval");
}
@Test
public void testGetAttributeWhenReadyWithPostProcessingConfigReturnsWhenSet() throws Exception {
TestEntity entity = new TestEntityImpl(app);
TestEntity entity2 = new TestEntityImpl(app);
entity.config().set(TestEntity.CONF_NAME, DependentConfiguration.attributePostProcessedWhenReady(entity2, TestEntity.NAME, Predicates.notNull(), new Function<String,String>() {
@Override public String apply(String input) {
return (input == null) ? null : input+"mysuffix";
}}));
Entities.manage(entity);
Entities.manage(entity2);
app.start(ImmutableList.of(new SimulatedLocation()));
entity2.sensors().set(TestEntity.NAME, "aval");
assertEquals(entity.getConfig(TestEntity.CONF_NAME), "avalmysuffix");
}
@Test
public void testGetAttributeWhenReadyConfigBlocksUntilSet() throws Exception {
TestEntity entity = new TestEntityImpl(app);
final TestEntity entity2 = new TestEntityImpl(app);
entity.config().set(TestEntity.CONF_NAME, DependentConfiguration.attributeWhenReady(entity2, TestEntity.NAME));
Entities.manage(entity);
Entities.manage(entity2);
app.start(ImmutableList.of(new SimulatedLocation()));
// previously was just sleep 10, and (endtime-starttime > 10); failed with exactly 10ms
final long sleepTime = 20;
final long earlyReturnGrace = 5;
Thread t = new Thread(new Runnable() {
@Override public void run() {
Time.sleep(sleepTime);
entity2.sensors().set(TestEntity.NAME, "aval");
}});
try {
long starttime = System.currentTimeMillis();
t.start();
assertEquals(entity.getConfig(TestEntity.CONF_NAME), "aval");
long endtime = System.currentTimeMillis();
assertTrue((endtime - starttime) >= (sleepTime - earlyReturnGrace), "starttime=$starttime; endtime=$endtime");
} finally {
t.interrupt();
}
}
}