Merge "Only bother building the host tests for Linux."
diff --git a/expectations/brokentests.txt b/expectations/brokentests.txt
index 2ff723f..0a047a2 100644
--- a/expectations/brokentests.txt
+++ b/expectations/brokentests.txt
@@ -67,7 +67,6 @@
   result: EXEC_FAILED,
   names: [
     "org.apache.harmony.tests.java.net.Inet6AddressTest#test_getByNameLjava_lang_String",
-    "org.apache.harmony.tests.java.net.InetAddressTest#test_equalsLjava_lang_Object",
     "org.apache.harmony.tests.java.net.InetAddressTest#test_getByNameLjava_lang_String",
     "org.apache.harmony.tests.java.net.InetAddressTest#test_isReachableLjava_net_NetworkInterfaceII_loopbackInterface"
   ]
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java
index 42f88c1..e5742d7 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java
@@ -47,7 +47,7 @@
     }
 
     public void test_equalsLjava_lang_Object() throws Exception {
-        InetAddress ia1 = InetAddress.getByName("localhost");
+        InetAddress ia1 = InetAddress.getByName("ip6-localhost");
         InetAddress ia2 = InetAddress.getByName("::1");
         assertEquals(ia2, ia1);
     }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java
index 19c6229..c971e99 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java
@@ -234,10 +234,10 @@
              * Allow a bit more slop for the maximum on "expected
              * instantaneous" results.
              */
-            long minimum = (long) ((double) expectedMillis * 0.90);
+            long minimum = (long) ((double) expectedMillis * 0.80);
             long maximum =
-                Math.max((long) ((double) expectedMillis * 1.10), 10);
-            long waitMillis = Math.max(expectedMillis * 10, 10);
+                Math.max((long) ((double) expectedMillis * 1.20), 10);
+            long waitMillis = Math.max(expectedMillis * 10, 30);
             long duration = getDurationMillis(waitMillis);
 
             if (duration < minimum) {
diff --git a/luni/src/main/java/java/net/Inet6Address.java b/luni/src/main/java/java/net/Inet6Address.java
index 8ab0f8d..347f43a 100644
--- a/luni/src/main/java/java/net/Inet6Address.java
+++ b/luni/src/main/java/java/net/Inet6Address.java
@@ -43,7 +43,7 @@
      */
     public static final InetAddress LOOPBACK =
             new Inet6Address(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
-                    "localhost", 0);
+                    "ip6-localhost", 0);
 
     private boolean scope_id_set;
     private int scope_id;
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java
index 6a02e0d..581e1bd 100644
--- a/luni/src/main/java/java/net/InetAddress.java
+++ b/luni/src/main/java/java/net/InetAddress.java
@@ -202,10 +202,10 @@
     /**
      * Gets all IP addresses associated with the given {@code host} identified
      * by name or literal IP address. The IP address is resolved by the
-     * configured name service. If the host name is empty or {@code null} an
-     * {@code UnknownHostException} is thrown. If the host name is a literal IP
-     * address string an array with the corresponding single {@code InetAddress}
-     * is returned.
+     * configured name service. If the host name is empty or {@code null} the
+     * IP addresses of the loopback interfaces are returned. If the host name
+     * is a literal IP address string an array with the corresponding single
+     * {@code InetAddress} is returned.
      *
      * @param host the hostname or literal IP string to be resolved.
      * @return the array of addresses associated with the specified host.
diff --git a/luni/src/main/java/java/nio/channels/Selector.java b/luni/src/main/java/java/nio/channels/Selector.java
index 6d9b063..baa6a7f 100644
--- a/luni/src/main/java/java/nio/channels/Selector.java
+++ b/luni/src/main/java/java/nio/channels/Selector.java
@@ -78,8 +78,11 @@
     public abstract boolean isOpen();
 
     /**
-     * Gets the set of registered keys. The set is immutable and is not thread-
-     * safe.
+     * Gets the set of registered keys.
+     *
+     * <p>The returned set cannot be changed directly but can be modified
+     * indirectly by operations on the Selector. It should therefore not be
+     * treated as thread-safe.
      *
      * @return the set of registered keys.
      */
@@ -127,9 +130,11 @@
     public abstract int select(long timeout) throws IOException;
 
     /**
-     * Gets the selection keys whose channels are ready for operation. The set
-     * is not thread-safe and no keys may be added to it. Removing keys is
-     * allowed.
+     * Gets the selection keys whose channels are ready for operation.
+     *
+     * <p>Keys cannot be added to the set directly. Keys can be removed.
+     * The set can be modified indirectly by operations on the Selector. It
+     * should therefore not be treated as thread-safe.
      *
      * @return the selection keys whose channels are ready for operation.
      * @throws ClosedSelectorException
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index d007b0f..771af83 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -147,6 +147,11 @@
     /**
      * Gets the name of this {@code ZipEntry}.
      *
+     * <p><em>Security note:</em> Entry names can represent relative paths. {@code foo/../bar} or
+     * {@code ../bar/baz}, for example. If the entry name is being used to construct a filename
+     * or as a path component, it must be validated or sanitized to ensure that files are not
+     * written outside of the intended destination directory.
+     *
      * @return the entry name.
      */
     public String getName() {
diff --git a/luni/src/main/native/java_util_jar_StrictJarFile.cpp b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
index f0cdbed..82547bd 100644
--- a/luni/src/main/native/java_util_jar_StrictJarFile.cpp
+++ b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
@@ -28,16 +28,15 @@
 #include "ziparchive/zip_archive.h"
 #include "cutils/log.h"
 
+// The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ)
+static jmethodID zipEntryCtor;
+
 static void throwIoException(JNIEnv* env, const int32_t errorCode) {
   jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
 }
 
 static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
-  ScopedLocalRef<jclass> zipEntryClass(env, env->FindClass("java/util/zip/ZipEntry"));
-  const jmethodID zipEntryCtor = env->GetMethodID(zipEntryClass.get(), "<init>",
-                                   "(Ljava/lang/String;Ljava/lang/String;JJJIII[BJJ)V");
-
-  return env->NewObject(zipEntryClass.get(),
+  return env->NewObject(JniConstants::zipEntryClass,
                         zipEntryCtor,
                         entryName,
                         NULL,  // comment
@@ -164,4 +163,7 @@
 void register_java_util_jar_StrictJarFile(JNIEnv* env) {
   jniRegisterNativeMethods(env, "java/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
 
+  zipEntryCtor = env->GetMethodID(JniConstants::zipEntryClass, "<init>",
+      "(Ljava/lang/String;Ljava/lang/String;JJJIII[BJJ)V");
+  LOG_ALWAYS_FATAL_IF(zipEntryCtor == NULL, "Unable to find ZipEntry.<init>");
 }
diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java
index 7a96b0b..8bdcf64 100644
--- a/luni/src/test/java/libcore/java/net/InetAddressTest.java
+++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java
@@ -19,13 +19,16 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
-import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 import libcore.util.SerializationTester;
 
 public class InetAddressTest extends junit.framework.TestCase {
+    private static final byte[] LOOPBACK4_BYTES = new byte[] { 127, 0, 0, 1 };
     private static final byte[] LOOPBACK6_BYTES = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
 
     private static final String[] INVALID_IPv4_NUMERIC_ADDRESSES = new String[] {
@@ -73,7 +76,7 @@
     }
 
     private static Inet6Address localhost6() throws Exception {
-        return (Inet6Address) InetAddress.getByAddress("localhost", LOOPBACK6_BYTES);
+        return (Inet6Address) InetAddress.getByAddress("ip6-localhost", LOOPBACK6_BYTES);
     }
 
     public void test_parseNumericAddress() throws Exception {
@@ -313,15 +316,83 @@
         }
     }
 
-    public void test_getHostString() throws Exception {
-        InetAddress inetAddress = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
-        assertEquals("127.0.0.1", inetAddress.getHostString());
-        assertEquals("localhost", inetAddress.getHostName());
-        assertEquals("localhost", inetAddress.getHostString());
+    public void test_getHostNameCaches() throws Exception {
+        InetAddress inetAddress = InetAddress.getByAddress(LOOPBACK6_BYTES);
+        assertEquals("::1", inetAddress.getHostString());
+        assertEquals("ip6-localhost", inetAddress.getHostName());
+        // getHostString() should now be different.
+        assertEquals("ip6-localhost", inetAddress.getHostString());
+    }
 
-        inetAddress = InetAddress.getByName("127.0.0.1");
-        assertEquals("127.0.0.1", inetAddress.getHostString());
-        assertEquals("localhost", inetAddress.getHostName());
-        assertEquals("localhost", inetAddress.getHostString());
+    public void test_getByAddress_loopbackIpv4() throws Exception {
+        InetAddress inetAddress = InetAddress.getByAddress(LOOPBACK4_BYTES);
+        assertEquals(LOOPBACK4_BYTES, "localhost", inetAddress);
+        assertTrue(inetAddress.isLoopbackAddress());
+    }
+
+    public void test_getByAddress_loopbackIpv6() throws Exception {
+        InetAddress inetAddress = InetAddress.getByAddress(LOOPBACK6_BYTES);
+        assertEquals(LOOPBACK6_BYTES, "ip6-localhost", inetAddress);
+        assertTrue(inetAddress.isLoopbackAddress());
+    }
+
+    public void test_getByName_loopbackIpv4() throws Exception {
+        InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
+        assertEquals(LOOPBACK4_BYTES, "localhost", inetAddress);
+        assertTrue(inetAddress.isLoopbackAddress());
+    }
+
+    public void test_getByName_loopbackIpv6() throws Exception {
+        InetAddress inetAddress = InetAddress.getByName("::1");
+        assertEquals(LOOPBACK6_BYTES, "ip6-localhost", inetAddress);
+        assertTrue(inetAddress.isLoopbackAddress());
+    }
+
+    public void test_getAllByName_localhost() throws Exception {
+        InetAddress[] inetAddresses = InetAddress.getAllByName("localhost");
+        assertEquals(1, inetAddresses.length);
+        InetAddress inetAddress = inetAddresses[0];
+        assertEquals(LOOPBACK4_BYTES, "localhost", inetAddress);
+        assertTrue(inetAddress.isLoopbackAddress());
+    }
+
+    public void test_getAllByName_ip6_localhost() throws Exception {
+        InetAddress[] inetAddresses = InetAddress.getAllByName("ip6-localhost");
+        assertEquals(1, inetAddresses.length);
+        InetAddress inetAddress = inetAddresses[0];
+        assertEquals(LOOPBACK6_BYTES, "ip6-localhost", inetAddress);
+        assertTrue(inetAddress.isLoopbackAddress());
+    }
+
+    public void test_getByName_null() throws Exception {
+        InetAddress inetAddress = InetAddress.getByName("::1");
+
+        Set<InetAddress> expectedLoopbackAddresses =
+                createSet(Inet4Address.LOOPBACK, Inet6Address.LOOPBACK);
+        assertTrue(expectedLoopbackAddresses.contains(inetAddress));
+    }
+
+    public void test_getAllByName_null() throws Exception {
+        InetAddress[] inetAddresses = InetAddress.getAllByName(null);
+        assertEquals(2, inetAddresses.length);
+        Set<InetAddress> expectedLoopbackAddresses =
+                createSet(Inet4Address.LOOPBACK, Inet6Address.LOOPBACK);
+        assertEquals(expectedLoopbackAddresses, createSet(inetAddresses));
+    }
+
+    private static void assertEquals(
+        byte[] expectedAddressBytes, String expectedHostname, InetAddress actual) {
+        assertArrayEquals(expectedAddressBytes, actual.getAddress());
+        assertEquals(expectedHostname, actual.getHostName());
+
+    }
+
+    private static void assertArrayEquals(byte[] expected, byte[] actual) {
+        assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual),
+                Arrays.equals(expected, actual));
+    }
+
+    private static Set<InetAddress> createSet(InetAddress... members) {
+        return new HashSet<InetAddress>(Arrays.asList(members));
     }
 }