You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2010/05/23 00:27:41 UTC

svn commit: r947342 - in /webservices/commons/trunk/modules/axiom/modules: axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/ axiom-testutils/src/main/java/org/apache/axiom/testutils/ axiom-testutils/src/main/java/org/apache/axiom/testutils/io/

Author: veithen
Date: Sat May 22 22:27:41 2010
New Revision: 947342

URL: http://svn.apache.org/viewvc?rev=947342&view=rev
Log:
Increased the test coverage for WSCOMMONS-372 (SafeXMLStreamReader).

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/InvocationCounter.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java   (with props)
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/StAXOMBuilderTest.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/StAXOMBuilderTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/StAXOMBuilderTest.java?rev=947342&r1=947341&r2=947342&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/StAXOMBuilderTest.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/StAXOMBuilderTest.java Sat May 22 22:27:41 2010
@@ -26,11 +26,14 @@ import org.apache.axiom.om.OMNode;
 import org.apache.axiom.om.OMText;
 import org.apache.axiom.om.impl.llom.factory.OMXMLBuilderFactory;
 import org.apache.axiom.om.util.StAXUtils;
+import org.apache.axiom.testutils.InvocationCounter;
+import org.apache.axiom.testutils.io.ExceptionInputStream;
 
-import java.io.FileReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.util.Iterator;
 
-import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
 
 public class StAXOMBuilderTest extends AbstractTestCase {
     StAXOMBuilder stAXOMBuilder;
@@ -124,11 +127,13 @@ public class StAXOMBuilderTest extends A
     }
     
     public void testInvalidXML() throws Exception {
+        XMLStreamReader originalReader = StAXUtils.createXMLStreamReader(getTestResource("invalid_xml.xml"));
+        InvocationCounter invocationCounter = new InvocationCounter();
+        XMLStreamReader reader = (XMLStreamReader)invocationCounter.createProxy(originalReader);
+        
         StAXOMBuilder stAXOMBuilder =
                 OMXMLBuilderFactory.createStAXOMBuilder(OMAbstractFactory.getSOAP11Factory(),
-                                                        XMLInputFactory.newInstance()
-                                                                       .createXMLStreamReader(
-                                                                         getTestResource("invalid_xml.xml")));
+                                                        reader);
         
         Exception exception = null;
         while (exception == null || stAXOMBuilder.isCompleted()) {
@@ -141,6 +146,9 @@ public class StAXOMBuilderTest extends A
         
         assertTrue("Expected an exception because invalid_xml.xml is wrong", exception != null);
         
+        assertTrue(invocationCounter.getInvocationCount() > 0);
+        invocationCounter.reset();
+        
         // Intentionally call builder again to make sure the same error is returned.
         Exception exception2 = null;
         try {
@@ -149,9 +157,60 @@ public class StAXOMBuilderTest extends A
             exception2 = e;
         }
         
+        assertEquals(0, invocationCounter.getInvocationCount());
+        
         assertTrue("Expected a second exception because invalid_xml.xml is wrong", exception2 != null);
         assertTrue("Expected the same exception. first=" + exception + " second=" + exception2, 
                     exception.getMessage().equals(exception2.getMessage()));
         
     }
+    
+    /**
+     * Test the behavior of the builder when an exception is thrown by
+     * {@link XMLStreamReader#getText()}. The test is only effective if the StAX
+     * implementation lazily loads the character data for a
+     * {@link javax.xml.stream.XMLStreamConstants#CHARACTERS} event. This is the
+     * case for Woodstox. It checks that after the exception is thrown by the
+     * parser, the builder no longer attempts to access the parser.
+     * 
+     * @throws Exception
+     */
+    public void testIOExceptionInGetText() throws Exception {
+        // Construct a stream that will throw an exception in the middle of a text node
+        StringBuffer xml = new StringBuffer("<root>");
+        for (int i=0; i<10000; i++) {
+            xml.append('x');
+        }
+        InputStream in = new ExceptionInputStream(new ByteArrayInputStream(xml.toString().getBytes("ASCII")));
+        
+        XMLStreamReader originalReader = StAXUtils.createXMLStreamReader(in);
+        InvocationCounter invocationCounter = new InvocationCounter();
+        XMLStreamReader reader = (XMLStreamReader)invocationCounter.createProxy(originalReader);
+        
+        StAXOMBuilder builder = new StAXOMBuilder(reader);
+        
+        try {
+            while (true) {
+                builder.next();
+            }
+        } catch (Exception ex) {
+            // Expected
+        }
+
+        assertTrue(invocationCounter.getInvocationCount() > 0);
+        invocationCounter.reset();
+
+        Exception exception;
+        try {
+            builder.next();
+            exception = null;
+        } catch (Exception ex) {
+            exception = ex;
+        }
+        if (exception == null) {
+            fail("Expected exception");
+        }
+        
+        assertEquals(0, invocationCounter.getInvocationCount());
+    }
 }
\ No newline at end of file

Added: webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/InvocationCounter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/InvocationCounter.java?rev=947342&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/InvocationCounter.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/InvocationCounter.java Sat May 22 22:27:41 2010
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.axiom.testutils;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Utility class that counts the number of invocations on one or more objects. It also counts the
+ * number of exceptions thrown by these invocations. The class uses dynamic proxies to implement
+ * this feature.
+ * <p>
+ * This class is thread safe.
+ * 
+ * @author Andreas Veithen
+ */
+public class InvocationCounter {
+    private class InvocationHandlerImpl implements InvocationHandler {
+        private final Object target;
+
+        public InvocationHandlerImpl(Object target) {
+            this.target = target;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            invocationCount.incrementAndGet();
+            try {
+                return method.invoke(target, args);
+            } catch (InvocationTargetException ex) {
+                exceptionCount.incrementAndGet();
+                throw ex.getCause();
+            }
+        }
+    }
+    
+    final AtomicInteger invocationCount = new AtomicInteger();
+    final AtomicInteger exceptionCount = new AtomicInteger();
+    
+    /**
+     * Create a new proxy. Every invocation of a method on this proxy increases the invocation count
+     * by one unit. If the invocation results in an exception, then the exception counter is also
+     * incremented. The returned proxy implements all interfaces of the target instance.
+     * 
+     * @param target the target instance
+     * @return the proxy instance
+     */
+    public Object createProxy(Object target) {
+        Set ifaces = new HashSet();
+        Class clazz = target.getClass();
+        do {
+            ifaces.addAll(Arrays.asList(clazz.getInterfaces()));
+            clazz = clazz.getSuperclass();
+        } while (clazz != null);
+        return Proxy.newProxyInstance(InvocationCounter.class.getClassLoader(),
+                (Class[])ifaces.toArray(new Class[ifaces.size()]), new InvocationHandlerImpl(target));
+    }
+
+    /**
+     * Get the number of invocations counted by this instance.
+     * 
+     * @return the number of invocations
+     */
+    public int getInvocationCount() {
+        return invocationCount.get();
+    }
+
+    /**
+     * Get the number of exceptions counted by this instance.
+     * 
+     * @return the number of exceptions
+     */
+    public int getExceptionCount() {
+        return exceptionCount.get();
+    }
+    
+    /**
+     * Reset all counters to zero.
+     */
+    public void reset() {
+        invocationCount.set(0);
+        exceptionCount.set(0);
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/InvocationCounter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java?rev=947342&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java Sat May 22 22:27:41 2010
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.axiom.testutils.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.input.ProxyInputStream;
+
+/**
+ * {@link InputStream} wrapper that throw an exception when the end of the
+ * parent stream is reached.
+ */
+public class ExceptionInputStream extends ProxyInputStream {
+    public ExceptionInputStream(InputStream in) {
+        super(in);
+    }
+
+    public int read() throws IOException {
+        int b = super.read();
+        if (b == -1) {
+            throw new IOException("End of stream reached");
+        }
+        return b;
+    }
+
+    public int read(byte[] b) throws IOException {
+        int c = super.read(b);
+        if (c == -1) {
+            throw new IOException("End of stream reached");
+        }
+        return c;
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        int c = super.read(b, off, len);
+        if (c == -1) {
+            throw new IOException("End of stream reached");
+        }
+        return c;
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native