////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.powermock.api.mockito.PowerMockito.when;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;

import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;

/**
 * Unit test for ConfigurationLoader.
 * @author Rick Giles
 * @author lkuehne
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({DefaultConfiguration.class, ConfigurationLoader.class})
public class ConfigurationLoaderTest extends AbstractPathTestSupport {

    @Override
    protected String getPackageLocation() {
        return "com/puppycrawl/tools/checkstyle/configurationloader";
    }

    private Configuration loadConfiguration(String name) throws Exception {
        return loadConfiguration(name, new Properties());
    }

    private Configuration loadConfiguration(
        String name, Properties props) throws Exception {
        final String fName = getPath(name);

        return ConfigurationLoader.loadConfiguration(fName, new PropertiesExpander(props));
    }

    private static Method getReplacePropertiesMethod() throws Exception {
        final Class<?>[] params = new Class<?>[3];
        params[0] = String.class;
        params[1] = PropertyResolver.class;
        params[2] = String.class;
        final Class<ConfigurationLoader> configurationLoaderClass = ConfigurationLoader.class;
        final Method replacePropertiesMethod =
            configurationLoaderClass.getDeclaredMethod("replaceProperties", params);
        replacePropertiesMethod.setAccessible(true);
        return replacePropertiesMethod;
    }

    @Test
    public void testResourceLoadConfiguration() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        // load config that's only found in the classpath
        final DefaultConfiguration config =
            (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                getPath("InputConfigurationLoaderChecks.xml"), new PropertiesExpander(props));

        //verify the root, and property substitution
        final Properties attributes = new Properties();
        attributes.setProperty("tabWidth", "4");
        attributes.setProperty("basedir", "basedir");
        verifyConfigNode(config, "Checker", 3, attributes);
    }

    @Test
    public void testResourceLoadConfigurationWithMultiThreadConfiguration() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final PropertiesExpander propertiesExpander = new PropertiesExpander(props);
        final String configPath = getPath("InputConfigurationLoaderChecks.xml");
        final ThreadModeSettings multiThreadModeSettings =
            new ThreadModeSettings(4, 2);

        try {
            ConfigurationLoader.loadConfiguration(
                configPath, propertiesExpander, multiThreadModeSettings);
            fail("An exception is expected");
        }
        catch (IllegalArgumentException ex) {
            assertEquals("Invalid exception message",
                "Multi thread mode for Checker module is not implemented",
                ex.getMessage());
        }
    }

    @Test
    public void testResourceLoadConfigurationWithSingleThreadConfiguration() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final PropertiesExpander propertiesExpander = new PropertiesExpander(props);
        final String configPath = getPath("InputConfigurationLoaderChecks.xml");
        final ThreadModeSettings singleThreadModeSettings =
            ThreadModeSettings.SINGLE_THREAD_MODE_INSTANCE;

        final DefaultConfiguration config =
            (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                configPath, propertiesExpander, singleThreadModeSettings);

        final Properties attributes = new Properties();
        attributes.setProperty("tabWidth", "4");
        attributes.setProperty("basedir", "basedir");
        verifyConfigNode(config, "Checker", 3, attributes);
    }

    @Test
    public void testEmptyConfiguration() throws Exception {
        final DefaultConfiguration config =
            (DefaultConfiguration) loadConfiguration("InputConfigurationLoaderEmpty.xml");
        verifyConfigNode(config, "Checker", 0, new Properties());
    }

    @Test
    public void testEmptyModuleResolver() throws Exception {
        final DefaultConfiguration config =
            (DefaultConfiguration) loadConfiguration(
                "InputConfigurationLoaderEmpty.xml", new Properties());
        verifyConfigNode(config, "Checker", 0, new Properties());
    }

    @Test
    public void testMissingPropertyName() throws Exception {
        try {
            loadConfiguration("InputConfigurationLoaderMissingPropertyName.xml");
            fail("missing property name");
        }
        catch (CheckstyleException ex) {
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"name\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"property\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().endsWith(":8:41"));
        }
    }

    @Test
    public void testMissingPropertyNameInMethodWithBooleanParameter() throws Exception {
        try {
            final String fName = getPath("InputConfigurationLoaderMissingPropertyName.xml");
            ConfigurationLoader.loadConfiguration(fName, new PropertiesExpander(new Properties()),
                    false);

            fail("missing property name");
        }
        catch (CheckstyleException ex) {
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"name\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"property\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().endsWith(":8:41"));
        }
    }

    @Test
    public void testMissingPropertyValue() throws Exception {
        try {
            loadConfiguration("InputConfigurationLoaderMissingPropertyValue.xml");
            fail("missing property value");
        }
        catch (CheckstyleException ex) {
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"value\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"property\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().endsWith(":8:41"));
        }
    }

    @Test
    public void testMissingConfigName() throws Exception {
        try {
            loadConfiguration("InputConfigurationLoaderMissingConfigName.xml");
            fail("missing module name");
        }
        catch (CheckstyleException ex) {
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"name\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"module\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().endsWith(":7:23"));
        }
    }

    @Test
    public void testMissingConfigParent() throws Exception {
        try {
            loadConfiguration("InputConfigurationLoaderMissingConfigParent.xml");
            fail("missing module parent");
        }
        catch (CheckstyleException ex) {
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"property\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().contains("\"module\""));
            assertTrue("Invalid exception message: " + ex.getMessage(),
                    ex.getMessage().endsWith(":8:38"));
        }
    }

    @Test
    public void testCheckstyleChecks() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final DefaultConfiguration config =
            (DefaultConfiguration) loadConfiguration(
                "InputConfigurationLoaderChecks.xml", props);

        //verify the root, and property substitution
        final Properties atts = new Properties();
        atts.setProperty("tabWidth", "4");
        atts.setProperty("basedir", "basedir");
        verifyConfigNode(config, "Checker", 3, atts);

        //verify children
        final Configuration[] children = config.getChildren();
        atts.clear();
        verifyConfigNode(
            (DefaultConfiguration) children[1], "JavadocPackage", 0, atts);
        verifyConfigNode(
            (DefaultConfiguration) children[2], "Translation", 0, atts);
        atts.setProperty("testName", "testValue");
        verifyConfigNode(
            (DefaultConfiguration) children[0],
            "TreeWalker",
            8,
            atts);

        //verify TreeWalker's first, last, NoWhitespaceAfterCheck
        final Configuration[] grandchildren = children[0].getChildren();
        atts.clear();
        verifyConfigNode(
            (DefaultConfiguration) grandchildren[0],
            "AvoidStarImport",
            0,
            atts);
        atts.setProperty("format", "System.out.println");
        verifyConfigNode(
            (DefaultConfiguration) grandchildren[grandchildren.length - 1],
            "GenericIllegalRegexp",
            0,
            atts);
        atts.clear();
        atts.setProperty("tokens", "DOT");
        atts.setProperty("allowLineBreaks", "true");
        verifyConfigNode(
            (DefaultConfiguration) grandchildren[6],
            "NoWhitespaceAfter",
            0,
            atts);
    }

    @Test
    public void testCustomMessages() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final DefaultConfiguration config =
            (DefaultConfiguration) loadConfiguration(
                "InputConfigurationLoaderCustomMessages.xml", props);

        final Configuration[] children = config.getChildren();
        final Configuration[] grandchildren = children[0].getChildren();

        final String expectedKey = "name.invalidPattern";
        assertTrue("Messages should contain key: " + expectedKey,
            grandchildren[0].getMessages()
            .containsKey(expectedKey));
    }

    private static void verifyConfigNode(
        DefaultConfiguration config, String name, int childrenLength,
        Properties atts) throws Exception {
        assertEquals("name.", name, config.getName());
        assertEquals(
            "children.length.",
            childrenLength,
            config.getChildren().length);

        final String[] attNames = config.getAttributeNames();
        assertEquals("attributes.length", atts.size(), attNames.length);

        for (String attName : attNames) {
            assertEquals(
                "attribute[" + attName + "]",
                atts.getProperty(attName),
                config.getAttribute(attName));
        }
    }

    @Test
    public void testReplacePropertiesNoReplace() throws Exception {
        final String[] testValues = {null, "", "a", "$a", "{a",
                                     "{a}", "a}", "$a}", "$", "a$b", };
        final Properties props = initProperties();
        for (String testValue : testValues) {
            final String value = (String) getReplacePropertiesMethod().invoke(
                null, testValue, new PropertiesExpander(props), null);
            assertEquals("\"" + testValue + "\"", value, testValue);
        }
    }

    @Test
    public void testReplacePropertiesSyntaxError() throws Exception {
        final Properties props = initProperties();
        try {
            final String value = (String) getReplacePropertiesMethod().invoke(
                null, "${a", new PropertiesExpander(props), null);
            fail("expected to fail, instead got: " + value);
        }
        catch (InvocationTargetException ex) {
            assertEquals("Invalid exception cause message",
                "Syntax error in property: ${a", ex.getCause().getMessage());
        }
    }

    @Test
    public void testReplacePropertiesMissingProperty() throws Exception {
        final Properties props = initProperties();
        try {
            final String value = (String) getReplacePropertiesMethod().invoke(
                null, "${c}", new PropertiesExpander(props), null);
            fail("expected to fail, instead got: " + value);
        }
        catch (InvocationTargetException ex) {
            assertEquals("Invalid exception cause message",
                "Property ${c} has not been set", ex.getCause().getMessage());
        }
    }

    @Test
    public void testReplacePropertiesReplace() throws Exception {
        final String[][] testValues = {
            {"${a}", "A"},
            {"x${a}", "xA"},
            {"${a}x", "Ax"},
            {"${a}${b}", "AB"},
            {"x${a}${b}", "xAB"},
            {"${a}x${b}", "AxB"},
            {"${a}${b}x", "ABx"},
            {"x${a}y${b}", "xAyB"},
            {"${a}x${b}y", "AxBy"},
            {"x${a}${b}y", "xABy"},
            {"x${a}y${b}z", "xAyBz"},
            {"$$", "$"},
        };
        final Properties props = initProperties();
        for (String[] testValue : testValues) {
            final String value = (String) getReplacePropertiesMethod().invoke(
                null, testValue[0], new PropertiesExpander(props), null);
            assertEquals("\"" + testValue[0] + "\"",
                testValue[1], value);
        }
    }

    private static Properties initProperties() {
        final Properties props = new Properties();
        props.setProperty("a", "A");
        props.setProperty("b", "B");
        return props;
    }

    @Test
    public void testExternalEntity() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final DefaultConfiguration config =
            (DefaultConfiguration) loadConfiguration(
                "InputConfigurationLoaderExternalEntity.xml", props);

        final Properties atts = new Properties();
        atts.setProperty("tabWidth", "4");
        atts.setProperty("basedir", "basedir");
        verifyConfigNode(config, "Checker", 2, atts);
    }

    @Test
    public void testExternalEntitySubdirectory() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final DefaultConfiguration config =
            (DefaultConfiguration) loadConfiguration(
                "subdir/InputConfigurationLoaderExternalEntitySubDir.xml", props);

        final Properties attributes = new Properties();
        attributes.setProperty("tabWidth", "4");
        attributes.setProperty("basedir", "basedir");
        verifyConfigNode(config, "Checker", 2, attributes);
    }

    @Test
    public void testExternalEntityFromUri() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");

        final File file = new File(
                getPath("subdir/InputConfigurationLoaderExternalEntitySubDir.xml"));
        final DefaultConfiguration config =
            (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                    file.toURI().toString(), new PropertiesExpander(props));

        final Properties atts = new Properties();
        atts.setProperty("tabWidth", "4");
        atts.setProperty("basedir", "basedir");
        verifyConfigNode(config, "Checker", 2, atts);
    }

    @Test
    public void testIncorrectTag() throws Exception {
        try {
            final Class<?> aClassParent = ConfigurationLoader.class;
            final Constructor<?> ctorParent = aClassParent.getDeclaredConstructor(
                    PropertyResolver.class, boolean.class, ThreadModeSettings.class);
            ctorParent.setAccessible(true);
            final Object objParent = ctorParent.newInstance(null, true, null);

            final Class<?> aClass = Class.forName("com.puppycrawl.tools.checkstyle."
                    + "ConfigurationLoader$InternalLoader");
            final Constructor<?> constructor = aClass.getConstructor(objParent.getClass());
            constructor.setAccessible(true);

            final Object obj = constructor.newInstance(objParent);

            final Class<?>[] param = new Class<?>[] {String.class, String.class,
                String.class, Attributes.class, };
            final Method method = aClass.getDeclaredMethod("startElement", param);

            method.invoke(obj, "", "", "hello", null);

            fail("Exception is expected");

        }
        catch (InvocationTargetException ex) {
            assertTrue("Invalid exception cause",
                ex.getCause() instanceof IllegalStateException);
            assertEquals("Invalid exception cause message",
                "Unknown name:" + "hello" + ".", ex.getCause().getMessage());
        }
    }

    @Test
    public void testPrivateConstructorWithPropertyResolverAndOmitIgnoreModules() throws Exception {
        final Class<?> configurationLoaderClass = ConfigurationLoader.class;
        final Constructor<?> configurationLoaderCtor =
                configurationLoaderClass.getDeclaredConstructor(
                        PropertyResolver.class, boolean.class);
        configurationLoaderCtor.setAccessible(true);

        final Properties properties = new Properties();
        final PropertyResolver propertyResolver = new PropertiesExpander(properties);
        final ConfigurationLoader configurationLoader =
                (ConfigurationLoader) configurationLoaderCtor.newInstance(
                        propertyResolver, true);

        final Field overridePropsResolverField =
                configurationLoaderClass.getDeclaredField("overridePropsResolver");
        overridePropsResolverField.setAccessible(true);
        assertEquals("Invalid property resolver",
            propertyResolver, overridePropsResolverField.get(configurationLoader));

        final Field omitIgnoredModulesField =
                configurationLoaderClass.getDeclaredField("omitIgnoredModules");
        omitIgnoredModulesField.setAccessible(true);
        assertEquals("omitIgnoredModules should be set to true",
            true, omitIgnoredModulesField.get(configurationLoader));
    }

    @Test
    public void testNonExistingPropertyName() throws Exception {
        try {
            loadConfiguration("InputConfigurationLoaderNonexistingProperty.xml");
            fail("exception in expected");
        }
        catch (CheckstyleException ex) {
            assertEquals("Invalid exception message",
                "unable to parse configuration stream", ex.getMessage());
            assertEquals("Invalid exception cause message",
                "Property ${nonexisting} has not been set",
                    ex.getCause().getMessage());
        }
    }

    @Test
    public void testConfigWithIgnore() throws Exception {

        final DefaultConfiguration config =
                (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                        getPath("InputConfigurationLoaderModuleIgnoreSeverity.xml"),
                        new PropertiesExpander(new Properties()), true);

        final Configuration[] children = config.getChildren();
        assertEquals("Invalid children count", 0, children[0].getChildren().length);
    }

    @Test
    public void testConfigWithIgnoreUsingInputSource() throws Exception {

        final DefaultConfiguration config =
                (DefaultConfiguration) ConfigurationLoader.loadConfiguration(new InputSource(
                        new File(getPath("InputConfigurationLoaderModuleIgnoreSeverity.xml"))
                            .toURI().toString()),
                        new PropertiesExpander(new Properties()), true);

        final Configuration[] children = config.getChildren();
        assertEquals("Invalid children count", 0, children[0].getChildren().length);
    }

    @Test
    public void testConfigCheckerWithIgnore() throws Exception {

        final DefaultConfiguration config =
                (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                        getPath("InputConfigurationLoaderCheckerIgnoreSeverity.xml"),
                        new PropertiesExpander(new Properties()), true);

        final Configuration[] children = config.getChildren();
        assertEquals("Invalid children count", 0, children.length);
    }

    @Test
    public void testLoadConfigurationWrongUrl() {
        try {
            final DefaultConfiguration config =
                    (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                            ";InputConfigurationLoaderModuleIgnoreSeverity.xml",
                            new PropertiesExpander(new Properties()), true);

            final Configuration[] children = config.getChildren();
            assertEquals("Invalid children count", 0, children[0].getChildren().length);
            fail("Exception is expected");
        }
        catch (CheckstyleException ex) {
            assertEquals("Invalid exception message",
                    "Unable to find: ;InputConfigurationLoaderModuleIgnoreSeverity.xml",
                    ex.getMessage());
        }
    }

    @Test
    public void testLoadConfigurationDeprecated() throws Exception {
        final DefaultConfiguration config =
                (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                        new FileInputStream(
                            getPath("InputConfigurationLoaderModuleIgnoreSeverity.xml")),
                        new PropertiesExpander(new Properties()), true);

        final Configuration[] children = config.getChildren();
        assertEquals("Invalid children count",
            0, children[0].getChildren().length);
    }

    @Test
    public void testReplacePropertiesDefault() throws Exception {
        final Properties props = new Properties();
        final String defaultValue = "defaultValue";

        final String value = (String) getReplacePropertiesMethod().invoke(
            null, "${checkstyle.basedir}", new PropertiesExpander(props), defaultValue);

        assertEquals("Invalid property value", defaultValue, value);
    }

    @Test
    public void testLoadConfigurationFromClassPath() throws Exception {
        final DefaultConfiguration config =
                (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                        getPath("InputConfigurationLoaderModuleIgnoreSeverity.xml"),
                        new PropertiesExpander(new Properties()), true);

        final Configuration[] children = config.getChildren();
        assertEquals("Invalid children count",
            0, children[0].getChildren().length);
    }

    /**
     * This SuppressWarning("unchecked") required to suppress
     * "Unchecked generics array creation for varargs parameter" during mock.
     * @throws Exception could happen from PowerMokito calls and getAttribute
     */
    @SuppressWarnings("unchecked")
    @Test
    public void testConfigWithIgnoreExceptionalAttributes() throws Exception {

        // emulate exception from unrelated code, but that is same try-catch
        final DefaultConfiguration tested = PowerMockito.mock(DefaultConfiguration.class);
        when(tested.getAttributeNames()).thenReturn(new String[] {"severity"});
        when(tested.getName()).thenReturn("MemberName");
        when(tested.getAttribute("severity")).thenThrow(CheckstyleException.class);
        // to void creation of 2 other mocks for now reason, only one moc is used for all cases
        PowerMockito.whenNew(DefaultConfiguration.class)
                .withArguments("MemberName", ThreadModeSettings.SINGLE_THREAD_MODE_INSTANCE)
                .thenReturn(tested);
        PowerMockito.whenNew(DefaultConfiguration.class)
                .withArguments("Checker", ThreadModeSettings.SINGLE_THREAD_MODE_INSTANCE)
                .thenReturn(tested);
        PowerMockito.whenNew(DefaultConfiguration.class)
                .withArguments("TreeWalker", ThreadModeSettings.SINGLE_THREAD_MODE_INSTANCE)
                .thenReturn(tested);

        try {
            ConfigurationLoader.loadConfiguration(
                    getPath("InputConfigurationLoaderModuleIgnoreSeverity.xml"),
                    new PropertiesExpander(new Properties()), true);
            fail("Exception is expected");
        }
        catch (CheckstyleException expected) {
            assertEquals("Invalid exception cause message",
                "Problem during accessing 'severity' attribute for MemberName",
                    expected.getCause().getMessage());
        }
    }

    @Test
    public void testParsePropertyString() throws Exception {
        final List<String> propertyRefs = new ArrayList<>();
        final List<String> fragments = new ArrayList<>();

        Whitebox.invokeMethod(ConfigurationLoader.class,
                "parsePropertyString", "$",
               fragments, propertyRefs);
        assertEquals("Fragments list has unexpected amount of items",
                1, fragments.size());
    }

    @Test
    public void testConstructors() throws Exception {
        final Properties props = new Properties();
        props.setProperty("checkstyle.basedir", "basedir");
        final String fName = getPath("InputConfigurationLoaderChecks.xml");

        final Configuration configuration = ConfigurationLoader.loadConfiguration(fName,
                new PropertiesExpander(props), ConfigurationLoader.IgnoredModulesOptions.OMIT);
        assertEquals("Name is not expected", "Checker", configuration.getName());

        final DefaultConfiguration configuration1 =
                (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
                        new InputSource(new FileInputStream(
                            getPath("InputConfigurationLoaderModuleIgnoreSeverity.xml"))),
                        new PropertiesExpander(new Properties()),
                        ConfigurationLoader.IgnoredModulesOptions.EXECUTE);

        final Configuration[] children = configuration1.getChildren();
        assertEquals("Unexpected children size", 1, children[0].getChildren().length);
    }
}
