001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with this 004 * work for additional information regarding copyright ownership. The ASF 005 * licenses this file to You under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations under 015 * the License. 016 */ 017 018 package org.apache.commons.configuration; 019 020 import static org.junit.Assert.assertEquals; 021 import static org.junit.Assert.assertFalse; 022 import static org.junit.Assert.assertTrue; 023 024 import java.io.File; 025 import java.io.FileWriter; 026 import java.io.IOException; 027 import java.io.PrintWriter; 028 import java.io.StringReader; 029 import java.io.StringWriter; 030 import java.io.Writer; 031 import java.util.HashSet; 032 import java.util.Iterator; 033 import java.util.List; 034 import java.util.Set; 035 036 import org.junit.After; 037 import org.junit.Test; 038 039 /** 040 * Test class for HierarchicalINIConfiguration. 041 * 042 * @author <a 043 * href="http://commons.apache.org/configuration/team-list.html">Commons 044 * Configuration team</a> 045 * @version $Id: TestHierarchicalINIConfiguration.java 1234362 2012-01-21 16:59:48Z oheger $ 046 */ 047 public class TestHierarchicalINIConfiguration 048 { 049 private static String LINE_SEPARATOR = System.getProperty("line.separator"); 050 051 /** Constant for the content of an ini file. */ 052 private static final String INI_DATA = "[section1]" + LINE_SEPARATOR 053 + "var1 = foo" + LINE_SEPARATOR + "var2 = 451" + LINE_SEPARATOR 054 + LINE_SEPARATOR + "[section2]" + LINE_SEPARATOR + "var1 = 123.45" 055 + LINE_SEPARATOR + "var2 = bar" + LINE_SEPARATOR + LINE_SEPARATOR 056 + "[section3]" + LINE_SEPARATOR + "var1 = true" + LINE_SEPARATOR 057 + "interpolated = ${section3.var1}" + LINE_SEPARATOR 058 + "multi = foo" + LINE_SEPARATOR + "multi = bar" + LINE_SEPARATOR 059 + LINE_SEPARATOR; 060 061 private static final String INI_DATA2 = "[section4]" + LINE_SEPARATOR 062 + "var1 = \"quoted value\"" + LINE_SEPARATOR 063 + "var2 = \"quoted value\\nwith \\\"quotes\\\"\"" + LINE_SEPARATOR 064 + "var3 = 123 ; comment" + LINE_SEPARATOR 065 + "var4 = \"1;2;3\" ; comment" + LINE_SEPARATOR 066 + "var5 = '\\'quoted\\' \"value\"' ; comment" + LINE_SEPARATOR 067 + "var6 = \"\"" + LINE_SEPARATOR; 068 069 private static final String INI_DATA3 = "[section5]" + LINE_SEPARATOR 070 + "multiLine = one \\" + LINE_SEPARATOR 071 + " two \\" + LINE_SEPARATOR 072 + " three" + LINE_SEPARATOR 073 + "singleLine = C:\\Temp\\" + LINE_SEPARATOR 074 + "multiQuoted = one \\" + LINE_SEPARATOR 075 + "\" two \" \\" + LINE_SEPARATOR 076 + " three" + LINE_SEPARATOR 077 + "multiComment = one \\ ; a comment" + LINE_SEPARATOR 078 + "two" + LINE_SEPARATOR 079 + "multiQuotedComment = \" one \" \\ ; comment" + LINE_SEPARATOR 080 + "two" + LINE_SEPARATOR 081 + "noFirstLine = \\" + LINE_SEPARATOR 082 + " line 2" + LINE_SEPARATOR 083 + "continueNoLine = one \\" + LINE_SEPARATOR; 084 085 private static final String INI_DATA_SEPARATORS = "[section]" 086 + LINE_SEPARATOR + "var1 = value1" + LINE_SEPARATOR 087 + "var2 : value2" + LINE_SEPARATOR 088 + "var3=value3" + LINE_SEPARATOR 089 + "var4:value4" + LINE_SEPARATOR 090 + "var5 : value=5" + LINE_SEPARATOR 091 + "var:6=value" + LINE_SEPARATOR 092 + "var:7=\"value7\"" + LINE_SEPARATOR 093 + "var:8 = \"value8\"" + LINE_SEPARATOR; 094 095 /** An ini file that contains only a property in the global section. */ 096 private static final String INI_DATA_GLOBAL_ONLY = "globalVar = testGlobal" 097 + LINE_SEPARATOR + LINE_SEPARATOR; 098 099 /** An ini file with a global section. */ 100 private static final String INI_DATA_GLOBAL = INI_DATA_GLOBAL_ONLY 101 + INI_DATA; 102 103 /** A test ini file. */ 104 private static final File TEST_FILE = new File("target/test.ini"); 105 106 @After 107 public void tearDown() throws Exception 108 { 109 if (TEST_FILE.exists()) 110 { 111 assertTrue("Cannot remove test file: " + TEST_FILE, TEST_FILE 112 .delete()); 113 } 114 } 115 116 /** 117 * Creates a HierarchicalINIConfiguration object that is initialized from 118 * the given data. 119 * 120 * @param data the data of the configuration (an ini file as string) 121 * @return the initialized configuration 122 * @throws ConfigurationException if an error occurs 123 */ 124 private static HierarchicalINIConfiguration setUpConfig(String data) 125 throws ConfigurationException 126 { 127 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration(); 128 load(instance, data); 129 return instance; 130 } 131 132 /** 133 * Loads the specified content into the given configuration instance. 134 * 135 * @param instance the configuration 136 * @param data the data to be loaded 137 * @throws ConfigurationException if an error occurs 138 */ 139 private static void load(HierarchicalINIConfiguration instance, String data) 140 throws ConfigurationException 141 { 142 StringReader reader = new StringReader(data); 143 instance.load(reader); 144 reader.close(); 145 } 146 147 /** 148 * Writes a test ini file. 149 * 150 * @param content the content of the file 151 * @throws IOException if an error occurs 152 */ 153 private static void writeTestFile(String content) throws IOException 154 { 155 PrintWriter out = new PrintWriter(new FileWriter(TEST_FILE)); 156 try 157 { 158 out.println(content); 159 } 160 finally 161 { 162 out.close(); 163 } 164 } 165 166 /** 167 * Test of save method, of class {@link HierarchicalINIConfiguration}. 168 */ 169 @Test 170 public void testSave() throws Exception 171 { 172 Writer writer = new StringWriter(); 173 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration(); 174 instance.addProperty("section1.var1", "foo"); 175 instance.addProperty("section1.var2", "451"); 176 instance.addProperty("section2.var1", "123.45"); 177 instance.addProperty("section2.var2", "bar"); 178 instance.addProperty("section3.var1", "true"); 179 instance.addProperty("section3.interpolated", "${section3.var1}"); 180 instance.addProperty("section3.multi", "foo"); 181 instance.addProperty("section3.multi", "bar"); 182 instance.save(writer); 183 184 assertEquals("Wrong content of ini file", INI_DATA, writer.toString()); 185 } 186 187 /** 188 * Helper method for testing a save operation. This method constructs a 189 * configuration from the specified content string. Then it saves this 190 * configuration and checks whether the result matches the original content. 191 * 192 * @param content the content of the configuration 193 * @throws ConfigurationException if an error occurs 194 */ 195 private void checkSave(String content) throws ConfigurationException 196 { 197 HierarchicalINIConfiguration config = setUpConfig(content); 198 StringWriter writer = new StringWriter(); 199 config.save(writer); 200 assertEquals("Wrong content of ini file", content, writer.toString()); 201 } 202 203 /** 204 * Tests saving a configuration that contains a global section. 205 */ 206 @Test 207 public void testSaveWithGlobalSection() throws ConfigurationException 208 { 209 checkSave(INI_DATA_GLOBAL); 210 } 211 212 /** 213 * Tests whether a configuration that contains only a global section can be 214 * saved correctly. 215 */ 216 @Test 217 public void testSaveWithOnlyGlobalSection() throws ConfigurationException 218 { 219 checkSave(INI_DATA_GLOBAL_ONLY); 220 } 221 222 /** 223 * Test of load method, of class {@link HierarchicalINIConfiguration}. 224 */ 225 @Test 226 public void testLoad() throws Exception 227 { 228 checkLoad(INI_DATA); 229 } 230 231 /** 232 * Tests the load() method when the alternative value separator is used (a 233 * ':' for '='). 234 */ 235 @Test 236 public void testLoadAlternativeSeparator() throws Exception 237 { 238 checkLoad(INI_DATA.replace('=', ':')); 239 } 240 241 /** 242 * Tests loading a configuration from a File. 243 */ 244 @Test 245 public void testLoadFile() throws ConfigurationException, IOException 246 { 247 writeTestFile(INI_DATA); 248 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration( 249 TEST_FILE); 250 checkContent(config); 251 } 252 253 /** 254 * Tests loading a configuration from a file name. 255 */ 256 @Test 257 public void testLoadFileName() throws ConfigurationException, IOException 258 { 259 writeTestFile(INI_DATA); 260 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration( 261 TEST_FILE.getAbsolutePath()); 262 checkContent(config); 263 } 264 265 /** 266 * Tests loading a configuration from a URL. 267 */ 268 @Test 269 public void testLoadURL() throws ConfigurationException, IOException 270 { 271 writeTestFile(INI_DATA); 272 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration( 273 TEST_FILE.toURI().toURL()); 274 checkContent(config); 275 } 276 277 /** 278 * Tests the values of some properties to ensure that the configuration was 279 * correctly loaded. 280 * 281 * @param instance the configuration to check 282 */ 283 private void checkContent(HierarchicalINIConfiguration instance) 284 { 285 assertTrue(instance.getString("section1.var1").equals("foo")); 286 assertTrue(instance.getInt("section1.var2") == 451); 287 assertTrue(instance.getDouble("section2.var1") == 123.45); 288 assertTrue(instance.getString("section2.var2").equals("bar")); 289 assertTrue(instance.getBoolean("section3.var1")); 290 assertTrue(instance.getSections().size() == 3); 291 } 292 293 /** 294 * Helper method for testing the load operation. Loads the specified content 295 * into a configuration and then checks some properties. 296 * 297 * @param data the data to load 298 */ 299 private void checkLoad(String data) throws ConfigurationException 300 { 301 HierarchicalINIConfiguration instance = setUpConfig(data); 302 checkContent(instance); 303 } 304 305 /** 306 * Test of isCommentLine method, of class 307 * {@link HierarchicalINIConfiguration}. 308 */ 309 @Test 310 public void testIsCommentLine() 311 { 312 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration(); 313 assertTrue(instance.isCommentLine("#comment1")); 314 assertTrue(instance.isCommentLine(";comment1")); 315 assertFalse(instance.isCommentLine("nocomment=true")); 316 assertFalse(instance.isCommentLine(null)); 317 } 318 319 /** 320 * Test of isSectionLine method, of class 321 * {@link HierarchicalINIConfiguration}. 322 */ 323 @Test 324 public void testIsSectionLine() 325 { 326 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration(); 327 assertTrue(instance.isSectionLine("[section]")); 328 assertFalse(instance.isSectionLine("nosection=true")); 329 assertFalse(instance.isSectionLine(null)); 330 } 331 332 /** 333 * Test of getSections method, of class {@link HierarchicalINIConfiguration} 334 * . 335 */ 336 @Test 337 public void testGetSections() 338 { 339 HierarchicalINIConfiguration instance = new HierarchicalINIConfiguration(); 340 instance.addProperty("test1.foo", "bar"); 341 instance.addProperty("test2.foo", "abc"); 342 Set<String> expResult = new HashSet<String>(); 343 expResult.add("test1"); 344 expResult.add("test2"); 345 Set<String> result = instance.getSections(); 346 assertEquals(expResult, result); 347 } 348 349 @Test 350 public void testQuotedValue() throws Exception 351 { 352 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 353 assertEquals("value", "quoted value", config.getString("section4.var1")); 354 } 355 356 @Test 357 public void testQuotedValueWithQuotes() throws Exception 358 { 359 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 360 assertEquals("value", "quoted value\\nwith \"quotes\"", config 361 .getString("section4.var2")); 362 } 363 364 @Test 365 public void testValueWithComment() throws Exception 366 { 367 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 368 assertEquals("value", "123", config.getString("section4.var3")); 369 } 370 371 @Test 372 public void testQuotedValueWithComment() throws Exception 373 { 374 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 375 assertEquals("value", "1;2;3", config.getString("section4.var4")); 376 } 377 378 @Test 379 public void testQuotedValueWithSingleQuotes() throws Exception 380 { 381 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 382 assertEquals("value", "'quoted' \"value\"", config 383 .getString("section4.var5")); 384 } 385 386 @Test 387 public void testWriteValueWithCommentChar() throws Exception 388 { 389 HierarchicalINIConfiguration config = new HierarchicalINIConfiguration(); 390 config.setProperty("section.key1", "1;2;3"); 391 392 StringWriter writer = new StringWriter(); 393 config.save(writer); 394 395 HierarchicalINIConfiguration config2 = new HierarchicalINIConfiguration(); 396 config2.load(new StringReader(writer.toString())); 397 398 assertEquals("value", "1;2;3", config2.getString("section.key1")); 399 } 400 401 /** 402 * Tests whether whitespace is left unchanged for quoted values. 403 */ 404 @Test 405 public void testQuotedValueWithWhitespace() throws Exception 406 { 407 final String content = "CmdPrompt = \" [test@cmd ~]$ \""; 408 HierarchicalINIConfiguration config = setUpConfig(content); 409 assertEquals("Wrong propert value", " [test@cmd ~]$ ", config 410 .getString("CmdPrompt")); 411 } 412 413 /** 414 * Tests a quoted value with space and a comment. 415 */ 416 @Test 417 public void testQuotedValueWithWhitespaceAndComment() throws Exception 418 { 419 final String content = "CmdPrompt = \" [test@cmd ~]$ \" ; a comment"; 420 HierarchicalINIConfiguration config = setUpConfig(content); 421 assertEquals("Wrong propert value", " [test@cmd ~]$ ", config 422 .getString("CmdPrompt")); 423 } 424 425 /** 426 * Tests an empty quoted value. 427 */ 428 @Test 429 public void testQuotedValueEmpty() throws ConfigurationException 430 { 431 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 432 assertEquals("Wrong value for empty property", "", config 433 .getString("section4.var6")); 434 } 435 436 /** 437 * Tests a property that has no value. 438 */ 439 @Test 440 public void testGetPropertyNoValue() throws ConfigurationException 441 { 442 final String data = INI_DATA2 + LINE_SEPARATOR + "noValue =" 443 + LINE_SEPARATOR; 444 HierarchicalINIConfiguration config = setUpConfig(data); 445 assertEquals("Wrong value of key", "", config 446 .getString("section4.noValue")); 447 } 448 449 /** 450 * Tests a property that has no key. 451 */ 452 @Test 453 public void testGetPropertyNoKey() throws ConfigurationException 454 { 455 final String data = INI_DATA2 + LINE_SEPARATOR + "= noKey" 456 + LINE_SEPARATOR; 457 HierarchicalINIConfiguration config = setUpConfig(data); 458 assertEquals("Cannot find property with no key", "noKey", config 459 .getString("section4. ")); 460 } 461 462 /** 463 * Tests reading a property from the global section. 464 */ 465 @Test 466 public void testGlobalProperty() throws ConfigurationException 467 { 468 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_GLOBAL); 469 assertEquals("Wrong value of global property", "testGlobal", config 470 .getString("globalVar")); 471 } 472 473 /** 474 * Tests whether the specified configuration contains exactly the expected 475 * sections. 476 * 477 * @param config the configuration to check 478 * @param expected an array with the expected sections 479 */ 480 private void checkSectionNames(HierarchicalINIConfiguration config, 481 String[] expected) 482 { 483 Set<String> sectionNames = config.getSections(); 484 Iterator<String> it = sectionNames.iterator(); 485 for (int idx = 0; idx < expected.length; idx++) 486 { 487 assertEquals("Wrong section at " + idx, expected[idx], it.next()); 488 } 489 assertFalse("Too many sections", it.hasNext()); 490 } 491 492 /** 493 * Tests the names of the sections returned by the configuration. 494 * 495 * @param data the data of the ini configuration 496 * @param expected the expected section names 497 * @return the configuration instance 498 */ 499 private HierarchicalINIConfiguration checkSectionNames(String data, 500 String[] expected) throws ConfigurationException 501 { 502 HierarchicalINIConfiguration config = setUpConfig(data); 503 checkSectionNames(config, expected); 504 return config; 505 } 506 507 /** 508 * Tests querying the sections if a global section if available. 509 */ 510 @Test 511 public void testGetSectionsWithGlobal() throws ConfigurationException 512 { 513 checkSectionNames(INI_DATA_GLOBAL, new String[] { 514 null, "section1", "section2", "section3" 515 }); 516 } 517 518 /** 519 * Tests querying the sections if there is no global section. 520 */ 521 @Test 522 public void testGetSectionsNoGlobal() throws ConfigurationException 523 { 524 checkSectionNames(INI_DATA, new String[] { 525 "section1", "section2", "section3" 526 }); 527 } 528 529 /** 530 * Tests whether the sections of a configuration can be queried that 531 * contains only a global section. 532 */ 533 @Test 534 public void testGetSectionsGlobalOnly() throws ConfigurationException 535 { 536 checkSectionNames(INI_DATA_GLOBAL_ONLY, new String[] { 537 null 538 }); 539 } 540 541 /** 542 * Tests whether variables containing a dot are not misinterpreted as 543 * sections. This test is related to CONFIGURATION-327. 544 */ 545 @Test 546 public void testGetSectionsDottedVar() throws ConfigurationException 547 { 548 final String data = "dotted.var = 1" + LINE_SEPARATOR + INI_DATA_GLOBAL; 549 HierarchicalINIConfiguration config = checkSectionNames(data, 550 new String[] { 551 null, "section1", "section2", "section3" 552 }); 553 assertEquals("Wrong value of dotted variable", 1, config 554 .getInt("dotted..var")); 555 } 556 557 /** 558 * Tests whether a section added later is also found by getSections(). 559 */ 560 @Test 561 public void testGetSectionsAdded() throws ConfigurationException 562 { 563 HierarchicalINIConfiguration config = setUpConfig(INI_DATA2); 564 config.addProperty("section5.test", Boolean.TRUE); 565 checkSectionNames(config, new String[] { 566 "section4", "section5" 567 }); 568 } 569 570 /** 571 * Tests querying the properties of an existing section. 572 */ 573 @Test 574 public void testGetSectionExisting() throws ConfigurationException 575 { 576 HierarchicalINIConfiguration config = setUpConfig(INI_DATA); 577 SubnodeConfiguration section = config.getSection("section1"); 578 assertEquals("Wrong value of var1", "foo", section.getString("var1")); 579 assertEquals("Wrong value of var2", "451", section.getString("var2")); 580 } 581 582 /** 583 * Tests querying the properties of a section that was merged from two 584 * sections with the same name. 585 */ 586 @Test 587 public void testGetSectionMerged() throws ConfigurationException 588 { 589 final String data = INI_DATA + "[section1]" + LINE_SEPARATOR 590 + "var3 = merged" + LINE_SEPARATOR; 591 HierarchicalINIConfiguration config = setUpConfig(data); 592 SubnodeConfiguration section = config.getSection("section1"); 593 assertEquals("Wrong value of var1", "foo", section.getString("var1")); 594 assertEquals("Wrong value of var2", "451", section.getString("var2")); 595 assertEquals("Wrong value of var3", "merged", section.getString("var3")); 596 } 597 598 /** 599 * Tests querying the content of the global section. 600 */ 601 @Test 602 public void testGetSectionGlobal() throws ConfigurationException 603 { 604 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_GLOBAL); 605 SubnodeConfiguration section = config.getSection(null); 606 assertEquals("Wrong value of global variable", "testGlobal", section 607 .getString("globalVar")); 608 } 609 610 /** 611 * Tests concurrent access to the global section. 612 */ 613 @Test 614 public void testGetSectionGloabalMultiThreaded() 615 throws ConfigurationException, InterruptedException 616 { 617 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_GLOBAL); 618 final int threadCount = 10; 619 GlobalSectionTestThread[] threads = new GlobalSectionTestThread[threadCount]; 620 for (int i = 0; i < threadCount; i++) 621 { 622 threads[i] = new GlobalSectionTestThread(config); 623 threads[i].start(); 624 } 625 for (int i = 0; i < threadCount; i++) 626 { 627 threads[i].join(); 628 assertFalse("Exception occurred", threads[i].error); 629 } 630 } 631 632 /** 633 * Tests querying the content of the global section if there is none. 634 */ 635 @Test 636 public void testGetSectionGlobalNonExisting() throws ConfigurationException 637 { 638 HierarchicalINIConfiguration config = setUpConfig(INI_DATA); 639 SubnodeConfiguration section = config.getSection(null); 640 assertTrue("Sub config not empty", section.isEmpty()); 641 } 642 643 /** 644 * Tests querying a non existing section. 645 */ 646 @Test 647 public void testGetSectionNonExisting() throws ConfigurationException 648 { 649 HierarchicalINIConfiguration config = setUpConfig(INI_DATA); 650 SubnodeConfiguration section = config 651 .getSection("Non existing section"); 652 assertTrue("Sub config not empty", section.isEmpty()); 653 } 654 655 /** 656 * Tests a property whose value spans multiple lines. 657 */ 658 @Test 659 public void testLineContinuation() throws ConfigurationException 660 { 661 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 662 assertEquals("Wrong value", "one" + LINE_SEPARATOR + "two" 663 + LINE_SEPARATOR + "three", config 664 .getString("section5.multiLine")); 665 } 666 667 /** 668 * Tests a property value that ends on a backslash, which is no line 669 * continuation character. 670 */ 671 @Test 672 public void testLineContinuationNone() throws ConfigurationException 673 { 674 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 675 assertEquals("Wrong value", "C:\\Temp\\", config 676 .getString("section5.singleLine")); 677 } 678 679 /** 680 * Tests a property whose value spans multiple lines when quoting is 681 * involved. In this case whitespace must not be trimmed. 682 */ 683 @Test 684 public void testLineContinuationQuoted() throws ConfigurationException 685 { 686 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 687 assertEquals("Wrong value", "one" + LINE_SEPARATOR + " two " 688 + LINE_SEPARATOR + "three", config 689 .getString("section5.multiQuoted")); 690 } 691 692 /** 693 * Tests a property whose value spans multiple lines with a comment. 694 */ 695 @Test 696 public void testLineContinuationComment() throws ConfigurationException 697 { 698 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 699 assertEquals("Wrong value", "one" + LINE_SEPARATOR + "two", config 700 .getString("section5.multiComment")); 701 } 702 703 /** 704 * Tests a property with a quoted value spanning multiple lines and a 705 * comment. 706 */ 707 @Test 708 public void testLineContinuationQuotedComment() 709 throws ConfigurationException 710 { 711 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 712 assertEquals("Wrong value", " one " + LINE_SEPARATOR + "two", config 713 .getString("section5.multiQuotedComment")); 714 } 715 716 /** 717 * Tests a multi-line property value with an empty line. 718 */ 719 @Test 720 public void testLineContinuationEmptyLine() throws ConfigurationException 721 { 722 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 723 assertEquals("Wrong value", LINE_SEPARATOR + "line 2", config 724 .getString("section5.noFirstLine")); 725 } 726 727 /** 728 * Tests a line continuation at the end of the file. 729 */ 730 @Test 731 public void testLineContinuationAtEnd() throws ConfigurationException 732 { 733 HierarchicalINIConfiguration config = setUpConfig(INI_DATA3); 734 assertEquals("Wrong value", "one" + LINE_SEPARATOR, config 735 .getString("section5.continueNoLine")); 736 } 737 738 /** 739 * Tests whether a configuration can be saved that contains section keys 740 * with delimiter characters. This test is related to CONFIGURATION-409. 741 */ 742 @Test 743 public void testSaveKeysWithDelimiters() throws ConfigurationException 744 { 745 HierarchicalINIConfiguration conf = new HierarchicalINIConfiguration(); 746 final String section = "Section..with..dots"; 747 conf.addProperty(section + ".test1", "test1"); 748 conf.addProperty(section + ".test2", "test2"); 749 conf.save(TEST_FILE); 750 conf = new HierarchicalINIConfiguration(); 751 conf.load(TEST_FILE); 752 assertEquals("Wrong value (1)", "test1", conf.getString(section + ".test1")); 753 assertEquals("Wrong value (2)", "test2", conf.getString(section + ".test2")); 754 } 755 756 /** 757 * Tests whether a value which contains a semicolon can be loaded 758 * successfully. This test is related to CONFIGURATION-434. 759 */ 760 @Test 761 public void testValueWithSemicolon() throws ConfigurationException 762 { 763 final String path = 764 "C:\\Program Files\\jar\\manage.jar;" 765 + "C:\\Program Files\\jar\\guiLauncher.jar"; 766 final String content = 767 "[Environment]" + LINE_SEPARATOR + "Application Type=any" 768 + LINE_SEPARATOR + "Class Path=" + path + " ;comment" 769 + LINE_SEPARATOR + "Path=" + path 770 + "\t; another comment"; 771 HierarchicalINIConfiguration config = setUpConfig(content); 772 assertEquals("Wrong class path", path, 773 config.getString("Environment.Class Path")); 774 assertEquals("Wrong path", path, config.getString("Environment.Path")); 775 } 776 777 /** 778 * Tests whether the different separators with or without whitespace are 779 * recognized. 780 */ 781 @Test 782 public void testSeparators() throws ConfigurationException 783 { 784 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_SEPARATORS); 785 for (int i = 1; i <= 4; i++) 786 { 787 assertEquals("Wrong value", "value" + i, 788 config.getString("section.var" + i)); 789 } 790 } 791 792 /** 793 * Tests property definitions containing multiple separators. 794 */ 795 @Test 796 public void testMultipleSeparators() throws ConfigurationException 797 { 798 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_SEPARATORS); 799 assertEquals("Wrong value for var5", "value=5", 800 config.getString("section.var5")); 801 assertEquals("Wrong value for var6", "6=value", 802 config.getString("section.var")); 803 } 804 805 /** 806 * Tests property definitions containing multiple separators that are 807 * quoted. 808 */ 809 @Test 810 public void testMultipleSeparatorsQuoted() throws ConfigurationException 811 { 812 HierarchicalINIConfiguration config = setUpConfig(INI_DATA_SEPARATORS); 813 assertEquals("Wrong value for var7", "value7", 814 config.getString("section.var:7")); 815 assertEquals("Wrong value for var8", "value8", 816 config.getString("section.var:8")); 817 } 818 819 /** 820 * Tests whether a section that has been cleared can be manipulated and 821 * saved later. 822 */ 823 @Test 824 public void testSaveClearedSection() throws ConfigurationException 825 { 826 final String data = "[section]\ntest = failed\n"; 827 HierarchicalINIConfiguration config = setUpConfig(data); 828 SubnodeConfiguration sub = config.getSection("section"); 829 assertFalse("No content", sub.isEmpty()); 830 sub.clear(); 831 sub.setProperty("test", "success"); 832 StringWriter writer = new StringWriter(); 833 config.save(writer); 834 HierarchicalConfiguration config2 = setUpConfig(writer.toString()); 835 assertEquals("Wrong value", "success", 836 config2.getString("section.test")); 837 } 838 839 /** 840 * Tests whether a duplicate session is merged. 841 */ 842 @Test 843 public void testMergeDuplicateSection() throws ConfigurationException 844 { 845 final String data = 846 "[section]\nvar1 = sec1\n\n" + "[section]\nvar2 = sec2\n"; 847 HierarchicalINIConfiguration config = setUpConfig(data); 848 assertEquals("Wrong value 1", "sec1", config.getString("section.var1")); 849 assertEquals("Wrong value 2", "sec2", config.getString("section.var2")); 850 SubnodeConfiguration sub = config.getSection("section"); 851 assertEquals("Wrong sub value 1", "sec1", sub.getString("var1")); 852 assertEquals("Wrong sub value 2", "sec2", sub.getString("var2")); 853 StringWriter writer = new StringWriter(); 854 config.save(writer); 855 String content = writer.toString(); 856 int pos = content.indexOf("[section]"); 857 assertTrue("Section not found: " + content, pos >= 0); 858 assertTrue("Section found multiple times: " + content, 859 content.indexOf("[section]", pos + 1) < 0); 860 } 861 862 /** 863 * Tests whether a section that was created by getSection() can be 864 * manipulated. 865 */ 866 @Test 867 public void testGetSectionNonExistingManipulate() 868 throws ConfigurationException 869 { 870 HierarchicalINIConfiguration config = setUpConfig(INI_DATA); 871 SubnodeConfiguration section = config.getSection("newSection"); 872 section.addProperty("test", "success"); 873 assertEquals("Main config not updated", "success", 874 config.getString("newSection.test")); 875 StringWriter writer = new StringWriter(); 876 config.save(writer); 877 HierarchicalINIConfiguration config2 = setUpConfig(writer.toString()); 878 section = config2.getSection("newSection"); 879 assertEquals("Wrong value", "success", section.getString("test")); 880 } 881 882 /** 883 * Tests whether getSection() can deal with duplicate sections. 884 */ 885 @Test 886 public void testGetSectionDuplicate() 887 { 888 HierarchicalINIConfiguration config = 889 new HierarchicalINIConfiguration(); 890 config.addProperty("section.var1", "value1"); 891 config.addProperty("section(-1).var2", "value2"); 892 SubnodeConfiguration section = config.getSection("section"); 893 Iterator<String> keys = section.getKeys(); 894 assertEquals("Wrong key", "var1", keys.next()); 895 assertFalse("Too many keys", keys.hasNext()); 896 } 897 898 /** 899 * Tests whether the list delimiter character is recognized. 900 */ 901 @Test 902 public void testValueWithDelimiters() throws ConfigurationException 903 { 904 HierarchicalINIConfiguration config = 905 setUpConfig("[test]" + LINE_SEPARATOR + "list=1,2,3" 906 + LINE_SEPARATOR); 907 List<Object> list = config.getList("test.list"); 908 assertEquals("Wrong number of elements", 3, list.size()); 909 assertEquals("Wrong element at 1", "1", list.get(0)); 910 assertEquals("Wrong element at 2", "2", list.get(1)); 911 assertEquals("Wrong element at 3", "3", list.get(2)); 912 } 913 914 /** 915 * Tests whether parsing of lists can be disabled. 916 */ 917 @Test 918 public void testListParsingDisabled() throws ConfigurationException 919 { 920 HierarchicalINIConfiguration config = 921 new HierarchicalINIConfiguration(); 922 config.setDelimiterParsingDisabled(true); 923 load(config, "[test]" + LINE_SEPARATOR + "nolist=1,2,3"); 924 assertEquals("Wrong value", "1,2,3", config.getString("test.nolist")); 925 } 926 927 /** 928 * A thread class for testing concurrent access to the global section. 929 */ 930 private static class GlobalSectionTestThread extends Thread 931 { 932 /** The configuration. */ 933 private final HierarchicalINIConfiguration config; 934 935 /** A flag whether an error was found. */ 936 volatile boolean error; 937 938 /** 939 * Creates a new instance of <code>GlobalSectionTestThread</code> and 940 * initializes it. 941 * 942 * @param conf the configuration object 943 */ 944 public GlobalSectionTestThread(HierarchicalINIConfiguration conf) 945 { 946 config = conf; 947 } 948 949 /** 950 * Accesses the global section in a loop. If there is no correct 951 * synchronization, this can cause an exception. 952 */ 953 @Override 954 public void run() 955 { 956 final int loopCount = 250; 957 958 for (int i = 0; i < loopCount && !error; i++) 959 { 960 try 961 { 962 config.getSection(null); 963 } 964 catch (IllegalStateException istex) 965 { 966 error = true; 967 } 968 } 969 } 970 } 971 }