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.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.commons.collections.CollectionUtils;
28 import org.apache.commons.configuration.event.ConfigurationEvent;
29 import org.apache.commons.configuration.event.ConfigurationListener;
30
31 import junit.framework.TestCase;
32
33 /***
34 * A test class for some of the basic functionality implemented by
35 * AbstractConfiguration.
36 *
37 * @version $Id: TestAbstractConfigurationBasicFeatures.java 567771 2007-08-20 17:57:08Z oheger $
38 */
39 public class TestAbstractConfigurationBasicFeatures extends TestCase
40 {
41 /*** Constant for the prefix of test keys.*/
42 private static final String KEY_PREFIX = "key";
43
44 /*** Constant for the number of properties in tests for copy operations.*/
45 private static final int PROP_COUNT = 12;
46
47 /***
48 * Tests the clear() implementation of AbstractConfiguration if the iterator
49 * returned by getKeys() does not support the remove() operation.
50 */
51 public void testClearIteratorNoRemove()
52 {
53 AbstractConfiguration config = new TestConfigurationImpl(
54 new BaseConfiguration())
55 {
56
57 public Iterator getKeys()
58 {
59 Collection keyCol = new ArrayList();
60 CollectionUtils.addAll(keyCol, getUnderlyingConfiguration()
61 .getKeys());
62 Object[] keys = keyCol.toArray();
63 return Arrays.asList(keys).iterator();
64 }
65 };
66 for (int i = 0; i < 20; i++)
67 {
68 config.addProperty("key" + i, "value" + i);
69 }
70 config.clear();
71 assertTrue("Configuration not empty", config.isEmpty());
72 }
73
74 /***
75 * Tests escaping the variable marker, so that no interpolation will be
76 * performed.
77 */
78 public void testInterpolateEscape()
79 {
80 AbstractConfiguration config = new TestConfigurationImpl(
81 new PropertiesConfiguration());
82 config
83 .addProperty(
84 "mypath",
85 "$${DB2UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc.jar//,$${DB2UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc_license_cu.jar");
86 assertEquals(
87 "Wrong interpolated value",
88 "${DB2UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc.jar,${DB2UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc_license_cu.jar",
89 config.getString("mypath"));
90 }
91
92 /***
93 * Tests adding list properties. The single elements of the list should be
94 * added.
95 */
96 public void testAddPropertyList()
97 {
98 checkAddListProperty(new TestConfigurationImpl(
99 new PropertiesConfiguration()));
100 }
101
102 /***
103 * Tests adding list properties when delimiter parsing is disabled.
104 */
105 public void testAddPropertyListNoDelimiterParsing()
106 {
107 AbstractConfiguration config = new TestConfigurationImpl(
108 new PropertiesConfiguration());
109 config.setDelimiterParsingDisabled(true);
110 checkAddListProperty(config);
111 }
112
113 /***
114 * Helper method for adding properties with multiple values.
115 *
116 * @param config the configuration to be used for testing
117 */
118 private void checkAddListProperty(AbstractConfiguration config)
119 {
120 config.addProperty("test", "value1");
121 Object[] lstValues1 = new Object[]
122 { "value2", "value3" };
123 Object[] lstValues2 = new Object[]
124 { "value4", "value5", "value6" };
125 config.addProperty("test", lstValues1);
126 config.addProperty("test", Arrays.asList(lstValues2));
127 List lst = config.getList("test");
128 assertEquals("Wrong number of list elements", 6, lst.size());
129 for (int i = 0; i < lst.size(); i++)
130 {
131 assertEquals("Wrong list element at " + i, "value" + (i + 1), lst
132 .get(i));
133 }
134 }
135
136 /***
137 * Tests the copy() method.
138 */
139 public void testCopy()
140 {
141 AbstractConfiguration config = setUpDestConfig();
142 Configuration srcConfig = setUpSourceConfig();
143 config.copy(srcConfig);
144 for (int i = 0; i < PROP_COUNT; i++)
145 {
146 String key = KEY_PREFIX + i;
147 if (srcConfig.containsKey(key))
148 {
149 assertEquals("Value not replaced: " + key, srcConfig
150 .getProperty(key), config.getProperty(key));
151 }
152 else
153 {
154 assertEquals("Value modified: " + key, "value" + i, config
155 .getProperty(key));
156 }
157 }
158 }
159
160 /***
161 * Tests the copy() method when properties with multiple values and escaped
162 * list delimiters are involved.
163 */
164 public void testCopyWithLists()
165 {
166 Configuration srcConfig = setUpSourceConfig();
167 AbstractConfiguration config = setUpDestConfig();
168 config.copy(srcConfig);
169 checkListProperties(config);
170 }
171
172 /***
173 * Tests the events generated by a copy() operation.
174 */
175 public void testCopyEvents()
176 {
177 AbstractConfiguration config = setUpDestConfig();
178 Configuration srcConfig = setUpSourceConfig();
179 CollectingConfigurationListener l = new CollectingConfigurationListener();
180 config.addConfigurationListener(l);
181 config.copy(srcConfig);
182 checkCopyEvents(l, srcConfig, AbstractConfiguration.EVENT_SET_PROPERTY);
183 }
184
185 /***
186 * Tests copying a null configuration. This should be a noop.
187 */
188 public void testCopyNull()
189 {
190 AbstractConfiguration config = setUpDestConfig();
191 config.copy(null);
192 ConfigurationAssert.assertEquals(setUpDestConfig(), config);
193 }
194
195 /***
196 * Tests the append() method.
197 */
198 public void testAppend()
199 {
200 AbstractConfiguration config = setUpDestConfig();
201 Configuration srcConfig = setUpSourceConfig();
202 config.append(srcConfig);
203 for (int i = 0; i < PROP_COUNT; i++)
204 {
205 String key = KEY_PREFIX + i;
206 if (srcConfig.containsKey(key))
207 {
208 List values = config.getList(key);
209 assertEquals("Value not added: " + key, 2, values.size());
210 assertEquals("Wrong value 1 for " + key, "value" + i, values
211 .get(0));
212 assertEquals("Wrong value 2 for " + key, "src" + i, values
213 .get(1));
214 }
215 else
216 {
217 assertEquals("Value modified: " + key, "value" + i, config
218 .getProperty(key));
219 }
220 }
221 }
222
223 /***
224 * Tests the append() method when properties with multiple values and
225 * escaped list delimiters are involved.
226 */
227 public void testAppendWithLists()
228 {
229 AbstractConfiguration config = setUpDestConfig();
230 config.append(setUpSourceConfig());
231 checkListProperties(config);
232 }
233
234 /***
235 * Tests the events generated by an append() operation.
236 */
237 public void testAppendEvents()
238 {
239 AbstractConfiguration config = setUpDestConfig();
240 Configuration srcConfig = setUpSourceConfig();
241 CollectingConfigurationListener l = new CollectingConfigurationListener();
242 config.addConfigurationListener(l);
243 config.append(srcConfig);
244 checkCopyEvents(l, srcConfig, AbstractConfiguration.EVENT_ADD_PROPERTY);
245 }
246
247 /***
248 * Tests appending a null configuration. This should be a noop.
249 */
250 public void testAppendNull()
251 {
252 AbstractConfiguration config = setUpDestConfig();
253 config.append(null);
254 ConfigurationAssert.assertEquals(setUpDestConfig(), config);
255 }
256
257 /***
258 * Creates the source configuration for testing the copy() and append()
259 * methods. This configuration contains keys with an odd index and values
260 * starting with the prefix "src". There are also some list properties.
261 *
262 * @return the source configuration for copy operations
263 */
264 private Configuration setUpSourceConfig()
265 {
266 BaseConfiguration config = new BaseConfiguration();
267 for (int i = 1; i < PROP_COUNT; i += 2)
268 {
269 config.addProperty(KEY_PREFIX + i, "src" + i);
270 }
271 config.addProperty("list1", "1,2,3");
272 config.addProperty("list2", "3//,1415,9//,81");
273 return config;
274 }
275
276 /***
277 * Creates the destination configuration for testing the copy() and append()
278 * methods. This configuration contains keys with a running index and
279 * corresponding values starting with the prefix "value".
280 *
281 * @return the destination configuration for copy operations
282 */
283 private AbstractConfiguration setUpDestConfig()
284 {
285 AbstractConfiguration config = new TestConfigurationImpl(
286 new PropertiesConfiguration());
287 for (int i = 0; i < PROP_COUNT; i++)
288 {
289 config.addProperty(KEY_PREFIX + i, "value" + i);
290 }
291 return config;
292 }
293
294 /***
295 * Tests the values of list properties after a copy operation.
296 *
297 * @param config the configuration to test
298 */
299 private void checkListProperties(Configuration config)
300 {
301 List values = config.getList("list1");
302 assertEquals("Wrong number of elements in list 1", 3, values.size());
303 values = config.getList("list2");
304 assertEquals("Wrong number of elements in list 2", 2, values.size());
305 assertEquals("Wrong value 1", "3,1415", values.get(0));
306 assertEquals("Wrong value 2", "9,81", values.get(1));
307 }
308
309 /***
310 * Tests whether the correct events are received for a copy operation.
311 *
312 * @param l the event listener
313 * @param src the configuration that was copied
314 * @param eventType the expected event type
315 */
316 private void checkCopyEvents(CollectingConfigurationListener l,
317 Configuration src, int eventType)
318 {
319 Map events = new HashMap();
320 for (Iterator it = l.events.iterator(); it.hasNext();)
321 {
322 ConfigurationEvent e = (ConfigurationEvent) it.next();
323 assertEquals("Wrong event type", eventType, e.getType());
324 assertTrue("Unknown property: " + e.getPropertyName(), src
325 .containsKey(e.getPropertyName()));
326 assertEquals("Wrong property value for " + e.getPropertyName(), e
327 .getPropertyValue(), src.getProperty(e.getPropertyName()));
328 if (!e.isBeforeUpdate())
329 {
330 assertTrue("After event without before event", events
331 .containsKey(e.getPropertyName()));
332 }
333 else
334 {
335 events.put(e.getPropertyName(), e);
336 }
337 }
338
339 for (Iterator it = src.getKeys(); it.hasNext();)
340 {
341 String key = (String) it.next();
342 assertTrue("No event received for key " + key, events
343 .containsKey(key));
344 }
345 }
346
347 /***
348 * A test configuration implementation. This implementation inherits
349 * directly from AbstractConfiguration. For implementing the required
350 * functionality another implementation of AbstractConfiguration is used;
351 * all methods that need to be implemented delegate to this wrapped
352 * configuration.
353 */
354 static class TestConfigurationImpl extends AbstractConfiguration
355 {
356 /*** Stores the underlying configuration. */
357 private AbstractConfiguration config;
358
359 public AbstractConfiguration getUnderlyingConfiguration()
360 {
361 return config;
362 }
363
364 public TestConfigurationImpl(AbstractConfiguration wrappedConfig)
365 {
366 config = wrappedConfig;
367 }
368
369 protected void addPropertyDirect(String key, Object value)
370 {
371 config.addPropertyDirect(key, value);
372 }
373
374 public boolean containsKey(String key)
375 {
376 return config.containsKey(key);
377 }
378
379 public Iterator getKeys()
380 {
381 return config.getKeys();
382 }
383
384 public Object getProperty(String key)
385 {
386 return config.getProperty(key);
387 }
388
389 public boolean isEmpty()
390 {
391 return config.isEmpty();
392 }
393
394 protected void clearPropertyDirect(String key)
395 {
396 config.clearPropertyDirect(key);
397 }
398 }
399
400 /***
401 * An event listener implementation that simply collects all received
402 * configuration events.
403 */
404 static class CollectingConfigurationListener implements
405 ConfigurationListener
406 {
407 List events = new ArrayList();
408
409 public void configurationChanged(ConfigurationEvent event)
410 {
411 events.add(event);
412 }
413 }
414 }