View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration2;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  
25  import java.math.BigDecimal;
26  import java.math.BigInteger;
27  import java.util.Arrays;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.NoSuchElementException;
31  import java.util.Properties;
32  
33  import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
34  import org.apache.commons.configuration2.ex.ConversionException;
35  import org.junit.jupiter.api.BeforeEach;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Tests some basic functions of the BaseConfiguration class. Missing keys might return null.
40   */
41  public class TestBaseNullConfiguration {
42      protected BaseConfiguration config;
43  
44      @BeforeEach
45      public void setUp() throws Exception {
46          config = new BaseConfiguration();
47          config.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
48          config.setThrowExceptionOnMissing(false);
49      }
50  
51      @Test
52      void testCommaSeparatedString() {
53          final String prop = "hey, that's a test";
54          config.setProperty("prop.string", prop);
55          final List<Object> list = config.getList("prop.string");
56          assertEquals(Arrays.asList("hey", "that's a test"), list);
57      }
58  
59      @Test
60      void testCommaSeparatedStringEscaped() {
61          final String prop2 = "hey\\, that's a test";
62          config.clearProperty("prop.string");
63          config.setProperty("prop.string", prop2);
64          assertEquals("hey, that's a test", config.getString("prop.string"));
65      }
66  
67      @Test
68      void testGetBigDecimal() {
69          config.setProperty("numberBigD", "123.456");
70          final BigDecimal number = new BigDecimal("123.456");
71          final BigDecimal defaultValue = new BigDecimal("654.321");
72  
73          assertEquals(number, config.getBigDecimal("numberBigD"));
74          assertEquals(number, config.getBigDecimal("numberBigD", defaultValue));
75          assertEquals(defaultValue, config.getBigDecimal("numberNotInConfig", defaultValue));
76      }
77  
78      @Test
79      void testGetBigDecimalIncompatibleType() {
80          config.setProperty("test.empty", "");
81          assertThrows(ConversionException.class, () -> config.getBigDecimal("test.empty"));
82      }
83  
84      @Test
85      void testGetBigDecimalUnknown() {
86          assertNull(config.getBigDecimal("numberNotInConfig"));
87      }
88  
89      @Test
90      void testGetBigInteger() {
91          config.setProperty("numberBigI", "1234567890");
92          final BigInteger number = new BigInteger("1234567890");
93          final BigInteger defaultValue = new BigInteger("654321");
94  
95          assertEquals(number, config.getBigInteger("numberBigI"));
96          assertEquals(number, config.getBigInteger("numberBigI", defaultValue));
97          assertEquals(defaultValue, config.getBigInteger("numberNotInConfig", defaultValue));
98      }
99  
100     @Test
101     void testGetBigIntegerIncompatibleType() {
102         config.setProperty("test.empty", "");
103         assertThrows(ConversionException.class, () -> config.getBigInteger("test.empty"));
104     }
105 
106     @Test
107     void testGetBigIntegerUnknown() {
108         assertNull(config.getBigInteger("numberNotInConfig"));
109     }
110 
111     @Test
112     void testGetBoolean() {
113         config.setProperty("boolA", Boolean.TRUE);
114         final boolean boolT = true;
115         final boolean boolF = false;
116         assertEquals(boolT, config.getBoolean("boolA"));
117         assertEquals(boolT, config.getBoolean("boolA", boolF));
118         assertEquals(boolF, config.getBoolean("boolNotInConfig", boolF));
119         assertEquals(Boolean.valueOf(boolT), config.getBoolean("boolA", Boolean.valueOf(boolF)));
120     }
121 
122     @Test
123     void testGetBooleanIncompatibleType() {
124         config.setProperty("test.empty", "");
125         assertThrows(ConversionException.class, () -> config.getBoolean("test.empty"));
126     }
127 
128     @Test
129     void testGetBooleanUnknown() {
130         assertThrows(NoSuchElementException.class, () -> config.getBoolean("numberNotInConfig"));
131     }
132 
133     @Test
134     void testGetByte() {
135         config.setProperty("number", "1");
136         final byte oneB = 1;
137         final byte twoB = 2;
138         assertEquals(oneB, config.getByte("number"));
139         assertEquals(oneB, config.getByte("number", twoB));
140         assertEquals(twoB, config.getByte("numberNotInConfig", twoB));
141         assertEquals(Byte.valueOf(oneB), config.getByte("number", Byte.valueOf("2")));
142     }
143 
144     @Test
145     void testGetByteIncompatibleType() {
146         config.setProperty("test.empty", "");
147         assertThrows(ConversionException.class, () -> config.getByte("test.empty"));
148     }
149 
150     @Test
151     void testGetByteUnknown() {
152         assertThrows(NoSuchElementException.class, () -> config.getByte("numberNotInConfig"));
153     }
154 
155     @Test
156     void testGetDouble() {
157         config.setProperty("numberD", "1.0");
158         final double oneD = 1;
159         final double twoD = 2;
160         assertEquals(oneD, config.getDouble("numberD"), 0);
161         assertEquals(oneD, config.getDouble("numberD", twoD), 0);
162         assertEquals(twoD, config.getDouble("numberNotInConfig", twoD), 0);
163         assertEquals(Double.valueOf(oneD), config.getDouble("numberD", Double.valueOf("2")));
164     }
165 
166     @Test
167     void testGetDoubleIncompatibleType() {
168         config.setProperty("test.empty", "");
169         assertThrows(ConversionException.class, () -> config.getDouble("test.empty"));
170     }
171 
172     @Test
173     void testGetDoubleUnknown() {
174         assertThrows(NoSuchElementException.class, () -> config.getDouble("numberNotInConfig"));
175     }
176 
177     @Test
178     void testGetFloat() {
179         config.setProperty("numberF", "1.0");
180         final float oneF = 1;
181         final float twoF = 2;
182         assertEquals(oneF, config.getFloat("numberF"), 0);
183         assertEquals(oneF, config.getFloat("numberF", twoF), 0);
184         assertEquals(twoF, config.getFloat("numberNotInConfig", twoF), 0);
185         assertEquals(Float.valueOf(oneF), config.getFloat("numberF", Float.valueOf("2")));
186     }
187 
188     @Test
189     void testGetFloatIncompatibleType() {
190         config.setProperty("test.empty", "");
191         assertThrows(ConversionException.class, () -> config.getFloat("test.empty"));
192     }
193 
194     @Test
195     void testGetFloatUnknown() {
196         assertThrows(NoSuchElementException.class, () -> config.getFloat("numberNotInConfig"));
197     }
198 
199     @Test
200     void testGetList() {
201         config.addProperty("number", "1");
202         config.addProperty("number", "2");
203         final List<Object> list = config.getList("number");
204         assertEquals(Arrays.asList("1", "2"), list);
205     }
206 
207     @Test
208     void testGetListAsScalar() {
209         config.addProperty("number", "1");
210         config.addProperty("number", "2");
211         assertEquals("1", config.getString("number"));
212     }
213 
214     @Test
215     void testGetLong() {
216         config.setProperty("numberL", "1");
217         final long oneL = 1;
218         final long twoL = 2;
219         assertEquals(oneL, config.getLong("numberL"));
220         assertEquals(oneL, config.getLong("numberL", twoL));
221         assertEquals(twoL, config.getLong("numberNotInConfig", twoL));
222         assertEquals(Long.valueOf(oneL), config.getLong("numberL", Long.valueOf("2")));
223     }
224 
225     @Test
226     void testGetLongIncompatibleTypes() {
227         config.setProperty("test.empty", "");
228         assertThrows(ConversionException.class, () -> config.getLong("test.empty"));
229     }
230 
231     @Test
232     void testGetLongUnknown() {
233         assertThrows(NoSuchElementException.class, () -> config.getLong("numberNotInConfig"));
234     }
235 
236     @Test
237     void testGetProperty() {
238         /* should be empty and return null */
239         assertNull(config.getProperty("foo"));
240 
241         /* add a real value, and get it two different ways */
242         config.setProperty("number", "1");
243         assertEquals("1", config.getProperty("number"));
244         assertEquals("1", config.getString("number"));
245     }
246 
247     @Test
248     void testGetShort() {
249         config.setProperty("numberS", "1");
250         final short oneS = 1;
251         final short twoS = 2;
252         assertEquals(oneS, config.getShort("numberS"));
253         assertEquals(oneS, config.getShort("numberS", twoS));
254         assertEquals(twoS, config.getShort("numberNotInConfig", twoS));
255         assertEquals(Short.valueOf(oneS), config.getShort("numberS", Short.valueOf("2")));
256     }
257 
258     @Test
259     void testGetShortIncompatibleType() {
260         config.setProperty("test.empty", "");
261         assertThrows(ConversionException.class, () -> config.getShort("test.empty"));
262     }
263 
264     @Test
265     void testGetShortUnknown() {
266         assertThrows(NoSuchElementException.class, () -> config.getShort("numberNotInConfig"));
267     }
268 
269     @Test
270     void testGetString() {
271         config.setProperty("testString", "The quick brown fox");
272         final String string = "The quick brown fox";
273         final String defaultValue = "jumps over the lazy dog";
274 
275         assertEquals(string, config.getString("testString"));
276         assertEquals(string, config.getString("testString", defaultValue));
277         assertEquals(defaultValue, config.getString("stringNotInConfig", defaultValue));
278     }
279 
280     @Test
281     void testGetStringUnknown() {
282         assertNull(config.getString("stringNotInConfig"));
283     }
284 
285     @Test
286     void testInterpolation() throws Exception {
287         config.setProperty("applicationRoot", "/home/applicationRoot");
288         config.setProperty("db", "${applicationRoot}/db/hypersonic");
289         final String unInterpolatedValue = "${applicationRoot2}/db/hypersonic";
290         config.setProperty("dbFailedInterpolate", unInterpolatedValue);
291         final String dbProp = "/home/applicationRoot/db/hypersonic";
292 
293         // construct a new config, using config as the defaults config for it.
294         final BaseConfiguration superProp = config;
295 
296         assertEquals(dbProp, superProp.getString("db"));
297         assertEquals(unInterpolatedValue, superProp.getString("dbFailedInterpolate"));
298 
299         superProp.setProperty("arrayInt", "${applicationRoot}/1");
300         final String[] arrayInt = superProp.getStringArray("arrayInt");
301         assertEquals("/home/applicationRoot/1", arrayInt[0]);
302     }
303 
304     @Test
305     void testInterpolationLoop() throws Exception {
306         config.setProperty("test.a", "${test.b}");
307         config.setProperty("test.b", "${test.a}");
308         assertThrows(IllegalStateException.class, () -> config.getString("test.a"));
309     }
310 
311     @Test
312     void testMultipleInterpolation() throws Exception {
313         config.setProperty("test.base-level", "/base-level");
314         config.setProperty("test.first-level", "${test.base-level}/first-level");
315         config.setProperty("test.second-level", "${test.first-level}/second-level");
316         config.setProperty("test.third-level", "${test.second-level}/third-level");
317 
318         final String expectedValue = "/base-level/first-level/second-level/third-level";
319 
320         assertEquals(expectedValue, config.getString("test.third-level"));
321     }
322 
323     @Test
324     void testPropertyAccess() {
325         config.clearProperty("prop.properties");
326         config.setProperty("prop.properties", "");
327         assertEquals(new Properties(), config.getProperties("prop.properties"));
328         config.clearProperty("prop.properties");
329         config.setProperty("prop.properties", "foo=bar, baz=moo, seal=clubber");
330 
331         final Properties p = new Properties();
332         p.setProperty("foo", "bar");
333         p.setProperty("baz", "moo");
334         p.setProperty("seal", "clubber");
335         assertEquals(p, config.getProperties("prop.properties"));
336     }
337 
338     @Test
339     void testSubset() {
340         /*
341          * test subset : assure we don't reprocess the data elements when generating the subset
342          */
343 
344         final String prop = "hey, that's a test";
345         final String prop2 = "hey\\, that's a test";
346         config.setProperty("prop.string", prop2);
347         config.setProperty("property.string", "hello");
348 
349         Configuration subEprop = config.subset("prop");
350 
351         assertEquals(prop, subEprop.getString("string"));
352         assertEquals(1, subEprop.getList("string").size());
353 
354         Iterator<String> it = subEprop.getKeys();
355         it.next();
356         assertFalse(it.hasNext());
357 
358         subEprop = config.subset("prop.");
359         it = subEprop.getKeys();
360         assertFalse(it.hasNext());
361     }
362 
363     @Test
364     void testThrowExceptionOnMissing() {
365         assertFalse(config.isThrowExceptionOnMissing());
366     }
367 }