1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.configuration;
19
20 import java.io.File;
21 import java.io.FileWriter;
22 import java.io.IOException;
23 import java.io.PrintWriter;
24 import java.io.StringReader;
25 import java.io.StringWriter;
26 import java.io.Writer;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.Set;
30
31 import junit.framework.TestCase;
32
33 /***
34 * Test class for HierarchicalINIConfiguration.
35 *
36 * @author <a
37 * href="http://commons.apache.org/configuration/team-list.html">Commons
38 * Configuration team</a>
39 * @version $Id: TestHierarchicalINIConfiguration.java 719869 2008-11-22 16:57:36Z oheger $
40 */
41 public class TestHierarchicalINIConfiguration extends TestCase
42 {
43 private static String LINE_SEPARATOR = System.getProperty("line.separator");
44
45 /*** Constant for the content of an ini file. */
46 private static final String INI_DATA = "[section1]" + LINE_SEPARATOR
47 + "var1 = foo" + LINE_SEPARATOR + "var2 = 451" + LINE_SEPARATOR
48 + LINE_SEPARATOR + "[section2]" + LINE_SEPARATOR + "var1 = 123.45"
49 + LINE_SEPARATOR + "var2 = bar" + LINE_SEPARATOR + LINE_SEPARATOR
50 + "[section3]" + LINE_SEPARATOR + "var1 = true" + LINE_SEPARATOR
51 + "interpolated = ${section3.var1}" + LINE_SEPARATOR
52 + "multi = foo" + LINE_SEPARATOR + "multi = bar" + LINE_SEPARATOR
53 + LINE_SEPARATOR;
54
55 private static final String INI_DATA2 = "[section4]" + LINE_SEPARATOR
56 + "var1 = \"quoted value\"" + LINE_SEPARATOR
57 + "var2 = \"quoted value//nwith //\"quotes//\"\"" + LINE_SEPARATOR
58 + "var3 = 123 ; comment" + LINE_SEPARATOR
59 + "var4 = \"1;2;3\" ; comment" + LINE_SEPARATOR
60 + "var5 = '//'quoted//' \"value\"' ; comment" + LINE_SEPARATOR
61 + "var6 = \"\"" + LINE_SEPARATOR;
62
63 private static final String INI_DATA3 = "[section5]" + LINE_SEPARATOR
64 + "multiLine = one //" + LINE_SEPARATOR
65 + " two //" + LINE_SEPARATOR
66 + " three" + LINE_SEPARATOR
67 + "singleLine = C://Temp//" + LINE_SEPARATOR
68 + "multiQuoted = one //" + LINE_SEPARATOR
69 + "\" two \" //" + LINE_SEPARATOR
70 + " three" + LINE_SEPARATOR
71 + "multiComment = one // ; a comment" + LINE_SEPARATOR
72 + "two" + LINE_SEPARATOR
73 + "multiQuotedComment = \" one \" // ; comment" + LINE_SEPARATOR
74 + "two" + LINE_SEPARATOR
75 + "noFirstLine = //" + LINE_SEPARATOR
76 + " line 2" + LINE_SEPARATOR
77 + "continueNoLine = one //" + LINE_SEPARATOR;
78
79 /*** An ini file with a global section. */
80 private static final String INI_DATA_GLOBAL = "globalVar = testGlobal"
81 + LINE_SEPARATOR + LINE_SEPARATOR + INI_DATA;
82
83 /*** A test ini file. */
84 private static final File TEST_FILE = new File("target/test.ini");
85
86 protected void tearDown() throws Exception
87 {
88 if (TEST_FILE.exists())
89 {
90 assertTrue("Cannot remove test file: " + TEST_FILE, TEST_FILE
91 .delete());
92 }
93
94 super.tearDown();
95 }
96
97 /***
98 * Creates a HierarchicalINIConfiguration object that is initialized from
99 * the given data.
100 *
101 * @param data the data of the configuration (an ini file as string)
102 * @return the initialized configuration
103 * @throws ConfigurationException if an error occurs
104 */
105 private static HierarchicalINIConfiguration setUpConfig(String data)
106 throws ConfigurationException
107 {
108 StringReader reader = new StringReader(data);
109 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration();
110 instance.load(reader);
111 reader.close();
112 return instance;
113 }
114
115 /***
116 * Writes a test ini file.
117 *
118 * @param content the content of the file
119 * @throws IOException if an error occurs
120 */
121 private static void writeTestFile(String content) throws IOException
122 {
123 PrintWriter out = new PrintWriter(new FileWriter(TEST_FILE));
124 try
125 {
126 out.println(content);
127 }
128 finally
129 {
130 out.close();
131 }
132 }
133
134 /***
135 * Test of save method, of class {@link HierarchicalINIConfiguration}.
136 */
137 public void testSave() throws Exception
138 {
139 Writer writer = new StringWriter();
140 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration();
141 instance.addProperty("section1.var1", "foo");
142 instance.addProperty("section1.var2", "451");
143 instance.addProperty("section2.var1", "123.45");
144 instance.addProperty("section2.var2", "bar");
145 instance.addProperty("section3.var1", "true");
146 instance.addProperty("section3.interpolated", "${section3.var1}");
147 instance.addProperty("section3.multi", "foo");
148 instance.addProperty("section3.multi", "bar");
149 instance.save(writer);
150
151 assertEquals("Wrong content of ini file", INI_DATA, writer.toString());
152 }
153
154 /***
155 * Tests saving a configuration that contains a global section.
156 */
157 public void testSaveWithGlobalSection() throws ConfigurationException
158 {
159 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
160 StringWriter writer = new StringWriter();
161 config.save(writer);
162 assertEquals("Wrong content of ini file", INI_DATA_GLOBAL, writer
163 .toString());
164 }
165
166 /***
167 * Test of load method, of class {@link HierarchicalINIConfiguration}.
168 */
169 public void testLoad() throws Exception
170 {
171 checkLoad(INI_DATA);
172 }
173
174 /***
175 * Tests the load() method when the alternative value separator is used (a
176 * ':' for '=').
177 */
178 public void testLoadAlternativeSeparator() throws Exception
179 {
180 checkLoad(INI_DATA.replace('=', ':'));
181 }
182
183 /***
184 * Tests loading a configuration from a File.
185 */
186 public void testLoadFile() throws ConfigurationException, IOException
187 {
188 writeTestFile(INI_DATA);
189 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration(
190 TEST_FILE);
191 checkContent(config);
192 }
193
194 /***
195 * Tests loading a configuration from a file name.
196 */
197 public void testLoadFileName() throws ConfigurationException, IOException
198 {
199 writeTestFile(INI_DATA);
200 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration(
201 TEST_FILE.getAbsolutePath());
202 checkContent(config);
203 }
204
205 /***
206 * Tests loading a configuration from a URL.
207 */
208 public void testLoadURL() throws ConfigurationException, IOException
209 {
210 writeTestFile(INI_DATA);
211 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration(
212 TEST_FILE.toURL());
213 checkContent(config);
214 }
215
216 /***
217 * Tests the values of some properties to ensure that the configuration was
218 * correctly loaded.
219 *
220 * @param instance the configuration to check
221 */
222 private void checkContent(HierarchicalINIConfiguration instance)
223 {
224 assertTrue(instance.getString("section1.var1").equals("foo"));
225 assertTrue(instance.getInt("section1.var2") == 451);
226 assertTrue(instance.getDouble("section2.var1") == 123.45);
227 assertTrue(instance.getString("section2.var2").equals("bar"));
228 assertTrue(instance.getBoolean("section3.var1"));
229 assertTrue(instance.getSections().size() == 3);
230 }
231
232 /***
233 * Helper method for testing the load operation. Loads the specified content
234 * into a configuration and then checks some properties.
235 *
236 * @param data the data to load
237 */
238 private void checkLoad(String data) throws ConfigurationException
239 {
240 HierarchicalINIConfiguration instance = setUpConfig(data);
241 checkContent(instance);
242 }
243
244 /***
245 * Test of isCommentLine method, of class
246 * {@link HierarchicalINIConfiguration}.
247 */
248 public void testIsCommentLine()
249 {
250 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration();
251 assertTrue(instance.isCommentLine("#comment1"));
252 assertTrue(instance.isCommentLine(";comment1"));
253 assertFalse(instance.isCommentLine("nocomment=true"));
254 assertFalse(instance.isCommentLine(null));
255 }
256
257 /***
258 * Test of isSectionLine method, of class
259 * {@link HierarchicalINIConfiguration}.
260 */
261 public void testIsSectionLine()
262 {
263 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration();
264 assertTrue(instance.isSectionLine("[section]"));
265 assertFalse(instance.isSectionLine("nosection=true"));
266 assertFalse(instance.isSectionLine(null));
267 }
268
269 /***
270 * Test of getSections method, of class {@link HierarchicalINIConfiguration}
271 * .
272 */
273 public void testGetSections()
274 {
275 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration();
276 instance.addProperty("test1.foo", "bar");
277 instance.addProperty("test2.foo", "abc");
278 Set expResult = new HashSet();
279 expResult.add("test1");
280 expResult.add("test2");
281 Set result = instance.getSections();
282 assertEquals(expResult, result);
283 }
284
285 public void testQuotedValue() throws Exception
286 {
287 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
288 assertEquals("value", "quoted value", config.getString("section4.var1"));
289 }
290
291 public void testQuotedValueWithQuotes() throws Exception
292 {
293 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
294 assertEquals("value", "quoted value//nwith \"quotes\"", config
295 .getString("section4.var2"));
296 }
297
298 public void testValueWithComment() throws Exception
299 {
300 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
301 assertEquals("value", "123", config.getString("section4.var3"));
302 }
303
304 public void testQuotedValueWithComment() throws Exception
305 {
306 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
307 assertEquals("value", "1;2;3", config.getString("section4.var4"));
308 }
309
310 public void testQuotedValueWithSingleQuotes() throws Exception
311 {
312 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
313 assertEquals("value", "'quoted' \"value\"", config
314 .getString("section4.var5"));
315 }
316
317 public void testWriteValueWithCommentChar() throws Exception
318 {
319 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration();
320 config.setProperty("section.key1", "1;2;3");
321
322 StringWriter writer = new StringWriter();
323 config.save(writer);
324
325 HierarchicalINIConfiguration config2 = new HierarchicalINIConfiguration();
326 config2.load(new StringReader(writer.toString()));
327
328 assertEquals("value", "1;2;3", config2.getString("section.key1"));
329 }
330
331 /***
332 * Tests whether whitespace is left unchanged for quoted values.
333 */
334 public void testQuotedValueWithWhitespace() throws Exception
335 {
336 final String content = "CmdPrompt = \" [test@cmd ~]$ \"";
337 HierarchicalINIConfiguration config = setUpConfig(content);
338 assertEquals("Wrong propert value", " [test@cmd ~]$ ", config
339 .getString("CmdPrompt"));
340 }
341
342 /***
343 * Tests a quoted value with space and a comment.
344 */
345 public void testQuotedValueWithWhitespaceAndComment() throws Exception
346 {
347 final String content = "CmdPrompt = \" [test@cmd ~]$ \" ; a comment";
348 HierarchicalINIConfiguration config = setUpConfig(content);
349 assertEquals("Wrong propert value", " [test@cmd ~]$ ", config
350 .getString("CmdPrompt"));
351 }
352
353 /***
354 * Tests an empty quoted value.
355 */
356 public void testQuotedValueEmpty() throws ConfigurationException
357 {
358 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
359 assertEquals("Wrong value for empty property", "", config
360 .getString("section4.var6"));
361 }
362
363 /***
364 * Tests a property that has no value.
365 */
366 public void testGetPropertyNoValue() throws ConfigurationException
367 {
368 final String data = INI_DATA2 + LINE_SEPARATOR + "noValue ="
369 + LINE_SEPARATOR;
370 HierarchicalINIConfiguration config = setUpConfig(data);
371 assertEquals("Wrong value of key", "", config
372 .getString("section4.noValue"));
373 }
374
375 /***
376 * Tests a property that has no key.
377 */
378 public void testGetPropertyNoKey() throws ConfigurationException
379 {
380 final String data = INI_DATA2 + LINE_SEPARATOR + "= noKey"
381 + LINE_SEPARATOR;
382 HierarchicalINIConfiguration config = setUpConfig(data);
383 assertEquals("Cannot find property with no key", "noKey", config
384 .getString("section4. "));
385 }
386
387 /***
388 * Tests reading a property from the global section.
389 */
390 public void testGlobalProperty() throws ConfigurationException
391 {
392 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
393 assertEquals("Wrong value of global property", "testGlobal", config
394 .getString("globalVar"));
395 }
396
397 /***
398 * Tests whether the specified configuration contains exactly the expected
399 * sections.
400 *
401 * @param config the configuration to check
402 * @param expected an array with the expected sections
403 */
404 private void checkSectionNames(HierarchicalINIConfiguration config,
405 String[] expected)
406 {
407 Set sectionNames = config.getSections();
408 Iterator it = sectionNames.iterator();
409 for (int idx = 0; idx < expected.length; idx++)
410 {
411 assertEquals("Wrong section at " + idx, expected[idx], it.next());
412 }
413 assertFalse("Too many sections", it.hasNext());
414 }
415
416 /***
417 * Tests the names of the sections returned by the configuration.
418 *
419 * @param data the data of the ini configuration
420 * @param expected the expected section names
421 * @return the configuration instance
422 */
423 private HierarchicalINIConfiguration checkSectionNames(String data,
424 String[] expected) throws ConfigurationException
425 {
426 HierarchicalINIConfiguration config = setUpConfig(data);
427 checkSectionNames(config, expected);
428 return config;
429 }
430
431 /***
432 * Tests querying the sections if a global section if available.
433 */
434 public void testGetSectionsWithGlobal() throws ConfigurationException
435 {
436 checkSectionNames(INI_DATA_GLOBAL, new String[] {
437 null, "section1", "section2", "section3"
438 });
439 }
440
441 /***
442 * Tests querying the sections if there is no global section.
443 */
444 public void testGetSectionsNoGlobal() throws ConfigurationException
445 {
446 checkSectionNames(INI_DATA, new String[] {
447 "section1", "section2", "section3"
448 });
449 }
450
451 /***
452 * Tests whether variables containing a dot are not misinterpreted as
453 * sections. This test is related to CONFIGURATION-327.
454 */
455 public void testGetSectionsDottedVar() throws ConfigurationException
456 {
457 final String data = "dotted.var = 1" + LINE_SEPARATOR + INI_DATA_GLOBAL;
458 HierarchicalINIConfiguration config = checkSectionNames(data,
459 new String[] {
460 null, "section1", "section2", "section3"
461 });
462 assertEquals("Wrong value of dotted variable", 1, config
463 .getInt("dotted..var"));
464 }
465
466 /***
467 * Tests whether a section added later is also found by getSections().
468 */
469 public void testGetSectionsAdded() throws ConfigurationException
470 {
471 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2);
472 config.addProperty("section5.test", Boolean.TRUE);
473 checkSectionNames(config, new String[] {
474 "section4", "section5"
475 });
476 }
477
478 /***
479 * Tests querying the properties of an existing section.
480 */
481 public void testGetSectionExisting() throws ConfigurationException
482 {
483 HierarchicalINIConfiguration config = setUpConfig(INI_DATA);
484 SubnodeConfiguration section = config.getSection("section1");
485 assertEquals("Wrong value of var1", "foo", section.getString("var1"));
486 assertEquals("Wrong value of var2", "451", section.getString("var2"));
487 }
488
489 /***
490 * Tests querying the properties of a section that was merged from two
491 * sections with the same name.
492 */
493 public void testGetSectionMerged() throws ConfigurationException
494 {
495 final String data = INI_DATA + "[section1]" + LINE_SEPARATOR
496 + "var3 = merged" + LINE_SEPARATOR;
497 HierarchicalINIConfiguration config = setUpConfig(data);
498 SubnodeConfiguration section = config.getSection("section1");
499 assertEquals("Wrong value of var1", "foo", section.getString("var1"));
500 assertEquals("Wrong value of var2", "451", section.getString("var2"));
501 assertEquals("Wrong value of var3", "merged", section.getString("var3"));
502 }
503
504 /***
505 * Tests querying the content of the global section.
506 */
507 public void testGetSectionGlobal() throws ConfigurationException
508 {
509 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
510 SubnodeConfiguration section = config.getSection(null);
511 assertEquals("Wrong value of global variable", "testGlobal", section
512 .getString("globalVar"));
513 }
514
515 /***
516 * Tests querying the content of the global section if there is none.
517 */
518 public void testGetSectionGlobalNonExisting() throws ConfigurationException
519 {
520 HierarchicalINIConfiguration config = setUpConfig(INI_DATA);
521 SubnodeConfiguration section = config.getSection(null);
522 assertTrue("Sub config not empty", section.isEmpty());
523 }
524
525 /***
526 * Tests querying a non existing section.
527 */
528 public void testGetSectionNonExisting() throws ConfigurationException
529 {
530 HierarchicalINIConfiguration config = setUpConfig(INI_DATA);
531 SubnodeConfiguration section = config
532 .getSection("Non existing section");
533 assertTrue("Sub config not empty", section.isEmpty());
534 }
535
536 /***
537 * Tests a property whose value spans multiple lines.
538 */
539 public void testLineContinuation() throws ConfigurationException
540 {
541 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
542 assertEquals("Wrong value", "one" + LINE_SEPARATOR + "two"
543 + LINE_SEPARATOR + "three", config
544 .getString("section5.multiLine"));
545 }
546
547 /***
548 * Tests a property value that ends on a backslash, which is no line
549 * continuation character.
550 */
551 public void testLineContinuationNone() throws ConfigurationException
552 {
553 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
554 assertEquals("Wrong value", "C://Temp//", config
555 .getString("section5.singleLine"));
556 }
557
558 /***
559 * Tests a property whose value spans multiple lines when quoting is
560 * involved. In this case whitespace must not be trimmed.
561 */
562 public void testLineContinuationQuoted() throws ConfigurationException
563 {
564 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
565 assertEquals("Wrong value", "one" + LINE_SEPARATOR + " two "
566 + LINE_SEPARATOR + "three", config
567 .getString("section5.multiQuoted"));
568 }
569
570 /***
571 * Tests a property whose value spans multiple lines with a comment.
572 */
573 public void testLineContinuationComment() throws ConfigurationException
574 {
575 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
576 assertEquals("Wrong value", "one" + LINE_SEPARATOR + "two", config
577 .getString("section5.multiComment"));
578 }
579
580 /***
581 * Tests a property with a quoted value spanning multiple lines and a
582 * comment.
583 */
584 public void testLineContinuationQuotedComment()
585 throws ConfigurationException
586 {
587 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
588 assertEquals("Wrong value", " one " + LINE_SEPARATOR + "two", config
589 .getString("section5.multiQuotedComment"));
590 }
591
592 /***
593 * Tests a multi-line property value with an empty line.
594 */
595 public void testLineContinuationEmptyLine() throws ConfigurationException
596 {
597 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
598 assertEquals("Wrong value", LINE_SEPARATOR + "line 2", config
599 .getString("section5.noFirstLine"));
600 }
601
602 /***
603 * Tests a line continuation at the end of the file.
604 */
605 public void testLineContinuationAtEnd() throws ConfigurationException
606 {
607 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3);
608 assertEquals("Wrong value", "one" + LINE_SEPARATOR, config
609 .getString("section5.continueNoLine"));
610 }
611 }