Permalink
Browse files

Coverage improvement. Found bug in ArrayCopy.copyOfRange.

Simplified NamespaceStack by joining duplicate code.
  • Loading branch information...
rolfl committed Feb 14, 2012
1 parent 0424a4b commit 3a79d1cfb99bcef6b5439153064a9fbc574e1457
@@ -64,6 +64,10 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
*
*/
public final class ArrayCopy {
+
+ private ArrayCopy() {
+ // inaccessible constructor.
+ }
/**
* Arrays.copyOf(...) is a Java6 thing. This is a replacement.
@@ -89,9 +93,13 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
*/
public static final <E> E[] copyOfRange(final E[] source, final int from, int to) {
final int len = to - from;
+ if (len < 0) {
+ throw new IllegalArgumentException("From(" + from + ") > To (" + to + ")");
+ }
@SuppressWarnings("unchecked")
final E[] dest = (E[])Array.newInstance(source.getClass().getComponentType(), len);
- System.arraycopy(source, from, dest, 0, len < source.length ? len : source.length);
+ final int tocopy = from + len > source.length ? source.length - from : len;
+ System.arraycopy(source, from, dest, 0, tocopy);
return dest;
}
@@ -239,6 +239,8 @@ public int compare(Namespace ns1, Namespace ns2) {
return ns1.getPrefix().compareTo(ns2.getPrefix());
}
};
+ private static final Namespace[] DEFAULTSEED = new Namespace[] {
+ Namespace.NO_NAMESPACE, Namespace.XML_NAMESPACE};
/**
* Lots of reasons for having our own binarySearch.
@@ -325,8 +327,7 @@ private static final int binarySearch(final Namespace[] data,
* @see #push(Element) for comprehensive notes.
*/
public NamespaceStack() {
- this(new Namespace[] {
- Namespace.NO_NAMESPACE, Namespace.XML_NAMESPACE});
+ this(DEFAULTSEED);
}
/**
@@ -456,57 +457,9 @@ public void push(Element element) {
newscope = checkNamespace(toadd, ns, newscope);
}
}
+
+ pushStack(mns, newscope, toadd);
- // OK, we've checked the namespaces in the Element, and 'toadd' contains
- // all namespaces that are not already in scope.
- depth++;
-
- if (depth >= scope.length) {
- // we need more space on the stack.
- scope = ArrayCopy.copyOf(scope, scope.length * 2);
- added = ArrayCopy.copyOf(added, scope.length);
- }
-
- // Sort out the added namespaces.
- if (toadd.isEmpty()) {
- // nothing changed in the scope.
- added[depth] = EMPTY;
- } else {
- added[depth] = toadd.toArray(new Namespace[toadd.size()]);
- if (added[depth][0] == mns) {
- Arrays.sort(added[depth], 1, added[depth].length, NSCOMP);
- } else {
- Arrays.sort(added[depth], NSCOMP);
- }
- }
-
- if (mns != newscope[0]) {
- if (toadd.isEmpty()) {
- // we need to make newscope a copy of the previous level's
- // scope, because it is not yet a copy.
- newscope = ArrayCopy.copyOf(newscope, newscope.length);
- }
- // we need to take the Namespace at position 0, and insert it
- // in it's place later in the array.
- // we need to take the mns from later in the array, and move it
- // to the front.
- final Namespace tmp = newscope[0];
- int ip = - binarySearch(newscope, 1, newscope.length, tmp) - 1;
- // we can be sure that (- ip - 1 ) is >= 1
- // we also know that we want to move the data before the ip
- // backwards one spot, so the math is slightly different....
- ip--;
- System.arraycopy(newscope, 1, newscope, 0, ip);
- newscope[ip] = tmp;
-
- ip = binarySearch(newscope, 0, newscope.length, mns);
- // we can be sure that ip is >= 0
- System.arraycopy(newscope, 0, newscope, 1, ip);
- newscope[0] = mns;
- }
-
- scope[depth] = newscope;
- return;
}
/**
@@ -520,8 +473,13 @@ public void push(Attribute att) {
// check to see whether the Namespace is new-to-scope.
Namespace[] newscope = checkNamespace(toadd, mns, scope[depth]);
- // OK, we've checked the namespaces in the Attribute, and 'toadd'
- // contains all namespaces that are not already in scope.
+ pushStack(mns, newscope, toadd);
+ }
+
+ private final void pushStack(final Namespace mns, Namespace[] newscope,
+ final List<Namespace> toadd) {
+ // OK, we've checked the namespaces in the Element, and 'toadd' contains
+ // all namespaces that are not already in scope.
depth++;
if (depth >= scope.length) {
@@ -535,7 +493,7 @@ public void push(Attribute att) {
// nothing changed in the scope.
added[depth] = EMPTY;
} else {
- added[depth] = toadd.toArray(new Namespace[1]);
+ added[depth] = toadd.toArray(new Namespace[toadd.size()]);
if (added[depth][0] == mns) {
Arrays.sort(added[depth], 1, added[depth].length, NSCOMP);
} else {
@@ -569,7 +527,6 @@ public void push(Attribute att) {
}
scope[depth] = newscope;
- return;
}
/**
@@ -0,0 +1,63 @@
+package org.jdom2.test.cases.util;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+import org.jdom2.test.util.UnitTestUtil;
+import org.jdom2.util.ArrayCopy;
+
+@SuppressWarnings("javadoc")
+public class TestArrayCopy {
+
+ // UnitTests/compile is done from Java6 .... so
+ // we can compare with Arrays.copyOf()
+
+ @Test
+ public void testCopyOfEArrayInt() {
+ final String[] val = {"a", "b", "c", "d"};
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 3), Arrays.copyOf(val, 3)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 0), Arrays.copyOf(val, 0)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 5), Arrays.copyOf(val, 5)));
+ }
+
+ @Test
+ public void testCopyOfRange() {
+ final String[] val = {"a", "b", "c", "d"};
+ assertTrue(Arrays.equals(ArrayCopy.copyOfRange(val, 1, 2), Arrays.copyOfRange(val, 1, 2)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOfRange(val, 1, 5), Arrays.copyOfRange(val, 1, 5)));
+ try {
+ ArrayCopy.copyOfRange(val, 3, 2);
+ UnitTestUtil.failNoException(IllegalArgumentException.class);
+ } catch (Exception e) {
+ UnitTestUtil.checkException(IllegalArgumentException.class, e);
+ }
+ }
+
+ @Test
+ public void testCopyOfCharArrayInt() {
+ final char[] val = {'a', 'b', 'c', 'd'};
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 3), Arrays.copyOf(val, 3)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 0), Arrays.copyOf(val, 0)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 5), Arrays.copyOf(val, 5)));
+ }
+
+ @Test
+ public void testCopyOfIntArrayInt() {
+ final int[] val = {1, 2, 3, 4};
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 3), Arrays.copyOf(val, 3)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 0), Arrays.copyOf(val, 0)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 5), Arrays.copyOf(val, 5)));
+ }
+
+ @Test
+ public void testCopyOfBooleanArrayInt() {
+ final boolean[] val = {true, false, true, false};
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 3), Arrays.copyOf(val, 3)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 0), Arrays.copyOf(val, 0)));
+ assertTrue(Arrays.equals(ArrayCopy.copyOf(val, 5), Arrays.copyOf(val, 5)));
+ }
+
+}
@@ -59,6 +59,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -194,9 +195,9 @@ private static final void checkDiagnostic(XPathExpression<?> xpc, Object context
int r = 0;
int f = 0;
for (int i = 0; i < draw.size(); i++) {
- if (dresult.get(r) == draw.get(i)) {
+ if (r < dresult.size() && dresult.get(r) == draw.get(i)) {
r++;
- } else if (dfilt.get(f)== draw.get(i)) {
+ } else if (f < dfilt.size() && dfilt.get(f)== draw.get(i)) {
f++;
} else {
fail (draw.get(i) + " is neither a result nor a filtered (or is in the wrong place)");
@@ -230,7 +231,7 @@ protected static void checkXPath(XPathExpression<?> xpath, Object context, Objec
}
}
- if (allns) {
+ if (allns && expect.length > 0) {
// we expect only Namespace results.
// we use different rules....
// for a start, we don't check on order.
@@ -971,6 +972,12 @@ public void testXPathOR() {
checkXPath("/main/node()[1] | /main/@*", child3emt, null, mainatt, maincomment);
}
+ @Test
+ public void testXPathNoMatch() {
+ checkXPath("//dummy", doc, null);
+ }
+
+
/* *******************************
* Negative TestCases
* ******************************* */
@@ -1031,5 +1038,36 @@ public void testNegativeBrokenExpression() {
}
}
+
+ @Test
+ public void testXPathFilteredDiagnostic() {
+ final XPathExpression<Element> xpe =
+ setupXPath(Filters.element("child"), "//*", null, null);
+ final ArrayList<Element> res = new ArrayList<Element>();
+ res.add(child1emt);
+ res.add(child2emt);
+ // child3 is not in the NO_NAMESPACE ... res.add(child3emt);
+ final XPathDiagnostic<Element> diag = xpe.diagnose(doc, false);
+ checkDiagnostic(xpe, doc, res, diag);
+ final XPathDiagnostic<Element> diagz = xpe.diagnose(doc, true);
+ // size is zero because first result ('main') does not pass the filter.
+ assertTrue(diagz.getResult().size() == 0);
+ assertTrue(diagz.toString() != null);
+
+ final XPathExpression<Element> xpf =
+ setupXPath(Filters.element("main"), "//*", null, null);
+ final XPathDiagnostic<Element> diagf = xpf.diagnose(doc, false);
+
+ assertTrue(main == diagf.getResult().get(0));
+ assertTrue(diagf.getFilteredResults().size() == 3);
+ assertTrue(child1emt == diagf.getFilteredResults().get(0));
+ assertTrue(child2emt == diagf.getFilteredResults().get(1));
+ assertTrue(child3emt == diagf.getFilteredResults().get(2));
+
+ final XPathDiagnostic<Element> diagg = xpf.diagnose(doc, true);
+
+ assertTrue(main == diagg.getResult().get(0));
+ assertTrue(diagg.getFilteredResults().size() == 0);
+ }
}
@@ -6,6 +6,7 @@
import org.junit.Test;
import org.jdom2.Element;
+import org.jdom2.filter.Filters;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;
import org.jdom2.xpath.jaxen.JaxenXPathFactory;
@@ -33,4 +34,16 @@ public void testNewInstanceString() {
assertTrue(emt == xp.evaluateFirst(emt));
}
+ @Test
+ public void testNewInstanceCompileNSList() {
+ XPathFactory xpf = XPathFactory.newInstance(JaxenXPathFactory.class.getName());
+ assertNotNull(xpf);
+ assertTrue(xpf != XPathFactory.newInstance(JaxenXPathFactory.class.getName()));
+ XPathExpression<?> xp = xpf.compile(".");
+ Element emt = new Element("root");
+ assertTrue(emt == xp.evaluateFirst(emt));
+ xp = xpf.compile(".", Filters.element(), null, emt.getNamespacesInScope());
+ assertTrue(emt == xp.evaluateFirst(emt));
+ }
+
}

0 comments on commit 3a79d1c

Please sign in to comment.