Merge "Move CtsLibcoreOjTestCases to group presubmit-large"
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 92bbc66..2623a51 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -595,7 +595,6 @@
         "nist-pkix-tests",
         "slf4j-jdk14",
         "sqlite-jdbc",
-        "tzdata-testing",
         "truth-prebuilt-jar",
     ],
 
@@ -1019,6 +1018,9 @@
 // avoid introducing compile time cycles.
 java_library {
     name: "art.module.api.annotations.for.system.modules",
+    visibility: [
+        "//art/libartservice",
+    ],
     srcs: [
         ":api_surface_annotation_files",
     ],
diff --git a/NativeCode.bp b/NativeCode.bp
index c93e214..5bfb49b 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -206,13 +206,6 @@
         "libnativehelper",
     ],
 
-    cflags: [
-        // -DANDROID_LINK_SHARED_ICU4C to enable access to the full ICU4C.
-        // See external/icu/android_icu4c/include/uconfig_local.h
-        // for more information.
-        "-DANDROID_LINK_SHARED_ICU4C",
-    ],
-
     strip: {
         keep_symbols: true,
     },
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index 031ddfa..e72d707 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -405,6 +405,17 @@
   }
 
   /**
+   * {@link java.text.SimpleDateFormat} does not handle some date symbols, e.g. 'B' / 'b',
+   * and simply ignore the symbol in formatting. Instead, we should avoid exposing the symbol
+   * entirely in all public APIs, e.g. {@link java.text.SimpleDateFormat#toPattern()},
+   * and thus we use a heuristic algorithm to remove the symbol. See http://b/174804526.
+   * See {@link #transformIcuDateTimePattern(String)} for documentation about the implementation.
+   */
+  public static String transformIcuDateTimePattern_forJavaText(String pattern) {
+    return transformIcuDateTimePattern(pattern);
+  }
+
+  /**
    * Rewrite the date/time pattern coming ICU to be consumed by libcore classes.
    * It's an ideal place to rewrite the pattern entirely when multiple symbols not digested
    * by libcore need to be removed/processed. Rewriting in single place could be more efficient
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index c255720..04170a6 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -413,21 +413,27 @@
         // libcore's java.text supports Gregorian calendar only.
         ExtendedCalendar extendedCalendar = ICU.getExtendedCalendar(locale, "gregorian");
 
-        fullTimeFormat = extendedCalendar.getDateTimePattern(
+        fullTimeFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.FULL);
-        longTimeFormat = extendedCalendar.getDateTimePattern(
+        longTimeFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.LONG);
-        mediumTimeFormat = extendedCalendar.getDateTimePattern(
+        mediumTimeFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.NONE, android.icu.text.DateFormat. MEDIUM);
-        shortTimeFormat = extendedCalendar.getDateTimePattern(
+        shortTimeFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.SHORT);
-        fullDateFormat = extendedCalendar.getDateTimePattern(
+        fullDateFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.FULL, android.icu.text.DateFormat.NONE);
-        longDateFormat = extendedCalendar.getDateTimePattern(
+        longDateFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.LONG, android.icu.text.DateFormat.NONE);
-        mediumDateFormat = extendedCalendar.getDateTimePattern(
+        mediumDateFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.MEDIUM, android.icu.text.DateFormat.NONE);
-        shortDateFormat = extendedCalendar.getDateTimePattern(
+        shortDateFormat = getDateTimeFormatString(extendedCalendar,
             android.icu.text.DateFormat.SHORT, android.icu.text.DateFormat.NONE);
     }
+
+    private static String getDateTimeFormatString(ExtendedCalendar extendedCalendar,
+            int dateStyle, int timeStyle) {
+        return ICU.transformIcuDateTimePattern_forJavaText(
+                extendedCalendar.getDateTimePattern(dateStyle, timeStyle));
+    }
 }
diff --git a/luni/src/main/java/libcore/util/FP16.java b/luni/src/main/java/libcore/util/FP16.java
index 602e1d4..78a3c19 100644
--- a/luni/src/main/java/libcore/util/FP16.java
+++ b/luni/src/main/java/libcore/util/FP16.java
@@ -158,18 +158,45 @@
     @libcore.api.CorePlatformApi
     public static final short POSITIVE_ZERO = (short) 0x0000;
 
+    /**
+     * The offset to shift by to obtain the sign bit.
+     */
     @libcore.api.CorePlatformApi
     public static final int SIGN_SHIFT                = 15;
+
+    /**
+     * The offset to shift by to obtain the exponent bits.
+     */
     @libcore.api.CorePlatformApi
     public static final int EXPONENT_SHIFT            = 10;
+
+    /**
+     * The bitmask to AND a number with to obtain the sign bit.
+     */
     @libcore.api.CorePlatformApi
     public static final int SIGN_MASK                 = 0x8000;
+
+    /**
+     * The bitmask to AND a number shifted by {@link #EXPONENT_SHIFT} right, to obtain exponent bits.
+     */
     @libcore.api.CorePlatformApi
     public static final int SHIFTED_EXPONENT_MASK     = 0x1f;
+
+    /**
+     * The bitmask to AND a number with to obtain significand bits.
+     */
     @libcore.api.CorePlatformApi
     public static final int SIGNIFICAND_MASK          = 0x3ff;
+
+    /**
+     * The bitmask to AND with to obtain exponent and significand bits.
+     */
     @libcore.api.CorePlatformApi
     public static final int EXPONENT_SIGNIFICAND_MASK = 0x7fff;
+
+    /**
+     * The offset of the exponent from the actual value.
+     */
     @libcore.api.CorePlatformApi
     public static final int EXPONENT_BIAS             = 15;
 
diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java
index def9c5d..6d1a135 100644
--- a/luni/src/test/java/libcore/android/system/OsTest.java
+++ b/luni/src/test/java/libcore/android/system/OsTest.java
@@ -49,21 +49,34 @@
 import java.time.Duration;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import junit.framework.TestCase;
-
 import libcore.io.IoUtils;
 import libcore.testing.io.TestIoUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 import static android.system.OsConstants.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
-public class OsTest extends TestCase {
+@RunWith(JUnit4.class)
+public class OsTest {
 
+    @Test
     public void testIsSocket() throws Exception {
         File f = new File("/dev/null");
         FileInputStream fis = new FileInputStream(f);
@@ -75,6 +88,7 @@
         s.close();
     }
 
+    @Test
     public void testFcntlInt() throws Exception {
         File f = File.createTempFile("OsTest", "tst");
         FileInputStream fis = null;
@@ -89,6 +103,7 @@
         }
     }
 
+    @Test
     public void testFcntlInt_udpSocket() throws Exception {
         final FileDescriptor fd = Os.socket(AF_INET, SOCK_DGRAM, 0);
         try {
@@ -106,6 +121,7 @@
         }
     }
 
+    @Test
     public void testFcntlInt_invalidCmd() throws Exception {
         final FileDescriptor fd = Os.socket(AF_INET, SOCK_DGRAM, 0);
         try {
@@ -119,7 +135,8 @@
         }
     }
 
-    public void testFcntlInt_nullFd() throws Exception {
+    @Test
+    public void testFcntlInt_nullFd() {
         try {
             Os.fcntlInt(null, F_SETFL, O_NONBLOCK);
             fail("Expected failure due to null file descriptor");
@@ -128,17 +145,20 @@
         }
     }
 
+    @Test
     public void testUnixDomainSockets_in_file_system() throws Exception {
         String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket";
         new File(path).delete();
         checkUnixDomainSocket(UnixSocketAddress.createFileSystem(path), false);
     }
 
+    @Test
     public void testUnixDomainSocket_abstract_name() throws Exception {
         // Linux treats a sun_path starting with a NUL byte as an abstract name. See unix(7).
         checkUnixDomainSocket(UnixSocketAddress.createAbstract("/abstract_name_unix_socket"), true);
     }
 
+    @Test
     public void testUnixDomainSocket_unnamed() throws Exception {
         final FileDescriptor fd = Os.socket(AF_UNIX, SOCK_STREAM, 0);
         // unix(7) says an unbound socket is unnamed.
@@ -172,8 +192,8 @@
                     byte[] request = new byte[256];
                     Os.read(clientFd, request, 0, request.length);
 
-                    String s = new String(request, "UTF-8");
-                    byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8");
+                    String s = new String(request, StandardCharsets.UTF_8);
+                    byte[] response = s.toUpperCase(Locale.ROOT).getBytes(StandardCharsets.UTF_8);
                     Os.write(clientFd, response, 0, response.length);
 
                     Os.close(clientFd);
@@ -191,13 +211,13 @@
 
         String string = "hello, world!";
 
-        byte[] request = string.getBytes("UTF-8");
+        byte[] request = string.getBytes(StandardCharsets.UTF_8);
         assertEquals(request.length, Os.write(clientFd, request, 0, request.length));
 
         byte[] response = new byte[request.length];
         assertEquals(response.length, Os.read(clientFd, response, 0, response.length));
 
-        assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8"));
+        assertEquals(string.toUpperCase(Locale.ROOT), new String(response, StandardCharsets.UTF_8));
 
         Os.close(clientFd);
     }
@@ -223,16 +243,17 @@
         checkNoName((UnixSocketAddress) Os.getsockname(fd));
     }
 
-    public void test_strsignal() throws Exception {
+    @Test
+    public void test_strsignal() {
         assertEquals("Killed", Os.strsignal(9));
         assertEquals("Unknown signal -1", Os.strsignal(-1));
     }
 
+    @Test
     public void test_byteBufferPositions_write_pwrite() throws Exception {
         FileOutputStream fos = new FileOutputStream(new File("/dev/null"));
         FileDescriptor fd = fos.getFD();
-        final byte[] contents = new String("goodbye, cruel world")
-                .getBytes(StandardCharsets.US_ASCII);
+        final byte[] contents = "goodbye, cruel world".getBytes(StandardCharsets.US_ASCII);
         ByteBuffer byteBuffer = ByteBuffer.wrap(contents);
 
         byteBuffer.position(0);
@@ -258,6 +279,7 @@
         fos.close();
     }
 
+    @Test
     public void test_byteBufferPositions_read_pread() throws Exception {
         FileInputStream fis = new FileInputStream(new File("/dev/zero"));
         FileDescriptor fd = fis.getFD();
@@ -286,7 +308,7 @@
         fis.close();
     }
 
-    static void checkByteBufferPositions_sendto_recvfrom(
+    private static void checkByteBufferPositions_sendto_recvfrom(
             int family, InetAddress loopback) throws Exception {
         final FileDescriptor serverFd = Os.socket(family, SOCK_STREAM, 0);
         Os.bind(serverFd, loopback, 0);
@@ -294,29 +316,27 @@
 
         InetSocketAddress address = (InetSocketAddress) Os.getsockname(serverFd);
 
-        final Thread server = new Thread(new Runnable() {
-            public void run() {
-                try {
-                    InetSocketAddress peerAddress = new InetSocketAddress();
-                    FileDescriptor clientFd = Os.accept(serverFd, peerAddress);
+        final Thread server = new Thread(() -> {
+            try {
+                InetSocketAddress peerAddress = new InetSocketAddress();
+                FileDescriptor clientFd = Os.accept(serverFd, peerAddress);
 
-                    // Attempt to receive a maximum of 24 bytes from the client, and then
-                    // close the connection.
-                    ByteBuffer buffer = ByteBuffer.allocate(16);
-                    int received = Os.recvfrom(clientFd, buffer, 0, null);
-                    assertTrue(received > 0);
-                    assertEquals(received, buffer.position());
+                // Attempt to receive a maximum of 24 bytes from the client, and then
+                // close the connection.
+                ByteBuffer buffer = ByteBuffer.allocate(16);
+                int received = Os.recvfrom(clientFd, buffer, 0, null);
+                assertTrue(received > 0);
+                assertEquals(received, buffer.position());
 
-                    ByteBuffer buffer2 = ByteBuffer.allocate(16);
-                    buffer2.position(8);
-                    received = Os.recvfrom(clientFd, buffer2, 0, null);
-                    assertTrue(received > 0);
-                    assertEquals(received + 8, buffer.position());
+                ByteBuffer buffer2 = ByteBuffer.allocate(16);
+                buffer2.position(8);
+                received = Os.recvfrom(clientFd, buffer2, 0, null);
+                assertTrue(received > 0);
+                assertEquals(received + 8, buffer.position());
 
-                    Os.close(clientFd);
-                } catch (Exception ex) {
-                    throw new RuntimeException(ex);
-                }
+                Os.close(clientFd);
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
             }
         });
 
@@ -346,9 +366,8 @@
         Os.close(clientFd);
     }
 
-    interface ExceptionalRunnable {
-
-        public void run() throws Exception;
+    private interface ExceptionalRunnable {
+        void run() throws Exception;
     }
 
     /**
@@ -377,7 +396,7 @@
     }
 
     private static void expectBindException(FileDescriptor socket, SocketAddress addr,
-            Class exClass, Integer expectedErrno) {
+            Class<? extends Exception> exClass, Integer expectedErrno) {
         String msg = String.format("bind(%s, %s)", socket, addr);
         expectException(() -> {
             Os.bind(socket, addr);
@@ -385,7 +404,7 @@
     }
 
     private static void expectConnectException(FileDescriptor socket, SocketAddress addr,
-            Class exClass, Integer expectedErrno) {
+            Class<? extends Exception> exClass, Integer expectedErrno) {
         String msg = String.format("connect(%s, %s)", socket, addr);
         expectException(() -> {
             Os.connect(socket, addr);
@@ -393,13 +412,13 @@
     }
 
     private static void expectSendtoException(FileDescriptor socket, SocketAddress addr,
-            Class exClass, Integer expectedErrno) {
+        Integer expectedErrno) {
         String msg = String.format("sendto(%s, %s)", socket, addr);
         byte[] packet = new byte[42];
         expectException(() -> {
                     Os.sendto(socket, packet, 0, packet.length, 0, addr);
                 },
-                exClass, expectedErrno, msg);
+            ErrnoException.class, expectedErrno, msg);
     }
 
     private static void expectBindConnectSendtoSuccess(FileDescriptor socket, String socketDesc,
@@ -424,7 +443,7 @@
 
                     assertEquals(addrISA.getAddress(), socknameISA.getAddress());
                     assertEquals(0, addrISA.getPort());
-                    assertFalse(0 == socknameISA.getPort());
+                    assertNotEquals(0, socknameISA.getPort());
                     addr = socknameISA;
                 }
 
@@ -434,8 +453,9 @@
                 Os.sendto(socket, packet, 0, packet.length, 0, addr);
                 // UNIX and IP sockets return different errors for this operation, so we can't check
                 // errno.
-                expectSendtoException(socket, null, ErrnoException.class, null);
-                expectSendtoException(null, null, ErrnoException.class, EBADF);
+                expectSendtoException(socket, null, null);
+                expectSendtoException(null, null, EBADF);
+                expectSendtoException(null, addr, EBADF);
 
                 // Expect that connect throws when any of its arguments are null.
                 expectConnectException(null, addr, ErrnoException.class, EBADF);
@@ -514,6 +534,7 @@
         return Os.socket(AF_UNIX, SOCK_DGRAM, 0);
     }
 
+    @Test
     public void testCrossFamilyBindConnectSendto() throws Exception {
         SocketAddress addrIpv4 = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0);
         SocketAddress addrIpv6 = new InetSocketAddress(InetAddress.getByName("::1"), 0);
@@ -539,6 +560,7 @@
         expectBindConnectSendtoSuccess(makeUnixSocket(), "unix", addrUnix);
     }
 
+    @Test
     public void testUnknownSocketAddressSubclass() throws Exception {
         class MySocketAddress extends SocketAddress {
 
@@ -577,6 +599,7 @@
         }
     }
 
+    @Test
     public void test_NetlinkSocket() throws Exception {
         FileDescriptor nlSocket = Os.socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
         try {
@@ -599,8 +622,10 @@
     // This test is excluded from CTS via the knownfailures.txt because it requires extra
     // permissions not available in CTS. To run it you have to use an -eng build and use a tool like
     // vogar that runs the Android runtime as a privileged user.
+    @Test
     public void test_PacketSocketAddress() throws Exception {
         NetworkInterface lo = NetworkInterface.getByName("lo");
+        assertNotNull(lo);
         FileDescriptor fd = Os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6);
         PacketSocketAddress addr =
                 new PacketSocketAddress(ETH_P_IPV6, lo.getIndex(), null /* sll_addr */);
@@ -614,6 +639,7 @@
 
         // The loopback address is ETH_ALEN bytes long and is all zeros.
         // http://lxr.free-electrons.com/source/drivers/net/loopback.c?v=3.10#L167
+        assertNotNull(bound.sll_addr);
         assertEquals(6, bound.sll_addr.length);
         for (int i = 0; i < 6; i++) {
             assertEquals(0, bound.sll_addr[i]);
@@ -665,16 +691,16 @@
 
     private static byte[] getIPv6AddressBytesAtOffset(byte[] packet, int offsetIndex) {
         byte[] address = new byte[16];
-        for (int i = 0; i < 16; i++) {
-            address[i] = packet[i + offsetIndex];
-        }
+        System.arraycopy(packet, offsetIndex, address, 0, 16);
         return address;
     }
 
+    @Test
     public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception {
         checkByteBufferPositions_sendto_recvfrom(AF_INET, InetAddress.getByName("127.0.0.1"));
     }
 
+    @Test
     public void test_byteBufferPositions_sendto_recvfrom_af_inet6() throws Exception {
         checkByteBufferPositions_sendto_recvfrom(AF_INET6, InetAddress.getByName("::1"));
     }
@@ -687,7 +713,8 @@
 
         InetSocketAddress to = ((InetSocketAddress) Os.getsockname(recvFd));
         FileDescriptor sendFd = Os.socket(family, SOCK_DGRAM, 0);
-        byte[] msg = ("Hello, I'm going to a socket address: " + to.toString()).getBytes("UTF-8");
+        byte[] msg = ("Hello, I'm going to a socket address: " + to.toString()).getBytes(
+            StandardCharsets.UTF_8);
         int len = msg.length;
 
         assertEquals(len, Os.sendto(sendFd, msg, 0, len, 0, to));
@@ -697,14 +724,17 @@
         assertEquals(loopback, from.getAddress());
     }
 
+    @Test
     public void test_sendtoSocketAddress_af_inet() throws Exception {
         checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1"));
     }
 
+    @Test
     public void test_sendtoSocketAddress_af_inet6() throws Exception {
         checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1"));
     }
 
+    @Test
     public void test_socketFamilies() throws Exception {
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_STREAM, 0);
         Os.bind(fd, InetAddress.getByName("::"), 0);
@@ -729,11 +759,6 @@
         }
     }
 
-    private static void assertArrayEquals(byte[] expected, byte[] actual) {
-        assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual),
-                Arrays.equals(expected, actual));
-    }
-
     private static void checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet,
             byte type, byte responseType, boolean useSendto) throws Exception {
         int len = packet.length;
@@ -755,12 +780,13 @@
         assertEquals(received[5], (byte) (icmpId & 0xff));
 
         received = Arrays.copyOf(received, len);
-        received[0] = (byte) type;
+        received[0] = type;
         received[2] = received[3] = 0;  // Checksum.
         received[4] = received[5] = 0;  // ICMP ID.
         assertArrayEquals(packet, received);
     }
 
+    @Test
     public void test_socketPing() throws Exception {
         final byte ICMP_ECHO = 8, ICMP_ECHOREPLY = 0;
         final byte ICMPV6_ECHO_REQUEST = (byte) 128, ICMPV6_ECHO_REPLY = (byte) 129;
@@ -779,6 +805,7 @@
         checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false);
     }
 
+    @Test
     public void test_Ipv4Fallback() throws Exception {
         // This number of iterations gives a ~60% chance of creating the conditions that caused
         // http://b/23088314 without making test times too long. On a hammerhead running MRZ37C
@@ -796,6 +823,7 @@
         }
     }
 
+    @Test
     public void test_unlink() throws Exception {
         File f = File.createTempFile("OsTest", "tst");
         assertTrue(f.exists());
@@ -811,6 +839,7 @@
     }
 
     // b/27294715
+    @Test
     public void test_recvfrom_concurrentShutdown() throws Exception {
         final FileDescriptor serverFd = Os.socket(AF_INET, SOCK_DGRAM, 0);
         Os.bind(serverFd, InetAddress.getByName("127.0.0.1"), 0);
@@ -818,22 +847,20 @@
         StructTimeval tv = StructTimeval.fromMillis(4000);
         Os.setsockoptTimeval(serverFd, SOL_SOCKET, SO_RCVTIMEO, tv);
 
-        final AtomicReference<Exception> killerThreadException = new AtomicReference<Exception>(
-                null);
-        final Thread killer = new Thread(new Runnable() {
-            public void run() {
+        final AtomicReference<Exception> killerThreadException = new AtomicReference<>(
+            null);
+        final Thread killer = new Thread(() -> {
+            try {
+                Thread.sleep(2000);
                 try {
-                    Thread.sleep(2000);
-                    try {
-                        Os.shutdown(serverFd, SHUT_RDWR);
-                    } catch (ErrnoException expected) {
-                        if (OsConstants.ENOTCONN != expected.errno) {
-                            killerThreadException.set(expected);
-                        }
+                    Os.shutdown(serverFd, SHUT_RDWR);
+                } catch (ErrnoException expected) {
+                    if (OsConstants.ENOTCONN != expected.errno) {
+                        killerThreadException.set(expected);
                     }
-                } catch (Exception ex) {
-                    killerThreadException.set(ex);
                 }
+            } catch (Exception ex) {
+                killerThreadException.set(ex);
             }
         });
         killer.start();
@@ -841,13 +868,14 @@
         ByteBuffer buffer = ByteBuffer.allocate(16);
         InetSocketAddress srcAddress = new InetSocketAddress();
         int received = Os.recvfrom(serverFd, buffer, 0, srcAddress);
-        assertTrue(received == 0);
+        assertEquals(0, received);
         Os.close(serverFd);
 
         killer.join();
         assertNull(killerThreadException.get());
     }
 
+    @Test
     public void test_xattr() throws Exception {
         final String NAME_TEST = "user.meow";
 
@@ -899,6 +927,7 @@
         }
     }
 
+    @Test
     public void test_xattr_NPE() throws Exception {
         File file = File.createTempFile("xattr", "test");
         final String path = file.getAbsolutePath();
@@ -954,7 +983,8 @@
         }
     }
 
-    public void test_xattr_Errno() throws Exception {
+    @Test
+    public void test_xattr_Errno() {
         final String NAME_TEST = "user.meow";
         final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8);
 
@@ -1016,6 +1046,7 @@
         }
     }
 
+    @Test
     public void test_realpath() throws Exception {
         File tmpDir = new File(System.getProperty("java.io.tmpdir"));
         // This is a chicken and egg problem. We have no way of knowing whether
@@ -1046,7 +1077,7 @@
         }
     }
 
-    private int[] getKernelVersion() throws Exception {
+    private int[] getKernelVersion() {
         // Example:
         // 4.9.29-g958411d --> 4.9
         String release = Os.uname().release;
@@ -1055,14 +1086,15 @@
         return new int[]{ Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) };
     }
 
-    private boolean kernelIsAtLeast(int major, int minor) throws Exception {
+    private boolean kernelIsAtLeast(int major, int minor) {
         int[] version = getKernelVersion();
         return version[0] > major || (version[0] == major && version[1] >= minor);
     }
 
+    @Test
     public void test_socket_udpGro_setAndGet() throws Exception {
         // UDP GRO not required to be enabled on kernels prior to 5.4
-        if (!kernelIsAtLeast(5, 4)) return;
+        assumeTrue(kernelIsAtLeast(5, 4));
 
         final FileDescriptor fd = Os.socket(AF_INET6, SOCK_DGRAM, 0);
         try {
@@ -1074,9 +1106,10 @@
         }
     }
 
+    @Test
     public void test_socket_udpGso_set() throws Exception {
         // UDP GSO not required to be enabled on kernels prior to 4.19.
-        if (!kernelIsAtLeast(4, 19)) return;
+        assumeTrue(kernelIsAtLeast(4, 19));
 
         final FileDescriptor fd = Os.socket(AF_INET, SOCK_DGRAM, 0);
         try {
@@ -1094,6 +1127,7 @@
      * Tests that TCP_USER_TIMEOUT can be set on a TCP socket, but doesn't test
      * that it behaves as expected.
      */
+    @Test
     public void test_socket_tcpUserTimeout_setAndGet() throws Exception {
         final FileDescriptor fd = Os.socket(AF_INET, SOCK_STREAM, 0);
         try {
@@ -1114,6 +1148,7 @@
         }
     }
 
+    @Test
     public void test_socket_tcpUserTimeout_doesNotWorkOnDatagramSocket() throws Exception {
         final FileDescriptor fd = Os.socket(AF_INET, SOCK_DGRAM, 0);
         try {
@@ -1127,6 +1162,7 @@
         }
     }
 
+    @Test
     public void test_socket_sockoptTimeval_readWrite() throws Exception {
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_STREAM, 0);
         try {
@@ -1148,7 +1184,11 @@
         }
     }
 
+    @Test
     public void test_socket_setSockoptTimeval_effective() throws Exception {
+        // b/176104885 Older devices can return a few ms early, add a tolerance for them
+        long timeoutTolerance = kernelIsAtLeast(3, 18) ? 0 : 10;
+
         int timeoutValueMillis = 250;
         int allowedTimeoutMillis = 3000;
 
@@ -1163,11 +1203,9 @@
             expectException(() -> Os.read(fd, request, 0, request.length),
                     ErrnoException.class, EAGAIN, "Expected timeout");
             long durationMillis = Duration.ofNanos(System.nanoTime() - startTime).toMillis();
-            // TODO(b/176104885): Sometimes returns 1 msec early. It's unclear that's correct.
-            // We haven't seen this on modern devices, and allow it for now. Needs investigation.
             assertTrue("Timeout of " + timeoutValueMillis + "ms returned after "
                     + durationMillis +"ms",
-                durationMillis >= timeoutValueMillis - 1);
+                durationMillis >= timeoutValueMillis - timeoutTolerance);
             assertTrue("Timeout of " + timeoutValueMillis + "ms failed to return within "
                     + allowedTimeoutMillis  + "ms",
                 durationMillis < allowedTimeoutMillis);
@@ -1176,13 +1214,15 @@
         }
     }
 
-    public void test_socket_setSockoptTimeval_nullFd() throws Exception {
+    @Test
+    public void test_socket_setSockoptTimeval_nullFd() {
         StructTimeval tv = StructTimeval.fromMillis(500);
         expectException(
                 () -> Os.setsockoptTimeval(null, SOL_SOCKET, SO_RCVTIMEO, tv),
                 ErrnoException.class, EBADF, "setsockoptTimeval(null, ...)");
     }
 
+    @Test
     public void test_socket_setSockoptTimeval_fileFd() throws Exception {
         File testFile = createTempFile("test_socket_setSockoptTimeval_invalidFd", "");
         try (FileInputStream fis = new FileInputStream(testFile)) {
@@ -1195,6 +1235,7 @@
         }
     }
 
+    @Test
     public void test_socket_setSockoptTimeval_badFd() throws Exception {
         StructTimeval tv = StructTimeval.fromMillis(500);
         FileDescriptor invalidFd = Os.socket(AF_INET6, SOCK_STREAM, 0);
@@ -1205,6 +1246,7 @@
                 ErrnoException.class, EBADF, "setsockoptTimeval(<closed fd>, ...)");
     }
 
+    @Test
     public void test_socket_setSockoptTimeval_invalidLevel() throws Exception {
         StructTimeval tv = StructTimeval.fromMillis(500);
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_STREAM, 0);
@@ -1218,6 +1260,7 @@
         }
     }
 
+    @Test
     public void test_socket_setSockoptTimeval_invalidOpt() throws Exception {
         StructTimeval tv = StructTimeval.fromMillis(500);
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_STREAM, 0);
@@ -1231,6 +1274,7 @@
         }
     }
 
+    @Test
     public void test_socket_setSockoptTimeval_nullTimeVal() throws Exception {
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_STREAM, 0);
         try {
@@ -1242,6 +1286,7 @@
         }
     }
 
+    @Test
     public void test_socket_getSockoptTimeval_invalidOption() throws Exception {
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_STREAM, 0);
         try {
@@ -1254,19 +1299,22 @@
         }
     }
 
+    @Test
     public void test_if_nametoindex_if_indextoname() throws Exception {
-        List<NetworkInterface> nis = Collections.list(NetworkInterface.getNetworkInterfaces());
+        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+        assertNotNull(networkInterfaces);
+        List<NetworkInterface> nis = Collections.list(networkInterfaces);
 
         assertTrue(nis.size() > 0);
         for (NetworkInterface ni : nis) {
             int index = ni.getIndex();
             String name = ni.getName();
             assertEquals(index, Os.if_nametoindex(name));
-            assertTrue(Os.if_indextoname(index).equals(name));
+            assertEquals(Os.if_indextoname(index), name);
         }
 
         assertEquals(0, Os.if_nametoindex("this-interface-does-not-exist"));
-        assertEquals(null, Os.if_indextoname(-1000));
+        assertNull(Os.if_indextoname(-1000));
 
         try {
             Os.if_nametoindex(null);
@@ -1284,6 +1332,7 @@
         }
     }
 
+    @Test
     public void test_readlink() throws Exception {
         File path = new File(TestIoUtils.createTemporaryDirectory("test_readlink"), "symlink");
 
@@ -1294,17 +1343,18 @@
         // failure are still on 3.18, far from current). Given that we don't
         // really care here, just use 2048 instead. http://b/33306057.
         int size = 2048;
-        String xs = "";
+        StringBuilder xs = new StringBuilder();
         for (int i = 0; i < size - 1; ++i) {
-            xs += "x";
+            xs.append("x");
         }
 
-        Os.symlink(xs, path.getPath());
+        Os.symlink(xs.toString(), path.getPath());
 
-        assertEquals(xs, Os.readlink(path.getPath()));
+        assertEquals(xs.toString(), Os.readlink(path.getPath()));
     }
 
     // Address should be correctly set for empty packets. http://b/33481605
+    @Test
     public void test_recvfrom_EmptyPacket() throws Exception {
         try (DatagramSocket ds = new DatagramSocket();
              DatagramSocket srcSock = new DatagramSocket()) {
@@ -1320,6 +1370,7 @@
         }
     }
 
+    @Test
     public void test_fstat_times() throws Exception {
         File file = File.createTempFile("OsTest", "fstattest");
         FileOutputStream fos = new FileOutputStream(file);
@@ -1338,6 +1389,7 @@
         assertEquals(0, structStat1.st_atim.compareTo(structStat2.st_atim));
     }
 
+    @Test
     public void test_getrlimit() throws Exception {
         StructRlimit rlimit = Os.getrlimit(OsConstants.RLIMIT_NOFILE);
         // We can't really make any assertions about these values since they might vary from
@@ -1348,7 +1400,8 @@
     }
 
     // http://b/65051835
-    public void test_pipe2_errno() throws Exception {
+    @Test
+    public void test_pipe2_errno() {
         try {
             // flag=-1 is not a valid value for pip2, will EINVAL
             Os.pipe2(-1);
@@ -1358,7 +1411,8 @@
     }
 
     // http://b/65051835
-    public void test_sendfile_errno() throws Exception {
+    @Test
+    public void test_sendfile_errno() {
         try {
             // FileDescriptor.out is not open for input, will cause EBADF
             Int64Ref offset = new Int64Ref(10);
@@ -1368,6 +1422,7 @@
         }
     }
 
+    @Test
     public void test_sendfile_null() throws Exception {
         File in = createTempFile("test_sendfile_null", "Hello, world!");
         try {
@@ -1378,6 +1433,7 @@
         }
     }
 
+    @Test
     public void test_sendfile_offset() throws Exception {
         File in = createTempFile("test_sendfile_offset", "Hello, world!");
         try {
@@ -1417,6 +1473,7 @@
         return f;
     }
 
+    @Test
     public void test_odirect() throws Exception {
         File testFile = createTempFile("test_odirect", "");
         try {
@@ -1433,6 +1490,7 @@
         }
     }
 
+    @Test
     public void test_splice() throws Exception {
         FileDescriptor[] pipe = Os.pipe2(0);
         File in = createTempFile("splice1", "foobar");
@@ -1465,6 +1523,7 @@
         Os.close(pipe[1]);
     }
 
+    @Test
     public void test_splice_errors() throws Exception {
         File in = createTempFile("splice3", "");
         File out = createTempFile("splice4", "");
@@ -1505,6 +1564,7 @@
         Os.close(pipe[1]);
     }
 
+    @Test
     public void testCloseNullFileDescriptor() throws Exception {
         try {
             Os.close(null);
@@ -1513,6 +1573,7 @@
         }
     }
 
+    @Test
     public void testSocketpairNullFileDescriptor1() throws Exception {
         try {
             Os.socketpair(AF_UNIX, SOCK_STREAM, 0, null, new FileDescriptor());
@@ -1521,6 +1582,7 @@
         }
     }
 
+    @Test
     public void testSocketpairNullFileDescriptor2() throws Exception {
         try {
             Os.socketpair(AF_UNIX, SOCK_STREAM, 0, new FileDescriptor(), null);
@@ -1529,6 +1591,7 @@
         }
     }
 
+    @Test
     public void testSocketpairNullFileDescriptorBoth() throws Exception {
         try {
             Os.socketpair(AF_UNIX, SOCK_STREAM, 0, null, null);
@@ -1537,30 +1600,35 @@
         }
     }
 
+    @Test
     public void testInetPtonIpv4() {
         String srcAddress = "127.0.0.1";
         InetAddress inetAddress = Os.inet_pton(AF_INET, srcAddress);
         assertEquals(srcAddress, inetAddress.getHostAddress());
     }
 
+    @Test
     public void testInetPtonIpv6() {
         String srcAddress = "1123:4567:89ab:cdef:fedc:ba98:7654:3210";
         InetAddress inetAddress = Os.inet_pton(AF_INET6, srcAddress);
         assertEquals(srcAddress, inetAddress.getHostAddress());
     }
 
+    @Test
     public void testInetPtonInvalidFamily() {
         String srcAddress = "127.0.0.1";
         InetAddress inetAddress = Os.inet_pton(AF_UNIX, srcAddress);
         assertNull(inetAddress);
     }
 
+    @Test
     public void testInetPtonWrongFamily() {
         String srcAddress = "127.0.0.1";
         InetAddress inetAddress = Os.inet_pton(AF_INET6, srcAddress);
         assertNull(inetAddress);
     }
 
+    @Test
     public void testInetPtonInvalidData() {
         String srcAddress = "10.1";
         InetAddress inetAddress = Os.inet_pton(AF_INET, srcAddress);
@@ -1570,6 +1638,7 @@
     /**
      * Verifies the {@link OsConstants#MAP_ANONYMOUS}.
      */
+    @Test
     public void testMapAnonymous() throws Exception {
         final long size = 4096;
         final long address = Os.mmap(0, size, PROT_READ,
@@ -1578,6 +1647,7 @@
         Os.munmap(address, size);
     }
 
+    @Test
     public void testMemfdCreate() throws Exception {
         FileDescriptor fd = null;
         try {
@@ -1606,6 +1676,7 @@
         }
     }
 
+    @Test
     public void testMemfdCreateFlags() throws Exception {
         FileDescriptor fd = null;
 
@@ -1615,8 +1686,8 @@
             assertNotNull(fd);
             assertTrue(fd.valid());
             int flags = Os.fcntlVoid(fd, F_GETFD);
-            assertTrue("Expected flags to not include " + FD_CLOEXEC + ", actual value: " + flags,
-                    0 == (flags & FD_CLOEXEC));
+            assertEquals("Expected flags to not include " + FD_CLOEXEC + ", actual value: " + flags,
+                0, (flags & FD_CLOEXEC));
         } finally {
             if (fd != null) {
                 Os.close(fd);
@@ -1638,7 +1709,8 @@
         }
     }
 
-    public void testMemfdCreateErrno() throws Exception {
+    @Test
+    public void testMemfdCreateErrno() {
         expectException(() -> Os.memfd_create(null, 0), NullPointerException.class, null,
                 "memfd_create(null, 0)");
 
diff --git a/luni/src/test/java/libcore/highmemorytest/java/text/DateFormatTest.java b/luni/src/test/java/libcore/highmemorytest/java/text/DateFormatTest.java
new file mode 100644
index 0000000..257a5de
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/java/text/DateFormatTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 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.highmemorytest.java.text;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tests {@link DateFormat} but runs in a separate java package because loading data in all locales
+ * creates a lot of garbage / permanent heap growth in ICU4J and causes gcstress test failing
+ * in ART test environment. See http://b/161420453. No known users/apps load all locale data like
+ * this test.
+ */
+@RunWith(Parameterized.class)
+public class DateFormatTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    // 1 January 2022 00:00:00 GMT+00:00
+    private static final Date TEST_DATE = new Date(1640995200000L);
+
+    /**
+     * Test {@link DateFormat#format(Date)} does not crash on available locales.
+     */
+    @Test
+    public void test_format_allLocales() {
+        for (int formatStyle = DateFormat.FULL; formatStyle <= DateFormat.SHORT;
+                formatStyle++) {
+            try {
+                DateFormat.getDateInstance(formatStyle, locale)
+                        .format(TEST_DATE);
+                DateFormat.getTimeInstance(formatStyle, locale)
+                        .format(TEST_DATE);
+                DateFormat.getDateTimeInstance(formatStyle, formatStyle, locale)
+                        .format(TEST_DATE);
+            } catch (RuntimeException cause) {
+                throw new RuntimeException("locale:" + locale +
+                        " formatStyle:" + formatStyle, cause);
+            }
+        }
+    }
+
+    /**
+     * Test {@link SimpleDateFormat#toPattern()} contains only supported symbols.
+     */
+    @Test
+    public void test_toPattern_allLocales() {
+        for (int formatStyle = DateFormat.FULL; formatStyle <= DateFormat.SHORT;
+                formatStyle++) {
+            try {
+                assertSupportedSymbols(DateFormat.getDateInstance(formatStyle, locale), locale);
+                assertSupportedSymbols(DateFormat.getTimeInstance(formatStyle, locale), locale);
+                assertSupportedSymbols(DateFormat.getDateTimeInstance(
+                        formatStyle, formatStyle, locale), locale);
+            } catch (RuntimeException cause) {
+                throw new RuntimeException("locale:" + locale +
+                        " formatStyle:" + formatStyle, cause);
+            }
+        }
+    }
+
+    private static final Set<Character> SUPPORTED_SYMBOLS = "GyYMLwWDdFEuaHkKhmsSzZXLc".chars()
+            .mapToObj(c -> (char)c)
+            .collect(Collectors.toSet());
+
+    private static void assertSupportedSymbols(DateFormat dateFormat, Locale locale) {
+        SimpleDateFormat simpleDateFormat = (SimpleDateFormat) dateFormat;
+        String pattern = simpleDateFormat.toPattern();
+        // The string in the quotation is not interpreted.
+        boolean inQuotation = false;
+        for (int i = 0; i < pattern.length(); i++) {
+            char curr = pattern.charAt(i);
+            if (curr == '\'') {
+                inQuotation = !inQuotation;
+                continue;
+            }
+            if (inQuotation) {
+                continue;
+            }
+
+            if ((curr >= 'a' && curr <= 'z') || (curr >= 'A' && curr <= 'Z')) { // ASCII alphabets
+                assertTrue("Locale:" + locale + " Pattern:" + pattern + " has unsupported symbol "
+                                + curr, SUPPORTED_SYMBOLS.contains(curr));
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/highmemorytest/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/highmemorytest/java/text/DecimalFormatTest.java
new file mode 100644
index 0000000..9baf972
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/java/text/DecimalFormatTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 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.highmemorytest.java.text;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Currency;
+import java.util.Locale;
+
+/**
+ * Runs in a separate java package because loading data in all locales creates a lot of garbage /
+ * permanent heap growth in ICU4J and causes gcstress test failing in ART test environment.
+ * See http://b/161420453.
+ */
+@RunWith(Parameterized.class)
+public class DecimalFormatTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    /**
+     * Test no extra spacing between currency symbol and the numeric amount
+     */
+    @Test
+    public void testCurrencySymbolSpacing() {
+        Currency currency = Currency.getInstance(Locale.US);
+        for (Locale locale : Locale.getAvailableLocales()) {
+            DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
+            String formattedZero = new DecimalFormat("0", dfs).format(0);
+
+            assertCurrencyFormat("USD" + formattedZero, "\u00a4\u00a40", dfs, currency, locale);
+            assertCurrencyFormat(formattedZero + "USD", "0\u00a4\u00a4", dfs, currency, locale);
+            assertCurrencyFormat(currency.getSymbol(locale) + formattedZero, "\u00a40", dfs,
+                    currency, locale);
+            assertCurrencyFormat(formattedZero + currency.getSymbol(locale), "0\u00a4", dfs,
+                    currency, locale);
+        }
+    }
+
+    private static void assertCurrencyFormat(String expected, String pattern,
+            DecimalFormatSymbols dfs, Currency currency, Locale locale) {
+        DecimalFormat df = new DecimalFormat(pattern, dfs);
+        df.setCurrency(currency);
+        df.setMaximumFractionDigits(0);
+        assertEquals("Not formatted as expected with pattern " + pattern + " in locale " + locale,
+                expected, df.format(0));
+    }
+}
diff --git a/luni/src/test/java/libcore/highmemorytest/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/highmemorytest/java/text/SimpleDateFormatTest.java
new file mode 100644
index 0000000..63ec023
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/java/text/SimpleDateFormatTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 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.highmemorytest.java.text;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Tests {@link SimpleDateFormat} but runs in a separate java package because loading data in all
+ * locales creates a lot of garbage / permanent heap growth in ICU4J and causes gcstress test
+ * failing in ART test environment. See http://b/161420453.
+ */
+@RunWith(Parameterized.class)
+public class SimpleDateFormatTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    @Test
+    public void testLocales() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzzz", locale);
+        sdf.format(new Date(0));
+    }
+}
diff --git a/luni/src/test/java/libcore/highmemorytest/java/time/format/DateTimeFormatterTest.java b/luni/src/test/java/libcore/highmemorytest/java/time/format/DateTimeFormatterTest.java
new file mode 100644
index 0000000..e2d28ec
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/java/time/format/DateTimeFormatterTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 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.highmemorytest.java.time.format;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.chrono.Chronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.time.temporal.TemporalAccessor;
+import java.util.Locale;
+
+/**
+ * Additional tests for {@link DateTimeFormatter}. Runs in a separate java package because
+ * loading data in all locales creates a lot of garbage / permanent heap growth in ICU4J and
+ * causes gcstress test failing in ART test environment. See http://b/161420453.
+ *
+ * @see tck.java.time.format.TCKDateTimeFormatter
+ * @see test.java.time.format.TestDateTimeFormatter
+ * @see libcore.java.time.format.DateTimeFormatterTest
+ */
+@RunWith(Parameterized.class)
+public class DateTimeFormatterTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter
+    public Locale locale;
+
+    // 1 January 2022 00:00:00 GMT+00:00
+    private static final Instant TEST_INSTANT = Instant.ofEpochSecond(1640995200L);
+
+    /**
+     * Test {@link DateTimeFormatter#format(TemporalAccessor)} does not crash on available locales.
+     */
+    @Test
+    public void test_format_allLocales() {
+        for (FormatStyle formatStyle : FormatStyle.values()) {
+            try {
+                DateTimeFormatter.ofLocalizedTime(formatStyle)
+                        .withLocale(locale)
+                        .withZone(ZoneOffset.UTC)
+                        .format(TEST_INSTANT);
+
+                DateTimeFormatter.ofLocalizedDate(formatStyle)
+                        .withLocale(locale)
+                        .withZone(ZoneOffset.UTC)
+                        .format(TEST_INSTANT);
+
+                DateTimeFormatter.ofLocalizedDateTime(formatStyle)
+                        .withLocale(locale)
+                        .withZone(ZoneOffset.UTC)
+                        .format(TEST_INSTANT);
+            } catch (RuntimeException cause) {
+                throw new RuntimeException("formatStyle:" + formatStyle.name(), cause);
+            }
+        }
+    }
+
+    /**
+     * Test {@link DateTimeFormatter#format(TemporalAccessor)} does not crash on available locales
+     * with all possible Chronologies.
+     */
+    @Test
+    public void test_format_allLocales_allChronologies() {
+        for (Chronology chronology : Chronology.getAvailableChronologies()) {
+            for (FormatStyle formatStyle : FormatStyle.values()) {
+                try {
+                    DateTimeFormatter.ofLocalizedTime(formatStyle)
+                            .withLocale(locale)
+                            .withChronology(chronology)
+                            .withZone(ZoneOffset.UTC)
+                            .format(TEST_INSTANT);
+
+                    DateTimeFormatter.ofLocalizedDate(formatStyle)
+                            .withLocale(locale)
+                            .withChronology(chronology)
+                            .withZone(ZoneOffset.UTC)
+                            .format(TEST_INSTANT);
+
+                    DateTimeFormatter.ofLocalizedDateTime(formatStyle)
+                            .withLocale(locale)
+                            .withChronology(chronology)
+                            .withZone(ZoneOffset.UTC)
+                            .format(TEST_INSTANT);
+                } catch (RuntimeException cause) {
+                    throw new RuntimeException("Chronology:" + chronology +
+                            " formatStyle:" + formatStyle.name(), cause);
+                }
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/highmemorytest/java/util/CalendarTest.java b/luni/src/test/java/libcore/highmemorytest/java/util/CalendarTest.java
new file mode 100644
index 0000000..036ed9f
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/java/util/CalendarTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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.highmemorytest.java.util;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+/**
+ * Runs in a separate java package because loading data in all locales creates a lot of garbage /
+ * permanent heap growth in ICU4J and causes gcstress test failing in ART test environment.
+ * See http://b/161420453.
+ */
+@RunWith(Parameterized.class)
+public class CalendarTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    /**
+     * Ensures that Gregorian is the default Calendar for all Locales in Android. This is the
+     * historic behavior on Android; this test exists to avoid unintentional regressions.
+     * http://b/80294184
+     */
+    @Test
+    public void testAllDefaultCalendar_Gregorian() {
+        assertTrue("Default calendar should be Gregorian: " + locale,
+                Calendar.getInstance(locale) instanceof GregorianCalendar);
+    }
+
+}
diff --git a/luni/src/test/java/libcore/highmemorytest/java/util/CurrencyTest.java b/luni/src/test/java/libcore/highmemorytest/java/util/CurrencyTest.java
new file mode 100644
index 0000000..d1cbf5e
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/java/util/CurrencyTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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.highmemorytest.java.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Currency;
+import java.util.Locale;
+
+/**
+ * Runs in a separate java package because loading data in all locales creates a lot of garbage /
+ * permanent heap growth in ICU4J and causes gcstress test failing in ART test environment.
+ * See http://b/161420453.
+ */
+@RunWith(Parameterized.class)
+public class CurrencyTest {
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    @Test
+    public void test_currencyCodeIcuConsistency() {
+        Currency javaCurrency = getCurrency(locale);
+        if (javaCurrency == null) {
+            return;
+        }
+        assertEquals("Currency code is not consistent:" + locale,
+                android.icu.util.Currency.getInstance(locale).getCurrencyCode(),
+                javaCurrency.getCurrencyCode());
+    }
+
+    private static Currency getCurrency(Locale l) {
+        try {
+            return Currency.getInstance(l);
+        } catch (IllegalArgumentException e) {
+            // The locale could have no country or does not have currency for other reasons.
+            return null;
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/highmemorytest/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/highmemorytest/libcore/icu/LocaleDataTest.java
new file mode 100644
index 0000000..ab396f9
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/libcore/icu/LocaleDataTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 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.highmemorytest.libcore.icu;
+
+import static org.junit.Assert.assertTrue;
+
+import libcore.icu.LocaleData;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Locale;
+
+@RunWith(Parameterized.class)
+public class LocaleDataTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    @Test
+    public void testLongDateTimeFormat() {
+        LocaleData d = LocaleData.get(locale);
+        int dateLength = d.longDateFormat.length();
+        assertTrue("LocaleData.longDateFormat has zero length: " + dateLength, dateLength != 0);
+        int timeLength = d.longTimeFormat.length();
+        assertTrue("LocaleData.longTimeFormat has zero length: " + timeLength, timeLength != 0);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index 2b420bb..4e5e994 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -408,34 +408,6 @@
         assertEquals(expected, numberFormat.format(2.01));
     }
 
-    /**
-     * Test no extra spacing between currency symbol and the numeric amount
-     */
-    public void testCurrencySymbolSpacing() {
-        Currency currency = Currency.getInstance(Locale.US);
-        for (Locale locale : Locale.getAvailableLocales()) {
-            DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
-            String formattedZero = new DecimalFormat("0", dfs).format(0);
-
-            assertCurrencyFormat("USD" + formattedZero, "\u00a4\u00a40", dfs, currency, locale);
-            assertCurrencyFormat(formattedZero + "USD", "0\u00a4\u00a4", dfs, currency, locale);
-            assertCurrencyFormat(currency.getSymbol(locale) + formattedZero, "\u00a40", dfs,
-                    currency, locale);
-            assertCurrencyFormat(formattedZero + currency.getSymbol(locale), "0\u00a4", dfs,
-                    currency, locale);
-        }
-    }
-
-    private static void assertCurrencyFormat(String expected, String pattern,
-            DecimalFormatSymbols dfs,
-            Currency currency, Locale locale) {
-        DecimalFormat df = new DecimalFormat(pattern, dfs);
-        df.setCurrency(currency);
-        df.setMaximumFractionDigits(0);
-        assertEquals("Not formatted as expected with pattern " + pattern + " in locale " + locale,
-                expected, df.format(0));
-    }
-
     // http://b/27855939
     public void testBug27855939() {
         DecimalFormat df = new DecimalFormat("00");
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index 55a84e0..a1c206d 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -388,15 +388,6 @@
         assertEquals(20, calendar.get(Calendar.HOUR_OF_DAY)); // 9:00 GMT+11:00
         assertEquals(0, calendar.get(Calendar.MINUTE));
     }
-
-    public void testLocales() throws Exception {
-        // Just run through them all. Handy as a poor man's benchmark, and a confidence check.
-        for (Locale l : Locale.getAvailableLocales()) {
-            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzzz", l);
-            sdf.format(new Date(0));
-        }
-    }
-
     // http://code.google.com/p/android/issues/detail?id=14963
     public void testParseTimezoneOnly() throws Exception {
         new SimpleDateFormat("z", Locale.FRANCE).parse("UTC");
diff --git a/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java b/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java
index 7ab33f7..7db90cd 100644
--- a/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java
+++ b/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java
@@ -106,71 +106,4 @@
         assertEquals(23, accessor.getLong(ChronoField.HOUR_OF_DAY));
         assertEquals(59, accessor.getLong(ChronoField.MINUTE_OF_HOUR));
     }
-
-
-    /**
-     * Test {@link DateTimeFormatter#format(TemporalAccessor)} does not crash on available locales.
-     */
-    @Test
-    public void test_format_allLocales() {
-        for (Locale locale : Locale.getAvailableLocales()) {
-            for (FormatStyle formatStyle : FormatStyle.values()) {
-                try {
-                    DateTimeFormatter.ofLocalizedTime(formatStyle)
-                            .withLocale(locale)
-                            .withZone(ZoneOffset.UTC)
-                            .format(TEST_INSTANT);
-
-                    DateTimeFormatter.ofLocalizedDate(formatStyle)
-                            .withLocale(locale)
-                            .withZone(ZoneOffset.UTC)
-                            .format(TEST_INSTANT);
-
-                    DateTimeFormatter.ofLocalizedDateTime(formatStyle)
-                            .withLocale(locale)
-                            .withZone(ZoneOffset.UTC)
-                            .format(TEST_INSTANT);
-                } catch (RuntimeException cause) {
-                    throw new RuntimeException("locale:" + locale +
-                            " formatStyle:" + formatStyle.name(), cause);
-                }
-            }
-        }
-    }
-
-    /**
-     * Test {@link DateTimeFormatter#format(TemporalAccessor)} does not crash on available locales
-     * with all possible Chronologies.
-     */
-    @Test
-    public void test_format_allLocales_allChronologies() {
-        for (Locale locale : Locale.getAvailableLocales()) {
-            for (Chronology chronology : Chronology.getAvailableChronologies()) {
-                for (FormatStyle formatStyle : FormatStyle.values()) {
-                    try {
-                        DateTimeFormatter.ofLocalizedTime(formatStyle)
-                                .withLocale(locale)
-                                .withChronology(chronology)
-                                .withZone(ZoneOffset.UTC)
-                                .format(TEST_INSTANT);
-
-                        DateTimeFormatter.ofLocalizedDate(formatStyle)
-                                .withLocale(locale)
-                                .withChronology(chronology)
-                                .withZone(ZoneOffset.UTC)
-                                .format(TEST_INSTANT);
-
-                        DateTimeFormatter.ofLocalizedDateTime(formatStyle)
-                                .withLocale(locale)
-                                .withChronology(chronology)
-                                .withZone(ZoneOffset.UTC)
-                                .format(TEST_INSTANT);
-                    } catch (RuntimeException cause) {
-                        throw new RuntimeException("locale:" + locale +
-                                " formatStyle:" + formatStyle.name(), cause);
-                    }
-                }
-            }
-        }
-    }
 }
diff --git a/luni/src/test/java/libcore/java/util/CalendarTest.java b/luni/src/test/java/libcore/java/util/CalendarTest.java
index cdeab95..abe5ab8 100644
--- a/luni/src/test/java/libcore/java/util/CalendarTest.java
+++ b/luni/src/test/java/libcore/java/util/CalendarTest.java
@@ -418,16 +418,4 @@
 
         }
     }
-
-    /**
-     * Ensures that Gregorian is the default Calendar for all Locales in Android. This is the
-     * historic behavior on Android; this test exists to avoid unintentional regressions.
-     * http://b/80294184
-     */
-    public void testAllDefaultCalendar_Gregorian() {
-        for (Locale locale : Locale.getAvailableLocales()) {
-            assertTrue("Default calendar should be Gregorian: " + locale,
-                    Calendar.getInstance(locale) instanceof GregorianCalendar);
-        }
-    }
 }
diff --git a/luni/src/test/java/libcore/java/util/CurrencyTest.java b/luni/src/test/java/libcore/java/util/CurrencyTest.java
index 9acdde7..87f4315 100644
--- a/luni/src/test/java/libcore/java/util/CurrencyTest.java
+++ b/luni/src/test/java/libcore/java/util/CurrencyTest.java
@@ -195,17 +195,6 @@
         }
     }
 
-    public void test_currencyCodeIcuConsistency() {
-        Locale[] locales = Locale.getAvailableLocales();
-        for (Locale l : locales) {
-            Currency javaCurrency = getCurrency(l);
-            if (javaCurrency == null) continue;
-            assertEquals("Currency code is not consistent:" + l,
-                android.icu.util.Currency.getInstance(l).getCurrencyCode(),
-                javaCurrency.getCurrencyCode());
-        }
-    }
-
     public void test_localeExtension() {
         // Language=en, Country=US, Currency=Euro
         Locale locale = Locale.forLanguageTag("en-US-u-cu-eur");
diff --git a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
index 637ccff..b524483 100644
--- a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
@@ -48,15 +48,6 @@
   public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance();
 
   @Test
-  public void testAll() {
-    // Test that we can get the locale data for all known locales.
-    for (Locale l : Locale.getAvailableLocales()) {
-      LocaleData d = LocaleData.get(l);
-      System.err.format("%s %s %s\n", l, d.longDateFormat, d.longTimeFormat);
-    }
-  }
-
-  @Test
   public void test_en_US() throws Exception {
     LocaleData l = LocaleData.get(Locale.US);
     assertEquals("AM", l.amPm[0]);
diff --git a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
index ef79442..31da1f1 100644
--- a/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
+++ b/luni/src/test/java/libcore/libcore/util/ZoneInfoTest.java
@@ -20,11 +20,9 @@
 
 import java.io.InputStream;
 import java.io.ObjectInputStream;
-import java.nio.ByteBuffer;
 import java.time.Instant;
 import java.util.TimeZone;
 
-import libcore.timezone.testing.ZoneInfoTestHelper;
 import libcore.util.ZoneInfo;
 
 /**
@@ -51,19 +49,12 @@
       zoneInfoRead = (ZoneInfo) object;
     }
 
-    long[][] transitions = {
-        { -5000, 0 },
-        { -2000, 1 },
-        { -500, 0 },
-        { 0, 2 },
-    };
-    int[][] types = {
-        { 3600, 0 },
-        { 1800, 1 },
-        { 5400, 0 }
-    };
-    ZoneInfo zoneInfoCreated = createZoneInfo(
-            "test", transitions, types, timeFromSeconds(-1));
+    long[] transitions = { -5000, -2000, -500, 0 };
+    byte[] types =       { 0,     1,     0,    2 }; // align each entry with transitions
+    int[] offsets =    { 3600,  1800, 5400  };
+    boolean[] isDsts = { false, true, false }; // align each entry with offsets
+    ZoneInfo zoneInfoCreated = createZoneInfo("TimeZone for 'test'", transitions, types, offsets,
+            isDsts, timeFromSeconds(-1));
 
     assertEquals("Read ZoneInfo does not match created one", zoneInfoCreated, zoneInfoRead);
     assertEquals("useDaylightTime() mismatch",
@@ -89,12 +80,9 @@
     return Instant.ofEpochSecond(timeInSeconds);
   }
 
-  private ZoneInfo createZoneInfo(String name, long[][] transitions, int[][] types,
-          Instant currentTime) throws Exception {
-    ZoneInfoTestHelper.ZicDataBuilder builder =
-            new ZoneInfoTestHelper.ZicDataBuilder()
-                    .setTransitionsAndTypes(transitions, types);
-    ZoneInfoData data = ZoneInfoData.createZoneInfo(name, ByteBuffer.wrap(builder.build()));
+  private ZoneInfo createZoneInfo(String id, long[] transitions, byte[] types, int[] offsets,
+          boolean[] isDsts, Instant currentTime) {
+    ZoneInfoData data = ZoneInfoData.createInstance(id, transitions, types, offsets, isDsts);
     return ZoneInfo.createZoneInfo(data, currentTime.toEpochMilli());
   }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index c32e2d1..6b9fcc3 100644
--- a/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -80,7 +80,7 @@
  *     final Runnable beeper = new Runnable() {
  *       public void run() { System.out.println("beep"); }
  *     };
- *     final ScheduledFuture<?> beeperHandle =
+ *     final ScheduledFuture&lt;?&lt; beeperHandle =
  *       scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
  *     scheduler.schedule(new Runnable() {
  *       public void run() { beeperHandle.cancel(true); }