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.FileOutputStream;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.io.PrintWriter;
26 import java.io.Reader;
27 import java.io.StringReader;
28 import java.io.StringWriter;
29 import java.net.HttpURLConnection;
30 import java.net.URL;
31 import java.net.URLConnection;
32 import java.net.URLStreamHandler;
33 import java.util.ArrayList;
34 import java.util.Iterator;
35 import java.util.List;
36
37 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
38
39 import junit.framework.TestCase;
40
41 /***
42 * Test for loading and saving properties files.
43 *
44 * @version $Id: TestPropertiesConfiguration.java 567771 2007-08-20 17:57:08Z oheger $
45 */
46 public class TestPropertiesConfiguration extends TestCase
47 {
48 private PropertiesConfiguration conf;
49
50 /*** The File that we test with */
51 private String testProperties = new File("conf/test.properties").getAbsolutePath();
52
53 private String testBasePath = new File("conf").getAbsolutePath();
54 private String testBasePath2 = new File("conf").getAbsoluteFile().getParentFile().getAbsolutePath();
55 private File testSavePropertiesFile = new File("target/testsave.properties");
56
57 protected void setUp() throws Exception
58 {
59 conf = new PropertiesConfiguration(testProperties);
60
61
62 if (testSavePropertiesFile.exists())
63 {
64 assertTrue("Test output file could not be deleted",
65 testSavePropertiesFile.delete());
66 }
67 }
68
69 public void testLoad() throws Exception
70 {
71 String loaded = conf.getString("configuration.loaded");
72 assertEquals("true", loaded);
73 }
74
75 /***
76 * Tests if properties can be appended by simply calling load() another
77 * time.
78 */
79 public void testAppend() throws Exception
80 {
81 File file2 = new File("conf/threesome.properties");
82 conf.load(file2);
83 assertEquals("aaa", conf.getString("test.threesome.one"));
84 assertEquals("true", conf.getString("configuration.loaded"));
85 }
86
87 /***
88 * Tests that empty properties are treated as the empty string
89 * (rather than as null).
90 */
91 public void testEmpty() throws Exception
92 {
93 String empty = conf.getString("test.empty");
94 assertNotNull(empty);
95 assertEquals("", empty);
96 }
97
98 /***
99 * Tests that references to other properties work
100 */
101 public void testReference() throws Exception
102 {
103 assertEquals("baseextra", conf.getString("base.reference"));
104 }
105
106 /***
107 * test if includes properties get loaded too
108 */
109 public void testLoadInclude() throws Exception
110 {
111 String loaded = conf.getString("include.loaded");
112 assertEquals("true", loaded);
113 }
114
115 public void testSetInclude() throws Exception
116 {
117
118 PropertiesConfiguration.setInclude("import");
119
120
121 PropertiesConfiguration conf = new PropertiesConfiguration();
122 conf.load("conf/test.properties");
123
124
125 PropertiesConfiguration.setInclude("include");
126
127 assertNull(conf.getString("include.loaded"));
128 }
129
130 /***
131 * Tests <code>List</code> parsing.
132 */
133 public void testList() throws Exception
134 {
135 List packages = conf.getList("packages");
136
137 assertEquals(3, packages.size());
138 }
139
140 public void testSave() throws Exception
141 {
142
143 conf.addProperty("string", "value1");
144 List list = new ArrayList();
145 for (int i = 1; i < 5; i++)
146 {
147 list.add("value" + i);
148 }
149 conf.addProperty("array", list);
150
151
152 String filename = testSavePropertiesFile.getAbsolutePath();
153 conf.save(filename);
154
155 assertTrue("The saved file doesn't exist", testSavePropertiesFile.exists());
156
157
158 PropertiesConfiguration checkConfig = new PropertiesConfiguration(filename);
159 ConfigurationAssert.assertEquals(conf, checkConfig);
160
161
162 checkConfig.save();
163 }
164
165 public void testSaveToCustomURL() throws Exception
166 {
167
168 URL url = new URL("foo", "", 0, "./target/testsave-custom-url.properties", new FileURLStreamHandler());
169 conf.save(url);
170
171
172 Configuration config2 = new PropertiesConfiguration(url);
173 assertEquals("true", config2.getString("configuration.loaded"));
174 }
175
176 public void testInMemoryCreatedSave() throws Exception
177 {
178 PropertiesConfiguration pc = new PropertiesConfiguration();
179
180 pc.addProperty("string", "value1");
181 List list = new ArrayList();
182 for (int i = 1; i < 5; i++)
183 {
184 list.add("value" + i);
185 }
186 pc.addProperty("array", list);
187
188
189 String filename = testSavePropertiesFile.getAbsolutePath();
190 pc.save(filename);
191
192 assertTrue("The saved file doesn't exist", testSavePropertiesFile.exists());
193
194
195 PropertiesConfiguration checkConfig = new PropertiesConfiguration(filename);
196 ConfigurationAssert.assertEquals(pc, checkConfig);
197
198
199 checkConfig.save();
200 }
201
202 /***
203 * Tests saving a configuration when delimiter parsing is disabled.
204 */
205 public void testSaveWithDelimiterParsingDisabled() throws ConfigurationException
206 {
207 conf.clear();
208 conf.setDelimiterParsingDisabled(true);
209 conf.addProperty("test.list", "a,b,c");
210 conf.addProperty("test.dirs", "C://Temp//,D://Data//");
211 conf.save(testSavePropertiesFile);
212
213 PropertiesConfiguration checkConfig = new PropertiesConfiguration();
214 checkConfig.setDelimiterParsingDisabled(true);
215 checkConfig.setFile(testSavePropertiesFile);
216 checkConfig.load();
217 ConfigurationAssert.assertEquals(conf, checkConfig);
218 }
219
220 public void testSaveMissingFilename()
221 {
222 PropertiesConfiguration pc = new PropertiesConfiguration();
223 try
224 {
225 pc.save();
226 fail("Should have throw ConfigurationException");
227 }
228 catch (ConfigurationException ce)
229 {
230
231 }
232 }
233
234 /***
235 * Tests if the base path is taken into account by the save() method.
236 * @throws Exception if an error occurs
237 */
238 public void testSaveWithBasePath() throws Exception
239 {
240 conf.setProperty("test", "true");
241 conf.setBasePath(testSavePropertiesFile.getParentFile().toURL().toString());
242 conf.setFileName(testSavePropertiesFile.getName());
243 conf.save();
244 assertTrue(testSavePropertiesFile.exists());
245 }
246
247 /***
248 * Tests whether the escape character for list delimiters can be itself
249 * escaped and survives a save operation.
250 */
251 public void testSaveEscapedEscapingCharacter()
252 throws ConfigurationException
253 {
254 conf.addProperty("test.dirs", "C://Temp////,D://Data////,E://Test//");
255 List dirs = conf.getList("test.dirs");
256 assertEquals("Wrong number of list elements", 3, dirs.size());
257 conf.save(testSavePropertiesFile);
258
259 PropertiesConfiguration checkConfig = new PropertiesConfiguration(
260 testSavePropertiesFile);
261 ConfigurationAssert.assertEquals(conf, checkConfig);
262 }
263
264 public void testLoadViaProperty() throws Exception
265 {
266 PropertiesConfiguration pc = new PropertiesConfiguration();
267 pc.setFileName(testProperties);
268 pc.load();
269
270 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
271 }
272
273 public void testLoadViaPropertyWithBasePath() throws Exception
274 {
275 PropertiesConfiguration pc = new PropertiesConfiguration();
276 pc.setBasePath(testBasePath);
277 pc.setFileName("test.properties");
278 pc.load();
279
280 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
281 }
282
283 public void testLoadViaPropertyWithBasePath2() throws Exception
284 {
285 PropertiesConfiguration pc = new PropertiesConfiguration();
286 pc.setBasePath(testBasePath2);
287 pc.setFileName("conf/test.properties");
288 pc.load();
289
290 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
291
292 pc = new PropertiesConfiguration();
293 pc.setBasePath(testBasePath2);
294 pc.setFileName("conf/test.properties");
295 pc.load();
296
297 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
298 }
299
300 public void testLoadFromFile() throws Exception
301 {
302 File file = new File("conf/test.properties");
303 conf = new PropertiesConfiguration(file);
304
305 assertEquals("true", conf.getString("configuration.loaded"));
306 }
307
308 public void testLoadUnexistingFile()
309 {
310 try
311 {
312 conf = new PropertiesConfiguration("Unexisting file");
313 fail("Unexisting file was loaded.");
314 }
315 catch(ConfigurationException cex)
316 {
317
318 }
319 }
320
321 /***
322 * Tests to load a file with enabled auto save mode.
323 */
324 public void testLoadWithAutoSave() throws Exception
325 {
326 setUpSavedProperties();
327 }
328
329 /***
330 * Tests the auto save functionality when an existing property is modified.
331 */
332 public void testLoadWithAutoSaveAndSetExisting() throws Exception
333 {
334 setUpSavedProperties();
335 conf.setProperty("a", "moreThanOne");
336 checkSavedConfig();
337 }
338
339 /***
340 * Tests the auto save functionality when a new property is added using the
341 * setProperty() method.
342 */
343 public void testLoadWithAutoSaveAndSetNew() throws Exception
344 {
345 setUpSavedProperties();
346 conf.setProperty("d", "four");
347 checkSavedConfig();
348 }
349
350 /***
351 * Tests the auto save functionality when a new property is added using the
352 * addProperty() method.
353 */
354 public void testLoadWithAutoSaveAndAdd() throws Exception
355 {
356 setUpSavedProperties();
357 conf.addProperty("d", "four");
358 checkSavedConfig();
359 }
360
361 /***
362 * Tests the auto save functionality when a property is removed.
363 */
364 public void testLoadWithAutoSaveAndClear() throws Exception
365 {
366 setUpSavedProperties();
367 conf.clearProperty("c");
368 PropertiesConfiguration checkConfig = checkSavedConfig();
369 assertFalse("The saved configuration contain the key '" + "c" + "'", checkConfig.containsKey("c"));
370 }
371
372 /***
373 * Creates a properties file on disk. Used for testing load and save
374 * operations.
375 *
376 * @throws IOException if an I/O error occurs
377 */
378 private void setUpSavedProperties() throws IOException, ConfigurationException
379 {
380 PrintWriter out = null;
381
382 try
383 {
384 out = new PrintWriter(new FileWriter(testSavePropertiesFile));
385 out.println("a = one");
386 out.println("b = two");
387 out.println("c = three");
388 out.close();
389 out = null;
390
391 conf = new PropertiesConfiguration();
392 conf.setAutoSave(true);
393 conf.setFile(testSavePropertiesFile);
394 conf.load();
395 assertEquals("one", conf.getString("a"));
396 assertEquals("two", conf.getString("b"));
397 assertEquals("three", conf.getString("c"));
398 }
399 finally
400 {
401 if (out != null)
402 {
403 out.close();
404 }
405 }
406 }
407
408 /***
409 * Helper method for testing a saved configuration. Reads in the file using
410 * a new instance and compares this instance with the original one.
411 *
412 * @return the newly created configuration instance
413 * @throws ConfigurationException if an error occurs
414 */
415 private PropertiesConfiguration checkSavedConfig()
416 throws ConfigurationException
417 {
418 PropertiesConfiguration checkConfig = new PropertiesConfiguration(testSavePropertiesFile);
419 for (Iterator i = conf.getKeys(); i.hasNext();)
420 {
421 String key = (String) i.next();
422 assertTrue("The saved configuration doesn't contain the key '" + key + "'", checkConfig.containsKey(key));
423 assertEquals("Value of the '" + key + "' property", conf.getProperty(key), checkConfig.getProperty(key));
424 }
425 return checkConfig;
426 }
427
428 public void testGetStringWithEscapedChars()
429 {
430 String property = conf.getString("test.unescape");
431 assertEquals("String with escaped characters", "This \n string \t contains \" escaped // characters", property);
432 }
433
434 public void testGetStringWithEscapedComma()
435 {
436 String property = conf.getString("test.unescape.list-separator");
437 assertEquals("String with an escaped list separator", "This string contains , an escaped list separator", property);
438 }
439
440 public void testUnescapeJava()
441 {
442 assertEquals("test//,test", PropertiesConfiguration.unescapeJava("test//,test", ','));
443 }
444
445 public void testEscapedKey() throws Exception
446 {
447 PropertiesConfiguration conf = new PropertiesConfiguration();
448 conf.load(new StringReader("//u0066//u006f//u006f=bar"));
449
450 assertEquals("value of the 'foo' property", "bar", conf.getString("foo"));
451 }
452
453 public void testMixedArray()
454 {
455 String[] array = conf.getStringArray("test.mixed.array");
456
457 assertEquals("array length", 4, array.length);
458 assertEquals("1st element", "a", array[0]);
459 assertEquals("2nd element", "b", array[1]);
460 assertEquals("3rd element", "c", array[2]);
461 assertEquals("4th element", "d", array[3]);
462 }
463
464 public void testMultilines()
465 {
466 String property = "This is a value spread out across several adjacent "
467 + "natural lines by escaping the line terminator with "
468 + "a backslash character.";
469
470 assertEquals("'test.multilines' property", property, conf.getString("test.multilines"));
471 }
472
473 public void testChangingDefaultListDelimiter() throws Exception
474 {
475 PropertiesConfiguration pc = new PropertiesConfiguration(testProperties);
476 assertEquals(4, pc.getList("test.mixed.array").size());
477
478 char delimiter = PropertiesConfiguration.getDefaultListDelimiter();
479 PropertiesConfiguration.setDefaultListDelimiter('^');
480 pc = new PropertiesConfiguration(testProperties);
481 assertEquals(2, pc.getList("test.mixed.array").size());
482 PropertiesConfiguration.setDefaultListDelimiter(delimiter);
483 }
484
485 public void testChangingListDelimiter() throws Exception
486 {
487 PropertiesConfiguration pc1 = new PropertiesConfiguration(testProperties);
488 assertEquals(4, pc1.getList("test.mixed.array").size());
489
490 PropertiesConfiguration pc2 = new PropertiesConfiguration();
491 pc2.setListDelimiter('^');
492 pc2.setFileName(testProperties);
493 pc2.load();
494 assertEquals("Should obtain the first value", "a", pc2.getString("test.mixed.array"));
495 assertEquals(2, pc2.getList("test.mixed.array").size());
496 }
497
498 public void testDisableListDelimiter() throws Exception
499 {
500 PropertiesConfiguration pc1 = new PropertiesConfiguration(testProperties);
501 assertEquals(4, pc1.getList("test.mixed.array").size());
502
503 PropertiesConfiguration pc2 = new PropertiesConfiguration();
504 pc2.setDelimiterParsingDisabled(true);
505 pc2.setFileName(testProperties);
506 pc2.load();
507 assertEquals(2, pc2.getList("test.mixed.array").size());
508 }
509
510 /***
511 * Tests escaping of an end of line with a backslash.
512 */
513 public void testNewLineEscaping()
514 {
515 List list = conf.getList("test.path");
516 assertEquals(3, list.size());
517 assertEquals("C://path1//", list.get(0));
518 assertEquals("C://path2//", list.get(1));
519 assertEquals("C://path3//complex//test//", list.get(2));
520 }
521
522 /***
523 * Tests if included files are loaded when the source lies in the class path.
524 */
525 public void testLoadIncludeFromClassPath() throws ConfigurationException
526 {
527 conf = new PropertiesConfiguration("test.properties");
528 assertEquals("true", conf.getString("include.loaded"));
529 }
530
531 /***
532 * Test if the lines starting with # or ! are properly ignored.
533 */
534 public void testComment() {
535 assertFalse("comment line starting with '#' parsed as a property", conf.containsKey("#comment"));
536 assertFalse("comment line starting with '!' parsed as a property", conf.containsKey("!comment"));
537 }
538
539 /***
540 * Check that key/value separators can be part of a key.
541 */
542 public void testEscapedKeyValueSeparator()
543 {
544 assertEquals("Escaped separator '=' not supported in keys", "foo", conf.getProperty("test.separator=in.key"));
545 assertEquals("Escaped separator ':' not supported in keys", "bar", conf.getProperty("test.separator:in.key"));
546 assertEquals("Escaped separator '//t' not supported in keys", "foo", conf.getProperty("test.separator\tin.key"));
547 assertEquals("Escaped separator '//f' not supported in keys", "bar", conf.getProperty("test.separator\fin.key"));
548 assertEquals("Escaped separator ' ' not supported in keys" , "foo", conf.getProperty("test.separator in.key"));
549 }
550
551 /***
552 * Test all acceptable key/value separators ('=', ':' or white spaces).
553 */
554 public void testKeyValueSeparators() {
555 assertEquals("equal separator not properly parsed", "foo", conf.getProperty("test.separator.equal"));
556 assertEquals("colon separator not properly parsed", "foo", conf.getProperty("test.separator.colon"));
557 assertEquals("tab separator not properly parsed", "foo", conf.getProperty("test.separator.tab"));
558 assertEquals("formfeed separator not properly parsed", "foo", conf.getProperty("test.separator.formfeed"));
559 assertEquals("whitespace separator not properly parsed", "foo", conf.getProperty("test.separator.whitespace"));
560 }
561
562 /***
563 * Tests including properties when they are loaded from a nested directory
564 * structure.
565 */
566 public void testIncludeInSubDir() throws ConfigurationException
567 {
568 ConfigurationFactory factory = new ConfigurationFactory("conf/testFactoryPropertiesInclude.xml");
569 Configuration config = factory.getConfiguration();
570 assertEquals(true, config.getBoolean("deeptest"));
571 assertEquals(true, config.getBoolean("deepinclude"));
572 assertFalse(config.containsKey("deeptestinvalid"));
573 }
574
575 /***
576 * Tests whether the correct line separator is used.
577 */
578 public void testLineSeparator() throws ConfigurationException
579 {
580 final String EOL = System.getProperty("line.separator");
581 conf = new PropertiesConfiguration();
582 conf.setHeader("My header");
583 conf.setProperty("prop", "value");
584
585 StringWriter out = new StringWriter();
586 conf.save(out);
587 String content = out.toString();
588 assertTrue("Header could not be found", content.indexOf("# My header"
589 + EOL + EOL) == 0);
590 assertTrue("Property could not be found", content.indexOf("prop = value" + EOL) > 0);
591 }
592
593 /***
594 * Tests what happens if a reloading strategy's <code>reloadingRequired()</code>
595 * implementation accesses methods of the configuration that in turn cause a reload.
596 */
597 public void testReentrantReload()
598 {
599 conf.setProperty("shouldReload", Boolean.FALSE);
600 conf.setReloadingStrategy(new FileChangedReloadingStrategy()
601 {
602 public boolean reloadingRequired()
603 {
604 return configuration.getBoolean("shouldReload");
605 }
606 });
607 assertFalse("Property has wrong value", conf.getBoolean("shouldReload"));
608 }
609
610 /***
611 * Tests accessing the layout object.
612 */
613 public void testGetLayout()
614 {
615 PropertiesConfigurationLayout layout = conf.getLayout();
616 assertNotNull("Layout is null", layout);
617 assertSame("Different object returned", layout, conf.getLayout());
618 conf.setLayout(null);
619 PropertiesConfigurationLayout layout2 = conf.getLayout();
620 assertNotNull("Layout 2 is null", layout2);
621 assertNotSame("Same object returned", layout, layout2);
622 }
623
624 /***
625 * Tests the propertyLoaded() method for a simple property.
626 */
627 public void testPropertyLoaded() throws ConfigurationException
628 {
629 DummyLayout layout = new DummyLayout(conf);
630 conf.setLayout(layout);
631 conf.propertyLoaded("layoutLoadedProperty", "yes");
632 assertEquals("Layout's load() was called", 0, layout.loadCalls);
633 assertEquals("Property not added", "yes", conf.getString("layoutLoadedProperty"));
634 }
635
636 /***
637 * Tests the propertyLoaded() method for an include property.
638 */
639 public void testPropertyLoadedInclude() throws ConfigurationException
640 {
641 DummyLayout layout = new DummyLayout(conf);
642 conf.setLayout(layout);
643 conf.propertyLoaded(PropertiesConfiguration.getInclude(), "testClasspath.properties,testEqual.properties");
644 assertEquals("Layout's load() was not correctly called", 2, layout.loadCalls);
645 assertFalse("Property was added", conf.containsKey(PropertiesConfiguration.getInclude()));
646 }
647
648 /***
649 * Tests propertyLoaded() for an include property, when includes are
650 * disabled.
651 */
652 public void testPropertyLoadedIncludeNotAllowed() throws ConfigurationException
653 {
654 DummyLayout layout = new DummyLayout(conf);
655 conf.setLayout(layout);
656 conf.setIncludesAllowed(false);
657 conf.propertyLoaded(PropertiesConfiguration.getInclude(), "testClassPath.properties,testEqual.properties");
658 assertEquals("Layout's load() was called", 0, layout.loadCalls);
659 assertFalse("Property was added", conf.containsKey(PropertiesConfiguration.getInclude()));
660 }
661
662 /***
663 * Tests whether comment lines are correctly detected.
664 */
665 public void testIsCommentLine()
666 {
667 assertTrue("Comment not detected", PropertiesConfiguration.isCommentLine("# a comment"));
668 assertTrue("Alternative comment not detected", PropertiesConfiguration.isCommentLine("! a comment"));
669 assertTrue("Comment with no space not detected", PropertiesConfiguration.isCommentLine("#a comment"));
670 assertTrue("Comment with leading space not detected", PropertiesConfiguration.isCommentLine(" ! a comment"));
671 assertFalse("Wrong comment", PropertiesConfiguration.isCommentLine(" a#comment"));
672 }
673
674 /***
675 * Tests whether a properties configuration can be successfully cloned. It
676 * is especially checked whether the layout object is taken into account.
677 */
678 public void testClone() throws ConfigurationException
679 {
680 PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone();
681 assertNotSame("Copy has same layout object", conf.getLayout(), copy.getLayout());
682 assertEquals("Wrong number of event listeners for original", 1, conf.getConfigurationListeners().size());
683 assertEquals("Wrong number of event listeners for clone", 1, copy.getConfigurationListeners().size());
684 assertSame("Wrong event listener for original", conf.getLayout(), conf.getConfigurationListeners().iterator().next());
685 assertSame("Wrong event listener for clone", copy.getLayout(), copy.getConfigurationListeners().iterator().next());
686 StringWriter outConf = new StringWriter();
687 conf.save(outConf);
688 StringWriter outCopy = new StringWriter();
689 copy.save(outCopy);
690 assertEquals("Output from copy is different", outConf.toString(), outCopy.toString());
691 }
692
693 /***
694 * Tests the clone() method when no layout object exists yet.
695 */
696 public void testCloneNullLayout()
697 {
698 conf = new PropertiesConfiguration();
699 PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone();
700 assertNotSame("Layout objects are the same", conf.getLayout(), copy.getLayout());
701 }
702
703 /***
704 * Tests saving a file-based configuration to a HTTP server.
705 */
706 public void testSaveToHTTPServerSuccess() throws Exception
707 {
708 MockHttpURLStreamHandler handler = new MockHttpURLStreamHandler(
709 HttpURLConnection.HTTP_OK, testSavePropertiesFile);
710 URL url = new URL(null, "http://jakarta.apache.org", handler);
711 conf.save(url);
712 MockHttpURLConnection con = handler.getMockConnection();
713 assertTrue("Wrong output flag", con.getDoOutput());
714 assertEquals("Wrong method", "PUT", con.getRequestMethod());
715
716 PropertiesConfiguration checkConfig = new PropertiesConfiguration(
717 testSavePropertiesFile);
718 ConfigurationAssert.assertEquals(conf, checkConfig);
719 }
720
721 /***
722 * Tests saving a file-based configuration to a HTTP server when the server
723 * reports a failure. This should cause an exception.
724 */
725 public void testSaveToHTTPServerFail() throws Exception
726 {
727 MockHttpURLStreamHandler handler = new MockHttpURLStreamHandler(
728 HttpURLConnection.HTTP_BAD_REQUEST, testSavePropertiesFile);
729 URL url = new URL(null, "http://jakarta.apache.org", handler);
730 try
731 {
732 conf.save(url);
733 fail("Response code was not checked!");
734 }
735 catch (ConfigurationException cex)
736 {
737 assertTrue("Wrong root cause: " + cex,
738 cex.getCause() instanceof IOException);
739 }
740 }
741
742 /***
743 * Tests initializing a properties configuration from a non existing file.
744 * There was a bug, which caused properties getting lost when later save()
745 * is called.
746 */
747 public void testInitFromNonExistingFile() throws ConfigurationException
748 {
749 final String testProperty = "test.successfull";
750 conf = new PropertiesConfiguration(testSavePropertiesFile);
751 conf.addProperty(testProperty, Boolean.TRUE);
752 conf.save();
753 PropertiesConfiguration checkConfig = new PropertiesConfiguration(
754 testSavePropertiesFile);
755 assertTrue("Test property not found", checkConfig
756 .getBoolean(testProperty));
757 }
758
759 /***
760 * Tests copying another configuration into the test configuration. This
761 * test ensures that the layout object is informed about the newly added
762 * properties.
763 */
764 public void testCopyAndSave() throws ConfigurationException
765 {
766 Configuration copyConf = setUpCopyConfig();
767 conf.copy(copyConf);
768 checkCopiedConfig(copyConf);
769 }
770
771 /***
772 * Tests appending a configuration to the test configuration. Again it has
773 * to be ensured that the layout object is correctly updated.
774 */
775 public void testAppendAndSave() throws ConfigurationException
776 {
777 Configuration copyConf = setUpCopyConfig();
778 conf.append(copyConf);
779 checkCopiedConfig(copyConf);
780 }
781
782 /***
783 * Creates a configuration that can be used for testing copy operations.
784 *
785 * @return the configuration to be copied
786 */
787 private Configuration setUpCopyConfig()
788 {
789 final int count = 25;
790 Configuration result = new BaseConfiguration();
791 for (int i = 1; i <= count; i++)
792 {
793 result.addProperty("copyKey" + i, "copyValue" + i);
794 }
795 return result;
796 }
797
798 /***
799 * Tests whether the data of a configuration that was copied into the test
800 * configuration is correctly saved.
801 *
802 * @param copyConf the copied configuration
803 * @throws ConfigurationException if an error occurs
804 */
805 private void checkCopiedConfig(Configuration copyConf)
806 throws ConfigurationException
807 {
808 conf.save(testSavePropertiesFile);
809 PropertiesConfiguration checkConf = new PropertiesConfiguration(
810 testSavePropertiesFile);
811 for (Iterator it = copyConf.getKeys(); it.hasNext();)
812 {
813 String key = (String) it.next();
814 assertEquals("Wrong value for property " + key, checkConf
815 .getProperty(key), copyConf.getProperty(key));
816 }
817 }
818
819 /***
820 * A dummy layout implementation for checking whether certain methods are
821 * correctly called by the configuration.
822 */
823 static class DummyLayout extends PropertiesConfigurationLayout
824 {
825 /*** Stores the number how often load() was called. */
826 public int loadCalls;
827
828 public DummyLayout(PropertiesConfiguration config)
829 {
830 super(config);
831 }
832
833 public void load(Reader in) throws ConfigurationException
834 {
835 loadCalls++;
836 }
837 }
838
839 /***
840 * A mock implementation of a HttpURLConnection used for testing saving to
841 * a HTTP server.
842 */
843 static class MockHttpURLConnection extends HttpURLConnection
844 {
845 /*** The response code to return.*/
846 private int responseCode;
847
848 /*** The output file. The output stream will point to this file.*/
849 private File outputFile;
850
851 protected MockHttpURLConnection(URL u, int respCode, File outFile)
852 {
853 super(u);
854 responseCode = respCode;
855 outputFile = outFile;
856 }
857
858 public void disconnect()
859 {
860 }
861
862 public boolean usingProxy()
863 {
864 return false;
865 }
866
867 public void connect() throws IOException
868 {
869 }
870
871 public int getResponseCode() throws IOException
872 {
873 return responseCode;
874 }
875
876 public OutputStream getOutputStream() throws IOException
877 {
878 return new FileOutputStream(outputFile);
879 }
880 }
881
882 /***
883 * A mock stream handler for working with the mock HttpURLConnection.
884 */
885 static class MockHttpURLStreamHandler extends URLStreamHandler
886 {
887 /*** Stores the response code.*/
888 private int responseCode;
889
890 /*** Stores the output file.*/
891 private File outputFile;
892
893 /*** Stores the connection.*/
894 private MockHttpURLConnection connection;
895
896 public MockHttpURLStreamHandler(int respCode, File outFile)
897 {
898 responseCode = respCode;
899 outputFile = outFile;
900 }
901
902 public MockHttpURLConnection getMockConnection()
903 {
904 return connection;
905 }
906
907 protected URLConnection openConnection(URL u) throws IOException
908 {
909 connection = new MockHttpURLConnection(u, responseCode, outputFile);
910 return connection;
911 }
912 }
913 }