diff options
Diffstat (limited to 'luni')
90 files changed, 4022 insertions, 1852 deletions
diff --git a/luni/src/main/java/java/lang/VMThread.java b/luni/src/main/java/java/lang/VMThread.java index 8e789cb..6d7bef0 100644 --- a/luni/src/main/java/java/lang/VMThread.java +++ b/luni/src/main/java/java/lang/VMThread.java @@ -16,6 +16,9 @@ package java.lang; +import java.util.logging.Logger; +import java.util.logging.Level; + class VMThread { Thread thread; @@ -47,20 +50,25 @@ class VMThread VMThread.create(thread, stacksize); } + private static final String UNSUPPORTED_THREAD_METHOD + = "Deprecated Thread methods are not supported."; + /** * Suspends the Thread. */ + @SuppressWarnings("ThrowableInstanceNeverThrown") void suspend() { - throw new UnsupportedOperationException( - "Deprecated Thread methods are not supported."); + Logger.global.log(Level.SEVERE, UNSUPPORTED_THREAD_METHOD, + new UnsupportedOperationException()); } /** * Resumes the Thread, assuming it is suspended. */ + @SuppressWarnings("ThrowableInstanceNeverThrown") void resume() { - throw new UnsupportedOperationException( - "Deprecated Thread methods are not supported."); + Logger.global.log(Level.SEVERE, UNSUPPORTED_THREAD_METHOD, + new UnsupportedOperationException()); } /** @@ -72,9 +80,10 @@ class VMThread /** * Stops the Thread, passing it a Throwable (which might be ThreadDeath). */ + @SuppressWarnings("ThrowableInstanceNeverThrown") void stop(Throwable throwable) { - throw new UnsupportedOperationException( - "Deprecated Thread methods are not supported."); + Logger.global.log(Level.SEVERE, UNSUPPORTED_THREAD_METHOD, + new UnsupportedOperationException()); } native void setPriority(int newPriority); diff --git a/luni/src/main/java/java/lang/reflect/AnnotatedElement.java b/luni/src/main/java/java/lang/reflect/AnnotatedElement.java index 23093c5..1f081b9 100644 --- a/luni/src/main/java/java/lang/reflect/AnnotatedElement.java +++ b/luni/src/main/java/java/lang/reflect/AnnotatedElement.java @@ -22,7 +22,6 @@ import java.lang.annotation.Annotation; /** * This interface provides reflective access to annotation information. * - * @since 1.5 * @since Android 1.0 */ public interface AnnotatedElement { diff --git a/luni/src/main/java/java/lang/reflect/GenericArrayType.java b/luni/src/main/java/java/lang/reflect/GenericArrayType.java index d47d7f2..81fb39f 100644 --- a/luni/src/main/java/java/lang/reflect/GenericArrayType.java +++ b/luni/src/main/java/java/lang/reflect/GenericArrayType.java @@ -21,7 +21,6 @@ package java.lang.reflect; * This interface represents an array type with a component type that is either * a parameterized type or a type variable. * - * @since 1.5 * @since Android 1.0 */ public interface GenericArrayType extends Type { diff --git a/luni/src/main/java/java/lang/reflect/GenericDeclaration.java b/luni/src/main/java/java/lang/reflect/GenericDeclaration.java index 6f2dcb3..c7cedcf 100644 --- a/luni/src/main/java/java/lang/reflect/GenericDeclaration.java +++ b/luni/src/main/java/java/lang/reflect/GenericDeclaration.java @@ -19,7 +19,6 @@ package java.lang.reflect; /** * Common interface for language constructs that declare type parameters. * - * @since 1.5 * @since Android 1.0 */ public interface GenericDeclaration { diff --git a/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java b/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java index 5691565..bb901fd 100644 --- a/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java +++ b/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java @@ -21,7 +21,6 @@ package java.lang.reflect; * Indicates that a malformed signature has been encountered via a reflective * method. * - * @since 1.5 * @since Android 1.0 */ public class GenericSignatureFormatError extends ClassFormatError { diff --git a/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java b/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java index d8f8096..7dfbc6f 100644 --- a/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java +++ b/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java @@ -21,7 +21,6 @@ package java.lang.reflect; * Indicates that a malformed parameterized type has been encountered by a * reflective method. * - * @since 1.5 * @since Android 1.0 */ public class MalformedParameterizedTypeException extends RuntimeException { diff --git a/luni/src/main/java/java/lang/reflect/ParameterizedType.java b/luni/src/main/java/java/lang/reflect/ParameterizedType.java index 349464a..3d03921 100644 --- a/luni/src/main/java/java/lang/reflect/ParameterizedType.java +++ b/luni/src/main/java/java/lang/reflect/ParameterizedType.java @@ -21,7 +21,6 @@ package java.lang.reflect; * This interface represents a parameterized type such as {@code * 'Set<String>'}. * - * @since 1.5 * @since Android 1.0 */ public interface ParameterizedType extends Type { diff --git a/luni/src/main/java/java/lang/reflect/Type.java b/luni/src/main/java/java/lang/reflect/Type.java index f0c6142..abd4978 100644 --- a/luni/src/main/java/java/lang/reflect/Type.java +++ b/luni/src/main/java/java/lang/reflect/Type.java @@ -19,7 +19,6 @@ package java.lang.reflect; /** * Common interface implemented by all Java types. * - * @since 1.5 * @since Android 1.0 */ public interface Type { diff --git a/luni/src/main/java/java/lang/reflect/TypeVariable.java b/luni/src/main/java/java/lang/reflect/TypeVariable.java index aef7ac9..99aca77 100644 --- a/luni/src/main/java/java/lang/reflect/TypeVariable.java +++ b/luni/src/main/java/java/lang/reflect/TypeVariable.java @@ -25,7 +25,6 @@ package java.lang.reflect; * @param <D> * the generic declaration that declares this type variable * - * @since 1.5 * @since Android 1.0 */ public interface TypeVariable<D extends GenericDeclaration> extends Type { diff --git a/luni/src/main/java/java/lang/reflect/WildcardType.java b/luni/src/main/java/java/lang/reflect/WildcardType.java index 2b913d0..72a022d 100644 --- a/luni/src/main/java/java/lang/reflect/WildcardType.java +++ b/luni/src/main/java/java/lang/reflect/WildcardType.java @@ -23,7 +23,6 @@ package java.lang.reflect; * multiple upper bounded wildcard {@code '? extends Closeable & Flushable'} or * the lower bounded wildcard {@code '? super OutputStream'}. * - * @since 1.5 * @since Android 1.0 */ public interface WildcardType extends Type { diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java index d6b6978..89f827b 100644 --- a/luni/src/main/java/java/net/InetAddress.java +++ b/luni/src/main/java/java/net/InetAddress.java @@ -160,9 +160,6 @@ public class InetAddress extends Object implements Serializable { */ @Override public boolean equals(Object obj) { - if (obj == null) { - return false; - } // BEGIN android-changed if (!(obj instanceof InetAddress)) { return false; @@ -217,10 +214,11 @@ public class InetAddress extends Object implements Serializable { // Added change taken from newer harmony concerning zero length hostname. // Added special handling for localhost, since it doesn't work properly. // TODO Get rid of this later... - if (host == null || 0 == host.length() || + if (host == null || 0 == host.length() || "localhost".equalsIgnoreCase(host)) { - return new InetAddress[] { preferIPv6Addresses() ? Inet6Address.LOOPBACK - : LOOPBACK }; + return new InetAddress[] { preferIPv6Addresses() + ? Inet6Address.LOOPBACK + : LOOPBACK }; } // END android-changed @@ -229,13 +227,27 @@ public class InetAddress extends Object implements Serializable { if (security != null) { security.checkConnect(host, -1); } - if (Socket.preferIPv4Stack()) { - return getAliasesByNameImpl(host); + + byte[][] rawAddresses = getallbyname(host, + Socket.preferIPv4Stack()); + InetAddress[] returnedAddresses = new + InetAddress[rawAddresses.length]; + for (int i = 0; i < rawAddresses.length; i++) { + byte[] rawAddress = rawAddresses[i]; + if (rawAddress.length == 16) { + returnedAddresses[i] = new Inet6Address(rawAddress, host); + } else if (rawAddress.length == 4) { + returnedAddresses[i] = new Inet4Address(rawAddress, host); + } else { + // Cannot happen, because the underlying code only returns + // addresses that are 4 or 16 bytes long. + throw new AssertionError("Impossible address length " + + rawAddress.length); + } } // ok we may have to re-order to make sure the // preferIPv6Addresses is respected - InetAddress[] returnedAddresses = getAliasesByNameImpl(host); InetAddress[] orderedAddresses = null; if (returnedAddresses != null) { orderedAddresses = new InetAddress[returnedAddresses.length]; @@ -522,54 +534,16 @@ public class InetAddress extends Object implements Serializable { } // END android-changed - /** - * Query the IP stack for aliases for the host. The host is in string name - * form. If the host does not have aliases (only multihomed hosts do), - * return an array with a single {@code InetAddress} constructed from the - * host name & address. - * - * @param name - * the host name to lookup. - * @throws UnknownHostException - * if an error occurs during lookup. - */ - // BEGIN android-changed + // BEGIN android-deleted // static native InetAddress[] getAliasesByNameImpl(String name) // throws UnknownHostException; - static InetAddress[] getAliasesByNameImpl(String name) - throws UnknownHostException { - // TODO Probably a bit inefficient. Provide native later. - InetAddress addr = getHostByNameImpl(name, false); - - String[] aliases = getaliasesbyname(name); - - if (aliases.length == 0) { - // If no alias addresses where found (only multihosts do have them) - // return the address with the name - byte[] address = addr.getAddress(); - InetAddress[] result = new InetAddress[1]; - result[0] = (address.length == 4 ? - new Inet4Address(address, name) : - new Inet6Address(address, name)); - return result; - } - - InetAddress[] result = new InetAddress[aliases.length]; - for (int i = 0; i < result.length; i++) { - byte[] address = addr.getAddress(); - result[i] = (address.length == 4 ? - new Inet4Address(address, aliases[i]) : - new Inet6Address(address, aliases[i])); - } - - return result; - } + // END android-deleted /** - * Wrapper for libc call. It is assumed to be thread-safe, which is - * in fact the case on Android. + * Resolves a host name to its IP addresses. Thread safe. */ - private static native String[] getaliasesbyname(String name); + private static native byte[][] getallbyname(String name, + boolean preferIPv4Stack); // END android-changed /** @@ -585,23 +559,13 @@ public class InetAddress extends Object implements Serializable { // throws UnknownHostException; static InetAddress getHostByAddrImpl(byte[] addr) throws UnknownHostException { - // TODO Probably inefficient. Provide native later. - String ipaddr = (addr[0] & 0xff) + "." + (addr[1] & 0xff) + "." - + (addr[2] & 0xff) + "." + (addr[3] & 0xff); - String host = gethostbyaddr(ipaddr); - - if (host == null) { - throw new UnknownHostException(ipaddr); - } - - return new InetAddress(addr, host); + return new InetAddress(addr, gethostbyaddr(addr)); } /** - * Wrapper for libc call. It is assumed to be thread-safe, which is - * in fact the case on Android. + * Resolves an IP address to a hostname. Thread safe. */ - private static native String gethostbyaddr(String addr); + private static native String gethostbyaddr(byte[] addr); // END android-changed static int inetAddr(String host) throws UnknownHostException { @@ -664,35 +628,22 @@ public class InetAddress extends Object implements Serializable { static InetAddress getHostByNameImpl(String name, boolean preferIPv6Address) throws UnknownHostException { // TODO Mapped Harmony to Android native. Get rid of indirection later. - return new InetAddress(gethostbyname(name, preferIPv6Address), name); + return getAllByName(name)[0]; } - - /** - * Wrapper for libc call. It is assumed to be thread-safe, which is - * in fact the case on Android. Either returns a raw address or throws - * UnknownHostException. - */ - private native static byte[] gethostbyname(String host, boolean preferIPv6Addresses); // END android-changed /** - * Query the IP stack for the host machine name. + * Gets the host name of the system. * - * @return String the host machine name + * @return String the system hostname */ // BEGIN android-changed - // static native String getHostNameImpl(); static String getHostNameImpl() { // TODO Mapped Harmony to Android native. Get rid of indirection later. return gethostname(); } - - /** - * Wrapper for libc call. It is assumed to be thread-safe, which is - * in fact the case on Android. - */ - private native static String gethostname(); + static native String gethostname(); // END android-changed static String getHostNameInternal(String host) throws UnknownHostException { @@ -1037,7 +988,7 @@ public class InetAddress extends Object implements Serializable { // if (!reachable) { reachable = isReachableByTCP(this, null, timeout); // } - // END adnroid-changed + // END android-changed } else { // Not Bind to any address if (null == netif.addresses) { diff --git a/luni/src/main/java/java/net/SocketPermission.java b/luni/src/main/java/java/net/SocketPermission.java index 9112590..72d77e7 100644 --- a/luni/src/main/java/java/net/SocketPermission.java +++ b/luni/src/main/java/java/net/SocketPermission.java @@ -14,6 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +// BEGIN andorid-note +// This class was copied from a newer version of harmony +// END andorid-note package java.net; @@ -140,7 +143,7 @@ public final class SocketPermission extends Permission implements Serializable { setActions(action); actions = toCanonicalActionString(action); // Use host since we are only checking for port presence - parsePort(host); + parsePort(host, hostName); } /** @@ -238,6 +241,7 @@ public final class SocketPermission extends Permission implements Serializable { } else if (action.equals(actionNames[SP_ACCEPT])) { actionsMask |= SP_ACCEPT; } else if (action.equals(actionNames[SP_RESOLVE])) { + // do nothing } else { throw new IllegalArgumentException(Msg.getString("K0048", //$NON-NLS-1$ action)); @@ -297,70 +301,61 @@ public final class SocketPermission extends Permission implements Serializable { public PermissionCollection newPermissionCollection() { return new SocketPermissionCollection(); } - + /** - * Parses the port string into the lower and higher bound of the port range. - * + * Parse the port, including the minPort, maxPort + * @param hostPort the host[:port] one + * @param host the host name we just get + * @throws IllegalArgumentException If the port is not a positive number or minPort + * is not less than or equal maxPort */ - private void parsePort(String hostString) throws IllegalArgumentException { - int negidx = -1; - int len = -1; - int lastIdx = hostString.lastIndexOf(':'); - int idx = hostString.indexOf(':'); - int endOfIPv6Addr = hostString.lastIndexOf(']'); - if ((endOfIPv6Addr == -1) && (idx != lastIdx)) { - // there are no square braces, but there are more than one ':' which - // implies an IPv6 address with no port, or an illegal argument - // check for valid IPv6 address - if (Inet6Util.isValidIP6Address(hostString)) { - return; - } - // throw an invalid argument exception - throw new IllegalArgumentException(Msg.getString("K004a")); //$NON-NLS-1$ - } - // if there is a colon and it occurs after the ']' then there is a port - // to be parsed - if ((lastIdx > -1) && (lastIdx > endOfIPv6Addr)) { - try { - len = hostString.length(); - // if hostString ends with ":*", such as "localhost:*" - // the port range should be 0-65535 - if (hostString.endsWith(":*")) { //$NON-NLS-1$ - portMin = 0; - portMax = 65535; - return; - } - // look for a '-' after the colon - negidx = hostString.indexOf('-', lastIdx); - if (negidx == lastIdx + 1) { - portMax = Integer.parseInt(hostString.substring( - lastIdx + 2, len)); - } else { - // A port range was provided - if (negidx != -1 && (negidx != len - 1)) { - portMin = Integer.parseInt(hostString.substring( - lastIdx + 1, negidx)); - portMax = Integer.parseInt(hostString.substring( - negidx + 1, len)); - } else { - if (negidx == -1) { - portMin = Integer.parseInt(hostString.substring( - lastIdx + 1, len)); - portMax = portMin; - } else { - portMin = Integer.parseInt(hostString.substring( - lastIdx + 1, negidx)); - } - } - } - if (portMax < portMin) { - throw new IllegalArgumentException(Msg.getString("K0049")); //$NON-NLS-1$ - } - - } catch (NumberFormatException e) { - throw new IllegalArgumentException(Msg.getString("K004a")); //$NON-NLS-1$ - } - } + private void parsePort(String hostPort, String host) throws IllegalArgumentException { + String port = hostPort.substring(host.length()); + String emptyString = ""; //$NON-NLS-1$ + + if (emptyString.equals(port)) { + // Not specified + portMin = 80; + portMax = 80; + return; + } + + if (":*".equals(port)) { + // The port range should be 0-65535 + portMin = 0; + portMax = 65535; + return; + } + + // Omit ':' + port = port.substring(1); + int negIdx = port.indexOf('-'); + String strPortMin = emptyString; + String strPortMax = emptyString; + if (-1 == negIdx) { + // No neg mark, only one number + strPortMin = port; + strPortMax = port; + } else { + strPortMin = port.substring(0, negIdx); + strPortMax = port.substring(negIdx + 1); + if (emptyString.equals(strPortMin)) { + strPortMin = "0"; + } + if (emptyString.equals(strPortMax)) { + strPortMax = "65535"; + } + } + try { + portMin = Integer.valueOf(strPortMin).intValue(); + portMax = Integer.valueOf(strPortMax).intValue(); + + if (portMin > portMax) { + throw new IllegalArgumentException(Msg.getString("K0049") + " " + port); //$NON-NLS-1$ + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException(Msg.getString("K004a") + " " + port); //$NON-NLS-1$ + } } /** @@ -400,13 +395,26 @@ public final class SocketPermission extends Permission implements Serializable { try { ipString = InetAddress.getHostNameInternal(hostName); } catch (UnknownHostException e) { + // ignore } resolved = true; } return ipString; } + /** + * Get the host part from the host[:port] one. + * The host should be + * host = (hostname | IPv4address | IPv6reference | IPv6 in full uncompressed form) + * The wildcard "*" may be included once in a DNS name host specification. If it is included, + * it must be in the leftmost position + * + * @param host + * @return + * @throws IllegalArgumentException if the host is invalid. + */ private String getHostString(String host) throws IllegalArgumentException { + host = host.trim(); int idx = -1; idx = host.indexOf(':'); isPartialWild = (host.length() > 0 && host.charAt(0) == '*'); @@ -423,22 +431,46 @@ public final class SocketPermission extends Permission implements Serializable { } int lastIdx = host.lastIndexOf(':'); - if ((idx > -1) && (idx == lastIdx)) { - host = host.substring(0, idx); - } else { - // likely host is or contains an IPv6 address - if (lastIdx != -1) { - if (Inet6Util.isValidIP6Address(host)) { - return host.toLowerCase(); - } else if (Inet6Util.isValidIP6Address(host.substring(0, - lastIdx))) { - host = host.substring(0, lastIdx); - } else { - throw new IllegalArgumentException(Msg.getString("K004a")); //$NON-NLS-1$ + + if (idx == lastIdx) { + if (-1 != idx) { + // only one colon, should be port + host = host.substring(0, idx); + } + return host.toLowerCase(); + } + // maybe ipv6 + boolean isFirstBracket = (host.charAt(0) == '['); + if (!isFirstBracket) { + // No bracket, should be in full form + int colonNum = 0; + for (int i = 0; i < host.length(); ++i) { + if (host.charAt(i) == ':') { + colonNum++; } } + // Get rid of the colon before port + if (8 == colonNum) { + host = host.substring(0, lastIdx); + } + if (Inet6Util.isIP6AddressInFullForm(host)) { + return host.toLowerCase(); + } + throw new IllegalArgumentException(Msg.getString("K004a") + " " + + host); + } + // forward bracket found + int bbracketIdx = host.indexOf(']'); + if (-1 == bbracketIdx) { + // no back bracket found, wrong + throw new IllegalArgumentException(Msg.getString("K004a") + " " + + host); + } + host = host.substring(0, bbracketIdx + 1); + if (Inet6Util.isValidIP6Address(host)) { + return host.toLowerCase(); } - return host.toLowerCase(); + throw new IllegalArgumentException(Msg.getString("K004a") + " " + host); } /** @@ -474,7 +506,7 @@ public final class SocketPermission extends Permission implements Serializable { portMax = HIGHEST_PORT; actionsMask = SP_RESOLVE; hostName = getHostString(getName()); - parsePort(getName()); + parsePort(getName(), hostName); setActions(actions); } } diff --git a/luni/src/main/java/java/net/URLConnection.java b/luni/src/main/java/java/net/URLConnection.java index ce92aad..6c1a192 100644 --- a/luni/src/main/java/java/net/URLConnection.java +++ b/luni/src/main/java/java/net/URLConnection.java @@ -840,9 +840,12 @@ public abstract class URLConnection { * @since Android 1.0 */ public void setDefaultUseCaches(boolean newValue) { - if (connected) { - throw new IllegalAccessError(Msg.getString("K0037")); //$NON-NLS-1$ - } + // BEGIN android-removed + // Setting the default doesn't concern the current connection. + // if (connected) { + // throw new IllegalAccessError(Msg.getString("K0037")); //$NON-NLS-1$ + // } + // END android-removed defaultUseCaches = newValue; } diff --git a/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java index d8aa6ee..6af24b0 100644 --- a/luni/src/main/java/java/util/Arrays.java +++ b/luni/src/main/java/java/util/Arrays.java @@ -27,9 +27,6 @@ import java.lang.reflect.Array; */ public class Arrays { - /* Specifies when to switch to insertion sort */ - private static final int SIMPLE_LENGTH = 7; - private static class ArrayList<E> extends AbstractList<E> implements List<E>, Serializable, RandomAccess { @@ -131,7 +128,7 @@ public class Arrays { } @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"}) public <T> T[] toArray(T[] contents) { int size = size(); if (size > contents.length) { @@ -2373,6 +2370,41 @@ public class Arrays { } } +// BEGIN android-changed + + /* + * <p>If this platform has an optimizing VM, check whether ComparableTimSort + * offers any performance benefit over TimSort in conjunction with a + * comparator that returns: + * {@code ((Comparable)first).compareTo(Second)}. + * If not, you are better off deleting ComparableTimSort to eliminate the + * code duplication. In other words, the commented out code below + * is the preferable implementation for sorting arrays of comparbles if it + * offers sufficient performance. + */ + +// /** +// * A comparator that implements the natural order of a group of +// * mutually comparable elements. Using this comparator saves us +// * from duplicating most of the code in this file (one version for +// * commparables, one for explicit comparators). +// */ +// private static final Comparator<Object> NATURAL_ORDER = +// new Comparator<Object>() { +// @SuppressWarnings("unchecked") +// public int compare(Object first, Object second) { +// return ((Comparable<Object>)first).compareTo(second); +// } +// }; +// +// public static void sort(Object[] a) { +// sort(a, 0, a.length, NATURAL_ORDER); +// } +// +// public static void sort(Object[] a, int fromIndex, int toIndex) { +// sort(a, fromIndex, toIndex, NATURAL_ORDER); +// } + /** * Sorts the specified array in ascending natural order. * @@ -2385,7 +2417,7 @@ public class Arrays { * @since Android 1.0 */ public static void sort(Object[] array) { - sort(0, array.length, array); + ComparableTimSort.sort(array); } /** @@ -2410,507 +2442,7 @@ public class Arrays { * @since Android 1.0 */ public static void sort(Object[] array, int start, int end) { - if (array == null) { - throw new NullPointerException(); - } - checkBounds(array.length, start, end); - sort(start, end, array); - } - - private static void sort(int fromIndex, int toIndex, Object[] array) { - int length = toIndex - fromIndex; - if (length <= 0) { - return; - } - if (array instanceof String[]) { - stableStringSort((String[]) array, fromIndex, toIndex); - } else { - Object[] out = new Object[toIndex]; - System.arraycopy(array, fromIndex, out, fromIndex, length); - mergeSort(out, array, fromIndex, toIndex); - } - } - - /** - * Swaps the elements at the specified positions in the specified array. - * - * @param a - - * the index of one element to be swapped. - * @param b - - * the index of the other element to be swapped. - * @param arr - - * the array in which to swap elements. - */ - private static void swap(int a, int b, Object[] arr) { - Object tmp = arr[a]; - arr[a] = arr[b]; - arr[b] = tmp; - } - - /** - * Sorts the specified range of the specified array of {@code Objects}. The range to - * be sorted extends from index {@code fromIndex}, inclusive, to index {@code toIndex}, - * exclusive. (If {@code fromIndex==toIndex}, the range to be sorted is empty.) This - * sort is guaranteed to be stable: equal elements will not be reordered as - * a result of the sort. - * - * The sorting algorithm is a mergesort with exponential search (in which - * the merge is performed by exponential search). This algorithm offers - * guaranteed {@code n*log(n)} performance and in average case faster then any - * mergesort in which the merge is performed by linear search. - * - * @param in - - * the array for sorting. - * @param out - - * the result, sorted array. - * @param fromIndex - - * the index of the first element (inclusive) to be sorted. - * @param toIndex - - * the index of the last element (exclusive) to be sorted. - */ - @SuppressWarnings("unchecked") - private static void mergeSort(Object[] in, Object[] out, int fromIndex, - int toIndex) { - int len = toIndex - fromIndex; - // use insertion sort for small arrays - if (len <= SIMPLE_LENGTH) { - for (int i = fromIndex + 1; i < toIndex; i++) { - Comparable<Object> current = (Comparable<Object>) out[i]; - Object prev = out[i - 1]; - if (current.compareTo(prev) < 0) { - int j = i; - do { - out[j--] = prev; - } while (j > fromIndex - && current.compareTo(prev = out[j - 1]) < 0); - out[j] = current; - } - } - return; - } - int med = (toIndex + fromIndex) >> 1; - mergeSort(out, in, fromIndex, med); - mergeSort(out, in, med, toIndex); - - // merging - - // if arrays are already sorted - no merge - if (((Comparable<Object>) in[med]).compareTo(in[med - 1]) >= 0) { - System.arraycopy(in, fromIndex, out, fromIndex, len); - return; - } - int r = med, i = fromIndex; - - // use merging with exponential search - do { - Comparable<Object> fromVal = (Comparable<Object>) in[fromIndex]; - Comparable<Object> rVal = (Comparable<Object>) in[r]; - if (fromVal.compareTo(rVal) <= 0) { - int l_1 = find(in, rVal, -1, fromIndex + 1, med - 1); - int toCopy = l_1 - fromIndex + 1; - System.arraycopy(in, fromIndex, out, i, toCopy); - i += toCopy; - out[i++] = rVal; - r++; - fromIndex = l_1 + 1; - } else { - int r_1 = find(in, fromVal, 0, r + 1, toIndex - 1); - int toCopy = r_1 - r + 1; - System.arraycopy(in, r, out, i, toCopy); - i += toCopy; - out[i++] = fromVal; - fromIndex++; - r = r_1 + 1; - } - } while ((toIndex - r) > 0 && (med - fromIndex) > 0); - - // copy rest of array - if ((toIndex - r) <= 0) { - System.arraycopy(in, fromIndex, out, i, med - fromIndex); - } else { - System.arraycopy(in, r, out, i, toIndex - r); - } - } - - /** - * Sorts the specified range of the specified array of objects. The range to - * be sorted extends from index fromIndex, inclusive, to index toIndex, - * exclusive. (If fromIndex==toIndex, the range to be sorted is empty.) This - * sort is guaranteed to be stable: equal elements will not be reordered as - * a result of the sort. - * - * The sorting algorithm is a mergesort with exponential search (in which - * the merge is performed by exponential search). This algorithm offers - * guaranteed n*log(n) performance and in average case faster then any - * mergesort in which the merge is performed by linear search. - * - * @param in - - * the array for sorting. - * @param out - - * the result, sorted array. - * @param fromIndex - - * the index of the first element (inclusive) to be sorted. - * @param toIndex - - * the index of the last element (exclusive) to be sorted. - * @param c - - * the comparator to determine the order of the array. - */ - @SuppressWarnings("unchecked") - private static void mergeSort(Object[] in, Object[] out, int fromIndex, - int toIndex, Comparator c) { - int len = toIndex - fromIndex; - // use insertion sort for small arrays - if (len <= SIMPLE_LENGTH) { - for (int i = fromIndex + 1; i < toIndex; i++) { - Object current = out[i]; - Object prev = out[i - 1]; - if (c.compare(prev, current) > 0) { - int j = i; - do { - out[j--] = prev; - } while (j > fromIndex - && (c.compare(prev = out[j - 1], current) > 0)); - out[j] = current; - } - } - return; - } - int med = (toIndex + fromIndex) >> 1; - mergeSort(out, in, fromIndex, med, c); - mergeSort(out, in, med, toIndex, c); - - // merging - - // if arrays are already sorted - no merge - if (c.compare(in[med], in[med - 1]) >= 0) { - System.arraycopy(in, fromIndex, out, fromIndex, len); - return; - } - int r = med, i = fromIndex; - - // use merging with exponential search - do { - Object fromVal = in[fromIndex]; - Object rVal = in[r]; - if (c.compare(fromVal, rVal) <= 0) { - int l_1 = find(in, rVal, -1, fromIndex + 1, med - 1, c); - int toCopy = l_1 - fromIndex + 1; - System.arraycopy(in, fromIndex, out, i, toCopy); - i += toCopy; - out[i++] = rVal; - r++; - fromIndex = l_1 + 1; - } else { - int r_1 = find(in, fromVal, 0, r + 1, toIndex - 1, c); - int toCopy = r_1 - r + 1; - System.arraycopy(in, r, out, i, toCopy); - i += toCopy; - out[i++] = fromVal; - fromIndex++; - r = r_1 + 1; - } - } while ((toIndex - r) > 0 && (med - fromIndex) > 0); - - // copy rest of array - if ((toIndex - r) <= 0) { - System.arraycopy(in, fromIndex, out, i, med - fromIndex); - } else { - System.arraycopy(in, r, out, i, toIndex - r); - } - } - - /** - * Finds the place where the element should be inserted into the specified - * range of the specified sorted array so that the resulting array would - * remain sorted. Uses an exponential search algorithm. - * - * @param arr - - * the array with a sorted range - * - * @param val - - * the object to be inserted - * - * @param l - - * the index of the first element (inclusive) - * - * @param r - - * the index of the last element (inclusive) - * - * @param bnd - - * A specifier to indicate how to treat the case where the - * array range contains an element or elements equal to - * {@code val}. "{@code -1}" indicates that val should be placed at - * the index greater than the indices of any elements equal to - * {@code val}. "{@code 0}" - indicates that val should be placed at - * the index less than the indices of any elements equal to - * {@code val}. - * - */ - @SuppressWarnings("unchecked") - private static int find(Object[] arr, Comparable val, int bnd, int l, int r) { - int m = l; - int d = 1; - while (m <= r) { - if (val.compareTo(arr[m]) > bnd) { - l = m + 1; - } else { - r = m - 1; - break; - } - m += d; - d <<= 1; - } - while (l <= r) { - m = (l + r) >> 1; - if (val.compareTo(arr[m]) > bnd) { - l = m + 1; - } else { - r = m - 1; - } - } - return l - 1; - } - - /** - * Finds the place where the element should be inserted into the specified - * range of the specified sorted array so that the resulting array would - * remain sorted. Uses an exponential search algorithm. - * - * @param arr - - * the array with a sorted range - * - * @param val - - * the object to be inserted - * - * @param l - - * the index of the first element (inclusive) - * - * @param r - - * the index of the last element (inclusive) - * - * @param bnd - - * A specifier to indicate how to treat the case where the - * array range contains an element or elements equal to - * {@code val}. "{@code -1}" indicates that val should be placed at - * the index greater than the indices of any elements equal to - * {@code val}. "{@code 0}" - indicates that val should be placed at - * the index less than the indices of any elements equal to - * {@code val}. - * - * @param c - - * the {@code Comparator} to determine the ordering of the array. - */ - @SuppressWarnings("unchecked") - private static int find(Object[] arr, Object val, int bnd, int l, int r, - Comparator c) { - int m = l; - int d = 1; - while (m <= r) { - if (c.compare(val, arr[m]) > bnd) { - l = m + 1; - } else { - r = m - 1; - break; - } - m += d; - d <<= 1; - } - while (l <= r) { - m = (l + r) >> 1; - if (c.compare(val, arr[m]) > bnd) { - l = m + 1; - } else { - r = m - 1; - } - } - return l - 1; - } - - /* - * returns the median index. - */ - private static int medChar(int a, int b, int c, String[] arr, int id) { - int ac = charAt(arr[a], id); - int bc = charAt(arr[b], id); - int cc = charAt(arr[c], id); - return ac < bc ? (bc < cc ? b : (ac < cc ? c : a)) - : (bc < cc ? (ac < cc ? a : c) : b); - - } - - /* - * Returns the char value at the specified index of string or -1 if the - * index more than the length of this string. - */ - private static int charAt(String str, int i) { - if (i >= str.length()) { - return -1; - } - return str.charAt(i); - } - - /** - * Copies object from one array to another array with reverse of objects - * order. Source and destination arrays may be the same. - * - * @param src - - * the source array. - * @param from - - * starting position in the source array. - * @param dst - - * the destination array. - * @param to - - * starting position in the destination array. - * @param len - - * the number of array elements to be copied. - */ - private static void copySwap(Object[] src, int from, Object[] dst, int to, - int len) { - if (src == dst && from + len > to) { - int new_to = to + len - 1; - for (; from < to; from++, new_to--, len--) { - dst[new_to] = src[from]; - } - for (; len > 1; from++, new_to--, len -= 2) { - swap(from, new_to, dst); - } - - } else { - to = to + len - 1; - for (; len > 0; from++, to--, len--) { - dst[to] = src[from]; - } - } - } - - /** - * Sorts the specified range of the specified {@code String} array. - * - * @param arr - - * the array to be sorted - * @param fromIndex - - * the index of the first element (inclusive) to be sorted. - * @param toIndex - - * the index of the last element (exclusive) to be sorted. - */ - private static void stableStringSort(String[] arr, int fromIndex, - int toIndex) { - stableStringSort(arr, arr, new String[toIndex], fromIndex, toIndex, 0); - } - - /** - * Sorts the specified range of the specified {@code String} array. Use stable - * ternary quick sort algorithm. - * - * @param arr - - * the array to be sorted - * @param src - - * auxiliary array - * @param dst - - * auxiliary array - * @param fromIndex - - * the index of the first element (inclusive) to be sorted. - * @param toIndex - - * the index of the last element (exclusive) to be sorted. - * @param chId - - * index of {@code char} for current sorting - */ - private static void stableStringSort(String[] arr, String[] src, - String[] dst, int fromIndex, int toIndex, int chId) { - int length = toIndex - fromIndex; - // use insertion sort for small arrays - if (length < SIMPLE_LENGTH) { - if (src == arr) { - for (int i = fromIndex + 1; i < toIndex; i++) { - String current = arr[i]; - String prev = arr[i - 1]; - if (current.compareTo(prev) < 0) { - int j = i; - do { - arr[j--] = prev; - } while (j > fromIndex - && current.compareTo(prev = arr[j - 1]) < 0); - arr[j] = current; - } - } - } else { - int end = toIndex - 1; - dst[fromIndex] = src[end--]; - for (int i = fromIndex + 1; i < toIndex; i++, end--) { - String current = src[end]; - String prev; - int j = i; - while (j > fromIndex - && current.compareTo(prev = dst[j - 1]) < 0) { - dst[j--] = prev; - } - dst[j] = current; - } - } - return; - } - // Approximate median - int s; - int mid = fromIndex + length / 2; - int lo = fromIndex; - int hi = toIndex - 1; - if (length > 40) { - s = length / 8; - lo = medChar(lo, lo + s, lo + s * 2, src, chId); - mid = medChar(mid - s, mid, mid + s, src, chId); - hi = medChar(hi, hi - s, hi - s * 2, src, chId); - } - mid = medChar(lo, mid, hi, src, chId); - // median found - // create 4 pointers <a (in star of src) , - // =b(in start of dst), >c (in end of dst) - // i - current element; - int midVal = charAt(src[mid], chId); - int a, b, c; - a = b = fromIndex; - c = toIndex - 1; - int cmp; - - for (int i = fromIndex; i < toIndex; i++) { - String el = src[i]; - cmp = charAt(el, chId) - midVal; - if (cmp < 0) { - src[a] = el; - a++; - } else if (cmp > 0) { - dst[c] = el; - c--; - } else { - dst[b] = el; - b++; - } - } - - s = b - fromIndex; - if (s > 0) { - if (arr == src) { - System.arraycopy(dst, fromIndex, arr, a, s); - } else { - copySwap(dst, fromIndex, arr, a, s); - } - - if (b >= toIndex && midVal == -1) { - return; - } - stableStringSort(arr, arr, arr == dst ? src : dst, a, a + s, - chId + 1); - } - - s = a - fromIndex; - if (s > 0) { - stableStringSort(arr, src, dst, fromIndex, a, chId); - } - - c++; - s = toIndex - c; - if (s > 0) { - stableStringSort(arr, dst, src, c, toIndex, chId); - } + ComparableTimSort.sort(array, start, end); } /** @@ -2937,23 +2469,7 @@ public class Arrays { */ public static <T> void sort(T[] array, int start, int end, Comparator<? super T> comparator) { - if (array == null) { - throw new NullPointerException(); - } - checkBounds(array.length, start, end); - sort(start, end, array, comparator); - } - - private static <T> void sort(int start, int end, T[] array, - Comparator<? super T> comparator) { - if (comparator == null) { - sort(start, end, array); - } else { - int length = end - start; - Object[] out = new Object[end]; - System.arraycopy(array, start, out, start, length); - mergeSort(out, array, start, end, comparator); - } + TimSort.sort(array, start, end, comparator); } /** @@ -2970,9 +2486,11 @@ public class Arrays { * @since Android 1.0 */ public static <T> void sort(T[] array, Comparator<? super T> comparator) { - sort(0, array.length, array, comparator); + TimSort.sort(array, comparator); } +// END android-changed + /** * Sorts the specified array in ascending numerical order. * diff --git a/luni/src/main/java/java/util/ComparableTimSort.java b/luni/src/main/java/java/util/ComparableTimSort.java new file mode 100644 index 0000000..b9f7145 --- /dev/null +++ b/luni/src/main/java/java/util/ComparableTimSort.java @@ -0,0 +1,885 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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 java.util; + +/** + * This is a near duplicate of {@link TimSort}, modified for use with + * arrays of objects that implement {@link Comparable}, instead of using + * explicit comparators. + * + * <p>If you are using an optimizing VM, you may find that ComparableTimSort + * offers no performance benefit over TimSort in conjunction with a + * comparator that simply returns {@code ((Comparable)first).compareTo(Second)}. + * If this is the case, you are better off deleting ComparableTimSort to + * eliminate the code duplication. (See Arrays.java for details.) + */ +class ComparableTimSort { + /** + * This is the minimum sized sequence that will be merged. Shorter + * sequences will be lengthened by calling binarySort. If the entire + * array is less than this length, no merges will be performed. + * + * This constant should be a power of two. It was 64 in Tim Peter's C + * implementation, but 32 was empirically determined to work better in + * this implementation. In the unlikely event that you set this constant + * to be a number that's not a power of two, you'll need to change the + * {@link #minRunLength} computation. + * + * If you decrease this constant, you must change the stackLen + * computation in the TimSort constructor, or you risk an + * ArrayOutOfBounds exception. See listsort.txt for a discussion + * of the minimum stack length required as a function of the length + * of the array being sorted and the minimum merge sequence length. + */ + private static final int MIN_MERGE = 32; + + /** + * The array being sorted. + */ + private final Object[] a; + + /** + * When we get into galloping mode, we stay there until both runs win less + * often than MIN_GALLOP consecutive times. + */ + private static final int MIN_GALLOP = 7; + + /** + * This controls when we get *into* galloping mode. It is initialized + * to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for + * random data, and lower for highly structured data. + */ + private int minGallop = MIN_GALLOP; + + /** + * Maximum initial size of tmp array, which is used for merging. The array + * can grow to accommodate demand. + * + * Unlike Tim's original C version, we do not allocate this much storage + * when sorting smaller arrays. This change was required for performance. + */ + private static final int INITIAL_TMP_STORAGE_LENGTH = 256; + + /** + * Temp storage for merges. + */ + private Object[] tmp; + + /** + * A stack of pending runs yet to be merged. Run i starts at + * address base[i] and extends for len[i] elements. It's always + * true (so long as the indices are in bounds) that: + * + * runBase[i] + runLen[i] == runBase[i + 1] + * + * so we could cut the storage for this, but it's a minor amount, + * and keeping all the info explicit simplifies the code. + */ + private int stackSize = 0; // Number of pending runs on stack + private final int[] runBase; + private final int[] runLen; + + /** + * Asserts have been placed in if-statements for performace. To enable them, + * set this field to true and enable them in VM with a command line flag. + * If you modify this class, please do test the asserts! + */ + private static final boolean DEBUG = false; + + /** + * Creates a TimSort instance to maintain the state of an ongoing sort. + * + * @param a the array to be sorted + */ + private ComparableTimSort(Object[] a) { + this.a = a; + + // Allocate temp storage (which may be increased later if necessary) + int len = a.length; + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ? + len >>> 1 : INITIAL_TMP_STORAGE_LENGTH]; + tmp = newArray; + + /* + * Allocate runs-to-be-merged stack (which cannot be expanded). The + * stack length requirements are described in listsort.txt. The C + * version always uses the same stack length (85), but this was + * measured to be too expensive when sorting "mid-sized" arrays (e.g., + * 100 elements) in Java. Therefore, we use smaller (but sufficiently + * large) stack lengths for smaller arrays. The "magic numbers" in the + * computation below must be changed if MIN_MERGE is decreased. See + * the MIN_MERGE declaration above for more information. + */ + int stackLen = (len < 120 ? 5 : + len < 1542 ? 10 : + len < 119151 ? 19 : 40); + runBase = new int[stackLen]; + runLen = new int[stackLen]; + } + + /* + * The next two methods (which are package private and static) constitute + * the entire API of this class. Each of these methods obeys the contract + * of the public method with the same signature in java.util.Arrays. + */ + + static void sort(Object[] a) { + sort(a, 0, a.length); + } + + static void sort(Object[] a, int lo, int hi) { + rangeCheck(a.length, lo, hi); + int nRemaining = hi - lo; + if (nRemaining < 2) + return; // Arrays of size 0 and 1 are always sorted + + // If array is small, do a "mini-TimSort" with no merges + if (nRemaining < MIN_MERGE) { + int initRunLen = countRunAndMakeAscending(a, lo, nRemaining); + binarySort(a, lo, hi, lo + initRunLen); + return; + } + + /** + * March over the array once, left to right, finding natural runs, + * extending short natural runs to minRun elements, and merging runs + * to maintain stack invariant. + */ + ComparableTimSort ts = new ComparableTimSort(a); + int minRun = minRunLength(nRemaining); + do { + // Identify next run + int runLen = countRunAndMakeAscending(a, lo, hi); + + // If run is short, extend to min(minRun, nRemaining) + if (runLen < minRun) { + int force = nRemaining <= minRun ? nRemaining : minRun; + binarySort(a, lo, lo + force, lo + runLen); + runLen = force; + } + + // Push run onto pending-run stack, and maybe merge + ts.pushRun(lo, runLen); + ts.mergeCollapse(); + + // Advance to find next run + lo += runLen; + nRemaining -= runLen; + } while (nRemaining != 0); + + // Merge all remaining runs to complete sort + if (DEBUG) assert lo == hi; + ts.mergeForceCollapse(); + if (DEBUG) assert ts.stackSize == 1; + } + + /** + * Sorts the specified portion of the specified array using a binary + * insertion sort. This is the best method for sorting small numbers + * of elements. It requires O(n log n) compares, but O(n^2) data + * movement (worst case). + * + * If the initial part of the specified range is already sorted, + * this method can take advantage of it: the method assumes that the + * elements from index {@code lo}, inclusive, to {@code start}, + * exclusive are already sorted. + * + * @param a the array in which a range is to be sorted + * @param lo the index of the first element in the range to be sorted + * @param hi the index after the last element in the range to be sorted + * @param start the index of the first element in the range that is + * not already known to be sorted (@code lo <= start <= hi} + */ + @SuppressWarnings("fallthrough") + private static void binarySort(Object[] a, int lo, int hi, int start) { + if (DEBUG) assert lo <= start && start <= hi; + if (start == lo) + start++; + for ( ; start < hi; start++) { + @SuppressWarnings("unchecked") + Comparable<Object> pivot = (Comparable) a[start]; + + // Set left (and right) to the index where a[start] (pivot) belongs + int left = lo; + int right = start; + if (DEBUG) assert left <= right; + /* + * Invariants: + * pivot >= all in [lo, left). + * pivot < all in [right, start). + */ + while (left < right) { + int mid = (left + right) >>> 1; + if (pivot.compareTo(a[mid]) < 0) + right = mid; + else + left = mid + 1; + } + if (DEBUG) assert left == right; + + /* + * The invariants still hold: pivot >= all in [lo, left) and + * pivot < all in [left, start), so pivot belongs at left. Note + * that if there are elements equal to pivot, left points to the + * first slot after them -- that's why this sort is stable. + * Slide elements over to make room to make room for pivot. + */ + int n = start - left; // The number of elements to move + // Switch is just an optimization for arraycopy in default case + switch(n) { + case 2: a[left + 2] = a[left + 1]; + case 1: a[left + 1] = a[left]; + break; + default: System.arraycopy(a, left, a, left + 1, n); + } + a[left] = pivot; + } + } + + /** + * Returns the length of the run beginning at the specified position in + * the specified array and reverses the run if it is descending (ensuring + * that the run will always be ascending when the method returns). + * + * A run is the longest ascending sequence with: + * + * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... + * + * or the longest descending sequence with: + * + * a[lo] > a[lo + 1] > a[lo + 2] > ... + * + * For its intended use in a stable mergesort, the strictness of the + * definition of "descending" is needed so that the call can safely + * reverse a descending sequence without violating stability. + * + * @param a the array in which a run is to be counted and possibly reversed + * @param lo index of the first element in the run + * @param hi index after the last element that may be contained in the run. + It is required that @code{lo < hi}. + * @return the length of the run beginning at the specified position in + * the specified array + */ + @SuppressWarnings("unchecked") + private static int countRunAndMakeAscending(Object[] a, int lo, int hi) { + if (DEBUG) assert lo < hi; + int runHi = lo + 1; + if (runHi == hi) + return 1; + + // Find end of run, and reverse range if descending + if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending + while(runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0) + runHi++; + reverseRange(a, lo, runHi); + } else { // Ascending + while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0) + runHi++; + } + + return runHi - lo; + } + + /** + * Reverse the specified range of the specified array. + * + * @param a the array in which a range is to be reversed + * @param lo the index of the first element in the range to be reversed + * @param hi the index after the last element in the range to be reversed + */ + private static void reverseRange(Object[] a, int lo, int hi) { + hi--; + while (lo < hi) { + Object t = a[lo]; + a[lo++] = a[hi]; + a[hi--] = t; + } + } + + /** + * Returns the minimum acceptable run length for an array of the specified + * length. Natural runs shorter than this will be extended with + * {@link #binarySort}. + * + * Roughly speaking, the computation is: + * + * If n < MIN_MERGE, return n (it's too small to bother with fancy stuff). + * Else if n is an exact power of 2, return MIN_MERGE/2. + * Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k + * is close to, but strictly less than, an exact power of 2. + * + * For the rationale, see listsort.txt. + * + * @param n the length of the array to be sorted + * @return the length of the minimum run to be merged + */ + private static int minRunLength(int n) { + if (DEBUG) assert n >= 0; + int r = 0; // Becomes 1 if any 1 bits are shifted off + while (n >= MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + return n + r; + } + + /** + * Pushes the specified run onto the pending-run stack. + * + * @param runBase index of the first element in the run + * @param runLen the number of elements in the run + */ + private void pushRun(int runBase, int runLen) { + this.runBase[stackSize] = runBase; + this.runLen[stackSize] = runLen; + stackSize++; + } + + /** + * Examines the stack of runs waiting to be merged and merges adjacent runs + * until the stack invariants are reestablished: + * + * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] + * 2. runLen[i - 2] > runLen[i - 1] + * + * This method is called each time a new run is pushed onto the stack, + * so the invariants are guaranteed to hold for i < stackSize upon + * entry to the method. + */ + private void mergeCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) { + if (runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } else if (runLen[n] <= runLen[n + 1]) { + mergeAt(n); + } else { + break; // Invariant is established + } + } + } + + /** + * Merges all runs on the stack until only one remains. This method is + * called once, to complete the sort. + */ + private void mergeForceCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } + } + + /** + * Merges the two runs at stack indices i and i+1. Run i must be + * the penultimate or antepenultimate run on the stack. In other words, + * i must be equal to stackSize-2 or stackSize-3. + * + * @param i stack index of the first of the two runs to merge + */ + @SuppressWarnings("unchecked") + private void mergeAt(int i) { + if (DEBUG) assert stackSize >= 2; + if (DEBUG) assert i >= 0; + if (DEBUG) assert i == stackSize - 2 || i == stackSize - 3; + + int base1 = runBase[i]; + int len1 = runLen[i]; + int base2 = runBase[i + 1]; + int len2 = runLen[i + 1]; + if (DEBUG) assert len1 > 0 && len2 > 0; + if (DEBUG) assert base1 + len1 == base2; + + /* + * Record the length of the combined runs; if i is the 3rd-last + * run now, also slide over the last run (which isn't involved + * in this merge). The current run (i+1) goes away in any case. + */ + runLen[i] = len1 + len2; + if (i == stackSize - 3) { + runBase[i + 1] = runBase[i + 2]; + runLen[i + 1] = runLen[i + 2]; + } + stackSize--; + + /* + * Find where the first element of run2 goes in run1. Prior elements + * in run1 can be ignored (because they're already in place). + */ + int k = gallopRight((Comparable<Object>) a[base2], a, base1, len1, 0); + if (DEBUG) assert k >= 0; + base1 += k; + len1 -= k; + if (len1 == 0) + return; + + /* + * Find where the last element of run1 goes in run2. Subsequent elements + * in run2 can be ignored (because they're already in place). + */ + len2 = gallopLeft((Comparable<Object>) a[base1 + len1 - 1], a, + base2, len2, len2 - 1); + if (DEBUG) assert len2 >= 0; + if (len2 == 0) + return; + + // Merge remaining runs, using tmp array with min(len1, len2) elements + if (len1 <= len2) + mergeLo(base1, len1, base2, len2); + else + mergeHi(base1, len1, base2, len2); + } + + /** + * Locates the position at which to insert the specified key into the + * specified sorted range; if the range contains an element equal to key, + * returns the index of the leftmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], + * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. + * In other words, key belongs at index b + k; or in other words, + * the first k elements of a should precede key, and the last n - k + * should follow it. + */ + private static int gallopLeft(Comparable<Object> key, Object[] a, + int base, int len, int hint) { + if (DEBUG) assert len > 0 && hint >= 0 && hint < len; + + int lastOfs = 0; + int ofs = 1; + if (key.compareTo(a[base + hint]) > 0) { + // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) > 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + lastOfs += hint; + ofs += hint; + } else { // key <= a[base + hint] + // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] + final int maxOfs = hint + 1; + while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) <= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + if (DEBUG) assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere + * to the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (key.compareTo(a[base + m]) > 0) + lastOfs = m + 1; // a[base + m] < key + else + ofs = m; // key <= a[base + m] + } + if (DEBUG) assert lastOfs == ofs; // so a[base + ofs - 1] < key <= a[base + ofs] + return ofs; + } + + /** + * Like gallopLeft, except that if the range contains an element equal to + * key, gallopRight returns the index after the rightmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] + */ + private static int gallopRight(Comparable<Object> key, Object[] a, + int base, int len, int hint) { + if (DEBUG) assert len > 0 && hint >= 0 && hint < len; + + int ofs = 1; + int lastOfs = 0; + if (key.compareTo(a[base + hint]) < 0) { + // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] + int maxOfs = hint + 1; + while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) < 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } else { // a[b + hint] <= key + // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) >= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + lastOfs += hint; + ofs += hint; + } + if (DEBUG) assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to + * the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (key.compareTo(a[base + m]) < 0) + ofs = m; // key < a[b + m] + else + lastOfs = m + 1; // a[b + m] <= key + } + if (DEBUG) assert lastOfs == ofs; // so a[b + ofs - 1] <= key < a[b + ofs] + return ofs; + } + + /** + * Merges two adjacent runs in place, in a stable fashion. The first + * element of the first run must be greater than the first element of the + * second run (a[base1] > a[base2]), and the last element of the first run + * (a[base1 + len1-1]) must be greater than all elements of the second run. + * + * For performance, this method should be called only when len1 <= len2; + * its twin, mergeHi should be called if len1 >= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + @SuppressWarnings("unchecked") + private void mergeLo(int base1, int len1, int base2, int len2) { + if (DEBUG) assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy first run into temp array + Object[] a = this.a; // For performance + Object[] tmp = ensureCapacity(len1); + System.arraycopy(a, base1, tmp, 0, len1); + + int cursor1 = 0; // Indexes into tmp array + int cursor2 = base2; // Indexes int a + int dest = base1; // Indexes int a + + // Move first element of second run and deal with degenerate cases + a[dest++] = a[cursor2++]; + if (--len2 == 0) { + System.arraycopy(tmp, cursor1, a, dest, len1); + return; + } + if (len1 == 1) { + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + return; + } + + int minGallop = this.minGallop; // Use local variable for performance + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run starts + * winning consistently. + */ + do { + if (DEBUG) assert len1 > 1 && len2 > 0; + if (((Comparable) a[cursor2]).compareTo(tmp[cursor1]) < 0) { + a[dest++] = a[cursor2++]; + count2++; + count1 = 0; + if (--len2 == 0) + break outer; + } else { + a[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--len1 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + if (DEBUG) assert len1 > 1 && len2 > 0; + count1 = gallopRight((Comparable) a[cursor2], tmp, cursor1, len1, 0); + if (count1 != 0) { + System.arraycopy(tmp, cursor1, a, dest, count1); + dest += count1; + cursor1 += count1; + len1 -= count1; + if (len1 == 1) + break outer; + } + a[dest++] = a[cursor2++]; + if (--len2 == 0) + break outer; + + count2 = gallopLeft((Comparable) tmp[cursor1], a, cursor2, len2, 0); + if (count2 != 0) { + System.arraycopy(a, cursor2, a, dest, count2); + dest += count2; + cursor2 += count2; + len2 -= count2; + if (len2 == 0) + break outer; + } + a[dest++] = tmp[cursor1++]; + if (--len1 == 1) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len1 == 1) { + if (DEBUG) assert len2 > 0; + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + } else { + if (DEBUG) assert len2 == 0; + if (DEBUG) assert len1 > 1; + System.arraycopy(tmp, cursor1, a, dest, len1); + } + } + + /** + * Like mergeLo, except that this method should be called only if + * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + @SuppressWarnings("unchecked") + private void mergeHi(int base1, int len1, int base2, int len2) { + if (DEBUG) assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy second run into temp array + Object[] a = this.a; // For performance + Object[] tmp = ensureCapacity(len2); + System.arraycopy(a, base2, tmp, 0, len2); + + int cursor1 = base1 + len1 - 1; // Indexes into a + int cursor2 = len2 - 1; // Indexes into tmp array + int dest = base2 + len2 - 1; // Indexes into a + + // Move last element of first run and deal with degenerate cases + a[dest--] = a[cursor1--]; + if (--len1 == 0) { + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + return; + } + if (len2 == 1) { + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; + return; + } + + int minGallop = this.minGallop; // Use local variable for performance + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run + * appears to win consistently. + */ + do { + if (DEBUG) assert len1 > 0 && len2 > 1; + if (((Comparable) tmp[cursor2]).compareTo(a[cursor1]) < 0) { + a[dest--] = a[cursor1--]; + count1++; + count2 = 0; + if (--len1 == 0) + break outer; + } else { + a[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--len2 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + if (DEBUG) assert len1 > 0 && len2 > 1; + count1 = len1 - gallopRight((Comparable) tmp[cursor2], a, base1, len1, len1 - 1); + if (count1 != 0) { + dest -= count1; + cursor1 -= count1; + len1 -= count1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, count1); + if (len1 == 0) + break outer; + } + a[dest--] = tmp[cursor2--]; + if (--len2 == 1) + break outer; + + count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1); + if (count2 != 0) { + dest -= count2; + cursor2 -= count2; + len2 -= count2; + System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2); + if (len2 == 1) + break outer; + } + a[dest--] = a[cursor1--]; + if (--len1 == 0) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len2 == 1) { + if (DEBUG) assert len1 > 0; + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; // Move first elt of run2 to front of merge + } else { + if (DEBUG) assert len1 == 0; + if (DEBUG) assert len2 > 0; + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + } + } + + /** + * Ensures that the external array tmp has at least the specified + * number of elements, increasing its size if necessary. The size + * increases exponentially to ensure amortized linear time complexity. + * + * @param minCapacity the minimum required capacity of the tmp array + * @return tmp, whether or not it grew + */ + private Object[] ensureCapacity(int minCapacity) { + if (tmp.length < minCapacity) { + // Compute smallest power of 2 > minCapacity + int newSize = minCapacity; + newSize |= newSize >> 1; + newSize |= newSize >> 2; + newSize |= newSize >> 4; + newSize |= newSize >> 8; + newSize |= newSize >> 16; + newSize++; + + if (newSize < 0) // Not bloody likely! + newSize = minCapacity; + else + newSize = Math.min(newSize, a.length >>> 1); + + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + Object[] newArray = new Object[newSize]; + tmp = newArray; + } + return tmp; + } + + /** + * Checks that fromIndex and toIndex are in range, and throws an + * appropriate exception if they aren't. + * + * @param arrayLen the length of the array + * @param fromIndex the index of the first element of the range + * @param toIndex the index after the last element of the range + * @throws IllegalArgumentException if fromIndex > toIndex + * @throws ArrayIndexOutOfBoundsException if fromIndex < 0 + * or toIndex > arrayLen + */ + private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) { + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex+")"); + if (fromIndex < 0) + throw new ArrayIndexOutOfBoundsException(fromIndex); + if (toIndex > arrayLen) + throw new ArrayIndexOutOfBoundsException(toIndex); + } +} diff --git a/luni/src/main/java/java/util/TimSort.java b/luni/src/main/java/java/util/TimSort.java new file mode 100644 index 0000000..3c73a2c --- /dev/null +++ b/luni/src/main/java/java/util/TimSort.java @@ -0,0 +1,918 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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 java.util; + +/** + * A stable, adaptive, iterative mergesort that requires far fewer than + * n lg(n) comparisons when running on partially sorted arrays, while + * offering performance comparable to a traditional mergesort when run + * on random arrays. Like all proper mergesorts, this sort is stable and + * runs O(n log n) time (worst case). In the worst case, this sort requires + * temporary storage space for n/2 object references; in the best case, + * it requires only a small constant amount of space. + * + * This implementation was adapted from Tim Peters's list sort for + * Python, which is described in detail here: + * + * http://svn.python.org/projects/python/trunk/Objects/listsort.txt + * + * Tim's C code may be found here: + * + * http://svn.python.org/projects/python/trunk/Objects/listobject.c + * + * The underlying techniques are described in this paper (and may have + * even earlier origins): + * + * "Optimistic Sorting and Information Theoretic Complexity" + * Peter McIlroy + * SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), + * pp 467-474, Austin, Texas, 25-27 January 1993. + * + * While the API to this class consists solely of static methods, it is + * (privately) instantiable; a TimSort instance holds the state of an ongoing + * sort, assuming the input array is large enough to warrant the full-blown + * TimSort. Small arrays are sorted in place, using a binary insertion sort. + */ +class TimSort<T> { + /** + * This is the minimum sized sequence that will be merged. Shorter + * sequences will be lengthened by calling binarySort. If the entire + * array is less than this length, no merges will be performed. + * + * This constant should be a power of two. It was 64 in Tim Peter's C + * implementation, but 32 was empirically determined to work better in + * this implementation. In the unlikely event that you set this constant + * to be a number that's not a power of two, you'll need to change the + * {@link #minRunLength} computation. + * + * If you decrease this constant, you must change the stackLen + * computation in the TimSort constructor, or you risk an + * ArrayOutOfBounds exception. See listsort.txt for a discussion + * of the minimum stack length required as a function of the length + * of the array being sorted and the minimum merge sequence length. + */ + private static final int MIN_MERGE = 32; + + /** + * The array being sorted. + */ + private final T[] a; + + /** + * The comparator for this sort. + */ + private final Comparator<? super T> c; + + /** + * When we get into galloping mode, we stay there until both runs win less + * often than MIN_GALLOP consecutive times. + */ + private static final int MIN_GALLOP = 7; + + /** + * This controls when we get *into* galloping mode. It is initialized + * to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for + * random data, and lower for highly structured data. + */ + private int minGallop = MIN_GALLOP; + + /** + * Maximum initial size of tmp array, which is used for merging. The array + * can grow to accommodate demand. + * + * Unlike Tim's original C version, we do not allocate this much storage + * when sorting smaller arrays. This change was required for performance. + */ + private static final int INITIAL_TMP_STORAGE_LENGTH = 256; + + /** + * Temp storage for merges. + */ + private T[] tmp; // Actual runtime type will be Object[], regardless of T + + /** + * A stack of pending runs yet to be merged. Run i starts at + * address base[i] and extends for len[i] elements. It's always + * true (so long as the indices are in bounds) that: + * + * runBase[i] + runLen[i] == runBase[i + 1] + * + * so we could cut the storage for this, but it's a minor amount, + * and keeping all the info explicit simplifies the code. + */ + private int stackSize = 0; // Number of pending runs on stack + private final int[] runBase; + private final int[] runLen; + + /** + * Asserts have been placed in if-statements for performace. To enable them, + * set this field to true and enable them in VM with a command line flag. + * If you modify this class, please do test the asserts! + */ + private static final boolean DEBUG = false; + + /** + * Creates a TimSort instance to maintain the state of an ongoing sort. + * + * @param a the array to be sorted + * @param c the comparator to determine the order of the sort + */ + private TimSort(T[] a, Comparator<? super T> c) { + this.a = a; + this.c = c; + + // Allocate temp storage (which may be increased later if necessary) + int len = a.length; + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ? + len >>> 1 : INITIAL_TMP_STORAGE_LENGTH]; + tmp = newArray; + + /* + * Allocate runs-to-be-merged stack (which cannot be expanded). The + * stack length requirements are described in listsort.txt. The C + * version always uses the same stack length (85), but this was + * measured to be too expensive when sorting "mid-sized" arrays (e.g., + * 100 elements) in Java. Therefore, we use smaller (but sufficiently + * large) stack lengths for smaller arrays. The "magic numbers" in the + * computation below must be changed if MIN_MERGE is decreased. See + * the MIN_MERGE declaration above for more information. + */ + int stackLen = (len < 120 ? 5 : + len < 1542 ? 10 : + len < 119151 ? 19 : 40); + runBase = new int[stackLen]; + runLen = new int[stackLen]; + } + + /* + * The next two methods (which are package private and static) constitute + * the entire API of this class. Each of these methods obeys the contract + * of the public method with the same signature in java.util.Arrays. + */ + + static <T> void sort(T[] a, Comparator<? super T> c) { + sort(a, 0, a.length, c); + } + + static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) { + if (c == null) { + Arrays.sort(a, lo, hi); + return; + } + + rangeCheck(a.length, lo, hi); + int nRemaining = hi - lo; + if (nRemaining < 2) + return; // Arrays of size 0 and 1 are always sorted + + // If array is small, do a "mini-TimSort" with no merges + if (nRemaining < MIN_MERGE) { + int initRunLen = countRunAndMakeAscending(a, lo, nRemaining, c); + binarySort(a, lo, hi, lo + initRunLen, c); + return; + } + + /** + * March over the array once, left to right, finding natural runs, + * extending short natural runs to minRun elements, and merging runs + * to maintain stack invariant. + */ + TimSort<T> ts = new TimSort<T>(a, c); + int minRun = minRunLength(nRemaining); + do { + // Identify next run + int runLen = countRunAndMakeAscending(a, lo, hi, c); + + // If run is short, extend to min(minRun, nRemaining) + if (runLen < minRun) { + int force = nRemaining <= minRun ? nRemaining : minRun; + binarySort(a, lo, lo + force, lo + runLen, c); + runLen = force; + } + + // Push run onto pending-run stack, and maybe merge + ts.pushRun(lo, runLen); + ts.mergeCollapse(); + + // Advance to find next run + lo += runLen; + nRemaining -= runLen; + } while (nRemaining != 0); + + // Merge all remaining runs to complete sort + if (DEBUG) assert lo == hi; + ts.mergeForceCollapse(); + if (DEBUG) assert ts.stackSize == 1; + } + + /** + * Sorts the specified portion of the specified array using a binary + * insertion sort. This is the best method for sorting small numbers + * of elements. It requires O(n log n) compares, but O(n^2) data + * movement (worst case). + * + * If the initial part of the specified range is already sorted, + * this method can take advantage of it: the method assumes that the + * elements from index {@code lo}, inclusive, to {@code start}, + * exclusive are already sorted. + * + * @param a the array in which a range is to be sorted + * @param lo the index of the first element in the range to be sorted + * @param hi the index after the last element in the range to be sorted + * @param start the index of the first element in the range that is + * not already known to be sorted (@code lo <= start <= hi} + * @param c comparator to used for the sort + */ + @SuppressWarnings("fallthrough") + private static <T> void binarySort(T[] a, int lo, int hi, int start, + Comparator<? super T> c) { + if (DEBUG) assert lo <= start && start <= hi; + if (start == lo) + start++; + for ( ; start < hi; start++) { + T pivot = a[start]; + + // Set left (and right) to the index where a[start] (pivot) belongs + int left = lo; + int right = start; + if (DEBUG) assert left <= right; + /* + * Invariants: + * pivot >= all in [lo, left). + * pivot < all in [right, start). + */ + while (left < right) { + int mid = (left + right) >>> 1; + if (c.compare(pivot, a[mid]) < 0) + right = mid; + else + left = mid + 1; + } + if (DEBUG) assert left == right; + + /* + * The invariants still hold: pivot >= all in [lo, left) and + * pivot < all in [left, start), so pivot belongs at left. Note + * that if there are elements equal to pivot, left points to the + * first slot after them -- that's why this sort is stable. + * Slide elements over to make room to make room for pivot. + */ + int n = start - left; // The number of elements to move + // Switch is just an optimization for arraycopy in default case + switch(n) { + case 2: a[left + 2] = a[left + 1]; + case 1: a[left + 1] = a[left]; + break; + default: System.arraycopy(a, left, a, left + 1, n); + } + a[left] = pivot; + } + } + + /** + * Returns the length of the run beginning at the specified position in + * the specified array and reverses the run if it is descending (ensuring + * that the run will always be ascending when the method returns). + * + * A run is the longest ascending sequence with: + * + * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... + * + * or the longest descending sequence with: + * + * a[lo] > a[lo + 1] > a[lo + 2] > ... + * + * For its intended use in a stable mergesort, the strictness of the + * definition of "descending" is needed so that the call can safely + * reverse a descending sequence without violating stability. + * + * @param a the array in which a run is to be counted and possibly reversed + * @param lo index of the first element in the run + * @param hi index after the last element that may be contained in the run. + It is required that @code{lo < hi}. + * @param c the comparator to used for the sort + * @return the length of the run beginning at the specified position in + * the specified array + */ + private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi, + Comparator<? super T> c) { + if (DEBUG) assert lo < hi; + int runHi = lo + 1; + if (runHi == hi) + return 1; + + // Find end of run, and reverse range if descending + if (c.compare(a[runHi++], a[lo]) < 0) { // Descending + while(runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0) + runHi++; + reverseRange(a, lo, runHi); + } else { // Ascending + while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0) + runHi++; + } + + return runHi - lo; + } + + /** + * Reverse the specified range of the specified array. + * + * @param a the array in which a range is to be reversed + * @param lo the index of the first element in the range to be reversed + * @param hi the index after the last element in the range to be reversed + */ + private static void reverseRange(Object[] a, int lo, int hi) { + hi--; + while (lo < hi) { + Object t = a[lo]; + a[lo++] = a[hi]; + a[hi--] = t; + } + } + + /** + * Returns the minimum acceptable run length for an array of the specified + * length. Natural runs shorter than this will be extended with + * {@link #binarySort}. + * + * Roughly speaking, the computation is: + * + * If n < MIN_MERGE, return n (it's too small to bother with fancy stuff). + * Else if n is an exact power of 2, return MIN_MERGE/2. + * Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k + * is close to, but strictly less than, an exact power of 2. + * + * For the rationale, see listsort.txt. + * + * @param n the length of the array to be sorted + * @return the length of the minimum run to be merged + */ + private static int minRunLength(int n) { + if (DEBUG) assert n >= 0; + int r = 0; // Becomes 1 if any 1 bits are shifted off + while (n >= MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + return n + r; + } + + /** + * Pushes the specified run onto the pending-run stack. + * + * @param runBase index of the first element in the run + * @param runLen the number of elements in the run + */ + private void pushRun(int runBase, int runLen) { + this.runBase[stackSize] = runBase; + this.runLen[stackSize] = runLen; + stackSize++; + } + + /** + * Examines the stack of runs waiting to be merged and merges adjacent runs + * until the stack invariants are reestablished: + * + * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] + * 2. runLen[i - 2] > runLen[i - 1] + * + * This method is called each time a new run is pushed onto the stack, + * so the invariants are guaranteed to hold for i < stackSize upon + * entry to the method. + */ + private void mergeCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) { + if (runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } else if (runLen[n] <= runLen[n + 1]) { + mergeAt(n); + } else { + break; // Invariant is established + } + } + } + + /** + * Merges all runs on the stack until only one remains. This method is + * called once, to complete the sort. + */ + private void mergeForceCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } + } + + /** + * Merges the two runs at stack indices i and i+1. Run i must be + * the penultimate or antepenultimate run on the stack. In other words, + * i must be equal to stackSize-2 or stackSize-3. + * + * @param i stack index of the first of the two runs to merge + */ + private void mergeAt(int i) { + if (DEBUG) assert stackSize >= 2; + if (DEBUG) assert i >= 0; + if (DEBUG) assert i == stackSize - 2 || i == stackSize - 3; + + int base1 = runBase[i]; + int len1 = runLen[i]; + int base2 = runBase[i + 1]; + int len2 = runLen[i + 1]; + if (DEBUG) assert len1 > 0 && len2 > 0; + if (DEBUG) assert base1 + len1 == base2; + + /* + * Record the length of the combined runs; if i is the 3rd-last + * run now, also slide over the last run (which isn't involved + * in this merge). The current run (i+1) goes away in any case. + */ + runLen[i] = len1 + len2; + if (i == stackSize - 3) { + runBase[i + 1] = runBase[i + 2]; + runLen[i + 1] = runLen[i + 2]; + } + stackSize--; + + /* + * Find where the first element of run2 goes in run1. Prior elements + * in run1 can be ignored (because they're already in place). + */ + int k = gallopRight(a[base2], a, base1, len1, 0, c); + if (DEBUG) assert k >= 0; + base1 += k; + len1 -= k; + if (len1 == 0) + return; + + /* + * Find where the last element of run1 goes in run2. Subsequent elements + * in run2 can be ignored (because they're already in place). + */ + len2 = gallopLeft(a[base1 + len1 - 1], a, base2, len2, len2 - 1, c); + if (DEBUG) assert len2 >= 0; + if (len2 == 0) + return; + + // Merge remaining runs, using tmp array with min(len1, len2) elements + if (len1 <= len2) + mergeLo(base1, len1, base2, len2); + else + mergeHi(base1, len1, base2, len2); + } + + /** + * Locates the position at which to insert the specified key into the + * specified sorted range; if the range contains an element equal to key, + * returns the index of the leftmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @param c the comparator used to order the range, and to search + * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], + * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. + * In other words, key belongs at index b + k; or in other words, + * the first k elements of a should precede key, and the last n - k + * should follow it. + */ + private static <T> int gallopLeft(T key, T[] a, int base, int len, int hint, + Comparator<? super T> c) { + if (DEBUG) assert len > 0 && hint >= 0 && hint < len; + int lastOfs = 0; + int ofs = 1; + if (c.compare(key, a[base + hint]) > 0) { + // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) > 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + lastOfs += hint; + ofs += hint; + } else { // key <= a[base + hint] + // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] + final int maxOfs = hint + 1; + while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) <= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + if (DEBUG) assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere + * to the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (c.compare(key, a[base + m]) > 0) + lastOfs = m + 1; // a[base + m] < key + else + ofs = m; // key <= a[base + m] + } + if (DEBUG) assert lastOfs == ofs; // so a[base + ofs - 1] < key <= a[base + ofs] + return ofs; + } + + /** + * Like gallopLeft, except that if the range contains an element equal to + * key, gallopRight returns the index after the rightmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @param c the comparator used to order the range, and to search + * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] + */ + private static <T> int gallopRight(T key, T[] a, int base, int len, + int hint, Comparator<? super T> c) { + if (DEBUG) assert len > 0 && hint >= 0 && hint < len; + + int ofs = 1; + int lastOfs = 0; + if (c.compare(key, a[base + hint]) < 0) { + // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] + int maxOfs = hint + 1; + while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) < 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } else { // a[b + hint] <= key + // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) >= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + lastOfs += hint; + ofs += hint; + } + if (DEBUG) assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to + * the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (c.compare(key, a[base + m]) < 0) + ofs = m; // key < a[b + m] + else + lastOfs = m + 1; // a[b + m] <= key + } + if (DEBUG) assert lastOfs == ofs; // so a[b + ofs - 1] <= key < a[b + ofs] + return ofs; + } + + /** + * Merges two adjacent runs in place, in a stable fashion. The first + * element of the first run must be greater than the first element of the + * second run (a[base1] > a[base2]), and the last element of the first run + * (a[base1 + len1-1]) must be greater than all elements of the second run. + * + * For performance, this method should be called only when len1 <= len2; + * its twin, mergeHi should be called if len1 >= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + private void mergeLo(int base1, int len1, int base2, int len2) { + if (DEBUG) assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy first run into temp array + T[] a = this.a; // For performance + T[] tmp = ensureCapacity(len1); + System.arraycopy(a, base1, tmp, 0, len1); + + int cursor1 = 0; // Indexes into tmp array + int cursor2 = base2; // Indexes int a + int dest = base1; // Indexes int a + + // Move first element of second run and deal with degenerate cases + a[dest++] = a[cursor2++]; + if (--len2 == 0) { + System.arraycopy(tmp, cursor1, a, dest, len1); + return; + } + if (len1 == 1) { + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + return; + } + + Comparator<? super T> c = this.c; // Use local variable for performance + int minGallop = this.minGallop; // " " " " " + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run starts + * winning consistently. + */ + do { + if (DEBUG) assert len1 > 1 && len2 > 0; + if (c.compare(a[cursor2], tmp[cursor1]) < 0) { + a[dest++] = a[cursor2++]; + count2++; + count1 = 0; + if (--len2 == 0) + break outer; + } else { + a[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--len1 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + if (DEBUG) assert len1 > 1 && len2 > 0; + count1 = gallopRight(a[cursor2], tmp, cursor1, len1, 0, c); + if (count1 != 0) { + System.arraycopy(tmp, cursor1, a, dest, count1); + dest += count1; + cursor1 += count1; + len1 -= count1; + if (len1 == 1) + break outer; + } + a[dest++] = a[cursor2++]; + if (--len2 == 0) + break outer; + + count2 = gallopLeft(tmp[cursor1], a, cursor2, len2, 0, c); + if (count2 != 0) { + System.arraycopy(a, cursor2, a, dest, count2); + dest += count2; + cursor2 += count2; + len2 -= count2; + if (len2 == 0) + break outer; + } + a[dest++] = tmp[cursor1++]; + if (--len1 == 1) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len1 == 1) { + if (DEBUG) assert len2 > 0; + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + } else { + if (DEBUG) assert len2 == 0; + if (DEBUG) assert len1 > 1; + System.arraycopy(tmp, cursor1, a, dest, len1); + } + } + + /** + * Like mergeLo, except that this method should be called only if + * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + private void mergeHi(int base1, int len1, int base2, int len2) { + if (DEBUG) assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy second run into temp array + T[] a = this.a; // For performance + T[] tmp = ensureCapacity(len2); + System.arraycopy(a, base2, tmp, 0, len2); + + int cursor1 = base1 + len1 - 1; // Indexes into a + int cursor2 = len2 - 1; // Indexes into tmp array + int dest = base2 + len2 - 1; // Indexes into a + + // Move last element of first run and deal with degenerate cases + a[dest--] = a[cursor1--]; + if (--len1 == 0) { + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + return; + } + if (len2 == 1) { + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; + return; + } + + Comparator<? super T> c = this.c; // Use local variable for performance + int minGallop = this.minGallop; // " " " " " + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run + * appears to win consistently. + */ + do { + if (DEBUG) assert len1 > 0 && len2 > 1; + if (c.compare(tmp[cursor2], a[cursor1]) < 0) { + a[dest--] = a[cursor1--]; + count1++; + count2 = 0; + if (--len1 == 0) + break outer; + } else { + a[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--len2 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + if (DEBUG) assert len1 > 0 && len2 > 1; + count1 = len1 - gallopRight(tmp[cursor2], a, base1, len1, len1 - 1, c); + if (count1 != 0) { + dest -= count1; + cursor1 -= count1; + len1 -= count1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, count1); + if (len1 == 0) + break outer; + } + a[dest--] = tmp[cursor2--]; + if (--len2 == 1) + break outer; + + count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c); + if (count2 != 0) { + dest -= count2; + cursor2 -= count2; + len2 -= count2; + System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2); + if (len2 == 1) + break outer; + } + a[dest--] = a[cursor1--]; + if (--len1 == 0) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len2 == 1) { + if (DEBUG) assert len1 > 0; + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; // Move first elt of run2 to front of merge + } else { + if (DEBUG) assert len1 == 0; + if (DEBUG) assert len2 > 0; + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + } + } + + /** + * Ensures that the external array tmp has at least the specified + * number of elements, increasing its size if necessary. The size + * increases exponentially to ensure amortized linear time complexity. + * + * @param minCapacity the minimum required capacity of the tmp array + * @return tmp, whether or not it grew + */ + private T[] ensureCapacity(int minCapacity) { + if (tmp.length < minCapacity) { + // Compute smallest power of 2 > minCapacity + int newSize = minCapacity; + newSize |= newSize >> 1; + newSize |= newSize >> 2; + newSize |= newSize >> 4; + newSize |= newSize >> 8; + newSize |= newSize >> 16; + newSize++; + + if (newSize < 0) // Not bloody likely! + newSize = minCapacity; + else + newSize = Math.min(newSize, a.length >>> 1); + + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + T[] newArray = (T[]) new Object[newSize]; + tmp = newArray; + } + return tmp; + } + + /** + * Checks that fromIndex and toIndex are in range, and throws an + * appropriate exception if they aren't. + * + * @param arrayLen the length of the array + * @param fromIndex the index of the first element of the range + * @param toIndex the index after the last element of the range + * @throws IllegalArgumentException if fromIndex > toIndex + * @throws ArrayIndexOutOfBoundsException if fromIndex < 0 + * or toIndex > arrayLen + */ + private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) { + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex+")"); + if (fromIndex < 0) + throw new ArrayIndexOutOfBoundsException(fromIndex); + if (toIndex > arrayLen) + throw new ArrayIndexOutOfBoundsException(toIndex); + } +} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java index 2718199..1f7589d 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java @@ -150,8 +150,6 @@ public class Header implements Cloneable { * Lists of Strings. * * @return an unmodifiable map of the headers - * - * @since 1.4 */ public Map<String, List<String>> getFieldMap() { Map<String, List<String>> result = new HashMap<String, List<String>>( diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java index 76432e6..6f5a2be 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java @@ -141,23 +141,41 @@ public class HttpURLConnection extends java.net.HttpURLConnection { throwClosed(); } - return is.read(); + int result = is.read(); + if (useCaches && cacheOut != null) { + cacheOut.write(result); + } + return result; } public int read(byte[] b, int off, int len) throws IOException { if (closed) { throwClosed(); } - - return is.read(b, off, len); + int result = is.read(b, off, len); + if (result > 0) { + // if user has set useCache to true and cache exists, writes to + // it + if (useCaches && cacheOut != null) { + cacheOut.write(b, off, result); + } + } + return result; } public int read(byte[] b) throws IOException { if (closed) { throwClosed(); } - - return is.read(b); + int result = is.read(b); + if (result > 0) { + // if user has set useCache to true and cache exists, writes to + // it + if (useCaches && cacheOut != null) { + cacheOut.write(b, 0, result); + } + } + return result; } public long skip(long n) throws IOException { @@ -178,6 +196,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { public void close() { closed = true; + if (useCaches && cacheRequest != null) { + cacheRequest.abort(); + } } public void mark(int readLimit) { @@ -1000,8 +1021,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * header field values associated with that key name. * * @return the mapping of header field names to values - * - * @since 1.4 */ @Override public Map<String, List<String>> getHeaderFields() { diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java b/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java index b062aee..8c8257b 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java @@ -144,7 +144,10 @@ public class Inet6Util { } - static String hexCharacters = "0123456789ABCDEF"; + // BEGIN android-changed + static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + // END android-changed public static String createIPAddrStringFromByteArray(byte ipByteArray[]) { if (ipByteArray.length == 4) { @@ -160,15 +163,31 @@ public class Inet6Util { return addressToString(bytesToInt(ipv4ByteArray, 0)); } StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < ipByteArray.length; i++) { - int j = (ipByteArray[i] & 0xf0) >>> 4; - buffer.append(hexCharacters.charAt(j)); - j = ipByteArray[i] & 0x0f; - buffer.append(hexCharacters.charAt(j)); - if (i % 2 != 0 && (i + 1) < ipByteArray.length) { + // BEGIN android-changed + for (int i = 0; i < 8; i++) { // ipByteArray.length / 2 + + int num = (ipByteArray[2 * i] & 0xff) << 8; + num ^= ipByteArray[2 * i + 1] & 0xff; + + // count the digits to display without leading 0 + int count = 1, j = num; + while ((j >>>= 4) != 0) { + count++; + } + + char[] buf = new char[count]; + do { + int t = num & 0x0f; + buf[--count] = hexCharacters[t]; + num >>>= 4; + } while (count > 0); + + buffer.append(buf); + if ((i + 1) < 8) { // ipByteArray.length / 2 buffer.append(":"); } } + // END android-changed return buffer.toString(); } return null; @@ -293,6 +312,21 @@ public class Inet6Util { + ((value >> 8) & 0xff) + "." + (value & 0xff); } + // BEGIN android-added + // copied from a newer version of harmony + public static boolean isIP6AddressInFullForm(String ipAddress) { + if (isValidIP6Address(ipAddress)) { + int doubleColonIndex = ipAddress.indexOf("::"); + if (doubleColonIndex >= 0) { + // Simplified form which contains :: + return false; + } + return true; + } + return false; + } + // END android-added + public static boolean isValidIP6Address(String ipAddress) { int length = ipAddress.length(); boolean doubleColon = false; @@ -501,4 +535,5 @@ public class Inet6Util { } // END android-changed } + } diff --git a/luni/src/main/native/java_net_InetAddress.cpp b/luni/src/main/native/java_net_InetAddress.cpp index a7693cd..84c9751 100644 --- a/luni/src/main/native/java_net_InetAddress.cpp +++ b/luni/src/main/native/java_net_InetAddress.cpp @@ -33,6 +33,8 @@ #include <sys/socket.h> +static jclass byteArrayClass = NULL; + static jstring InetAddress_gethostname(JNIEnv* env, jobject obj) { char name[256]; @@ -57,10 +59,24 @@ static void throwNullPointerException(JNIEnv* env) } } -static jbyteArray getHostByNameAdb(JNIEnv* env, const char* name) +static void logIpString(struct addrinfo* ai, const char* name) +{ + char ipString[INET6_ADDRSTRLEN]; + int result = getnameinfo(ai->ai_addr, ai->ai_addrlen, ipString, + sizeof(ipString), NULL, 0, NI_NUMERICHOST); + if (result == 0) { + LOGD("%s: %s (family %d, proto %d)", name, ipString, ai->ai_family, + ai->ai_protocol); + } else { + LOGE("%s: getnameinfo: %s", name, gai_strerror(result)); + } +} + +static jobjectArray getAllByNameUsingAdb(JNIEnv* env, const char* name) { struct in_addr outaddr; - jbyteArray out = NULL; + jobjectArray addressArray = NULL; + jbyteArray byteArray; #if 0 LOGI("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u", @@ -70,156 +86,210 @@ static jbyteArray getHostByNameAdb(JNIEnv* env, const char* name) #endif if (adb_networking_gethostbyname(name, &outaddr) >= 0) { - out = env->NewByteArray(4); - env->SetByteArrayRegion(out, 0, 4, (jbyte*) &outaddr.s_addr); + addressArray = env->NewObjectArray(1, byteArrayClass, NULL); + byteArray = env->NewByteArray(4); + if (addressArray && byteArray) { + env->SetByteArrayRegion(byteArray, 0, 4, (jbyte*) &outaddr.s_addr); + env->SetObjectArrayElement(addressArray, 1, byteArray); + } } - - return out; + return addressArray; } -static jbyteArray getHostByNameGetAddrInfo(JNIEnv* env, const char* name, jboolean preferIPv6Address) +static jobjectArray getAllByNameUsingDns(JNIEnv* env, const char* name, + jboolean preferIPv4Stack) { - struct addrinfo hints, *res = NULL; - jbyteArray out = NULL; + struct addrinfo hints, *addressList = NULL, *addrInfo; + jobjectArray addressArray = NULL; memset(&hints, 0, sizeof(hints)); - hints.ai_family = preferIPv6Address ? AF_UNSPEC : AF_INET; - - int ret = getaddrinfo(name, NULL, &hints, &res); - if (ret == 0 && res) { - struct sockaddr* saddr = res[0].ai_addr; - size_t addrlen = 0; - void* rawaddr; - - switch (res[0].ai_family) { - // Find the raw address length and start pointer. - case AF_INET6: - addrlen = 16; - rawaddr = &((struct sockaddr_in6*) saddr)->sin6_addr.s6_addr; - break; - case AF_INET: - addrlen = 4; - rawaddr = &((struct sockaddr_in*) saddr)->sin_addr.s_addr; - break; - default: - // Do nothing. addrlength = 0, so we will return NULL. - break; + /* + * If we don't specify a socket type, every address will appear twice, once + * for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family + * anyway, just pick one. + */ + hints.ai_family = preferIPv4Stack ? AF_INET : AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + int result = getaddrinfo(name, NULL, &hints, &addressList); + if (result == 0 && addressList) { + // Count results so we know how to size the output array. + int addressCount = 0; + for (addrInfo = addressList; addrInfo; addrInfo = addrInfo->ai_next) { + if (addrInfo->ai_family == AF_INET || + addrInfo->ai_family == AF_INET6) { + addressCount++; + } } - if (addrlen) { - out = env->NewByteArray(addrlen); - env->SetByteArrayRegion(out, 0, addrlen, (jbyte*) rawaddr); + // Prepare output array. + addressArray = env->NewObjectArray(addressCount, byteArrayClass, NULL); + if (addressArray == NULL) { + // Appropriate exception will be thrown. + LOGE("getAllByNameUsingDns: could not allocate output array"); + freeaddrinfo(addrInfo); + return NULL; } - } else if (ret == EAI_SYSTEM && errno == EACCES) { + + // Examine returned addresses one by one, save them in the output array. + int index = 0; + for (addrInfo = addressList; addrInfo; addrInfo = addrInfo->ai_next) { + struct sockaddr* address = addrInfo->ai_addr; + size_t addressLength = 0; + void* rawAddress; + + switch (addrInfo->ai_family) { + // Find the raw address length and start pointer. + case AF_INET6: + addressLength = 16; + rawAddress = + &((struct sockaddr_in6*) address)->sin6_addr.s6_addr; + logIpString(addrInfo, name); + break; + case AF_INET: + addressLength = 4; + rawAddress = + &((struct sockaddr_in*) address)->sin_addr.s_addr; + logIpString(addrInfo, name); + break; + default: + // Unknown address family. Skip this address. + LOGE("getAllByNameUsingDns: Unknown address family %d", + addrInfo->ai_family); + continue; + } + + // Convert each IP address into a Java byte array. + jbyteArray bytearray = env->NewByteArray(addressLength); + if (bytearray == NULL) { + // Out of memory error will be thrown on return. + LOGE("getAllByNameUsingDns: Can't allocate %d-byte array", + addressLength); + addressArray = NULL; + break; + } + env->SetByteArrayRegion(bytearray, 0, addressLength, + (jbyte*) rawAddress); + env->SetObjectArrayElement(addressArray, index, bytearray); + env->DeleteLocalRef(bytearray); + index++; + } + } else if (result == EAI_SYSTEM && errno == EACCES) { /* No permission to use network */ jniThrowException( - env, "java/lang/SecurityException", - "Permission denied (maybe missing INTERNET permission)"); + env, "java/lang/SecurityException", + "Permission denied (maybe missing INTERNET permission)"); + } else { + // Do nothing. Return value will be null and the caller will throw an + // UnknownHostExeption. } - if (res) { - freeaddrinfo(res); + if (addressList) { + freeaddrinfo(addressList); } - return out; + return addressArray; } -jbyteArray InetAddress_gethostbyname(JNIEnv* env, jobject obj, jstring nameStr, jboolean preferIPv6Address) +jobjectArray InetAddress_getallbyname(JNIEnv* env, jobject obj, + jstring javaName, + jboolean preferIPv4Stack) { - if (nameStr == NULL) { + if (javaName == NULL) { throwNullPointerException(env); - return 0; + return NULL; } - const char* name = env->GetStringUTFChars(nameStr, NULL); - jbyteArray out = NULL; + const char* name = env->GetStringUTFChars(javaName, NULL); + jobjectArray out = NULL; char useAdbNetworkingProperty[PROPERTY_VALUE_MAX]; char adbConnected[PROPERTY_VALUE_MAX]; - property_get ("android.net.use-adb-networking", + property_get("android.net.use-adb-networking", useAdbNetworkingProperty, ""); - property_get ("adb.connected", + property_get("adb.connected", adbConnected, ""); // Any non-empty string value for use-adb-networking is considered "set" if ((strlen(useAdbNetworkingProperty) > 0) && (strlen(adbConnected) > 0) ) { - out = getHostByNameAdb(env, name); + out = getAllByNameUsingAdb(env, name); } else { - out = getHostByNameGetAddrInfo(env, name, preferIPv6Address); + out = getAllByNameUsingDns(env, name, preferIPv4Stack); } if (!out) { LOGI("Unknown host %s, throwing UnknownHostException", name); jniThrowException(env, "java/net/UnknownHostException", name); } - env->ReleaseStringUTFChars(nameStr, name); + env->ReleaseStringUTFChars(javaName, name); return out; } -static jstring InetAddress_gethostbyaddr(JNIEnv* env, jobject obj, jstring addrStr) +static jstring InetAddress_gethostbyaddr(JNIEnv* env, jobject obj, + jbyteArray javaAddress) { - if (addrStr == NULL) { + if (javaAddress == NULL) { throwNullPointerException(env); - return false; - } - - jstring result; - const char* addr = env->GetStringUTFChars(addrStr, NULL); - - struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET); - - if (ent != NULL && ent->h_name != NULL) { - result = env->NewStringUTF(ent->h_name); - } else { - result = NULL; + return NULL; } - env->ReleaseStringUTFChars(addrStr, addr); - - return result; -} - - -static jobjectArray InetAddress_getaliasesbyname(JNIEnv* env, jobject obj, jstring nameStr) -{ - if (nameStr == NULL) { + size_t addrlen = env->GetArrayLength(javaAddress); + jbyte* rawAddress = env->GetByteArrayElements(javaAddress, NULL); + if (rawAddress == NULL) { throwNullPointerException(env); return NULL; } - jclass clazz = env->FindClass("java/lang/String"); - if (clazz == NULL) { - jniThrowException(env, "java/lang/ClassNotFoundException", "couldn't find class java.lang.String"); - return NULL; + // Convert the raw address bytes into a socket address structure. + struct sockaddr_storage ss; + struct sockaddr_in *sin = (struct sockaddr_in *) &ss; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss; + size_t socklen; + switch (addrlen) { + case 4: + socklen = sizeof(struct sockaddr_in); + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr.s_addr, rawAddress, 4); + break; + case 16: + socklen = sizeof(struct sockaddr_in6); + memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr.s6_addr, rawAddress, 4); + break; + default: + jniThrowException(env, "java/net/UnknownHostException", + "Invalid address length"); + return NULL; } - jobjectArray result; - const char* name = env->GetStringUTFChars(nameStr, NULL); + // Convert the socket address structure to an IP string for logging. + int ret; + char ipstr[INET6_ADDRSTRLEN]; + ret = getnameinfo((struct sockaddr *) &ss, socklen, ipstr, sizeof(ipstr), + NULL, 0, NI_NUMERICHOST); + if (ret) { + LOGE("gethostbyaddr: getnameinfo: %s", gai_strerror(ret)); + return NULL; + } - struct hostent* ent = gethostbyname(name); - - if (ent != NULL) { - // Count aliases - int count = 0; - while (ent->h_aliases[count] != NULL) { - count++; - } - - // Create an array of String objects and fill it. - result = env->NewObjectArray(count, clazz, NULL); - int i; - for (i = 0; i < count; i++) { - env->SetObjectArrayElement(result, i, env->NewStringUTF(ent->h_aliases[i])); - } + // Look up the IP address from the socket address structure. + jstring result = NULL; + char name[NI_MAXHOST]; + ret = getnameinfo((struct sockaddr *) &ss, socklen, name, sizeof(name), + NULL, 0, 0); + if (ret == 0) { + LOGI("gethostbyaddr: getnameinfo: %s = %s", ipstr, name); + result = env->NewStringUTF(name); } else { - result = env->NewObjectArray(0, clazz, NULL); + LOGE("gethostbyaddr: getnameinfo: unknown host %s: %s", ipstr, + gai_strerror(ret)); } - env->ReleaseStringUTFChars(nameStr, name); - return result; } @@ -228,18 +298,24 @@ static jobjectArray InetAddress_getaliasesbyname(JNIEnv* env, jobject obj, jstri */ static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ - { "getaliasesbyname", "(Ljava/lang/String;)[Ljava/lang/String;", - (void*) InetAddress_getaliasesbyname }, - { "gethostbyaddr", "(Ljava/lang/String;)Ljava/lang/String;", + { "gethostbyaddr", "([B)Ljava/lang/String;", (void*) InetAddress_gethostbyaddr }, - { "gethostbyname", "(Ljava/lang/String;Z)[B", - (void*) InetAddress_gethostbyname }, + { "getallbyname", "(Ljava/lang/String;Z)[[B", + (void*) InetAddress_getallbyname }, { "gethostname", "()Ljava/lang/String;", - (void*) InetAddress_gethostname } + (void*) InetAddress_gethostname }, }; extern "C" int register_java_net_InetAddress(JNIEnv* env) { + jclass tempClass = env->FindClass("[B"); + if (tempClass) { + byteArrayClass = (jclass) env->NewGlobalRef(tempClass); + } + if (!byteArrayClass) { + LOGE("register_java_net_InetAddress: cannot allocate byte array class"); + return -1; + } return jniRegisterNativeMethods(env, "java/net/InetAddress", gMethods, NELEM(gMethods)); } diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/AllTests.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/AllTests.java index a81be7e..b4f3e5f 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/AllTests.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/AllTests.java @@ -93,7 +93,6 @@ public class AllTests { suite.addTestSuite(RuntimePermissionTest.class); suite.addTestSuite(RuntimeTest.class); suite.addTestSuite(SecurityExceptionTest.class); - suite.addTestSuite(SecurityManager2Test.class); suite.addTestSuite(SecurityManagerTest.class); suite.addTestSuite(ShortTest.class); suite.addTestSuite(StackOverflowErrorTest.class); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/CharacterImplTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/CharacterImplTest.java index 1ba3f2e..93e3abb 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/CharacterImplTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/CharacterImplTest.java @@ -16,6 +16,7 @@ package org.apache.harmony.luni.tests.java.lang; +import dalvik.annotation.AndroidOnly; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -32,6 +33,7 @@ public class CharacterImplTest extends TestCase { method = "valueOf", args = {char.class} ) + @AndroidOnly("valueOf doesn't return the same values on RI.") public void test_valueOfC() { // test the cache range for (char c = '\u0000'; c < 512; c++) { @@ -40,7 +42,7 @@ public class CharacterImplTest extends TestCase { assertEquals(e, a); // WARN: this assertion may not be valid on other JREs - assertEquals(Character.valueOf(c), Character.valueOf(c)); + assertSame(Character.valueOf(c), Character.valueOf(c)); } // test the rest of the chars for (int c = '\u0512'; c <= Character.MAX_VALUE; c++) { diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java index 0f3ea2d..fd68f66 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java @@ -18,6 +18,7 @@ package org.apache.harmony.luni.tests.java.lang; import dalvik.annotation.AndroidOnly; +import dalvik.annotation.BrokenTest; import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; @@ -123,7 +124,9 @@ public class ClassLoaderTest extends TestCase { method = "clearAssertionStatus", args = {} ) - @KnownFailure("clearAssertionStatus method is not supported.") + @AndroidOnly("clearAssertionStatus method is not supported.") + @BrokenTest("Android doesn't support assertions to be activated through " + + "the api") public void test_clearAssertionStatus() { String className = getClass().getPackage().getName() + ".TestAssertions"; String className1 = getClass().getPackage().getName() + ".TestAssertions1"; @@ -399,8 +402,8 @@ public class ClassLoaderTest extends TestCase { method = "loadClass", args = {java.lang.String.class} ) - @KnownFailure("Both threads try to define class; " + - "findClass method is not supported.") + @BrokenTest("Both threads try to define class. But defineClass is not " + + "supported on Adnroid. so both seem to succeed defining the class.") public void test_loadClass_concurrentLoad() throws Exception { Object lock = new Object(); @@ -552,6 +555,8 @@ public class ClassLoaderTest extends TestCase { fail("IOException getting stream for resource : " + e.getMessage()); } + + assertNull(ClassLoader.getSystemClassLoader(). getResource("not.found.resource")); } @@ -602,7 +607,7 @@ public class ClassLoaderTest extends TestCase { * @tests java.lang.ClassLoader#getSystemClassLoader() */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.SUFFICIENT, notes = "", method = "getSystemClassLoader", args = {} @@ -611,6 +616,7 @@ public class ClassLoaderTest extends TestCase { // Test for method java.lang.ClassLoader // java.lang.ClassLoader.getSystemClassLoader() ClassLoader cl = ClassLoader.getSystemClassLoader(); + java.io.InputStream is = cl.getResourceAsStream("hyts_Foo.c"); assertNotNull("Failed to find resource from system classpath", is); try { @@ -618,6 +624,44 @@ public class ClassLoaderTest extends TestCase { } catch (java.io.IOException e) { } + SecurityManager sm = new SecurityManager() { + public void checkPermission(Permission perm) { + if(perm.getName().equals("getClassLoader")) { + throw new SecurityException(); + } + } + }; + + SecurityManager oldManager = System.getSecurityManager(); + System.setSecurityManager(sm); + try { + ClassLoader.getSystemClassLoader(); + } catch(SecurityException se) { + //expected + } finally { + System.setSecurityManager(oldManager); + } +/* + * // java.lang.Error is not thrown on RI, but it's specified. + * + * String keyProp = "java.system.class.loader"; + * String oldProp = System.getProperty(keyProp); + * System.setProperty(keyProp, "java.test.UnknownClassLoader"); + * boolean isFailed = false; + * try { + * ClassLoader.getSystemClassLoader(); + * isFailed = true; + * } catch(java.lang.Error e) { + * //expected + * } finally { + * if(oldProp == null) { + * System.clearProperty(keyProp); + * } else { + * System.setProperty(keyProp, oldProp); + * } + * } + * assertFalse("java.lang.Error was not thrown.", isFailed); + */ } /** @@ -700,7 +744,6 @@ public class ClassLoaderTest extends TestCase { method = "getSystemResources", args = {java.lang.String.class} ) - @KnownFailure("Can't find existent resource.") public void test_getSystemResources() { String textResource = "HelloWorld.txt"; @@ -726,6 +769,7 @@ public class ClassLoaderTest extends TestCase { method = "getPackage", args = {java.lang.String.class} ) + @KnownFailure("PackageClassLoader.getPackage returns null.") public void test_getPackageLjava_lang_String() { PackageClassLoader pcl = new PackageClassLoader(); @@ -761,8 +805,9 @@ public class ClassLoaderTest extends TestCase { method = "getPackages", args = {} ) - @KnownFailure("ClassCastException is thrown during casting Object " + - "to Package.") + @KnownFailure("The package canot be found. Seems like the cache is not" + + "shared between the class loaders. But this test seems to" + + "expect exactly that. this tests works on the RI.") public void test_getPackages() { PackageClassLoader pcl = new PackageClassLoader(); @@ -842,7 +887,6 @@ public class ClassLoaderTest extends TestCase { method = "getResources", args = {java.lang.String.class} ) - @KnownFailure("Can't find existent resource.") public void test_getResourcesLjava_lang_String() { Enumeration<java.net.URL> urls = null; FileInputStream fis = null; @@ -939,6 +983,7 @@ public class ClassLoaderTest extends TestCase { method = "findClass", args = {java.lang.String.class} ) + @AndroidOnly("findClass method throws ClassNotFoundException exception.") public void test_findClass(){ try { @@ -964,6 +1009,7 @@ public class ClassLoaderTest extends TestCase { method = "findLibrary", args = {java.lang.String.class} ) + @AndroidOnly("findLibrary method is not supported, it returns null.") public void test_findLibrary() { PackageClassLoader pcl = new PackageClassLoader(); assertNull(pcl.findLibrary("libjvm.so")); @@ -975,6 +1021,7 @@ public class ClassLoaderTest extends TestCase { method = "findResource", args = {java.lang.String.class} ) + @AndroidOnly("findResource method is not supported, it returns null.") public void test_findResourceLjava_lang_String() { assertNull(new PackageClassLoader().findResource("hyts_Foo.c")); } @@ -985,6 +1032,8 @@ public class ClassLoaderTest extends TestCase { method = "findResources", args = {java.lang.String.class} ) + @AndroidOnly("findResources method is not supported, it returns " + + "empty Enumeration.") public void test_findResourcesLjava_lang_String() throws IOException { assertFalse(new PackageClassLoader().findResources("hyts_Foo.c"). hasMoreElements()); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java index d58a0e9..c33a8e3 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java @@ -47,19 +47,27 @@ import java.util.Vector; import tests.support.resource.Support_Resources; import dalvik.annotation.AndroidOnly; +import dalvik.annotation.BrokenTest; import dalvik.annotation.KnownFailure; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; import dalvik.annotation.TestTargetNew; @SuppressWarnings("deprecation") -@TestTargetClass(Class.class) +@TestTargetClass(Class.class) public class ClassTest extends junit.framework.TestCase { - public static final String FILENAME = + public static final String FILENAME = ClassTest.class.getPackage().getName().replace('.', '/') + "/test#.properties"; - + + final String packageName = getClass().getPackage().getName(); + final String classNameInitError1 = packageName + ".TestClass1"; + final String classNameInitError2 = packageName + ".TestClass1B"; + final String classNameLinkageError = packageName + ".TestClass"; + final String sourceJARfile = "illegalClasses.jar"; + final String illegalClassName = "illegalClass"; + static class StaticMember$Class { class Member2$A { } @@ -103,54 +111,54 @@ public class ClassTest extends junit.framework.TestCase { public static class SubTestClass extends TestClass { } - + interface Intf1 { public int field1 = 1; public int field2 = 1; void test(); } - + interface Intf2 { public int field1 = 1; void test(); } - + interface Intf3 extends Intf1 { public int field1 = 1; } - + interface Intf4 extends Intf1, Intf2 { public int field1 = 1; void test2(int a, Object b); } - + interface Intf5 extends Intf1 { } - + class Cls1 implements Intf2 { public int field1 = 2; public int field2 = 2; public void test() { } } - + class Cls2 extends Cls1 implements Intf1 { public int field1 = 2; @Override public void test() { } } - + class Cls3 implements Intf3, Intf4 { public void test() { } public void test2(int a, Object b) { } } - + static class Cls4 { - - } + + } @TestTargetNew( level = TestLevel.COMPLETE, @@ -162,14 +170,14 @@ public class ClassTest extends junit.framework.TestCase { Annotation [] annotations = PublicTestClass.class.getAnnotations(); assertEquals(1, annotations.length); assertEquals(TestAnnotation.class, annotations[0].annotationType()); - + annotations = ExtendTestClass.class.getAnnotations(); assertEquals(2, annotations.length); - + for(int i = 0; i < annotations.length; i++) { Class<? extends Annotation> type = annotations[i].annotationType(); - assertTrue("Annotation's type " + i + ": " + type, - type.equals(Deprecated.class) || + assertTrue("Annotation's type " + i + ": " + type, + type.equals(Deprecated.class) || type.equals(TestAnnotation.class)); } } @@ -183,9 +191,10 @@ public class ClassTest extends junit.framework.TestCase { method = "forName", args = {java.lang.String.class} ) - @AndroidOnly("harmony specific: test with 'org.apache.harmony.luni.tests.java.lang.TestClass1'") + @AndroidOnly("harmony specific: test with " + + "'org.apache.harmony.luni.tests.java.lang.TestClass1'") public void test_forNameLjava_lang_String() throws Exception { - + assertSame("Class for name failed for java.lang.Object", Object.class, Class.forName("java.lang.Object")); assertSame("Class for name failed for [[Ljava.lang.Object;", @@ -243,25 +252,24 @@ public class ClassTest extends junit.framework.TestCase { fail(); } catch (ClassNotFoundException e) { } - + //regression test for JIRA 2162 try { Class.forName("%"); fail("should throw ClassNotFoundException."); } catch (ClassNotFoundException e) { } - + //Regression Test for HARMONY-3332 String securityProviderClassName; int count = 1; while ((securityProviderClassName = Security .getProperty("security.provider." + count++)) != null) { Class.forName(securityProviderClassName); - } - + } + try { - Class.forName( - "org.apache.harmony.luni.tests.java.lang.TestClass1"); + Class.forName(classNameInitError1); fail("ExceptionInInitializerError or ClassNotFoundException " + "expected."); } catch (java.lang.ExceptionInInitializerError ie) { @@ -280,80 +288,78 @@ public class ClassTest extends junit.framework.TestCase { public void test_forNameLjava_lang_StringLbooleanLClassLoader() throws Exception { ClassLoader pcl = getClass().getClassLoader(); - + Class<?> [] classes = {PublicTestClass.class, ExtendTestClass.class, ExtendTestClass1.class, TestInterface.class, String.class}; - + for(int i = 0; i < classes.length; i++) { Class<?> clazz = Class.forName(classes[i].getName(), true, pcl); assertEquals(classes[i], clazz); - + clazz = Class.forName(classes[i].getName(), false, pcl); assertEquals(classes[i], clazz); } - + for(int i = 0; i < classes.length; i++) { - Class<?> clazz = Class.forName(classes[i].getName(), true, + Class<?> clazz = Class.forName(classes[i].getName(), true, ClassLoader.getSystemClassLoader()); assertEquals(classes[i], clazz); - - clazz = Class.forName(classes[i].getName(), false, + + clazz = Class.forName(classes[i].getName(), false, ClassLoader.getSystemClassLoader()); assertEquals(classes[i], clazz); } - + try { Class.forName(null, true, pcl); fail("NullPointerException is not thrown."); } catch(NullPointerException npe) { //expected } - + try { Class.forName("NotExistClass", true, pcl); fail("ClassNotFoundException is not thrown for non existent class."); } catch(ClassNotFoundException cnfe) { //expected - } - + } + try { Class.forName("String", false, pcl); fail("ClassNotFoundException is not thrown for non existent class."); } catch(ClassNotFoundException cnfe) { //expected - } - + } + try { - Class.forName("org.apache.harmony.luni.tests.java.PublicTestClass", + Class.forName("org.apache.harmony.luni.tests.java.PublicTestClass", false, pcl); fail("ClassNotFoundException is not thrown for non existent class."); } catch(ClassNotFoundException cnfe) { //expected - } + } } - + @TestTargetNew( level = TestLevel.SUFFICIENT, notes = "", method = "forName", args = {java.lang.String.class, boolean.class, java.lang.ClassLoader.class} ) - @KnownFailure("Class.forName does not work with an URLClassLoader; " + - "the VMClassLoader does not support loading classes from a " + - "(jar) byte array.") - public void test_forNameLjava_lang_StringLbooleanLClassLoader_FailsOnAndroid() throws Exception { + @AndroidOnly("Class.forName method throws ClassNotFoundException on " + + "Android.") + public void test_forNameLjava_lang_StringLbooleanLClassLoader_AndroidOnly() throws Exception { // Android doesn't support loading class files from a jar. - File resources = Support_Resources.createTempFolder(); try { - Support_Resources.copyFile(resources, null, "illegalClasses.jar"); - File file = new File(resources.toString() + "/illegalClasses.jar"); - URL url = new URL("file:" + file.getPath()); - ClassLoader loader = new URLClassLoader(new URL[] { url }, + URL url = getClass().getClassLoader().getResource( + packageName.replace(".", "/") + "/" + sourceJARfile); + + ClassLoader loader = new URLClassLoader(new URL[] { url }, getClass().getClassLoader()); try { - Class.forName("TestClass", true, loader); + Class.forName(classNameLinkageError, true, loader); fail("LinkageError or ClassNotFoundException expected."); } catch (java.lang.LinkageError le) { // Expected for the RI. @@ -365,20 +371,18 @@ public class ClassTest extends junit.framework.TestCase { } try { - Class.forName( - "org.apache.harmony.luni.tests.java.lang.TestClass1B", + Class.forName(classNameInitError2, true, getClass().getClassLoader()); fail("ExceptionInInitializerError or ClassNotFoundException " + "should be thrown."); } catch (java.lang.ExceptionInInitializerError ie) { // Expected for the RI. -/* Remove this comment to let the test pass on Android. + // Remove this comment to let the test pass on Android. } catch (java.lang.ClassNotFoundException ce) { // Expected for Android. -*/ } } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -386,15 +390,15 @@ public class ClassTest extends junit.framework.TestCase { args = {java.lang.Class.class} ) public void test_getAnnotation() { - TestAnnotation target = PublicTestClass.class.getAnnotation(TestAnnotation.class); + TestAnnotation target = PublicTestClass.class.getAnnotation(TestAnnotation.class); assertEquals(target.value(), PublicTestClass.class.getName()); - + assertNull(PublicTestClass.class.getAnnotation(Deprecated.class)); - + Deprecated target2 = ExtendTestClass.class.getAnnotation(Deprecated.class); assertNotNull(target2); - } - + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -404,17 +408,17 @@ public class ClassTest extends junit.framework.TestCase { public void test_getDeclaredAnnotations() { Annotation [] annotations = PublicTestClass.class.getDeclaredAnnotations(); assertEquals(1, annotations.length); - + annotations = ExtendTestClass.class.getDeclaredAnnotations(); assertEquals(2, annotations.length); annotations = TestInterface.class.getDeclaredAnnotations(); assertEquals(0, annotations.length); - + annotations = String.class.getDeclaredAnnotations(); - assertEquals(0, annotations.length); - } - + assertEquals(0, annotations.length); + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -424,13 +428,13 @@ public class ClassTest extends junit.framework.TestCase { public void test_getEnclosingClass() { Class clazz = ExtendTestClass.class.getEnclosingClass(); assertNull(clazz); - + assertEquals(getClass(), Cls1.class.getEnclosingClass()); assertEquals(getClass(), Intf1.class.getEnclosingClass()); assertEquals(getClass(), Cls4.class.getEnclosingClass()); - } - - + } + + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -440,18 +444,18 @@ public class ClassTest extends junit.framework.TestCase { public void test_getEnclosingMethod() { Method clazz = ExtendTestClass.class.getEnclosingMethod(); assertNull(clazz); - + PublicTestClass ptc = new PublicTestClass(); try { assertEquals("getEnclosingMethod returns incorrect method.", - PublicTestClass.class.getMethod("getLocalClass", + PublicTestClass.class.getMethod("getLocalClass", (Class []) null), ptc.getLocalClass().getClass().getEnclosingMethod()); } catch(NoSuchMethodException nsme) { fail("NoSuchMethodException was thrown."); } - } - + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -459,13 +463,13 @@ public class ClassTest extends junit.framework.TestCase { args = {} ) public void test_getEnclosingConstructor() { - + PublicTestClass ptc = new PublicTestClass(); - assertEquals("getEnclosingConstructor method returns incorrect class.", - PublicTestClass.class.getConstructors()[0], + assertEquals("getEnclosingConstructor method returns incorrect class.", + PublicTestClass.class.getConstructors()[0], ptc.clazz.getClass().getEnclosingConstructor()); - + assertNull("getEnclosingConstructor should return null for local " + "class declared in method.", ptc.getLocalClass().getClass().getEnclosingConstructor()); @@ -474,8 +478,8 @@ public class ClassTest extends junit.framework.TestCase { "class declared in method.", ExtendTestClass.class.getEnclosingConstructor()); } - - + + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -491,7 +495,7 @@ public class ClassTest extends junit.framework.TestCase { assertEquals(TestEnum.values()[i], constants[i]); } assertEquals(0, TestEmptyEnum.class.getEnumConstants().length); - } + } public enum TestEnum { ONE, TWO, THREE } @@ -507,86 +511,116 @@ public class ClassTest extends junit.framework.TestCase { public void test_getGenericInterfaces() { Type [] types = ExtendTestClass1.class.getGenericInterfaces(); assertEquals(0, types.length); - - Class [] interfaces = {TestInterface.class, Serializable.class, + + Class [] interfaces = {TestInterface.class, Serializable.class, Cloneable.class}; types = PublicTestClass.class.getGenericInterfaces(); assertEquals(interfaces.length, types.length); for(int i = 0; i < types.length; i++) { assertEquals(interfaces[i], types[i]); } - + types = TestInterface.class.getGenericInterfaces(); - assertEquals(0, types.length); - + assertEquals(0, types.length); + types = List.class.getGenericInterfaces(); assertEquals(1, types.length); assertEquals(Collection.class, ((ParameterizedType)types[0]).getRawType()); - + assertEquals(0, int.class.getGenericInterfaces().length); - assertEquals(0, void.class.getGenericInterfaces().length); + assertEquals(0, void.class.getGenericInterfaces().length); } - + @TestTargetNew( level = TestLevel.SUFFICIENT, notes = "GenericSignatureFormatError, TypeNotPresentException, MalformedParameterizedTypeException are not verified.", method = "getGenericSuperclass", args = {} - ) + ) public void test_getGenericSuperclass () { - assertEquals(PublicTestClass.class, + assertEquals(PublicTestClass.class, ExtendTestClass.class.getGenericSuperclass()); - assertEquals(ExtendTestClass.class, - ExtendTestClass1.class.getGenericSuperclass()); + assertEquals(ExtendTestClass.class, + ExtendTestClass1.class.getGenericSuperclass()); assertEquals(Object.class, PublicTestClass.class.getGenericSuperclass()); assertEquals(Object.class, String.class.getGenericSuperclass()); assertEquals(null, TestInterface.class.getGenericSuperclass()); - - ParameterizedType type = (ParameterizedType) Vector.class.getGenericSuperclass(); + + ParameterizedType type = (ParameterizedType) Vector.class.getGenericSuperclass(); assertEquals(AbstractList.class, type.getRawType()); } - + @TestTargetNew( - level = TestLevel.NOT_FEASIBLE, + level = TestLevel.SUFFICIENT, method = "getPackage", args = {} ) - @KnownFailure("Class.getPackage does not work with an URLClassLoader; " + - "the VMClassLoader does not support loading classes from a " + - "(jar) byte array.") + @AndroidOnly("Uses dalvik.system.PathClassLoader.") public void test_getPackage() { - assertEquals(Package.getPackage("org.apache.harmony.luni.tests.java.lang"), - PublicTestClass.class.getPackage()); + Package thisPackage = getClass().getPackage(); + assertEquals("org.apache.harmony.luni.tests.java.lang", + thisPackage.getName()); + + Package stringPackage = String.class.getPackage(); + assertNotNull("java.lang", stringPackage.getName()); + + String hyts_package_name = "hyts_package_dex.jar"; File resources = Support_Resources.createTempFolder(); + Support_Resources.copyFile(resources, "Package", hyts_package_name); + + String resPath = resources.toString(); + if (resPath.charAt(0) == '/' || resPath.charAt(0) == '\\') + resPath = resPath.substring(1); + try { - Support_Resources.copyFile(resources, null, "illegalClasses.jar"); - File file = new File(resources.toString() + "/illegalClasses.jar"); - URL url = new URL("file:" + file.getPath()); - ClassLoader loader = new URLClassLoader(new URL[] { url }, null); - - try { - Class<?> clazz = loader.loadClass("IllegalClass"); - Package pack = clazz.getPackage(); - assertNull(pack); - } catch(ClassNotFoundException cne) { - fail("ClassNotFoundException was thrown for IllegalClass."); - } + + URL resourceURL = new URL("file:/" + resPath + "/Package/" + + hyts_package_name); + + ClassLoader cl = new dalvik.system.PathClassLoader( + resourceURL.getPath(), getClass().getClassLoader()); + + Class clazz = cl.loadClass("C"); + assertNull("getPackage for C.class should return null", + clazz.getPackage()); + + clazz = cl.loadClass("a.b.C"); + Package cPackage = clazz.getPackage(); + assertNotNull("getPackage for a.b.C.class should not return null", + cPackage); + + /* + * URLClassLoader doesn't work on Android for jar files + * + * URL url = getClass().getClassLoader().getResource( + * packageName.replace(".", "/") + "/" + sourceJARfile); + * + * ClassLoader loader = new URLClassLoader(new URL[] { url }, null); + * + * try { + * Class<?> clazz = loader.loadClass(illegalClassName); + * Package pack = clazz.getPackage(); + * assertNull(pack); + * } catch(ClassNotFoundException cne) { + * fail("ClassNotFoundException was thrown for " + illegalClassName); + * } + */ } catch(Exception e) { fail("Unexpected exception was thrown: " + e.toString()); } } - + @TestTargetNew( level = TestLevel.COMPLETE, method = "getProtectionDomain", args = {} - ) - @KnownFailure("There is no protection domain set.") + ) + @BrokenTest("There is no protection domain set in Android.") public void test_getProtectionDomain() { ProtectionDomain pd = PublicTestClass.class.getProtectionDomain(); assertNotNull("Test 1: Protection domain expected to be set.", pd); - + SecurityManager sm = new SecurityManager() { public void checkPermission(Permission perm) { @@ -612,19 +646,19 @@ public class ClassTest extends junit.framework.TestCase { notes = "", method = "getSigners", args = {} - ) + ) public void test_getSigners() { assertNull(void.class.getSigners()); assertNull(PublicTestClass.class.getSigners()); } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "getSimpleName", args = {} - ) + ) public void test_getSimpleName() { assertEquals("PublicTestClass", PublicTestClass.class.getSimpleName()); assertEquals("void", void.class.getSimpleName()); @@ -636,44 +670,44 @@ public class ClassTest extends junit.framework.TestCase { notes = "", method = "getTypeParameters", args = {} - ) + ) public void test_getTypeParameters() { assertEquals(0, PublicTestClass.class.getTypeParameters().length); TypeVariable [] tv = TempTestClass1.class.getTypeParameters(); assertEquals(1, tv.length); assertEquals(Object.class, tv[0].getBounds()[0]); - + TempTestClass2<String> tc = new TempTestClass2<String>(); tv = tc.getClass().getTypeParameters(); assertEquals(1, tv.length); assertEquals(String.class, tv[0].getBounds()[0]); } - - class TempTestClass1<T> { + + class TempTestClass1<T> { } - - class TempTestClass2<S extends String> extends TempTestClass1<S> { + + class TempTestClass2<S extends String> extends TempTestClass1<S> { } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isAnnotation", args = {} - ) + ) public void test_isAnnotation() { assertTrue(Deprecated.class.isAnnotation()); assertTrue(TestAnnotation.class.isAnnotation()); assertFalse(PublicTestClass.class.isAnnotation()); assertFalse(String.class.isAnnotation()); } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isAnnotationPresent", args = {java.lang.Class.class} - ) + ) public void test_isAnnotationPresent() { assertTrue(PublicTestClass.class.isAnnotationPresent(TestAnnotation.class)); assertFalse(ExtendTestClass1.class.isAnnotationPresent(TestAnnotation.class)); @@ -681,51 +715,51 @@ public class ClassTest extends junit.framework.TestCase { assertTrue(ExtendTestClass.class.isAnnotationPresent(TestAnnotation.class)); assertTrue(ExtendTestClass.class.isAnnotationPresent(Deprecated.class)); } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isAnonymousClass", args = {} - ) + ) public void test_isAnonymousClass() { assertFalse(PublicTestClass.class.isAnonymousClass()); assertTrue((new Thread() {}).getClass().isAnonymousClass()); - } - + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isEnum", args = {} - ) + ) public void test_isEnum() { assertFalse(PublicTestClass.class.isEnum()); assertFalse(ExtendTestClass.class.isEnum()); assertTrue(TestEnum.ONE.getClass().isEnum()); assertTrue(TestEnum.class.isEnum()); - } - + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isLocalClass", args = {} - ) + ) public void test_isLocalClass() { assertFalse(ExtendTestClass.class.isLocalClass()); assertFalse(TestInterface.class.isLocalClass()); assertFalse(TestEnum.class.isLocalClass()); class InternalClass {} assertTrue(InternalClass.class.isLocalClass()); - } + } @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isMemberClass", args = {} - ) + ) public void test_isMemberClass() { assertFalse(ExtendTestClass.class.isMemberClass()); assertFalse(TestInterface.class.isMemberClass()); @@ -733,23 +767,23 @@ public class ClassTest extends junit.framework.TestCase { assertTrue(TestEnum.class.isMemberClass()); assertTrue(StaticMember$Class.class.isMemberClass()); } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isSynthetic", args = {} - ) + ) public void test_isSynthetic() { - assertFalse("Returned true for non synthetic class.", + assertFalse("Returned true for non synthetic class.", ExtendTestClass.class.isSynthetic()); - assertFalse("Returned true for non synthetic class.", + assertFalse("Returned true for non synthetic class.", TestInterface.class.isSynthetic()); - assertFalse("Returned true for non synthetic class.", + assertFalse("Returned true for non synthetic class.", String.class.isSynthetic()); - + String className = "org.apache.harmony.luni.tests.java.lang.ClassLoaderTest$1"; - + /* *try { * assertTrue("Returned false for synthetic class.", @@ -759,18 +793,18 @@ public class ClassTest extends junit.framework.TestCase { * fail("Class " + className + " can't be found."); *} */ - - } - + + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "isInstance", args = {java.lang.Object.class} - ) + ) public void test_isInstance() { } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -779,38 +813,37 @@ public class ClassTest extends junit.framework.TestCase { ) public void test_getCanonicalName() { String name = int[].class.getCanonicalName(); - Class [] classArray = { int.class, int[].class, String.class, + Class [] classArray = { int.class, int[].class, String.class, PublicTestClass.class, TestInterface.class, ExtendTestClass.class }; - String [] classNames = {"int", "int[]", "java.lang.String", + String [] classNames = {"int", "int[]", "java.lang.String", "org.apache.harmony.luni.tests.java.lang.PublicTestClass", "org.apache.harmony.luni.tests.java.lang.TestInterface", "org.apache.harmony.luni.tests.java.lang.ExtendTestClass"}; - + for(int i = 0; i < classArray.length; i++) { assertEquals(classNames[i], classArray[i].getCanonicalName()); - } - } - + } + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "getClassLoader", args = {} ) - @KnownFailure("getClassLoader() does not return null for primitive types.") public void test_getClassLoader() { - - assertEquals(ExtendTestClass.class.getClassLoader(), + + assertEquals(ExtendTestClass.class.getClassLoader(), PublicTestClass.class.getClassLoader()); - + assertNull(int.class.getClassLoader()); assertNull(void.class.getClassLoader()); - + SecurityManager sm = new SecurityManager() { public void checkPermission(Permission perm) { - if ((perm instanceof RuntimePermission) && + if ((perm instanceof RuntimePermission) && perm.getName().equals("getClassLoader")) { throw new SecurityException(); } @@ -826,8 +859,8 @@ public class ClassTest extends junit.framework.TestCase { } finally { System.setSecurityManager(oldSm); } - } - + } + /** * @tests java.lang.Class#getClasses() */ @@ -850,7 +883,7 @@ public class ClassTest extends junit.framework.TestCase { method = "getClasses", args = {} ) - @KnownFailure("Class.forName does not work with an URLClassLoader; " + + @BrokenTest("Class.forName does not work with an URLClassLoader; " + "the VMClassLoader does not support loading classes from a " + "(jar) byte array.") public void test_getClasses_subtest0() { @@ -1027,7 +1060,7 @@ public class ClassTest extends junit.framework.TestCase { /* Remove this comment to let the test pass on Android. } catch (java.lang.ClassNotFoundException ce) { // Expected for Android. -*/ +*/ } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; @@ -1069,7 +1102,7 @@ public class ClassTest extends junit.framework.TestCase { throws NoSuchMethodException { Constructor constr = TestClass.class.getConstructor(new Class[0]); assertNotNull(constr); - assertEquals("org.apache.harmony.luni.tests.java.lang.ClassTest$TestClass", + assertEquals("org.apache.harmony.luni.tests.java.lang.ClassTest$TestClass", constr.getName()); try { TestClass.class.getConstructor(Object.class); @@ -1077,11 +1110,11 @@ public class ClassTest extends junit.framework.TestCase { } catch (NoSuchMethodException e) { // Correct - constructor with obj is private } - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getConstructor(new Class[0]); + TestClass.class.getConstructor(new Class[0]); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1102,11 +1135,11 @@ public class ClassTest extends junit.framework.TestCase { public void test_getConstructors() throws Exception { Constructor[] c = TestClass.class.getConstructors(); assertEquals("Incorrect number of constructors returned", 1, c.length); - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getConstructors(); + TestClass.class.getConstructors(); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1125,36 +1158,36 @@ public class ClassTest extends junit.framework.TestCase { args = {} ) public void test_getDeclaredClasses() { - + Class [] declClasses = Object.class.getDeclaredClasses(); assertEquals("Incorrect length of declared classes array is returned " + "for Object.", 0, declClasses.length); - - declClasses = PublicTestClass.class.getDeclaredClasses(); + + declClasses = PublicTestClass.class.getDeclaredClasses(); assertEquals(2, declClasses.length); - + assertEquals(0, int.class.getDeclaredClasses().length); - assertEquals(0, void.class.getDeclaredClasses().length); - - for(int i = 0; i < declClasses.length; i++) { + assertEquals(0, void.class.getDeclaredClasses().length); + + for(int i = 0; i < declClasses.length; i++) { Constructor<?> constr = declClasses[i].getDeclaredConstructors()[0]; constr.setAccessible(true); PublicTestClass publicClazz = new PublicTestClass(); try { Object o = constr.newInstance(publicClazz); - assertTrue("Returned incorrect class: " + o.toString(), + assertTrue("Returned incorrect class: " + o.toString(), o.toString().startsWith("PrivateClass")); } catch(Exception e) { fail("Unexpected exception was thrown: " + e.toString()); } } - - - declClasses = TestInterface.class.getDeclaredClasses(); + + + declClasses = TestInterface.class.getDeclaredClasses(); assertEquals(0, declClasses.length); - + SecurityManager sm = new SecurityManager() { - + final String forbidenPermissionName = "user.dir"; public void checkPermission(Permission perm) { @@ -1162,36 +1195,36 @@ public class ClassTest extends junit.framework.TestCase { throw new SecurityException(); } } - + public void checkMemberAccess(Class<?> clazz, int which) { if(clazz.equals(TestInterface.class)) { throw new SecurityException(); } } - + public void checkPackageAccess(String pkg) { if(pkg.equals(PublicTestClass.class.getPackage())) { throw new SecurityException(); } } - + }; SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestInterface.class.getDeclaredClasses(); + TestInterface.class.getDeclaredClasses(); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected } finally { System.setSecurityManager(oldSm); } - + } - - + + /** * @tests java.lang.Class#getDeclaredConstructor(java.lang.Class[]) */ @@ -1205,18 +1238,18 @@ public class ClassTest extends junit.framework.TestCase { Constructor<TestClass> c = TestClass.class.getDeclaredConstructor(new Class[0]); assertNull("Incorrect constructor returned", c.newInstance().cValue()); c = TestClass.class.getDeclaredConstructor(Object.class); - + try { TestClass.class.getDeclaredConstructor(String.class); fail("NoSuchMethodException should be thrown."); } catch(NoSuchMethodException nsme) { //expected } - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getDeclaredConstructor(Object.class); + TestClass.class.getDeclaredConstructor(Object.class); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1237,11 +1270,11 @@ public class ClassTest extends junit.framework.TestCase { public void test_getDeclaredConstructors() throws Exception { Constructor[] c = TestClass.class.getDeclaredConstructors(); assertEquals("Incorrect number of constructors returned", 2, c.length); - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getDeclaredConstructors(); + TestClass.class.getDeclaredConstructors(); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1259,30 +1292,28 @@ public class ClassTest extends junit.framework.TestCase { method = "getDeclaredField", args = {java.lang.String.class} ) - @KnownFailure("Should throw NullPointerException instead of " + - "NoSuchFieldException.") public void test_getDeclaredFieldLjava_lang_String() throws Exception { Field f = TestClass.class.getDeclaredField("pubField"); assertEquals("Returned incorrect field", 2, f.getInt(new TestClass())); - + try { TestClass.class.getDeclaredField(null); fail("NullPointerException is not thrown."); } catch(NullPointerException npe) { //expected } - + try { TestClass.class.getDeclaredField("NonExistentField"); - fail("NoSuchFieldException is not thrown."); + fail("NoSuchFieldException is not thrown."); } catch(NoSuchFieldException nsfe) { //expected } - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getDeclaredField("pubField"); + TestClass.class.getDeclaredField("pubField"); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1306,11 +1337,11 @@ public class ClassTest extends junit.framework.TestCase { f = SubTestClass.class.getDeclaredFields(); // Declared fields do not include inherited assertEquals("Returned incorrect number of fields", 0, f.length); - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getDeclaredFields(); + TestClass.class.getDeclaredFields(); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1329,32 +1360,30 @@ public class ClassTest extends junit.framework.TestCase { method = "getDeclaredMethod", args = {java.lang.String.class, java.lang.Class[].class} ) - @KnownFailure("Should throw NullPointerException instead of " + - "NoSuchMethodException.") public void test_getDeclaredMethodLjava_lang_String$Ljava_lang_Class() throws Exception { Method m = TestClass.class.getDeclaredMethod("pubMethod", new Class[0]); assertEquals("Returned incorrect method", 2, ((Integer) (m.invoke(new TestClass()))) .intValue()); m = TestClass.class.getDeclaredMethod("privMethod", new Class[0]); - + try { TestClass.class.getDeclaredMethod(null, new Class[0]); fail("NullPointerException is not thrown."); } catch(NullPointerException npe) { //expected } - + try { TestClass.class.getDeclaredMethod("NonExistentMethod", new Class[0]); fail("NoSuchMethodException is not thrown."); } catch(NoSuchMethodException nsme) { //expected } - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getDeclaredMethod("pubMethod", new Class[0]); + TestClass.class.getDeclaredMethod("pubMethod", new Class[0]); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1377,11 +1406,11 @@ public class ClassTest extends junit.framework.TestCase { assertEquals("Returned incorrect number of methods", 3, m.length); m = SubTestClass.class.getDeclaredMethods(); assertEquals("Returned incorrect number of methods", 0, m.length); - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getDeclaredMethods(); + TestClass.class.getDeclaredMethods(); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1413,37 +1442,34 @@ public class ClassTest extends junit.framework.TestCase { method = "getField", args = {java.lang.String.class} ) - @KnownFailure("Should return a Field object that reflects the public " + - "field of the interface represented by this Class object too, " + - "but it throws a NoSuchFieldException.") public void test_getFieldLjava_lang_String() throws Exception { Field f = TestClass.class.getField("pubField"); assertEquals("Returned incorrect field", 2, f.getInt(new TestClass())); - + f = PublicTestClass.class.getField("TEST_FIELD"); - assertEquals("Returned incorrect field", "test field", + assertEquals("Returned incorrect field", "test field", f.get(new PublicTestClass())); - + f = PublicTestClass.class.getField("TEST_INTERFACE_FIELD"); - assertEquals("Returned incorrect field", 0, + assertEquals("Returned incorrect field", 0, f.getInt(new PublicTestClass())); - + try { f = TestClass.class.getField("privField"); fail("Private field access failed to throw exception"); } catch (NoSuchFieldException e) { // Correct } - + try { TestClass.class.getField(null); fail("NullPointerException is thrown."); } catch(NullPointerException npe) { //expected } - + SecurityManager sm = new SecurityManager() { - + final String forbidenPermissionName = "user.dir"; public void checkPermission(Permission perm) { @@ -1451,26 +1477,26 @@ public class ClassTest extends junit.framework.TestCase { throw new SecurityException(); } } - + public void checkMemberAccess(Class<?> clazz, int which) { if(clazz.equals(TestClass.class)) { throw new SecurityException(); } } - + public void checkPackageAccess(String pkg) { if(pkg.equals(TestClass.class.getPackage())) { throw new SecurityException(); } } - + }; SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getField("pubField"); + TestClass.class.getField("pubField"); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1488,21 +1514,19 @@ public class ClassTest extends junit.framework.TestCase { method = "getFields", args = {} ) - @KnownFailure("Fails because public static fields declared in an " + - "interface implemented by the class are not recognized.") - public void test_getFields_FailsOnAndroid() throws Exception { + public void test_getFields2() throws Exception { Field[] f; Field expected = null; - + f = PublicTestClass.class.getFields(); assertEquals("Test 1: Incorrect number of fields;", 2, f.length); - + f = Cls2.class.getFields(); - assertEquals("Test 2: Incorrect number of fields;", 6, f.length); + assertEquals("Test 2: Incorrect number of fields;", 6, f.length); f = Cls3.class.getFields(); - assertEquals("Test 2: Incorrect number of fields;", 5, f.length); - + assertEquals("Test 2: Incorrect number of fields;", 5, f.length); + for (Field field : f) { if (field.toString().equals("public static final int org.apache" + ".harmony.luni.tests.java.lang.ClassTest$Intf3.field1")) { @@ -1513,9 +1537,9 @@ public class ClassTest extends junit.framework.TestCase { if (expected == null) { fail("Test 3: getFields() did not return all fields."); } - assertEquals("Test 4: Incorrect field;", expected, + assertEquals("Test 4: Incorrect field;", expected, Cls3.class.getField("field1")); - + expected = null; for (Field field : f) { if(field.toString().equals("public static final int org.apache" + @@ -1527,7 +1551,7 @@ public class ClassTest extends junit.framework.TestCase { if (expected == null) { fail("Test 5: getFields() did not return all fields."); } - assertEquals("Test 6: Incorrect field;", expected, + assertEquals("Test 6: Incorrect field;", expected, Cls3.class.getField("field2")); } @@ -1546,11 +1570,11 @@ public class ClassTest extends junit.framework.TestCase { f = SubTestClass.class.getFields(); // Check inheritance of pub fields assertEquals("Test 2: Incorrect number of fields;", 2, f.length); - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.getFields(); + TestClass.class.getFields(); fail("Should throw SecurityException"); } catch (SecurityException e) { // expected @@ -1592,20 +1616,20 @@ public class ClassTest extends junit.framework.TestCase { .contains(Cloneable.class) && interfaceList.contains(Serializable.class) && interfaceList.contains(List.class)); - + Class [] interfaces1 = Cls1.class.getInterfaces(); assertEquals(1, interfaces1.length); assertEquals(Intf2.class, interfaces1[0]); - + Class [] interfaces2 = Cls2.class.getInterfaces(); assertEquals(1, interfaces2.length); assertEquals(Intf1.class, interfaces2[0]); - + Class [] interfaces3 = Cls3.class.getInterfaces(); assertEquals(2, interfaces3.length); - assertEquals(Intf3.class, interfaces3[0]); - assertEquals(Intf4.class, interfaces3[1]); - + assertEquals(Intf3.class, interfaces3[0]); + assertEquals(Intf4.class, interfaces3[1]); + Class [] interfaces4 = Cls4.class.getInterfaces(); assertEquals(0, interfaces4.length); } @@ -1623,11 +1647,11 @@ public class ClassTest extends junit.framework.TestCase { Method m = TestClass.class.getMethod("pubMethod", new Class[0]); assertEquals("Returned incorrect method", 2, ((Integer) (m.invoke(new TestClass()))) .intValue()); - + m = ExtendTestClass1.class.getMethod("getCount", new Class[0]); assertEquals("Returned incorrect method", 0, ((Integer) (m.invoke(new ExtendTestClass1()))) .intValue()); - + try { m = TestClass.class.getMethod("privMethod", new Class[0]); fail("Failed to throw exception accessing private method"); @@ -1635,7 +1659,7 @@ public class ClassTest extends junit.framework.TestCase { // Correct return; } - + try { m = TestClass.class.getMethod("init", new Class[0]); fail("Failed to throw exception accessing to init method"); @@ -1643,14 +1667,14 @@ public class ClassTest extends junit.framework.TestCase { // Correct return; } - + try { TestClass.class.getMethod("pubMethod", new Class[0]); fail("NullPointerException is not thrown."); } catch(NullPointerException npe) { //expected } - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { @@ -1680,7 +1704,7 @@ public class ClassTest extends junit.framework.TestCase { assertEquals("Returned incorrect number of sub-class methods", 2 + Object.class.getMethods().length, m.length); // Number of inherited methods - + SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { @@ -1696,7 +1720,7 @@ public class ClassTest extends junit.framework.TestCase { Cls2.class.getMethods().length); assertEquals("Incorrect number of methods", 11, Cls3.class.getMethods().length); - + Method expected = null; Method[] methods = Cls2.class.getMethods(); for (Method method : methods) { @@ -1710,7 +1734,7 @@ public class ClassTest extends junit.framework.TestCase { fail("getMethods() did not return all methods"); } assertEquals(expected, Cls2.class.getMethod("test")); - + expected = null; methods = Cls3.class.getMethods(); for (Method method : methods) { @@ -1724,7 +1748,7 @@ public class ClassTest extends junit.framework.TestCase { fail("getMethods() did not return all methods"); } assertEquals(expected, Cls3.class.getMethod("test")); - + expected = null; methods = Cls3.class.getMethods(); for (Method method : methods) { @@ -1739,7 +1763,7 @@ public class ClassTest extends junit.framework.TestCase { fail("getMethods() did not return all methods"); } - assertEquals(expected, Cls3.class.getMethod("test2", int.class, + assertEquals(expected, Cls3.class.getMethod("test2", int.class, Object.class)); assertEquals("Incorrect number of methods", 1, @@ -1835,23 +1859,7 @@ public class ClassTest extends junit.framework.TestCase { ClassLoader pcl = getClass().getClassLoader(); Class<?> clazz = pcl.loadClass("org.apache.harmony.luni.tests.java.lang.ClassTest"); assertNotNull(clazz.getResourceAsStream("HelloWorld1.txt")); -/* - InputStream str = Object.class.getResourceAsStream("Class.class"); - assertNotNull("java.lang.Object couldn't find Class.class with " + - "getResource...", str); - assertTrue("Cannot read single byte", str.read() != -1); - assertEquals("Cannot read multiple bytes", 5, str.read(new byte[5])); - str.close(); - - - InputStream str2 = getClass().getResourceAsStream("ClassTest.class"); - assertNotNull("Can't find resource", str2); - assertTrue("Cannot read single byte", str2.read() != -1); - assertEquals("Cannot read multiple bytes", 5, str2.read(new byte[5])); - str2.close(); -*/ - try { getClass().getResourceAsStream(null); fail("NullPointerException is not thrown."); @@ -1916,21 +1924,21 @@ public class ClassTest extends junit.framework.TestCase { clazz1 = Object.class; clazz2 = Class.class; - assertTrue("returned false for superclass", + assertTrue("returned false for superclass", clazz1.isAssignableFrom(clazz2)); clazz1 = TestClass.class; - assertTrue("returned false for same class", + assertTrue("returned false for same class", clazz1.isAssignableFrom(clazz1)); clazz1 = Runnable.class; clazz2 = Thread.class; - assertTrue("returned false for implemented interface", + assertTrue("returned false for implemented interface", clazz1.isAssignableFrom(clazz2)); - - assertFalse("returned true not assignable classes", + + assertFalse("returned true not assignable classes", Integer.class.isAssignableFrom(String.class)); - + try { clazz1.isAssignableFrom(null); fail("NullPointerException is not thrown."); @@ -1973,17 +1981,17 @@ public class ClassTest extends junit.framework.TestCase { args = {} ) public void test_isPrimitive() { - assertFalse("Interface type claims to be primitive.", + assertFalse("Interface type claims to be primitive.", Runnable.class.isPrimitive()); - assertFalse("Object type claims to be primitive.", + assertFalse("Object type claims to be primitive.", Object.class.isPrimitive()); - assertFalse("Prim Array type claims to be primitive.", + assertFalse("Prim Array type claims to be primitive.", int[].class.isPrimitive()); - assertFalse("Array type claims to be primitive.", + assertFalse("Array type claims to be primitive.", Object[].class.isPrimitive()); - assertTrue("Prim type claims not to be primitive.", + assertTrue("Prim type claims not to be primitive.", int.class.isPrimitive()); - assertFalse("Object type claims to be primitive.", + assertFalse("Object type claims to be primitive.", Object.class.isPrimitive()); } @@ -2013,14 +2021,14 @@ public class ClassTest extends junit.framework.TestCase { } catch (InstantiationException e) { // expected } - + try { TestClass3.class.newInstance(); fail("IllegalAccessException is not thrown."); } catch(IllegalAccessException iae) { //expected } - + try { TestClass1C.class.newInstance(); fail("ExceptionInInitializerError should be thrown."); @@ -2038,12 +2046,11 @@ public class ClassTest extends junit.framework.TestCase { method = "newInstance", args = {} ) - @KnownFailure("SecurityException is not thrown.") - public void test_newInstance_FailsOnAndroid() throws Exception { + public void test_newInstance2() throws Exception { SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - TestClass.class.newInstance(); + TestClass.class.newInstance(); fail("Test 1: SecurityException expected."); } catch (SecurityException e) { // expected @@ -2051,7 +2058,7 @@ public class ClassTest extends junit.framework.TestCase { System.setSecurityManager(oldSm); } } - + /** * @tests java.lang.Class#toString() */ @@ -2077,7 +2084,7 @@ public class ClassTest extends junit.framework.TestCase { assertEquals("Class toString printed wrong value", "class [Ljava.lang.Object;", clazz.toString()); } - + @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, notes = "", @@ -2089,16 +2096,16 @@ public class ClassTest extends junit.framework.TestCase { InputStream in = getClass().getResourceAsStream("/" + FILENAME); assertNotNull(in); in.close(); - + in = getClass().getResourceAsStream(FILENAME); assertNull(in); - + in = this.getClass().getClassLoader().getResourceAsStream( FILENAME); assertNotNull(in); - in.close(); + in.close(); } - + /* * Regression test for HARMONY-2644: * Load system and non-system array classes via Class.forName() @@ -2109,8 +2116,6 @@ public class ClassTest extends junit.framework.TestCase { method = "forName", args = {java.lang.String.class} ) - @KnownFailure("Class.forName(String) returns null for invalid class " + - "names instead of throwing a ClassNotFoundException.") public void test_forName_arrays() throws Exception { Class<?> c1 = getClass(); String s = c1.getName(); @@ -2120,7 +2125,7 @@ public class ClassTest extends junit.framework.TestCase { assertSame(a1, a2.getComponentType()); Class<?> l4 = Class.forName("[[[[[J"); assertSame(long[][][][][].class, l4); - + try{ Class<?> clazz = Class.forName("[;"); fail("1: " + clazz); @@ -2146,35 +2151,33 @@ public class ClassTest extends junit.framework.TestCase { fail("6:" + clazz); } catch (ClassNotFoundException ok) {} } - + @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "asSubclass", args = {java.lang.Class.class} - ) + ) public void test_asSubclass1() { - assertEquals(ExtendTestClass.class, + assertEquals(ExtendTestClass.class, ExtendTestClass.class.asSubclass(PublicTestClass.class)); - - assertEquals(PublicTestClass.class, + + assertEquals(PublicTestClass.class, PublicTestClass.class.asSubclass(TestInterface.class)); - - assertEquals(ExtendTestClass1.class, - ExtendTestClass1.class.asSubclass(PublicTestClass.class)); - - assertEquals(PublicTestClass.class, + + assertEquals(ExtendTestClass1.class, + ExtendTestClass1.class.asSubclass(PublicTestClass.class)); + + assertEquals(PublicTestClass.class, PublicTestClass.class.asSubclass(PublicTestClass.class)); } - + @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "asSubclass", args = {java.lang.Class.class} - ) - @KnownFailure("The implementation does not check the validity of the " + - "requested cast.") + ) public void test_asSubclass2() { try { PublicTestClass.class.asSubclass(ExtendTestClass.class); @@ -2190,55 +2193,53 @@ public class ClassTest extends junit.framework.TestCase { // Expected. } } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "cast", args = {java.lang.Object.class} - ) - @KnownFailure("The implementation does not check the validity of the " + - "requested cast.") + ) public void test_cast() { Object o = PublicTestClass.class.cast(new ExtendTestClass()); assertTrue(o instanceof ExtendTestClass); - + try { ExtendTestClass.class.cast(new PublicTestClass()); fail("Test 1: ClassCastException expected."); } catch(ClassCastException cce) { //expected } - + try { ExtendTestClass.class.cast(new String()); fail("ClassCastException is not thrown."); } catch(ClassCastException cce) { //expected } - } - + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "desiredAssertionStatus", args = {} - ) + ) public void test_desiredAssertionStatus() { - Class [] classArray = { Object.class, Integer.class, - String.class, PublicTestClass.class, + Class [] classArray = { Object.class, Integer.class, + String.class, PublicTestClass.class, ExtendTestClass.class, ExtendTestClass1.class}; for(int i = 0; i < classArray.length; i++) { - assertFalse("assertion status for " + classArray[i], + assertFalse("assertion status for " + classArray[i], classArray[i].desiredAssertionStatus()); - } - } + } + } + + - - SecurityManager sm = new SecurityManager() { - + final String forbidenPermissionName = "user.dir"; public void checkPermission(Permission perm) { @@ -2246,19 +2247,19 @@ public class ClassTest extends junit.framework.TestCase { throw new SecurityException(); } } - + public void checkMemberAccess(Class<?> clazz, int which) { if(clazz.equals(TestClass.class)) { throw new SecurityException(); } } - + public void checkPackageAccess(String pkg) { if(pkg.equals(TestClass.class.getPackage())) { throw new SecurityException(); } } - + }; } diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/DoubleTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/DoubleTest.java index 2740b85..3b2d405 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/DoubleTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/DoubleTest.java @@ -17,7 +17,6 @@ package org.apache.harmony.luni.tests.java.lang; import dalvik.annotation.KnownFailure; -import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; @@ -542,6 +541,8 @@ public class DoubleTest extends TestCase { method = "parseDouble", args = {java.lang.String.class} ) + @KnownFailure("parseDouble returns different value on Android " + + "for 0x44b52d02c7e14af6L, it returns 1.0e23.") public void test_parseDoubleLjava_lang_String() { assertEquals("Incorrect double returned, expected zero.", 0.0, Double .parseDouble("2.4703282292062327208828439643411e-324"), 0.0); @@ -858,11 +859,10 @@ public class DoubleTest extends TestCase { @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "", + notes = "Regression test for hotfix in native code of double parser.", method = "parseDouble", args = {java.lang.String.class} ) - @KnownFailure("Hot fix is submitted to ToT.") public void test_parseDouble_LString_AndroidRegression() { // Android regression test long startTime = System.currentTimeMillis(); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java index 11139cd..e38ee63 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java @@ -27,6 +27,8 @@ import java.net.URL; import java.net.URLClassLoader; import java.lang.annotation.Annotation; +import java.lang.annotation.Annotation; + import tests.support.resource.Support_Resources; @TestTargetClass(Package.class) @@ -38,16 +40,31 @@ public class PackageTest extends junit.framework.TestCase { Class clazz; + // URLClassLoader doesn't load classes from jar. + // use PathClassLoader + boolean USE_PATH_CLASS_LOADER = true; + Package getTestPackage(String resourceJar, String className) throws Exception { + + if (USE_PATH_CLASS_LOADER) { + resourceJar = resourceJar.substring(0, resourceJar.indexOf(".")) + + "_dex.jar"; + } Support_Resources.copyFile(resources, "Package", resourceJar); URL resourceURL = new URL("file:/" + resPath + "/Package/" + resourceJar); - URLClassLoader ucl = new URLClassLoader(new URL[] { resourceURL }, null); - - clazz = Class.forName(className, true, ucl); - return clazz.getPackage(); + ClassLoader cl = null; + if(USE_PATH_CLASS_LOADER) { + cl = new dalvik.system.PathClassLoader( + resourceURL.getPath(), getClass().getClassLoader()); + } else { + cl = new URLClassLoader(new URL[] { resourceURL }, + getClass().getClassLoader()); + } + clazz = cl.loadClass(className); + return clazz.getPackage(); } @Override @@ -110,6 +127,7 @@ public class PackageTest extends junit.framework.TestCase { args = {} ) }) + @KnownFailure("get methods don't work.") public void test_helper_Attributes() throws Exception { Package p = getTestPackage("hyts_all_attributes.jar", "p.C"); @@ -301,6 +319,7 @@ public class PackageTest extends junit.framework.TestCase { method = "isCompatibleWith", args = {java.lang.String.class} ) + @KnownFailure("isCompatibleWith returns incorrect value.") public void test_isCompatibleWithLjava_lang_String() throws Exception { Package p = getTestPackage("hyts_c.jar", "p.C"); @@ -357,6 +376,7 @@ public class PackageTest extends junit.framework.TestCase { method = "isSealed", args = {} ) + @KnownFailure("isSealed method returns false for sealed package.") public void test_isSealed() throws Exception { Package p = getTestPackage("hyts_pq.jar", "p.q.C"); assertTrue("Package isSealed returns wrong boolean", p.isSealed()); @@ -374,6 +394,7 @@ public class PackageTest extends junit.framework.TestCase { method = "isSealed", args = {java.net.URL.class} ) + @KnownFailure("isSealed method returns false for sealed package.") public void test_isSealedLjava_net_URL() throws Exception { Package p = getTestPackage("hyts_c.jar", "p.C"); assertFalse("Package isSealed returns wrong boolean (1)", p @@ -404,7 +425,7 @@ public class PackageTest extends junit.framework.TestCase { method = "getAnnotation", args = {java.lang.Class.class} ) - @KnownFailure("Problem in android with loading class from jar") + @KnownFailure("Class loader can't retrieve information about annotations.") public void test_getAnnotation() throws Exception { String annotationName = "a.b.PackageAnnotation"; Package p = getTestPackage("hyts_package.jar", annotationName); @@ -422,6 +443,7 @@ public class PackageTest extends junit.framework.TestCase { method = "getAnnotations", args = {} ) + @KnownFailure("Class loader can't retrieve information about annotations.") public void test_getAnnotations() throws Exception { String annotationName = "a.b.PackageAnnotation"; Package p = getTestPackage("hyts_package.jar", annotationName); @@ -439,6 +461,7 @@ public class PackageTest extends junit.framework.TestCase { method = "getDeclaredAnnotations", args = {} ) + @KnownFailure("Class loader can't retrieve information about annotations.") public void test_getDeclaredAnnotations() throws Exception { String annotationName = "a.b.PackageAnnotation"; Package p = getTestPackage("hyts_package.jar", annotationName); @@ -457,6 +480,7 @@ public class PackageTest extends junit.framework.TestCase { method = "isAnnotationPresent", args = {java.lang.Class.class} ) + @KnownFailure("Class loader can't retrieve information about annotations.") public void test_isAnnotationPresent() throws Exception { String annotationName = "a.b.PackageAnnotation"; Package p = getTestPackage("hyts_package.jar", annotationName); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java index c4066d2..2f2b823 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/RuntimeTest.java @@ -17,8 +17,6 @@ package org.apache.harmony.luni.tests.java.lang; -import tests.support.resource.Support_Resources; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; @@ -34,6 +32,8 @@ import java.security.Permission; import java.util.Arrays; import java.util.Vector; +import tests.support.resource.Support_Resources; + @TestTargetClass(Runtime.class) public class RuntimeTest extends junit.framework.TestCase { @@ -46,6 +46,8 @@ public class RuntimeTest extends junit.framework.TestCase { static boolean flag = false; static boolean ranFinalize = false; + + int statusCode = -1; class HasFinalizer { String internalString; @@ -71,24 +73,10 @@ public class RuntimeTest extends junit.framework.TestCase { } /** - * @tests java.lang.Runtime#exit(int) - */ - @TestTargetNew( - level = TestLevel.COMPLETE, - notes = "This method never returns normally, and can't be tested.", - method = "exit", - args = {int.class} - ) - public void test_exitI() { - // Test for method void java.lang.Runtime.exit(int) - assertTrue("Can't really test this", true); - } - - /** * @tests java.lang.Runtime#exec(java.lang.String) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.ADDITIONAL, notes = "", method = "exec", args = {java.lang.String.class} @@ -111,8 +99,26 @@ public class RuntimeTest extends junit.framework.TestCase { args = {} ) public void test_freeMemory() { - // Test for method long java.lang.Runtime.freeMemory() - assertTrue("freeMemory returned nonsense value", r.freeMemory() > 0); + try { + long before = r.freeMemory(); + Vector<StringBuffer> v = new Vector<StringBuffer>(); + for (int i = 1; i < 10; i++) + v.addElement(new StringBuffer(10000)); + long after = r.freeMemory(); + v = null; + r.gc(); + assertTrue("freeMemory should return less value after " + + "creating an object", after < before); + long afterGC = r.freeMemory(); + assertTrue("freeMemory should not return less value after " + + "creating an object", afterGC > after); + } catch (Exception e) { + System.out.println("Out of memory during freeMemory test: " + + e.getMessage()); + r.gc(); + } finally { + r.gc(); + } } /** @@ -141,7 +147,7 @@ public class RuntimeTest extends junit.framework.TestCase { assertTrue("space was not reclaimed", (r.totalMemory() - r .freeMemory()) < secondRead); } catch (Throwable t) { - System.out.println("Out of memory during freeMemory test"); + System.out.println("Out of memory during gc test"); r.gc(); r.gc(); } @@ -158,7 +164,7 @@ public class RuntimeTest extends junit.framework.TestCase { ) public void test_getRuntime() { // Test for method java.lang.Runtime java.lang.Runtime.getRuntime() - assertTrue("Used to test", true); + assertNotNull(Runtime.getRuntime()); } /** @@ -206,9 +212,6 @@ public class RuntimeTest extends junit.framework.TestCase { method = "addShutdownHook", args = {java.lang.Thread.class} ) - @KnownFailure("IllegalArgumentException is not thrown if " + - "hook is already registered, and addShutdownHook is " + - "called again. ToT fixed.") public void test_addShutdownHook() { Thread thrException = new Thread () { public void run() { @@ -710,23 +713,11 @@ public class RuntimeTest extends junit.framework.TestCase { } @TestTargetNew( - level = TestLevel.NOT_FEASIBLE, - notes = "Can't be tested. This method terminates the currently running JVM", - method = "halt", - args = {int.class} - ) - public void test_halt() { - // TODO Can't be tested. - // This method terminates the currently running JVM. - } - - @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "runFinalizersOnExit", args = {boolean.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_runFinalizersOnExit() { Runtime.getRuntime().runFinalizersOnExit(true); @@ -758,7 +749,6 @@ public class RuntimeTest extends junit.framework.TestCase { method = "removeShutdownHook", args = {java.lang.Thread.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_removeShutdownHookLjava_lang_Thread() { Thread thr1 = new Thread () { public void run() { @@ -847,7 +837,6 @@ public class RuntimeTest extends junit.framework.TestCase { method = "traceMethodCalls", args = {boolean.class} ) - @KnownFailure("java.lang.InternalError occurs. ToT fixed.") public void test_traceMethodCalls() { Runtime.getRuntime().traceMethodCalls(false); Runtime.getRuntime().traceMethodCalls(true); @@ -866,7 +855,6 @@ public class RuntimeTest extends junit.framework.TestCase { method = "getLocalizedInputStream", args = {java.io.InputStream.class} ) - @KnownFailure("ToT fixed.") public void test_getLocalizedInputStream() { String simpleString = "Heart \u2f3c"; byte[] expected = {72, 0, 101, 0, 97, 0, 114, 0, 116, 0, 32, 0, 60, 47}; @@ -903,7 +891,6 @@ public class RuntimeTest extends junit.framework.TestCase { method = "getLocalizedOutputStream", args = {java.io.OutputStream.class} ) - @KnownFailure("ToT fixed.") public void test_getLocalizedOutputStream() { String simpleString = "Heart \u2f3c"; byte[] expected = {72, 0, 101, 0, 97, 0, 114, 0, 116, 0, 32, 0, 60, 47}; @@ -942,8 +929,6 @@ public class RuntimeTest extends junit.framework.TestCase { method = "load", args = {java.lang.String.class} ) - @KnownFailure("UnsatisfiedLinkError is not thrown for non existent " + - "library. ToT fixed.") public void test_load() { try { @@ -967,7 +952,7 @@ public class RuntimeTest extends junit.framework.TestCase { } public void checkLink(String lib) { - if (lib.endsWith("libTestLibrary.so")) { + if (lib.endsWith("libjvm.so")) { throw new SecurityException(); } } @@ -976,7 +961,7 @@ public class RuntimeTest extends junit.framework.TestCase { SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - Runtime.getRuntime().load("libTestLibrary.so"); + Runtime.getRuntime().load("libjvm.so"); fail("SecurityException should be thrown."); } catch (SecurityException e) { // expected @@ -1013,7 +998,7 @@ public class RuntimeTest extends junit.framework.TestCase { } public void checkLink(String lib) { - if (lib.endsWith("libTestLibrary.so")) { + if (lib.endsWith("libjvm.so")) { throw new SecurityException(); } } @@ -1022,7 +1007,7 @@ public class RuntimeTest extends junit.framework.TestCase { SecurityManager oldSm = System.getSecurityManager(); System.setSecurityManager(sm); try { - Runtime.getRuntime().loadLibrary("libTestLibrary.so"); + Runtime.getRuntime().loadLibrary("libjvm.so"); fail("SecurityException should be thrown."); } catch (SecurityException e) { // expected @@ -1031,6 +1016,76 @@ public class RuntimeTest extends junit.framework.TestCase { } } + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "This method never returns normally, " + + "and can't be tested. Only SecurityException can be checked.", + method = "exit", + args = {int.class} + ) + public void test_exit() { + statusCode = -1; + SecurityManager sm = new SecurityManager() { + + public void checkPermission(Permission perm) { + + } + + public void checkExit(int status) { + statusCode = status; + throw new SecurityException(); + } + }; + + SecurityManager oldSm = System.getSecurityManager(); + System.setSecurityManager(sm); + try { + r.exit(0); + fail("SecurityException should be thrown."); + } catch (SecurityException e) { + // expected + } finally { + assertTrue("Incorrect status code was received: " + statusCode, + statusCode == 0); + System.setSecurityManager(oldSm); + } + + } + + @TestTargetNew( + level = TestLevel.SUFFICIENT, + notes = "Can't be tested. This method terminates the currently " + + "running VM. Only SecurityException can be checked.", + method = "halt", + args = {int.class} + ) + public void test_halt() { + statusCode = -1; + SecurityManager sm = new SecurityManager() { + + public void checkPermission(Permission perm) { + + } + + public void checkExit(int status) { + statusCode = status; + throw new SecurityException(); + } + }; + + SecurityManager oldSm = System.getSecurityManager(); + System.setSecurityManager(sm); + try { + r.halt(0); + fail("SecurityException should be thrown."); + } catch (SecurityException e) { + // expected + } finally { + assertTrue("Incorrect status code was received: " + statusCode, + statusCode == 0); + System.setSecurityManager(oldSm); + } + } public RuntimeTest() { } diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManager2Test.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManager2Test.java deleted file mode 100644 index 9c70c87..0000000 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManager2Test.java +++ /dev/null @@ -1,64 +0,0 @@ -/* 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.harmony.luni.tests.java.lang; - -import dalvik.annotation.BrokenTest; -import dalvik.annotation.TestTargets; -import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargetClass; - -import junit.framework.TestCase; - -import java.security.Permission; - -import tests.support.Support_Exec; - -@TestTargetClass(SecurityManager.class) -public class SecurityManager2Test extends TestCase { - - @TestTargetNew( - level = TestLevel.COMPLETE, - notes = "", - method = "SecurityManager", - args = {} - ) - @BrokenTest("Support_Exec.execJava is not so simple to use: Harmony Test cannot be easily adapted.") - public void test_SecurityManager_via_SystemProperty() throws Exception { - String[] arg = new String[] { - "-Djava.security.manager=" + MySecurityManager.class.getName(), - TestForSystemProperty.class.getName() }; - - Support_Exec.execJava(arg, null, true); - } - - public static class TestForSystemProperty { - - public static void main(String[] args) { - assertEquals(MySecurityManager.class, System.getSecurityManager() - .getClass()); - } - } - - /** - * Custom security manager - */ - public static class MySecurityManager extends SecurityManager { - public void checkPermission(Permission perm) { - } - } -} diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java index 3f40541..be5aa41 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java @@ -16,7 +16,6 @@ package org.apache.harmony.luni.tests.java.lang; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -215,7 +214,6 @@ public class SecurityManagerTest extends TestCase { method = "checkMemberAccess", args = {java.lang.Class.class, int.class} ) - @KnownFailure("ToT fixed.") public void test_checkMemberAccessLjava_lang_ClassI() { // enable all but one check mutableSM.addPermission(new AllPermission()); @@ -510,7 +508,6 @@ public class SecurityManagerTest extends TestCase { method = "checkConnect", args = {java.lang.String.class, int.class} ) - @KnownFailure("ToT fixed.") public void test_checkConnectLjava_lang_StringI() { String hostName = "localhost"; int port = 1024; @@ -569,7 +566,6 @@ public class SecurityManagerTest extends TestCase { method = "checkConnect", args = {java.lang.String.class, int.class, java.lang.Object.class} ) - @KnownFailure("ToT fixed.") @SuppressWarnings("nls") public void test_checkConnectLjava_lang_String_int_Ljava_lang_Object() { // enable all but one check @@ -1558,7 +1554,6 @@ public class SecurityManagerTest extends TestCase { method = "getClassContext", args = {} ) - @KnownFailure("ToT fixed.") public void test_getClassContext() { Class [] stack = {MockSecurityManager.class, diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java index b1b3c5f..2c65f52 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SystemTest.java @@ -17,7 +17,6 @@ package org.apache.harmony.luni.tests.java.lang; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -51,7 +50,6 @@ public class SystemTest extends junit.framework.TestCase { method = "setIn", args = {java.io.InputStream.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_setInLjava_io_InputStream() { InputStream orgIn = System.in; InputStream in = new ByteArrayInputStream(new byte[0]); @@ -90,7 +88,6 @@ public class SystemTest extends junit.framework.TestCase { method = "setOut", args = {java.io.PrintStream.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_setOutLjava_io_PrintStream() { PrintStream orgOut = System.out; PrintStream out = new PrintStream(new ByteArrayOutputStream()); @@ -129,7 +126,6 @@ public class SystemTest extends junit.framework.TestCase { method = "setErr", args = {java.io.PrintStream.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_setErrLjava_io_PrintStream() { PrintStream orgErr = System.err; PrintStream err = new PrintStream(new ByteArrayOutputStream()); @@ -170,8 +166,6 @@ public class SystemTest extends junit.framework.TestCase { args = {java.lang.Object.class, int.class, java.lang.Object.class, int.class, int.class} ) - @KnownFailure("Doesn't throw IndexOutOfBoundsException for boundary value " + - "of src position. Failure in native code, doesn't check overflow.") public void test_arraycopyLjava_lang_ObjectILjava_lang_ObjectII() { // Test for method void java.lang.System.arraycopy(java.lang.Object, // int, java.lang.Object, int, int) @@ -684,7 +678,6 @@ public class SystemTest extends junit.framework.TestCase { method = "inheritedChannel", args = {} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_inheritedChannel() throws IOException { Channel iChannel = System.inheritedChannel(); assertNull("Incorrect value of channel", iChannel); @@ -747,7 +740,6 @@ public class SystemTest extends junit.framework.TestCase { method = "runFinalizersOnExit", args = {boolean.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") @SuppressWarnings("deprecation") public void test_runFinalizersOnExitZ() { // Can we call the method at least? @@ -1001,9 +993,6 @@ public class SystemTest extends junit.framework.TestCase { method = "getenv", args = {} ) - @KnownFailure("getenv() method returns empty map, " + - "because getEnvByIndex always returns null. " + - "ToT fixed.") public void test_getenv() { // String[] props = { "PATH", "HOME", "USER"}; @@ -1090,7 +1079,6 @@ public class SystemTest extends junit.framework.TestCase { method = "load", args = {java.lang.String.class} ) - @KnownFailure("UnsatisfiedLinkError is not thrown. ToT fixed.") public void test_load() { try { new TestLibrary().checkString(); @@ -1142,7 +1130,6 @@ public class SystemTest extends junit.framework.TestCase { method = "loadLibrary", args = {java.lang.String.class} ) - @KnownFailure("Security checking is missed. ToT fixed.") public void test_loadLibrary() { try { diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java index 12eb1fc..2748223 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/TestLibrary.java @@ -16,6 +16,12 @@ package org.apache.harmony.luni.tests.java.lang; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + class TestLibrary { private native String printName(); @@ -25,7 +31,20 @@ class TestLibrary { return false; } - static { - Runtime.getRuntime().load(TestLibrary.class.getResource("/libTestLibrary.so").getPath()); + TestLibrary() { + InputStream in = TestLibrary.class.getResourceAsStream("/libTestLibrary.so"); + try { + File tmp = File.createTempFile("libTestLibrary", "so"); + tmp.deleteOnExit(); + FileOutputStream out = new FileOutputStream(tmp); + while (in.available() > 0) { + out.write(in.read()); // slow + } + in.close(); + out.close(); + Runtime.getRuntime().load(tmp.getAbsolutePath()); + } catch (FileNotFoundException e) { + } catch (IOException e) { + } } } diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java index 9afa4a9..7e8030a 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadGroupTest.java @@ -18,7 +18,6 @@ package org.apache.harmony.luni.tests.java.lang; import dalvik.annotation.AndroidOnly; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -83,8 +82,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "ThreadGroup", args = {java.lang.String.class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_ConstructorLjava_lang_String() { // Test for method java.lang.ThreadGroup(java.lang.String) @@ -131,8 +128,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "ThreadGroup", args = {java.lang.ThreadGroup.class, java.lang.String.class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() { // Test for method java.lang.ThreadGroup(java.lang.ThreadGroup, // java.lang.String) @@ -207,8 +202,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "activeCount", args = {} ) - @KnownFailure("Active thread count is not increased after starting of " + - "the thread from ThreadGroup.") public void test_activeCount() { // Test for method int java.lang.ThreadGroup.activeCount() ThreadGroup tg = new ThreadGroup("activeCount"); @@ -250,7 +243,7 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. 0, tg.activeGroupCount()); Thread t1 = new Thread(tg, new Runnable() { public void run() { - // TODO Auto-generated method stub + } }); assertEquals("Incorrect number of groups", @@ -293,8 +286,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "checkAccess", args = {} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_checkAccess() { // Test for method void java.lang.ThreadGroup.checkAccess() @@ -334,8 +325,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "enumerate", args = {java.lang.Thread[].class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_enumerateLThreadArray() { int numThreads = initialThreadGroup.activeCount(); Thread[] listOfThreads = new Thread[numThreads]; @@ -362,7 +351,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "enumerate", args = {java.lang.Thread[].class, boolean.class} ) - @KnownFailure("Depends of activeCount failure.") public void test_enumerateLThreadArrayLZ() { int numThreads = initialThreadGroup.activeCount(); Thread[] listOfThreads = new Thread[numThreads]; @@ -440,8 +428,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "enumerate", args = {java.lang.ThreadGroup[].class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_enumerateLThreadGroupArray() { int numGroupThreads = initialThreadGroup.activeGroupCount(); ThreadGroup[] listOfGroups = new ThreadGroup[numGroupThreads]; @@ -480,8 +466,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "enumerate", args = {java.lang.ThreadGroup[].class, boolean.class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_enumerateLThreadGroupArrayLZ() { ThreadGroup thrGroup = new ThreadGroup("Test Group 1"); Vector<MyThread> subThreads = populateGroupsWithThreads(thrGroup, 3); @@ -551,8 +535,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "destroy", args = {} ) - @KnownFailure("the daemon thread group is not get destroyed " + - " if the last daemon's child is destroyed.") public void test_destroy() { // Test for method void java.lang.ThreadGroup.destroy() @@ -773,7 +755,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "getParent", args = {} ) - @KnownFailure("checkAccess method is called with incorrect group???") public void test_getParent() { // Test for method java.lang.ThreadGroup // java.lang.ThreadGroup.getParent() @@ -838,8 +819,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "interrupt", args = {} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_interrupt() { Thread.setDefaultUncaughtExceptionHandler(this); @@ -1019,7 +998,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "resume", args = {} ) - @KnownFailure("Failure depends on activeCount().") @SuppressWarnings("deprecation") @AndroidOnly("Thread.resume is implemented on some RI") public void test_resume() throws OutOfMemoryError { @@ -1087,8 +1065,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "setDaemon", args = {boolean.class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_setDaemonZ() { // Test for method void java.lang.ThreadGroup.setDaemon(boolean) daemonTests(); @@ -1119,8 +1095,6 @@ public class ThreadGroupTest extends junit.framework.TestCase implements Thread. method = "setMaxPriority", args = {int.class} ) - @KnownFailure("Security checking is missed. " + - "checkAccess method should be invoked.") public void test_setMaxPriorityI() { // Test for method void java.lang.ThreadGroup.setMaxPriority(int) final ThreadGroup originalCurrent = getInitialThreadGroup(); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java index 588106c..b290555 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java @@ -24,7 +24,6 @@ import java.security.Permission; import java.util.Map; import dalvik.annotation.AndroidOnly; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -1971,7 +1970,6 @@ public class ThreadTest extends junit.framework.TestCase { method = "getState", args = {} ) - @KnownFailure("ToT FIXED") public void test_getState() { Thread.State state = Thread.currentThread().getState(); assertNotNull(state); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java index 51189ff..7a6c505 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java @@ -32,39 +32,36 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; import java.io.File; import java.io.FilePermission; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.lang.reflect.Field; -import java.net.ContentHandler; -import java.net.ContentHandlerFactory; +import java.net.CacheRequest; +import java.net.CacheResponse; import java.net.FileNameMap; import java.net.HttpURLConnection; import java.net.JarURLConnection; import java.net.MalformedURLException; +import java.net.ResponseCache; import java.net.SocketPermission; import java.net.SocketTimeoutException; +import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.UnknownServiceException; -import java.security.AllPermission; import java.security.Permission; import java.util.Arrays; import java.util.Calendar; -import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.Map; import java.util.TimeZone; -import java.util.Vector; -import java.util.logging.StreamHandler; @TestTargetClass( value = URLConnection.class, @@ -98,8 +95,18 @@ public class URLConnectionTest extends TestCase { private URLConnection gifURLCon; private URL gifURL; + + public boolean isGetCalled; + + public boolean isPutCalled; - + private Map<String, List<String>> mockHeaderMap; + + private InputStream mockIs = new MockInputStream(); + + public boolean isCacheWriteCalled; + + public boolean isAbortCalled; /** * @tests {@link java.net.URLConnection#addRequestProperty(String, String)} @@ -255,6 +262,98 @@ public class URLConnectionTest extends TestCase { }; } } + + class MockCachedResponseCache extends ResponseCache { + + public CacheResponse get(URI arg0, String arg1, Map arg2) + throws IOException { + if (null == arg0 || null == arg1 || null == arg2) { + throw new NullPointerException(); + } + isGetCalled = true; + return new MockCacheResponse(); + } + + public CacheRequest put(URI arg0, URLConnection arg1) + throws IOException { + if (null == arg0 || null == arg1) { + throw new NullPointerException(); + } + isPutCalled = true; + return new MockCacheRequest(); + } + } + + class MockNonCachedResponseCache extends ResponseCache { + + public CacheResponse get(URI arg0, String arg1, Map arg2) + throws IOException { + isGetCalled = true; + return null; + } + + public CacheRequest put(URI arg0, URLConnection arg1) + throws IOException { + isPutCalled = true; + return new MockCacheRequest(); + } + } + + class MockCacheRequest extends CacheRequest { + + public OutputStream getBody() throws IOException { + isCacheWriteCalled = true; + return new MockOutputStream(); + } + + public void abort() { + isAbortCalled = true; + } + + } + + class MockInputStream extends InputStream { + + public int read() throws IOException { + return 4711; + } + + public int read(byte[] arg0, int arg1, int arg2) throws IOException { + return 1; + } + + public int read(byte[] arg0) throws IOException { + return 1; + } + + } + + class MockOutputStream extends OutputStream { + + public void write(int b) throws IOException { + isCacheWriteCalled = true; + } + + public void write(byte[] b, int off, int len) throws IOException { + isCacheWriteCalled = true; + } + + public void write(byte[] b) throws IOException { + isCacheWriteCalled = true; + } + } + + class MockCacheResponse extends CacheResponse { + + public Map<String, List<String>> getHeaders() throws IOException { + return mockHeaderMap; + } + + public InputStream getBody() throws IOException { + return mockIs; + } + } + private static int port; @@ -274,6 +373,7 @@ public class URLConnectionTest extends TestCase { URLConnection uc2; + @Override public void setUp() throws Exception { super.setUp(); @@ -298,6 +398,7 @@ public class URLConnectionTest extends TestCase { } + @Override public void tearDown()throws Exception { super.tearDown(); ((HttpURLConnection) uc).disconnect(); @@ -367,7 +468,7 @@ public class URLConnectionTest extends TestCase { args = {} ), @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.SUFFICIENT, notes = "From harmony branch.", method = "setAllowUserInteraction", args = {boolean.class} @@ -391,6 +492,44 @@ public class URLConnectionTest extends TestCase { //ok } + // test if setAllowUserInteraction works + URL serverURL = new URL("http://onearth.jpl.nasa.gov/landsat.cgi"); + + // connect to server + URLConnection uc2 = serverURL.openConnection(); + HttpURLConnection conn = (HttpURLConnection) uc2; + uc2.setAllowUserInteraction(true); + + uc2.setDoInput(true); + uc2.setDoOutput(true); + + // get reference to stream to post to + OutputStream os = uc2.getOutputStream(); + + InputStream in = uc2.getInputStream(); + + + int contentLength = uc2.getContentLength(); + String contentType = uc2.getContentType(); + int numBytesRead = 0; + int allBytesRead = 0; + + byte[] buffer = new byte[4096]; + + do { + + numBytesRead = in.read(buffer); + allBytesRead += allBytesRead + numBytesRead; + + } while (numBytesRead > 0); + + assertTrue(allBytesRead > 0); + + uc2.connect(); + + numBytesRead = in.read(buffer); + + assertEquals(-1, numBytesRead); } /** @@ -643,12 +782,11 @@ public class URLConnectionTest extends TestCase { ), @TestTargetNew( level = TestLevel.COMPLETE, - notes = "From harmony branch. Test Fails: undocumented exception IlligalAccessError", + notes = "From harmony branch.", method = "setDefaultAllowUserInteraction", args = {boolean.class} ) }) - @KnownFailure("needs investigation") public void test_getDefaultAllowUserInteraction() throws IOException { boolean oldSetting = URLConnection.getDefaultAllowUserInteraction(); @@ -662,20 +800,10 @@ public class URLConnectionTest extends TestCase { URLConnection.getDefaultAllowUserInteraction()); URLConnection.setDefaultAllowUserInteraction(oldSetting); - - uc.connect(); - - // check if undocumented exception is thrown - try { - uc.setDefaultUseCaches(oldSetting); - } catch ( IllegalAccessError e) { - fail("Undocumented exception thrown "+e.getMessage()); - } - } /** - * @tests {@link java.net.URLConnection#getDefaultRequestProperty(java.lang.String)} + * @tests {@link java.net.URLConnection#getDefaultRequestProperty(String)} */ @TestTargets({ @TestTargetNew( @@ -709,7 +837,7 @@ public class URLConnectionTest extends TestCase { /** * @throws IOException - * @tests{@link java.net.URLConnection#getDefaultUseCaches()} + * @tests {@link java.net.URLConnection#getDefaultUseCaches()} */ @TestTargets({ @TestTargetNew( @@ -725,25 +853,63 @@ public class URLConnectionTest extends TestCase { args = {boolean.class} ) }) - @KnownFailure("The final call to connect throws an unexpected Exception") - public void test_getDefaultUseCaches() throws IOException { + public void test_getDefaultUseCaches_CachedRC() throws IOException { boolean oldSetting = uc.getDefaultUseCaches(); - + + ResponseCache old = ResponseCache.getDefault(); + ResponseCache rc = new MockCachedResponseCache(); + ResponseCache.setDefault(rc); + + // Recreate the connection so that we get the cache from ResponseCache. + uc2 = url2.openConnection(); + + uc2.setUseCaches(true); + uc.setDefaultUseCaches(false); - assertFalse("getDefaultUseCaches should have returned false", uc - .getDefaultUseCaches()); - uc.setDefaultUseCaches(true); - assertTrue("getDefaultUseCaches should have returned true", uc + // uc unaffected + assertTrue(uc.getUseCaches()); + // uc2 unaffected + assertTrue(uc2.getUseCaches()); + + //test get + assertFalse("getDefaultUseCaches should have returned false", uc .getDefaultUseCaches()); - - uc.setDefaultUseCaches(oldSetting); + // subsequent connections should have default value + URL url3 = new URL(Support_Configuration.hTTPURLyahoo); + URLConnection uc3 = url3.openConnection(); + assertFalse(uc3.getUseCaches()); + + // test if uc does not chash but uc2 does + isGetCalled = false; + isPutCalled = false; + + // test uc + uc.setDoOutput(true); + + assertFalse(isGetCalled); uc.connect(); + assertFalse(isGetCalled); + assertFalse(isPutCalled); + OutputStream os = uc.getOutputStream(); + assertFalse(isPutCalled); + assertFalse(isGetCalled); - // check if undocumented exception is thrown - + os.close(); + + isGetCalled = false; + isPutCalled = false; + + //uc2 should be unaffected + uc2.setDoOutput(true); + assertFalse(isGetCalled); + uc2.connect(); + assertTrue(isGetCalled); + assertFalse(isPutCalled); + uc.setDefaultUseCaches(oldSetting); + ResponseCache.setDefault(null); } /** @@ -833,6 +999,8 @@ public class URLConnectionTest extends TestCase { method = "getExpiration", args = {} ) + @KnownFailure("URLConnection.getExpiration crashes because the returned" + + " expiration date doesn't seems to be parsable.") public void test_getExpiration() throws IOException { URL url3 = new URL(Support_Configuration.hTTPURLwExpiration); URLConnection uc3 = url3.openConnection(); @@ -1038,6 +1206,7 @@ public class URLConnectionTest extends TestCase { method = "getHeaderField", args = {java.lang.String.class} ) + @BrokenTest("Flaky due to third party servers used to do the test.") public void test_getHeaderFieldLjava_lang_String() { String hf; int hfDefault; @@ -1437,10 +1606,7 @@ public class URLConnectionTest extends TestCase { */ @TestTargetNew( level = TestLevel.COMPLETE, - notes = "Test fails: checking file://data/local/tmp/hyts_htmltest.html " + - "with file:/data/local/tmp/openStreamTest15770.txt expected: " + - "<...html> but was:<...plain>\n" + - "", + notes = "", method = "guessContentTypeFromName", args = {java.lang.String.class} ) @@ -1478,21 +1644,28 @@ public class URLConnectionTest extends TestCase { method = "guessContentTypeFromStream", args = {java.io.InputStream.class} ) - @BrokenTest("Also fails on the RI.") + @BrokenTest("MIME type application xml is not supported: only text html."+ + " Should be implemented if compatibility is required. The RI" + + " on the other hand doesn't recognise the '<head' tag.") public void test_guessContentTypeFromStreamLjava_io_InputStream() throws IOException { String[] headers = new String[] { "<html>", "<head>", " <head ", - "<body", "<BODY ", "<!DOCTYPE html", "<?xml " }; - String[] expected = new String[] { "text/html", "text/html", - "text/html", "text/html", "text/html", "text/html", - "application/xml" }; - - String[] encodings = new String[] { "ASCII", "UTF-8", "UTF-16BE", - "UTF-16LE", "UTF-32BE", "UTF-32LE" }; + "<body", "<BODY ", //"<!DOCTYPE html", + "<?xml " }; + String[] expected = new String[] { "text/html","text/html", "text/html", + "text/html","text/html", "application/xml" }; + + String[] encodings = new String[] { "ASCII", "UTF-8", + //"UTF-16BE", not supported + //"UTF-16LE", not supported + //"UTF-32BE", not supported encoding + //"UTF-32LE" not supported encoding + }; for (int i = 0; i < headers.length; i++) { for (String enc : encodings) { - InputStream is = new ByteArrayInputStream(toBOMBytes( - headers[i], enc)); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + String encodedString = new String(headers[i].getBytes(), enc); + InputStream is = new ByteArrayInputStream(encodedString.getBytes()); String mime = URLConnection.guessContentTypeFromStream(is); assertEquals("checking " + headers[i] + " with " + enc, expected[i], mime); @@ -1506,7 +1679,7 @@ public class URLConnectionTest extends TestCase { } catch (NullPointerException e) { // expected } - + /* not supported // Test magic bytes byte[][] bytes = new byte[][] { { 'P', 'K' }, { 'G', 'I' } }; expected = new String[] { "application/zip", "image/gif" }; @@ -1516,6 +1689,7 @@ public class URLConnectionTest extends TestCase { assertEquals(expected[i], URLConnection .guessContentTypeFromStream(is)); } + */ } // /** @@ -1774,7 +1948,6 @@ public class URLConnectionTest extends TestCase { args = {} ) }) - @KnownFailure("uc2.getContent returns null") public void test_setReadTimeoutI() throws Exception { assertEquals(0, uc.getReadTimeout()); uc.setReadTimeout(0); @@ -1798,9 +1971,12 @@ public class URLConnectionTest extends TestCase { byte[] ba = new byte[600]; - uc2.setReadTimeout(50); + uc2.setReadTimeout(5); + uc2.setDoInput(true); + uc2.connect(); + try { - ((InputStream) uc2.getContent()).read(ba, 0, 600); + ((InputStream) uc2.getInputStream()).read(ba, 0, 600); } catch (SocketTimeoutException e) { //ok } catch ( UnknownServiceException e) { @@ -1837,11 +2013,12 @@ public class URLConnectionTest extends TestCase { } @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "", - method = "getInputStream", - args = {} - ) + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "getInputStream", + args = {} + ) + @BrokenTest("Flaky test due to the use of third party servers") public void testGetInputStream() throws IOException { fileURLCon.setDoInput(true); fileURLCon.connect(); @@ -1898,33 +2075,7 @@ public class URLConnectionTest extends TestCase { System.setSecurityManager(old_sm); } - } - - private byte[] toBOMBytes(String text, String enc) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - - if (enc.equals("UTF-8")) { - bos.write(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }); - } - if (enc.equals("UTF-16BE")) { - bos.write(new byte[] { (byte) 0xFE, (byte) 0xFF }); - } - if (enc.equals("UTF-16LE")) { - bos.write(new byte[] { (byte) 0xFF, (byte) 0xFE }); - } - if (enc.equals("UTF-32BE")) { - bos.write(new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xFE, - (byte) 0xFF }); - } - if (enc.equals("UTF-32LE")) { - bos.write(new byte[] { (byte) 0xFF, (byte) 0xFE, (byte) 0x00, - (byte) 0x00 }); - } - - bos.write(text.getBytes(enc)); - return bos.toByteArray(); - } - + } private URLConnection openGifURLConnection() throws IOException { String cts = System.getProperty("java.io.tmpdir"); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java index f16f881..1e38d90 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLTest.java @@ -53,6 +53,7 @@ import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import java.security.Permission; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; @TestTargetClass(URL.class) @@ -528,7 +529,6 @@ public class URLTest extends TestCase { method = "toURI", args = {} ) - @BrokenTest("cannot think of case which throws URISyntaxException on a valid URL") public void testToURI() throws MalformedURLException, URISyntaxException { String testHTTPURLString = "http://www.gamelan.com/pages/"; String testFTPURLString = "ftp://myname@host.dom/etc/motd"; @@ -540,12 +540,42 @@ public class URLTest extends TestCase { assertEquals(testHTTPURI.toString(),testHTTPURLString); assertEquals(testFTPURI.toString(),testFTPURLString); - try { - URL urlQuery = new URL("jar:file:tests/resources/hyts_att.jar!/NoAttributes.txt"); - urlQuery.toURI(); - fail("Exception expected"); - } catch (URISyntaxException e) { - // ok + //Exception test + String[] constructorTestsInvalid = new String[] { + "http:///a path#frag", // space char in path, not in escaped + // octet form, with no host + "http://host/a[path#frag", // an illegal char, not in escaped + // octet form, should throw an + // exception + "http://host/a%path#frag", // invalid escape sequence in path + "http://host/a%#frag", // incomplete escape sequence in path + + "http://host#a frag", // space char in fragment, not in + // escaped octet form, no path + "http://host/a#fr#ag", // illegal char in fragment + "http:///path#fr%ag", // invalid escape sequence in fragment, + // with no host + "http://host/path#frag%", // incomplete escape sequence in + // fragment + + "http://host/path?a query#frag", // space char in query, not + // in escaped octet form + "http://host?query%ag", // invalid escape sequence in query, no + // path + "http:///path?query%", // incomplete escape sequence in query, + // with no host + + "mailto:user^name@fklkf.com" // invalid char in scheme + }; + + for (String malformedURI : Arrays.asList(constructorTestsInvalid)) { + try { + URL urlQuery = new URL("http://host/a%path#frag"); + urlQuery.toURI(); + fail("Exception expected"); + } catch (URISyntaxException e) { + // ok + } } } @@ -554,83 +584,81 @@ public class URLTest extends TestCase { */ @TestTargetNew( level = TestLevel.NOT_FEASIBLE, - notes = "Proxy does not work. Neither Proxy HTTP nor Proxy SOCKS work.", + notes = "See ExcludedProxyTest.", method = "openConnection", args = {java.net.Proxy.class} ) - @BrokenTest("Hangs in RI and fails in Android") + @BrokenTest("the host address isn't working anymore") public void testOpenConnectionProxy() throws IOException { - URL gSearch = new URL("http://www.google.ch/"); - HttpURLConnection uc = null; - int port = Support_PortManager.getNextPort(); - SocketAddress addr1 = new InetSocketAddress("test.domain.org", port); - startServer("test.domain.org", port); - Proxy proxy1 = new Proxy(Proxy.Type.SOCKS, addr1); - Socket sock = new Socket(proxy1); - try { - uc = (HttpURLConnection) gSearch.openConnection( - ); - uc.connect(); - uc.getResponseCode(); - assertEquals(uc.getURL(), gSearch); - } finally { - uc.disconnect(); + // create Proxy + + System.setProperty("http.proxyHost", + Support_Configuration.ProxyServerTestHost); + System.setProperty("http.proxyPort", "80"); + + URL u2 = new URL("http://" + + Support_Configuration.ProxyServerTestHost + + "/cgi-bin/test.pl"); + + SocketAddress addr1 = new InetSocketAddress(Support_Configuration.ProxyServerTestHost, 80); + Proxy proxy1 = new Proxy(Proxy.Type.HTTP, addr1); + + // create test input + String posted = "just a test"; + + // perform test + java.net.HttpURLConnection conn = (java.net.HttpURLConnection) u2 + .openConnection(proxy1); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + conn.setConnectTimeout(3000); + + OutputStream out = conn.getOutputStream(); + out.write(posted.getBytes()); + out.close(); + + + /* + InputStream in = conn.getErrorStream(); + if (in != null ){ + BufferedReader r = new BufferedReader(new InputStreamReader(in), 200); + String line; + while((line = r.readLine())!= null) { + System.err.println(line); + } } + */ - SocketAddress addr2 = new InetSocketAddress("test.domain.org", 2130); - Proxy proxy2 = new Proxy(Proxy.Type.HTTP, addr2); - Socket sock2 = new Socket(proxy1); + conn.getResponseCode(); + InputStream is = conn.getInputStream(); + String response = ""; + byte[] b = new byte[1024]; + int count = 0; + while ((count = is.read(b)) > 0) { + response += new String(b, 0, count); + } + assertTrue("Response to POST method invalid", response + .equals(posted)); - try { - - Proxy proxyList[] = { proxy1, proxy2 - }; - for (int i = 0; i < proxyList.length; ++i) { - String posted = "just a test"; - URL u = new URL("http://www.test.domain.org:2130"); - java.net.HttpURLConnection conn = (java.net.HttpURLConnection) u - .openConnection(proxyList[i]); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-length", String.valueOf(posted - .length())); - - OutputStream out = conn.getOutputStream(); - out.write(posted.getBytes()); - out.close(); - - conn.getResponseCode(); - InputStream is = conn.getInputStream(); - String response = ""; - byte[] b = new byte[1024]; - int count = 0; - while ((count = is.read(b)) > 0) { - response += new String(b, 0, count); - } - assertTrue("Response to POST method invalid", response - .equals(posted)); - } - - URL httpUrl = new URL("http://abc.com"); - URL jarUrl = new URL("jar:" - + Support_Resources.getResourceURL("/JUC/lf.jar!/plus.bmp")); - URL ftpUrl = new URL("ftp://" + Support_Configuration.FTPTestAddress - + "/nettest.txt"); - URL fileUrl = new URL("file://abc"); - URL[] urlList = { httpUrl, jarUrl, ftpUrl, fileUrl }; - for (int i = 0; i < urlList.length; ++i) { - try { - urlList[i].openConnection(null); - } catch (IllegalArgumentException iae) { - // expected - } + // Exception test + URL httpUrl = new URL("http://abc.com"); + URL jarUrl = new URL("jar:" + + Support_Resources.getResourceURL("/JUC/lf.jar!/plus.bmp")); + URL ftpUrl = new URL("ftp://" + Support_Configuration.FTPTestAddress + + "/nettest.txt"); + URL fileUrl = new URL("file://abc"); + URL[] urlList = { httpUrl, jarUrl, ftpUrl, fileUrl }; + for (int i = 0; i < urlList.length; ++i) { + try { + urlList[i].openConnection(null); + } catch (IllegalArgumentException iae) { + // expected } - // should not throw exception - fileUrl.openConnection(Proxy.NO_PROXY); - } finally { - sock.close(); } + // should not throw exception too + fileUrl.openConnection(Proxy.NO_PROXY); + } /** @@ -1036,21 +1064,30 @@ public class URLTest extends TestCase { InputStream is; String s; - /* throws nullpointer exception: failed or not failed test? Debatable + // Cannot make this test fail if no exception is thrown: Debatable + /* try { u = new URL("http", "www.yahoo.com", 8080, "test.html#foo", null); fail("No error occurred"); } catch (MalformedURLException e) { // ok + } catch (NullPointerException e) { + // ok } */ TestURLStreamHandler lh = new TestURLStreamHandler(); + + u = new URL("http", "www.yahoo.com", 8080, "test.html#foo", + lh); + try { new URL(null, "1", 0, "file", lh); - fail("NullPointerException expected, but nothing was thrown!"); + fail("Exception expected, but nothing was thrown!"); + } catch (MalformedURLException e) { + // ok } catch (NullPointerException e) { // Expected NullPointerException } @@ -1066,37 +1103,42 @@ public class URLTest extends TestCase { method = "getContent", args = {java.lang.Class[].class} ) - @BrokenTest("both RI and android fail on getcontent which returns null.") public void test_getContent_LJavaLangClass() throws Exception { - + File sampleFile = createTempHelloWorldFile(); - + byte[] ba; String s; - u = sampleFile.toURL(); - u.openConnection(); - assertNotNull(u); - - s = (String) u.getContent(new Class[] { String.class }); - assertNotNull(s); - assertTrue("Incorrect content " + u - + " does not contain: \"Hello World\"", - s.indexOf("Hello World") >= 0); - - //Exception test InputStream is = null; - + try { - u = new URL("file:///data/tmp/hyts_htmltest.html"); -// u.openConnection(); - is = (InputStream) u.getContent(new Class[] { InputStream.class }); - is.read(ba = new byte[4096]); - fail("No error occurred reading from nonexisting file"); + u = new URL("file:///data/tmp/hyts_htmltest.html"); + is = (InputStream) u.getContent(new Class[] {InputStream.class}); + is.read(ba = new byte[4096]); + fail("No error occurred reading from nonexisting file"); } catch (IOException e) { - //ok + // ok } - + + try { + u = new URL("file:///data/tmp/hyts_htmltest.html"); + is = (InputStream) u.getContent(new Class[] { + String.class, InputStream.class}); + is.read(ba = new byte[4096]); + fail("No error occurred reading from nonexisting file"); + } catch (IOException e) { + // ok + } + + // Check for null + u = sampleFile.toURL(); + u.openConnection(); + assertNotNull(u); + + s = (String) u.getContent(new Class[] {String.class}); + assertNull(s); + } /** diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java index 8f2cd27..e5e3c11 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/util/AbstractMapTest.java @@ -21,7 +21,6 @@ import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; -import dalvik.annotation.KnownFailure; import java.util.AbstractMap; import java.util.AbstractSet; @@ -405,7 +404,6 @@ public class AbstractMapTest extends junit.framework.TestCase { method = "putAll", args = {java.util.Map.class} ) - @KnownFailure("ToT fixed") public void test_putAllLMap() { Hashtable ht = new Hashtable(); AbstractMap amt = new AMT(); @@ -431,7 +429,6 @@ public class AbstractMapTest extends junit.framework.TestCase { method = "equals", args = {java.lang.Object.class} ) - @KnownFailure("ToT fixed") public void test_equalsLjava_lang_Object() { AbstractMap amt1 = new AMT(); AbstractMap amt2 = new AMT(); diff --git a/luni/src/test/java/tests/TestSuiteFactory.java b/luni/src/test/java/tests/TestSuiteFactory.java index 15d0ea9..4f4a479 100644 --- a/luni/src/test/java/tests/TestSuiteFactory.java +++ b/luni/src/test/java/tests/TestSuiteFactory.java @@ -19,6 +19,7 @@ package tests; import dalvik.annotation.AndroidOnly; import dalvik.annotation.KnownFailure; +import junit.extensions.TestSetup; import junit.framework.AssertionFailedError; import junit.framework.Protectable; import junit.framework.Test; @@ -39,7 +40,7 @@ import java.util.Vector; * a sample command line: * * /usr/lib/jvm/java-1.5.0-sun/bin/java -Xmx1024m -Dcts.listOnlyFailingTests=true - * -Dcts.ignoreKnownFailure=false -Dcts.runOnDalvikVM=false + * -Dcts.includeKnownFailure=false -Dcts.runOnDalvikVM=false * -Dcts.allowUnderscoreTests=false -Dcts.useEnhancedJunit=true * -Dcts.collectOnly=false * -cp @@ -59,8 +60,9 @@ public class TestSuiteFactory { static boolean _useEnhancedJunit = false; static boolean _allowUnderscoreTests = false; static boolean _runOnDalvikVM = true; - static boolean _ignoreKnowFailure = false; + static boolean _includeKnowFailure = false; static boolean _listOnlyFailingTests = false; + static boolean _useSuppliedTestResult = false; static int _maxRunningTimePerTest = 15000; // 15 seconds static { @@ -69,16 +71,17 @@ public class TestSuiteFactory { _collectOnly = System.getProperty("cts.collectOnly", "false").equals("true"); _allowUnderscoreTests= System.getProperty("cts.allowUnderscoreTests", "false").equals("true"); _runOnDalvikVM = System.getProperty("cts.runOnDalvikVM", "true").equals("true"); - _ignoreKnowFailure = System.getProperty("cts.ignoreKnownFailure", "false").equals("true"); + _includeKnowFailure = System.getProperty("cts.includeKnownFailure", "false").equals("true"); _maxRunningTimePerTest = Integer.parseInt(System.getProperty("cts.maxRunningTimePerTest", "15000")); _listOnlyFailingTests = System.getProperty("cts.listOnlyFailingTests", "false").equals("true"); + _useSuppliedTestResult = System.getProperty("cts.useSuppliedTestResult", "false").equals("true"); System.out.println("TestSuiteFactory: v0.97"); System.out.println("TestSuiteFactory: using cts.useEnhancedJunit: "+_useEnhancedJunit); System.out.println("TestSuiteFactory: using cts.collectOnly: "+_collectOnly); System.out.println("TestSuiteFactory: max allowed running time per test (using Thread.stop()) (cts.maxRunningTimePerTest): "+_maxRunningTimePerTest); System.out.println("TestSuiteFactory: run tests on a dalvik vm (cts.runOnDalvikVM): "+_runOnDalvikVM); - System.out.println("TestSuiteFactory: ignore @KnowFailure when running on dalvik vm (cts.ignoreKnownFailure): "+_ignoreKnowFailure); + System.out.println("TestSuiteFactory: include @KnowFailure when running on dalvik vm (cts.includeKnownFailure): "+_includeKnowFailure); System.out.println("TestSuiteFactory: include '_test...' methods in test run (cts.allowUnderscoreTests): "+_allowUnderscoreTests); System.out.println("TestSuiteFactory: list only failing tests (cts.listOnlyFailingTests): "+_listOnlyFailingTests); System.out.println(); @@ -175,7 +178,15 @@ class MyTestSuite extends TestSuite { private static int testCnt = 0; public void runTest(Test test, final TestResult dummy_result) { - TestResult aresult = new TestResult(); + + if (TestSuiteFactory._useSuppliedTestResult) { + if (test instanceof TestSetup) { + test = ((TestSetup)test).getTest(); + } + test.run(dummy_result); + return; + } + TestResult eresult = new TestResult() { private String msg; private boolean error = false; @@ -195,7 +206,7 @@ class MyTestSuite extends TestSuite { // @AndroidOnly("Because...") if the test is Android-specific, succeeds on Android but fails on the JDK. try { Annotation[] annosClass = testcase.getClass().getDeclaredAnnotations(); - Method runMethod= testcase.getClass().getMethod(testcase.getName(), (Class[]) null); + Method runMethod= testcase.getClass().getMethod(testcase.getName()); Annotation[] annosMethod = runMethod.getDeclaredAnnotations(); Annotation[] annos = null; for (int i = 0; i < 2; i++) { @@ -223,7 +234,7 @@ class MyTestSuite extends TestSuite { !TestSuiteFactory._collectOnly && ( (TestSuiteFactory._runOnDalvikVM && - (TestSuiteFactory._ignoreKnowFailure || !knownFailure) + (TestSuiteFactory._includeKnowFailure || !knownFailure) ) || (!TestSuiteFactory._runOnDalvikVM && !androidOnly) @@ -293,7 +304,7 @@ class MyTestSuite extends TestSuite { if (!TestSuiteFactory._runOnDalvikVM && androidOnly) { msg+= "ignoring on RI since @AndroidOnly: "+((AndroidOnly)aAndroidOnly).value(); } - if (TestSuiteFactory._runOnDalvikVM && knownFailure && !TestSuiteFactory._ignoreKnowFailure) { + if (TestSuiteFactory._runOnDalvikVM && knownFailure && !TestSuiteFactory._includeKnowFailure) { msg += "ignoring on dalvik since @KnownFailure: "+((KnownFailure)aKnownFailure).value(); } } diff --git a/luni/src/test/java/tests/api/java/io/BufferedInputStreamTest.java b/luni/src/test/java/tests/api/java/io/BufferedInputStreamTest.java index 6e2076c..d5ab18e 100644 --- a/luni/src/test/java/tests/api/java/io/BufferedInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/BufferedInputStreamTest.java @@ -400,21 +400,21 @@ public class BufferedInputStreamTest extends TestCase { bis.read(new byte[0], -1, -1); fail("should throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) { - //expected + // Expected } try { bis.read(new byte[0], 1, -1); fail("should throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) { - //expected + // Expected } try { bis.read(new byte[0], 1, 1); fail("should throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) { - //expected + // Expected } bis.close(); diff --git a/luni/src/test/java/tests/api/java/io/BufferedOutputStreamTest.java b/luni/src/test/java/tests/api/java/io/BufferedOutputStreamTest.java index fb09643..3b727a5 100644 --- a/luni/src/test/java/tests/api/java/io/BufferedOutputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/BufferedOutputStreamTest.java @@ -165,7 +165,7 @@ public class BufferedOutputStreamTest extends junit.framework.TestCase { method = "write", args = {byte[].class, int.class, int.class} ) - public void test_write_$BII_Exception() throws IOException { + public void test_write$BII_Exception() throws IOException { OutputStream bos = new BufferedOutputStream(new ByteArrayOutputStream()); byte[] nullByteArray = null; byte[] byteArray = new byte[10]; @@ -179,23 +179,23 @@ public class BufferedOutputStreamTest extends junit.framework.TestCase { try { bos.write(byteArray, -1, 1); - fail("Test 2: ArrayIndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException e) { - // Expected. + fail("Test 2: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected } try { bos.write(byteArray, 0, -1); - fail("Test 3: ArrayIndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException e) { - // Expected. + fail("Test 3: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected } try { bos.write(byteArray, 1, 10); - fail("Test 4: ArrayIndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException e) { - // Expected. + fail("Test 4: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected } } diff --git a/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java b/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java index 50bb44e..b1a5755 100644 --- a/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/BufferedReaderTest.java @@ -326,6 +326,39 @@ public class BufferedReaderTest extends junit.framework.TestCase { } catch (IOException e) { fail("Unexpected: " + e); } + } + + /** + * @tests java.io.BufferedReader#read(char[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "The test verifies read(char[] cbuf, int off, int len) method.", + method = "read", + args = {char[].class, int.class, int.class} + ) + public void test_read$CII_Exception() throws Exception { + br = new BufferedReader(new Support_StringReader(testString)); + try{ + br.read(new char[10], -1, 1); + fail("should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + + try{ + br.read(new char[10], 0, -1); + fail("should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + + try{ + br.read(new char[10], 10, 1); + fail("should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected + } //regression for HARMONY-831 try{ diff --git a/luni/src/test/java/tests/api/java/io/BufferedWriterTest.java b/luni/src/test/java/tests/api/java/io/BufferedWriterTest.java index 4c58318..d8ea5a8 100644 --- a/luni/src/test/java/tests/api/java/io/BufferedWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/BufferedWriterTest.java @@ -219,42 +219,42 @@ public class BufferedWriterTest extends junit.framework.TestCase { bw.write(charArray, -1, 0); fail("Test 2: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { bw.write(charArray, 0, -1); fail("Test 3: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { bw.write(charArray, charArray.length + 1, 0); fail("Test 4: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { bw.write(charArray, charArray.length, 1); fail("Test 5: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { bw.write(charArray, 0, charArray.length + 1); fail("Test 6: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { bw.write(charArray, 1, charArray.length); fail("Test 7: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } bw.close(); diff --git a/luni/src/test/java/tests/api/java/io/ByteArrayInputStreamTest.java b/luni/src/test/java/tests/api/java/io/ByteArrayInputStreamTest.java index a9a20d5..eaf4c48 100644 --- a/luni/src/test/java/tests/api/java/io/ByteArrayInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/ByteArrayInputStreamTest.java @@ -19,6 +19,7 @@ package tests.api.java.io; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; @@ -233,21 +234,21 @@ public class ByteArrayInputStreamTest extends junit.framework.TestCase { is.read(buf1 , -1, 1); fail("Test 3: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { is.read(buf1 , 1, -1); fail("Test 4: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { is.read(buf1, 1, buf1.length); fail("Test 5: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } } diff --git a/luni/src/test/java/tests/api/java/io/ByteArrayOutputStreamTest.java b/luni/src/test/java/tests/api/java/io/ByteArrayOutputStreamTest.java index 2848a50..b2a4e21 100644 --- a/luni/src/test/java/tests/api/java/io/ByteArrayOutputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/ByteArrayOutputStreamTest.java @@ -276,31 +276,25 @@ public class ByteArrayOutputStreamTest extends TestCase { try { bos.write(target, -1, 1); fail("Test 1: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { - assertEquals( - "IndexOutOfBoundsException rather than a subclass expected;", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } try { bos.write(target, 0, -1); fail("Test 2: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { - assertEquals( - "IndexOutOfBoundsException rather than a subclass expected;", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } try { bos.write(target, 1, target.length); fail("Test 3: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { - assertEquals( - "IndexOutOfBoundsException rather than a subclass expected;", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } try { bos.write(null, 1, 1); fail("Test 4: NullPointerException expected."); - } catch (NullPointerException t) { + } catch (NullPointerException e) { // Expected. } } diff --git a/luni/src/test/java/tests/api/java/io/CharArrayReaderTest.java b/luni/src/test/java/tests/api/java/io/CharArrayReaderTest.java index 114e32a..e94f74b 100644 --- a/luni/src/test/java/tests/api/java/io/CharArrayReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/CharArrayReaderTest.java @@ -211,21 +211,21 @@ public class CharArrayReaderTest extends junit.framework.TestCase { cr.read(c , -1, 1); fail("Test 3: ArrayIndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { cr.read(c , 1, -1); fail("Test 4: ArrayIndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } try { cr.read(c, 1, c.length); fail("Test 5: ArrayIndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { - // Expected. + // Expected } cr.close(); diff --git a/luni/src/test/java/tests/api/java/io/CharArrayWriterTest.java b/luni/src/test/java/tests/api/java/io/CharArrayWriterTest.java index a398303..5c7d355 100644 --- a/luni/src/test/java/tests/api/java/io/CharArrayWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/CharArrayWriterTest.java @@ -219,28 +219,25 @@ public class CharArrayWriterTest extends junit.framework.TestCase { try { cw.write(target, -1, 1); fail("Test 1: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { - assertEquals("IndexOutOfBoundsException rather than a subclass expected;", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } try { cw.write(target, 0, -1); fail("Test 2: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { - assertEquals("IndexOutOfBoundsException rather than a subclass expected;", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } try { cw.write(target, 1, target.length); fail("Test 3: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { - assertEquals("IndexOutOfBoundsException rather than a subclass expected;", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } try { cw.write((char[]) null, 1, 1); fail("Test 4: NullPointerException expected."); - } catch (NullPointerException t) { + } catch (NullPointerException e) { // Expected. } } diff --git a/luni/src/test/java/tests/api/java/io/DataInputStreamTest.java b/luni/src/test/java/tests/api/java/io/DataInputStreamTest.java index cda04a7..cde968a 100644 --- a/luni/src/test/java/tests/api/java/io/DataInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/DataInputStreamTest.java @@ -112,7 +112,7 @@ public class DataInputStreamTest extends junit.framework.TestCase { * @tests java.io.DataInputStream#read(byte[], int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, method = "read", args = {byte[].class, int.class, int.class} ) @@ -149,6 +149,43 @@ public class DataInputStreamTest extends junit.framework.TestCase { } /** + * @tests java.io.DataInputStream#read(byte[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "read", + args = {byte[].class, int.class, int.class} + ) + public void test_read$BII_Exception() throws IOException { + byte rbytes[] = new byte[testLength - 5]; + + os.write(fileString.getBytes()); + os.close(); + openDataInputStream(); + + try { + dis.read(rbytes, -1, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + + try { + dis.read(rbytes, 0, -1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + + try { + dis.read(rbytes, rbytes.length, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + } + + /** * @tests java.io.DataInputStream#readFully(byte[]) */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/FileOutputStreamTest.java b/luni/src/test/java/tests/api/java/io/FileOutputStreamTest.java index f2773ae..eb14a3c 100644 --- a/luni/src/test/java/tests/api/java/io/FileOutputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/FileOutputStreamTest.java @@ -344,27 +344,37 @@ public class FileOutputStreamTest extends junit.framework.TestCase { try { fos.write(new byte[1], -1, 0); fail("Test 2: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException e) {} + } catch (IndexOutOfBoundsException e) { + // Expected + } try { fos.write(new byte[1], 0, -1); fail("Test 3: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException e) {} + } catch (IndexOutOfBoundsException e) { + // Expected + } try { fos.write(new byte[1], 0, 5); fail("Test 4: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException e) {} + } catch (IndexOutOfBoundsException e) { + // Expected + } try { fos.write(new byte[10], Integer.MAX_VALUE, 5); fail("Test 5: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException e) {} + } catch (IndexOutOfBoundsException e) { + // Expected + } try { fos.write(new byte[10], 5, Integer.MAX_VALUE); fail("Test 6: IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException e) {} + } catch (IndexOutOfBoundsException e) { + // Expected + } fos.close(); try { diff --git a/luni/src/test/java/tests/api/java/io/FileTest.java b/luni/src/test/java/tests/api/java/io/FileTest.java index 817249a..865717e 100644 --- a/luni/src/test/java/tests/api/java/io/FileTest.java +++ b/luni/src/test/java/tests/api/java/io/FileTest.java @@ -2338,7 +2338,7 @@ public class FileTest extends junit.framework.TestCase { ) public void test_toURI2() { - File f = new File(System.getProperty("ctsdir"), "a/b/c/../d/e/./f"); + File f = new File(System.getProperty("java.io.tmpdir"), "a/b/c/../d/e/./f"); String path = f.getAbsolutePath(); path = path.replace(File.separatorChar, '/'); diff --git a/luni/src/test/java/tests/api/java/io/FilterOutputStreamTest.java b/luni/src/test/java/tests/api/java/io/FilterOutputStreamTest.java index 8062ac0..ab0bebc 100644 --- a/luni/src/test/java/tests/api/java/io/FilterOutputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/FilterOutputStreamTest.java @@ -188,6 +188,41 @@ public class FilterOutputStreamTest extends junit.framework.TestCase { } /** + * @tests java.io.FilterOutputStream#write(byte[], int, int) + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "write", + args = {byte[].class, int.class, int.class} + ) + public void test_write$BII_Exception() throws IOException { + Support_OutputStream sos = new Support_OutputStream(testLength); + os = new FilterOutputStream(sos); + byte[] buf = new byte[10]; + + try { + os.write(buf, -1, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + os.write(buf, 0, -1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + os.write(buf, 10, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + + /** * @tests java.io.FilterOutputStream#write(int) */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/FilterReaderTest.java b/luni/src/test/java/tests/api/java/io/FilterReaderTest.java index 3a58e74..14313d0 100644 --- a/luni/src/test/java/tests/api/java/io/FilterReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/FilterReaderTest.java @@ -17,8 +17,10 @@ package tests.api.java.io; +import java.io.ByteArrayInputStream; import java.io.FilterReader; import java.io.IOException; +import java.io.InputStreamReader; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; @@ -161,7 +163,7 @@ public class FilterReaderTest extends junit.framework.TestCase { * @tests java.io.FilterReader#read(char[], int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, notes = "Verifies read(char[], int, int).", method = "read", args = {char[].class, int.class, int.class} @@ -173,6 +175,44 @@ public class FilterReaderTest extends junit.framework.TestCase { } /** + * @tests java.io.FilterReader#read(char[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "Verifies read(char[], int, int).", + method = "read", + args = {char[].class, int.class, int.class} + ) + public void test_read$CII_Exception() throws IOException { + byte[] bbuffer = new byte[20]; + char[] buffer = new char[10]; + + fr = new MyFilterReader(new InputStreamReader( + new ByteArrayInputStream(bbuffer))); + + try { + fr.read(buffer, 0, -1); + fail("Test 1: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + fr.read(buffer, -1, 1); + fail("Test 2: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + fr.read(buffer, 10, 1); + fail("Test 3: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + + /** * @tests java.io.FilterReader#ready() */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/FilterWriterTest.java b/luni/src/test/java/tests/api/java/io/FilterWriterTest.java index 37d6991..6fcb57d 100644 --- a/luni/src/test/java/tests/api/java/io/FilterWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/FilterWriterTest.java @@ -17,8 +17,14 @@ package tests.api.java.io; +import tests.api.java.io.FilterReaderTest.MyFilterReader; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.FilterWriter; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; @@ -147,6 +153,43 @@ public class FilterWriterTest extends junit.framework.TestCase { } /** + * @tests java.io.FilterReader#read(char[], int, int) + */ + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "Verifies write(char[], int, int).", + method = "write", + args = {char[].class, int.class, int.class} + ) + public void test_write$CII_Exception() throws IOException { + char[] buffer = new char[10]; + + fw = new MyFilterWriter(new OutputStreamWriter( + new ByteArrayOutputStream())); + + try { + fw.write(buffer, 0, -1); + fail("Test 1: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + fw.write(buffer, -1, 1); + fail("Test 2: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + fw.write(buffer, 10, 1); + fail("Test 3: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + + /** * @tests java.io.FilterWriter#write(char[], int, int) */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/InputStreamTest.java b/luni/src/test/java/tests/api/java/io/InputStreamTest.java index 40fbc88..0a87df4 100644 --- a/luni/src/test/java/tests/api/java/io/InputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/InputStreamTest.java @@ -200,23 +200,23 @@ public class InputStreamTest extends junit.framework.TestCase { method = "read", args = {byte[].class, int.class, int.class} ) - public void test_read$BII_IllegalArgument() throws IOException { + public void test_read$BII_Exception() throws IOException { byte[] b = new byte[10]; int bytesRead = 0; // Test 1: Invalid offset. try { bytesRead = is.read(b, -1, 5); - fail("Test 1: ArrayIndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException e) { + fail("Test 1: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { // expected } // Test 2: Invalid length. try { bytesRead = is.read(b, 5, -1); - fail("Test 2: ArrayIndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException e) { + fail("Test 2: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { // expected } @@ -224,16 +224,16 @@ public class InputStreamTest extends junit.framework.TestCase { // than the length of b). try { bytesRead = is.read(b, 6, 5); - fail("Test 3: ArrayIndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException e) { + fail("Test 3: IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { // expected } // Test 4: Border case. try { bytesRead = is.read(b, 6, 4); - } catch (ArrayIndexOutOfBoundsException e) { - fail("Test 4: Unexpected ArrayIndexOutOfBoundsException."); + } catch (IndexOutOfBoundsException e) { + fail("Test 4: Unexpected IndexOutOfBoundsException."); } assertEquals("Test 4:", bytesRead, 4); diff --git a/luni/src/test/java/tests/api/java/io/LineNumberInputStreamTest.java b/luni/src/test/java/tests/api/java/io/LineNumberInputStreamTest.java index d95dd74..491def9 100644 --- a/luni/src/test/java/tests/api/java/io/LineNumberInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/LineNumberInputStreamTest.java @@ -152,7 +152,7 @@ public class LineNumberInputStreamTest extends junit.framework.TestCase { * @tests java.io.LineNumberInputStream#read(byte[], int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, method = "read", args = {byte[].class, int.class, int.class} ) @@ -172,6 +172,39 @@ public class LineNumberInputStreamTest extends junit.framework.TestCase { } /** + * @tests java.io.LineNumberInputStream#read(byte[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "read", + args = {byte[].class, int.class, int.class} + ) + public void test_read$BII_Exception() throws IOException { + byte[] buf = new byte[10]; + + try { + lnis.read(buf, -1, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + lnis.read(buf, 0, -1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + lnis.read(buf, 10, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + + /** * @tests java.io.LineNumberInputStream#reset() */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/LineNumberReaderTest.java b/luni/src/test/java/tests/api/java/io/LineNumberReaderTest.java index ace864e..3e1ca4a 100644 --- a/luni/src/test/java/tests/api/java/io/LineNumberReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/LineNumberReaderTest.java @@ -146,7 +146,7 @@ public class LineNumberReaderTest extends junit.framework.TestCase { * @tests java.io.LineNumberReader#read(char[], int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, method = "read", args = {char[].class, int.class, int.class} ) @@ -169,6 +169,40 @@ public class LineNumberReaderTest extends junit.framework.TestCase { } /** + * @tests java.io.LineNumberReader#read(char[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + method = "read", + args = {char[].class, int.class, int.class} + ) + public void test_read$CII_Exception() throws IOException { + lnr = new LineNumberReader(new StringReader(text)); + char[] c = new char[10]; + + try { + lnr.read(c, -1, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + lnr.read(c, 0, -1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + try { + lnr.read(c, 10, 1); + fail("IndexOutOfBoundsException expected."); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + + /** * @tests java.io.LineNumberReader#readLine() */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/ObjectInputStreamTest.java b/luni/src/test/java/tests/api/java/io/ObjectInputStreamTest.java index d091158..2258507 100644 --- a/luni/src/test/java/tests/api/java/io/ObjectInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/ObjectInputStreamTest.java @@ -350,14 +350,36 @@ public class ObjectInputStreamTest extends junit.framework.TestCase implements */ @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "Checks IOException.", + notes = "Checks Exceptions.", method = "read", args = {byte[].class, int.class, int.class} ) - public void test_read$BII_IOException() throws IOException { + public void test_read$BII_Exception() throws IOException { byte[] buf = new byte[testLength]; oos.writeObject(testString); oos.close(); + + ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray())); + try { + ois.read(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + ois.read(buf, -1,1); + fail("IndexOutOfBoundsException was not thrown."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + ois.read(buf, testLength, 1); + fail("IndexOutOfBoundsException was not thrown."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + ois.close(); + Support_ASimpleInputStream sis = new Support_ASimpleInputStream(bao.toByteArray()); ois = new ObjectInputStream(sis); @@ -450,7 +472,7 @@ public class ObjectInputStreamTest extends junit.framework.TestCase implements method = "readFully", args = {byte[].class} ) - public void test_readFully$B_IOException() throws IOException { + public void test_readFully$B_Exception() throws IOException { byte[] buf = new byte[testLength]; oos.writeObject(testString); oos.close(); @@ -502,14 +524,35 @@ public class ObjectInputStreamTest extends junit.framework.TestCase implements */ @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "Checks IOException.", + notes = "Checks Exceptions.", method = "readFully", args = {byte[].class, int.class, int.class} ) - public void test_readFully$BII_IOException() throws IOException { + public void test_readFully$BII_Exception() throws IOException { byte[] buf = new byte[testLength]; oos.writeObject(testString); oos.close(); + + ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray())); + try { + ois.readFully(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + ois.readFully(buf, -1,1); + fail("IndexOutOfBoundsException was not thrown."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + ois.readFully(buf, testLength, 1); + fail("IndexOutOfBoundsException was not thrown."); + } catch (IndexOutOfBoundsException e) { + // Expected + } + ois.close(); Support_ASimpleInputStream sis = new Support_ASimpleInputStream(bao.toByteArray()); ois = new ObjectInputStream(sis); diff --git a/luni/src/test/java/tests/api/java/io/ObjectOutputStreamTest.java b/luni/src/test/java/tests/api/java/io/ObjectOutputStreamTest.java index 51ac740..e8042ca 100644 --- a/luni/src/test/java/tests/api/java/io/ObjectOutputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/ObjectOutputStreamTest.java @@ -1032,6 +1032,28 @@ public class ObjectOutputStreamTest extends junit.framework.TestCase implements ois.close(); assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0, 10)); + + ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray())); + try { + ois.read(buf, 0, -1); + fail("IndexOutOfBoundsException not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + ois.read(buf, -1, 1); + fail("IndexOutOfBoundsException not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + ois.read(buf, 10, 1); + fail("IndexOutOfBoundsException not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + ois.close(); + } /** diff --git a/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java b/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java index 89f6bef..1f35f97 100644 --- a/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; +import dalvik.annotation.BrokenTest; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; import dalvik.annotation.TestTargetNew; @@ -383,31 +384,25 @@ public class PipedInputStreamTest extends junit.framework.TestCase { public void test_read$BII_3() throws IOException { PipedInputStream obj = new PipedInputStream(); try { - obj.read(new byte[0], -1, 0); + obj.read(new byte[10], -1, 1); fail("IndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException t) { - fail("IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { + // Expected + assertTrue(e.getClass().equals(IndexOutOfBoundsException.class)); } - } - - /** - * @tests java.io.PipedInputStream#read(byte[], int, int) - */ - @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "Tests invalid combination of offset and length arguments.", - method = "read", - args = {byte[].class, int.class, int.class} - ) - public void test_read$BII_4() throws IOException { - PipedInputStream obj = new PipedInputStream(); try { - obj.read(new byte[10], 2, 9); + obj.read(new byte[10], 0, -1); fail("IndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { + // Expected + assertTrue(e.getClass().equals(IndexOutOfBoundsException.class)); + } + try { + obj.read(new byte[10], 9, 2); fail("IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { + // Expected + assertTrue(e.getClass().equals(IndexOutOfBoundsException.class)); } } @@ -420,6 +415,7 @@ public class PipedInputStreamTest extends junit.framework.TestCase { method = "receive", args = {int.class} ) + @BrokenTest("Test hangs indefinitely on the RI") public void test_receive() throws IOException { pis = new PipedInputStream(); pos = new PipedOutputStream(); diff --git a/luni/src/test/java/tests/api/java/io/PipedOutputStreamTest.java b/luni/src/test/java/tests/api/java/io/PipedOutputStreamTest.java index 19c1f95..44d7e27 100644 --- a/luni/src/test/java/tests/api/java/io/PipedOutputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/PipedOutputStreamTest.java @@ -259,6 +259,7 @@ public class PipedOutputStreamTest extends junit.framework.TestCase { } out.close(); + out = new PipedOutputStream(); try { rt = new Thread(reader = new PReader(out)); rt.start(); @@ -270,16 +271,6 @@ public class PipedOutputStreamTest extends junit.framework.TestCase { fail("Test 5: Unexpected IOException: " + e.getMessage()); } -/* Test disabled due to incomplete implementation, see ticket #92. - rt.interrupt(); - - try { - out.write(testString.getBytes(), 0, 5); - fail("Test 6: IOException expected."); - } catch (IOException e) { - // Expected. - } -*/ reader.getReader().close(); try { out.write(testString.getBytes(), 0, 5); diff --git a/luni/src/test/java/tests/api/java/io/PipedReaderTest.java b/luni/src/test/java/tests/api/java/io/PipedReaderTest.java index f1d8ea8..f67790b 100644 --- a/luni/src/test/java/tests/api/java/io/PipedReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/PipedReaderTest.java @@ -298,81 +298,28 @@ public class PipedReaderTest extends junit.framework.TestCase { method = "read", args = {char[].class, int.class, int.class} ) - public void test_read$CII_2() throws IOException{ + public void test_read$CII_Exception() throws IOException{ PipedWriter pw = new PipedWriter(); - PipedReader obj = null; + PipedReader obj = new PipedReader(pw); try { - obj = new PipedReader(pw); - obj.read(new char[0], 0, -1); + obj.read(new char[10], 0, -1); fail("IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { // Expected. - assertEquals( - "IndexOutOfBoundsException rather than a subclass expected.", - IndexOutOfBoundsException.class, t.getClass()); } - } - - /** - * @tests java.io.PipedReader#read(char[], int, int) - */ - @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "", - method = "read", - args = {char[].class, int.class, int.class} - ) - public void test_read$CII_3() throws IOException { - PipedWriter pw = new PipedWriter(); - PipedReader obj = null; try { - obj = new PipedReader(pw); - obj.read(new char[0], -1, 0); - fail("IndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException t) { + obj.read(new char[10], -1, 1); fail("IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { // Expected. - } - } - - /** - * @tests java.io.PipedReader#read(char[], int, int) - */ - @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "", - method = "read", - args = {char[].class, int.class, int.class} - ) - public void test_read$CII_4() throws IOException { - PipedWriter pw = new PipedWriter(); - PipedReader obj = null; + } try { - obj = new PipedReader(pw); obj.read(new char[10], 2, 9); fail("IndexOutOfBoundsException expected."); - } catch (ArrayIndexOutOfBoundsException t) { - fail("IndexOutOfBoundsException expected."); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { // Expected. } - } - - /** - * @tests java.io.PipedReader#read(char[], int, int) - */ - @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "", - method = "read", - args = {char[].class, int.class, int.class} - ) - public void test_read$CII_5() throws IOException{ - PipedWriter pw = new PipedWriter(); - PipedReader obj = null; try { - obj = new PipedReader(pw); obj.read(null, 0, 1); fail("NullPointerException expected."); } catch (NullPointerException e) { @@ -389,7 +336,7 @@ public class PipedReaderTest extends junit.framework.TestCase { method = "read", args = {} ) - public void test_read$CII_6() throws Exception { + public void test_read$CII_2() throws Exception { Thread writerThread; PipedWriter pw; PWriter2 pwriter; diff --git a/luni/src/test/java/tests/api/java/io/PipedWriterTest.java b/luni/src/test/java/tests/api/java/io/PipedWriterTest.java index c51c353..263d9b2 100644 --- a/luni/src/test/java/tests/api/java/io/PipedWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/PipedWriterTest.java @@ -17,6 +17,7 @@ package tests.api.java.io; +import dalvik.annotation.BrokenTest; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -256,13 +257,10 @@ public class PipedWriterTest extends junit.framework.TestCase { pw = new PipedWriter(new PipedReader()); try { - pw.write(testBuf, -1, 10); + pw.write(testBuf, -1, 1); fail("Test 2: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { // Expected. - assertEquals( - "Test 2: IndexOutOfBoundsException rather than a subclass expected.", - IndexOutOfBoundsException.class, e.getClass()); } try { @@ -270,9 +268,6 @@ public class PipedWriterTest extends junit.framework.TestCase { fail("Test 3: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { // Expected. - assertEquals( - "Test 3: IndexOutOfBoundsException rather than a subclass expected.", - IndexOutOfBoundsException.class, e.getClass()); } try { @@ -280,9 +275,6 @@ public class PipedWriterTest extends junit.framework.TestCase { fail("Test 4: IndexOutOfBoundsException expected."); } catch (IndexOutOfBoundsException e) { // Expected. - assertEquals( - "Test 4: IndexOutOfBoundsException rather than a subclass expected.", - IndexOutOfBoundsException.class, e.getClass()); } pw.close(); @@ -326,6 +318,7 @@ public class PipedWriterTest extends junit.framework.TestCase { method = "write", args = {char[].class, int.class, int.class} ) + @BrokenTest("Hangs on RI") public void test_write$CII_MultiThread() throws Exception { final PipedReader pr = new PipedReader(); final PipedWriter pw = new PipedWriter(); @@ -429,6 +422,7 @@ public class PipedWriterTest extends junit.framework.TestCase { method = "write", args = {int.class} ) + @BrokenTest("Hangs on RI") public void test_writeI_MultiThread() throws IOException { final PipedReader pr = new PipedReader(); final PipedWriter pw = new PipedWriter(); diff --git a/luni/src/test/java/tests/api/java/io/PrintStreamTest.java b/luni/src/test/java/tests/api/java/io/PrintStreamTest.java index db0e142..ccc0bc1 100644 --- a/luni/src/test/java/tests/api/java/io/PrintStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/PrintStreamTest.java @@ -815,6 +815,27 @@ public class PrintStreamTest extends junit.framework.TestCase { bis.read(rbytes, 0, fileString.length()); assertTrue("Incorrect bytes written", new String(rbytes, 0, fileString .length()).equals(fileString)); + + try { + os.write(rbytes, -1, 1); + fail("IndexOutOfBoundsException should have been thrown."); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + os.write(rbytes, 0, -1); + fail("IndexOutOfBoundsException should have been thrown."); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + os.write(rbytes, 1, rbytes.length); + fail("IndexOutOfBoundsException should have been thrown."); + } catch (IndexOutOfBoundsException e) { + // expected + } } /** diff --git a/luni/src/test/java/tests/api/java/io/PrintWriterTest.java b/luni/src/test/java/tests/api/java/io/PrintWriterTest.java index 9957f0b..2796e7b 100644 --- a/luni/src/test/java/tests/api/java/io/PrintWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/PrintWriterTest.java @@ -843,7 +843,7 @@ public class PrintWriterTest extends junit.framework.TestCase { * @tests java.io.PrintWriter#write(char[], int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "write", args = {char[].class, int.class, int.class} @@ -867,6 +867,38 @@ public class PrintWriterTest extends junit.framework.TestCase { } /** + * @tests java.io.PrintWriter#write(char[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class, int.class, int.class} + ) + public void test_write$CII_Exception() { + // Test for method void java.io.PrintWriter.write(char [], int, int) + char[] chars = new char[10]; + try { + pw.write(chars, 0, -1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + pw.write(chars, -1, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + pw.write(chars, 10, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + } + + /** * @tests java.io.PrintWriter#write(int) */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/PushbackInputStreamTest.java b/luni/src/test/java/tests/api/java/io/PushbackInputStreamTest.java index 267fbaa..8625664 100644 --- a/luni/src/test/java/tests/api/java/io/PushbackInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/PushbackInputStreamTest.java @@ -181,7 +181,7 @@ public class PushbackInputStreamTest extends junit.framework.TestCase { * @tests java.io.PushbackInputStream#read(byte[], int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "read", args = {byte[].class, int.class, int.class} @@ -204,6 +204,40 @@ public class PushbackInputStreamTest extends junit.framework.TestCase { } /** + * @tests java.io.PushbackInputStream#read(byte[], int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "read", + args = {byte[].class, int.class, int.class} + ) + public void test_read$BII_Exception() throws IOException { + PushbackInputStream tobj; + byte[] buf = new byte[10]; + + tobj = new PushbackInputStream(underlying); + try { + tobj.read(buf, -1, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + tobj.read(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + tobj.read(buf, 10, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + } + + /** * @tests java.io.PushbackInputStream#skip(long) */ @TestTargetNew( @@ -344,6 +378,30 @@ public class PushbackInputStreamTest extends junit.framework.TestCase { } catch (IOException e) { fail("IOException during unread test : " + e.getMessage()); } + + try { + byte[] buf = new byte[10]; + pis.unread(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + + try { + byte[] buf = new byte[10]; + pis.unread(buf, -1, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + + try { + byte[] buf = new byte[10]; + pis.unread(buf, 10, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } } /** diff --git a/luni/src/test/java/tests/api/java/io/PushbackReaderTest.java b/luni/src/test/java/tests/api/java/io/PushbackReaderTest.java index 5c13663..12ffce7 100644 --- a/luni/src/test/java/tests/api/java/io/PushbackReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/PushbackReaderTest.java @@ -593,11 +593,23 @@ public class PushbackReaderTest extends junit.framework.TestCase { public void test_unread_$CII_ArrayIndexOutOfBoundsException() throws IOException { //a pushback reader with one character buffer pbr = new PushbackReader(new StringReader(pbString)); - + + try { + pbr.unread(new char[pbString.length()], -1 , 1); + fail("should throw ArrayIndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // expected + } try { - pbr.unread(new char[pbString.length()], -1 , -1); + pbr.unread(new char[pbString.length()], 0 , -1); fail("should throw ArrayIndexOutOfBoundsException"); - } catch (ArrayIndexOutOfBoundsException e) { + } catch (IndexOutOfBoundsException e) { + // expected + } + try { + pbr.unread(new char[10], 10 , 1); + fail("should throw ArrayIndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { // expected } } diff --git a/luni/src/test/java/tests/api/java/io/SequenceInputStreamTest.java b/luni/src/test/java/tests/api/java/io/SequenceInputStreamTest.java index 2ddfb42..f05507e 100644 --- a/luni/src/test/java/tests/api/java/io/SequenceInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/SequenceInputStreamTest.java @@ -299,7 +299,7 @@ public class SequenceInputStreamTest extends junit.framework.TestCase { method = "read", args = {byte[].class, int.class, int.class} ) - public void test_read$BII_exc() throws IOException { + public void test_read$BII_Excpetion() throws IOException { byte[] buf = new byte[4]; si.read(buf, 0, 2); si.read(buf, 2, 1); @@ -313,6 +313,29 @@ public class SequenceInputStreamTest extends junit.framework.TestCase { } catch (IOException e) { // expected } + + buf = new byte[10]; + simple1 = new Support_ASimpleInputStream(s1); + simple2 = new Support_ASimpleInputStream(s2); + si = new SequenceInputStream(simple1, simple2); + try { + si.read(buf, -1, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + si.read(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + si.read(buf, 1, 10); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } } /** diff --git a/luni/src/test/java/tests/api/java/io/SerializationStressTest.java b/luni/src/test/java/tests/api/java/io/SerializationStressTest.java index 0bbf205..7c4d0b1 100644 --- a/luni/src/test/java/tests/api/java/io/SerializationStressTest.java +++ b/luni/src/test/java/tests/api/java/io/SerializationStressTest.java @@ -165,41 +165,47 @@ public class SerializationStressTest extends junit.framework.TestCase implements "S-TEST"); static final Calendar CALENDAR = new GregorianCalendar(TIME_ZONE); + + static Exception INITIALIZE_EXCEPTION = null; static { - TABLE.put("one", "1"); - TABLE.put("two", "2"); - TABLE.put("three", "3"); - MAP.put("one", "1"); - MAP.put("two", "2"); - MAP.put("three", "3"); - LINKEDMAP.put("one", "1"); - LINKEDMAP.put("two", "2"); - LINKEDMAP.put("three", "3"); - IDENTITYMAP.put("one", "1"); - IDENTITYMAP.put("two", "2"); - IDENTITYMAP.put("three", "3"); - LINKEDSET.add("one"); - LINKEDSET.add("two"); - LINKEDSET.add("three"); - TREE.put("one", "1"); - TREE.put("two", "2"); - TREE.put("three", "3"); - PERMCOL.add(PERM); - // To make sure they all use the same Calendar - CALENDAR.setTimeZone(new SimpleTimeZone(0, "GMT")); - CALENDAR.set(1999, Calendar.JUNE, 23, 15, 47, 13); - CALENDAR.set(Calendar.MILLISECOND, 553); - DATEFORM.setCalendar(CALENDAR); - java.text.DateFormatSymbols symbols = new java.text.DateFormatSymbols(); - symbols.setZoneStrings(new String[][] { { "a", "b", "c", "d" }, - { "e", "f", "g", "h" } }); - ((java.text.SimpleDateFormat) DATEFORM).setDateFormatSymbols(symbols); - DATEFORM.setNumberFormat(new java.text.DecimalFormat("#.#;'-'#.#")); - DATEFORM.setTimeZone(TimeZone.getTimeZone("EST")); - ((java.text.DecimalFormat) NUMBERFORM).applyPattern("#.#;'-'#.#"); - MESSAGE.setFormat(0, DATEFORM); - MESSAGE.setFormat(1, DATEFORM); + try { + TABLE.put("one", "1"); + TABLE.put("two", "2"); + TABLE.put("three", "3"); + MAP.put("one", "1"); + MAP.put("two", "2"); + MAP.put("three", "3"); + LINKEDMAP.put("one", "1"); + LINKEDMAP.put("two", "2"); + LINKEDMAP.put("three", "3"); + IDENTITYMAP.put("one", "1"); + IDENTITYMAP.put("two", "2"); + IDENTITYMAP.put("three", "3"); + LINKEDSET.add("one"); + LINKEDSET.add("two"); + LINKEDSET.add("three"); + TREE.put("one", "1"); + TREE.put("two", "2"); + TREE.put("three", "3"); + PERMCOL.add(PERM); + // To make sure they all use the same Calendar + CALENDAR.setTimeZone(new SimpleTimeZone(0, "GMT")); + CALENDAR.set(1999, Calendar.JUNE, 23, 15, 47, 13); + CALENDAR.set(Calendar.MILLISECOND, 553); + DATEFORM.setCalendar(CALENDAR); + java.text.DateFormatSymbols symbols = new java.text.DateFormatSymbols(); + symbols.setZoneStrings(new String[][] { { "a", "b", "c", "d" }, + { "e", "f", "g", "h" } }); + ((java.text.SimpleDateFormat) DATEFORM).setDateFormatSymbols(symbols); + DATEFORM.setNumberFormat(new java.text.DecimalFormat("#.#;'-'#.#")); + DATEFORM.setTimeZone(TimeZone.getTimeZone("EST")); + ((java.text.DecimalFormat) NUMBERFORM).applyPattern("#.#;'-'#.#"); + MESSAGE.setFormat(0, DATEFORM); + MESSAGE.setFormat(1, DATEFORM); + } catch (Exception e) { + INITIALIZE_EXCEPTION = e; + } } public SerializationStressTest() { @@ -256,6 +262,9 @@ public class SerializationStressTest extends junit.framework.TestCase implements * is called before a test is executed. */ protected void setUp() { + if (INITIALIZE_EXCEPTION != null) { + throw new ExceptionInInitializerError(INITIALIZE_EXCEPTION); + } try { if (xdump) { oos = new ObjectOutputStream(new FileOutputStream(xFileName diff --git a/luni/src/test/java/tests/api/java/io/SerializationStressTest1.java b/luni/src/test/java/tests/api/java/io/SerializationStressTest1.java index 8327660..b4d8677 100644 --- a/luni/src/test/java/tests/api/java/io/SerializationStressTest1.java +++ b/luni/src/test/java/tests/api/java/io/SerializationStressTest1.java @@ -358,10 +358,6 @@ public class SerializationStressTest1 extends SerializationStressTest { } } - public SerializationStressTest1(String name) { - super(name); - } - @TestTargetNew( level = TestLevel.COMPLETE, notes = "Verifies serialization.", diff --git a/luni/src/test/java/tests/api/java/io/SerializationStressTest2.java b/luni/src/test/java/tests/api/java/io/SerializationStressTest2.java index ba998d8..989469c 100644 --- a/luni/src/test/java/tests/api/java/io/SerializationStressTest2.java +++ b/luni/src/test/java/tests/api/java/io/SerializationStressTest2.java @@ -804,10 +804,6 @@ public class SerializationStressTest2 extends SerializationStressTest { } } - public SerializationStressTest2(String name) { - super(name); - } - @TestTargetNew( level = TestLevel.COMPLETE, notes = "Verifies serialization.", diff --git a/luni/src/test/java/tests/api/java/io/SerializationStressTest3.java b/luni/src/test/java/tests/api/java/io/SerializationStressTest3.java index 0b8c38d..f3617a3 100644 --- a/luni/src/test/java/tests/api/java/io/SerializationStressTest3.java +++ b/luni/src/test/java/tests/api/java/io/SerializationStressTest3.java @@ -358,10 +358,6 @@ public class SerializationStressTest3 extends SerializationStressTest { } } - public SerializationStressTest3(String name) { - super(name); - } - @TestTargetNew( level = TestLevel.COMPLETE, notes = "Verifies serialization.", diff --git a/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java b/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java index b06a457..1ec1211 100644 --- a/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java +++ b/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java @@ -65,10 +65,6 @@ public class SerializationStressTest4 extends SerializationStressTest { } } - public SerializationStressTest4(String name) { - super(name); - } - @TestTargetNew( level = TestLevel.COMPLETE, notes = "Verifies serialization.", diff --git a/luni/src/test/java/tests/api/java/io/SerializationStressTest5.java b/luni/src/test/java/tests/api/java/io/SerializationStressTest5.java index 0f139a3..7b515d9 100644 --- a/luni/src/test/java/tests/api/java/io/SerializationStressTest5.java +++ b/luni/src/test/java/tests/api/java/io/SerializationStressTest5.java @@ -59,10 +59,6 @@ public class SerializationStressTest5 extends SerializationStressTest { { new Integer(5), new Boolean(false), new Boolean(false), new Integer(5), new Integer(5) }, {} }; - public SerializationStressTest5(String name) { - super(name); - } - @TestTargetNew( level = TestLevel.ADDITIONAL, notes = "", diff --git a/luni/src/test/java/tests/api/java/io/StringBufferInputStreamTest.java b/luni/src/test/java/tests/api/java/io/StringBufferInputStreamTest.java index 219d445..bf6b11a 100644 --- a/luni/src/test/java/tests/api/java/io/StringBufferInputStreamTest.java +++ b/luni/src/test/java/tests/api/java/io/StringBufferInputStreamTest.java @@ -66,7 +66,7 @@ public class StringBufferInputStreamTest extends junit.framework.TestCase { * @tests java.io.StringBufferInputStream#read() */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "read", args = {byte[].class, int.class, int.class} @@ -80,6 +80,38 @@ public class StringBufferInputStreamTest extends junit.framework.TestCase { } /** + * @tests java.io.StringBufferInputStream#read() + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "read", + args = {byte[].class, int.class, int.class} + ) + public void test_read$BII_Exception() { + // Test for method int java.io.StringBufferInputStream.read() + byte[] buf = new byte[10]; + try { + sbis.read(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + sbis.read(buf, -1, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + sbis.read(buf, 10, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + } + + /** * @tests java.io.StringBufferInputStream#read(byte[], int, int) */ @TestTargetNew( diff --git a/luni/src/test/java/tests/api/java/io/StringReaderTest.java b/luni/src/test/java/tests/api/java/io/StringReaderTest.java index 9cd9293..b0fa469 100644 --- a/luni/src/test/java/tests/api/java/io/StringReaderTest.java +++ b/luni/src/test/java/tests/api/java/io/StringReaderTest.java @@ -147,7 +147,7 @@ public class StringReaderTest extends junit.framework.TestCase { method = "read", args = {char[].class, int.class, int.class} ) - public void test_read$CII() { + public void test_read$CII() throws Exception { // Test for method int java.io.StringReader.read(char [], int, int) try { sr = new StringReader(testString); @@ -159,6 +159,27 @@ public class StringReaderTest extends junit.framework.TestCase { } catch (Exception e) { fail("Exception during read test : " + e.getMessage()); } + + char[] buf = new char[testString.length()]; + sr = new StringReader(testString); + try { + sr.read(buf, 0, -1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + sr.read(buf, -1, 1); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } + try { + sr.read(buf, 1, testString.length()); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) { + // Expected + } } /** diff --git a/luni/src/test/java/tests/api/java/io/StringWriterTest.java b/luni/src/test/java/tests/api/java/io/StringWriterTest.java index 980526d..1436b1e 100644 --- a/luni/src/test/java/tests/api/java/io/StringWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/StringWriterTest.java @@ -150,58 +150,27 @@ public class StringWriterTest extends junit.framework.TestCase { method = "write", args = {char[].class, int.class, int.class} ) - public void test_write$CII_2() { - StringWriter obj = null; + public void test_write$CII_Exception() { + StringWriter obj = new StringWriter(); try { - obj = new StringWriter(); - obj.write(new char[0], (int) 0, (int) -1); + obj.write(new char[10], 0, -1); fail("IndexOutOfBoundsException expected"); - } catch (IndexOutOfBoundsException t) { - assertEquals( - "IndexOutOfBoundsException rather than a subclass expected", - IndexOutOfBoundsException.class, t.getClass()); + } catch (IndexOutOfBoundsException e) { + // Expected } - } - /** - * @tests java.io.StringWriter#write(char[], int, int) - */ - @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "", - method = "write", - args = {char[].class, int.class, int.class} - ) - public void test_write$CII_3() { - StringWriter obj = null; try { - obj = new StringWriter(); - obj.write(new char[0], (int) -1, (int) 0); - fail("IndexOutOfBoundsException expected"); - } catch (ArrayIndexOutOfBoundsException t) { + obj.write(new char[10], -1, 1); fail("IndexOutOfBoundsException expected"); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { + // Expected } - } - /** - * @tests java.io.StringWriter#write(char[], int, int) - */ - @TestTargetNew( - level = TestLevel.PARTIAL_COMPLETE, - notes = "", - method = "write", - args = {char[].class, int.class, int.class} - ) - public void test_write$CII_4() { - StringWriter obj = null; try { - obj = new StringWriter(); - obj.write(new char[0], (int) -1, (int) -1); - fail("IndexOutOfBoundsException expected"); - } catch (ArrayIndexOutOfBoundsException t) { + obj.write(new char[10], 2, 9); fail("IndexOutOfBoundsException expected"); - } catch (IndexOutOfBoundsException t) { + } catch (IndexOutOfBoundsException e) { + // Expected } } diff --git a/luni/src/test/java/tests/api/java/io/WriterTest.java b/luni/src/test/java/tests/api/java/io/WriterTest.java index 4c6f98f..2a15c67 100644 --- a/luni/src/test/java/tests/api/java/io/WriterTest.java +++ b/luni/src/test/java/tests/api/java/io/WriterTest.java @@ -87,10 +87,10 @@ public class WriterTest extends TestCase { * @tests java.io.Writer#append(CharSequence, int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "append", - args = {java.lang.CharSequence.class, int.class, int.class} + args = {CharSequence.class, int.class, int.class} ) public void test_appendCharSequenceIntInt() throws IOException { String testString = "My Test String"; @@ -123,6 +123,38 @@ public class WriterTest extends TestCase { } } + /** + * @tests java.io.Writer#append(CharSequence, int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "append", + args = {CharSequence.class, int.class, int.class} + ) + public void test_appendCharSequenceIntInt_Exception() throws IOException { + String testString = "My Test String"; + Writer tobj = new Support_ASimpleWriter(21); + try { + tobj.append(testString, 30, 31); + fail("IndexOutOfBoundsException not thrown!"); + } catch (IndexOutOfBoundsException e) { + // expected + } + try { + tobj.append(testString, -1, 1); + fail("IndexOutOfBoundsException not thrown!"); + } catch (IndexOutOfBoundsException e) { + // expected + } + try { + tobj.append(testString, 0, -1); + fail("IndexOutOfBoundsException not thrown!"); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + @TestTargetNew( level = TestLevel.COMPLETE, @@ -193,10 +225,10 @@ public class WriterTest extends TestCase { * @tests java.io.PrintWriter#write(java.lang.String, int, int) */ @TestTargetNew( - level = TestLevel.COMPLETE, + level = TestLevel.PARTIAL_COMPLETE, notes = "", method = "write", - args = {java.lang.String.class, int.class, int.class} + args = {String.class, int.class, int.class} ) public void test_writeLjava_lang_StringII() throws IOException { String testString; @@ -222,7 +254,38 @@ public class WriterTest extends TestCase { // expected } } - + + /** + * @tests java.io.Writer#append(CharSequence, int, int) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {String.class, int.class, int.class} + ) + public void test_writeLjava_lang_StringII_Exception() throws IOException { + String testString = "My Test String"; + Writer tobj = new Support_ASimpleWriter(21); + try { + tobj.write(testString, 30, 31); + fail("IndexOutOfBoundsException not thrown!"); + } catch (IndexOutOfBoundsException e) { + // expected + } + try { + tobj.write(testString, -1, 1); + fail("IndexOutOfBoundsException not thrown!"); + } catch (IndexOutOfBoundsException e) { + // expected + } + try { + tobj.write(testString, 0, -1); + fail("IndexOutOfBoundsException not thrown!"); + } catch (IndexOutOfBoundsException e) { + // expected + } + } class MockWriter extends Writer { private char[] contents; diff --git a/luni/src/test/java/tests/api/java/lang/ProcessManagerTest.java b/luni/src/test/java/tests/api/java/lang/ProcessManagerTest.java index e1a2cfc..8a6da3b 100644 --- a/luni/src/test/java/tests/api/java/lang/ProcessManagerTest.java +++ b/luni/src/test/java/tests/api/java/lang/ProcessManagerTest.java @@ -251,5 +251,5 @@ public class ProcessManagerTest extends TestCase { String[] commands = { "doesnotexist" }; Runtime.getRuntime().exec(commands, null, null); } catch (IOException e) { /* expected */ } - } -}
\ No newline at end of file + } +} diff --git a/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java b/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java index 03375a5..0a32139 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/ReferenceQueueTest.java @@ -247,11 +247,11 @@ public class ReferenceQueueTest extends junit.framework.TestCase { try { rq.remove(-1); - fail("IllegalArgumentException was not thrown."); + fail("IllegalArgumentException expected."); } catch(IllegalArgumentException iae) { //expected } catch (InterruptedException e) { - fail("InterruptedException was not thrown."); + fail("Unexpected InterruptedException."); } } diff --git a/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java b/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java index f571b63..68284ef 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/ReferenceTest.java @@ -252,13 +252,17 @@ public class ReferenceTest extends junit.framework.TestCase { @TestTargets({ @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "Makes sure that overridden versions of clear() and enqueue() get called, and that clear/enqueue/finalize happen in the right order for WeakReferences.", + notes = "Makes sure that overridden versions of clear() and enqueue() " + + "get called, and that clear/enqueue/finalize happen in the " + + "right order for WeakReferences.", method = "clear", args = {} ), @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "Makes sure that overridden versions of clear() and enqueue() get called, and that clear/enqueue/finalize happen in the right order for WeakReferences.", + notes = "Makes sure that overridden versions of clear() and enqueue() " + + "get called, and that clear/enqueue/finalize happen in the " + + "right order for WeakReferences.", method = "enqueue", args = {} ) @@ -388,7 +392,10 @@ public class ReferenceTest extends junit.framework.TestCase { */ @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "Contrives a situation where the only reference to a string is a WeakReference from an object that is being finalized. Checks to make sure that the referent of the WeakReference is still pointing to a valid object.", + notes = "Contrives a situation where the only reference to a string " + + "is a WeakReference from an object that is being finalized. " + + "Checks to make sure that the referent of the WeakReference " + + "is still pointing to a valid object.", method = "get", args = {} ) @@ -434,7 +441,7 @@ public class ReferenceTest extends junit.framework.TestCase { t.join(); System.gc(); System.runFinalization(); - + Thread.sleep(1000); if (error != null) { throw error; } diff --git a/luni/src/test/java/tests/api/java/lang/reflect/AccessibleObjectTest.java b/luni/src/test/java/tests/api/java/lang/reflect/AccessibleObjectTest.java index 0fd60b0..f1c7026 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/AccessibleObjectTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/AccessibleObjectTest.java @@ -17,7 +17,6 @@ package tests.api.java.lang.reflect; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -168,7 +167,6 @@ public class AccessibleObjectTest extends junit.framework.TestCase { method = "getAnnotation", args = {java.lang.Class.class} ) - @KnownFailure("Does not throw NPE if argument is null. Fixed in ToT") public void test_getAnnotation() throws Exception{ AccessibleObject ao = SubTestClass.class.getMethod("annotatedMethod"); //test error case @@ -238,7 +236,6 @@ public class AccessibleObjectTest extends junit.framework.TestCase { method = "isAnnotationPresent", args = {java.lang.Class.class} ) - @KnownFailure("Does not throw NPE if argument is null. Fixed in ToT") public void test_isAnnotationPresent() throws Exception { AccessibleObject ao = SubTestClass.class.getMethod("annotatedMethod"); assertTrue("Missing @AnnotationRuntime0", diff --git a/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java b/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java index 9d6d39c..6bdb55a 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java @@ -17,7 +17,6 @@ package tests.api.java.lang.reflect; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; @@ -217,7 +216,6 @@ public class ConstructorTest extends junit.framework.TestCase { method = "toGenericString", args = {} ) - @KnownFailure("Generic string does not contain declared exception types. Fixed in ToT.") public void test_toGenericString() throws Exception { Constructor<GenericConstructorTestHelper> genericCtor = GenericConstructorTestHelper.class .getConstructor(Object.class, Object.class); @@ -471,7 +469,6 @@ public class ConstructorTest extends junit.framework.TestCase { args = {} ) @SuppressWarnings("unchecked") - @KnownFailure("Does not return any declared exception types. Fixed in ToT.") public void test_getGenericExceptionTypes() { Type[] types = null; diff --git a/luni/src/test/java/tests/api/java/lang/reflect/FieldTest.java b/luni/src/test/java/tests/api/java/lang/reflect/FieldTest.java index 8e693cf..460cf66 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/FieldTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/FieldTest.java @@ -17,7 +17,6 @@ package tests.api.java.lang.reflect; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; @@ -2130,7 +2129,6 @@ public class FieldTest extends junit.framework.TestCase { method = "hashCode", args = {} ) - @KnownFailure("Spec and code is not conform with other well-established implementation. Fixed in ToT.") public void test_hashCode() throws Exception { Field field = TestClass.class.getDeclaredField("annotatedField"); assertEquals("Wrong hashCode returned", field.getName().hashCode() diff --git a/luni/src/test/java/tests/api/java/lang/reflect/GenericSignatureFormatErrorTest.java b/luni/src/test/java/tests/api/java/lang/reflect/GenericSignatureFormatErrorTest.java index f61cd29..eb5cead 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/GenericSignatureFormatErrorTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/GenericSignatureFormatErrorTest.java @@ -1,5 +1,6 @@ package tests.api.java.lang.reflect; +import dalvik.annotation.AndroidOnly; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; import dalvik.annotation.TestTargetNew; @@ -36,7 +37,9 @@ public class GenericSignatureFormatErrorTest extends TestCase{ ) public void test_readResource() throws Exception { File tf = File.createTempFile("classes", ".dex"); - System.out.println("GenericSignatureFormatErrorTest:"+tf.getAbsolutePath()+", canRead: "+tf.canRead()+", canWrite: "+tf.canWrite()); + // System.out.println("GenericSignatureFormatErrorTest:" + // +tf.getAbsolutePath()+", canRead: "+tf.canRead() + // +", canWrite: "+tf.canWrite()); InputStream is = this.getClass().getResourceAsStream("dex1.bytes"); assertNotNull(is); } @@ -48,6 +51,8 @@ public class GenericSignatureFormatErrorTest extends TestCase{ method = "GenericSignatureFormatError", args = {} ) + @AndroidOnly("Uses Android specific class dalvik.system.DexFile " + + "for loading classes.") public void test_signatureFormatError() throws Exception { /* * dex1.bytes is a jar file with a classes.dex in it. @@ -66,7 +71,9 @@ public class GenericSignatureFormatErrorTest extends TestCase{ */ File tf = File.createTempFile("classes", ".dex"); - System.out.println("GenericSignatureFormatErrorTest:"+tf.getAbsolutePath()+", canRead: "+tf.canRead()+", canWrite: "+tf.canWrite()); + // System.out.println("GenericSignatureFormatErrorTest:" + + // tf.getAbsolutePath() + ", canRead: " + tf.canRead() + + // ", canWrite: "+tf.canWrite()); InputStream is = this.getClass().getResourceAsStream("dex1.bytes"); assertNotNull(is); OutputStream fos = new FileOutputStream(tf); @@ -81,9 +88,9 @@ public class GenericSignatureFormatErrorTest extends TestCase{ Class clazz = df.loadClass("demo/HelloWorld", this.getClass().getClassLoader()); TypeVariable[] tvs = clazz.getTypeParameters(); fail("expecting a GenericSignatureFormatError"); - for (TypeVariable tv : tvs) { - System.out.println("tv:"+tv.toString()); - } + // for (TypeVariable tv : tvs) { + // System.out.println("tv:"+tv.toString()); + // } } catch (GenericSignatureFormatError gsfe) { // expected } diff --git a/luni/src/test/java/tests/api/java/lang/reflect/ProxyTest.java b/luni/src/test/java/tests/api/java/lang/reflect/ProxyTest.java index 2dd4ccf..051d5b2 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/ProxyTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/ProxyTest.java @@ -163,7 +163,6 @@ public class ProxyTest extends junit.framework.TestCase { method = "newProxyInstance", args = {java.lang.ClassLoader.class, java.lang.Class[].class, java.lang.reflect.InvocationHandler.class} ) - @KnownFailure("Fixed in ToT") public void test_newProxyInstanceLjava_lang_ClassLoader$Ljava_lang_ClassLjava_lang_reflect_InvocationHandler() { Object p = Proxy.newProxyInstance(Support_Proxy_I1.class .getClassLoader(), new Class[] { Support_Proxy_I1.class, @@ -295,7 +294,6 @@ public class ProxyTest extends junit.framework.TestCase { method = "getInvocationHandler", args = {java.lang.Object.class} ) - @KnownFailure("Fixed in ToT") public void test_getInvocationHandlerLjava_lang_Object() { InvocationHandler handler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) @@ -341,7 +339,6 @@ public class ProxyTest extends junit.framework.TestCase { method = "newProxyInstance", args = {java.lang.ClassLoader.class, java.lang.Class[].class, java.lang.reflect.InvocationHandler.class} ) - @KnownFailure("Fixed in ToT") public void test_newProxyInstance_withNonCompatibleReturnTypes() { try { Proxy.newProxyInstance(this.getClass().getClassLoader(), diff --git a/luni/src/test/java/tests/api/java/net/SocketTest.java b/luni/src/test/java/tests/api/java/net/SocketTest.java index b4376c5..94e7d09 100644 --- a/luni/src/test/java/tests/api/java/net/SocketTest.java +++ b/luni/src/test/java/tests/api/java/net/SocketTest.java @@ -18,7 +18,7 @@ package tests.api.java.net; import dalvik.annotation.AndroidOnly; -import dalvik.annotation.KnownFailure; +//import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargetClass; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; @@ -617,8 +617,8 @@ public class SocketTest extends SocketTestCase { int sport = startServer("SServer getLocAddress"); int portNumber = Support_PortManager.getNextPort(); s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber); - assertTrue("Returned incorrect InetAddress", s.getLocalAddress() - .equals(InetAddress.getLocalHost())); + assertEquals("Returned incorrect InetAddress", + InetAddress.getLocalHost(), s.getLocalAddress()); // now validate thet behaviour when the any address is returned String preferIPv4StackValue = System @@ -675,7 +675,6 @@ public class SocketTest extends SocketTestCase { method = "getOutputStream", args = {} ) - @KnownFailure("Needs investigation") public void test_getOutputStream() throws IOException { // Test for method java.io.OutputStream // java.net.Socket.getOutputStream() @@ -1586,7 +1585,7 @@ public class SocketTest extends SocketTestCase { assertTrue( "Local address not correct after bind:" + theSocket.getLocalSocketAddress().toString() - + "Expected: " + + " Expected: " + (new InetSocketAddress(InetAddress.getLocalHost(), portNumber)).toString(), theSocket .getLocalSocketAddress().equals( @@ -1604,7 +1603,7 @@ public class SocketTest extends SocketTestCase { assertTrue( "Returned Remote address from server connected to does not match expected local address:" + servSock.getRemoteSocketAddress().toString() - + "Expected: " + + " Expected: " + (new InetSocketAddress(InetAddress.getLocalHost(), portNumber)).toString(), servSock .getRemoteSocketAddress().equals( diff --git a/luni/src/test/java/tests/api/java/util/AbstractMapTest.java b/luni/src/test/java/tests/api/java/util/AbstractMapTest.java index 70f73f3..c6a612c 100644 --- a/luni/src/test/java/tests/api/java/util/AbstractMapTest.java +++ b/luni/src/test/java/tests/api/java/util/AbstractMapTest.java @@ -17,9 +17,7 @@ package tests.api.java.util; -import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; @@ -295,7 +293,6 @@ public class AbstractMapTest extends junit.framework.TestCase { method = "putAll", args = {java.util.Map.class} ) - @KnownFailure("ToT fixed.") public void test_putAllLMap() { Hashtable ht = new Hashtable(); AMT amt = new AMT(); diff --git a/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java b/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java index aec90f8..7169aca 100644 --- a/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java +++ b/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java @@ -462,6 +462,38 @@ public class LinkedHashMapTest extends junit.framework.TestCase { assertEquals("keySet() was not cloned", "key2", key2.iterator().next()); } + + /** + * @tests java.util.LinkedHashMap#clone() + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "clone", + args = {} + ) + public void test_clone_ordered() { + // Test for method java.lang.Object java.util.LinkedHashMap.clone() + LinkedHashMap<String, String> hm1 = new LinkedHashMap<String, String>(10, 0.75f, true); + hm1.put("a", "a"); + hm1.put("b", "b"); + hm1.put("c", "c"); + LinkedHashMap<String, String> hm2 = (LinkedHashMap<String, String>) hm1.clone(); + hm1.get("a"); + + Map.Entry<String, String>[] set = new Map.Entry[3]; + Iterator<Map.Entry<String,String>> iterator = hm1.entrySet().iterator(); + + assertEquals("b", iterator.next().getKey()); + assertEquals("c", iterator.next().getKey()); + assertEquals("a", iterator.next().getKey()); + + iterator = hm2.entrySet().iterator(); + assertEquals("a", iterator.next().getKey()); + assertEquals("b", iterator.next().getKey()); + assertEquals("c", iterator.next().getKey()); + } + @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, notes = "Regression test.", diff --git a/luni/src/test/java/tests/api/java/util/PropertiesTest.java b/luni/src/test/java/tests/api/java/util/PropertiesTest.java index f1024f6..61d7c35 100644 --- a/luni/src/test/java/tests/api/java/util/PropertiesTest.java +++ b/luni/src/test/java/tests/api/java/util/PropertiesTest.java @@ -17,11 +17,10 @@ package tests.api.java.util; +import dalvik.annotation.KnownFailure; import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetClass; -import dalvik.annotation.KnownFailure; +import dalvik.annotation.TestTargetClass; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -202,7 +201,6 @@ public class PropertiesTest extends junit.framework.TestCase { method = "load", args = {java.io.InputStream.class} ) - @KnownFailure("ToT fixed") public void test_loadLjava_io_InputStream() throws IOException { Properties prop = new Properties(); InputStream is = new ByteArrayInputStream(writeProperties()); @@ -389,7 +387,7 @@ public class PropertiesTest extends junit.framework.TestCase { method = "loadFromXML", args = {java.io.InputStream.class} ) - @KnownFailure("ToT fixed") + @KnownFailure("ToT fixed?") public void test_loadFromXMLLjava_io_InputStream() throws IOException { Properties myProps = new Properties(); myProps.put("Property A", " aye\\\f\t\n\r\b"); diff --git a/luni/src/test/java/tests/api/java/util/ResourceBundleTest.java b/luni/src/test/java/tests/api/java/util/ResourceBundleTest.java index d693ca3..8fecc7e 100644 --- a/luni/src/test/java/tests/api/java/util/ResourceBundleTest.java +++ b/luni/src/test/java/tests/api/java/util/ResourceBundleTest.java @@ -21,7 +21,6 @@ import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; -import dalvik.annotation.KnownFailure; import java.io.File; import java.net.MalformedURLException; @@ -139,7 +138,6 @@ public class ResourceBundleTest extends junit.framework.TestCase { method = "getBundle", args = {java.lang.String.class, java.util.Locale.class, java.lang.ClassLoader.class} ) - @KnownFailure("ToT fixed") public void test_getBundleLjava_lang_StringLjava_util_LocaleLjava_lang_ClassLoader() { String classPath = System.getProperty("java.class.path"); StringTokenizer tok = new StringTokenizer(classPath, File.pathSeparator); diff --git a/luni/src/test/java/tests/api/java/util/StringTokenizerTest.java b/luni/src/test/java/tests/api/java/util/StringTokenizerTest.java index a3ece6c..a7ba8da 100644 --- a/luni/src/test/java/tests/api/java/util/StringTokenizerTest.java +++ b/luni/src/test/java/tests/api/java/util/StringTokenizerTest.java @@ -21,7 +21,6 @@ import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetClass; -import dalvik.annotation.KnownFailure; import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -238,7 +237,6 @@ public class StringTokenizerTest extends junit.framework.TestCase { method = "nextToken", args = {java.lang.String.class} ) - @KnownFailure("ToT fixed") public void test_nextTokenLjava_lang_String() { // Test for method java.lang.String // java.util.StringTokenizer.nextToken(java.lang.String) diff --git a/luni/src/test/resources/org/apache/harmony/luni/tests/java/lang/illegalClasses.jar b/luni/src/test/resources/org/apache/harmony/luni/tests/java/lang/illegalClasses.jar Binary files differnew file mode 100644 index 0000000..4a5f4ef --- /dev/null +++ b/luni/src/test/resources/org/apache/harmony/luni/tests/java/lang/illegalClasses.jar |