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