summaryrefslogtreecommitdiffstats
path: root/luni/src
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src')
-rw-r--r--luni/src/main/java/java/security/cert/Extension.java65
-rw-r--r--luni/src/main/java/java/util/zip/ZipFile.java15
-rw-r--r--luni/src/main/java/javax/net/ssl/SSLEngineResult.java8
-rw-r--r--luni/src/main/java/libcore/reflect/AnnotationAccess.java56
-rw-r--r--luni/src/main/java/org/apache/harmony/security/x509/Extension.java19
-rw-r--r--luni/src/main/java/org/apache/harmony/security/x509/Extensions.java8
-rw-r--r--luni/src/main/native/java_math_NativeBN.cpp2
-rw-r--r--luni/src/test/java/libcore/icu/AlphabeticIndexTest.java16
-rw-r--r--luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java14
-rw-r--r--luni/src/test/java/libcore/java/net/URLConnectionTest.java69
-rw-r--r--luni/src/test/java/libcore/java/nio/channels/FileIOInterruptTest.java83
-rw-r--r--luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java44
-rw-r--r--luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java90
-rw-r--r--luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java73
14 files changed, 438 insertions, 124 deletions
diff --git a/luni/src/main/java/java/security/cert/Extension.java b/luni/src/main/java/java/security/cert/Extension.java
new file mode 100644
index 0000000..8013809
--- /dev/null
+++ b/luni/src/main/java/java/security/cert/Extension.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014 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.security.cert;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The Extension part of an X.509 certificate (as specified in <a
+ * href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280 &mdash; Internet X.509
+ * Public Key Infrastructure: Certificate and Certificate Revocation List (CRL)
+ * Profile</p>):
+ *
+ * <pre>
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING
+ * }
+ * </pre>
+ *
+ * @since 1.7
+ * @hide
+ */
+public interface Extension {
+ /**
+ * Returns the OID (Object Identifier) for this extension encoded as a
+ * string (e.g., "2.5.29.15").
+ */
+ String getId();
+
+ /**
+ * Returns {@code true} if this extension is critical. If this is true and
+ * an implementation does not understand this extension, it must reject it.
+ * See RFC 3280 section 4.2 for more information.
+ */
+ boolean isCritical();
+
+ /**
+ * The DER-encoded value of this extension.
+ */
+ byte[] getValue();
+
+ /**
+ * Writes the DER-encoded extension to {@code out}.
+ *
+ * @throws IOException when there is an encoding error or error writing to
+ * {@code out}
+ */
+ void encode(OutputStream out) throws IOException;
+}
diff --git a/luni/src/main/java/java/util/zip/ZipFile.java b/luni/src/main/java/java/util/zip/ZipFile.java
index 4b3e431..43e8567 100644
--- a/luni/src/main/java/java/util/zip/ZipFile.java
+++ b/luni/src/main/java/java/util/zip/ZipFile.java
@@ -33,6 +33,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import libcore.io.BufferIterator;
import libcore.io.HeapBufferIterator;
+import libcore.io.IoUtils;
import libcore.io.Streams;
/**
@@ -199,7 +200,19 @@ public class ZipFile implements Closeable, ZipConstants {
raf = new RandomAccessFile(filename, "r");
- readCentralDir();
+ // Make sure to close the RandomAccessFile if reading the central directory fails.
+ boolean mustCloseFile = true;
+ try {
+ readCentralDir();
+
+ // Read succeeded so do not close the underlying RandomAccessFile.
+ mustCloseFile = false;
+ } finally {
+ if (mustCloseFile) {
+ IoUtils.closeQuietly(raf);
+ }
+ }
+
guard.open("close");
}
diff --git a/luni/src/main/java/javax/net/ssl/SSLEngineResult.java b/luni/src/main/java/javax/net/ssl/SSLEngineResult.java
index 8a98831..3360832 100644
--- a/luni/src/main/java/javax/net/ssl/SSLEngineResult.java
+++ b/luni/src/main/java/javax/net/ssl/SSLEngineResult.java
@@ -110,16 +110,16 @@ public class SSLEngineResult {
public SSLEngineResult(SSLEngineResult.Status status,
SSLEngineResult.HandshakeStatus handshakeStatus, int bytesConsumed, int bytesProduced) {
if (status == null) {
- throw new IllegalArgumentException("status is null");
+ throw new IllegalArgumentException("status == null");
}
if (handshakeStatus == null) {
- throw new IllegalArgumentException("handshakeStatus is null");
+ throw new IllegalArgumentException("handshakeStatus == null");
}
if (bytesConsumed < 0) {
- throw new IllegalArgumentException("bytesConsumed is negative");
+ throw new IllegalArgumentException("bytesConsumed < 0: " + bytesConsumed);
}
if (bytesProduced < 0) {
- throw new IllegalArgumentException("bytesProduced is negative");
+ throw new IllegalArgumentException("bytesProduced < 0: " + bytesProduced);
}
this.status = status;
this.handshakeStatus = handshakeStatus;
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
index d63ad30..2a72c18 100644
--- a/luni/src/main/java/libcore/reflect/AnnotationAccess.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
@@ -16,7 +16,6 @@
package libcore.reflect;
-import com.android.dex.ClassDef;
import com.android.dex.Dex;
import com.android.dex.EncodedValueReader;
import com.android.dex.FieldId;
@@ -167,7 +166,7 @@ public final class AnnotationAccess {
*/
public static <A extends Annotation> A getDeclaredAnnotation(
AnnotatedElement element, Class<A> annotationClass) {
- com.android.dex.Annotation a = getMethodAnnotation(element, annotationClass);
+ com.android.dex.Annotation a = getAnnotation(element, annotationClass);
return a != null
? toAnnotationInstance(getDexClass(element), annotationClass, a)
: null;
@@ -178,10 +177,10 @@ public final class AnnotationAccess {
*/
public static boolean isDeclaredAnnotationPresent(
AnnotatedElement element, Class<? extends Annotation> annotationClass) {
- return getMethodAnnotation(element, annotationClass) != null;
+ return getAnnotation(element, annotationClass) != null;
}
- private static com.android.dex.Annotation getMethodAnnotation(
+ private static com.android.dex.Annotation getAnnotation(
AnnotatedElement element, Class<? extends Annotation> annotationClass) {
int annotationSetOffset = getAnnotationSetOffset(element);
if (annotationSetOffset == 0) {
@@ -190,17 +189,17 @@ public final class AnnotationAccess {
Class<?> dexClass = getDexClass(element);
Dex dex = dexClass.getDex();
- int annotationTypeIndex = getTypeIndex(dex, annotationClass);
- if (annotationTypeIndex == -1) {
- return null; // The dex file doesn't use this annotation.
- }
-
Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
+ String annotationInternalName = InternalNames.getInternalName(annotationClass);
for (int i = 0, size = setIn.readInt(); i < size; i++) {
int annotationOffset = setIn.readInt();
Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
+ // The internal string name of the annotation is compared here and deliberately not
+ // the value of annotationClass.getTypeIndex(). The annotationClass may have been
+ // defined by a different dex file, which would make the indexes incomparable.
com.android.dex.Annotation candidate = annotationIn.readAnnotation();
- if (candidate.getTypeIndex() == annotationTypeIndex) {
+ String candidateInternalName = dex.typeNames().get(candidate.getTypeIndex());
+ if (candidateInternalName.equals(annotationInternalName)) {
return candidate;
}
}
@@ -268,23 +267,6 @@ public final class AnnotationAccess {
: ((Member) element).getDeclaringClass();
}
- public static int getFieldIndex(Class<?> declaringClass, Class<?> type, String name) {
- Dex dex = declaringClass.getDex();
- int declaringClassIndex = getTypeIndex(dex, declaringClass);
- int typeIndex = getTypeIndex(dex, type);
- int nameIndex = dex.findStringIndex(name);
- FieldId fieldId = new FieldId(dex, declaringClassIndex, typeIndex, nameIndex);
- return dex.findFieldIndex(fieldId);
- }
-
- public static int getMethodIndex(Class<?> declaringClass, String name, int protoIndex) {
- Dex dex = declaringClass.getDex();
- int declaringClassIndex = getTypeIndex(dex, declaringClass);
- int nameIndex = dex.findStringIndex(name);
- MethodId methodId = new MethodId(dex, declaringClassIndex, protoIndex, nameIndex);
- return dex.findMethodIndex(methodId);
- }
-
/**
* Returns the parameter annotations on {@code member}.
*/
@@ -357,6 +339,8 @@ public final class AnnotationAccess {
*/
Class<?> annotationClass = method.getDeclaringClass();
+ // All lookups of type and string indexes are within the Dex that declares the annotation so
+ // the indexes can be compared directly.
Dex dex = annotationClass.getDex();
EncodedValueReader reader = getOnlyAnnotationValue(
dex, annotationClass, "Ldalvik/annotation/AnnotationDefault;");
@@ -365,7 +349,7 @@ public final class AnnotationAccess {
}
int fieldCount = reader.readAnnotation();
- if (reader.getAnnotationType() != getTypeIndex(dex, annotationClass)) {
+ if (reader.getAnnotationType() != annotationClass.getDexTypeIndex()) {
throw new AssertionError("annotation value type != annotation class");
}
@@ -540,22 +524,6 @@ public final class AnnotationAccess {
* was derived.
*/
- /** Find dex's type index for the class c */
- private static int getTypeIndex(Dex dex, Class<?> c) {
- if (dex == c.getDex()) {
- return c.getDexTypeIndex();
- }
- if (dex == null) {
- return -1;
- }
- int typeIndex = dex.findTypeIndex(InternalNames.getInternalName(c));
- if (typeIndex < 0) {
- typeIndex = -1;
- }
- return typeIndex;
- }
-
-
private static EncodedValueReader getAnnotationReader(
Dex dex, AnnotatedElement element, String annotationName, int expectedFieldCount) {
int annotationSetOffset = getAnnotationSetOffset(element);
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/Extension.java b/luni/src/main/java/org/apache/harmony/security/x509/Extension.java
index d9b02f9..d5d8015 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/Extension.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/Extension.java
@@ -23,6 +23,7 @@
package org.apache.harmony.security.x509;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.Arrays;
import org.apache.harmony.security.asn1.ASN1Boolean;
import org.apache.harmony.security.asn1.ASN1OctetString;
@@ -49,7 +50,7 @@ import org.apache.harmony.security.utils.Array;
* }
* </pre>
*/
-public final class Extension {
+public final class Extension implements java.security.cert.Extension {
// critical constants
public static final boolean CRITICAL = true;
public static final boolean NON_CRITICAL = false;
@@ -145,7 +146,8 @@ public final class Extension {
/**
* Returns the value of extnID field of the structure.
*/
- public String getExtnID() {
+ @Override
+ public String getId() {
if (extnID_str == null) {
extnID_str = ObjectIdentifier.toString(extnID);
}
@@ -155,14 +157,16 @@ public final class Extension {
/**
* Returns the value of critical field of the structure.
*/
- public boolean getCritical() {
+ @Override
+ public boolean isCritical() {
return critical;
}
/**
* Returns the value of extnValue field of the structure.
*/
- public byte[] getExtnValue() {
+ @Override
+ public byte[] getValue() {
return extnValue;
}
@@ -187,6 +191,11 @@ public final class Extension {
return encoding;
}
+ @Override
+ public void encode(OutputStream out) throws IOException {
+ out.write(getEncoded());
+ }
+
@Override public boolean equals(Object ext) {
if (!(ext instanceof Extension)) {
return false;
@@ -287,7 +296,7 @@ public final class Extension {
}
public void dumpValue(StringBuilder sb, String prefix) {
- sb.append("OID: ").append(getExtnID()).append(", Critical: ").append(critical).append('\n');
+ sb.append("OID: ").append(getId()).append(", Critical: ").append(critical).append('\n');
if (!valueDecoded) {
try {
decodeExtensionValue();
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java b/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
index 92ff3a9..7a10ebc 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
@@ -136,8 +136,8 @@ public final class Extensions {
Set<String> localNoncritical = new HashSet<String>(size);
Boolean localHasUnsupported = Boolean.FALSE;
for (Extension extension : extensions) {
- String oid = extension.getExtnID();
- if (extension.getCritical()) {
+ String oid = extension.getId();
+ if (extension.isCritical()) {
if (!SUPPORTED_CRITICAL.contains(oid)) {
localHasUnsupported = Boolean.TRUE;
}
@@ -162,7 +162,7 @@ public final class Extensions {
if (localOidMap == null) {
localOidMap = new HashMap<String, Extension>();
for (Extension extension : extensions) {
- localOidMap.put(extension.getExtnID(), extension);
+ localOidMap.put(extension.getId(), extension);
}
this.oidMap = localOidMap;
}
@@ -311,7 +311,7 @@ public final class Extensions {
}
Collection<List<?>> collection = ((GeneralNames) GeneralNames.ASN1.decode(extension
- .getExtnValue())).getPairsList();
+ .getValue())).getPairsList();
/*
* If the extension had any invalid entries, we may have an empty
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index d0a03b7..be87ea6 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -212,7 +212,7 @@ static void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len,
#else
int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
#endif
- ret->top = len;
+ ret->top = wlen;
ret->neg = neg;
// need to call this due to clear byte at top if avoiding
// having the top bit set (-ve number)
diff --git a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
index 8b8c729..6c7452d 100644
--- a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
+++ b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
@@ -20,8 +20,7 @@ import java.util.Locale;
public class AlphabeticIndexTest extends junit.framework.TestCase {
private static AlphabeticIndex.ImmutableIndex createIndex(Locale locale) {
- return new AlphabeticIndex(locale).addLabels(Locale.US)
- .getImmutableIndex();
+ return new AlphabeticIndex(locale).addLabels(Locale.US).getImmutableIndex();
}
private static void assertHasLabel(AlphabeticIndex.ImmutableIndex ii, String string, String expectedLabel) {
@@ -111,8 +110,8 @@ public class AlphabeticIndexTest extends junit.framework.TestCase {
// German: [A-Z] (no ß or umlauted characters in standard alphabet)
AlphabeticIndex.ImmutableIndex de = createIndex(Locale.GERMAN);
assertHasLabel(de, "ßind", "S");
+ // We no longer split out "S", "Sch", and "St".
assertHasLabel(de, "Sacher", "S");
- // "Sch" and "St" are also options for lists by last name.
assertHasLabel(de, "Schiller", "S");
assertHasLabel(de, "Steiff", "S");
}
@@ -141,14 +140,19 @@ public class AlphabeticIndexTest extends junit.framework.TestCase {
public void test_zh_CN() throws Exception {
// Simplified Chinese (default collator Pinyin): [A-Z]
- // Shen/Chen (simplified): should be, usually, 'S' for name collator and 'C' for apps/other
AlphabeticIndex.ImmutableIndex zh_CN = createIndex(new Locale("zh", "CN"));
// Jia/Gu: should be, usually, 'J' for name collator and 'G' for apps/other
assertHasLabel(zh_CN, "\u8d3e", "J");
- // Shen/Chen
- assertHasLabel(zh_CN, "\u6c88", "C"); // icu4c 50 does not specialize for names.
+ // Shen/Chen (simplified): should usually be 'S' for names and 'C' for apps/other.
+ // icu4c does not specialize for names and defaults to 'C'.
+ // Some OEMs prefer to default to 'S'.
+ // We allow either to pass CTS since neither choice is right all the time.
+ // assertHasLabel(zh_CN, "\u6c88", "C");
+ String shenChenLabel = zh_CN.getBucketLabel(zh_CN.getBucketIndex("\u6c88"));
+ assertTrue(shenChenLabel.equals("C") || shenChenLabel.equals("S"));
+
// Shen/Chen (traditional)
assertHasLabel(zh_CN, "\u700b", "S");
}
diff --git a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
index d03ae65..9766cef 100644
--- a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
+++ b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
@@ -22,10 +22,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
-import libcore.dalvik.system.CloseGuardTester;
+import libcore.java.util.AbstractResourceLeakageDetectorTestCase;
import static tests.support.Support_Exec.execAndCheckOutput;
-public class ProcessBuilderTest extends junit.framework.TestCase {
+public class ProcessBuilderTest extends AbstractResourceLeakageDetectorTestCase {
private static String shell() {
String deviceSh = "/system/bin/sh";
@@ -84,14 +84,8 @@ public class ProcessBuilderTest extends junit.framework.TestCase {
}
public void testDestroyDoesNotLeak() throws IOException {
- CloseGuardTester closeGuardTester = new CloseGuardTester();
- try {
- Process process = new ProcessBuilder(shell(), "-c", "echo out; echo err 1>&2").start();
- process.destroy();
- closeGuardTester.assertEverythingWasClosed();
- } finally {
- closeGuardTester.close();
- }
+ Process process = new ProcessBuilder(shell(), "-c", "echo out; echo err 1>&2").start();
+ process.destroy();
}
public void testEnvironmentMapForbidsNulls() throws Exception {
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index b40976e..e945e60 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -21,9 +21,7 @@ import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;
import com.google.mockwebserver.RecordedRequest;
import com.google.mockwebserver.SocketPolicy;
-import dalvik.system.CloseGuard;
import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -31,7 +29,6 @@ import java.io.OutputStream;
import java.net.Authenticator;
import java.net.CacheRequest;
import java.net.CacheResponse;
-import java.net.ConnectException;
import java.net.HttpRetryException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
@@ -68,9 +65,8 @@ import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
-import junit.framework.TestCase;
-import libcore.java.lang.ref.FinalizationTester;
import libcore.java.security.TestKeyStore;
+import libcore.java.util.AbstractResourceLeakageDetectorTestCase;
import libcore.javax.net.ssl.TestSSLContext;
import tests.net.StuckServer;
@@ -80,7 +76,8 @@ import static com.google.mockwebserver.SocketPolicy.FAIL_HANDSHAKE;
import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
-public final class URLConnectionTest extends TestCase {
+public final class URLConnectionTest extends AbstractResourceLeakageDetectorTestCase {
+
private MockWebServer server;
private HttpResponseCache cache;
private String hostName;
@@ -101,8 +98,10 @@ public final class URLConnectionTest extends TestCase {
System.clearProperty("https.proxyHost");
System.clearProperty("https.proxyPort");
server.shutdown();
+ server = null;
if (cache != null) {
cache.delete();
+ cache = null;
}
super.tearDown();
}
@@ -797,47 +796,17 @@ public final class URLConnectionTest extends TestCase {
}
public void testDisconnectAfterOnlyResponseCodeCausesNoCloseGuardWarning() throws IOException {
- CloseGuardGuard guard = new CloseGuardGuard();
- try {
- server.enqueue(new MockResponse()
- .setBody(gzip("ABCABCABC".getBytes("UTF-8")))
- .addHeader("Content-Encoding: gzip"));
- server.play();
+ server.enqueue(new MockResponse()
+ .setBody(gzip("ABCABCABC".getBytes("UTF-8")))
+ .addHeader("Content-Encoding: gzip"));
+ server.play();
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
+ HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
+ try {
assertEquals(200, connection.getResponseCode());
- connection.disconnect();
- connection = null;
- assertFalse(guard.wasCloseGuardCalled());
} finally {
- guard.close();
- }
- }
-
- public static class CloseGuardGuard implements Closeable, CloseGuard.Reporter {
- private final CloseGuard.Reporter oldReporter = CloseGuard.getReporter();
-
- private AtomicBoolean closeGuardCalled = new AtomicBoolean();
-
- public CloseGuardGuard() {
- CloseGuard.setReporter(this);
- }
-
- @Override public void report(String message, Throwable allocationSite) {
- oldReporter.report(message, allocationSite);
- closeGuardCalled.set(true);
- }
-
- public boolean wasCloseGuardCalled() {
- FinalizationTester.induceFinalization();
- close();
- return closeGuardCalled.get();
- }
-
- @Override public void close() {
- CloseGuard.setReporter(oldReporter);
+ connection.disconnect();
}
-
}
public void testDefaultRequestProperty() throws Exception {
@@ -2272,11 +2241,15 @@ public final class URLConnectionTest extends TestCase {
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
connection.connect();
- assertNotNull(connection.getHostnameVerifier());
- assertNull(connection.getLocalCertificates());
- assertNotNull(connection.getServerCertificates());
- assertNotNull(connection.getCipherSuite());
- assertNotNull(connection.getPeerPrincipal());
+ try {
+ assertNotNull(connection.getHostnameVerifier());
+ assertNull(connection.getLocalCertificates());
+ assertNotNull(connection.getServerCertificates());
+ assertNotNull(connection.getCipherSuite());
+ assertNotNull(connection.getPeerPrincipal());
+ } finally {
+ connection.disconnect();
+ }
}
/**
diff --git a/luni/src/test/java/libcore/java/nio/channels/FileIOInterruptTest.java b/luni/src/test/java/libcore/java/nio/channels/FileIOInterruptTest.java
index c06df04..02c6f3b 100644
--- a/luni/src/test/java/libcore/java/nio/channels/FileIOInterruptTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/FileIOInterruptTest.java
@@ -17,7 +17,6 @@ package libcore.java.nio.channels;
import junit.framework.TestCase;
-import android.system.ErrnoException;
import android.system.OsConstants;
import java.io.File;
import java.io.FileInputStream;
@@ -90,6 +89,9 @@ public class FileIOInterruptTest extends TestCase {
super.tearDown();
fifoFile.delete();
VOGAR_DEVICE_TEMP_DIR.delete();
+
+ // Clear the interrupted state, if set.
+ Thread.interrupted();
}
public void testStreamRead_exceptionWhenAlreadyClosed() throws Exception {
@@ -208,6 +210,43 @@ public class FileIOInterruptTest extends TestCase {
fifoWriter.tidyUp();
}
+ public void testChannelRead_exceptionWhenAlreadyInterrupted() throws Exception {
+ testChannelRead_exceptionWhenAlreadyInterrupted(ChannelReader.Method.READ);
+ }
+
+ public void testChannelReadV_exceptionWhenAlreadyInterrupted() throws Exception {
+ testChannelRead_exceptionWhenAlreadyInterrupted(ChannelReader.Method.READV);
+ }
+
+ private void testChannelRead_exceptionWhenAlreadyInterrupted(ChannelReader.Method method)
+ throws Exception {
+ FifoWriter fifoWriter = new FifoWriter(fifoFile);
+ fifoWriter.start();
+ FileInputStream fis = new FileInputStream(fifoFile);
+ FileChannel fileInputChannel = fis.getChannel();
+
+ Thread.currentThread().interrupt();
+
+ ByteBuffer buffer = ByteBuffer.allocateDirect(10);
+ try {
+ if (method == ChannelReader.Method.READ) {
+ fileInputChannel.read(buffer);
+ } else {
+ ByteBuffer buffer2 = ByteBuffer.allocateDirect(10);
+ fileInputChannel.read(new ByteBuffer[] { buffer, buffer2});
+ }
+ fail();
+ } catch (IOException expected) {
+ assertSame(ClosedByInterruptException.class, expected.getClass());
+ }
+
+ // Check but also clear the interrupted status, so we can wait for the FifoWriter thread in
+ // tidyUp().
+ assertTrue(Thread.interrupted());
+
+ fifoWriter.tidyUp();
+ }
+
public void testChannelRead_exceptionOnCloseWhenBlocked() throws Exception {
testChannelRead_exceptionOnCloseWhenBlocked(ChannelReader.Method.READ);
}
@@ -303,6 +342,43 @@ public class FileIOInterruptTest extends TestCase {
fifoReader.tidyUp();
}
+ public void testChannelWrite_exceptionWhenAlreadyInterrupted() throws Exception {
+ testChannelWrite_exceptionWhenAlreadyInterrupted(ChannelWriter.Method.WRITE);
+ }
+
+ public void testChannelWriteV_exceptionWhenAlreadyInterrupted() throws Exception {
+ testChannelWrite_exceptionWhenAlreadyInterrupted(ChannelWriter.Method.WRITEV);
+ }
+
+ private void testChannelWrite_exceptionWhenAlreadyInterrupted(ChannelWriter.Method method)
+ throws Exception {
+ FifoReader fifoReader = new FifoReader(fifoFile);
+ fifoReader.start();
+ FileOutputStream fos = new FileOutputStream(fifoFile);
+ FileChannel fileInputChannel = fos.getChannel();
+
+ Thread.currentThread().interrupt();
+
+ ByteBuffer buffer = ByteBuffer.allocateDirect(10);
+ try {
+ if (method == ChannelWriter.Method.WRITE) {
+ fileInputChannel.write(buffer);
+ } else {
+ ByteBuffer buffer2 = ByteBuffer.allocateDirect(10);
+ fileInputChannel.write(new ByteBuffer[] { buffer, buffer2 });
+ }
+ fail();
+ } catch (IOException expected) {
+ assertSame(ClosedByInterruptException.class, expected.getClass());
+ }
+
+ // Check but also clear the interrupted status, so we can wait for the FifoReader thread in
+ // tidyUp().
+ assertTrue(Thread.interrupted());
+
+ fifoReader.tidyUp();
+ }
+
public void testChannelWrite_exceptionOnCloseWhenBlocked() throws Exception {
testChannelWrite_exceptionOnCloseWhenBlocked(ChannelWriter.Method.WRITE);
}
@@ -608,6 +684,9 @@ public class FileIOInterruptTest extends TestCase {
}
private static void waitToDie(Thread thread) {
+ // Protect against this thread already being interrupted, which would prevent the test waiting
+ // for the requested time.
+ assertFalse(Thread.currentThread().isInterrupted());
try {
thread.join(5000);
} catch (InterruptedException ignored) {
@@ -619,6 +698,8 @@ public class FileIOInterruptTest extends TestCase {
}
private static void delay(int millis) {
+ // Protect against this thread being interrupted, which would prevent us waiting.
+ assertFalse(Thread.currentThread().isInterrupted());
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {
diff --git a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java b/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
new file mode 100644
index 0000000..5ea67d3
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 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 libcore.java.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Ensures that resources used within a test are cleaned up; will detect problems with tests and
+ * also with runtime.
+ */
+public abstract class AbstractResourceLeakageDetectorTestCase extends TestCase {
+ /**
+ * The leakage detector.
+ */
+ private ResourceLeakageDetector detector;
+
+ @Override
+ protected void setUp() throws Exception {
+ detector = ResourceLeakageDetector.newDetector();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // If available check for resource leakage. At this point it is impossible to determine
+ // whether the test has thrown an exception. If it has then the exception thrown by this
+ // could hide that test failure; it largely depends on the test runner.
+ if (detector != null) {
+ detector.checkForLeaks();
+ }
+ }
+}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
new file mode 100644
index 0000000..954665a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 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 libcore.java.util;
+
+/**
+ * Detects resource leakages for resources that are protected by <code>CloseGuard</code> mechanism.
+ *
+ * <p>If multiple instances of this are active at the same time, i.e. have been created but not yet
+ * had their {@link #checkForLeaks()} method called then while they will report all the leakages
+ * detected they may report the leakages caused by the code being tested by another detector.
+ *
+ * <p>The underlying CloseGuardMonitor is loaded using reflection to ensure that this will run,
+ * albeit doing nothing, on the reference implementation.
+ */
+public class ResourceLeakageDetector {
+ /** The class for the CloseGuardMonitor, null if not supported. */
+ private static final Class<?> CLOSE_GUARD_MONITOR_CLASS;
+
+ static {
+ ClassLoader classLoader = ResourceLeakageDetector.class.getClassLoader();
+ Class<?> clazz;
+ try {
+ // Make sure that the CloseGuard class exists; this ensures that this is not running
+ // on a RI JVM.
+ classLoader.loadClass("dalvik.system.CloseGuard");
+
+ // Load the monitor class for later instantiation.
+ clazz = classLoader.loadClass("dalvik.system.CloseGuardMonitor");
+
+ } catch (ClassNotFoundException e) {
+ System.err.println("Resource leakage will not be detected; "
+ + "this is expected in the reference implementation");
+ e.printStackTrace(System.err);
+
+ // Ignore, probably running in reference implementation.
+ clazz = null;
+ }
+
+ CLOSE_GUARD_MONITOR_CLASS = clazz;
+ }
+
+ /**
+ * The underlying CloseGuardMonitor that will perform the post test checks for resource
+ * leakage.
+ */
+ private Runnable postTestChecker;
+
+ /**
+ * Create a new detector.
+ *
+ * @return The new {@link ResourceLeakageDetector}, its {@link #checkForLeaks()} method must be
+ * called otherwise it will not clean up properly after itself.
+ */
+ public static ResourceLeakageDetector newDetector()
+ throws Exception {
+ return new ResourceLeakageDetector();
+ }
+
+ private ResourceLeakageDetector()
+ throws Exception {
+ if (CLOSE_GUARD_MONITOR_CLASS != null) {
+ postTestChecker = (Runnable) CLOSE_GUARD_MONITOR_CLASS.newInstance();
+ }
+ }
+
+ /**
+ * Detect any leaks that have arisen since this was created.
+ *
+ * @throws Exception If any leaks were detected.
+ */
+ public void checkForLeaks() throws Exception {
+ // If available check for resource leakage.
+ if (postTestChecker != null) {
+ postTestChecker.run();
+ }
+ }
+}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
new file mode 100644
index 0000000..d86c9f2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 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 libcore.java.util;
+
+import dalvik.system.CloseGuard;
+import junit.framework.TestCase;
+
+/**
+ * Test for {@link ResourceLeakageDetector}
+ */
+public class ResourceLeakageDetectorTest extends TestCase {
+ /**
+ * This test will not work on RI as it does not support the <code>CloseGuard</code> or similar
+ * mechanism.
+ */
+ public void testDetectsUnclosedCloseGuard() throws Exception {
+ ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
+ try {
+ CloseGuard closeGuard = createCloseGuard();
+ closeGuard.open("open");
+ } finally {
+ try {
+ System.logI("Checking for leaks");
+ detector.checkForLeaks();
+ fail();
+ } catch (AssertionError expected) {
+ }
+ }
+ }
+
+ public void testIgnoresClosedCloseGuard() throws Exception {
+ ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
+ try {
+ CloseGuard closeGuard = createCloseGuard();
+ closeGuard.open("open");
+ closeGuard.close();
+ } finally {
+ detector.checkForLeaks();
+ }
+ }
+
+ /**
+ * Private method to ensure that the CloseGuard object is garbage collected.
+ */
+ private CloseGuard createCloseGuard() {
+ final CloseGuard closeGuard = CloseGuard.get();
+ new Object() {
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ closeGuard.warnIfOpen();
+ } finally {
+ super.finalize();
+ }
+ }
+ };
+
+ return closeGuard;
+ }
+}