001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.configuration.tree; 018 019 import static org.junit.Assert.assertEquals; 020 import static org.junit.Assert.assertFalse; 021 import static org.junit.Assert.assertNotSame; 022 import static org.junit.Assert.assertNull; 023 import static org.junit.Assert.assertSame; 024 import static org.junit.Assert.assertTrue; 025 026 import java.util.Iterator; 027 import java.util.List; 028 import java.util.StringTokenizer; 029 030 import org.junit.Before; 031 import org.junit.Test; 032 033 /** 034 * Test class for DefaultConfigurationNode. 035 * 036 * @author <a 037 * href="http://commons.apache.org/configuration/team-list.html">Commons 038 * Configuration team</a> 039 * @version $Id: TestDefaultConfigurationNode.java 1225917 2011-12-30 20:42:09Z oheger $ 040 */ 041 public class TestDefaultConfigurationNode 042 { 043 /** Constant array for the field names. */ 044 private static final String[] FIELD_NAMES = 045 { "UID", "NAME", "FIRSTNAME", "LASTLOGIN"}; 046 047 /** Constant array for the field data types. */ 048 private static final String[] FIELD_TYPES = 049 { "long", "string", "string", "date"}; 050 051 /** Constant array for additional field attributes. */ 052 private static final String[] FIELD_ATTRS = 053 { "primarykey,unique", "notnull", "notnull", null}; 054 055 /** The node to be tested. */ 056 DefaultConfigurationNode node; 057 058 @Before 059 public void setUp() throws Exception 060 { 061 node = new DefaultConfigurationNode(); 062 node.setName("table"); 063 node.setReference("TestReference"); 064 node.addAttribute(new DefaultConfigurationNode("type", "system")); 065 node.addChild(new DefaultConfigurationNode("name", "users")); 066 067 // Add nodes for the table's fields 068 for (int i = 0; i < FIELD_NAMES.length; i++) 069 { 070 DefaultConfigurationNode field = new DefaultConfigurationNode( 071 "field"); 072 field 073 .addChild(new DefaultConfigurationNode("name", 074 FIELD_NAMES[i])); 075 field.addAttribute(new DefaultConfigurationNode("type", 076 FIELD_TYPES[i])); 077 if (FIELD_ATTRS[i] != null) 078 { 079 StringTokenizer tok = new StringTokenizer(FIELD_ATTRS[i], ", "); 080 while (tok.hasMoreTokens()) 081 { 082 field.addAttribute(new DefaultConfigurationNode( 083 "attribute", tok.nextToken())); 084 } 085 } 086 node.addChild(field); 087 } 088 } 089 090 /** 091 * Tests a newly created, uninitialized node. 092 */ 093 @Test 094 public void testNewNode() 095 { 096 node = new DefaultConfigurationNode(); 097 assertNull("name is not null", node.getName()); 098 assertNull("value is not null", node.getValue()); 099 assertNull("reference is not null", node.getReference()); 100 assertTrue("Children are not empty", node.getChildren().isEmpty()); 101 assertTrue("Named children are not empty", node.getChildren("test") 102 .isEmpty()); 103 assertEquals("Children cound is not 0", 0, node.getChildrenCount()); 104 assertEquals("Named children count is not 0", 0, node 105 .getChildrenCount("test")); 106 assertTrue("Attributes are not empty", node.getAttributes().isEmpty()); 107 assertTrue("Named attributes are not empty", node.getAttributes("test") 108 .isEmpty()); 109 assertNull("Node has a parent", node.getParentNode()); 110 assertFalse("Node is defined", node.isDefined()); 111 } 112 113 /** 114 * Tries to access an attribute using an invalid index. 115 */ 116 @Test(expected = IndexOutOfBoundsException.class) 117 public void testGetAttributeNonExisting() 118 { 119 node = new DefaultConfigurationNode(); 120 node.getAttribute(0); 121 } 122 123 /** 124 * Tests accessing a node's reference. 125 */ 126 @Test 127 public void testGetReference() 128 { 129 assertEquals("Reference was not stored", "TestReference", node 130 .getReference()); 131 } 132 133 /** 134 * Tests accessing the node's children. 135 */ 136 @Test 137 public void testGetChildren() 138 { 139 assertEquals("Number of children incorrect", FIELD_NAMES.length + 1, 140 node.getChildrenCount()); 141 List<ConfigurationNode> children = node.getChildren(); 142 Iterator<ConfigurationNode> it = children.iterator(); 143 DefaultConfigurationNode child = (DefaultConfigurationNode) it.next(); 144 assertEquals("Wrong node", "name", child.getName()); 145 checkFieldNodes(it); 146 } 147 148 /** 149 * Tests accessing the node's children by name. 150 */ 151 @Test 152 public void testGetChildrenByName() 153 { 154 List<ConfigurationNode> children = node.getChildren("field"); 155 assertEquals("Incorrect number of child nodes", FIELD_NAMES.length, 156 children.size()); 157 assertEquals("Incorrect result of getChildrenCount()", 158 FIELD_NAMES.length, node.getChildrenCount("field")); 159 checkFieldNodes(children.iterator()); 160 assertTrue("Found non existing nodes", node.getChildren("test") 161 .isEmpty()); 162 assertEquals("Wrong children list for null", node.getChildren(), node 163 .getChildren(null)); 164 } 165 166 /** 167 * Tests adding a new child node. 168 */ 169 @Test 170 public void testAddChild() 171 { 172 int cnt = node.getChildrenCount(); 173 DefaultConfigurationNode ndNew = new DefaultConfigurationNode("test", 174 "xyz"); 175 node.addChild(ndNew); 176 assertEquals("New node was not added", cnt + 1, node.getChildrenCount()); 177 List<ConfigurationNode> children = node.getChildren(); 178 assertEquals("Incorrect number of children", node.getChildrenCount(), 179 children.size()); 180 assertSame("Node was not added to end", ndNew, children.get(cnt)); 181 assertEquals("Incorrect number of named children", 1, node 182 .getChildrenCount(ndNew.getName())); 183 assertFalse("Child is an attribute", ndNew.isAttribute()); 184 assertSame("Parent was not set", node, ndNew.getParentNode()); 185 } 186 187 /** 188 * Tries to add a null child node. 189 */ 190 @Test(expected = IllegalArgumentException.class) 191 public void testAddChildNull() 192 { 193 node.addChild(null); 194 } 195 196 /** 197 * Tries to add a node without a name. 198 */ 199 @Test(expected = IllegalArgumentException.class) 200 public void testAddUndefinedChild() 201 { 202 node.addChild(new DefaultConfigurationNode()); 203 } 204 205 /** 206 * Tests removing a child node. 207 */ 208 @Test 209 public void testRemoveChild() 210 { 211 DefaultConfigurationNode child = (DefaultConfigurationNode) node 212 .getChildren().get(3); 213 int cnt = node.getChildrenCount(); 214 node.removeChild(child); 215 assertEquals("Child was not removed", cnt - 1, node.getChildrenCount()); 216 for (ConfigurationNode nd : node.getChildren()) 217 { 218 assertNotSame("Found removed node", child, nd); 219 } 220 assertNull("Parent reference was not removed", child.getParentNode()); 221 } 222 223 /** 224 * Tests removing a child node that does not belong to this node. 225 */ 226 @Test 227 public void testRemoveNonExistingChild() 228 { 229 int cnt = node.getChildrenCount(); 230 node.removeChild(new DefaultConfigurationNode("test")); 231 node.removeChild(new DefaultConfigurationNode()); 232 node.removeChild((ConfigurationNode) null); 233 node.removeChild("non existing child node"); 234 node.removeChild((String) null); 235 assertEquals("Children were changed", cnt, node.getChildrenCount()); 236 } 237 238 /** 239 * Tests removing children by their name. 240 */ 241 @Test 242 public void testRemoveChildByName() 243 { 244 int cnt = node.getChildrenCount(); 245 node.removeChild("name"); 246 assertEquals("Child was not removed", cnt - 1, node.getChildrenCount()); 247 assertEquals("Still found name child", 0, node.getChildrenCount("name")); 248 node.removeChild("field"); 249 assertEquals("Still remaining nodes", 0, node.getChildrenCount()); 250 } 251 252 /** 253 * Tests removing all children at once. 254 */ 255 @Test 256 public void testRemoveChildren() 257 { 258 node.removeChildren(); 259 assertEquals("Children count is not 0", 0, node.getChildrenCount()); 260 assertTrue("Children are not empty", node.getChildren().isEmpty()); 261 } 262 263 /** 264 * Tests accessing a child by its index. 265 */ 266 @Test 267 public void testGetChild() 268 { 269 ConfigurationNode child = node.getChild(2); 270 assertEquals("Wrong child returned", child, node.getChildren().get(2)); 271 } 272 273 /** 274 * Tests accessing child nodes with invalid indices. 275 */ 276 @Test(expected = IndexOutOfBoundsException.class) 277 public void testGetChildInvalidIndex() 278 { 279 node.getChild(4724); 280 } 281 282 /** 283 * Tests accessing the node's attributes. 284 */ 285 @Test 286 public void testGetAttributes() 287 { 288 assertEquals("Number of attributes incorrect", 1, node 289 .getAttributeCount()); 290 List<ConfigurationNode> attributes = node.getAttributes(); 291 Iterator<ConfigurationNode> it = attributes.iterator(); 292 DefaultConfigurationNode attr = (DefaultConfigurationNode) it.next(); 293 assertEquals("Wrong node", "type", attr.getName()); 294 assertFalse("More attributes", it.hasNext()); 295 } 296 297 /** 298 * Tests accessing the node's attributes by name. 299 */ 300 @Test 301 public void testGetAttributesByName() 302 { 303 assertEquals("Incorrect number of attributes", 1, node 304 .getAttributeCount("type")); 305 DefaultConfigurationNode field = (DefaultConfigurationNode) node 306 .getChildren().get(1); 307 assertEquals("Incorrect number of attributes", 2, field 308 .getAttributeCount("attribute")); 309 List<ConfigurationNode> attrs = field.getAttributes("attribute"); 310 assertEquals("Wrong value", "primarykey", 311 ((DefaultConfigurationNode) attrs.get(0)).getValue()); 312 assertEquals("Wrong value", "unique", ((DefaultConfigurationNode) attrs 313 .get(1)).getValue()); 314 } 315 316 /** 317 * Tests adding a new attribute node. 318 */ 319 @Test 320 public void testAddAttribute() 321 { 322 int cnt = node.getAttributeCount(); 323 DefaultConfigurationNode ndNew = new DefaultConfigurationNode("test", 324 "xyz"); 325 node.addAttribute(ndNew); 326 assertEquals("New node was not added", cnt + 1, node 327 .getAttributeCount()); 328 List<ConfigurationNode> attrs = node.getAttributes(); 329 assertEquals("Incorrect number of attributes", 330 node.getAttributeCount(), attrs.size()); 331 assertSame("Node was not added to end", ndNew, attrs.get(cnt)); 332 assertEquals("Incorrect number of named attributes", 1, node 333 .getAttributeCount(ndNew.getName())); 334 assertTrue("Child is no attribute", ndNew.isAttribute()); 335 assertSame("Parent was not set", node, ndNew.getParentNode()); 336 } 337 338 /** 339 * Tests removing an attribute node. 340 */ 341 @Test 342 public void testRemoveAttribute() 343 { 344 DefaultConfigurationNode attr = (DefaultConfigurationNode) node 345 .getAttributes().get(0); 346 int cnt = node.getAttributeCount(); 347 node.removeAttribute(attr); 348 assertEquals("Attribute was not removed", cnt - 1, node 349 .getAttributeCount()); 350 for (ConfigurationNode nd : node.getAttributes()) 351 { 352 assertNotSame("Found removed node", attr, nd); 353 } 354 assertNull("Parent reference was not removed", attr.getParentNode()); 355 } 356 357 /** 358 * Tests removing attributes by their names. 359 */ 360 @Test 361 public void testRemoveAttributeByName() 362 { 363 ConfigurationNode field = node.getChild(1); 364 assertEquals("Incorrect number of attributes", 3, field 365 .getAttributeCount()); 366 field.removeAttribute("attribute"); 367 assertEquals("Not all nodes removed", 1, field.getAttributeCount()); 368 assertTrue("Remaining attributes", field.getAttributes("attribute") 369 .isEmpty()); 370 field.removeAttribute("type"); 371 assertEquals("Remaining attributes", 0, field.getAttributeCount()); 372 } 373 374 /** 375 * Tests removing all attributes. 376 */ 377 @Test 378 public void testRemoveAttributes() 379 { 380 node.removeAttributes(); 381 assertEquals("Not all attributes removed", 0, node.getAttributeCount()); 382 assertTrue("Attributes not empty", node.getAttributes().isEmpty()); 383 } 384 385 /** 386 * Tests changing a node's attribute state. 387 */ 388 @Test(expected = IllegalStateException.class) 389 public void testChangeAttributeState() 390 { 391 ConfigurationNode attr = node.getAttribute(0); 392 attr.setAttribute(false); 393 } 394 395 /** 396 * Tests the visit() method using a simple visitor. 397 */ 398 @Test 399 public void testVisit() 400 { 401 CountNodeVisitor visitor = new CountNodeVisitor(); 402 node.visit(visitor); 403 assertEquals("Not all nodes visited", 19, visitor.beforeCalls); 404 assertEquals("Different number of before and after calls", 405 visitor.beforeCalls, visitor.afterCalls); 406 } 407 408 /** 409 * Tests the visit() method with a visitor that terminates the visit 410 * process. 411 */ 412 @Test 413 public void testVisitWithTerminate() 414 { 415 CountNodeVisitor visitor = new CountNodeVisitor(10); 416 node.visit(visitor); 417 assertEquals("Incorrect number of nodes visited", visitor.maxCalls, 418 visitor.beforeCalls); 419 assertEquals("Different number of before and after calls", 420 visitor.beforeCalls, visitor.afterCalls); 421 } 422 423 /** 424 * Tests the visit() method when null is passed in. This should throw an 425 * exception. 426 */ 427 @Test(expected = IllegalArgumentException.class) 428 public void testVisitWithNullVisitor() 429 { 430 node.visit(null); 431 } 432 433 /** 434 * Tests cloning a node. 435 */ 436 @Test 437 public void testClone() 438 { 439 node.setValue("TestValue"); 440 DefaultConfigurationNode clone = (DefaultConfigurationNode) node.clone(); 441 assertEquals("Value not cloned", "TestValue", clone.getValue()); 442 assertEquals("Name not cloned", "table", clone.getName()); 443 assertEquals("Reference not cloned", "TestReference", clone.getReference()); 444 assertEquals("Children were cloned", 0, clone.getChildrenCount()); 445 assertEquals("Attributes were cloned", 0, clone.getAttributeCount()); 446 } 447 448 /** 449 * Helper method for checking the child nodes of type "field". 450 * 451 * @param itFields the iterator with the child nodes 452 */ 453 private void checkFieldNodes(Iterator<ConfigurationNode> itFields) 454 { 455 for (int i = 0; i < FIELD_NAMES.length; i++) 456 { 457 DefaultConfigurationNode child = (DefaultConfigurationNode) itFields 458 .next(); 459 assertEquals("Wrong node", "field", child.getName()); 460 List<ConfigurationNode> nameNodes = child.getChildren("name"); 461 assertEquals("Wrong number of name nodes", 1, nameNodes.size()); 462 DefaultConfigurationNode nameNode = (DefaultConfigurationNode) nameNodes 463 .get(0); 464 assertEquals("Wrong field name", FIELD_NAMES[i], nameNode 465 .getValue()); 466 } 467 } 468 469 /** 470 * A test visitor implementation that is able to count the number of visits. 471 * It also supports a maximum number of visits to be set; if this number is 472 * reached, the <code>terminate()</code> method returns <b>true</b>. 473 */ 474 public static class CountNodeVisitor implements ConfigurationNodeVisitor 475 { 476 public int beforeCalls; 477 478 public int afterCalls; 479 480 public int maxCalls; 481 482 public CountNodeVisitor() 483 { 484 this(Integer.MAX_VALUE); 485 } 486 487 public CountNodeVisitor(int maxNumberOfVisits) 488 { 489 maxCalls = maxNumberOfVisits; 490 } 491 492 public void visitBeforeChildren(ConfigurationNode node) 493 { 494 beforeCalls++; 495 } 496 497 public void visitAfterChildren(ConfigurationNode node) 498 { 499 afterCalls++; 500 } 501 502 public boolean terminate() 503 { 504 return beforeCalls >= maxCalls; 505 } 506 } 507 }