1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNotSame;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertSame;
25 import static org.junit.Assert.assertTrue;
26
27 import java.io.File;
28 import java.io.FileWriter;
29 import java.io.IOException;
30 import java.io.PrintWriter;
31 import java.io.StringReader;
32 import java.io.StringWriter;
33 import java.text.MessageFormat;
34 import java.util.Collection;
35 import java.util.List;
36 import java.util.NoSuchElementException;
37 import java.util.Set;
38
39 import junit.framework.Assert;
40
41 import org.apache.commons.configuration.event.ConfigurationEvent;
42 import org.apache.commons.configuration.event.ConfigurationListener;
43 import org.apache.commons.configuration.reloading.FileAlwaysReloadingStrategy;
44 import org.apache.commons.configuration.reloading.FileRandomReloadingStrategy;
45 import org.apache.commons.configuration.tree.DefaultExpressionEngine;
46 import org.apache.commons.configuration.tree.MergeCombiner;
47 import org.apache.commons.configuration.tree.NodeCombiner;
48 import org.apache.commons.configuration.tree.OverrideCombiner;
49 import org.apache.commons.configuration.tree.UnionCombiner;
50 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
51 import org.junit.Before;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.rules.TemporaryFolder;
55
56
57
58
59
60
61 public class TestCombinedConfiguration
62 {
63
64 private static final String TEST_NAME = "SUBCONFIG";
65
66
67 private static final String TEST_KEY = "test.value";
68
69
70 private static final String CHILD1 = TEST_NAME + "1";
71
72
73 private static final String CHILD2 = TEST_NAME + "2";
74
75
76 private static final String RELOAD_XML_NAME = "reload.xml";
77
78
79 private static final String RELOAD_XML_CONTENT = "<xml><xmlReload>{0}</xmlReload></xml>";
80
81
82 private static final String RELOAD_PROPS_NAME = "reload.properties";
83
84
85 private static final String RELOAD_PROPS_CONTENT = "propsReload = {0}";
86
87
88 @Rule
89 public TemporaryFolder folder = new TemporaryFolder();
90
91
92 private CombinedConfiguration config;
93
94
95 private CombinedListener listener;
96
97 @Before
98 public void setUp() throws Exception
99 {
100 config = new CombinedConfiguration();
101 listener = new CombinedListener();
102 config.addConfigurationListener(listener);
103 }
104
105
106
107
108 @Test
109 public void testInit()
110 {
111 assertEquals("Already configurations contained", 0, config
112 .getNumberOfConfigurations());
113 assertTrue("Set of names is not empty", config.getConfigurationNames()
114 .isEmpty());
115 assertTrue("Wrong node combiner",
116 config.getNodeCombiner() instanceof UnionCombiner);
117 assertNull("Test config was found", config.getConfiguration(TEST_NAME));
118 assertFalse("Force reload check flag is set", config.isForceReloadCheck());
119 }
120
121
122
123
124 @Test
125 public void testAddConfiguration()
126 {
127 AbstractConfiguration c = setUpTestConfiguration();
128 config.addConfiguration(c);
129 checkAddConfig(c);
130 assertEquals("Wrong number of configs", 1, config
131 .getNumberOfConfigurations());
132 assertTrue("Name list is not empty", config.getConfigurationNames()
133 .isEmpty());
134 assertSame("Added config not found", c, config.getConfiguration(0));
135 assertTrue("Wrong property value", config.getBoolean(TEST_KEY));
136 listener.checkEvent(1, 0);
137 }
138
139
140
141
142 @Test
143 public void testAddConfigurationWithName()
144 {
145 AbstractConfiguration c = setUpTestConfiguration();
146 config.addConfiguration(c, TEST_NAME);
147 checkAddConfig(c);
148 assertEquals("Wrong number of configs", 1, config
149 .getNumberOfConfigurations());
150 assertSame("Added config not found", c, config.getConfiguration(0));
151 assertSame("Added config not found by name", c, config
152 .getConfiguration(TEST_NAME));
153 Set<String> names = config.getConfigurationNames();
154 assertEquals("Wrong number of config names", 1, names.size());
155 assertTrue("Name not found", names.contains(TEST_NAME));
156 assertTrue("Wrong property value", config.getBoolean(TEST_KEY));
157 listener.checkEvent(1, 0);
158 }
159
160
161
162
163
164 @Test(expected = ConfigurationRuntimeException.class)
165 public void testAddConfigurationWithNameTwice()
166 {
167 config.addConfiguration(setUpTestConfiguration(), TEST_NAME);
168 config.addConfiguration(setUpTestConfiguration(), TEST_NAME,
169 "prefix");
170 }
171
172
173
174
175 @Test
176 public void testAddConfigurationAt()
177 {
178 AbstractConfiguration c = setUpTestConfiguration();
179 config.addConfiguration(c, null, "my");
180 checkAddConfig(c);
181 assertTrue("Wrong property value", config.getBoolean("my." + TEST_KEY));
182 }
183
184
185
186
187
188 @Test
189 public void testAddConfigurationComplexAt()
190 {
191 AbstractConfiguration c = setUpTestConfiguration();
192 config.addConfiguration(c, null, "This..is.a.complex");
193 checkAddConfig(c);
194 assertTrue("Wrong property value", config
195 .getBoolean("This..is.a.complex." + TEST_KEY));
196 }
197
198
199
200
201
202
203 private void checkAddConfig(AbstractConfiguration c)
204 {
205 Collection<ConfigurationListener> listeners = c.getConfigurationListeners();
206 assertEquals("Wrong number of configuration listeners", 1, listeners
207 .size());
208 assertTrue("Combined config is no listener", listeners.contains(config));
209 }
210
211
212
213
214
215 @Test(expected = IllegalArgumentException.class)
216 public void testAddNullConfiguration()
217 {
218 config.addConfiguration(null);
219 }
220
221
222
223
224 @Test
225 public void testAccessPropertyEmpty()
226 {
227 assertFalse("Found a key", config.containsKey(TEST_KEY));
228 assertNull("Key has a value", config.getString("test.comment"));
229 assertTrue("Config is not empty", config.isEmpty());
230 }
231
232
233
234
235 @Test
236 public void testAccessPropertyMulti()
237 {
238 config.addConfiguration(setUpTestConfiguration());
239 config.addConfiguration(setUpTestConfiguration(), null, "prefix1");
240 config.addConfiguration(setUpTestConfiguration(), null, "prefix2");
241 assertTrue("Prop1 not found", config.getBoolean(TEST_KEY));
242 assertTrue("Prop 2 not found", config.getBoolean("prefix1." + TEST_KEY));
243 assertTrue("Prop 3 not found", config.getBoolean("prefix2." + TEST_KEY));
244 assertFalse("Configuration is empty", config.isEmpty());
245 listener.checkEvent(3, 0);
246 }
247
248
249
250
251 @Test
252 public void testRemoveConfiguration()
253 {
254 AbstractConfiguration c = setUpTestConfiguration();
255 config.addConfiguration(c);
256 checkAddConfig(c);
257 assertTrue("Config could not be removed", config.removeConfiguration(c));
258 checkRemoveConfig(c);
259 }
260
261
262
263
264 @Test
265 public void testRemoveConfigurationAt()
266 {
267 AbstractConfiguration c = setUpTestConfiguration();
268 config.addConfiguration(c);
269 assertSame("Wrong config removed", c, config.removeConfigurationAt(0));
270 checkRemoveConfig(c);
271 }
272
273
274
275
276 @Test
277 public void testRemoveConfigurationByName()
278 {
279 AbstractConfiguration c = setUpTestConfiguration();
280 config.addConfiguration(c, TEST_NAME);
281 assertSame("Wrong config removed", c, config
282 .removeConfiguration(TEST_NAME));
283 checkRemoveConfig(c);
284 }
285
286
287
288
289 @Test
290 public void testRemoveNamedConfiguration()
291 {
292 AbstractConfiguration c = setUpTestConfiguration();
293 config.addConfiguration(c, TEST_NAME);
294 config.removeConfiguration(c);
295 checkRemoveConfig(c);
296 }
297
298
299
300
301 @Test
302 public void testRemoveNamedConfigurationAt()
303 {
304 AbstractConfiguration c = setUpTestConfiguration();
305 config.addConfiguration(c, TEST_NAME);
306 assertSame("Wrong config removed", c, config.removeConfigurationAt(0));
307 checkRemoveConfig(c);
308 }
309
310
311
312
313 @Test
314 public void testRemoveNonContainedConfiguration()
315 {
316 assertFalse("Could remove non contained config", config
317 .removeConfiguration(setUpTestConfiguration()));
318 listener.checkEvent(0, 0);
319 }
320
321
322
323
324 @Test
325 public void testRemoveConfigurationByUnknownName()
326 {
327 assertNull("Could remove configuration by unknown name", config
328 .removeConfiguration("unknownName"));
329 listener.checkEvent(0, 0);
330 }
331
332
333
334
335
336
337 private void checkRemoveConfig(AbstractConfiguration c)
338 {
339 assertTrue("Listener was not removed", c.getConfigurationListeners()
340 .isEmpty());
341 assertEquals("Wrong number of contained configs", 0, config
342 .getNumberOfConfigurations());
343 assertTrue("Name was not removed", config.getConfigurationNames()
344 .isEmpty());
345 listener.checkEvent(2, 0);
346 }
347
348
349
350
351
352 @Test
353 public void testUpdateContainedConfiguration()
354 {
355 AbstractConfiguration c = setUpTestConfiguration();
356 config.addConfiguration(c);
357 c.addProperty("test.otherTest", "yes");
358 assertEquals("New property not found", "yes", config
359 .getString("test.otherTest"));
360 listener.checkEvent(2, 0);
361 }
362
363
364
365
366 @Test
367 public void testSetNodeCombiner()
368 {
369 NodeCombiner combiner = new UnionCombiner();
370 config.setNodeCombiner(combiner);
371 assertSame("Node combiner was not set", combiner, config
372 .getNodeCombiner());
373 listener.checkEvent(1, 0);
374 }
375
376
377
378
379 @Test(expected = IllegalArgumentException.class)
380 public void testSetNullNodeCombiner()
381 {
382 config.setNodeCombiner(null);
383 }
384
385
386
387
388 @Test
389 public void testClone()
390 {
391 config.addConfiguration(setUpTestConfiguration());
392 config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
393 config.addConfiguration(new PropertiesConfiguration(), "props");
394
395 CombinedConfiguration cc2 = (CombinedConfiguration) config.clone();
396 assertEquals("Wrong number of contained configurations", config
397 .getNumberOfConfigurations(), cc2.getNumberOfConfigurations());
398 assertSame("Wrong node combiner", config.getNodeCombiner(), cc2
399 .getNodeCombiner());
400 assertEquals("Wrong number of names", config.getConfigurationNames()
401 .size(), cc2.getConfigurationNames().size());
402 assertTrue("Event listeners were cloned", cc2
403 .getConfigurationListeners().isEmpty());
404
405 StrictConfigurationComparator comp = new StrictConfigurationComparator();
406 for (int i = 0; i < config.getNumberOfConfigurations(); i++)
407 {
408 assertNotSame("Configuration at " + i + " was not cloned", config
409 .getConfiguration(i), cc2.getConfiguration(i));
410 assertEquals("Wrong config class at " + i, config.getConfiguration(
411 i).getClass(), cc2.getConfiguration(i).getClass());
412 assertTrue("Configs not equal at " + i, comp.compare(config
413 .getConfiguration(i), cc2.getConfiguration(i)));
414 }
415
416 assertTrue("Combined configs not equal", comp.compare(config, cc2));
417 }
418
419
420
421
422 @Test
423 public void testCloneModify()
424 {
425 config.addConfiguration(setUpTestConfiguration(), TEST_NAME);
426 CombinedConfiguration cc2 = (CombinedConfiguration) config.clone();
427 assertTrue("Name is missing", cc2.getConfigurationNames().contains(
428 TEST_NAME));
429 cc2.removeConfiguration(TEST_NAME);
430 assertFalse("Names in original changed", config.getConfigurationNames()
431 .isEmpty());
432 }
433
434
435
436
437
438 @Test
439 public void testClear()
440 {
441 config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "test");
442 config.addConfiguration(setUpTestConfiguration());
443
444 config.clear();
445 assertEquals("Still configs contained", 0, config
446 .getNumberOfConfigurations());
447 assertTrue("Still names contained", config.getConfigurationNames()
448 .isEmpty());
449 assertTrue("Config is not empty", config.isEmpty());
450
451 listener.checkEvent(3, 2);
452 }
453
454
455
456
457 @Test
458 public void testReloading() throws Exception
459 {
460 config.setForceReloadCheck(true);
461 File testXmlFile = writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 0);
462 File testPropsFile = writeReloadFile(RELOAD_PROPS_NAME, RELOAD_PROPS_CONTENT, 0);
463 XMLConfiguration c1 = new XMLConfiguration(testXmlFile);
464 c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
465 PropertiesConfiguration c2 = new PropertiesConfiguration(testPropsFile);
466 c2.setThrowExceptionOnMissing(true);
467 c2.setReloadingStrategy(new FileAlwaysReloadingStrategy());
468 config.addConfiguration(c1);
469 config.addConfiguration(c2);
470 assertEquals("Wrong xml reload value", 0, config.getInt("xmlReload"));
471 assertEquals("Wrong props reload value", 0, config
472 .getInt("propsReload"));
473
474 writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 1);
475 assertEquals("XML reload not detected", 1, config.getInt("xmlReload"));
476 config.setForceReloadCheck(false);
477 writeReloadFile(RELOAD_PROPS_NAME, RELOAD_PROPS_CONTENT, 1);
478 assertEquals("Props reload detected though check flag is false", 0, config
479 .getInt("propsReload"));
480 }
481
482
483
484
485
486 @Test
487 public void testReloadingSubnodeConfig() throws IOException,
488 ConfigurationException
489 {
490 config.setForceReloadCheck(true);
491 File testXmlFile = writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT,
492 0);
493 XMLConfiguration c1 = new XMLConfiguration(testXmlFile);
494 c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
495 final String prefix = "reloadCheck";
496 config.addConfiguration(c1, CHILD1, prefix);
497 SubnodeConfiguration sub = config.configurationAt(prefix, true);
498 writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 1);
499 assertEquals("Reload not detected", 1, sub.getInt("xmlReload"));
500 }
501
502
503
504
505
506 @Test
507 public void testReloadingNestedCC() throws IOException,
508 ConfigurationException
509 {
510 config.setForceReloadCheck(true);
511 File testXmlFile =
512 writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 0);
513 File testPropsFile =
514 writeReloadFile(RELOAD_PROPS_NAME, RELOAD_PROPS_CONTENT, 0);
515 XMLConfiguration c1 = new XMLConfiguration(testXmlFile);
516 c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
517 PropertiesConfiguration c2 = new PropertiesConfiguration(testPropsFile);
518 c2.setReloadingStrategy(new FileAlwaysReloadingStrategy());
519 config.addConfiguration(c2);
520 CombinedConfiguration cc2 = new CombinedConfiguration();
521 cc2.setForceReloadCheck(true);
522 cc2.addConfiguration(c1);
523 config.addConfiguration(cc2);
524 assertEquals("Wrong xml reload value", 0, config.getInt("xmlReload"));
525 writeReloadFile(RELOAD_XML_NAME, RELOAD_XML_CONTENT, 1);
526 assertEquals("XML reload not detected", 1, config.getInt("xmlReload"));
527 }
528
529
530
531
532 private void setUpSourceTest()
533 {
534 HierarchicalConfiguration c1 = new HierarchicalConfiguration();
535 PropertiesConfiguration c2 = new PropertiesConfiguration();
536 c1.addProperty(TEST_KEY, TEST_NAME);
537 c2.addProperty("another.key", "test");
538 config.addConfiguration(c1, CHILD1);
539 config.addConfiguration(c2, CHILD2);
540 }
541
542
543
544
545
546 @Test
547 public void testGetSourceHierarchical()
548 {
549 setUpSourceTest();
550 assertEquals("Wrong source configuration", config
551 .getConfiguration(CHILD1), config.getSource(TEST_KEY));
552 }
553
554
555
556
557
558 @Test
559 public void testGetSourceNonHierarchical()
560 {
561 setUpSourceTest();
562 assertEquals("Wrong source configuration", config
563 .getConfiguration(CHILD2), config.getSource("another.key"));
564 }
565
566
567
568
569
570 @Test
571 public void testGetSourceUnknown()
572 {
573 setUpSourceTest();
574 assertNull("Wrong result for unknown key", config
575 .getSource("an.unknown.key"));
576 }
577
578
579
580
581
582 @Test(expected = IllegalArgumentException.class)
583 public void testGetSourceNull()
584 {
585 config.getSource(null);
586 }
587
588
589
590
591
592 @Test
593 public void testGetSourceCombined()
594 {
595 setUpSourceTest();
596 final String key = "yet.another.key";
597 config.addProperty(key, Boolean.TRUE);
598 assertEquals("Wrong source for key", config, config.getSource(key));
599 }
600
601
602
603
604
605 @Test
606 public void testGetSourceMulti()
607 {
608 setUpSourceTest();
609 final String key = "list.key";
610 config.getConfiguration(CHILD1).addProperty(key, "1,2,3");
611 assertEquals("Wrong source for multi-value property", config
612 .getConfiguration(CHILD1), config.getSource(key));
613 }
614
615
616
617
618
619 @Test(expected = IllegalArgumentException.class)
620 public void testGetSourceMultiSources()
621 {
622 setUpSourceTest();
623 final String key = "list.key";
624 config.getConfiguration(CHILD1).addProperty(key, "1,2,3");
625 config.getConfiguration(CHILD2).addProperty(key, "a,b,c");
626 config.getSource(key);
627 }
628
629
630
631
632 @Test
633 public void testEscapeListDelimiters()
634 {
635 PropertiesConfiguration sub = new PropertiesConfiguration();
636 sub.addProperty("test.pi", "3\\,1415");
637 config.addConfiguration(sub);
638 assertEquals("Wrong value", "3,1415", config.getString("test.pi"));
639 }
640
641
642
643
644
645 @Test
646 public void testInvalidateAfterChange()
647 {
648 ConfigurationEvent event = new ConfigurationEvent(config, 0, null,
649 null, true);
650 config.configurationChanged(event);
651 assertEquals("Invalidate event fired", 0, listener.invalidateEvents);
652 event = new ConfigurationEvent(config, 0, null, null, false);
653 config.configurationChanged(event);
654 assertEquals("No invalidate event fired", 1, listener.invalidateEvents);
655 }
656
657
658
659
660
661 @Test
662 public void testConversionExpressionEngine()
663 {
664 PropertiesConfiguration child = new PropertiesConfiguration();
665 child.addProperty("test(a)", "1,2,3");
666 config.addConfiguration(child);
667 DefaultExpressionEngine engineQuery = new DefaultExpressionEngine();
668 engineQuery.setIndexStart("<");
669 engineQuery.setIndexEnd(">");
670 config.setExpressionEngine(engineQuery);
671 DefaultExpressionEngine engineConvert = new DefaultExpressionEngine();
672 engineConvert.setIndexStart("[");
673 engineConvert.setIndexEnd("]");
674 config.setConversionExpressionEngine(engineConvert);
675 assertEquals("Wrong property 1", "1", config.getString("test(a)<0>"));
676 assertEquals("Wrong property 2", "2", config.getString("test(a)<1>"));
677 assertEquals("Wrong property 3", "3", config.getString("test(a)<2>"));
678 }
679
680
681
682
683
684
685 @Test
686 public void testDeadlockWithReload() throws ConfigurationException,
687 InterruptedException
688 {
689 final PropertiesConfiguration child = new PropertiesConfiguration(
690 "test.properties");
691 child.setReloadingStrategy(new FileAlwaysReloadingStrategy());
692 config.addConfiguration(child);
693 final int count = 1000;
694
695 class TestDeadlockReloadThread extends Thread
696 {
697 boolean error = false;
698
699 @Override
700 public void run()
701 {
702 for (int i = 0; i < count && !error; i++)
703 {
704 try
705 {
706 if (!child.getBoolean("configuration.loaded"))
707 {
708 error = true;
709 }
710 }
711 catch (NoSuchElementException nsex)
712 {
713 error = true;
714 }
715 }
716 }
717 }
718
719 TestDeadlockReloadThread reloadThread = new TestDeadlockReloadThread();
720 reloadThread.start();
721 for (int i = 0; i < count; i++)
722 {
723 assertEquals("Wrong value of combined property", 10, config
724 .getInt("test.integer"));
725 }
726 reloadThread.join();
727 assertFalse("Failure in thread", reloadThread.error);
728 }
729
730 @Test
731 public void testGetConfigurations() throws Exception
732 {
733 config.addConfiguration(setUpTestConfiguration());
734 config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
735 AbstractConfiguration pc = new PropertiesConfiguration();
736 config.addConfiguration(pc, "props");
737 List<AbstractConfiguration> list = config.getConfigurations();
738 assertNotNull("No list of configurations returned", list);
739 assertTrue("Incorrect number of configurations", list.size() == 3);
740 AbstractConfiguration c = list.get(2);
741 assertTrue("Incorrect configuration", c == pc);
742 }
743
744 @Test
745 public void testGetConfigurationNameList() throws Exception
746 {
747 config.addConfiguration(setUpTestConfiguration());
748 config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
749 AbstractConfiguration pc = new PropertiesConfiguration();
750 config.addConfiguration(pc, "props");
751 List<String> list = config.getConfigurationNameList();
752 assertNotNull("No list of configurations returned", list);
753 assertTrue("Incorrect number of configurations", list.size() == 3);
754 String name = list.get(1);
755 assertNotNull("No name returned", name);
756 assertTrue("Incorrect configuration name", TEST_NAME.equals(name));
757 }
758
759
760
761
762
763
764 @Test
765 public void testReloadWithSubNodeConfig() throws Exception
766 {
767 final String reloadContent = "<config><default><xmlReload1>{0}</xmlReload1></default></config>";
768 config.setForceReloadCheck(true);
769 config.setNodeCombiner(new OverrideCombiner());
770 File testXmlFile1 = writeReloadFile(RELOAD_XML_NAME, reloadContent, 0);
771 final String prefix1 = "default";
772 XMLConfiguration c1 = new XMLConfiguration(testXmlFile1);
773 SubnodeConfiguration sub1 = c1.configurationAt(prefix1, true);
774 assertEquals("Inital test for sub config 1 failed", 0, sub1
775 .getInt("xmlReload1"));
776 config.addConfiguration(sub1);
777 assertEquals(
778 "Could not get value for sub config 1 from combined config", 0,
779 config.getInt("xmlReload1"));
780 c1.setReloadingStrategy(new FileAlwaysReloadingStrategy());
781 writeReloadFile(RELOAD_XML_NAME, reloadContent, 1);
782 assertEquals("Reload of sub config 1 not detected", 1, config
783 .getInt("xmlReload1"));
784 }
785
786 @Test
787 public void testConcurrentGetAndReload() throws Exception
788 {
789 final int threadCount = 5;
790 final int loopCount = 1000;
791 config.setForceReloadCheck(true);
792 config.setNodeCombiner(new MergeCombiner());
793 final XMLConfiguration xml = new XMLConfiguration("configA.xml");
794 xml.setReloadingStrategy(new FileRandomReloadingStrategy());
795 config.addConfiguration(xml);
796 final XMLConfiguration xml2 = new XMLConfiguration("configB.xml");
797 xml2.setReloadingStrategy(new FileRandomReloadingStrategy());
798 config.addConfiguration(xml2);
799 config.setExpressionEngine(new XPathExpressionEngine());
800
801 assertEquals(config.getString("/property[@name='config']/@value"), "100");
802
803 Thread testThreads[] = new Thread[threadCount];
804 int failures[] = new int[threadCount];
805
806 for (int i = 0; i < testThreads.length; ++i)
807 {
808 testThreads[i] = new ReloadThread(config, failures, i, loopCount);
809 testThreads[i].start();
810 }
811
812 int totalFailures = 0;
813 for (int i = 0; i < testThreads.length; ++i)
814 {
815 testThreads[i].join();
816 totalFailures += failures[i];
817 }
818 assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
819 }
820
821
822
823
824
825 @Test
826 public void testCombinedCopyToXML() throws ConfigurationException
827 {
828 XMLConfiguration x1 = new XMLConfiguration();
829 x1.addProperty("key1", "value1");
830 x1.addProperty("key1[@override]", "USER1");
831 x1.addProperty("key2", "value2");
832 x1.addProperty("key2[@override]", "USER2");
833 XMLConfiguration x2 = new XMLConfiguration();
834 x2.addProperty("key2", "value2.2");
835 x2.addProperty("key2[@override]", "USER2");
836 config.setNodeCombiner(new OverrideCombiner());
837 config.addConfiguration(x2);
838 config.addConfiguration(x1);
839 XMLConfiguration x3 = new XMLConfiguration(config);
840 assertEquals("Wrong element value", "value2.2", x3.getString("key2"));
841 assertEquals("Wrong attribute value", "USER2",
842 x3.getString("key2[@override]"));
843 StringWriter w = new StringWriter();
844 x3.save(w);
845 String s = w.toString();
846 x3 = new XMLConfiguration();
847 x3.load(new StringReader(s));
848 assertEquals("Wrong element value after load", "value2.2",
849 x3.getString("key2"));
850 assertEquals("Wrong attribute value after load", "USER2",
851 x3.getString("key2[@override]"));
852 }
853
854 private class ReloadThread extends Thread
855 {
856 CombinedConfiguration combined;
857 int[] failures;
858 int index;
859 int count;
860
861 ReloadThread(CombinedConfiguration config, int[] failures, int index, int count)
862 {
863 combined = config;
864 this.failures = failures;
865 this.index = index;
866 this.count = count;
867 }
868 @Override
869 public void run()
870 {
871 failures[index] = 0;
872 for (int i = 0; i < count; i++)
873 {
874 try
875 {
876 String value = combined.getString("/property[@name='config']/@value");
877 if (value == null || !value.equals("100"))
878 {
879 ++failures[index];
880 }
881 }
882 catch (Exception ex)
883 {
884 ++failures[index];
885 }
886 }
887 }
888 }
889
890
891
892
893
894
895
896
897
898 private void writeFile(File file, String content) throws IOException
899 {
900 PrintWriter out = null;
901 try
902 {
903 out = new PrintWriter(new FileWriter(file));
904 out.print(content);
905 }
906 finally
907 {
908 if (out != null)
909 {
910 out.close();
911 }
912 }
913 }
914
915
916
917
918
919
920
921
922
923
924
925 private File writeFile(String fileName, String content) throws IOException
926 {
927 File file = new File(folder.getRoot(), fileName);
928 writeFile(file, content);
929 return file;
930 }
931
932
933
934
935
936
937
938
939
940
941 private File writeReloadFile(String name, String content, int value)
942 throws IOException
943 {
944 return writeFile(name, MessageFormat.format(content, new Object[] {
945 new Integer(value)
946 }));
947 }
948
949
950
951
952
953
954
955 private AbstractConfiguration setUpTestConfiguration()
956 {
957 HierarchicalConfiguration config = new HierarchicalConfiguration();
958 config.addProperty(TEST_KEY, Boolean.TRUE);
959 config.addProperty("test.comment", "This is a test");
960 return config;
961 }
962
963
964
965
966
967 static class CombinedListener implements ConfigurationListener
968 {
969 int invalidateEvents;
970
971 int otherEvents;
972
973 public void configurationChanged(ConfigurationEvent event)
974 {
975 if (event.getType() == CombinedConfiguration.EVENT_COMBINED_INVALIDATE)
976 {
977 invalidateEvents++;
978 }
979 else
980 {
981 otherEvents++;
982 }
983 }
984
985
986
987
988
989
990
991 public void checkEvent(int expectedInvalidate, int expectedOthers)
992 {
993 Assert.assertEquals("Wrong number of invalidate events",
994 expectedInvalidate, invalidateEvents);
995 Assert.assertEquals("Wrong number of other events", expectedOthers,
996 otherEvents);
997 }
998 }
999 }