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.apache.commons.configuration2.TempDirUtils.newFile;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26 import static org.junit.jupiter.api.Assertions.fail;
27
28 import java.io.File;
29 import java.io.FileWriter;
30 import java.io.IOException;
31 import java.io.PrintWriter;
32 import java.io.StringReader;
33 import java.io.StringWriter;
34 import java.io.Writer;
35 import java.text.MessageFormat;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.HashSet;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Set;
42 import java.util.stream.Stream;
43
44 import org.apache.commons.configuration2.SynchronizerTestImpl.Methods;
45 import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
46 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
47 import org.apache.commons.configuration2.builder.fluent.Parameters;
48 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
49 import org.apache.commons.configuration2.ex.ConfigurationException;
50 import org.apache.commons.configuration2.sync.ReadWriteSynchronizer;
51 import org.apache.commons.configuration2.tree.DefaultExpressionEngine;
52 import org.apache.commons.configuration2.tree.DefaultExpressionEngineSymbols;
53 import org.apache.commons.configuration2.tree.ImmutableNode;
54 import org.apache.commons.configuration2.tree.NodeHandler;
55 import org.apache.commons.configuration2.tree.NodeNameMatchers;
56 import org.junit.jupiter.api.Test;
57 import org.junit.jupiter.api.io.TempDir;
58 import org.junit.jupiter.params.ParameterizedTest;
59 import org.junit.jupiter.params.provider.Arguments;
60 import org.junit.jupiter.params.provider.MethodSource;
61
62
63
64
65 public class TestINIConfiguration {
66
67
68
69
70 private static final class GlobalSectionTestThread extends Thread {
71
72
73 private final INIConfiguration config;
74
75
76 private volatile boolean error;
77
78
79
80
81
82
83 public GlobalSectionTestThread(final INIConfiguration conf) {
84 config = conf;
85 }
86
87
88
89
90 @Override
91 public void run() {
92 final int loopCount = 250;
93
94 for (int i = 0; i < loopCount && !error; i++) {
95 try {
96 config.getSection(null);
97 } catch (final IllegalStateException istex) {
98 error = true;
99 }
100 }
101 }
102 }
103
104 private static final String LINE_SEPARATOR = System.lineSeparator();
105
106
107 private static final String INI_DATA = "[section1]" + LINE_SEPARATOR + "var1 = foo" + LINE_SEPARATOR + "var2 = 451" + LINE_SEPARATOR + LINE_SEPARATOR
108 + "[section2]" + LINE_SEPARATOR + "var1 = 123.45" + LINE_SEPARATOR + "var2 = bar" + LINE_SEPARATOR + LINE_SEPARATOR + "[section3]" + LINE_SEPARATOR
109 + "var1 = true" + LINE_SEPARATOR + "interpolated = ${section3.var1}" + LINE_SEPARATOR + "multi = foo" + LINE_SEPARATOR + "multi = bar" + LINE_SEPARATOR
110 + LINE_SEPARATOR;
111
112 private static final String INI_DATA2 = "[section4]" + LINE_SEPARATOR + "var1 = \"quoted value\"" + LINE_SEPARATOR
113 + "var2 = \"quoted value\\nwith \\\"quotes\\\"\"" + LINE_SEPARATOR + "var3 = 123 ; comment" + LINE_SEPARATOR + "var4 = \"1;2;3\" ; comment"
114 + LINE_SEPARATOR + "var5 = '\\'quoted\\' \"value\"' ; comment" + LINE_SEPARATOR + "var6 = \"\"" + LINE_SEPARATOR;
115
116 private static final String INI_DATA3 = "[section5]" + LINE_SEPARATOR + "multiLine = one \\" + LINE_SEPARATOR + " two \\" + LINE_SEPARATOR
117 + " three" + LINE_SEPARATOR + "singleLine = C:\\Temp\\" + LINE_SEPARATOR + "multiQuoted = one \\" + LINE_SEPARATOR + "\" two \" \\" + LINE_SEPARATOR
118 + " three" + LINE_SEPARATOR + "multiComment = one \\ ; a comment" + LINE_SEPARATOR + "two" + LINE_SEPARATOR
119 + "multiQuotedComment = \" one \" \\ ; comment" + LINE_SEPARATOR + "two" + LINE_SEPARATOR + "noFirstLine = \\" + LINE_SEPARATOR + " line 2"
120 + LINE_SEPARATOR + "continueNoLine = one \\" + LINE_SEPARATOR;
121
122 private static final String INI_DATA4 = "[section6]" + LINE_SEPARATOR + "key1{0}value1" + LINE_SEPARATOR + "key2{0}value2" + LINE_SEPARATOR + LINE_SEPARATOR
123 + "[section7]" + LINE_SEPARATOR + "key3{0}value3" + LINE_SEPARATOR;
124
125 private static final String INI_DATA5 = "[section4]" + LINE_SEPARATOR + "var1 = \"quoted value\"" + LINE_SEPARATOR
126 + "var2 = \"quoted value\\nwith \\\"quotes\\\"\"" + LINE_SEPARATOR + "var3 = 123 # comment" + LINE_SEPARATOR + "var4 = \"1#2;3\" # comment"
127 + LINE_SEPARATOR + "var5 = '\\'quoted\\' \"value\"' # comment" + LINE_SEPARATOR + "var6 = \"\"" + LINE_SEPARATOR;
128
129
130 private static final String INI_DATA6 = "[section1]; main section" + LINE_SEPARATOR + "var1 = foo" + LINE_SEPARATOR + LINE_SEPARATOR
131 + "[section11] ; sub-section related to [section1]" + LINE_SEPARATOR + "var1 = 123.45" + LINE_SEPARATOR;
132
133
134 private static final String INI_DATA7 = "[section1]# main section" + LINE_SEPARATOR + "var1 = foo" + LINE_SEPARATOR + LINE_SEPARATOR
135 + "[section11] # sub-section related to [section1]" + LINE_SEPARATOR + "var1 = 123.45" + LINE_SEPARATOR;
136
137 private static final String INI_DATA_SEPARATORS = "[section]" + LINE_SEPARATOR + "var1 = value1" + LINE_SEPARATOR + "var2 : value2" + LINE_SEPARATOR
138 + "var3=value3" + LINE_SEPARATOR + "var4:value4" + LINE_SEPARATOR + "var5 : value=5" + LINE_SEPARATOR + "var:6=value" + LINE_SEPARATOR
139 + "var:7=\"value7\"" + LINE_SEPARATOR + "var:8 = \"value8\"" + LINE_SEPARATOR;
140
141
142 private static final String INI_DATA_GLOBAL_ONLY = "globalVar = testGlobal" + LINE_SEPARATOR + LINE_SEPARATOR;
143
144
145 private static final String INI_DATA_GLOBAL = INI_DATA_GLOBAL_ONLY + INI_DATA;
146
147
148
149
150
151
152
153
154 private static void load(final INIConfiguration instance, final String data) throws ConfigurationException {
155 try (StringReader reader = new StringReader(data)) {
156 instance.read(reader);
157 } catch (final IOException e) {
158 throw new ConfigurationException(e);
159 }
160 }
161
162 private static Stream<Arguments> provideSectionsWithComments() {
163 return Stream.of(
164 Arguments.of(INI_DATA6, false, new String[]{null, "section11] ; sub-section related to [section1"}),
165 Arguments.of(INI_DATA7, false, new String[]{null, "section11] # sub-section related to [section1"}),
166 Arguments.of(INI_DATA6, true, new String[]{"section1", "section11"}),
167 Arguments.of(INI_DATA7, true, new String[]{"section1", "section11"})
168 );
169 }
170
171 private static Stream<Arguments> provideValuesWithComments() {
172 return Stream.of(
173 Arguments.of(INI_DATA2, "section4.var3", "123"),
174 Arguments.of(INI_DATA2, "section4.var4", "1;2;3"),
175 Arguments.of(INI_DATA2, "section4.var5", "'quoted' \"value\""),
176 Arguments.of(INI_DATA5, "section4.var3", "123"),
177 Arguments.of(INI_DATA5, "section4.var4", "1#2;3"),
178 Arguments.of(INI_DATA5, "section4.var5", "'quoted' \"value\"")
179 );
180 }
181
182
183
184
185
186
187
188
189
190 private static String saveToString(final INIConfiguration config) throws ConfigurationException {
191 final StringWriter writer = new StringWriter();
192 try {
193 config.write(writer);
194 } catch (final IOException e) {
195 throw new ConfigurationException(e);
196 }
197 return writer.toString();
198 }
199
200
201
202
203
204
205
206
207 private static INIConfiguration setUpConfig(final String data) throws ConfigurationException {
208 return setUpConfig(data, false);
209 }
210
211
212
213
214
215
216
217
218
219 private static INIConfiguration setUpConfig(final String data, final boolean inLineCommentsAllowed) throws ConfigurationException {
220
221 final INIConfiguration instance = INIConfiguration.builder()
222 .setSectionInLineCommentsAllowed(inLineCommentsAllowed)
223 .build();
224
225 instance.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
226 load(instance, data);
227 return instance;
228 }
229
230
231 @TempDir
232 public File tempFolder;
233
234
235
236
237
238
239 private void checkContent(final INIConfiguration instance) {
240 assertEquals("foo", instance.getString("section1.var1"));
241 assertEquals(451, instance.getInt("section1.var2"));
242 assertEquals(123.45, instance.getDouble("section2.var1"), .001);
243 assertEquals("bar", instance.getString("section2.var2"));
244 assertTrue(instance.getBoolean("section3.var1"));
245 assertEquals(new HashSet<>(Arrays.asList("section1", "section2", "section3")), instance.getSections());
246 }
247
248
249
250
251
252
253
254 private void checkLoad(final String data) throws ConfigurationException {
255 final INIConfiguration instance = setUpConfig(data);
256 checkContent(instance);
257 }
258
259
260
261
262
263
264
265
266 private void checkSave(final String content) throws ConfigurationException {
267 final INIConfiguration config = setUpConfig(content);
268 final String sOutput = saveToString(config);
269 assertEquals(content, sOutput);
270 }
271
272
273
274
275
276
277
278 private void checkSectionNames(final INIConfiguration config, final String[] expected) {
279 final Set<String> sectionNames = config.getSections();
280 assertEquals(new HashSet<>(Arrays.asList(expected)), sectionNames);
281 }
282
283
284
285
286
287
288
289
290 private INIConfiguration checkSectionNames(final String data, final String[] expected) throws ConfigurationException {
291 final INIConfiguration config = setUpConfig(data);
292 checkSectionNames(config, expected);
293 return config;
294 }
295
296
297
298
299 @Test
300 void testCommentLeadingSeparatorUsedInINIInput() throws Exception {
301 final String inputCommentLeadingSeparator = ";";
302 final String input = "[section]" + LINE_SEPARATOR + "key1=a;b;c" + LINE_SEPARATOR + "key2=a#b#c" + LINE_SEPARATOR + ";key3=value3" + LINE_SEPARATOR
303 + "#key4=value4" + LINE_SEPARATOR;
304
305 final INIConfiguration instance = new FileBasedConfigurationBuilder<>(INIConfiguration.class)
306 .configure(new Parameters().ini().setCommentLeadingCharsUsedInInput(inputCommentLeadingSeparator)).getConfiguration();
307 load(instance, input);
308
309 assertEquals("a;b;c", instance.getString("section.key1"));
310 assertEquals("a#b#c", instance.getString("section.key2"));
311 assertNull(instance.getString("section.;key3"));
312 assertEquals("value4", instance.getString("section.#key4"));
313 }
314
315
316
317
318 @Test
319 void testEmptySection() throws ConfigurationException {
320 final INIConfiguration config = setUpConfig("[]" + LINE_SEPARATOR + "key=value" + LINE_SEPARATOR);
321 final String value = config.getString(" .key");
322 assertEquals("value", value);
323 }
324
325
326
327
328 @Test
329 void testExpressionEngineIgnoringCase() throws ConfigurationException {
330 final DefaultExpressionEngine engine = new DefaultExpressionEngine(DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS, NodeNameMatchers.EQUALS_IGNORE_CASE);
331 final INIConfiguration config = new INIConfiguration();
332 config.setExpressionEngine(engine);
333 load(config, INI_DATA);
334
335 checkContent(config);
336 assertEquals("foo", config.getString("Section1.var1"));
337 assertEquals("foo", config.getString("section1.Var1"));
338 assertEquals("foo", config.getString("SECTION1.VAR1"));
339 }
340
341
342
343
344 @Test
345 void testGetPropertyNoKey() throws ConfigurationException {
346 final String data = INI_DATA2 + LINE_SEPARATOR + "= noKey" + LINE_SEPARATOR;
347 final INIConfiguration config = setUpConfig(data);
348 assertEquals("noKey", config.getString("section4. "));
349 }
350
351
352
353
354 @Test
355 void testGetPropertyNoValue() throws ConfigurationException {
356 final String data = INI_DATA2 + LINE_SEPARATOR + "noValue =" + LINE_SEPARATOR;
357 final INIConfiguration config = setUpConfig(data);
358 assertEquals("", config.getString("section4.noValue"));
359 }
360
361
362
363
364 @Test
365 void testGetSectionConnected() throws ConfigurationException {
366 final INIConfiguration config = setUpConfig(INI_DATA);
367 final HierarchicalConfiguration<ImmutableNode> section = config.getSection("section1");
368 section.setProperty("var1", "foo2");
369 assertEquals("foo2", config.getString("section1.var1"));
370 }
371
372
373
374
375 @Test
376 void testGetSectionDuplicate() {
377 final INIConfiguration config = new INIConfiguration();
378 config.addProperty("section.var1", "value1");
379 config.addProperty("section(-1).var2", "value2");
380 final HierarchicalConfiguration<ImmutableNode> section = config.getSection("section");
381 final Iterator<String> keys = section.getKeys();
382 assertEquals("var1", keys.next());
383 assertFalse(keys.hasNext());
384 }
385
386
387
388
389 @Test
390 void testGetSectionExisting() throws ConfigurationException {
391 final INIConfiguration config = setUpConfig(INI_DATA);
392 final HierarchicalConfiguration<ImmutableNode> section = config.getSection("section1");
393 assertEquals("foo", section.getString("var1"));
394 assertEquals("451", section.getString("var2"));
395 }
396
397
398
399
400 @Test
401 void testGetSectionGloabalMultiThreaded() throws ConfigurationException, InterruptedException {
402 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
403 config.setSynchronizer(new ReadWriteSynchronizer());
404 final int threadCount = 10;
405 final GlobalSectionTestThread[] threads = new GlobalSectionTestThread[threadCount];
406 for (int i = 0; i < threadCount; i++) {
407 threads[i] = new GlobalSectionTestThread(config);
408 threads[i].start();
409 }
410 for (int i = 0; i < threadCount; i++) {
411 threads[i].join();
412 assertFalse(threads[i].error);
413 }
414 }
415
416
417
418
419 @Test
420 void testGetSectionGlobal() throws ConfigurationException {
421 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
422 final HierarchicalConfiguration<ImmutableNode> section = config.getSection(null);
423 assertEquals("testGlobal", section.getString("globalVar"));
424 }
425
426
427
428
429 @Test
430 void testGetSectionGlobalNonExisting() throws ConfigurationException {
431 final INIConfiguration config = setUpConfig(INI_DATA);
432 final HierarchicalConfiguration<ImmutableNode> section = config.getSection(null);
433 assertTrue(section.isEmpty());
434 }
435
436
437
438
439 @Test
440 void testGetSectionMerged() throws ConfigurationException {
441 final String data = INI_DATA + "[section1]" + LINE_SEPARATOR + "var3 = merged" + LINE_SEPARATOR;
442 final INIConfiguration config = setUpConfig(data);
443 final HierarchicalConfiguration<ImmutableNode> section = config.getSection("section1");
444 assertEquals("foo", section.getString("var1"));
445 assertEquals("451", section.getString("var2"));
446 assertEquals("merged", section.getString("var3"));
447 }
448
449
450
451
452 @Test
453 void testGetSectionNonExisting() throws ConfigurationException {
454 final INIConfiguration config = setUpConfig(INI_DATA);
455 final HierarchicalConfiguration<ImmutableNode> section = config.getSection("Non existing section");
456 assertTrue(section.isEmpty());
457 }
458
459
460
461
462 @Test
463 void testGetSectionNonExistingManipulate() throws ConfigurationException, IOException {
464 final INIConfiguration config = setUpConfig(INI_DATA);
465 HierarchicalConfiguration<ImmutableNode> section = config.getSection("newSection");
466 section.addProperty("test", "success");
467 assertEquals("success", config.getString("newSection.test"));
468 final StringWriter writer = new StringWriter();
469 config.write(writer);
470 final INIConfiguration config2 = setUpConfig(writer.toString());
471 section = config2.getSection("newSection");
472 assertEquals("success", section.getString("test"));
473 }
474
475
476
477
478 @Test
479 void testGetSections() {
480 final INIConfiguration instance = new INIConfiguration();
481 instance.addProperty("test1.foo", "bar");
482 instance.addProperty("test2.foo", "abc");
483 final Set<String> expResult = new HashSet<>();
484 expResult.add("test1");
485 expResult.add("test2");
486 final Set<String> result = instance.getSections();
487 assertEquals(expResult, result);
488 }
489
490
491
492
493 @Test
494 void testGetSectionsAdded() throws ConfigurationException {
495 final INIConfiguration config = setUpConfig(INI_DATA2);
496 config.addProperty("section5.test", Boolean.TRUE);
497 checkSectionNames(config, new String[] {"section4", "section5"});
498 }
499
500
501
502
503
504 @Test
505 void testGetSectionsDottedVar() throws ConfigurationException {
506 final String data = "dotted.var = 1" + LINE_SEPARATOR + INI_DATA_GLOBAL;
507 final INIConfiguration config = checkSectionNames(data, new String[] {null, "section1", "section2", "section3"});
508 assertEquals(1, config.getInt("dotted..var"));
509 }
510
511
512
513
514 @Test
515 void testGetSectionsGlobalOnly() throws ConfigurationException {
516 checkSectionNames(INI_DATA_GLOBAL_ONLY, new String[] {null});
517 }
518
519
520
521
522 @Test
523 void testGetSectionsNoGlobal() throws ConfigurationException {
524 checkSectionNames(INI_DATA, new String[] {"section1", "section2", "section3"});
525 }
526
527
528
529
530 @Test
531 void testGetSectionsSynchronized() throws ConfigurationException {
532 final INIConfiguration config = setUpConfig(INI_DATA);
533 final SynchronizerTestImpl sync = new SynchronizerTestImpl();
534 config.setSynchronizer(sync);
535 assertFalse(config.getSections().isEmpty());
536 sync.verify(Methods.BEGIN_READ, Methods.END_READ);
537 }
538
539
540
541
542 @Test
543 void testGetSectionsWithGlobal() throws ConfigurationException {
544 checkSectionNames(INI_DATA_GLOBAL, new String[] {null, "section1", "section2", "section3"});
545 }
546
547
548
549
550 @ParameterizedTest
551 @MethodSource("provideSectionsWithComments")
552 void testGetSectionsWithInLineComment(final String source, final boolean allowComments, final String[] results) throws ConfigurationException {
553 final INIConfiguration config = setUpConfig(source, allowComments);
554 checkSectionNames(config, results);
555 }
556
557
558
559
560 @Test
561 void testGlobalProperty() throws ConfigurationException {
562 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
563 assertEquals("testGlobal", config.getString("globalVar"));
564 }
565
566
567
568
569 @Test
570 void testGlobalSectionConnected() throws ConfigurationException {
571 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
572 final HierarchicalConfiguration<ImmutableNode> sub = config.getSection(null);
573 config.setProperty("globalVar", "changed");
574 assertEquals("changed", sub.getString("globalVar"));
575 }
576
577
578
579
580 @Test
581 void testGlobalSectionNodeHandlerGetChildByIndex() throws ConfigurationException {
582 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
583 final SubnodeConfiguration sub = config.getSection(null);
584 final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler();
585 final ImmutableNode rootNode = handler.getRootNode();
586 final ImmutableNode child = handler.getChild(rootNode, 0);
587 assertEquals("globalVar", child.getNodeName());
588 assertThrows(IndexOutOfBoundsException.class, () -> handler.getChild(rootNode, 1));
589 }
590
591
592
593
594 @Test
595 void testGlobalSectionNodeHandlerGetChildrenByName() throws ConfigurationException {
596 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
597 final SubnodeConfiguration sub = config.getSection(null);
598 final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler();
599 assertTrue(handler.getChildren(sub.getModel().getNodeHandler().getRootNode(), "section1").isEmpty());
600 }
601
602
603
604
605 @Test
606 void testGlobalSectionNodeHandlerGetChildrenCount() throws ConfigurationException {
607 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
608 final SubnodeConfiguration sub = config.getSection(null);
609 final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler();
610 assertEquals(1, handler.getChildrenCount(handler.getRootNode(), null));
611 }
612
613
614
615
616 @Test
617 void testGlobalSectionNodeHandlerIndexOfChild() throws ConfigurationException {
618 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
619 final SubnodeConfiguration sub = config.getSection(null);
620 final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler();
621 final List<ImmutableNode> children = handler.getRootNode().getChildren();
622 assertEquals(0, handler.indexOfChild(handler.getRootNode(), children.get(0)));
623 assertEquals(-1, handler.indexOfChild(handler.getRootNode(), children.get(1)));
624 }
625
626
627
628
629 @Test
630 void testIsCommentLine() {
631 final INIConfiguration instance = new INIConfiguration();
632 assertTrue(instance.isCommentLine("#comment1"));
633 assertTrue(instance.isCommentLine(";comment1"));
634 assertFalse(instance.isCommentLine("nocomment=true"));
635 assertFalse(instance.isCommentLine(null));
636 }
637
638
639
640
641 @Test
642 void testIsSectionLine() {
643 final INIConfiguration instance = new INIConfiguration();
644 assertTrue(instance.isSectionLine("[section]"));
645 assertFalse(instance.isSectionLine("nosection=true"));
646 assertFalse(instance.isSectionLine(null));
647 }
648
649
650
651
652 @Test
653 void testKeysOfGlobalSection() throws ConfigurationException {
654 final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
655 final HierarchicalConfiguration<ImmutableNode> sub = config.getSection(null);
656 final Iterator<String> keys = sub.getKeys();
657 assertEquals("globalVar", keys.next());
658 if (keys.hasNext()) {
659 final StringBuilder buf = new StringBuilder();
660 do {
661 buf.append(keys.next()).append(' ');
662 } while (keys.hasNext());
663 fail("Got additional keys: " + buf);
664 }
665 }
666
667
668
669
670 @Test
671 void testLineContinuation() throws ConfigurationException {
672 final INIConfiguration config = setUpConfig(INI_DATA3);
673 assertEquals("one" + LINE_SEPARATOR + "two" + LINE_SEPARATOR + "three", config.getString("section5.multiLine"));
674 }
675
676
677
678
679 @Test
680 void testLineContinuationAtEnd() throws ConfigurationException {
681 final INIConfiguration config = setUpConfig(INI_DATA3);
682 assertEquals("one" + LINE_SEPARATOR, config.getString("section5.continueNoLine"));
683 }
684
685
686
687
688 @Test
689 void testLineContinuationComment() throws ConfigurationException {
690 final INIConfiguration config = setUpConfig(INI_DATA3);
691 assertEquals("one" + LINE_SEPARATOR + "two", config.getString("section5.multiComment"));
692 }
693
694
695
696
697 @Test
698 void testLineContinuationEmptyLine() throws ConfigurationException {
699 final INIConfiguration config = setUpConfig(INI_DATA3);
700 assertEquals(LINE_SEPARATOR + "line 2", config.getString("section5.noFirstLine"));
701 }
702
703
704
705
706 @Test
707 void testLineContinuationNone() throws ConfigurationException {
708 final INIConfiguration config = setUpConfig(INI_DATA3);
709 assertEquals("C:\\Temp\\", config.getString("section5.singleLine"));
710 }
711
712
713
714
715
716 @Test
717 void testLineContinuationQuoted() throws ConfigurationException {
718 final INIConfiguration config = setUpConfig(INI_DATA3);
719 assertEquals("one" + LINE_SEPARATOR + " two " + LINE_SEPARATOR + "three", config.getString("section5.multiQuoted"));
720 }
721
722
723
724
725 @Test
726 void testLineContinuationQuotedComment() throws ConfigurationException {
727 final INIConfiguration config = setUpConfig(INI_DATA3);
728 assertEquals(" one " + LINE_SEPARATOR + "two", config.getString("section5.multiQuotedComment"));
729 }
730
731
732
733
734 @Test
735 void testListDelimiterHandling() throws ConfigurationException {
736 final INIConfiguration config = new INIConfiguration();
737 config.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
738 config.addProperty("list", "a,b,c");
739 config.addProperty("listesc", "3\\,1415");
740 final String output = saveToString(config);
741 final INIConfiguration config2 = setUpConfig(output);
742 assertEquals(Arrays.asList("a", "b", "c"), config2.getList("list"));
743 assertEquals("3,1415", config2.getString("listesc"));
744 }
745
746
747
748
749 @Test
750 void testListDelimiterHandlingInList() throws ConfigurationException {
751 final String data = INI_DATA + "[sectest]" + LINE_SEPARATOR + "list = 3\\,1415,pi,\\\\Test\\,5" + LINE_SEPARATOR;
752 final INIConfiguration config = setUpConfig(data);
753 final INIConfiguration config2 = setUpConfig(saveToString(config));
754 final List<Object> list = config2.getList("sectest.list");
755 assertEquals(Arrays.asList("3,1415", "pi", "\\Test,5"), list);
756 }
757
758
759
760
761 @Test
762 void testListParsingDisabled() throws ConfigurationException {
763 final INIConfiguration config = new INIConfiguration();
764 load(config, "[test]" + LINE_SEPARATOR + "nolist=1,2,3");
765 assertEquals("1,2,3", config.getString("test.nolist"));
766 }
767
768
769
770
771 @Test
772 void testLoad() throws Exception {
773 checkLoad(INI_DATA);
774 }
775
776
777
778
779 @Test
780 void testLoadAlternativeSeparator() throws Exception {
781 checkLoad(INI_DATA.replace('=', ':'));
782 }
783
784
785
786
787 @Test
788 void testLoadFromBuilder() throws ConfigurationException, IOException {
789 final File file = writeTestFile(INI_DATA);
790 final FileBasedConfigurationBuilder<INIConfiguration> builder = new FileBasedConfigurationBuilder<>(INIConfiguration.class);
791 builder.configure(new FileBasedBuilderParametersImpl().setFile(file));
792 final INIConfiguration config = builder.getConfiguration();
793 checkContent(config);
794 }
795
796
797
798
799 @Test
800 void testMergeDuplicateSection() throws ConfigurationException, IOException {
801
802 final String data =
803 "[section]\nvar1 = sec1\n\n"
804 + "[section]\nvar2 = sec2\n";
805
806 final INIConfiguration config = setUpConfig(data);
807 assertEquals("sec1", config.getString("section.var1"));
808 assertEquals("sec2", config.getString("section.var2"));
809 final HierarchicalConfiguration<ImmutableNode> sub = config.getSection("section");
810 assertEquals("sec1", sub.getString("var1"));
811 assertEquals("sec2", sub.getString("var2"));
812 final StringWriter writer = new StringWriter();
813 config.write(writer);
814 final String content = writer.toString();
815 final int pos = content.indexOf("[section]");
816 assertTrue(pos >= 0);
817 assertTrue(content.indexOf("[section]", pos + 1) < 0);
818 }
819
820
821
822
823 @Test
824 void testMultipleSeparators() throws ConfigurationException {
825 final INIConfiguration config = setUpConfig(INI_DATA_SEPARATORS);
826 assertEquals("value=5", config.getString("section.var5"));
827 assertEquals("6=value", config.getString("section.var"));
828 }
829
830
831
832
833 @Test
834 void testMultipleSeparatorsQuoted() throws ConfigurationException {
835 final INIConfiguration config = setUpConfig(INI_DATA_SEPARATORS);
836 assertEquals("value7", config.getString("section.var:7"));
837 assertEquals("value8", config.getString("section.var:8"));
838 }
839
840
841
842
843
844 @Test
845 void testPropertyWithDelimiter() throws ConfigurationException {
846 final String data = INI_DATA + "key.dot = dotValue";
847 final INIConfiguration conf = new INIConfiguration();
848 load(conf, data);
849 assertEquals("dotValue", conf.getString("section3.key..dot"));
850 final String output = saveToString(conf);
851 assertTrue(output.contains("key.dot = dotValue"));
852 }
853
854 @Test
855 void testQuotedValue() throws Exception {
856 final INIConfiguration config = setUpConfig(INI_DATA2);
857 assertEquals("quoted value", config.getString("section4.var1"));
858 }
859
860
861
862
863 @Test
864 void testQuotedValueEmpty() throws ConfigurationException {
865 final INIConfiguration config = setUpConfig(INI_DATA2);
866 assertEquals("", config.getString("section4.var6"));
867 }
868
869 @Test
870 void testQuotedValueWithComment() throws Exception {
871 final INIConfiguration config = setUpConfig(INI_DATA2);
872 assertEquals("1;2;3", config.getString("section4.var4"));
873 }
874
875 @Test
876 void testQuotedValueWithQuotes() throws Exception {
877 final INIConfiguration config = setUpConfig(INI_DATA2);
878 assertEquals("quoted value\\nwith \"quotes\"", config.getString("section4.var2"));
879 }
880
881 @Test
882 void testQuotedValueWithSingleQuotes() throws Exception {
883 final INIConfiguration config = setUpConfig(INI_DATA2);
884 assertEquals("'quoted' \"value\"", config.getString("section4.var5"));
885 }
886
887
888
889
890 @Test
891 void testQuotedValueWithWhitespace() throws Exception {
892 final String content = "CmdPrompt = \" [test@cmd ~]$ \"";
893 final INIConfiguration config = setUpConfig(content);
894 assertEquals(" [test@cmd ~]$ ", config.getString("CmdPrompt"));
895 }
896
897
898
899
900 @Test
901 void testQuotedValueWithWhitespaceAndComment() throws Exception {
902 final String content = "CmdPrompt = \" [test@cmd ~]$ \" ; a comment";
903 final INIConfiguration config = setUpConfig(content);
904 assertEquals(" [test@cmd ~]$ ", config.getString("CmdPrompt"));
905 }
906
907
908
909
910 @Test
911 void testSave() throws Exception {
912 final Writer writer = new StringWriter();
913 final INIConfiguration instance = new INIConfiguration();
914 instance.addProperty("section1.var1", "foo");
915 instance.addProperty("section1.var2", "451");
916 instance.addProperty("section2.var1", "123.45");
917 instance.addProperty("section2.var2", "bar");
918 instance.addProperty("section3.var1", "true");
919 instance.addProperty("section3.interpolated", "${section3.var1}");
920 instance.addProperty("section3.multi", "foo");
921 instance.addProperty("section3.multi", "bar");
922 instance.write(writer);
923
924 assertEquals(INI_DATA, writer.toString());
925 }
926
927
928
929
930 @Test
931 void testSaveClearedSection() throws ConfigurationException, IOException {
932 final String data = "[section]\ntest = failed\n";
933 final INIConfiguration config = setUpConfig(data);
934 SubnodeConfiguration sub = config.getSection("section");
935 assertFalse(sub.isEmpty());
936 sub.clear();
937 sub.close();
938 sub = config.getSection("section");
939 sub.setProperty("test", "success");
940 final StringWriter writer = new StringWriter();
941 config.write(writer);
942 final HierarchicalConfiguration<?> config2 = setUpConfig(writer.toString());
943 assertEquals("success", config2.getString("section.test"));
944 }
945
946
947
948
949
950 @Test
951 void testSaveKeysWithDelimiters() throws ConfigurationException, IOException {
952 INIConfiguration conf = new INIConfiguration();
953 final String section = "Section..with..dots";
954 conf.addProperty(section + ".test1", "test1");
955 conf.addProperty(section + ".test2", "test2");
956 final StringWriter writer = new StringWriter();
957 conf.write(writer);
958 conf = new INIConfiguration();
959 conf.read(new StringReader(writer.toString()));
960 assertEquals("test1", conf.getString(section + ".test1"));
961 assertEquals("test2", conf.getString(section + ".test2"));
962 }
963
964
965
966
967 @Test
968 void testSaveWithDelimiterParsingDisabled() throws ConfigurationException {
969 final INIConfiguration config = new INIConfiguration();
970 final String data = INI_DATA.substring(0, INI_DATA.length() - LINE_SEPARATOR.length()) + "nolist = 1,2, 3";
971 load(config, data);
972 assertEquals("1,2, 3", config.getString("section3.nolist"));
973 final String content = saveToString(config);
974 final INIConfiguration config2 = new INIConfiguration();
975 load(config2, content);
976 assertEquals("1,2, 3", config2.getString("section3.nolist"));
977 }
978
979
980
981
982 @Test
983 void testSaveWithGlobalSection() throws ConfigurationException {
984 checkSave(INI_DATA_GLOBAL);
985 }
986
987
988
989
990 @Test
991 void testSaveWithOnlyGlobalSection() throws ConfigurationException {
992 checkSave(INI_DATA_GLOBAL_ONLY);
993 }
994
995
996
997
998 @Test
999 void testSeparators() throws ConfigurationException {
1000 final INIConfiguration config = setUpConfig(INI_DATA_SEPARATORS);
1001 for (int i = 1; i <= 4; i++) {
1002 assertEquals("value" + i, config.getString("section.var" + i));
1003 }
1004 }
1005
1006
1007
1008
1009 @Test
1010 void testSeparatorUsedInINIInput() throws Exception {
1011 final String inputSeparator = "=";
1012 final String input = "[section]" + LINE_SEPARATOR + "k1:v1$key1=value1" + LINE_SEPARATOR + "k1:v1,k2:v2$key2=value2" + LINE_SEPARATOR + "key3:value3"
1013 + LINE_SEPARATOR + "key4 = value4" + LINE_SEPARATOR;
1014
1015 final INIConfiguration instance = new FileBasedConfigurationBuilder<>(INIConfiguration.class)
1016 .configure(new Parameters().ini().setSeparatorUsedInInput(inputSeparator)).getConfiguration();
1017 load(instance, input);
1018
1019 assertEquals("value1", instance.getString("section.k1:v1$key1"));
1020 assertEquals("value2", instance.getString("section.k1:v1,k2:v2$key2"));
1021 assertEquals("", instance.getString("section.key3:value3"));
1022 assertEquals("value4", instance.getString("section.key4").trim());
1023 }
1024
1025
1026
1027
1028 @Test
1029 void testSeparatorUsedInINIOutput() throws Exception {
1030 final String outputSeparator = ": ";
1031 final String input = MessageFormat.format(INI_DATA4, "=").trim();
1032 final String expectedOutput = MessageFormat.format(INI_DATA4, outputSeparator).trim();
1033
1034 final INIConfiguration instance = new FileBasedConfigurationBuilder<>(INIConfiguration.class)
1035 .configure(new Parameters().ini().setSeparatorUsedInOutput(outputSeparator)).getConfiguration();
1036 load(instance, input);
1037
1038 final Writer writer = new StringWriter();
1039 instance.write(writer);
1040 final String result = writer.toString().trim();
1041
1042 assertEquals(expectedOutput, result);
1043 }
1044
1045
1046
1047
1048 @ParameterizedTest
1049 @MethodSource("provideValuesWithComments")
1050 void testValueWithComment(final String source, final String key, final String value) throws Exception {
1051 final INIConfiguration config = setUpConfig(source);
1052 assertEquals(value, config.getString(key));
1053 }
1054
1055
1056
1057
1058 @Test
1059 void testValueWithDelimiters() throws ConfigurationException {
1060 final INIConfiguration config = setUpConfig("[test]" + LINE_SEPARATOR + "list=1,2,3" + LINE_SEPARATOR);
1061 final List<Object> list = config.getList("test.list");
1062 assertEquals(Arrays.asList("1", "2", "3"), list);
1063 }
1064
1065
1066
1067
1068
1069 @Test
1070 void testValueWithSemicolon() throws ConfigurationException {
1071 final String path = "C:\\Program Files\\jar\\manage.jar;C:\\Program Files\\jar\\guiLauncher.jar";
1072 final String content = "[Environment]" + LINE_SEPARATOR + "Application Type=any" + LINE_SEPARATOR + "Class Path=" + path + " ;comment" + LINE_SEPARATOR
1073 + "Path=" + path + "\t; another comment";
1074 final INIConfiguration config = setUpConfig(content);
1075 assertEquals(path, config.getString("Environment.Class Path"));
1076 assertEquals(path, config.getString("Environment.Path"));
1077 }
1078
1079
1080
1081
1082 @Test
1083 void testWriteEmptySection() throws ConfigurationException, IOException {
1084 final String section = "[EmptySection]";
1085 final INIConfiguration config = setUpConfig(section);
1086 assertEquals(Collections.singleton("EmptySection"), config.getSections());
1087
1088 final StringWriter writer = new StringWriter();
1089 config.write(writer);
1090 assertEquals(section + LINE_SEPARATOR + LINE_SEPARATOR, writer.toString());
1091 }
1092
1093 @Test
1094 void testWriteValueWithCommentChar() throws Exception {
1095 final INIConfiguration config = new INIConfiguration();
1096 config.setProperty("section.key1", "1;2;3");
1097
1098 final StringWriter writer = new StringWriter();
1099 config.write(writer);
1100
1101 final INIConfiguration config2 = new INIConfiguration();
1102 config2.read(new StringReader(writer.toString()));
1103
1104 assertEquals("1;2;3", config2.getString("section.key1"));
1105 }
1106
1107
1108
1109
1110
1111
1112
1113
1114 private File writeTestFile(final String content) throws IOException {
1115 final File file = newFile(tempFolder);
1116 try (PrintWriter out = new PrintWriter(new FileWriter(file))) {
1117 out.println(content);
1118 }
1119 return file;
1120 }
1121 }