You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sk...@apache.org on 2004/04/04 07:03:23 UTC

cvs commit: jakarta-commons/digester/src/test/org/apache/commons/digester Box.java OverlappingCallMethodRuleTestCase.java

skitching    2004/04/03 21:03:23

  Added:       digester/src/test/org/apache/commons/digester Box.java
                        OverlappingCallMethodRuleTestCase.java
  Log:
  Some more test cases for CallMethodRule behaviour when calls and
  params overlap and nest.
  
  Revision  Changes    Path
  1.1                  jakarta-commons/digester/src/test/org/apache/commons/digester/Box.java
  
  Index: Box.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */ 
  
  package org.apache.commons.digester;
  
  import java.util.List;
  import java.util.LinkedList;
  import java.util.Iterator;
  
  /**
   * Simple class for use in unit tests. A box has an ID, and can have
   * multiple boxes within it.
   */
  public class Box {
      private String id;
      
      private List children = new LinkedList();
  
      public Box() {}
      
      public String getId() {
          return id;
      }
      
      public void setId(String id) {
          this.id = id;
      }
      
      public void addChild(Box child) {
          this.children.add(child);
      }
      
      public List getChildren() {
          return children;
      }
      
      public String toString()
      {
          StringBuffer buf = new StringBuffer();
          buf.append("[Box] id=");
          buf.append(id);
          buf.append(" nchildren=");
          buf.append(children.size());
          
          for(Iterator i = children.iterator(); i.hasNext(); ) {
              Box child = (Box) i.next();
              buf.append("  ");
              buf.append(child.toString());
          }
          return buf.toString();
      }
      
      /**
       * Return a string containing this object's name value, followed by the
       * names of all child objects (and their children etc) in pre-order
       * sequence. Each name is separated by a space from the preceding one.
       */
      public String getIds() {
          StringBuffer buf = new StringBuffer();
          buf.append(this.id);
          for(Iterator i = children.iterator(); i.hasNext(); ) {
              Box child = (Box) i.next();
              buf.append(" ");
              buf.append(child.getIds());
          }
          return buf.toString();
      }
  }
  
  
  
  1.1                  jakarta-commons/digester/src/test/org/apache/commons/digester/OverlappingCallMethodRuleTestCase.java
  
  Index: OverlappingCallMethodRuleTestCase.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */ 
  
  
  package org.apache.commons.digester;
  
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.StringReader;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Map;
  
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  
  import org.xml.sax.SAXException;
  
  /**
   * <p>Tests for situations where CallMethodRule instances and their
   * parameters overlap each other.</p>
   */
  public class OverlappingCallMethodRuleTestCase extends TestCase {
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The digester instance we will be processing.
       */
      protected Digester digester = null;
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Construct a new instance of this test case.
       *
       * @param name Name of the test case
       */
      public OverlappingCallMethodRuleTestCase(String name) {
  
          super(name);
  
      }
  
  
      // --------------------------------------------------- Overall Test Methods
  
  
      /**
       * Set up instance variables required by this test case.
       */
      public void setUp() {
      }
  
  
      /**
       * Return the tests included in this test suite.
       */
      public static Test suite() {
          return (new TestSuite(OverlappingCallMethodRuleTestCase.class));
      }
  
  
      /**
       * Tear down instance variables required by this test case.
       */
      public void tearDown() {
      }
  
  
  
      String itemId;
      String itemName;
      
      public void setItemId(String id) { itemId = id; }
      public void setItemName(String name) { itemName = name; }
      
      // ------------------------------------------------ Individual Test Methods
  
  
      public void testItem1() throws SAXException, IOException {
          StringBuffer input = new StringBuffer();
          input.append("<root>");
          input.append(" <item id='1'>anitem</item>");
          input.append("</root>");
  
          Digester digester = new Digester();
          
          digester.addCallMethod("root/item", "setItemId", 1);
          digester.addCallParam("root/item", 0, "id");
          digester.addCallMethod("root/item", "setItemName", 1);
          digester.addCallParam("root/item", 0);
  
          this.itemId = null;
          this.itemName = null;
          digester.push(this);
          digester.parse(new StringReader(input.toString()));
  
          assertEquals("1", this.itemId);
          assertEquals("anitem", this.itemName);
      }
  
      public void testItem2() throws SAXException, IOException {
          StringBuffer input = new StringBuffer();
          input.append("<root>");
          input.append(" <item id='1'>anitem</item>");
          input.append("</root>");
  
          Digester digester = new Digester();
  
          digester.addCallMethod("root/item", "setItemName", 1);
          digester.addCallParam("root/item", 0);
          digester.addCallMethod("root/item", "setItemId", 1);
          digester.addCallParam("root/item", 0, "id");
  
          this.itemId = null;
          this.itemName = null;
          digester.push(this);
          digester.parse(new StringReader(input.toString()));
  
          assertEquals("1", this.itemId);
          assertEquals("anitem", this.itemName);
      }
  
      public void testItem3() throws SAXException, IOException {
          StringBuffer input = new StringBuffer();
          input.append("<root>");
          input.append(" <item>1</item>");
          input.append("</root>");
  
          Digester digester = new Digester();
  
          digester.addCallMethod("root/item", "setItemId", 1);
          digester.addCallParam("root/item", 0);
          digester.addCallMethod("root/item", "setItemName", 1);
          digester.addCallParam("root/item", 0);
  
          this.itemId = null;
          this.itemName = null;
          digester.push(this);
          digester.parse(new StringReader(input.toString()));
  
          assertEquals("1", this.itemId);
          assertEquals("1", this.itemName);
      }
  
      /**
       * This is an "anti-test" that demonstrates how digester can <i>fails</i> 
       * to produce the correct results, due to a design flaw (or at least
       * limitation) in the way that CallMethodRule and CallParamRule work. 
       * <p>
       * The following sequence always fails:
       * <ul>
       * <li>CallMethodRule A fires (pushing params array)</li>
       * <li>CallMethodRule B fires (pushing params array)</li>
       * <li>params rule for A fires --> writes to params of method B!</li>
       * <li>params rule for B fires --> overwrites params for method B</li>
       * </ul>
       * The result is that method "b" appears to work ok, but method "a"
       * loses its input parameters.
       * <p>
       * One solution is for CallParamRule objects to know which CallMethodRule
       * they are associated with. Even this might fail in corner cases where
       * the same rule is associated with multiple patterns, or with wildcard
       * patterns which cause a rule to fire in a "recursive" manner. However
       * implementing this is not possible with the current digester design.
       */
      
      public void testItem4() throws SAXException, IOException {
          StringBuffer input = new StringBuffer();
          input.append("<root>");
          input.append(" <item>");
          input.append("  <id value='1'/>");
          input.append("  <name value='name'/>");
          input.append(" </item>");
          input.append("</root>");
  
          Digester digester = new Digester();
  
          digester.addCallMethod("root/item", "setItemId", 1);
          digester.addCallParam("root/item/id", 0, "value");
          digester.addCallMethod("root/item", "setItemName", 1);
          digester.addCallParam("root/item/name", 0, "value");
  
          this.itemId = null;
          this.itemName = null;
          digester.push(this);
          digester.parse(new StringReader(input.toString()));
  
          // These are the "correct" results
          //assertEquals("1", this.itemId);
          //assertEquals("name", this.itemName);
  
          // These are what actually happens
          assertEquals(null, this.itemId);
          assertEquals("name", this.itemName);
      }
  
      /**
       * This test checks that CallParamRule instances which fetch data
       * from xml attributes work ok when invoked "recursively",
       * ie a rule instances' methods gets called in the order
       * begin[1]/begin[2]/body[2]/end[2]/body[1]/end[1]
       */
      public void testWildcard1() throws SAXException, IOException {
          StringBuffer input = new StringBuffer();
          input.append("<box id='A1'>");
          input.append(" <box id='B1'>");
          input.append("  <box id='C1'/>");
          input.append("  <box id='C2'/>");
          input.append(" </box>");
          input.append("</box>");
  
          Digester digester = new Digester();
  
          digester.addObjectCreate("*/box", Box.class);
          digester.addCallMethod("*/box", "setId", 1);
          digester.addCallParam("*/box", 0, "id");
          digester.addSetNext("*/box", "addChild");
  
          Box root = new Box();
          root.setId("root");
          digester.push(root);
          digester.parse(new StringReader(input.toString()));
  
          // walk the object tree, concatenating the id strings
          String ids = root.getIds();
          assertEquals("root A1 B1 C1 C2", ids);
      }
  
      /**
       * This test checks that CallParamRule instances which fetch data
       * from the xml element body work ok when invoked "recursively",
       * ie a rule instances' methods gets called in the order
       * begin[1]/begin[2]/body[2]/end[2]/body[1]/end[1]
       */
      public void testWildcard2() throws SAXException, IOException {
          StringBuffer input = new StringBuffer();
          input.append("<box>A1");
          input.append(" <box>B1");
          input.append("  <box>C1</box>");
          input.append("  <box>C2</box>");
          input.append(" </box>");
          input.append("</box>");
  
          Digester digester = new Digester();
  
          digester.addObjectCreate("*/box", Box.class);
          digester.addCallMethod("*/box", "setId", 1);
          digester.addCallParam("*/box", 0);
          digester.addSetNext("*/box", "addChild");
  
          Box root = new Box();
          root.setId("root");
          digester.push(root);
          digester.parse(new StringReader(input.toString()));
  
          // walk the object tree, concatenating the id strings
          String ids = root.getIds();
          assertEquals("root A1 B1 C1 C2", ids);
      }
  }
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org