1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.assertInstanceOf;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertSame;
25 import static org.junit.jupiter.api.Assertions.assertThrows;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27 import static org.mockito.Mockito.mock;
28
29 import java.math.BigDecimal;
30 import java.math.BigInteger;
31 import java.time.Duration;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.NoSuchElementException;
40 import java.util.Properties;
41 import java.util.StringTokenizer;
42
43 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
44 import org.apache.commons.configuration2.event.ConfigurationEvent;
45 import org.apache.commons.configuration2.event.EventListener;
46 import org.apache.commons.configuration2.event.EventListenerTestImpl;
47 import org.apache.commons.configuration2.ex.ConversionException;
48 import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
49 import org.apache.commons.configuration2.interpol.Lookup;
50 import org.junit.jupiter.api.BeforeEach;
51 import org.junit.jupiter.api.Test;
52
53
54
55
56 public class TestBaseConfiguration {
57
58 static final String KEY_NUMBER = "number";
59
60 protected static Class<?> missingElementException = NoSuchElementException.class;
61 protected static Class<?> incompatibleElementException = ConversionException.class;
62 protected BaseConfiguration config;
63
64 @BeforeEach
65 public void setUp() throws Exception {
66 config = new BaseConfiguration();
67 config.setThrowExceptionOnMissing(true);
68 config.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
69 }
70
71 @Test
72 public void testAddProperty() throws Exception {
73 Collection<Object> props = new ArrayList<>();
74 props.add("one");
75 props.add("two,three,four");
76 props.add(new String[] {"5.1", "5.2", "5.3,5.4", "5.5"});
77 props.add("six");
78 config.addProperty("complex.property", props);
79
80 Object val = config.getProperty("complex.property");
81 Collection<?> col = assertInstanceOf(Collection.class, val);
82 assertEquals(10, col.size());
83
84 props = new ArrayList<>();
85 props.add("quick");
86 props.add("brown");
87 props.add("fox,jumps");
88 final Object[] data = {"The", props, "over,the", "lazy", "dog."};
89 config.setProperty("complex.property", data);
90 val = config.getProperty("complex.property");
91 col = assertInstanceOf(Collection.class, val);
92 final Iterator<?> it = col.iterator();
93 final StringTokenizer tok = new StringTokenizer("The quick brown fox jumps over the lazy dog.", " ");
94 while (tok.hasMoreTokens()) {
95 assertTrue(it.hasNext());
96 assertEquals(tok.nextToken(), it.next());
97 }
98 assertFalse(it.hasNext());
99
100 config.setProperty("complex.property", null);
101 assertFalse(config.containsKey("complex.property"));
102 }
103
104
105
106
107 @Test
108 public void testClone() {
109 for (int i = 0; i < 10; i++) {
110 config.addProperty("key" + i, Integer.valueOf(i));
111 }
112 final BaseConfiguration config2 = (BaseConfiguration) config.clone();
113
114 for (final Iterator<String> it = config.getKeys(); it.hasNext();) {
115 final String key = it.next();
116 assertTrue(config2.containsKey(key), "Key not found: " + key);
117 assertEquals(config.getProperty(key), config2.getProperty(key), "Wrong value for key " + key);
118 }
119 }
120
121
122
123
124 @Test
125 public void testCloneInterpolation() {
126 final String keyAnswer = "answer";
127 config.addProperty(keyAnswer, "The answer is ${" + KEY_NUMBER + "}.");
128 config.addProperty(KEY_NUMBER, 42);
129 final BaseConfiguration clone = (BaseConfiguration) config.clone();
130 clone.setProperty(KEY_NUMBER, 43);
131 assertEquals("The answer is 42.", config.getString(keyAnswer));
132 assertEquals("The answer is 43.", clone.getString(keyAnswer));
133 }
134
135
136
137
138 @Test
139 public void testCloneListProperty() {
140 final String key = "list";
141 config.addProperty(key, "value1");
142 config.addProperty(key, "value2");
143 final BaseConfiguration config2 = (BaseConfiguration) config.clone();
144 config2.addProperty(key, "value3");
145 assertEquals(2, config.getList(key).size());
146 }
147
148
149
150
151 @Test
152 public void testCloneModify() {
153 final EventListener<ConfigurationEvent> l = new EventListenerTestImpl(config);
154 config.addEventListener(ConfigurationEvent.ANY, l);
155 config.addProperty("original", Boolean.TRUE);
156 final BaseConfiguration config2 = (BaseConfiguration) config.clone();
157
158 config2.addProperty("clone", Boolean.TRUE);
159 assertFalse(config.containsKey("clone"));
160 config2.setProperty("original", Boolean.FALSE);
161 assertTrue(config.getBoolean("original"));
162
163 assertTrue(config2.getEventListeners(ConfigurationEvent.ANY).isEmpty());
164 }
165
166 @Test
167 public void testCommaSeparatedString() {
168 final String prop = "hey, that's a test";
169 config.setProperty("prop.string", prop);
170 final List<Object> list = config.getList("prop.string");
171 assertEquals(Arrays.asList("hey", "that's a test"), list);
172 }
173
174 @Test
175 public void testCommaSeparatedStringEscaped() {
176 final String prop2 = "hey\\, that's a test";
177 config.setProperty("prop.string", prop2);
178 assertEquals("hey, that's a test", config.getString("prop.string"));
179 }
180
181 @Test
182 public void testGetBigDecimal() {
183 config.setProperty("numberBigD", "123.456");
184 final BigDecimal number = new BigDecimal("123.456");
185 final BigDecimal defaultValue = new BigDecimal("654.321");
186
187 assertEquals(number, config.getBigDecimal("numberBigD"));
188 assertEquals(number, config.getBigDecimal("numberBigD", defaultValue));
189 assertEquals(defaultValue, config.getBigDecimal("numberNotInConfig", defaultValue));
190 }
191
192 @Test
193 public void testGetBigDecimalIncompatibleType() {
194 config.setProperty("test.empty", "");
195 assertThrows(ConversionException.class, () -> config.getBigDecimal("test.empty"));
196 }
197
198 @Test
199 public void testGetBigDecimalUnknown() {
200 assertThrows(NoSuchElementException.class, () -> config.getBigDecimal("numberNotInConfig"));
201 }
202
203 @Test
204 public void testGetBigInteger() {
205 config.setProperty("numberBigI", "1234567890");
206 final BigInteger number = new BigInteger("1234567890");
207 final BigInteger defaultValue = new BigInteger("654321");
208
209 assertEquals(number, config.getBigInteger("numberBigI"));
210 assertEquals(number, config.getBigInteger("numberBigI", defaultValue));
211 assertEquals(defaultValue, config.getBigInteger("numberNotInConfig", defaultValue));
212 }
213
214 @Test
215 public void testGetBigIntegerIncompatibleType() {
216 config.setProperty("test.empty", "");
217 assertThrows(ConversionException.class, () -> config.getBigInteger("test.empty"));
218 }
219
220 @Test
221 public void testGetBigIntegerUnknown() {
222 assertThrows(NoSuchElementException.class, () -> config.getBigInteger("numberNotInConfig"));
223 }
224
225 @Test
226 public void testGetBinaryValue() {
227 config.setProperty("number", "0b11111111");
228 assertEquals((byte) 0xFF, config.getByte("number"));
229
230 config.setProperty("number", "0b1111111111111111");
231 assertEquals((short) 0xFFFF, config.getShort("number"));
232
233 config.setProperty("number", "0b11111111111111111111111111111111");
234 assertEquals(0xFFFFFFFF, config.getInt("number"));
235
236 config.setProperty("number", "0b1111111111111111111111111111111111111111111111111111111111111111");
237 assertEquals(0xFFFFFFFFFFFFFFFFL, config.getLong("number"));
238
239 assertEquals(0xFFFFFFFFFFFFFFFFL, config.getBigInteger("number").longValue());
240 }
241
242 @Test
243 public void testGetBoolean() {
244 config.setProperty("boolA", Boolean.TRUE);
245 final boolean boolT = true, boolF = false;
246 assertEquals(boolT, config.getBoolean("boolA"));
247 assertEquals(boolT, config.getBoolean("boolA", boolF));
248 assertEquals(boolF, config.getBoolean("boolNotInConfig", boolF));
249 assertEquals(Boolean.valueOf(boolT), config.getBoolean("boolA", Boolean.valueOf(boolF)));
250 }
251
252 @Test
253 public void testGetBooleanIncompatibleType() {
254 config.setProperty("test.empty", "");
255 assertThrows(ConversionException.class, () -> config.getBoolean("test.empty"));
256 }
257
258 @Test
259 public void testGetBooleanUnknown() {
260 assertThrows(NoSuchElementException.class, () -> config.getBoolean("numberNotInConfig"));
261 }
262
263 @Test
264 public void testGetByte() {
265 config.setProperty("number", "1");
266 final byte oneB = 1;
267 final byte twoB = 2;
268 assertEquals(oneB, config.getByte("number"));
269 assertEquals(oneB, config.getByte("number", twoB));
270 assertEquals(twoB, config.getByte("numberNotInConfig", twoB));
271 assertEquals(Byte.valueOf(oneB), config.getByte("number", Byte.valueOf("2")));
272 }
273
274 @Test
275 public void testGetByteIncompatibleType() {
276 config.setProperty("test.empty", "");
277 assertThrows(ConversionException.class, () -> config.getByte("test.empty"));
278 }
279
280 @Test
281 public void testGetByteUnknown() {
282 assertThrows(NoSuchElementException.class, () -> config.getByte("numberNotInConfig"));
283 }
284
285 @Test
286 public void testGetDouble() {
287 config.setProperty("numberD", "1.0");
288 final double oneD = 1;
289 final double twoD = 2;
290 assertEquals(oneD, config.getDouble("numberD"), 0);
291 assertEquals(oneD, config.getDouble("numberD", twoD), 0);
292 assertEquals(twoD, config.getDouble("numberNotInConfig", twoD), 0);
293 assertEquals(Double.valueOf(oneD), config.getDouble("numberD", Double.valueOf("2")));
294 }
295
296 @Test
297 public void testGetDoubleIncompatibleType() {
298 config.setProperty("test.empty", "");
299 assertThrows(ConversionException.class, () -> config.getDouble("test.empty"));
300 }
301
302 @Test
303 public void testGetDoubleUnknown() {
304 assertThrows(NoSuchElementException.class, () -> config.getDouble("numberNotInConfig"));
305 }
306
307 @Test
308 public void testGetDuration() {
309 final Duration d = Duration.ofSeconds(1);
310 config.setProperty("durationD", d.toString());
311 final Duration oneD = Duration.ofSeconds(1);
312 final Duration twoD = Duration.ofSeconds(2);
313 assertEquals(oneD, config.getDuration("durationD"));
314 assertEquals(oneD, config.getDuration("durationD", twoD));
315 assertEquals(twoD, config.getDuration("numberNotInConfig", twoD));
316 assertEquals(oneD, config.getDuration("durationD", twoD));
317 }
318
319 @Test
320 public void testGetDurationIncompatibleType() {
321 config.setProperty("test.empty", "");
322 assertThrows(ConversionException.class, () -> config.getDuration("test.empty"));
323 }
324
325 @Test
326 public void testGetDurationUnknown() {
327 assertThrows(NoSuchElementException.class, () -> config.getDuration("numberNotInConfig"));
328 }
329
330 @Test
331 public void testGetEnum() {
332 config.setProperty("testEnum", EnumFixture.SMALLTALK.name());
333 config.setProperty("testBadEnum", "This is not an enum value.");
334 final EnumFixture enum1 = EnumFixture.SMALLTALK;
335 final EnumFixture defaultValue = EnumFixture.JAVA;
336
337 assertEquals(enum1, config.getEnum("testEnum", EnumFixture.class));
338 assertEquals(enum1, config.getEnum("testEnum", EnumFixture.class, defaultValue));
339 assertEquals(defaultValue, config.getEnum("stringNotInConfig", EnumFixture.class, defaultValue));
340
341 assertThrows(ConversionException.class, () -> config.getEnum("testBadEnum", EnumFixture.class));
342
343 assertThrows(ConversionException.class, () -> config.getEnum("testBadEnum", EnumFixture.class, defaultValue));
344 }
345
346 @Test
347 public void testGetFloat() {
348 config.setProperty("numberF", "1.0");
349 final float oneF = 1;
350 final float twoF = 2;
351 assertEquals(oneF, config.getFloat("numberF"), 0);
352 assertEquals(oneF, config.getFloat("numberF", twoF), 0);
353 assertEquals(twoF, config.getFloat("numberNotInConfig", twoF), 0);
354 assertEquals(Float.valueOf(oneF), config.getFloat("numberF", Float.valueOf("2")));
355 }
356
357 @Test
358 public void testGetFloatIncompatibleType() {
359 config.setProperty("test.empty", "");
360 assertThrows(ConversionException.class, () -> config.getFloat("test.empty"));
361 }
362
363 @Test
364 public void testGetFloatUnknown() {
365 assertThrows(NoSuchElementException.class, () -> config.getFloat("numberNotInConfig"));
366 }
367
368 @Test
369 public void testGetHexadecimalValue() {
370 config.setProperty("number", "0xFF");
371 assertEquals((byte) 0xFF, config.getByte("number"));
372
373 config.setProperty("number", "0xFFFF");
374 assertEquals((short) 0xFFFF, config.getShort("number"));
375
376 config.setProperty("number", "0xFFFFFFFF");
377 assertEquals(0xFFFFFFFF, config.getInt("number"));
378
379 config.setProperty("number", "0xFFFFFFFFFFFFFFFF");
380 assertEquals(0xFFFFFFFFFFFFFFFFL, config.getLong("number"));
381
382 assertEquals(0xFFFFFFFFFFFFFFFFL, config.getBigInteger("number").longValue());
383 }
384
385 @Test
386 public void testGetInterpolatedList() {
387 config.addProperty("number", "1");
388 config.addProperty("array", "${number}");
389 config.addProperty("array", "${number}");
390
391 final List<String> list = new ArrayList<>();
392 list.add("1");
393 list.add("1");
394
395 assertEquals(list, config.getList("array"));
396 }
397
398 @Test
399 public void testGetInterpolatedPrimitives() {
400 config.addProperty("number", "1");
401 config.addProperty("value", "${number}");
402
403 config.addProperty("boolean", "true");
404 config.addProperty("booleanValue", "${boolean}");
405
406
407 assertTrue(config.getBoolean("booleanValue"));
408 assertEquals(1, config.getByte("value"));
409 assertEquals(1, config.getShort("value"));
410 assertEquals(1, config.getInt("value"));
411 assertEquals(1, config.getLong("value"));
412 assertEquals(1, config.getFloat("value"), 0);
413 assertEquals(1, config.getDouble("value"), 0);
414
415
416 assertEquals(Boolean.TRUE, config.getBoolean("booleanValue", null));
417 assertEquals(Byte.valueOf("1"), config.getByte("value", null));
418 assertEquals(Short.valueOf("1"), config.getShort("value", null));
419 assertEquals(Integer.valueOf("1"), config.getInteger("value", null));
420 assertEquals(Long.valueOf("1"), config.getLong("value", null));
421 assertEquals(Float.valueOf("1"), config.getFloat("value", null));
422 assertEquals(Double.valueOf("1"), config.getDouble("value", null));
423
424 assertEquals(new BigInteger("1"), config.getBigInteger("value", null));
425 assertEquals(new BigDecimal("1"), config.getBigDecimal("value", null));
426 }
427
428
429
430
431 @Test
432 public void testGetInterpolator() {
433 InterpolationTestHelper.testGetInterpolator(config);
434 }
435
436 @Test
437 public void testGetList() {
438 config.addProperty("number", "1");
439 config.addProperty("number", "2");
440 final List<Object> list = config.getList("number");
441 assertEquals(Arrays.asList("1", "2"), list);
442 }
443
444 @Test
445 public void testGetLong() {
446 config.setProperty("numberL", "1");
447 final long oneL = 1;
448 final long twoL = 2;
449 assertEquals(oneL, config.getLong("numberL"));
450 assertEquals(oneL, config.getLong("numberL", twoL));
451 assertEquals(twoL, config.getLong("numberNotInConfig", twoL));
452 assertEquals(Long.valueOf(oneL), config.getLong("numberL", Long.valueOf("2")));
453 }
454
455 @Test
456 public void testGetLongIncompatibleTypes() {
457 config.setProperty("test.empty", "");
458 assertThrows(ConversionException.class, () -> config.getLong("test.empty"));
459 }
460
461 @Test
462 public void testGetLongUnknown() {
463 assertThrows(NoSuchElementException.class, () -> config.getLong("numberNotInConfig"));
464 }
465
466 @Test
467 public void testGetProperty() {
468
469 assertNull(config.getProperty("foo"));
470
471
472 config.setProperty("number", "1");
473 assertEquals("1", config.getProperty("number"));
474 assertEquals("1", config.getString("number"));
475 }
476
477 @Test
478 public void testGetShort() {
479 config.setProperty("numberS", "1");
480 final short oneS = 1;
481 final short twoS = 2;
482 assertEquals(oneS, config.getShort("numberS"));
483 assertEquals(oneS, config.getShort("numberS", twoS));
484 assertEquals(twoS, config.getShort("numberNotInConfig", twoS));
485 assertEquals(Short.valueOf(oneS), config.getShort("numberS", Short.valueOf("2")));
486 }
487
488 @Test
489 public void testGetShortIncompatibleType() {
490 config.setProperty("test.empty", "");
491 assertThrows(ConversionException.class, () -> config.getShort("test.empty"));
492 }
493
494 @Test
495 public void testGetShortUnknown() {
496 assertThrows(NoSuchElementException.class, () -> config.getShort("numberNotInConfig"));
497 }
498
499 @Test
500 public void testGetString() {
501 config.setProperty("testString", "The quick brown fox");
502 final String string = "The quick brown fox";
503 final String defaultValue = "jumps over the lazy dog";
504
505 assertEquals(string, config.getString("testString"));
506 assertEquals(string, config.getString("testString", defaultValue));
507 assertEquals(defaultValue, config.getString("stringNotInConfig", defaultValue));
508 }
509
510
511
512
513 @Test
514 public void testGetStringForListValue() {
515 config.addProperty("number", "1");
516 config.addProperty("number", "2");
517 assertEquals("1", config.getString("number"));
518 }
519
520 @Test
521 public void testGetStringUnknown() {
522 assertThrows(NoSuchElementException.class, () -> config.getString("stringNotInConfig"));
523 }
524
525
526
527
528 @Test
529 public void testInstallInterpolator() {
530 final Lookup prefixLookup = mock(Lookup.class);
531 final Lookup defLookup = mock(Lookup.class);
532 final Map<String, Lookup> prefixLookups = new HashMap<>();
533 prefixLookups.put("test", prefixLookup);
534 final List<Lookup> defLookups = new ArrayList<>();
535 defLookups.add(defLookup);
536 config.installInterpolator(prefixLookups, defLookups);
537 final ConfigurationInterpolator interpolator = config.getInterpolator();
538 assertEquals(prefixLookups, interpolator.getLookups());
539 final List<Lookup> defLookups2 = interpolator.getDefaultLookups();
540 assertEquals(2, defLookups2.size());
541 assertSame(defLookup, defLookups2.get(0));
542 final String var = "testVariable";
543 final Object value = 42;
544 config.addProperty(var, value);
545 assertEquals(value, defLookups2.get(1).lookup(var));
546 }
547
548
549
550
551 @Test
552 public void testInterpolatedConfiguration() {
553 InterpolationTestHelper.testInterpolatedConfiguration(config);
554 }
555
556 @Test
557 public void testInterpolation() {
558 InterpolationTestHelper.testInterpolation(config);
559 }
560
561
562
563
564 @Test
565 public void testInterpolationConstants() {
566 InterpolationTestHelper.testInterpolationConstants(config);
567 }
568
569
570
571
572 @Test
573 public void testInterpolationEnvironment() {
574 InterpolationTestHelper.testInterpolationEnvironment(config);
575 }
576
577
578
579
580 @Test
581 public void testInterpolationEscaped() {
582 InterpolationTestHelper.testInterpolationEscaped(config);
583 }
584
585
586
587
588 @Test
589 public void testInterpolationLocalhost() {
590 InterpolationTestHelper.testInterpolationLocalhost(config);
591 }
592
593 @Test
594 public void testInterpolationLoop() {
595 InterpolationTestHelper.testInterpolationLoop(config);
596 }
597
598
599
600
601 @Test
602 public void testInterpolationSubset() {
603 InterpolationTestHelper.testInterpolationSubset(config);
604 }
605
606
607
608
609 @Test
610 public void testInterpolationSystemProperties() {
611 InterpolationTestHelper.testInterpolationSystemProperties(config);
612 }
613
614
615
616
617 @Test
618 public void testInterpolationUnknownProperty() {
619 InterpolationTestHelper.testInterpolationUnknownProperty(config);
620 }
621
622 @Test
623 public void testMultipleInterpolation() {
624 InterpolationTestHelper.testMultipleInterpolation(config);
625 }
626
627
628
629
630 @Test
631 public void testNoInterpolator() {
632 config.setProperty("test", "${value}");
633 config.setInterpolator(null);
634 assertEquals("${value}", config.getString("test"));
635 }
636
637
638
639
640 @Test
641 public void testNumberConversions() {
642 config.setProperty(KEY_NUMBER, Integer.valueOf(42));
643 assertEquals(42, config.getInt(KEY_NUMBER));
644 assertEquals(42L, config.getLong(KEY_NUMBER));
645 assertEquals((byte) 42, config.getByte(KEY_NUMBER));
646 assertEquals(42.0f, config.getFloat(KEY_NUMBER), 0.01f);
647 assertEquals(42.0, config.getDouble(KEY_NUMBER), 0.001);
648
649 assertEquals(Long.valueOf(42L), config.getLong(KEY_NUMBER, null));
650 assertEquals(new BigInteger("42"), config.getBigInteger(KEY_NUMBER));
651 assertEquals(new BigDecimal("42.0"), config.getBigDecimal(KEY_NUMBER));
652 }
653
654 @Test
655 public void testPropertyAccess() {
656 config.clearProperty("prop.properties");
657 config.setProperty("prop.properties", "");
658 assertEquals(new Properties(), config.getProperties("prop.properties"));
659 config.clearProperty("prop.properties");
660 config.setProperty("prop.properties", "foo=bar, baz=moo, seal=clubber");
661
662 final Properties p = new Properties();
663 p.setProperty("foo", "bar");
664 p.setProperty("baz", "moo");
665 p.setProperty("seal", "clubber");
666 assertEquals(p, config.getProperties("prop.properties"));
667 }
668
669
670
671
672 @Test
673 public void testSetInterpolator() {
674 final ConfigurationInterpolator interpolator = mock(ConfigurationInterpolator.class);
675 config.setInterpolator(interpolator);
676 assertSame(interpolator, config.getInterpolator());
677 }
678
679
680
681
682 @Test
683 public void testSize() {
684 final int count = 16;
685 for (int i = 0; i < count; i++) {
686 config.addProperty("key" + i, "value" + i);
687 }
688 assertEquals(count, config.size());
689 }
690
691 @Test
692 public void testSubset() {
693
694
695
696
697 final String prop = "hey, that's a test";
698 final String prop2 = "hey\\, that's a test";
699 config.setProperty("prop.string", prop2);
700 config.setProperty("property.string", "hello");
701
702 Configuration subEprop = config.subset("prop");
703
704 assertEquals(prop, subEprop.getString("string"));
705 assertEquals(1, subEprop.getList("string").size());
706
707 Iterator<String> it = subEprop.getKeys();
708 it.next();
709 assertFalse(it.hasNext());
710
711 subEprop = config.subset("prop.");
712 it = subEprop.getKeys();
713 assertFalse(it.hasNext());
714 }
715
716 @Test
717 public void testThrowExceptionOnMissing() {
718 assertTrue(config.isThrowExceptionOnMissing());
719 }
720 }