001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.configuration;
018    
019    import static org.junit.Assert.assertEquals;
020    import static org.junit.Assert.fail;
021    
022    import java.awt.event.KeyEvent;
023    import java.util.List;
024    
025    import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
026    import org.apache.commons.lang.text.StrLookup;
027    
028    /**
029     * A helper class that defines a bunch of tests related to variable
030     * interpolation. It can be used for running these tests on different
031     * configuration implementations.
032     *
033     * @author <a
034     * href="http://commons.apache.org/configuration/team-list.html">Commons
035     * Configuration team</a>
036     * @version $Id: InterpolationTestHelper.java 1222452 2011-12-22 21:06:17Z oheger $
037     */
038    public class InterpolationTestHelper
039    {
040        /**
041         * Tests basic interpolation facilities of the specified configuration.
042         *
043         * @param config the configuration to test
044         */
045        public static void testInterpolation(Configuration config)
046        {
047            config.setProperty("applicationRoot", "/home/applicationRoot");
048            config.setProperty("db", "${applicationRoot}/db/hypersonic");
049            String unInterpolatedValue = "${applicationRoot2}/db/hypersonic";
050            config.setProperty("dbFailedInterpolate", unInterpolatedValue);
051            String dbProp = "/home/applicationRoot/db/hypersonic";
052    
053            assertEquals("Checking interpolated variable", dbProp, config
054                    .getString("db"));
055            assertEquals("lookup fails, leave variable as is", config
056                    .getString("dbFailedInterpolate"), unInterpolatedValue);
057    
058            config.setProperty("arrayInt", "${applicationRoot}/1");
059            String[] arrayInt = config.getStringArray("arrayInt");
060            assertEquals("check first entry was interpolated",
061                    "/home/applicationRoot/1", arrayInt[0]);
062    
063            config.addProperty("path", "/temp,C:\\Temp,/usr/local/tmp");
064            config.setProperty("path.current", "${path}");
065            assertEquals("Interpolation with multi-valued property",
066                    "/temp", config.getString("path.current"));
067        }
068    
069        /**
070         * Tests an interpolation over multiple levels (i.e. the replacement of a
071         * variable is another variable and so on).
072         *
073         * @param config the configuration to test
074         */
075        public static void testMultipleInterpolation(Configuration config)
076        {
077            config.setProperty("test.base-level", "/base-level");
078            config
079                    .setProperty("test.first-level",
080                            "${test.base-level}/first-level");
081            config.setProperty("test.second-level",
082                    "${test.first-level}/second-level");
083            config.setProperty("test.third-level",
084                    "${test.second-level}/third-level");
085    
086            String expectedValue = "/base-level/first-level/second-level/third-level";
087    
088            assertEquals(config.getString("test.third-level"),
089                            expectedValue);
090        }
091    
092        /**
093         * Tests an invalid interpolation that results in an infinite loop. This
094         * loop should be detected and an exception should be thrown.
095         *
096         * @param config the configuration to test
097         */
098        public static void testInterpolationLoop(Configuration config)
099        {
100            config.setProperty("test.a", "${test.b}");
101            config.setProperty("test.b", "${test.a}");
102    
103            try
104            {
105                config.getString("test.a");
106                fail("IllegalStateException should have been thrown for looped property references");
107            }
108            catch (IllegalStateException e)
109            {
110                // ok
111            }
112    
113        }
114    
115        /**
116         * Tests interpolation when a subset configuration is involved.
117         *
118         * @param config the configuration to test
119         */
120        public static void testInterpolationSubset(Configuration config)
121        {
122            config.addProperty("test.a", new Integer(42));
123            config.addProperty("test.b", "${test.a}");
124            assertEquals("Wrong interpolated value", 42, config
125                    .getInt("test.b"));
126            Configuration subset = config.subset("test");
127            assertEquals("Wrong string property", "42", subset
128                    .getString("b"));
129            assertEquals("Wrong int property", 42, subset.getInt("b"));
130        }
131    
132        /**
133         * Tests interpolation when the referred property is not found.
134         *
135         * @param config the configuration to test
136         */
137        public static void testInterpolationUnknownProperty(Configuration config)
138        {
139            config.addProperty("test.interpol", "${unknown.property}");
140            assertEquals("Wrong interpolated unknown property",
141                    "${unknown.property}", config.getString("test.interpol"));
142        }
143    
144        /**
145         * Tests interpolation of system properties.
146         *
147         * @param config the configuration to test
148         */
149        public static void testInterpolationSystemProperties(Configuration config)
150        {
151            String[] sysProperties =
152            { "java.version", "java.vendor", "os.name", "java.class.path" };
153            for (int i = 0; i < sysProperties.length; i++)
154            {
155                config.addProperty("prop" + i, "${sys:" + sysProperties[i] + "}");
156            }
157    
158            for (int i = 0; i < sysProperties.length; i++)
159            {
160                assertEquals("Wrong value for system property "
161                        + sysProperties[i], System.getProperty(sysProperties[i]),
162                        config.getString("prop" + i));
163            }
164        }
165    
166        /**
167         * Tests interpolation of constant values.
168         *
169         * @param config the configuration to test
170         */
171        public static void testInterpolationConstants(Configuration config)
172        {
173            config.addProperty("key.code",
174                    "${const:java.awt.event.KeyEvent.VK_CANCEL}");
175            assertEquals("Wrong value of constant variable",
176                    KeyEvent.VK_CANCEL, config.getInt("key.code"));
177            assertEquals("Wrong value when fetching constant from cache",
178                    KeyEvent.VK_CANCEL, config.getInt("key.code"));
179        }
180    
181        /**
182         * Tests whether a variable can be escaped, so that it won't be
183         * interpolated.
184         *
185         * @param config the configuration to test
186         */
187        public static void testInterpolationEscaped(Configuration config)
188        {
189            config.addProperty("var", "x");
190            config.addProperty("escVar", "Use the variable $${${var}}.");
191            assertEquals("Wrong escaped variable", "Use the variable ${x}.",
192                    config.getString("escVar"));
193        }
194    
195        /**
196         * Tests accessing and manipulating the interpolator object.
197         *
198         * @param config the configuration to test
199         */
200        public static void testGetInterpolator(AbstractConfiguration config)
201        {
202            config.addProperty("var", "${echo:testVar}");
203            ConfigurationInterpolator interpol = config.getInterpolator();
204            interpol.registerLookup("echo", new StrLookup()
205            {
206                @Override
207                public String lookup(String varName)
208                {
209                    return "Value of variable " + varName;
210                }
211            });
212            assertEquals("Wrong value of echo variable",
213                    "Value of variable testVar", config.getString("var"));
214        }
215    
216        /**
217         * Tests obtaining a configuration with all variables replaced by their
218         * actual values.
219         *
220         * @param config the configuration to test
221         * @return the interpolated configuration
222         */
223        public static Configuration testInterpolatedConfiguration(
224                AbstractConfiguration config)
225        {
226            config.setProperty("applicationRoot", "/home/applicationRoot");
227            config.setProperty("db", "${applicationRoot}/db/hypersonic");
228            config.setProperty("inttest.interpol", "${unknown.property}");
229            config.setProperty("intkey.code",
230                    "${const:java.awt.event.KeyEvent.VK_CANCEL}");
231            config.setProperty("inttest.sysprop", "${sys:java.version}");
232            config.setProperty("inttest.numvalue", "3\\,1415");
233            config.setProperty("inttest.value", "${inttest.numvalue}");
234            config.setProperty("inttest.list", "${db}");
235            config.addProperty("inttest.list", "${inttest.value}");
236    
237            Configuration c = config.interpolatedConfiguration();
238            assertEquals("Property not replaced",
239                    "/home/applicationRoot/db/hypersonic", c.getProperty("db"));
240            assertEquals("Const variable not replaced", KeyEvent.VK_CANCEL,
241                    c.getInt("intkey.code"));
242            assertEquals("Sys property not replaced", System
243                    .getProperty("java.version"), c.getProperty("inttest.sysprop"));
244            assertEquals("Delimiter value not replaced", "3,1415", c
245                    .getProperty("inttest.value"));
246            List<?> lst = (List<?>) c.getProperty("inttest.list");
247            assertEquals("Wrong number of list elements", 2, lst.size());
248            assertEquals("List element 0 not replaced",
249                    "/home/applicationRoot/db/hypersonic", lst.get(0));
250            assertEquals("List element 1 not replaced", "3,1415", lst
251                            .get(1));
252            assertEquals("Unresolvable variable not found",
253                    "${unknown.property}", c.getProperty("inttest.interpol"));
254    
255            return c;
256        }
257    }