blob: be086c104fb0a5a0e3958a721b54feee15670098 [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
*
* https://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.commons.configuration2.builder;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.configuration2.ConfigurationDecoder;
import org.apache.commons.configuration2.beanutils.BeanHelper;
import org.apache.commons.configuration2.convert.ConversionHandler;
import org.apache.commons.configuration2.convert.DefaultConversionHandler;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.convert.ListDelimiterHandler;
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
import org.apache.commons.configuration2.interpol.InterpolatorSpecification;
import org.apache.commons.configuration2.interpol.Lookup;
import org.apache.commons.configuration2.io.ConfigurationLogger;
import org.apache.commons.configuration2.sync.ReadWriteSynchronizer;
import org.apache.commons.configuration2.sync.Synchronizer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* Test class for {@code BasicBuilderParameters}.
*/
public class TestBasicBuilderParameters {
/** The instance to be tested. */
private BasicBuilderParameters params;
@BeforeEach
public void setUp() throws Exception {
params = new BasicBuilderParameters();
}
/**
* Tests whether the collection with default lookups can be cloned, too.
*/
@Test
void testCloneDefaultLookups() {
final Lookup look = mock(Lookup.class);
final Collection<Lookup> looks = Collections.singleton(look);
params.setDefaultLookups(looks);
final BasicBuilderParameters clone = params.clone();
Collection<?> defLooks = (Collection<?>) params.getParameters().get("defaultLookups");
defLooks.clear();
defLooks = (Collection<?>) clone.getParameters().get("defaultLookups");
assertEquals(1, defLooks.size());
assertTrue(defLooks.contains(look));
}
/**
* Tests whether the map with prefix lookups is cloned, too.
*/
@Test
void testClonePrefixLookups() {
final Lookup look = mock(Lookup.class);
final Map<String, Lookup> lookups = Collections.singletonMap("test", look);
params.setPrefixLookups(lookups);
final BasicBuilderParameters clone = params.clone();
Map<?, ?> map = (Map<?, ?>) params.getParameters().get("prefixLookups");
map.clear();
map = (Map<?, ?>) clone.getParameters().get("prefixLookups");
assertEquals(1, map.size());
assertSame(look, map.get("test"));
}
/**
* Tests whether a cloned instance contains the same data as the original object.
*/
@Test
void testCloneValues() {
final ConfigurationLogger log = mock(ConfigurationLogger.class);
final ConfigurationInterpolator ci = mock(ConfigurationInterpolator.class);
final ListDelimiterHandler handler1 = mock(ListDelimiterHandler.class);
final ListDelimiterHandler handler2 = mock(ListDelimiterHandler.class);
params.setListDelimiterHandler(handler1);
params.setLogger(log);
params.setInterpolator(ci);
params.setThrowExceptionOnMissing(true);
final BasicBuilderParameters clone = params.clone();
params.setListDelimiterHandler(handler2);
params.setThrowExceptionOnMissing(false);
final Map<String, Object> map = clone.getParameters();
assertSame(log, map.get("logger"));
assertSame(ci, map.get("interpolator"));
assertEquals(handler1, map.get("listDelimiterHandler"));
assertEquals(Boolean.TRUE, map.get("throwExceptionOnMissing"));
}
/**
* Tests the default parameter values.
*/
@Test
void testDefaults() {
final Map<String, Object> paramMap = params.getParameters();
assertTrue(paramMap.isEmpty());
}
/**
* Tests fetchBeanHelper() if no helper was set.
*/
@Test
void testFetchBeanHelperNoSet() {
assertNull(BasicBuilderParameters.fetchBeanHelper(params.getParameters()));
}
/**
* Tries to invoke fetchBeanHelper() on a null map.
*/
@Test
void testFetchBeanHelperNullMap() {
assertThrows(IllegalArgumentException.class, () -> BasicBuilderParameters.fetchBeanHelper(null));
}
/**
* Tests whether a specification object for interpolation can be obtained.
*/
@Test
void testFetchInterpolatorSpecification() {
final ConfigurationInterpolator parent = mock(ConfigurationInterpolator.class);
final Lookup l1 = mock(Lookup.class);
final Lookup l2 = mock(Lookup.class);
final Lookup l3 = mock(Lookup.class);
final Map<String, Lookup> prefixLookups = new HashMap<>();
prefixLookups.put("p1", l1);
prefixLookups.put("p2", l2);
final Collection<Lookup> defLookups = Collections.singleton(l3);
params.setParentInterpolator(parent);
params.setPrefixLookups(prefixLookups);
params.setDefaultLookups(defLookups);
final Map<String, Object> map = params.getParameters();
final InterpolatorSpecification spec = BasicBuilderParameters.fetchInterpolatorSpecification(map);
assertSame(parent, spec.getParentInterpolator());
assertEquals(prefixLookups, spec.getPrefixLookups());
assertEquals(1, spec.getDefaultLookups().size());
assertTrue(spec.getDefaultLookups().contains(l3));
}
/**
* Tests that an empty map does not cause any problems.
*/
@Test
void testFetchInterpolatorSpecificationEmpty() {
final InterpolatorSpecification spec = BasicBuilderParameters.fetchInterpolatorSpecification(params.getParameters());
assertNull(spec.getInterpolator());
assertTrue(spec.getDefaultLookups().isEmpty());
}
/**
* Tests fetchInterpolatorSpecification() if the collection with default lookups contains an invalid value.
*/
@Test
void testFetchInterpolatorSpecificationInvalidCollectionValue() {
final Map<String, Object> map = new HashMap<>();
map.put("defaultLookups", Collections.singleton("not a lookup"));
assertThrows(IllegalArgumentException.class, () -> BasicBuilderParameters.fetchInterpolatorSpecification(map));
}
/**
* Tests fetchInterpolatorSpecification() if the map contains a property of an invalid data type.
*/
@Test
void testFetchInterpolatorSpecificationInvalidDataType() {
final Map<String, Object> map = new HashMap<>();
map.put("interpolator", this);
assertThrows(IllegalArgumentException.class, () -> BasicBuilderParameters.fetchInterpolatorSpecification(map));
}
/**
* Tests fetchInterpolatorSpecification() if the map with prefix lookups contains an invalid key.
*/
@Test
void testFetchInterpolatorSpecificationInvalidMapKey() {
final Map<String, Object> map = new HashMap<>();
final Map<Object, Object> prefix = new HashMap<>();
prefix.put(42, mock(Lookup.class));
map.put("prefixLookups", prefix);
assertThrows(IllegalArgumentException.class, () -> BasicBuilderParameters.fetchInterpolatorSpecification(map));
}
/**
* Tests fetchInterpolatorSpecification() if the map with prefix lookups contains an invalid value.
*/
@Test
void testFetchInterpolatorSpecificationInvalidMapValue() {
final Map<String, Object> map = new HashMap<>();
final Map<Object, Object> prefix = new HashMap<>();
prefix.put("test", this);
map.put("prefixLookups", prefix);
assertThrows(IllegalArgumentException.class, () -> BasicBuilderParameters.fetchInterpolatorSpecification(map));
}
/**
* Tries to obtain an {@code InterpolatorSpecification} from a null map.
*/
@Test
void testFetchInterpolatorSpecificationNull() {
assertThrows(IllegalArgumentException.class, () -> BasicBuilderParameters.fetchInterpolatorSpecification(null));
}
/**
* Tests whether an InterpolatorSpecification can be fetched if a ConfigurationInterpolator is present.
*/
@Test
void testFetchInterpolatorSpecificationWithInterpolator() {
final ConfigurationInterpolator ci = mock(ConfigurationInterpolator.class);
params.setInterpolator(ci);
final InterpolatorSpecification spec = BasicBuilderParameters.fetchInterpolatorSpecification(params.getParameters());
assertSame(ci, spec.getInterpolator());
assertNull(spec.getParentInterpolator());
}
/**
* Tests whether a defensive copy is created when the parameter map is returned.
*/
@Test
void testGetParametersDefensiveCopy() {
final Map<String, Object> map1 = params.getParameters();
final Map<String, Object> mapCopy = new HashMap<>(map1);
map1.put("otherProperty", "value");
final Map<String, Object> map2 = params.getParameters();
assertNotSame(map1, map2);
assertEquals(mapCopy, map2);
}
/**
* Tests whether properties can be inherited from another parameters map.
*/
@Test
void testInheritFrom() {
final BeanHelper beanHelper = new BeanHelper();
final ConfigurationDecoder decoder = mock(ConfigurationDecoder.class);
final ConversionHandler conversionHandler = new DefaultConversionHandler();
final ListDelimiterHandler listDelimiterHandler = new DefaultListDelimiterHandler('#');
final ConfigurationLogger logger = new ConfigurationLogger("test");
final Synchronizer synchronizer = new ReadWriteSynchronizer();
params.setBeanHelper(beanHelper).setConfigurationDecoder(decoder).setConversionHandler(conversionHandler).setListDelimiterHandler(listDelimiterHandler)
.setLogger(logger).setSynchronizer(synchronizer).setThrowExceptionOnMissing(true);
final BasicBuilderParameters p2 = new BasicBuilderParameters();
p2.inheritFrom(params.getParameters());
final Map<String, Object> parameters = p2.getParameters();
assertEquals(beanHelper, parameters.get("config-BeanHelper"));
assertEquals(decoder, parameters.get("configurationDecoder"));
assertEquals(conversionHandler, parameters.get("conversionHandler"));
assertEquals(listDelimiterHandler, parameters.get("listDelimiterHandler"));
assertEquals(logger, parameters.get("logger"));
assertEquals(synchronizer, parameters.get("synchronizer"));
assertEquals(Boolean.TRUE, parameters.get("throwExceptionOnMissing"));
}
/**
* Tests whether null input is handled by inheritFrom().
*/
@Test
void testInheritFromNull() {
assertThrows(IllegalArgumentException.class, () -> params.inheritFrom(null));
}
/**
* Tests that undefined properties are not copied over by inheritFrom().
*/
@Test
void testInheritFromUndefinedProperties() {
final BasicBuilderParameters p2 = new BasicBuilderParameters().setThrowExceptionOnMissing(true);
p2.inheritFrom(Collections.<String, Object>emptyMap());
final Map<String, Object> parameters = p2.getParameters();
assertEquals(Collections.singletonMap("throwExceptionOnMissing", Boolean.TRUE), parameters);
}
/**
* Tests whether properties of other parameter objects can be merged.
*/
@Test
void testMerge() {
final ListDelimiterHandler handler1 = mock(ListDelimiterHandler.class);
final ListDelimiterHandler handler2 = mock(ListDelimiterHandler.class);
final Map<String, Object> props = new HashMap<>();
props.put("throwExceptionOnMissing", Boolean.TRUE);
props.put("listDelimiterHandler", handler1);
props.put("other", "test");
props.put(BuilderParameters.RESERVED_PARAMETER_PREFIX + "test", "reserved");
final BuilderParameters p = mock(BuilderParameters.class);
when(p.getParameters()).thenReturn(props);
params.setListDelimiterHandler(handler2);
params.merge(p);
final Map<String, Object> map = params.getParameters();
assertEquals(handler2, map.get("listDelimiterHandler"));
assertEquals(Boolean.TRUE, map.get("throwExceptionOnMissing"));
assertEquals("test", map.get("other"));
assertFalse(map.containsKey(BuilderParameters.RESERVED_PARAMETER_PREFIX + "test"));
verify(p).getParameters();
verifyNoMoreInteractions(p);
}
/**
* Tries a merge with a null object.
*/
@Test
void testMergeNull() {
assertThrows(IllegalArgumentException.class, () -> params.merge(null));
}
/**
* Tests whether a BeanHelper can be set.
*/
@Test
void testSetBeanHelper() {
final BeanHelper helper = new BeanHelper();
assertSame(params, params.setBeanHelper(helper));
assertSame(helper, BasicBuilderParameters.fetchBeanHelper(params.getParameters()));
}
/**
* Tests whether a decoder can be set.
*/
@Test
void testSetConfigurationDecoder() {
final ConfigurationDecoder decoder = mock(ConfigurationDecoder.class);
assertSame(params, params.setConfigurationDecoder(decoder));
assertSame(decoder, params.getParameters().get("configurationDecoder"));
}
/**
* Tests whether a ConversionHandler can be set.
*/
@Test
void testSetConversionHandler() {
final ConversionHandler handler = mock(ConversionHandler.class);
assertSame(params, params.setConversionHandler(handler));
assertSame(handler, params.getParameters().get("conversionHandler"));
}
/**
* Tests whether default lookups can be set.
*/
@Test
void testSetDefaultLookups() {
final Lookup look = mock(Lookup.class);
final Collection<Lookup> looks = Collections.singleton(look);
assertSame(params, params.setDefaultLookups(looks));
final Collection<?> col = (Collection<?>) params.getParameters().get("defaultLookups");
assertNotSame(col, looks);
assertEquals(1, col.size());
assertSame(look, col.iterator().next());
final Collection<?> col2 = (Collection<?>) params.getParameters().get("defaultLookups");
assertNotSame(col, col2);
}
/**
* Tests whether null values are handled by setDefaultLookups().
*/
@Test
void testSetDefaultLookupsNull() {
params.setDefaultLookups(new ArrayList<>());
params.setDefaultLookups(null);
assertFalse(params.getParameters().containsKey("defaultLookups"));
}
/**
* Tests whether a {@code ConfigurationInterpolator} can be set.
*/
@Test
void testSetInterpolator() {
final ConfigurationInterpolator ci = mock(ConfigurationInterpolator.class);
assertSame(params, params.setInterpolator(ci));
assertSame(ci, params.getParameters().get("interpolator"));
}
/**
* Tests whether the list delimiter handler property can be set.
*/
@Test
void testSetListDelimiter() {
final ListDelimiterHandler handler = mock(ListDelimiterHandler.class);
assertSame(params, params.setListDelimiterHandler(handler));
assertSame(handler, params.getParameters().get("listDelimiterHandler"));
}
/**
* Tests whether the logger parameter can be set.
*/
@Test
void testSetLogger() {
final ConfigurationLogger log = mock(ConfigurationLogger.class);
assertSame(params, params.setLogger(log));
assertSame(log, params.getParameters().get("logger"));
}
/**
* Tests whether a custom {@code ConfigurationInterpolator} overrides settings for custom lookups.
*/
@Test
void testSetLookupsAndInterpolator() {
final Lookup look1 = mock(Lookup.class);
final Lookup look2 = mock(Lookup.class);
final ConfigurationInterpolator parent = mock(ConfigurationInterpolator.class);
final ConfigurationInterpolator ci = mock(ConfigurationInterpolator.class);
params.setDefaultLookups(Collections.singleton(look1));
params.setPrefixLookups(Collections.singletonMap("test", look2));
params.setInterpolator(ci);
params.setParentInterpolator(parent);
final Map<String, Object> map = params.getParameters();
assertFalse(map.containsKey("prefixLookups"));
assertFalse(map.containsKey("defaultLookups"));
assertFalse(map.containsKey("parentInterpolator"));
}
/**
* Tests whether a parent {@code ConfigurationInterpolator} can be set.
*/
@Test
void testSetParentInterpolator() {
final ConfigurationInterpolator parent = mock(ConfigurationInterpolator.class);
assertSame(params, params.setParentInterpolator(parent));
assertSame(parent, params.getParameters().get("parentInterpolator"));
}
/**
* Tests whether prefix lookups can be set.
*/
@Test
void testSetPrefixLookups() {
final Lookup look = mock(Lookup.class);
final Map<String, Lookup> lookups = Collections.singletonMap("test", look);
assertSame(params, params.setPrefixLookups(lookups));
final Map<?, ?> map = (Map<?, ?>) params.getParameters().get("prefixLookups");
assertNotSame(lookups, map);
assertEquals(Collections.singletonMap("test", look), map);
final Map<?, ?> map2 = (Map<?, ?>) params.getParameters().get("prefixLookups");
assertNotSame(map, map2);
}
/**
* Tests whether null values are handled by setPrefixLookups().
*/
@Test
void testSetPrefixLookupsNull() {
params.setPrefixLookups(new HashMap<>());
params.setPrefixLookups(null);
assertFalse(params.getParameters().containsKey("prefixLookups"));
}
/**
* Tests whether a Synchronizer can be set.
*/
@Test
void testSetSynchronizer() {
final Synchronizer sync = mock(Synchronizer.class);
assertSame(params, params.setSynchronizer(sync));
assertSame(sync, params.getParameters().get("synchronizer"));
}
/**
* Tests whether the throw exception on missing property can be set.
*/
@Test
void testSetThrowExceptionOnMissing() {
assertSame(params, params.setThrowExceptionOnMissing(true));
assertEquals(Boolean.TRUE, params.getParameters().get("throwExceptionOnMissing"));
}
}