blob: 5ebf24ae0f6cb0ef99e12dc0f9a1b2487253d322 [file] [log] [blame]
/*
* 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.qpid.server.model.testmodels.singleton;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import javax.security.auth.Subject;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Model;
import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.test.utils.QpidTestCase;
/**
* Tests behaviour of AbstractConfiguredObject related to attributes including
* persistence, defaulting, and attribute values derived from context variables.
*/
public class AbstractConfiguredObjectTest extends QpidTestCase
{
private final Model _model = TestModel.getInstance();
public void testAttributePersistence()
{
final String objectName = "testNonPersistAttributes";
TestSingleton object =
_model.getObjectFactory().create(TestSingleton.class,
Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
objectName)
);
assertEquals(objectName, object.getName());
assertNull(object.getAutomatedNonPersistedValue());
assertNull(object.getAutomatedPersistedValue());
assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
ConfiguredObjectRecord record = object.asObjectRecord();
assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_PERSISTED_VALUE));
assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_NONPERSISTED_VALUE));
assertFalse(record.getAttributes().containsKey(TestSingleton.DERIVED_VALUE));
Map<String, Object> updatedAttributes = new HashMap<>();
final String newValue = "newValue";
updatedAttributes.put(TestSingleton.AUTOMATED_PERSISTED_VALUE, newValue);
updatedAttributes.put(TestSingleton.AUTOMATED_NONPERSISTED_VALUE, newValue);
updatedAttributes.put(TestSingleton.DERIVED_VALUE, System.currentTimeMillis()); // Will be ignored
object.setAttributes(updatedAttributes);
assertEquals(newValue, object.getAutomatedPersistedValue());
assertEquals(newValue, object.getAutomatedNonPersistedValue());
record = object.asObjectRecord();
assertEquals(objectName, record.getAttributes().get(ConfiguredObject.NAME));
assertEquals(newValue, record.getAttributes().get(TestSingleton.AUTOMATED_PERSISTED_VALUE));
assertFalse(record.getAttributes().containsKey(TestSingleton.AUTOMATED_NONPERSISTED_VALUE));
assertFalse(record.getAttributes().containsKey(TestSingleton.DERIVED_VALUE));
}
public void testDefaultedAttributeValue()
{
final String objectName = "myName";
Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestSingleton.NAME, objectName);
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals(TestSingleton.DEFAULTED_VALUE_DEFAULT, object1.getDefaultedValue());
}
public void testOverriddenDefaultedAttributeValue()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.DEFAULTED_VALUE, "override");
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object.getName());
assertEquals("override", object.getDefaultedValue());
}
public void testOverriddenDefaultedAttributeValueRevertedToDefault()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.DEFAULTED_VALUE, "override");
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object.getName());
assertEquals("override", object.getDefaultedValue());
object.setAttributes(Collections.singletonMap(TestSingleton.DEFAULTED_VALUE, null));
assertEquals(TestSingleton.DEFAULTED_VALUE_DEFAULT, object.getDefaultedValue());
}
public void testDefaultInitialization()
{
TestSingleton object =
_model.getObjectFactory().create(TestSingleton.class,
Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
"testDefaultInitialization")
);
assertEquals(object.getAttrWithDefaultFromContextNoInit(), TestSingleton.testGlobalDefault);
assertEquals(object.getAttrWithDefaultFromContextCopyInit(), TestSingleton.testGlobalDefault);
assertEquals(object.getAttrWithDefaultFromContextMaterializeInit(), TestSingleton.testGlobalDefault);
assertFalse(object.getActualAttributes().containsKey("attrWithDefaultFromContextNoInit"));
assertEquals("${"+TestSingleton.TEST_CONTEXT_DEFAULT+"}",object.getActualAttributes().get("attrWithDefaultFromContextCopyInit"));
assertEquals(TestSingleton.testGlobalDefault,object.getActualAttributes().get("attrWithDefaultFromContextMaterializeInit"));
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, "testDefaultInitialization2");
attributes.put(ConfiguredObject.CONTEXT, Collections.singletonMap(TestSingleton.TEST_CONTEXT_DEFAULT, "foo"));
object = _model.getObjectFactory().create(TestSingleton.class,
attributes
);
assertEquals("foo", object.getAttrWithDefaultFromContextNoInit());
assertEquals("foo", object.getAttrWithDefaultFromContextCopyInit());
assertEquals("foo", object.getAttrWithDefaultFromContextMaterializeInit());
assertFalse(object.getActualAttributes().containsKey("attrWithDefaultFromContextNoInit"));
assertEquals("${"+TestSingleton.TEST_CONTEXT_DEFAULT+"}",object.getActualAttributes().get("attrWithDefaultFromContextCopyInit"));
assertEquals("foo",object.getActualAttributes().get("attrWithDefaultFromContextMaterializeInit"));
setTestSystemProperty(TestSingleton.TEST_CONTEXT_DEFAULT, "bar");
object = _model.getObjectFactory().create(TestSingleton.class,
Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
"testDefaultInitialization3")
);
assertEquals("bar", object.getAttrWithDefaultFromContextNoInit());
assertEquals("bar", object.getAttrWithDefaultFromContextCopyInit());
assertEquals("bar", object.getAttrWithDefaultFromContextMaterializeInit());
assertFalse(object.getActualAttributes().containsKey("attrWithDefaultFromContextNoInit"));
assertEquals("${"+TestSingleton.TEST_CONTEXT_DEFAULT+"}",object.getActualAttributes().get("attrWithDefaultFromContextCopyInit"));
assertEquals("bar",object.getActualAttributes().get("attrWithDefaultFromContextMaterializeInit"));
}
public void testEnumAttributeValueFromString()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.ENUM_VALUE, TestEnum.TEST_ENUM1.name());
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
}
public void testEnumAttributeValueFromEnum()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.ENUM_VALUE, TestEnum.TEST_ENUM1);
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals(TestEnum.TEST_ENUM1, object1.getEnumValue());
}
public void testIntegerAttributeValueFromString()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.INT_VALUE, "-4");
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals(-4, object1.getIntValue());
}
public void testIntegerAttributeValueFromInteger()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.INT_VALUE, 5);
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals(5, object1.getIntValue());
}
public void testIntegerAttributeValueFromDouble()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.INT_VALUE, 6.1);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertEquals(objectName, object.getName());
assertEquals(6, object.getIntValue());
}
public void testDateAttributeFromMillis()
{
final String objectName = "myName";
long now = System.currentTimeMillis();
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.DATE_VALUE, now);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertEquals(objectName, object.getName());
assertEquals(new Date(now), object.getDateValue());
}
public void testDateAttributeFromIso8601()
{
final String objectName = "myName";
String date = "1970-01-01Z";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.DATE_VALUE, date);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertEquals(objectName, object.getName());
assertEquals(new Date(0), object.getDateValue());
}
public void testStringAttributeValueFromContextVariableProvidedBySystemProperty()
{
String sysPropertyName = "testStringAttributeValueFromContextVariableProvidedBySystemProperty";
String contextToken = "${" + sysPropertyName + "}";
System.setProperty(sysPropertyName, "myValue");
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.STRING_VALUE, contextToken);
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals("myValue", object1.getStringValue());
// System property set empty string
System.setProperty(sysPropertyName, "");
TestSingleton object2 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals("", object2.getStringValue());
// System property not set
System.clearProperty(sysPropertyName);
TestSingleton object3 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
// yields the unexpanded token - not sure if this is really useful behaviour?
assertEquals(contextToken, object3.getStringValue());
}
public void testMapAttributeValueFromContextVariableProvidedBySystemProperty()
{
String sysPropertyName = "testMapAttributeValueFromContextVariableProvidedBySystemProperty";
String contextToken = "${" + sysPropertyName + "}";
Map<String,String> expectedMap = new HashMap<>();
expectedMap.put("field1", "value1");
expectedMap.put("field2", "value2");
System.setProperty(sysPropertyName, "{ \"field1\" : \"value1\", \"field2\" : \"value2\"}");
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
attributes.put(TestSingleton.MAP_VALUE, contextToken);
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertEquals(objectName, object1.getName());
assertEquals(expectedMap, object1.getMapValue());
// System property not set
System.clearProperty(sysPropertyName);
}
public void testStringAttributeValueFromContextVariableProvidedObjectsContext()
{
String contextToken = "${myReplacement}";
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, objectName);
attributes.put(ConfiguredObject.CONTEXT, Collections.singletonMap("myReplacement", "myValue"));
attributes.put(TestSingleton.STRING_VALUE, contextToken);
TestSingleton object1 = _model.getObjectFactory().create(TestSingleton.class,
attributes);
// Check the object's context itself
assertTrue(object1.getContext().containsKey("myReplacement"));
assertEquals("myValue", object1.getContext().get("myReplacement"));
assertEquals(objectName, object1.getName());
assertEquals("myValue", object1.getStringValue());
}
public void testInvalidIntegerAttributeValueFromContextVariable()
{
final Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, "myName");
attributes.put(TestSingleton.TYPE, TestSingletonImpl.TEST_SINGLETON_TYPE);
attributes.put(TestSingleton.CONTEXT, Collections.singletonMap("contextVal", "notAnInteger"));
attributes.put(TestSingleton.INT_VALUE, "${contextVal}");
try
{
_model.getObjectFactory().create(TestSingleton.class, attributes);
fail("creation of child object should have failed due to invalid value");
}
catch (IllegalArgumentException e)
{
// PASS
String message = e.getMessage();
assertTrue("Message does not contain the attribute name", message.contains("intValue"));
assertTrue("Message does not contain the non-interpolated value", message.contains("contextVal"));
assertTrue("Message does not contain the interpolated value", message.contains("contextVal"));
}
}
public void testCreateEnforcesAttributeValidValues() throws Exception
{
final String objectName = getName();
Map<String, Object> illegalCreateAttributes = new HashMap<>();
illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
illegalCreateAttributes.put(TestSingleton.VALID_VALUE, "illegal");
try
{
_model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
fail("Exception not thrown");
}
catch (IllegalConfigurationException ice)
{
// PASS
}
Map<String, Object> legalCreateAttributes = new HashMap<>();
legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
legalCreateAttributes.put(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE1);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
assertEquals(TestSingleton.VALID_VALUE1, object.getValidValue());
}
public void testCreateEnforcesAttributeValidValuePattern() throws Exception
{
final String objectName = getName();
Map<String, Object> illegalCreateAttributes = new HashMap<>();
illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
illegalCreateAttributes.put(TestSingleton.VALUE_WITH_PATTERN, "illegal");
try
{
_model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
fail("Exception not thrown");
}
catch (IllegalConfigurationException ice)
{
// PASS
}
illegalCreateAttributes = new HashMap<>();
illegalCreateAttributes.put(ConfiguredObject.NAME, objectName);
illegalCreateAttributes.put(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "1"));
try
{
_model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
fail("Exception not thrown");
}
catch (IllegalConfigurationException ice)
{
// PASS
}
Map<String, Object> legalCreateAttributes = new HashMap<>();
legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
legalCreateAttributes.put(TestSingleton.VALUE_WITH_PATTERN, "foozzzzzbar");
legalCreateAttributes.put(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "255.255.255.255"));
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
assertEquals("foozzzzzbar", object.getValueWithPattern());
}
public void testChangeEnforcesAttributeValidValues() throws Exception
{
final String objectName = getName();
Map<String, Object> legalCreateAttributes = new HashMap<>();
legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
legalCreateAttributes.put(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE1);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
assertEquals(TestSingleton.VALID_VALUE1, object.getValidValue());
object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, TestSingleton.VALID_VALUE2));
assertEquals(TestSingleton.VALID_VALUE2, object.getValidValue());
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, "illegal"));
fail("Exception not thrown");
}
catch (IllegalConfigurationException iae)
{
// PASS
}
assertEquals(TestSingleton.VALID_VALUE2, object.getValidValue());
object.setAttributes(Collections.singletonMap(TestSingleton.VALID_VALUE, null));
assertNull(object.getValidValue());
}
public void testCreateEnforcesAttributeValidValuesWithSets() throws Exception
{
final String objectName = getName();
final Map<String, Object> name = Collections.singletonMap(ConfiguredObject.NAME, (Object)objectName);
Map<String, Object> illegalCreateAttributes = new HashMap<>(name);
illegalCreateAttributes.put(TestSingleton.ENUMSET_VALUES, Collections.singleton(TestEnum.TEST_ENUM3));
try
{
_model.getObjectFactory().create(TestSingleton.class, illegalCreateAttributes);
fail("Exception not thrown");
}
catch (IllegalConfigurationException ice)
{
// PASS
}
{
Map<String, Object> legalCreateAttributesEnums = new HashMap<>(name);
legalCreateAttributesEnums.put(TestSingleton.ENUMSET_VALUES,
Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3));
TestSingleton obj = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributesEnums);
assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
}
{
Map<String, Object> legalCreateAttributesStrings = new HashMap<>(name);
legalCreateAttributesStrings.put(TestSingleton.ENUMSET_VALUES,
Arrays.asList(TestEnum.TEST_ENUM2.name(), TestEnum.TEST_ENUM3.name()));
TestSingleton
obj = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributesStrings);
assertTrue(obj.getEnumSetValues().containsAll(Arrays.asList(TestEnum.TEST_ENUM2, TestEnum.TEST_ENUM3)));
}
}
public void testChangeEnforcesAttributeValidValuePatterns() throws Exception
{
final String objectName = getName();
Map<String, Object> legalCreateAttributes = new HashMap<>();
legalCreateAttributes.put(ConfiguredObject.NAME, objectName);
legalCreateAttributes.put(TestSingleton.VALUE_WITH_PATTERN, "foozzzzzbar");
legalCreateAttributes.put(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "255.255.255.255"));
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, legalCreateAttributes);
assertEquals("foozzzzzbar", object.getValueWithPattern());
assertEquals(Arrays.asList("1.1.1.1", "255.255.255.255"), object.getListValueWithPattern());
object.setAttributes(Collections.singletonMap(TestSingleton.VALUE_WITH_PATTERN, "foobar"));
assertEquals("foobar", object.getValueWithPattern());
object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, Collections.singletonList("1.2.3.4")));
assertEquals(Collections.singletonList("1.2.3.4"), object.getListValueWithPattern());
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.VALUE_WITH_PATTERN, "foobaz"));
fail("Exception not thrown");
}
catch (IllegalConfigurationException iae)
{
// PASS
}
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, Arrays.asList("1.1.1.1", "1")));
fail("Exception not thrown");
}
catch (IllegalConfigurationException iae)
{
// PASS
}
assertEquals("foobar", object.getValueWithPattern());
assertEquals(Collections.singletonList("1.2.3.4"), object.getListValueWithPattern());
object.setAttributes(Collections.singletonMap(TestSingleton.VALUE_WITH_PATTERN, null));
assertNull(object.getValueWithPattern());
object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, Collections.emptyList()));
assertEquals(Collections.emptyList(), object.getListValueWithPattern());
object.setAttributes(Collections.singletonMap(TestSingleton.LIST_VALUE_WITH_PATTERN, null));
assertNull(object.getListValueWithPattern());
}
public void testDefaultContextIsInContextKeys()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, objectName);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertTrue("context default not in contextKeys",
object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT));
assertEquals("default",
object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT));
setTestSystemProperty(TestSingleton.TEST_CONTEXT_DEFAULT, "notdefault");
assertTrue("context default not in contextKeys",
object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT));
assertEquals("notdefault", object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT));
}
public void testDefaultContextVariableWhichRefersToThis()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, objectName);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class,
attributes);
assertTrue("context default not in contextKeys",
object.getContextKeys(true).contains(TestSingleton.TEST_CONTEXT_DEFAULT_WITH_THISREF));
String expected = "a context var that refers to an attribute " + objectName;
assertEquals(expected, object.getContextValue(String.class, TestSingleton.TEST_CONTEXT_DEFAULT_WITH_THISREF));
}
public void testDerivedAttributeValue()
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, objectName);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
// Check that update is ignored
object.setAttributes(Collections.singletonMap(TestSingleton.DERIVED_VALUE, System.currentTimeMillis()));
assertEquals(TestSingletonImpl.DERIVED_VALUE, object.getDerivedValue());
}
public void testSecureValueRetrieval()
{
final String objectName = "myName";
final String secret = "secret";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, objectName);
attributes.put(TestSingleton.SECURE_VALUE, secret);
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertEquals(AbstractConfiguredObject.SECURED_STRING_VALUE, object.getAttribute(TestSingleton.SECURE_VALUE));
assertEquals(secret, object.getSecureValue());
//verify we can retrieve the actual secure value using system rights
object.doAsSystem(
new PrivilegedAction<Object>()
{
@Override
public Object run()
{
assertEquals(secret, object.getAttribute(TestSingleton.SECURE_VALUE));
assertEquals(secret, object.getSecureValue());
return null;
}
});
}
public void testImmutableAttribute()
{
final String originalValue = "myvalue";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, "myName");
attributes.put(TestSingleton.IMMUTABLE_VALUE, originalValue);
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertEquals("Immutable value unexpectedly changed", originalValue, object.getImmutableValue());
// Update to the same value is allowed
object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, originalValue));
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, "newvalue"));
fail("Exception not thrown");
}
catch(IllegalConfigurationException e)
{
// PASS
}
assertEquals(originalValue, object.getImmutableValue());
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, null));
fail("Exception not thrown");
}
catch(IllegalConfigurationException e)
{
// PASS
}
assertEquals("Immutable value unexpectedly changed", originalValue, object.getImmutableValue());
}
public void testImmutableAttributeNullValue()
{
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, "myName");
attributes.put(TestSingleton.IMMUTABLE_VALUE, null);
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
assertNull(object.getImmutableValue());
// Update to the same value is allowed
object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, null));
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.IMMUTABLE_VALUE, "newvalue"));
fail("Exception not thrown");
}
catch(IllegalConfigurationException e)
{
// PASS
}
assertNull("Immutable value unexpectedly changed", object.getImmutableValue());
}
/** Id and Type are key attributes in the model and are thus worthy of test of their own */
public void testIdAndTypeAreImmutableAttribute()
{
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, "myName");
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
UUID originalUuid = object.getId();
String originalType = object.getType();
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.ID, UUID.randomUUID()));
fail("Exception not thrown");
}
catch(IllegalConfigurationException e)
{
// PASS
}
assertEquals(originalUuid, object.getId());
try
{
object.setAttributes(Collections.singletonMap(TestSingleton.TYPE, "newtype"));
fail("Exception not thrown");
}
catch(IllegalConfigurationException e)
{
// PASS
}
assertEquals(originalType, object.getType());
}
public void testSetAttributesFiresListener()
{
final String objectName = "listenerFiring";
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, objectName);
attributes.put(TestSingleton.STRING_VALUE, "first");
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
final AtomicInteger listenerCount = new AtomicInteger();
final LinkedHashMap<String, String> updates = new LinkedHashMap<>();
object.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void attributeSet(final ConfiguredObject<?> object,
final String attributeName,
final Object oldAttributeValue,
final Object newAttributeValue)
{
listenerCount.incrementAndGet();
String delta = String.valueOf(oldAttributeValue) + "=>" + String.valueOf(newAttributeValue);
updates.put(attributeName, delta);
}
});
// Set updated value (should cause listener to fire)
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "second"));
assertEquals(1, listenerCount.get());
String delta = updates.remove(TestSingleton.STRING_VALUE);
assertEquals("first=>second", delta);
// Set unchanged value (should not cause listener to fire)
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "second"));
assertEquals(1, listenerCount.get());
// Set value to null (should cause listener to fire)
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, null));
assertEquals(2, listenerCount.get());
delta = updates.remove(TestSingleton.STRING_VALUE);
assertEquals("second=>null", delta);
// Set to null again (should not cause listener to fire)
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, null));
assertEquals(2, listenerCount.get());
// Set updated value (should cause listener to fire)
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "third"));
assertEquals(3, listenerCount.get());
delta = updates.remove(TestSingleton.STRING_VALUE);
assertEquals("null=>third", delta);
}
public void testSetAttributesInterpolateValues()
{
setTestSystemProperty("foo1", "myValue1");
setTestSystemProperty("foo2", "myValue2");
setTestSystemProperty("foo3", null);
Map<String, Object> attributes = new HashMap<>();
attributes.put(ConfiguredObject.NAME, getTestName());
attributes.put(TestSingleton.STRING_VALUE, "${foo1}");
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
final AtomicInteger listenerCount = new AtomicInteger();
object.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void attributeSet(final ConfiguredObject<?> object,
final String attributeName,
final Object oldAttributeValue,
final Object newAttributeValue)
{
listenerCount.incrementAndGet();
}
});
assertEquals("myValue1", object.getStringValue());
assertEquals("${foo1}", object.getActualAttributes().get(TestSingleton.STRING_VALUE));
// Update the actual value ${foo1} => ${foo2}
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "${foo2}"));
assertEquals(1, listenerCount.get());
assertEquals("myValue2", object.getStringValue());
assertEquals("${foo2}", object.getActualAttributes().get(TestSingleton.STRING_VALUE));
// No change
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "${foo2}"));
assertEquals(1, listenerCount.get());
// Update the actual value ${foo2} => ${foo3} (which doesn't have a value)
object.setAttributes(Collections.singletonMap(TestSingleton.STRING_VALUE, "${foo3}"));
assertEquals(2, listenerCount.get());
assertEquals("${foo3}", object.getStringValue());
assertEquals("${foo3}", object.getActualAttributes().get(TestSingleton.STRING_VALUE));
}
public void testCreateAndLastUpdateDate() throws Exception
{
final String objectName = "myName";
final Date now = new Date();
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
Date createdTime = object.getCreatedTime();
assertTrue("Create date not populated", createdTime.compareTo(now) >= 0);
assertEquals("Last updated not populated", createdTime, object.getLastUpdatedTime());
Thread.sleep(10);
object.setAttributes(Collections.singletonMap(TestSingleton.DESCRIPTION, "desc"));
assertEquals("Created time should not be updated by update", createdTime, object.getCreatedTime());
assertTrue("Last update time should be updated by update", object.getLastUpdatedTime().compareTo(createdTime) > 0);
}
public void testStatistics() throws Exception
{
final String objectName = "myName";
Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
final Map<String, Object> stats = object.getStatistics();
assertEquals("Unexpected number of statistics", 1, stats.size());
assertTrue("Expected statistic not found", stats.containsKey("longStatistic"));
}
public void testAuditInformation() throws Exception
{
final String creatingUser = "creatingUser";
final String updatingUser = "updatingUser";
final Subject creatorSubject = createTestAuthenticatedSubject(creatingUser);
final Subject updaterSubject = createTestAuthenticatedSubject(updatingUser);
final Date now = new Date();
Thread.sleep(5); // Let a small amount of time pass
final Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, "myName");
final TestSingleton object = Subject.doAs(creatorSubject,
new PrivilegedAction<TestSingleton>()
{
@Override
public TestSingleton run()
{
return _model.getObjectFactory().create(TestSingleton.class, attributes);
}
});
assertEquals("Unexpected creating user after object creation", creatingUser, object.getCreatedBy());
assertEquals("Unexpected last updating user after object creation", creatingUser, object.getLastUpdatedBy());
final Date originalCreatedTime = object.getCreatedTime();
final Date originalLastUpdatedTime = object.getLastUpdatedTime();
assertTrue("Unexpected created time", originalCreatedTime.after(now));
assertEquals("Unexpected created and updated time", originalCreatedTime, originalLastUpdatedTime);
Thread.sleep(5); // Let a small amount of time pass
Subject.doAs(updaterSubject,
new PrivilegedAction<Void>()
{
@Override
public Void run()
{
object.setAttributes(Collections.singletonMap(TestSingleton.INT_VALUE, 5));
return null;
}
});
assertEquals("Creating user should not be changed by update", creatingUser, object.getCreatedBy());
assertEquals("Created time should not be changed by update", originalCreatedTime, object.getCreatedTime());
assertEquals("Last updated by should be changed by update", updatingUser, object.getLastUpdatedBy());
assertTrue("Last updated time by should be changed by update", originalLastUpdatedTime.before(object.getLastUpdatedTime()));
}
public void testAuditInformationIgnoresUserSuppliedAttributes() throws Exception
{
final String user = "user";
final Subject userSubject = createTestAuthenticatedSubject(user);
final Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, "myName");
attributes.put(TestSingleton.CREATED_BY, "bogusCreator");
attributes.put(TestSingleton.CREATED_TIME, new Date(0));
attributes.put(TestSingleton.LAST_UPDATED_BY, "bogusUpdater");
attributes.put(TestSingleton.LAST_UPDATED_TIME, new Date(0));
final Date now = new Date();
Thread.sleep(5); // Let a small amount of time pass
final TestSingleton object = Subject.doAs(userSubject,
new PrivilegedAction<TestSingleton>()
{
@Override
public TestSingleton run()
{
return _model.getObjectFactory().create(TestSingleton.class, attributes);
}
});
assertEquals("Unexpected creating user after object creation", user, object.getCreatedBy());
assertEquals("Unexpected last updating user after object creation", user, object.getLastUpdatedBy());
final Date originalCreatedTime = object.getCreatedTime();
assertTrue("Unexpected created time", originalCreatedTime.after(now));
final Date originalLastUpdatedTime = object.getLastUpdatedTime();
assertEquals("Unexpected created and updated time", originalCreatedTime, originalLastUpdatedTime);
Subject.doAs(userSubject,
new PrivilegedAction<Void>()
{
@Override
public Void run()
{
final Map<String, Object> updateMap = new HashMap<>();
updateMap.put(TestSingleton.INT_VALUE, 5);
updateMap.put(TestSingleton.CREATED_BY, "bogusCreator");
updateMap.put(TestSingleton.CREATED_TIME, new Date(0));
updateMap.put(TestSingleton.LAST_UPDATED_BY, "bogusUpdater");
updateMap.put(TestSingleton.LAST_UPDATED_TIME, new Date(0));
object.setAttributes(updateMap);
return null;
}
});
Thread.sleep(50); // Let a small amount of time pass
assertEquals("Creating user should not be changed by update", user, object.getCreatedBy());
assertEquals("Created time should not be changed by update", originalCreatedTime, object.getCreatedTime());
assertEquals("Last updated by should be changed by update", user, object.getLastUpdatedBy());
assertTrue("Last updated time by should be changed by update", originalLastUpdatedTime.before(object.getLastUpdatedTime()));
}
public void testAuditInformationPersistenceAndRecovery() throws Exception
{
final String creatingUser = "creatingUser";
final Subject creatorSubject = createTestAuthenticatedSubject(creatingUser);
final String objectName = "myName";
final Map<String, Object> attributes = new HashMap<>();
attributes.put(TestSingleton.NAME, objectName);
final TestSingleton object = Subject.doAs(creatorSubject,
new PrivilegedAction<TestSingleton>()
{
@Override
public TestSingleton run()
{
return _model.getObjectFactory()
.create(TestSingleton.class, attributes);
}
});
final ConfiguredObjectRecord cor = object.asObjectRecord();
final Map<String, Object> recordedAttributes = cor.getAttributes();
assertTrue(recordedAttributes.containsKey(ConfiguredObject.LAST_UPDATED_BY));
assertTrue(recordedAttributes.containsKey(ConfiguredObject.LAST_UPDATED_TIME));
assertTrue(recordedAttributes.containsKey(ConfiguredObject.CREATED_BY));
assertTrue(recordedAttributes.containsKey(ConfiguredObject.CREATED_TIME));
assertEquals(creatingUser, recordedAttributes.get(ConfiguredObject.CREATED_BY));
assertEquals(creatingUser, recordedAttributes.get(ConfiguredObject.LAST_UPDATED_BY));
// Now recover the object
final SystemConfig mockSystemConfig = mock(SystemConfig.class);
when(mockSystemConfig.getId()).thenReturn(UUID.randomUUID());
when(mockSystemConfig.getModel()).thenReturn(TestModel.getInstance());
final TestSingleton recovered = (TestSingleton) _model.getObjectFactory().recover(cor, mockSystemConfig).resolve();
recovered.open();
assertEquals("Unexpected recovered object created by", object.getCreatedBy(), recovered.getCreatedBy());
assertEquals("Unexpected recovered object created time", object.getCreatedTime(), recovered.getCreatedTime());
assertEquals("Unexpected recovered object updated by", object.getLastUpdatedBy(), recovered.getLastUpdatedBy());
assertEquals("Unexpected recovered object updated time", object.getLastUpdatedTime(), recovered.getLastUpdatedTime());
}
private Subject createTestAuthenticatedSubject(final String username)
{
return new Subject(true,
Collections.singleton(new AuthenticatedPrincipal(new UsernamePrincipal(username, null))),
Collections.emptySet(),
Collections.emptySet());
}
}