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 java.util.Collection;
20 import java.util.Set;
21
22 import org.apache.commons.configuration.event.ConfigurationEvent;
23 import org.apache.commons.configuration.event.ConfigurationListener;
24 import org.apache.commons.configuration.tree.NodeCombiner;
25 import org.apache.commons.configuration.tree.UnionCombiner;
26
27 import junit.framework.Assert;
28 import junit.framework.TestCase;
29
30 /***
31 * Test class for CombinedConfiguration.
32 *
33 * @version $Id: TestCombinedConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
34 */
35 public class TestCombinedConfiguration extends TestCase
36 {
37 /*** Constant for the name of a sub configuration. */
38 static final String TEST_NAME = "SUBCONFIG";
39
40 /*** Constant for a test key. */
41 static final String TEST_KEY = "test.value";
42
43 /*** The configuration to be tested. */
44 CombinedConfiguration config;
45
46 /*** The test event listener. */
47 CombinedListener listener;
48
49 protected void setUp() throws Exception
50 {
51 super.setUp();
52 config = new CombinedConfiguration();
53 listener = new CombinedListener();
54 config.addConfigurationListener(listener);
55 }
56
57 /***
58 * Tests accessing a newly created combined configuration.
59 */
60 public void testInit()
61 {
62 assertEquals("Already configurations contained", 0, config
63 .getNumberOfConfigurations());
64 assertTrue("Set of names is not empty", config.getConfigurationNames()
65 .isEmpty());
66 assertTrue("Wrong node combiner",
67 config.getNodeCombiner() instanceof UnionCombiner);
68 assertNull("Test config was found", config.getConfiguration(TEST_NAME));
69 }
70
71 /***
72 * Tests adding a configuration (without further information).
73 */
74 public void testAddConfiguration()
75 {
76 AbstractConfiguration c = setUpTestConfiguration();
77 config.addConfiguration(c);
78 checkAddConfig(c);
79 assertEquals("Wrong number of configs", 1, config
80 .getNumberOfConfigurations());
81 assertTrue("Name list is not empty", config.getConfigurationNames()
82 .isEmpty());
83 assertSame("Added config not found", c, config.getConfiguration(0));
84 assertTrue("Wrong property value", config.getBoolean(TEST_KEY));
85 listener.checkEvent(1, 0);
86 }
87
88 /***
89 * Tests adding a configuration with a name.
90 */
91 public void testAddConfigurationWithName()
92 {
93 AbstractConfiguration c = setUpTestConfiguration();
94 config.addConfiguration(c, TEST_NAME);
95 checkAddConfig(c);
96 assertEquals("Wrong number of configs", 1, config
97 .getNumberOfConfigurations());
98 assertSame("Added config not found", c, config.getConfiguration(0));
99 assertSame("Added config not found by name", c, config
100 .getConfiguration(TEST_NAME));
101 Set names = config.getConfigurationNames();
102 assertEquals("Wrong number of config names", 1, names.size());
103 assertTrue("Name not found", names.contains(TEST_NAME));
104 assertTrue("Wrong property value", config.getBoolean(TEST_KEY));
105 listener.checkEvent(1, 0);
106 }
107
108 /***
109 * Tests adding a configuration with a name when this name already exists.
110 * This should cause an exception.
111 */
112 public void testAddConfigurationWithNameTwice()
113 {
114 config.addConfiguration(setUpTestConfiguration(), TEST_NAME);
115 try
116 {
117 config.addConfiguration(setUpTestConfiguration(), TEST_NAME,
118 "prefix");
119 fail("Could add config with same name!");
120 }
121 catch (ConfigurationRuntimeException cex)
122 {
123
124 }
125 }
126
127 /***
128 * Tests adding a configuration and specifying an at position.
129 */
130 public void testAddConfigurationAt()
131 {
132 AbstractConfiguration c = setUpTestConfiguration();
133 config.addConfiguration(c, null, "my");
134 checkAddConfig(c);
135 assertTrue("Wrong property value", config.getBoolean("my." + TEST_KEY));
136 }
137
138 /***
139 * Tests adding a configuration with a complex at position. Here the at path
140 * contains a dot, which must be escaped.
141 */
142 public void testAddConfigurationComplexAt()
143 {
144 AbstractConfiguration c = setUpTestConfiguration();
145 config.addConfiguration(c, null, "This..is.a.complex");
146 checkAddConfig(c);
147 assertTrue("Wrong property value", config
148 .getBoolean("This..is.a.complex." + TEST_KEY));
149 }
150
151 /***
152 * Checks if a configuration was correctly added to the combined config.
153 *
154 * @param c the config to check
155 */
156 private void checkAddConfig(AbstractConfiguration c)
157 {
158 Collection listeners = c.getConfigurationListeners();
159 assertEquals("Wrong number of configuration listeners", 1, listeners
160 .size());
161 assertTrue("Combined config is no listener", listeners.contains(config));
162 }
163
164 /***
165 * Tests adding a null configuration. This should cause an exception to be
166 * thrown.
167 */
168 public void testAddNullConfiguration()
169 {
170 try
171 {
172 config.addConfiguration(null);
173 fail("Could add null configuration!");
174 }
175 catch (IllegalArgumentException iex)
176 {
177
178 }
179 }
180
181 /***
182 * Tests accessing properties if no configurations have been added.
183 */
184 public void testAccessPropertyEmpty()
185 {
186 assertFalse("Found a key", config.containsKey(TEST_KEY));
187 assertNull("Key has a value", config.getString("test.comment"));
188 assertTrue("Config is not empty", config.isEmpty());
189 }
190
191 /***
192 * Tests accessing properties if multiple configurations have been added.
193 */
194 public void testAccessPropertyMulti()
195 {
196 config.addConfiguration(setUpTestConfiguration());
197 config.addConfiguration(setUpTestConfiguration(), null, "prefix1");
198 config.addConfiguration(setUpTestConfiguration(), null, "prefix2");
199 assertTrue("Prop1 not found", config.getBoolean(TEST_KEY));
200 assertTrue("Prop 2 not found", config.getBoolean("prefix1." + TEST_KEY));
201 assertTrue("Prop 3 not found", config.getBoolean("prefix2." + TEST_KEY));
202 assertFalse("Configuration is empty", config.isEmpty());
203 listener.checkEvent(3, 0);
204 }
205
206 /***
207 * Tests removing a configuration.
208 */
209 public void testRemoveConfiguration()
210 {
211 AbstractConfiguration c = setUpTestConfiguration();
212 config.addConfiguration(c);
213 checkAddConfig(c);
214 assertTrue("Config could not be removed", config.removeConfiguration(c));
215 checkRemoveConfig(c);
216 }
217
218 /***
219 * Tests removing a configuration by index.
220 */
221 public void testRemoveConfigurationAt()
222 {
223 AbstractConfiguration c = setUpTestConfiguration();
224 config.addConfiguration(c);
225 assertSame("Wrong config removed", c, config.removeConfigurationAt(0));
226 checkRemoveConfig(c);
227 }
228
229 /***
230 * Tests removing a configuration by name.
231 */
232 public void testRemoveConfigurationByName()
233 {
234 AbstractConfiguration c = setUpTestConfiguration();
235 config.addConfiguration(c, TEST_NAME);
236 assertSame("Wrong config removed", c, config
237 .removeConfiguration(TEST_NAME));
238 checkRemoveConfig(c);
239 }
240
241 /***
242 * Tests removing a configuration with a name.
243 */
244 public void testRemoveNamedConfiguration()
245 {
246 AbstractConfiguration c = setUpTestConfiguration();
247 config.addConfiguration(c, TEST_NAME);
248 config.removeConfiguration(c);
249 checkRemoveConfig(c);
250 }
251
252 /***
253 * Tests removing a named configuration by index.
254 */
255 public void testRemoveNamedConfigurationAt()
256 {
257 AbstractConfiguration c = setUpTestConfiguration();
258 config.addConfiguration(c, TEST_NAME);
259 assertSame("Wrong config removed", c, config.removeConfigurationAt(0));
260 checkRemoveConfig(c);
261 }
262
263 /***
264 * Tests removing a configuration that was not added prior.
265 */
266 public void testRemoveNonContainedConfiguration()
267 {
268 assertFalse("Could remove non contained config", config
269 .removeConfiguration(setUpTestConfiguration()));
270 listener.checkEvent(0, 0);
271 }
272
273 /***
274 * Tests removing a configuration by name, which is not contained.
275 */
276 public void testRemoveConfigurationByUnknownName()
277 {
278 assertNull("Could remove configuration by unknown name", config
279 .removeConfiguration("unknownName"));
280 listener.checkEvent(0, 0);
281 }
282
283 /***
284 * Tests whether a configuration was completely removed.
285 *
286 * @param c the removed configuration
287 */
288 private void checkRemoveConfig(AbstractConfiguration c)
289 {
290 assertTrue("Listener was not removed", c.getConfigurationListeners()
291 .isEmpty());
292 assertEquals("Wrong number of contained configs", 0, config
293 .getNumberOfConfigurations());
294 assertTrue("Name was not removed", config.getConfigurationNames()
295 .isEmpty());
296 listener.checkEvent(2, 0);
297 }
298
299 /***
300 * Tests if an update of a contained configuration leeds to an invalidation
301 * of the combined configuration.
302 */
303 public void testUpdateContainedConfiguration()
304 {
305 AbstractConfiguration c = setUpTestConfiguration();
306 config.addConfiguration(c);
307 c.addProperty("test.otherTest", "yes");
308 assertEquals("New property not found", "yes", config
309 .getString("test.otherTest"));
310 listener.checkEvent(3, 0);
311 }
312
313 /***
314 * Tests if setting a node combiner causes an invalidation.
315 */
316 public void testSetNodeCombiner()
317 {
318 NodeCombiner combiner = new UnionCombiner();
319 config.setNodeCombiner(combiner);
320 assertSame("Node combiner was not set", combiner, config
321 .getNodeCombiner());
322 listener.checkEvent(1, 0);
323 }
324
325 /***
326 * Tests setting a null node combiner. This should cause an exception.
327 */
328 public void testSetNullNodeCombiner()
329 {
330 try
331 {
332 config.setNodeCombiner(null);
333 fail("Could set null node combiner!");
334 }
335 catch (IllegalArgumentException iex)
336 {
337
338 }
339 }
340
341 /***
342 * Tests cloning a combined configuration.
343 */
344 public void testClone()
345 {
346 config.addConfiguration(setUpTestConfiguration());
347 config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "conf2");
348 config.addConfiguration(new PropertiesConfiguration(), "props");
349
350 CombinedConfiguration cc2 = (CombinedConfiguration) config.clone();
351 assertEquals("Wrong number of contained configurations", config
352 .getNumberOfConfigurations(), cc2.getNumberOfConfigurations());
353 assertSame("Wrong node combiner", config.getNodeCombiner(), cc2
354 .getNodeCombiner());
355 assertEquals("Wrong number of names", config.getConfigurationNames()
356 .size(), cc2.getConfigurationNames().size());
357 assertTrue("Event listeners were cloned", cc2
358 .getConfigurationListeners().isEmpty());
359
360 StrictConfigurationComparator comp = new StrictConfigurationComparator();
361 for (int i = 0; i < config.getNumberOfConfigurations(); i++)
362 {
363 assertNotSame("Configuration at " + i + " was not cloned", config
364 .getConfiguration(i), cc2.getConfiguration(i));
365 assertEquals("Wrong config class at " + i, config.getConfiguration(
366 i).getClass(), cc2.getConfiguration(i).getClass());
367 assertTrue("Configs not equal at " + i, comp.compare(config
368 .getConfiguration(i), cc2.getConfiguration(i)));
369 }
370
371 assertTrue("Combined configs not equal", comp.compare(config, cc2));
372 }
373
374 /***
375 * Tests if the cloned configuration is decoupled from the original.
376 */
377 public void testCloneModify()
378 {
379 config.addConfiguration(setUpTestConfiguration(), TEST_NAME);
380 CombinedConfiguration cc2 = (CombinedConfiguration) config.clone();
381 assertTrue("Name is missing", cc2.getConfigurationNames().contains(
382 TEST_NAME));
383 cc2.removeConfiguration(TEST_NAME);
384 assertFalse("Names in original changed", config.getConfigurationNames()
385 .isEmpty());
386 }
387
388 /***
389 * Tests clearing a combined configuration. This should remove all contained
390 * configurations.
391 */
392 public void testClear()
393 {
394 config.addConfiguration(setUpTestConfiguration(), TEST_NAME, "test");
395 config.addConfiguration(setUpTestConfiguration());
396
397 config.clear();
398 assertEquals("Still configs contained", 0, config
399 .getNumberOfConfigurations());
400 assertTrue("Still names contained", config.getConfigurationNames()
401 .isEmpty());
402 assertTrue("Config is not empty", config.isEmpty());
403
404 listener.checkEvent(3, 2);
405 }
406
407 /***
408 * Helper method for creating a test configuration to be added to the
409 * combined configuration.
410 *
411 * @return the test configuration
412 */
413 private AbstractConfiguration setUpTestConfiguration()
414 {
415 HierarchicalConfiguration config = new HierarchicalConfiguration();
416 config.addProperty(TEST_KEY, Boolean.TRUE);
417 config.addProperty("test.comment", "This is a test");
418 return config;
419 }
420
421 /***
422 * Test event listener class for checking if the expected invalidate events
423 * are fired.
424 */
425 static class CombinedListener implements ConfigurationListener
426 {
427 int invalidateEvents;
428
429 int otherEvents;
430
431 public void configurationChanged(ConfigurationEvent event)
432 {
433 if (event.getType() == CombinedConfiguration.EVENT_COMBINED_INVALIDATE)
434 {
435 invalidateEvents++;
436 }
437 else
438 {
439 otherEvents++;
440 }
441 }
442
443 /***
444 * Checks if the expected number of events was fired.
445 *
446 * @param expectedInvalidate the expected number of invalidate events
447 * @param expectedOthers the expected number of other events
448 */
449 public void checkEvent(int expectedInvalidate, int expectedOthers)
450 {
451 Assert.assertEquals("Wrong number of invalidate events",
452 expectedInvalidate, invalidateEvents);
453 Assert.assertEquals("Wrong number of other events", expectedOthers,
454 otherEvents);
455 }
456 }
457 }