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.util.ArrayList;
21 import java.util.Collection;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Set;
26
27 import org.apache.commons.collections.CollectionUtils;
28 import org.apache.commons.configuration.HierarchicalConfiguration.Node;
29 import org.apache.commons.configuration.event.ConfigurationEvent;
30 import org.apache.commons.configuration.event.ConfigurationListener;
31 import org.apache.commons.configuration.tree.DefaultConfigurationNode;
32 import org.apache.commons.configuration.tree.DefaultExpressionEngine;
33 import org.apache.commons.configuration.tree.ExpressionEngine;
34
35 import junit.framework.TestCase;
36
37 /***
38 * Test class for HierarchicalConfiguration.
39 *
40 * @version $Id: TestHierarchicalConfiguration.java 589136 2007-10-27 15:38:15Z oheger $
41 */
42 public class TestHierarchicalConfiguration extends TestCase
43 {
44 private static String[] tables = { "users", "documents" };
45
46 private static String[][] fields =
47 {
48 { "uid", "uname", "firstName", "lastName", "email" },
49 { "docid", "name", "creationDate", "authorID", "version" }
50 };
51
52 private HierarchicalConfiguration config;
53
54 protected void setUp() throws Exception
55 {
56 /***
57 * Initialize the configuration with the following structure:
58 *
59 * tables
60 * table
61 * name
62 * fields
63 * field
64 * name
65 * field
66 * name
67 */
68 config = new HierarchicalConfiguration();
69 HierarchicalConfiguration.Node nodeTables = createNode("tables", null);
70 for(int i = 0; i < tables.length; i++)
71 {
72 HierarchicalConfiguration.Node nodeTable = createNode("table", null);
73 nodeTables.addChild(nodeTable);
74 HierarchicalConfiguration.Node nodeName = createNode("name", tables[i]);
75 nodeTable.addChild(nodeName);
76 HierarchicalConfiguration.Node nodeFields = createNode("fields", null);
77 nodeTable.addChild(nodeFields);
78
79 for (int j = 0; j < fields[i].length; j++)
80 {
81 nodeFields.addChild(createFieldNode(fields[i][j]));
82 }
83 }
84
85 config.getRoot().addChild(nodeTables);
86 }
87
88 public void testSetRoot()
89 {
90 try
91 {
92 config.setRoot(null);
93 fail("Could set null root node!");
94 }
95 catch(IllegalArgumentException iex)
96 {
97
98 }
99
100 config.setRoot(new HierarchicalConfiguration.Node("test"));
101 assertTrue(config.isEmpty());
102 }
103
104 public void testSetRootNode()
105 {
106 config.setRootNode(new DefaultConfigurationNode("testNode"));
107 assertNotSame("Same root node", config.getRootNode(), config.getRoot());
108 assertEquals("Wrong name of root node", "testNode", config.getRoot().getName());
109
110 config.setRootNode(new HierarchicalConfiguration.Node("test"));
111 assertSame("Wrong root node", config.getRootNode(), config.getRoot());
112 }
113
114 public void testSetRootNodeNull()
115 {
116 try
117 {
118 config.setRootNode(null);
119 fail("Could set null root node!");
120 }
121 catch(IllegalArgumentException iex)
122 {
123
124 }
125 }
126
127 public void testIsEmpty()
128 {
129 assertFalse(config.isEmpty());
130 HierarchicalConfiguration conf2 = new HierarchicalConfiguration();
131 assertTrue(conf2.isEmpty());
132 HierarchicalConfiguration.Node child1 = new HierarchicalConfiguration.Node("child1");
133 HierarchicalConfiguration.Node child2 = new HierarchicalConfiguration.Node("child2");
134 child1.addChild(child2);
135 conf2.getRoot().addChild(child1);
136 assertTrue(conf2.isEmpty());
137 }
138
139 public void testGetProperty()
140 {
141 assertNull(config.getProperty("tables.table.resultset"));
142 assertNull(config.getProperty("tables.table.fields.field"));
143
144 Object prop = config.getProperty("tables.table(0).fields.field.name");
145 assertNotNull(prop);
146 assertTrue(prop instanceof Collection);
147 assertEquals(5, ((Collection) prop).size());
148
149 prop = config.getProperty("tables.table.fields.field.name");
150 assertNotNull(prop);
151 assertTrue(prop instanceof Collection);
152 assertEquals(10, ((Collection) prop).size());
153
154 prop = config.getProperty("tables.table.fields.field(3).name");
155 assertNotNull(prop);
156 assertTrue(prop instanceof Collection);
157 assertEquals(2, ((Collection) prop).size());
158
159 prop = config.getProperty("tables.table(1).fields.field(2).name");
160 assertNotNull(prop);
161 assertEquals("creationDate", prop.toString());
162 }
163
164 public void testSetProperty()
165 {
166 config.setProperty("tables.table(0).name", "resources");
167 assertEquals("resources", config.getString("tables.table(0).name"));
168 config.setProperty("tables.table.name", "tab1,tab2");
169 assertEquals("tab1", config.getString("tables.table(0).name"));
170 assertEquals("tab2", config.getString("tables.table(1).name"));
171
172 config.setProperty("test.items.item", new int[] { 2, 4, 8, 16 });
173 assertEquals(3, config.getMaxIndex("test.items.item"));
174 assertEquals(8, config.getInt("test.items.item(2)"));
175 config.setProperty("test.items.item(2)", new Integer(6));
176 assertEquals(6, config.getInt("test.items.item(2)"));
177 config.setProperty("test.items.item(2)", new int[] { 7, 9, 11 });
178 assertEquals(5, config.getMaxIndex("test.items.item"));
179
180 config.setProperty("test", Boolean.TRUE);
181 config.setProperty("test.items", "01/01/05");
182 assertEquals(5, config.getMaxIndex("test.items.item"));
183 assertTrue(config.getBoolean("test"));
184 assertEquals("01/01/05", config.getProperty("test.items"));
185
186 config.setProperty("test.items.item", new Integer(42));
187 assertEquals(0, config.getMaxIndex("test.items.item"));
188 assertEquals(42, config.getInt("test.items.item"));
189 }
190
191 public void testClearProperty()
192 {
193 config.clearProperty("tables.table(0).fields.field(0).name");
194 assertEquals("uname", config.getProperty("tables.table(0).fields.field(0).name"));
195 config.clearProperty("tables.table(0).name");
196 assertFalse(config.containsKey("tables.table(0).name"));
197 assertEquals("firstName", config.getProperty("tables.table(0).fields.field(1).name"));
198 assertEquals("documents", config.getProperty("tables.table.name"));
199 config.clearProperty("tables.table");
200 assertEquals("documents", config.getProperty("tables.table.name"));
201
202 config.addProperty("test", "first");
203 config.addProperty("test.level", "second");
204 config.clearProperty("test");
205 assertEquals("second", config.getString("test.level"));
206 assertFalse(config.containsKey("test"));
207 }
208
209 public void testClearTree()
210 {
211 Object prop = config.getProperty("tables.table(0).fields.field.name");
212 assertNotNull(prop);
213 config.clearTree("tables.table(0).fields.field(3)");
214 prop = config.getProperty("tables.table(0).fields.field.name");
215 assertNotNull(prop);
216 assertTrue(prop instanceof Collection);
217 assertEquals(4, ((Collection) prop).size());
218
219 config.clearTree("tables.table(0).fields");
220 assertNull(config.getProperty("tables.table(0).fields.field.name"));
221 prop = config.getProperty("tables.table.fields.field.name");
222 assertNotNull(prop);
223 assertTrue(prop instanceof Collection);
224 assertEquals(5, ((Collection) prop).size());
225
226 config.clearTree("tables.table(1)");
227 assertNull(config.getProperty("tables.table.fields.field.name"));
228 }
229
230 /***
231 * Tests removing more complex node structures.
232 */
233 public void testClearTreeComplex()
234 {
235 final int count = 5;
236
237 for (int idx = 0; idx < count; idx++)
238 {
239 config.addProperty("indexList.index(-1)[@default]", Boolean.FALSE);
240 config.addProperty("indexList.index[@name]", "test" + idx);
241 config.addProperty("indexList.index.dir", "testDir" + idx);
242 }
243 assertEquals("Wrong number of nodes", count - 1, config
244 .getMaxIndex("indexList.index[@name]"));
245
246
247 boolean found = false;
248 for (int idx = 0; true; idx++)
249 {
250 String name = config.getString("indexList.index(" + idx
251 + ")[@name]");
252 if (name == null)
253 {
254 break;
255 }
256 if ("test3".equals(name))
257 {
258 assertEquals("Wrong dir", "testDir3", config
259 .getString("indexList.index(" + idx + ").dir"));
260 config.clearTree("indexList.index(" + idx + ")");
261 found = true;
262 }
263 }
264 assertTrue("Key to remove not found", found);
265 assertEquals("Wrong number of nodes after remove", count - 2, config
266 .getMaxIndex("indexList.index[@name]"));
267 assertEquals("Wrong number of dir nodes after remove", count - 2,
268 config.getMaxIndex("indexList.index.dir"));
269
270
271 for (int idx = 0; true; idx++)
272 {
273 String name = config.getString("indexList.index(" + idx
274 + ")[@name]");
275 if (name == null)
276 {
277 break;
278 }
279 if ("test3".equals(name))
280 {
281 fail("Key was not removed!");
282 }
283 }
284 }
285
286 /***
287 * Tests the clearTree() method on a hierarchical structure of nodes. This
288 * is a test case for CONFIGURATION-293.
289 */
290 public void testClearTreeHierarchy()
291 {
292 config.addProperty("a.b.c", "c");
293 config.addProperty("a.b.c.d", "d");
294 config.addProperty("a.b.c.d.e", "e");
295 config.clearTree("a.b.c");
296 assertFalse("Property not removed", config.containsKey("a.b.c"));
297 assertFalse("Sub property not removed", config.containsKey("a.b.c.d"));
298 }
299
300 public void testContainsKey()
301 {
302 assertTrue(config.containsKey("tables.table(0).name"));
303 assertTrue(config.containsKey("tables.table(1).name"));
304 assertFalse(config.containsKey("tables.table(2).name"));
305
306 assertTrue(config.containsKey("tables.table(0).fields.field.name"));
307 assertFalse(config.containsKey("tables.table(0).fields.field"));
308 config.clearTree("tables.table(0).fields");
309 assertFalse(config.containsKey("tables.table(0).fields.field.name"));
310
311 assertTrue(config.containsKey("tables.table.fields.field.name"));
312 }
313
314 public void testGetKeys()
315 {
316 List keys = new ArrayList();
317 for (Iterator it = config.getKeys(); it.hasNext();)
318 {
319 keys.add(it.next());
320 }
321
322 assertEquals(2, keys.size());
323 assertTrue(keys.contains("tables.table.name"));
324 assertTrue(keys.contains("tables.table.fields.field.name"));
325
326
327 config.addProperty("order.key1", "value1");
328 config.addProperty("order.key2", "value2");
329 config.addProperty("order.key3", "value3");
330
331 Iterator it = config.getKeys("order");
332 assertEquals("1st key", "order.key1", it.next());
333 assertEquals("2nd key", "order.key2", it.next());
334 assertEquals("3rd key", "order.key3", it.next());
335 }
336
337 public void testGetKeysString()
338 {
339
340 config.addProperty("tables.table(0).fields.field(1).type", "VARCHAR");
341 config.addProperty("tables.table(0)[@type]", "system");
342 config.addProperty("tables.table(0).size", "42");
343 config.addProperty("tables.table(0).fields.field(0).size", "128");
344 config.addProperty("connections.connection.param.url", "url1");
345 config.addProperty("connections.connection.param.user", "me");
346 config.addProperty("connections.connection.param.pwd", "secret");
347 config.addProperty("connections.connection(-1).param.url", "url2");
348 config.addProperty("connections.connection(1).param.user", "guest");
349
350 checkKeys("tables.table(1)", new String[] { "name", "fields.field.name" });
351 checkKeys("tables.table(0)",
352 new String[] { "name", "fields.field.name", "tables.table(0)[@type]", "size", "fields.field.type", "fields.field.size" });
353 checkKeys("connections.connection(0).param",
354 new String[] {"url", "user", "pwd" });
355 checkKeys("connections.connection(1).param",
356 new String[] {"url", "user" });
357 }
358
359 public void testAddProperty()
360 {
361 config.addProperty("tables.table(0).fields.field(-1).name", "phone");
362 Object prop = config.getProperty("tables.table(0).fields.field.name");
363 assertNotNull(prop);
364 assertTrue(prop instanceof Collection);
365 assertEquals(6, ((Collection) prop).size());
366
367 config.addProperty("tables.table(0).fields.field.name", "fax");
368 prop = config.getProperty("tables.table.fields.field(5).name");
369 assertNotNull(prop);
370 assertTrue(prop instanceof List);
371 List list = (List) prop;
372 assertEquals("phone", list.get(0));
373 assertEquals("fax", list.get(1));
374
375 config.addProperty("tables.table(-1).name", "config");
376 prop = config.getProperty("tables.table.name");
377 assertNotNull(prop);
378 assertTrue(prop instanceof Collection);
379 assertEquals(3, ((Collection) prop).size());
380 config.addProperty("tables.table(2).fields.field(0).name", "cid");
381 config.addProperty("tables.table(2).fields.field(-1).name",
382 "confName");
383 prop = config.getProperty("tables.table(2).fields.field.name");
384 assertNotNull(prop);
385 assertTrue(prop instanceof Collection);
386 assertEquals(2, ((Collection) prop).size());
387 assertEquals("confName",
388 config.getProperty("tables.table(2).fields.field(1).name"));
389
390 config.addProperty("connection.user", "scott");
391 config.addProperty("connection.passwd", "tiger");
392 assertEquals("tiger", config.getProperty("connection.passwd"));
393
394 ConfigurationKey key = new ConfigurationKey();
395 key.append("tables").append("table").appendIndex(0);
396 key.appendAttribute("tableType");
397 config.addProperty(key.toString(), "system");
398 assertEquals("system", config.getProperty(key.toString()));
399
400 try
401 {
402 config.addProperty(".", "InvalidKey");
403 fail("Could add invalid key!");
404 }
405 catch(IllegalArgumentException iex)
406 {
407
408 }
409 }
410
411 public void testGetMaxIndex()
412 {
413 assertEquals(4, config.getMaxIndex("tables.table(0).fields.field"));
414 assertEquals(4, config.getMaxIndex("tables.table(1).fields.field"));
415 assertEquals(1, config.getMaxIndex("tables.table"));
416 assertEquals(1, config.getMaxIndex("tables.table.name"));
417 assertEquals(0, config.getMaxIndex("tables.table(0).name"));
418 assertEquals(0, config.getMaxIndex("tables.table(1).fields.field(1)"));
419 assertEquals(-1, config.getMaxIndex("tables.table(2).fields"));
420
421 int maxIdx = config.getMaxIndex("tables.table(0).fields.field.name");
422 for(int i = 0; i <= maxIdx; i++)
423 {
424 ConfigurationKey key = new ConfigurationKey("tables.table(0).fields");
425 key.append("field").appendIndex(i).append("name");
426 assertNotNull(config.getProperty(key.toString()));
427 }
428 }
429
430 public void testSubset()
431 {
432
433 Configuration subset = config.subset("tables.table(0)");
434 assertEquals(tables[0], subset.getProperty("name"));
435
436 Object prop = subset.getProperty("fields.field.name");
437 assertNotNull(prop);
438 assertTrue(prop instanceof Collection);
439 assertEquals(5, ((Collection) prop).size());
440
441 for (int i = 0; i < fields[0].length; i++)
442 {
443 ConfigurationKey key = new ConfigurationKey();
444 key.append("fields").append("field").appendIndex(i);
445 key.append("name");
446 assertEquals(fields[0][i], subset.getProperty(key.toString()));
447 }
448
449
450 assertTrue("subset is not empty", config.subset("tables.table(2)").isEmpty());
451
452
453 subset = config.subset("tables.table.fields.field");
454 prop = subset.getProperty("name");
455 assertTrue("prop is not a collection", prop instanceof Collection);
456 assertEquals(10, ((Collection) prop).size());
457
458 assertEquals(fields[0][0], subset.getProperty("name(0)"));
459
460
461 subset = config.subset("tables.table.fields.field.name");
462 assertTrue("subset is not empty", subset.isEmpty());
463 }
464
465 /***
466 * Tests the subset() method when the specified node has a value. This value
467 * must be available in the subset, too. Related to CONFIGURATION-295.
468 */
469 public void testSubsetNodeWithValue()
470 {
471 config.setProperty("tables.table(0).fields", "My fields");
472 Configuration subset = config.subset("tables.table(0).fields");
473 assertEquals("Wrong field name", fields[0][0], subset
474 .getString("field(0).name"));
475 assertEquals("Wrong value of root", "My fields", subset.getString(""));
476 }
477
478 /***
479 * Tests the subset() method when the specified key selects multiple keys.
480 * The resulting root node should have a value only if exactly one of the
481 * selected nodes has a value. Related to CONFIGURATION-295.
482 */
483 public void testSubsetMultipleNodesWithValues()
484 {
485 config.setProperty("tables.table(0).fields", "My fields");
486 Configuration subset = config.subset("tables.table.fields");
487 assertEquals("Wrong value of root", "My fields", subset.getString(""));
488 config.setProperty("tables.table(1).fields", "My other fields");
489 subset = config.subset("tables.table.fields");
490 assertNull("Root value is not null though there are multiple values",
491 subset.getString(""));
492 }
493
494 /***
495 * Tests the configurationAt() method to obtain a configuration for a sub
496 * tree.
497 */
498 public void testConfigurationAt()
499 {
500 HierarchicalConfiguration subConfig = config
501 .configurationAt("tables.table(1)");
502 assertEquals("Wrong table name", tables[1], subConfig.getString("name"));
503 List lstFlds = subConfig.getList("fields.field.name");
504 assertEquals("Wrong number of fields", fields[1].length, lstFlds.size());
505 for (int i = 0; i < fields[1].length; i++)
506 {
507 assertEquals("Wrong field at position " + i, fields[1][i], lstFlds
508 .get(i));
509 }
510
511 subConfig.setProperty("name", "testTable");
512 assertEquals("Change not visible in parent", "testTable", config
513 .getString("tables.table(1).name"));
514 config.setProperty("tables.table(1).fields.field(2).name", "testField");
515 assertEquals("Change not visible in sub config", "testField", subConfig
516 .getString("fields.field(2).name"));
517 }
518
519 /***
520 * Tests the configurationAt() method when the passed in key does not exist.
521 */
522 public void testConfigurationAtUnknownSubTree()
523 {
524 try
525 {
526 config.configurationAt("non.existing.key");
527 fail("Could obtain sub config for unknown key!");
528 }
529 catch (IllegalArgumentException iex)
530 {
531
532 }
533 }
534
535 /***
536 * Tests the configurationAt() method when the passed in key selects
537 * multiple nodes. This should cause an exception.
538 */
539 public void testConfigurationAtMultipleNodes()
540 {
541 try
542 {
543 config.configurationAt("tables.table.name");
544 fail("Could create sub config with non unique key!");
545 }
546 catch (IllegalArgumentException iex)
547 {
548
549 }
550 }
551
552 /***
553 * Tests the configurationsAt() method.
554 */
555 public void testConfigurationsAt()
556 {
557 List lstFlds = config.configurationsAt("tables.table(1).fields.field");
558 assertEquals("Wrong size of fields", fields[1].length, lstFlds.size());
559 for (int i = 0; i < fields[1].length; i++)
560 {
561 HierarchicalConfiguration sub = (HierarchicalConfiguration) lstFlds
562 .get(i);
563 assertEquals("Wrong field at position " + i, fields[1][i], sub
564 .getString("name"));
565 }
566 }
567
568 /***
569 * Tests the configurationsAt() method when the passed in key does not
570 * select any sub nodes.
571 */
572 public void testConfigurationsAtEmpty()
573 {
574 assertTrue("List is not empty", config.configurationsAt("unknown.key")
575 .isEmpty());
576 }
577
578 public void testClone()
579 {
580 Configuration copy = (Configuration) config.clone();
581 assertTrue(copy instanceof HierarchicalConfiguration);
582 checkContent(copy);
583 }
584
585 /***
586 * Tests whether registered event handlers are handled correctly when a
587 * configuration is cloned. They should not be registered at the clone.
588 */
589 public void testCloneWithEventListeners()
590 {
591 config.addConfigurationListener(new ConfigurationListener()
592 {
593 public void configurationChanged(ConfigurationEvent event)
594 {
595
596 }
597 });
598 HierarchicalConfiguration copy = (HierarchicalConfiguration) config
599 .clone();
600 assertTrue("Event listener registered at clone", copy
601 .getConfigurationListeners().isEmpty());
602 }
603
604 public void testAddNodes()
605 {
606 Collection nodes = new ArrayList();
607 nodes.add(createFieldNode("birthDate"));
608 nodes.add(createFieldNode("lastLogin"));
609 nodes.add(createFieldNode("language"));
610 config.addNodes("tables.table(0).fields", nodes);
611 assertEquals(7, config.getMaxIndex("tables.table(0).fields.field"));
612 assertEquals("birthDate", config.getString("tables.table(0).fields.field(5).name"));
613 assertEquals("lastLogin", config.getString("tables.table(0).fields.field(6).name"));
614 assertEquals("language", config.getString("tables.table(0).fields.field(7).name"));
615 }
616
617 /***
618 * Tests the addNodes() method when the provided key does not exist. In
619 * this case, a new node (or even a complete new branch) will be created.
620 */
621 public void testAddNodesForNonExistingKey()
622 {
623 Collection nodes = new ArrayList();
624 nodes.add(createNode("usr", "scott"));
625 Node nd = createNode("pwd", "tiger");
626 nd.setAttribute(true);
627 nodes.add(nd);
628 config.addNodes("database.connection.settings", nodes);
629
630 assertEquals("Usr node not found", "scott", config.getString("database.connection.settings.usr"));
631 assertEquals("Pwd node not found", "tiger", config.getString("database.connection.settings[@pwd]"));
632 }
633
634 /***
635 * Tests the addNodes() method when the new nodes should be added to an
636 * attribute node. This is not allowed.
637 */
638 public void testAddNodesWithAttributeKey()
639 {
640 Collection nodes = new ArrayList();
641 nodes.add(createNode("testNode", "yes"));
642 try
643 {
644 config.addNodes("database.connection[@settings]", nodes);
645 fail("Could add nodes to an attribute node!");
646 }
647 catch(IllegalArgumentException iex)
648 {
649
650 }
651 }
652
653 /***
654 * Tests copying nodes from one configuration to another one.
655 */
656 public void testAddNodesCopy()
657 {
658 HierarchicalConfiguration configDest = new HierarchicalConfiguration();
659 configDest.addProperty("test", "TEST");
660 Collection nodes = config.getRootNode().getChildren();
661 assertEquals("Wrong number of children", 1, nodes.size());
662 configDest.addNodes("newNodes", nodes);
663 for (int i = 0; i < tables.length; i++)
664 {
665 String keyTab = "newNodes.tables.table(" + i + ").";
666 assertEquals("Table " + i + " not found", tables[i], configDest
667 .getString(keyTab + "name"));
668 for (int j = 0; j < fields[i].length; j++)
669 {
670 assertEquals("Invalid field " + j + " in table " + i,
671 fields[i][j], configDest.getString(keyTab
672 + "fields.field(" + j + ").name"));
673 }
674 }
675 }
676
677 /***
678 * Tests removing children from a configuration node.
679 */
680 public void testNodeRemove()
681 {
682 HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(
683 "parent", "test");
684 assertFalse(node.hasChildren());
685 node.removeChildren();
686 assertFalse(node.remove("child"));
687
688 node.addChild(createNode("test", "test"));
689 assertTrue(node.hasChildren());
690 assertTrue(node.remove("test"));
691 assertFalse(node.hasChildren());
692
693 for (int i = 0; i < 10; i++)
694 {
695 node.addChild(createNode("child" + i, "test" + i));
696 }
697 assertTrue(node.hasChildren());
698 assertFalse(node.remove("child"));
699 assertTrue(node.remove("child2"));
700 assertTrue(node.getChildren("child2").isEmpty());
701
702 HierarchicalConfiguration.Node child = createNode("child0", "testChild");
703 assertFalse(node.remove(child));
704 node.addChild(child);
705 assertTrue(node.remove(child));
706 assertEquals(1, node.getChildren("child0").size());
707 assertEquals("test0", ((HierarchicalConfiguration.Node) node
708 .getChildren("child0").get(0)).getValue());
709
710 assertTrue(node.remove("child0"));
711 assertFalse(node.remove(child));
712
713 node.removeChildren();
714 assertTrue(node.getChildren().isEmpty());
715 assertFalse(node.remove(child));
716 }
717
718 /***
719 * Tests the visitor mechanism.
720 */
721 public void testNodeVisitor()
722 {
723 CountVisitor v = new CountVisitor();
724 config.getRoot().visit(v, null);
725 assertEquals(28, v.beforeCount);
726 assertEquals(v.beforeCount, v.afterCount);
727 }
728
729 /***
730 * Tests setting a custom expression engine, which uses a slightly different
731 * syntax.
732 */
733 public void testSetExpressionEngine()
734 {
735 config.setExpressionEngine(null);
736 assertNotNull("Expression engine is null", config.getExpressionEngine());
737 assertSame("Default engine is not used", HierarchicalConfiguration
738 .getDefaultExpressionEngine(), config.getExpressionEngine());
739
740 config.setExpressionEngine(createAlternativeExpressionEngine());
741 checkAlternativeSyntax();
742 }
743
744 /***
745 * Tests setting the default expression engine. This should impact all
746 * configuration instances that do not have their own engine.
747 */
748 public void testSetDefaultExpressionEngine()
749 {
750 ExpressionEngine engineOld = HierarchicalConfiguration.getDefaultExpressionEngine();
751 HierarchicalConfiguration
752 .setDefaultExpressionEngine(createAlternativeExpressionEngine());
753 checkAlternativeSyntax();
754 HierarchicalConfiguration.setDefaultExpressionEngine(engineOld);
755 }
756
757 /***
758 * Tests setting the default expression engine to null. This should not be
759 * allowed.
760 */
761 public void testSetDefaultExpressionEngineNull()
762 {
763 try
764 {
765 HierarchicalConfiguration.setDefaultExpressionEngine(null);
766 fail("Could set default expression engine to null!");
767 }
768 catch (IllegalArgumentException iex)
769 {
770
771 }
772 }
773
774 /***
775 * Tests the copy constructor.
776 */
777 public void testInitCopy()
778 {
779 HierarchicalConfiguration copy = new HierarchicalConfiguration(config);
780 checkContent(copy);
781 }
782
783 /***
784 * Tests whether the nodes of a copied configuration are independent from
785 * the source configuration.
786 */
787 public void testInitCopyUpdate()
788 {
789 HierarchicalConfiguration copy = new HierarchicalConfiguration(config);
790 config.setProperty("tables.table(0).name", "NewTable");
791 checkContent(copy);
792 }
793
794 /***
795 * Tests interpolation facilities.
796 */
797 public void testInterpolation()
798 {
799 config.addProperty("base.dir", "/home/foo");
800 config.addProperty("test.absolute.dir.dir1", "${base.dir}/path1");
801 config.addProperty("test.absolute.dir.dir2", "${base.dir}/path2");
802 config.addProperty("test.absolute.dir.dir3", "${base.dir}/path3");
803
804 Configuration sub = config.subset("test.absolute.dir");
805 for (int i = 1; i < 4; i++)
806 {
807 assertEquals("Wrong interpolation in parent", "/home/foo/path" + i,
808 config.getString("test.absolute.dir.dir" + i));
809 assertEquals("Wrong interpolation in subnode",
810 "/home/foo/path" + i, sub.getString("dir" + i));
811 }
812 }
813
814 /***
815 * Basic interpolation tests.
816 */
817 public void testInterpolationBasic()
818 {
819 InterpolationTestHelper.testInterpolation(config);
820 }
821
822 /***
823 * Tests multiple levels of interpolation.
824 */
825 public void testInterpolationMultipleLevels()
826 {
827 InterpolationTestHelper.testMultipleInterpolation(config);
828 }
829
830 /***
831 * Tests an invalid interpolation that causes an endless loop.
832 */
833 public void testInterpolationLoop()
834 {
835 InterpolationTestHelper.testInterpolationLoop(config);
836 }
837
838 /***
839 * Tests interpolation with a subset.
840 */
841 public void testInterpolationSubset()
842 {
843 InterpolationTestHelper.testInterpolationSubset(config);
844 }
845
846 /***
847 * Tests interpolation of a variable, which cannot be resolved.
848 */
849 public void testInterpolationUnknownProperty()
850 {
851 InterpolationTestHelper.testInterpolationUnknownProperty(config);
852 }
853
854 /***
855 * Tests interpolation with system properties.
856 */
857 public void testInterpolationSysProperties()
858 {
859 InterpolationTestHelper.testInterpolationSystemProperties(config);
860 }
861
862 /***
863 * Tests interpolation with constant values.
864 */
865 public void testInterpolationConstants()
866 {
867 InterpolationTestHelper.testInterpolationConstants(config);
868 }
869
870 /***
871 * Tests escaping variables.
872 */
873 public void testInterpolationEscaped()
874 {
875 InterpolationTestHelper.testInterpolationEscaped(config);
876 }
877
878 /***
879 * Tests manipulating the interpolator.
880 */
881 public void testInterpolator()
882 {
883 InterpolationTestHelper.testGetInterpolator(config);
884 }
885
886 /***
887 * Tests obtaining a configuration with all variables substituted.
888 */
889 public void testInterpolatedConfiguration()
890 {
891 HierarchicalConfiguration c = (HierarchicalConfiguration) InterpolationTestHelper
892 .testInterpolatedConfiguration(config);
893
894
895 config = c;
896 testGetProperty();
897 }
898
899 /***
900 * Tests the copy constructor when a null reference is passed.
901 */
902 public void testInitCopyNull()
903 {
904 HierarchicalConfiguration copy = new HierarchicalConfiguration(null);
905 assertTrue("Configuration not empty", copy.isEmpty());
906 }
907
908 /***
909 * Helper method for testing the getKeys(String) method.
910 *
911 * @param prefix the key to pass into getKeys()
912 * @param expected the expected result
913 */
914 private void checkKeys(String prefix, String[] expected)
915 {
916 Set values = new HashSet();
917 for(int i = 0; i < expected.length; i++)
918 {
919 values.add((expected[i].startsWith(prefix)) ? expected[i] : prefix + "." + expected[i]);
920 }
921
922 Iterator itKeys = config.getKeys(prefix);
923 while(itKeys.hasNext())
924 {
925 String key = (String) itKeys.next();
926 if(!values.contains(key))
927 {
928 fail("Found unexpected key: " + key);
929 }
930 else
931 {
932 values.remove(key);
933 }
934 }
935
936 assertTrue("Remaining keys " + values, values.isEmpty());
937 }
938
939 /***
940 * Helper method for checking keys using an alternative syntax.
941 */
942 private void checkAlternativeSyntax()
943 {
944 assertNull(config.getProperty("tables/table/resultset"));
945 assertNull(config.getProperty("tables/table/fields/field"));
946
947 Object prop = config.getProperty("tables/table[0]/fields/field/name");
948 assertNotNull(prop);
949 assertTrue(prop instanceof Collection);
950 assertEquals(5, ((Collection) prop).size());
951
952 prop = config.getProperty("tables/table/fields/field/name");
953 assertNotNull(prop);
954 assertTrue(prop instanceof Collection);
955 assertEquals(10, ((Collection) prop).size());
956
957 prop = config.getProperty("tables/table/fields/field[3]/name");
958 assertNotNull(prop);
959 assertTrue(prop instanceof Collection);
960 assertEquals(2, ((Collection) prop).size());
961
962 prop = config.getProperty("tables/table[1]/fields/field[2]/name");
963 assertNotNull(prop);
964 assertEquals("creationDate", prop.toString());
965
966 Set keys = new HashSet();
967 CollectionUtils.addAll(keys, config.getKeys());
968 assertEquals("Wrong number of defined keys", 2, keys.size());
969 assertTrue("Key not found", keys.contains("tables/table/name"));
970 assertTrue("Key not found", keys
971 .contains("tables/table/fields/field/name"));
972 }
973
974 /***
975 * Checks the content of the passed in configuration object. Used by some
976 * tests that copy a configuration.
977 *
978 * @param c the configuration to check
979 */
980 private void checkContent(Configuration c)
981 {
982 for (int i = 0; i < tables.length; i++)
983 {
984 assertEquals(tables[i], c.getString("tables.table(" + i + ").name"));
985 for (int j = 0; j < fields[i].length; j++)
986 {
987 assertEquals(fields[i][j], c.getString("tables.table(" + i
988 + ").fields.field(" + j + ").name"));
989 }
990 }
991 }
992
993 private ExpressionEngine createAlternativeExpressionEngine()
994 {
995 DefaultExpressionEngine engine = new DefaultExpressionEngine();
996 engine.setPropertyDelimiter("/");
997 engine.setIndexStart("[");
998 engine.setIndexEnd("]");
999 return engine;
1000 }
1001
1002 /***
1003 * Helper method for creating a field node with its children.
1004 *
1005 * @param name the name of the field
1006 * @return the field node
1007 */
1008 private static HierarchicalConfiguration.Node createFieldNode(String name)
1009 {
1010 HierarchicalConfiguration.Node fld = createNode("field", null);
1011 fld.addChild(createNode("name", name));
1012 return fld;
1013 }
1014
1015 /***
1016 * Helper method for creating a configuration node.
1017 * @param name the node's name
1018 * @param value the node's value
1019 * @return the new node
1020 */
1021 private static HierarchicalConfiguration.Node createNode(String name, Object value)
1022 {
1023 HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(name);
1024 node.setValue(value);
1025 return node;
1026 }
1027
1028 /***
1029 * A test visitor implementation for checking whether all visitor methods
1030 * are correctly called.
1031 */
1032 static class CountVisitor extends HierarchicalConfiguration.NodeVisitor
1033 {
1034 public int beforeCount;
1035
1036 public int afterCount;
1037
1038 public void visitAfterChildren(Node node, ConfigurationKey key)
1039 {
1040 super.visitAfterChildren(node, key);
1041 afterCount++;
1042 }
1043
1044 public void visitBeforeChildren(Node node, ConfigurationKey key)
1045 {
1046 super.visitBeforeChildren(node, key);
1047 beforeCount++;
1048 }
1049 }
1050 }