Merge changes from topic "am-0bc6a3da35c34e7da6d874a3480a9314" into pie-cts-dev am: 4cfdffcf38 am: 6d83851dc3 am: 8e150dbc83 am: bd90c0d898 am: 43b8793507 am: 1f7ba0b17c am: 11d0e607d4

Original change: https://android-review.googlesource.com/c/platform/libcore/+/2194739

Change-Id: I6000cd686c0fbad310d383d08eed68df011b27cc
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/luni/src/test/java/libcore/android/compat/CompatibilityTest.java b/luni/src/test/java/libcore/android/compat/CompatibilityTest.java
new file mode 100644
index 0000000..40ed9e6
--- /dev/null
+++ b/luni/src/test/java/libcore/android/compat/CompatibilityTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.android.compat;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.compat.Compatibility;
+import android.compat.Compatibility.BehaviorChangeDelegate;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class CompatibilityTest {
+
+    @Test
+    public void testBehaviorChangeDelegate() {
+        long changeId = 1L;
+        BehaviorChangeDelegate defaultDelegate = new BehaviorChangeDelegate() {};
+
+        // default implementation should not throw exception
+        defaultDelegate.onChangeReported(changeId);
+        assertTrue(defaultDelegate.isChangeEnabled(changeId));
+    }
+
+    @Test
+    public void testReportUnconditionalChange() {
+        long changeId = 1L;
+        BehaviorChangeDelegate delegate = mock(BehaviorChangeDelegate.class);
+        Compatibility.setBehaviorChangeDelegate(delegate);
+
+        Compatibility.reportUnconditionalChange(changeId);
+        verify(delegate).onChangeReported(changeId);
+    }
+
+    @Test
+    public void testClearBehaviorChangeDelegate() {
+        long changeId = 1L;
+        BehaviorChangeDelegate delegate = mock(BehaviorChangeDelegate.class);
+        Compatibility.setBehaviorChangeDelegate(delegate);
+
+        Compatibility.clearBehaviorChangeDelegate();
+        Compatibility.reportUnconditionalChange(changeId);
+        verify(delegate, never()).onChangeReported(anyLong());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/ConsoleTest.java b/luni/src/test/java/libcore/java/io/ConsoleTest.java
new file mode 100644
index 0000000..36d382f
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/ConsoleTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Console;
+import java.io.IOError;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ConsoleTest {
+
+    private Console createConsole(InputStream inStream, OutputStream outStream) throws Exception {
+        Constructor<Console> constructor =
+            Console.class.getDeclaredConstructor(InputStream.class, OutputStream.class);
+        constructor.setAccessible(true);
+        return constructor.newInstance(inStream, outStream);
+    }
+
+    private boolean isTty() {
+        // It is important for some tests to know if it is running in an environment where tty is
+        // available or not. This is because some API calls end up calling the native echo()
+        // function which throws an exception if tty is not available.
+        // The Console.isTty() method is private, however an option to check, without reflection, if
+        // tty is available is to see if console() return null or not. The function will always
+        // return an instance of Console if isTty() is true, or null otherwise.
+        return (Console.console() != null);
+    }
+
+    @Test
+    public void testReadPassword() throws Exception {
+        final byte[] bytes = "secret password\n".getBytes();
+        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        Console console = createConsole(inStream, outStream);
+        try {
+            String password = String.valueOf(console.readPassword());
+            // Due to readPassword depending on echo, which depends on having stdin as a tty, it is
+            // expected that it will throw an IOError if tty is not available
+            assertTrue("readPassword succeeded unexpectedly", isTty());
+            assertEquals("secret password", password);
+        } catch(IOError e) {
+            assertFalse("readPassword threw unexpected IOError", isTty());
+            assertTrue("readPassword exception not as expected",
+                    e.getMessage().contains("Inappropriate ioctl for device"));
+        }
+    }
+
+    @Test
+    public void testReadPasswordWithPrompt() throws Exception {
+        final byte[] bytes = "secret password\n".getBytes();
+        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        Console console = createConsole(inStream, outStream);
+        String username = "Alice";
+        try {
+            String password = String.valueOf(
+                    console.readPassword("%s, please enter your password:", username));
+            // Due to readPassword depending on echo, which depends on having stdin as a tty, it is
+            // expected that it will throw an IOError if tty is not available
+            assertTrue("readPassword succeeded unexpectedly", isTty());
+            assertEquals("secret password", password);
+            String prompt = new String(((ByteArrayOutputStream) outStream).toByteArray());
+            assertEquals("Alice, please enter your password:", prompt);
+        } catch(IOError e) {
+            assertFalse("readPassword threw unexpected IOError", isTty());
+            assertTrue("readPassword exception not as expected",
+                    e.getMessage().contains("Inappropriate ioctl for device"));
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
index 390cfd6..f4ed41d 100644
--- a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
+++ b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
@@ -72,4 +72,11 @@
       Os.close(target);
     }
   }
+
+  public void testGetSetInt$() {
+      FileDescriptor fd = new FileDescriptor();
+      assertEquals(-1, fd.getInt$());
+      fd.setInt$(42);
+      assertEquals(42, fd.getInt$());
+  }
 }
diff --git a/luni/src/test/java/libcore/java/io/FilePermissionTest.java b/luni/src/test/java/libcore/java/io/FilePermissionTest.java
new file mode 100644
index 0000000..cae7b06
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/FilePermissionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FilePermission;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FilePermissionTest {
+
+    @Test
+    public void testImplies() {
+        FilePermission permission = new FilePermission("none", null);
+        // Implementation is stubbed in Android
+        assertTrue(permission.implies(null));
+    }
+
+    @Test
+    public void testGetActions() {
+        FilePermission permission = new FilePermission("none", null);
+        // Implementation is stubbed in Android
+        assertNull(permission.getActions());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/OldFileWriterTest.java b/luni/src/test/java/libcore/java/io/OldFileWriterTest.java
index 1db9a3e..c68c92e 100644
--- a/luni/src/test/java/libcore/java/io/OldFileWriterTest.java
+++ b/luni/src/test/java/libcore/java/io/OldFileWriterTest.java
@@ -20,6 +20,7 @@
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -77,7 +78,7 @@
         }
     }
 
-    public void test_handleEarlyEOFChar_1() {
+    public void test_handleEarlyEOFChar_1() throws IOException {
         String str = "All work and no play makes Jack a dull boy\n";
         int NUMBER = 2048;
         int j = 0;
@@ -91,27 +92,23 @@
         }
         File f = null;
         FileWriter fw = null;
-        try {
-            f = File.createTempFile("ony", "by_one");
-            fw = new FileWriter(f);
-            fw.write(strChars);
-            fw.close();
-            InputStreamReader in = null;
-            FileInputStream fis = new FileInputStream(f);
-            in = new InputStreamReader(fis);
-            int b;
-            int errors = 0;
-            for (int offset = 0; offset < strChars.length; ++offset) {
-                b = in.read();
-                if (b == -1) {
-                    fail("Early EOF at offset " + offset + "\n");
-                    return;
-                }
+        f = File.createTempFile("ony", "by_one");
+        fw = new FileWriter(f);
+        fw.write(strChars);
+        fw.close();
+        InputStreamReader in = null;
+        FileInputStream fis = new FileInputStream(f);
+        in = new InputStreamReader(fis);
+        int b;
+        int errors = 0;
+        for (int offset = 0; offset < strChars.length; ++offset) {
+            b = in.read();
+            if (b == -1) {
+                fail("Early EOF at offset " + offset + "\n");
+                return;
             }
-            assertEquals(0, errors);
-        } catch (IOException e) {
-            e.printStackTrace();
         }
+        assertEquals(0, errors);
     }
 
     public void test_handleEarlyEOFChar_2() throws IOException {
@@ -141,6 +138,40 @@
         assertEquals(inputStr, outStr);
     }
 
+    public void test_handleExternalFileDescriptor() throws IOException {
+        String str = "All work and no play makes Jack a dull boy\n";
+        int NUMBER = 2048;
+        int j = 0;
+        int len = str.length() * NUMBER;
+        /* == 88064 *//* NUMBER compulsively written copies of the same string */
+        char[] strChars = new char[len];
+        for (int i = 0; i < NUMBER; ++i) {
+            for (int k = 0; k < str.length(); ++k) {
+                strChars[j++] = str.charAt(k);
+            }
+        }
+        File f = null;
+        FileWriter fw = null;
+        f = File.createTempFile("ony", "by_one");
+        FileOutputStream stream = new FileOutputStream(f);
+        fw = new FileWriter(stream.getFD());
+        fw.write(strChars);
+        fw.close();
+        InputStreamReader in = null;
+        FileInputStream fis = new FileInputStream(f);
+        in = new InputStreamReader(fis);
+        int b;
+        int errors = 0;
+        for (int offset = 0; offset < strChars.length; ++offset) {
+            b = in.read();
+            if (b == -1) {
+                fail("Early EOF at offset " + offset + "\n");
+                return;
+            }
+        }
+        assertEquals(0, errors);
+    }
+
     protected void setUp() throws Exception {
         f = File.createTempFile("writer", ".tst");
 
diff --git a/luni/src/test/java/libcore/java/io/PrintWriterTest.java b/luni/src/test/java/libcore/java/io/PrintWriterTest.java
new file mode 100644
index 0000000..cf3b86a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/PrintWriterTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class PrintWriterTest {
+
+    private class Writer extends PrintWriter {
+
+        Writer(File f) throws FileNotFoundException {
+            super(f);
+        }
+
+        public void setError() {
+            super.setError();
+        }
+
+        public void clearError() {
+            super.clearError();
+        }
+    }
+
+    @Test
+    public void testSetError() throws IOException {
+        File f = File.createTempFile("tmp", "tst");
+        Writer writer = new Writer(f);
+        assertFalse(writer.checkError());
+        writer.setError();
+        assertTrue(writer.checkError());
+        writer.clearError();
+        assertFalse(writer.checkError());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/SerializablePermissionTest.java b/luni/src/test/java/libcore/java/io/SerializablePermissionTest.java
new file mode 100644
index 0000000..29c0b96
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/SerializablePermissionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.SerializablePermission;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class SerializablePermissionTest {
+
+    @Test
+    public void testConstructorWithActions() {
+        SerializablePermission permission = new SerializablePermission("none", "no action");
+        // Implementation is stubbed in Android
+        assertEquals("", permission.getName());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/StreamCorruptedExceptionTest.java b/luni/src/test/java/libcore/java/io/StreamCorruptedExceptionTest.java
new file mode 100644
index 0000000..61307f8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/StreamCorruptedExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.StreamCorruptedException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class StreamCorruptedExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        StreamCorruptedException exception = new StreamCorruptedException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/UTFDataFormatExceptionTest.java b/luni/src/test/java/libcore/java/io/UTFDataFormatExceptionTest.java
new file mode 100644
index 0000000..f3102a2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/UTFDataFormatExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.UTFDataFormatException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class UTFDataFormatExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        UTFDataFormatException exception = new UTFDataFormatException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/UnsupportedEncodingExceptionTest.java b/luni/src/test/java/libcore/java/io/UnsupportedEncodingExceptionTest.java
new file mode 100644
index 0000000..d791167
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/UnsupportedEncodingExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.UnsupportedEncodingException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class UnsupportedEncodingExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        UnsupportedEncodingException exception = new UnsupportedEncodingException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java b/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java
index 5debdcb..559eb99 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java
@@ -31,14 +31,22 @@
 import static java.lang.invoke.MethodHandles.Lookup.*;
 
 public class CallSitesTest extends TestCase {
-    public void test_ConstantCallSite() throws Throwable {
-        final MethodType type = MethodType.methodType(int.class, int.class, int.class);
-        final MethodHandle mh =
-                MethodHandles.lookup().findStatic(CallSitesTest.class, "add2", type);
-        final ConstantCallSite site = new ConstantCallSite(mh);
-        assertEquals(mh, site.getTarget());
-        assertEquals(type, site.type());
+    public void test_ConstantCallSiteConstructorNullMethodHandle() throws Throwable {
+        try {
+            ConstantCallSite site = new ConstantCallSite((MethodHandle) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
 
+    private static MethodHandle methodHandleForAdd2() throws Throwable {
+        final MethodType mt = MethodType.methodType(int.class, int.class, int.class);
+        return MethodHandles.lookup().findStatic(CallSitesTest.class, "add2", mt);
+    }
+
+    public void test_ConstantCallSite() throws Throwable {
+        final MethodHandle mh = methodHandleForAdd2();
+        ConstantCallSite site = new ConstantCallSite(mh);
         int n = (int) site.dynamicInvoker().invokeExact(7, 37);
         assertEquals(44, n);
         try {
@@ -48,6 +56,147 @@
         }
     }
 
+    static class OurConstantCallSite extends ConstantCallSite {
+        OurConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
+            super(targetType, createTargetHook);
+        }
+
+        static MethodHandle createTargetHook(OurConstantCallSite callSite) throws Throwable {
+            final MethodType add2MethodType =
+                    MethodType.methodType(int.class, int.class, int.class);
+            return MethodHandles.lookup().findStatic(CallSitesTest.class, "add2", add2MethodType);
+        }
+    }
+
+    public void test_ConstantCallSiteWithHook() throws Throwable {
+        final MethodType targetType =
+                MethodType.methodType(int.class, int.class, int.class);
+        MethodHandle createTargetHook =
+                MethodHandles.lookup().findStatic(OurConstantCallSite.class, "createTargetHook",
+                                                  MethodType.methodType(MethodHandle.class,
+                                                                        OurConstantCallSite.class));
+        OurConstantCallSite callSite = new OurConstantCallSite(targetType, createTargetHook);
+        int x = (int) callSite.getTarget().invoke(1, 2);
+        assertEquals(3, x);
+    }
+
+    public void test_MutableCallSiteConstructorNullMethodType() throws Throwable {
+        try {
+            MutableCallSite callSite = new MutableCallSite((MethodType) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_MutableCallSiteConstructorNullMethodHandle() throws Throwable {
+        try {
+            MutableCallSite callSite = new MutableCallSite((MethodHandle) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_MutableCallsiteNoMethodHandle() throws Throwable {
+        try {
+            MutableCallSite callSite =
+                    new MutableCallSite(MethodType.methodType(int.class, int.class, int.class));
+            int result = (int) callSite.getTarget().invokeExact(1, 2);
+            fail();
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    public void test_MutableCallSite() throws Throwable {
+        final MethodHandle mh = methodHandleForAdd2();
+        final MutableCallSite site = new MutableCallSite(mh);
+
+        // Invocation test
+        int n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(44, n);
+
+        // setTarget() tests
+        try {
+            final MethodType mt_add3 =
+                    MethodType.methodType(int.class, int.class, int.class, int.class);
+            final MethodHandle mh_add3 =
+                    MethodHandles.lookup().findStatic(CallSitesTest.class, "add3", mt_add3);
+
+            site.setTarget(mh_add3);
+            fail();
+        } catch (WrongMethodTypeException e) {
+        }
+        try {
+            site.setTarget(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+        final MethodHandle mh_sub2 =
+                MethodHandles.lookup().findStatic(CallSitesTest.class, "sub2",
+                                                  MethodType.methodType(int.class, int.class, int.class));
+        site.setTarget(mh_sub2);
+        n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(-30, n);
+    }
+
+    public void test_VolatileCallSiteConstructorNullMethodType() throws Throwable {
+        try {
+            VolatileCallSite vc = new VolatileCallSite((MethodType) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_VolatileCallSiteConstructorNullMethodHandle() throws Throwable {
+        try {
+            VolatileCallSite vc = new VolatileCallSite((MethodHandle) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_VolatileCallsiteNoMethodHandle() throws Throwable {
+        try {
+            VolatileCallSite vc =
+                    new VolatileCallSite(MethodType.methodType(int.class, int.class, int.class));
+            int result = (int) vc.getTarget().invokeExact(1, 2);
+            fail();
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    public void test_VolatileCallSite() throws Throwable {
+        final MethodHandle mh = methodHandleForAdd2();
+        final VolatileCallSite site = new VolatileCallSite(mh);
+
+        // Invocation test
+        int n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(44, n);
+
+        // setTarget() tests
+        try {
+            final MethodType mt_add3 =
+                    MethodType.methodType(int.class, int.class, int.class, int.class);
+            final MethodHandle mh_add3 =
+                    MethodHandles.lookup().findStatic(CallSitesTest.class, "add3", mt_add3);
+            site.setTarget(mh_add3);
+            fail();
+        } catch (WrongMethodTypeException e) {
+        }
+        try {
+            site.setTarget(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+
+        // One last invocation test
+        final MethodHandle mh_sub2 =
+                MethodHandles.lookup().findStatic(CallSitesTest.class, "sub2",
+                                                  MethodType.methodType(int.class, int.class, int.class));
+        site.setTarget(mh_sub2);
+        n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(-30, n);
+    }
+
     public void test_EarlyBoundMutableCallSite() throws Throwable {
         final MethodType type = MethodType.methodType(int.class, int.class, int.class);
         final MethodHandle add2 =
@@ -97,7 +246,7 @@
     }
 
     private static void commonMutableCallSitesTest(CallSite site,
-                                                  MethodHandle firstTarget) throws Throwable{
+                                                   MethodHandle firstTarget) throws Throwable {
         site.setTarget(firstTarget);
         site.setTarget(firstTarget);
 
@@ -133,15 +282,15 @@
         assertEquals(100, (int) site.dynamicInvoker().invokeExact(147, 47));
     }
 
-    private static int add2(int x, int y) {
+    public static int add2(int x, int y) {
         return x + y;
     }
 
-    private static int add3(int x, int y, int z) {
+    public static int add3(int x, int y, int z) {
         return x + y + z;
     }
 
-    private static int sub2(int x, int y) {
+    public static int sub2(int x, int y) {
         return x - y;
     }
 }
diff --git a/luni/src/test/java/libcore/java/lang/invoke/LambdaConversionExceptionTest.java b/luni/src/test/java/libcore/java/lang/invoke/LambdaConversionExceptionTest.java
new file mode 100644
index 0000000..06a923a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/invoke/LambdaConversionExceptionTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.java.lang.invoke;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.invoke.LambdaConversionException;
+
+@RunWith(JUnit4.class)
+public class LambdaConversionExceptionTest {
+    private static final String MESSAGE = "message";
+
+    @Test
+    public void constructor() {
+        try {
+            throw new LambdaConversionException();
+        } catch (LambdaConversionException e) {
+            assertNull(e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @Test
+    public void constructorLString() {
+        try {
+            throw new LambdaConversionException(MESSAGE);
+        } catch (LambdaConversionException e) {
+            assertEquals(MESSAGE, e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @Test
+    public void constructorLStringLThrowable() {
+        try {
+            try {
+                throw new IllegalArgumentException();
+            } catch (Throwable t) {
+                throw new LambdaConversionException(MESSAGE, t);
+            }
+        } catch (LambdaConversionException e) {
+            assertEquals(MESSAGE, e.getMessage());
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+        }
+    }
+
+    @Test
+    public void constructorLThrowable() {
+        try {
+            try {
+                throw new IllegalArgumentException();
+            } catch (Throwable t) {
+                throw new LambdaConversionException(t);
+            }
+        } catch (LambdaConversionException e) {
+            assertEquals("java.lang.IllegalArgumentException", e.getMessage());
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+        }
+
+        try {
+            throw new LambdaConversionException((Throwable) null);
+        } catch (LambdaConversionException e) {
+            assertNull(e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @Test
+    public void constructorWithSuppressionsAndWritableStackTraces() {
+        boolean trueAndFalse[] = { true, false };
+
+        for (boolean enableSuppression : trueAndFalse) {
+            for (boolean writableStackTrace : trueAndFalse) {
+                try {
+                    throw new LambdaConversionException(MESSAGE, null, enableSuppression,
+                                                        writableStackTrace);
+                } catch (LambdaConversionException e) {
+                    assertEquals(MESSAGE, e.getMessage());
+
+                    // Check if exceptions can be suppressed.
+                    e.addSuppressed(new LambdaConversionException());
+                    boolean haveSuppressed = (e.getSuppressed().length == 1);
+                    assertEquals(enableSuppression, haveSuppressed);
+
+                    // Check if stack trace is writable.
+                    boolean stackTraceHasElements = (0 != e.getStackTrace().length);
+                    assertEquals(writableStackTrace, stackTraceHasElements);
+                    if (stackTraceHasElements) {
+                        // Only a writable stack trace has elements present. Now re-write it.
+                        e.setStackTrace(new StackTraceElement[0]);
+                        boolean wroteStackTrace = (e.getStackTrace().length == 0);
+                        assertEquals(writableStackTrace, wroteStackTrace);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java
index 12b82b0..a4e62f0 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java
@@ -54,6 +54,25 @@
         }
     }
 
+    public void test_constants() {
+        final int [] REF_CONSTANTS = {
+            0,                                     // Not used
+            MethodHandleInfo.REF_getField,         // 1
+            MethodHandleInfo.REF_getStatic,        // 2
+            MethodHandleInfo.REF_putField,         // 3
+            MethodHandleInfo.REF_putStatic,        // 4
+            MethodHandleInfo.REF_invokeVirtual,    // 5
+            MethodHandleInfo.REF_invokeStatic,     // 6
+            MethodHandleInfo.REF_invokeSpecial,    // 7
+            MethodHandleInfo.REF_newInvokeSpecial, // 8
+            MethodHandleInfo.REF_invokeInterface,  // 9
+        };
+        assertEquals(10, REF_CONSTANTS.length);
+        for (int i = 0; i < REF_CONSTANTS.length; ++i) {
+            assertEquals(i, REF_CONSTANTS[i]);
+        }
+    }
+
     public void test_referenceKindToString() {
         assertEquals("getField", referenceKindToString(REF_getField));
         assertEquals("getStatic", referenceKindToString(REF_getStatic));
@@ -77,4 +96,46 @@
         } catch (IllegalArgumentException expected) {
         }
     }
+
+    public void test_refKindIsField() {
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_getField));
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_getStatic));
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_putField));
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_putStatic));
+
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeVirtual));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeStatic));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeSpecial));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_newInvokeSpecial));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeInterface));
+    }
+
+    public void test_refKindIsValid() {
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_getField));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_getStatic));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_putField));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_putStatic));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeVirtual));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeStatic));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeSpecial));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_newInvokeSpecial));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeInterface));
+    }
+
+    public void test_refKindName() {
+        assertEquals("getField", MethodHandleInfo.refKindName(MethodHandleInfo.REF_getField));
+        assertEquals("getStatic", MethodHandleInfo.refKindName(MethodHandleInfo.REF_getStatic));
+        assertEquals("putField", MethodHandleInfo.refKindName(MethodHandleInfo.REF_putField));
+        assertEquals("putStatic", MethodHandleInfo.refKindName(MethodHandleInfo.REF_putStatic));
+        assertEquals("invokeVirtual",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeVirtual));
+        assertEquals("invokeStatic",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeStatic));
+        assertEquals("invokeSpecial",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeSpecial));
+        assertEquals("newInvokeSpecial",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_newInvokeSpecial));
+        assertEquals("invokeInterface",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeInterface));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/invoke/WrongMethodTypeExceptionTest.java b/luni/src/test/java/libcore/java/lang/invoke/WrongMethodTypeExceptionTest.java
new file mode 100644
index 0000000..d9288d2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/invoke/WrongMethodTypeExceptionTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.java.lang.invoke;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+@RunWith(JUnit4.class)
+public class WrongMethodTypeExceptionTest {
+    private static final String MESSAGE = "message";
+
+    @Test
+    public void constructor() {
+        try {
+            throw new WrongMethodTypeException();
+        } catch (WrongMethodTypeException e) {
+            assertNull(e.getCause());
+            assertNull(e.getMessage());
+        }
+    }
+
+    @Test
+    public void constructorLString() {
+        try {
+            throw new WrongMethodTypeException(MESSAGE);
+        } catch (WrongMethodTypeException e) {
+            assertNull(e.getCause());
+            assertEquals(MESSAGE, e.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/GenericSignatureFormatErrorTest.java b/luni/src/test/java/libcore/java/lang/reflect/GenericSignatureFormatErrorTest.java
new file mode 100644
index 0000000..8324aa4
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/GenericSignatureFormatErrorTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.java.lang.reflect;
+
+import java.lang.reflect.GenericSignatureFormatError;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class GenericSignatureFormatErrorTest {
+    private static final String MESSAGE = "message";
+
+    @Test
+    public void constructor() {
+        try {
+            throw new GenericSignatureFormatError();
+        } catch (GenericSignatureFormatError e) {
+            assertNull(e.getCause());
+            assertNull(e.getMessage());
+        }
+    }
+
+    @Test
+    public void constructorLString() {
+        try {
+            throw new GenericSignatureFormatError(MESSAGE);
+        } catch (GenericSignatureFormatError e) {
+            assertNull(e.getCause());
+            assertEquals(MESSAGE, e.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ReflectPermissionTest.java b/luni/src/test/java/libcore/java/lang/reflect/ReflectPermissionTest.java
new file mode 100644
index 0000000..1f788fe
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/ReflectPermissionTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.java.lang.reflect;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.reflect.ReflectPermission;
+
+@RunWith(JUnit4.class)
+public class ReflectPermissionTest {
+    private static final String NAME = "message";
+    private static final String ACTIONS = "No action";
+
+    private void checkFieldsAreEmpty(ReflectPermission permission) {
+        // The super-class of ReflectPermission overrides the name and actions provided to
+        // the ReflectPermission constructors with empty strings.
+        //
+        // This is legacy code that is not intended for use.
+        assertTrue(permission.getName().isEmpty());
+        assertTrue(permission.getActions().isEmpty());
+    }
+
+    @Test
+    public void reflectPermissionWithName() {
+        ReflectPermission permission = new ReflectPermission(NAME);
+        checkFieldsAreEmpty(permission);
+    }
+
+    @Test
+    public void reflectPermissionWithNameAndActions() {
+        ReflectPermission permission = new ReflectPermission(NAME, ACTIONS);
+        checkFieldsAreEmpty(permission);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java b/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java
index 7c47206..1cc25bf 100644
--- a/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java
+++ b/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java
@@ -726,6 +726,13 @@
         assertNotEquals(createCookie("theme", "light", "a.com", "/path"), baseCookie);
     }
 
+    public void testIsHttpOnly() throws Exception {
+        HttpCookie cookie = createCookie("a", "android", "a.com", "/");
+        assertFalse(cookie.isHttpOnly());
+        cookie.setHttpOnly(true);
+        assertTrue(cookie.isHttpOnly());
+    }
+
     private static void assertNotEquals(HttpCookie one, HttpCookie two) {
         assertFalse(one.equals(two));
         assertFalse(two.equals(one));
diff --git a/luni/src/test/java/libcore/java/net/AuthenticatorTest.java b/luni/src/test/java/libcore/java/net/AuthenticatorTest.java
new file mode 100644
index 0000000..6531107
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/AuthenticatorTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.java.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.net.Authenticator;
+import java.net.InetAddress;
+import java.net.PasswordAuthentication;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AuthenticatorTest {
+
+    private class MockAuthenticator extends Authenticator {
+        private int requests = 0;
+        private String userName;
+        private String password;
+
+        public void setUserName(String userName) {
+            this.userName = userName;
+        }
+
+        public void setPassword(String password) {
+            this.password = password;
+        }
+
+        @Override
+        protected PasswordAuthentication getPasswordAuthentication() {
+            ++requests;
+            return new PasswordAuthentication(userName, password.toCharArray());
+        }
+
+        public int getRequests() {
+            return requests;
+        }
+
+        public InetAddress getAddr() {
+            return getRequestingSite();
+        }
+
+        public int getPort() {
+            return getRequestingPort();
+        }
+
+        public String getProtocol() {
+            return getRequestingProtocol();
+        }
+
+        public String getPrompt() {
+            return getRequestingPrompt();
+        }
+
+        public String getScheme() {
+            return getRequestingScheme();
+        }
+    }
+
+    @Test
+    public void testRequestPasswordAuthentication() throws Exception {
+        final InetAddress addr = InetAddress.getByName("localhost");
+        final int port = 42;
+        final String protocol = "HTTP";
+        final String prompt = "Please enter your password";
+        final String scheme = "scheme";
+        final String userName = "007";
+        final String password = "super secret";
+
+        MockAuthenticator auth = new MockAuthenticator();
+        auth.setUserName(userName);
+        auth.setPassword(password);
+        Authenticator.setDefault(auth);
+        PasswordAuthentication passAuth = Authenticator.requestPasswordAuthentication(
+                addr, port, protocol, prompt, scheme);
+
+        assertNotNull(passAuth);
+        assertEquals(userName, passAuth.getUserName());
+        assertEquals(password, String.valueOf(passAuth.getPassword()));
+
+        assertEquals(1, auth.getRequests());
+        assertEquals(addr, auth.getAddr());
+        assertEquals(port, auth.getPort());
+        assertEquals(protocol, auth.getProtocol());
+        assertEquals(prompt, auth.getPrompt());
+        assertEquals(scheme, auth.getScheme());
+    }
+
+    @Test
+    public void testRequestPasswordAuthenticationWithNullAuthenticator() throws Exception {
+        final InetAddress addr = InetAddress.getByName("localhost");
+        final int port = 42;
+        final String protocol = "HTTP";
+        final String prompt = "Please enter your password";
+        final String scheme = "scheme";
+
+        Authenticator.setDefault(null);
+        assertNull(Authenticator.requestPasswordAuthentication(
+                addr, port, protocol, prompt, scheme));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
index fabed97..f6c3a27 100644
--- a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.net;
 
+import java.io.FileDescriptor;
 import java.lang.reflect.Field;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
@@ -219,4 +220,19 @@
       assertSame(packetAddr, newPacketAddr);
     }
   }
+
+  public void testGetFileDescriptor$() throws Exception {
+    final int port = 9999;
+
+    try(DatagramSocket s = new DatagramSocket()) {
+        s.connect(InetAddress.getLocalHost(), port);
+
+        FileDescriptor fd = s.getFileDescriptor$();
+        assertTrue(fd.valid());
+
+        s.disconnect();
+        fd = s.getFileDescriptor$();
+        assertTrue(fd.valid());
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java
index 3b072f2..43f5b7d 100644
--- a/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java
@@ -27,8 +27,10 @@
 import java.nio.channels.AsynchronousFileChannel;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.CompletionHandler;
+import java.nio.channels.FileLock;
 import java.nio.channels.NonReadableChannelException;
 import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
@@ -701,4 +703,67 @@
         } catch(ClosedChannelException expected) {}
     }
 
+    static class LockHandler implements CompletionHandler<FileLock, Integer> {
+        public FileLock fileLock;
+        public Throwable exc;
+
+        private final CountDownLatch cdl = new CountDownLatch(1);
+
+        @Override
+        public void completed(FileLock fileLock, Integer attachment) {
+            this.fileLock = fileLock;
+
+            cdl.countDown();
+        }
+
+        @Override
+        public void failed(Throwable exc, Integer attachment) {
+            this.exc = exc;
+        }
+
+        public boolean awaitCompletion() throws InterruptedException {
+            return cdl.await(10, TimeUnit.SECONDS);
+        }
+    }
+
+
+    @Test
+    public void testLock() throws Exception {
+        File temp = createTemporaryFile(256);
+        assertEquals(256, temp.length());
+        AsynchronousFileChannel afc = AsynchronousFileChannel.open(temp.toPath(),
+                StandardOpenOption.WRITE);
+        LockHandler handler = new LockHandler();
+
+        afc.lock(null, handler);
+        assertTrue(handler.awaitCompletion());
+        assertNotNull(handler.fileLock);
+        assertNull(handler.exc);
+        assertTrue(handler.fileLock.isValid());
+        assertFalse(handler.fileLock.isShared());
+
+        AsynchronousFileChannel otherAfc = AsynchronousFileChannel.open(temp.toPath(),
+                StandardOpenOption.WRITE);
+        LockHandler otherHandler = new LockHandler();
+        try {
+            otherAfc.lock(null, otherHandler);
+            fail();
+        } catch (OverlappingFileLockException expected) {
+        }
+
+        handler.fileLock.release();
+
+        otherHandler = new LockHandler();
+        otherAfc.lock(null, otherHandler);
+        assertTrue(otherHandler.awaitCompletion());
+        assertNotNull(otherHandler.fileLock);
+        assertNull(otherHandler.exc);
+        assertTrue(otherHandler.fileLock.isValid());
+
+        otherHandler.fileLock.release();
+
+        afc.close();
+        otherAfc.close();
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/FileLockTest.java b/luni/src/test/java/libcore/java/nio/channels/FileLockTest.java
new file mode 100644
index 0000000..dbf72f9
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/channels/FileLockTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.java.nio.channels;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FileLockTest {
+
+    @Test
+    public void testToString() throws Exception {
+        File tmp = File.createTempFile("FileLockTest", "tmp");
+
+        try(FileOutputStream fos = new FileOutputStream(tmp)) {
+            try(FileChannel fc = fos.getChannel()) {
+                FileLock lock = fc.lock(0, 42, false);
+                String strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("exclusive"));
+                assertTrue(strLock.contains("valid"));
+                assertFalse(strLock.contains("invalid"));
+
+                lock.release();
+                strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("exclusive"));
+                assertTrue(strLock.contains("invalid"));
+            }
+        }
+
+        try(FileInputStream fis = new FileInputStream(tmp)) {
+            try(FileChannel fc = fis.getChannel()) {
+                FileLock lock = fc.lock(0, 42, true);
+                String strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("shared"));
+                assertTrue(strLock.contains("valid"));
+                assertFalse(strLock.contains("invalid"));
+
+                lock.release();
+                strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("shared"));
+                assertTrue(strLock.contains("invalid"));
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/ClosedFileSystemExceptionTest.java b/luni/src/test/java/libcore/java/nio/file/ClosedFileSystemExceptionTest.java
new file mode 100644
index 0000000..f209899
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/ClosedFileSystemExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.java.nio.file;
+
+import static org.junit.Assert.assertNull;
+
+import java.nio.file.ClosedFileSystemException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ClosedFileSystemExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        ClosedFileSystemException exception = new ClosedFileSystemException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java b/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java
index 277db4f..480d9b4 100644
--- a/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java
@@ -22,6 +22,12 @@
 
 public class ProviderNotFoundExceptionTest extends TestCase {
 
+    public void test_constructor$() {
+        ProviderNotFoundException exception = new ProviderNotFoundException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
     public void test_constructor$String() {
         String message = "message";
         ProviderNotFoundException exception = new ProviderNotFoundException(message);
diff --git a/luni/src/test/java/libcore/java/nio/file/ReadOnlyFileSystemExceptionTest.java b/luni/src/test/java/libcore/java/nio/file/ReadOnlyFileSystemExceptionTest.java
new file mode 100644
index 0000000..b89eccd
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/ReadOnlyFileSystemExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.java.nio.file;
+
+import static org.junit.Assert.assertNull;
+
+import java.nio.file.ReadOnlyFileSystemException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ReadOnlyFileSystemExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        ReadOnlyFileSystemException exception = new ReadOnlyFileSystemException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java b/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java
index 6e0ccd8..0464faf 100644
--- a/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java
@@ -55,4 +55,31 @@
         assertEquals(1, flags.size());
         assertTrue(flags.contains(AclEntryFlag.INHERIT_ONLY));
     }
+
+    @Test
+    public void testBuilder() throws Exception {
+        UserPrincipal user = Files.getOwner(Paths.get("."));
+
+        AclEntry aclEntry = AclEntry.newBuilder()
+            .setType(AclEntryType.ALLOW)
+            .setPrincipal(user)
+            .setFlags(AclEntryFlag.INHERIT_ONLY)
+            .setPermissions(AclEntryPermission.READ_DATA, AclEntryPermission.READ_ATTRIBUTES)
+            .build();
+
+        AclEntry.Builder builder = AclEntry.newBuilder(aclEntry);
+        aclEntry = builder.build();
+
+        assertEquals(AclEntryType.ALLOW, aclEntry.type());
+        assertEquals(user, aclEntry.principal());
+
+        Set<AclEntryPermission> permissions = aclEntry.permissions();
+        assertEquals(2, permissions.size());
+        assertTrue(permissions.contains(AclEntryPermission.READ_DATA));
+        assertTrue(permissions.contains(AclEntryPermission.READ_ATTRIBUTES));
+
+        Set<AclEntryFlag> flags = aclEntry.flags();
+        assertEquals(1, flags.size());
+        assertTrue(flags.contains(AclEntryFlag.INHERIT_ONLY));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/file/spi/FileSystemProviderTest.java b/luni/src/test/java/libcore/java/nio/file/spi/FileSystemProviderTest.java
new file mode 100644
index 0000000..82c58a1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/spi/FileSystemProviderTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.java.nio.file.spi;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.AccessMode;
+import java.nio.file.CopyOption;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.LinkOption;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FileSystemProviderTest {
+
+    class MockFileSystemProvider extends FileSystemProvider {
+        @Override
+        public String getScheme() {
+            return "mock";
+        }
+
+        @Override
+        public FileSystem newFileSystem(URI uri, Map<String,?> env) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public FileSystem getFileSystem(URI uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Path getPath(URI uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public SeekableByteChannel newByteChannel(Path path,
+                Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public DirectoryStream<Path> newDirectoryStream(Path dir,
+                DirectoryStream.Filter<? super Path> filter) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void delete(Path path) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void copy(Path source, Path target, CopyOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void move(Path source, Path target, CopyOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isSameFile(Path path, Path path2) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isHidden(Path path) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public FileStore getFileStore(Path path) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void checkAccess(Path path, AccessMode... modes) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public <V extends FileAttributeView> V getFileAttributeView(
+                Path path, Class<V> type, LinkOption... options) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public <A extends BasicFileAttributes> A readAttributes(
+                Path path, Class<A> type, LinkOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Map<String,Object> readAttributes(
+                Path path, String attributes, LinkOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void setAttribute(Path path, String attribute,
+                Object value, LinkOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Test
+    public void testCreateLink() throws Exception {
+        MockFileSystemProvider provider = new MockFileSystemProvider();
+
+        Path link = Paths.get("testdir");
+        Path existing = Paths.get("testfile");
+
+        try {
+            provider.createLink(link, existing);
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test
+    public void testNewAsynchronousFileChannel() throws Exception {
+        MockFileSystemProvider provider = new MockFileSystemProvider();
+
+        Path path = Paths.get("testfile");
+        Set<OpenOption> options = new TreeSet<OpenOption>();
+
+        try {
+            provider.newAsynchronousFileChannel(path, options, null);
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException expected) {
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java b/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java
index 3ea4378..baa3344 100644
--- a/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java
+++ b/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java
@@ -156,21 +156,40 @@
     }
 
     // http://b/7955614
-    public void test_getZoneStrings_Apia() throws Exception {
+    public void test_getZoneStrings_Apia() {
         String[][] array = DateFormatSymbols.getInstance(Locale.US).getZoneStrings();
+
         for (int i = 0; i < array.length; ++i) {
             String[] row = array[i];
             // Pacific/Apia is somewhat arbitrary; we just want a zone we have to generate
             // "GMT" strings for the short names.
             if (row[0].equals("Pacific/Apia")) {
+                TimeZone apiaTz = TimeZone.getTimeZone("Pacific/Apia");
                 assertEquals("Apia Standard Time", row[1]);
-                assertEquals("GMT+13:00", row[2]);
+                assertEquals(formattedStandardTimeOffset(apiaTz), row[2]);
                 assertEquals("Apia Daylight Time", row[3]);
-                assertEquals("GMT+14:00", row[4]);
+                assertEquals(formattedDstOffset(apiaTz), row[4]);
             }
         }
     }
 
+    private static String formattedStandardTimeOffset(TimeZone tz) {
+        return formattedOffset(tz.getRawOffset());
+    }
+
+    private static String formattedDstOffset(TimeZone tz) {
+        return formattedOffset(tz.getRawOffset() + tz.getDSTSavings());
+    }
+
+    private static String formattedOffset(int offset) {
+        String pattern = "GMT%+d:%02d";
+        int millisInHour = 60 * 60 * 1_000;
+        int hours = offset / millisInHour;
+        int minutes = (offset - hours * millisInHour) / 1_000 / 60;
+
+        return String.format(pattern, hours, minutes);
+    }
+
     public void test_setZoneStrings_checks_dimensions() throws Exception {
         DateFormatSymbols dfs = DateFormatSymbols.getInstance();
         String[][] zoneStrings = dfs.getZoneStrings();
diff --git a/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java b/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java
index a319980..d6a0de4 100644
--- a/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java
+++ b/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.time.chrono;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -24,14 +25,22 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.time.Instant;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.ChronoZonedDateTime;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.JapaneseDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.FormatStyle;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalUnit;
+import java.util.Locale;
 
 @RunWith(JUnit4.class)
 public class ChronoZonedDateTimeTest {
@@ -58,6 +67,21 @@
         verify(temporalUnit).isSupportedBy(chronoZonedDateTime);
     }
 
+    @Test
+    public void testFormat() {
+        JapaneseChronology chrono = JapaneseChronology.INSTANCE;
+        DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
+                .appendLocalized(FormatStyle.MEDIUM, null)
+                .toFormatter(Locale.US);
+        ZonedDateTime epochTime = ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("UTC"));
+
+        ChronoZonedDateTime<JapaneseDate> chronoZonedDateTime = chrono.zonedDateTime(epochTime);
+        assertEquals("Jan 1, 45 Shōwa", chronoZonedDateTime.format(dateFormatter));
+
+        ChronoLocalDateTime<JapaneseDate> chronoLocalDateTime = chrono.localDateTime(epochTime);
+        assertEquals("Jan 1, 45 Shōwa", chronoLocalDateTime.format(dateFormatter));
+    }
+
     /* Used to test default methods. */
     private static class TestChronoZonedDateTime implements ChronoZonedDateTime {
 
diff --git a/luni/src/test/java/libcore/java/util/AbstractMapTest.java b/luni/src/test/java/libcore/java/util/AbstractMapTest.java
new file mode 100644
index 0000000..4b68018
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/AbstractMapTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.java.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.AbstractMap;
+
+@RunWith(JUnit4.class)
+public class AbstractMapTest {
+
+
+    @Test
+    public void testSimpleEntrySetValue() {
+        AbstractMap.SimpleEntry<String, Integer> entry = new AbstractMap.SimpleEntry<>("abc", 1);
+        assertEquals(Integer.valueOf(1), entry.getValue());
+        entry.setValue(-1);
+        assertEquals(Integer.valueOf(-1), entry.getValue());
+
+        AbstractMap.SimpleImmutableEntry<String, Integer> immutableEntry =
+                new AbstractMap.SimpleImmutableEntry<>("abc", 1);
+        assertEquals(Integer.valueOf(1), immutableEntry.getValue());
+        Assert.assertThrows(UnsupportedOperationException.class, () -> immutableEntry.setValue(-1));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/SpliteratorsTest.java b/luni/src/test/java/libcore/java/util/SpliteratorsTest.java
index 639ebf1..5e01ee0 100644
--- a/luni/src/test/java/libcore/java/util/SpliteratorsTest.java
+++ b/luni/src/test/java/libcore/java/util/SpliteratorsTest.java
@@ -26,6 +26,10 @@
 import java.util.PrimitiveIterator;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.Spliterators.AbstractDoubleSpliterator;
+import java.util.Spliterators.AbstractIntSpliterator;
+import java.util.Spliterators.AbstractLongSpliterator;
+import java.util.Spliterators.AbstractSpliterator;
 import java.util.function.Consumer;
 import java.util.function.DoubleConsumer;
 import java.util.function.IntConsumer;
@@ -863,4 +867,302 @@
 
         assertFalse(it.hasNext());
     }
+
+    private static class IncrementalDoubleSequenceSpliterator extends AbstractDoubleSpliterator {
+        private int current = 0;
+        private final int size;
+
+        IncrementalDoubleSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(DoubleConsumer action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractDoubleSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractDoubleSpliterator spliterator = new IncrementalDoubleSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator.OfDouble resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0);
+        assertFalse(spliterator.tryAdvance((DoubleConsumer) value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(0d, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(1d, value);
+        })));
+    }
+
+    public void testAbstractDoubleSpliterator_largeSize() {
+        // AbstractDoubleSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractDoubleSpliterator spliterator = new IncrementalDoubleSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator.OfDouble resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(0d, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(1d, value);
+        })));;
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals((double) maxBatch, value);
+        })));
+
+    }
+
+    private static class IncrementalIntSequenceSpliterator extends AbstractIntSpliterator {
+        private int current = 0;
+        private final int size;
+
+        IncrementalIntSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractIntSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractIntSpliterator spliterator = new IncrementalIntSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator.OfInt resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0);
+        assertFalse(spliterator.tryAdvance((IntConsumer) value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(0, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(1, value);
+        })));
+    }
+
+    public void testAbstractIntSpliterator_largeSize() {
+        // AbstractIntSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractIntSpliterator spliterator = new IncrementalIntSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator.OfInt resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(0, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(1, value);
+        })));
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(maxBatch, value);
+        })));
+    }
+
+    private static class IncrementalLongSequenceSpliterator extends AbstractLongSpliterator {
+        private int current = 0;
+        private final int size;
+
+        IncrementalLongSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(LongConsumer action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractLongSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractLongSpliterator spliterator = new IncrementalLongSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator.OfLong resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0L);
+        assertFalse(spliterator.tryAdvance((LongConsumer) value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(0L, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(1L, value);
+        })));
+    }
+
+    public void testAbstractLongSpliterator_largeSize() {
+        // AbstractLongSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractLongSpliterator spliterator = new IncrementalLongSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator.OfLong resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(0, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(1, value);
+        })));;
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(maxBatch, value);
+        })));
+
+    }
+
+    private static class IncrementalIntegerSequenceSpliterator extends
+            AbstractSpliterator<Integer> {
+        private int current = 0;
+        private final int size;
+
+        IncrementalIntegerSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super Integer> action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractSpliterator<Integer> spliterator = new IncrementalIntegerSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator<Integer> resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0L);
+        assertFalse(spliterator.tryAdvance(value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(0), value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(1), value);
+        })));
+    }
+
+    public void testAbstractSpliterator_largeSize() {
+        // AbstractSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractSpliterator<Integer> spliterator = new IncrementalIntegerSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator<Integer> resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(0), value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(1), value);
+        })));
+
+        ;
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(maxBatch), value);
+        })));
+
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index a686534..9b8ea47 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -319,12 +319,16 @@
     }
 
     // http://b/7955614
-    public void testApia() throws Exception {
+    public void testApia() {
         TimeZone tz = TimeZone.getTimeZone("Pacific/Apia");
         assertEquals("Apia Daylight Time", tz.getDisplayName(true, TimeZone.LONG, Locale.US));
         assertEquals("Apia Standard Time", tz.getDisplayName(false, TimeZone.LONG, Locale.US));
-        assertEquals("GMT+14:00", tz.getDisplayName(true, TimeZone.SHORT, Locale.US));
-        assertEquals("GMT+13:00", tz.getDisplayName(false, TimeZone.SHORT, Locale.US));
+
+        long samoaStandardTime = 1630315635000L; // 30 Aug 2021
+        long samoaDst = 1614504435000L; // 28 Feb 2021
+
+        assertEquals(13 * 60 * 60 * 1_000, tz.getOffset(samoaStandardTime));
+        assertEquals(14 * 60 * 60 * 1_000, tz.getOffset(samoaDst));
     }
 
     private static boolean isGmtString(String s) {
diff --git a/luni/src/test/java/libcore/javax/security/auth/AuthPermissionTest.java b/luni/src/test/java/libcore/javax/security/auth/AuthPermissionTest.java
new file mode 100644
index 0000000..e4715d0
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/AuthPermissionTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.javax.security.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import javax.security.auth.AuthPermission;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class AuthPermissionTest {
+
+    @Test
+    public void constructorWithString() {
+        AuthPermission permission = new AuthPermission("name");
+        assertNotNull(permission);
+        assertEquals("", permission.getName());
+    }
+
+    @Test
+    public void constructorWithStringAndString() {
+        AuthPermission permission = new AuthPermission("name", "actions");
+        assertNotNull(permission);
+        assertEquals("", permission.getName());
+        assertEquals("", permission.getActions());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/PrivateCredentialPermissionTest.java b/luni/src/test/java/libcore/javax/security/auth/PrivateCredentialPermissionTest.java
new file mode 100644
index 0000000..8ecb49b
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/PrivateCredentialPermissionTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.javax.security.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.security.AllPermission;
+import javax.security.auth.AuthPermission;
+import javax.security.auth.PrivateCredentialPermission;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class PrivateCredentialPermissionTest {
+
+    private PrivateCredentialPermission permission;
+
+    @Before
+    public void setUp() {
+        permission = new PrivateCredentialPermission("name", "actions");
+    }
+
+    @Test
+    public void constructorWithStringAndString() {
+        assertNotNull(permission);
+        assertEquals("", permission.getName());
+        assertNull(permission.getActions());
+    }
+
+    @Test
+    public void getActions() {
+        assertNull(permission.getActions());
+    }
+
+    @Test
+    public void getCredentialClass() {
+        assertNull(permission.getCredentialClass());
+    }
+
+    @Test
+    public void getPrincipals() {
+        assertNull(permission.getPrincipals());
+    }
+
+    @Test
+    public void implies() {
+        assertTrue(permission.implies(new AuthPermission("")));
+        assertTrue(permission.implies(new AllPermission()));
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/SubjectDomainCombinerTest.java b/luni/src/test/java/libcore/javax/security/auth/SubjectDomainCombinerTest.java
new file mode 100644
index 0000000..a88670c
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/SubjectDomainCombinerTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.javax.security.auth;
+
+import static org.junit.Assert.assertNull;
+
+import javax.security.auth.Subject;
+import javax.security.auth.SubjectDomainCombiner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class SubjectDomainCombinerTest {
+
+    @Test
+    public void combine() {
+        SubjectDomainCombiner combiner = new SubjectDomainCombiner(null);
+        assertNull(combiner.combine(null, null));
+    }
+
+    @Test
+    public void getSubject() {
+        SubjectDomainCombiner combiner = new SubjectDomainCombiner(null);
+        assertNull(combiner.getSubject());
+
+        combiner = new SubjectDomainCombiner(new Subject());
+        assertNull(combiner.getSubject());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/SubjectTest.java b/luni/src/test/java/libcore/javax/security/auth/SubjectTest.java
new file mode 100644
index 0000000..26efed7
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/SubjectTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.javax.security.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.security.Principal;
+import java.util.Set;
+import javax.security.auth.Subject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class SubjectTest {
+
+    private Set<Principal> set;
+    private Subject subject;
+
+    @Before
+    public void setUp() {
+        set = Set.of(new PrincipalImpl());
+        subject = new Subject(true, set, set, set);
+    }
+
+    @Test
+    public void getPrincipals() {
+        assertEquals(set, subject.getPrincipals());
+    }
+
+    @Test
+    public void getPrivateCredentials() {
+        assertEquals(set, subject.getPrivateCredentials());
+    }
+
+    @Test
+    public void getPublicCredentials() {
+        assertEquals(set, subject.getPublicCredentials());
+    }
+
+    @Test
+    public void isReadOnly() {
+        assertTrue(subject.isReadOnly());
+
+        subject = new Subject(false, set, set, set);
+        assertFalse(subject.isReadOnly());
+    }
+
+    @Test
+    public void setReadOnly() {
+        subject = new Subject(false, set, set, set);
+        assertFalse(subject.isReadOnly());
+
+        subject.setReadOnly();
+        assertTrue(subject.isReadOnly());
+    }
+
+    private static final class PrincipalImpl implements Principal {
+
+        @Override
+        public String getName() {
+            return "";
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java
new file mode 100644
index 0000000..3b6708d
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.javax.xml.datatype;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DatatypeConfigurationExceptionTest {
+
+    @Test
+    public void constructor() {
+        DatatypeConfigurationException e = new DatatypeConfigurationException();
+        assertNull(e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndThrowable() {
+        Throwable t = new Throwable();
+        DatatypeConfigurationException e = new DatatypeConfigurationException("message", t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        DatatypeConfigurationException e = new DatatypeConfigurationException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConstantsTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConstantsTest.java
new file mode 100644
index 0000000..f1797d1
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConstantsTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.javax.xml.datatype;
+
+import javax.xml.datatype.DatatypeConstants;
+import junit.framework.TestCase;
+
+public class DatatypeConstantsTest extends TestCase {
+
+    public void testField_getId() {
+        assertEquals(0, DatatypeConstants.YEARS.getId());
+        assertEquals(1, DatatypeConstants.MONTHS.getId());
+        assertEquals(2, DatatypeConstants.DAYS.getId());
+        assertEquals(3, DatatypeConstants.HOURS.getId());
+        assertEquals(4, DatatypeConstants.MINUTES.getId());
+        assertEquals(5, DatatypeConstants.SECONDS.getId());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java
new file mode 100644
index 0000000..8a48eca
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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.javax.xml.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+import junit.framework.TestCase;
+
+public class DatatypeFactoryTest extends TestCase {
+
+    private DatatypeFactory factory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        factory = new ExtendsDatatypeFactory();
+    }
+
+    public void testConstructor() {
+        DatatypeFactory f = new ExtendsDatatypeFactory();
+    }
+
+    public void testNewDuration_biiiiii() {
+        Duration duration = factory.newDuration(true, 1, 2, 3, 4, 5, 6);
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+    }
+
+    public void testNewDurationDayTime_biiii() {
+        Duration duration = factory.newDurationDayTime(true, 3, 4, 5, 6);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+    }
+
+    public void testNewDurationDayTime_bBigInteger() {
+        Duration duration = factory.newDuration(true, BigInteger.valueOf(1), BigInteger.valueOf(2),
+                BigInteger.valueOf(3), BigInteger.valueOf(4), BigInteger.valueOf(5),
+                BigDecimal.valueOf(6));
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+    }
+
+    public void testNewDurationDayTime_String() {
+        Duration duration = factory.newDuration("");
+        assertNull(duration);
+    }
+
+    public void testNewDurationDayTime_long() {
+        Duration duration = factory.newDuration(1000L);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(1, duration.getSeconds());
+    }
+
+    public void testNewDurationYearMonth_bii() {
+        Duration duration = factory.newDurationYearMonth(true, 1, 2);
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(0, duration.getSeconds());
+    }
+
+    public void testNewDurationYearMonth_bBigInteger() {
+        Duration duration = factory.newDurationYearMonth(true, BigInteger.valueOf(1), BigInteger.valueOf(2));
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(0, duration.getSeconds());
+    }
+
+    public void testNewDurationYearMonth_String() {
+        Duration duration = factory.newDurationYearMonth("");
+        assertNull(duration);
+    }
+
+    public void testNewDurationYearMonth_long() {
+        Duration duration = factory.newDurationYearMonth(1000);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(1, duration.getSeconds());
+    }
+
+    public void testNewInstance() {
+        try {
+            DatatypeFactory.newInstance();
+            fail("Unexpectedly created new instance");
+        } catch (DatatypeConfigurationException expected) {
+            // no default implementation in Android
+        }
+    }
+
+    public void testNewInstance_customClass() {
+        try {
+            DatatypeFactory.newInstance(null, null);
+            fail("Unexpectedly created new instance");
+        } catch (DatatypeConfigurationException expected) {
+            // class loading disabled
+        }
+    }
+
+    public void testNewXMLGregorianCalendar_iiiiiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendar(
+                1, 2, 3, 4, 5, 6, 7, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarDate_iiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarDate(1, 2, 3, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarTime_iiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarTime_iiiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, 7, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarTime_BigDecimal() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, BigDecimal.valueOf(7), 0);
+        assertNull(calendar);
+    }
+
+    private static class ExtendsDatatypeFactory extends DatatypeFactory {
+
+        protected ExtendsDatatypeFactory() {
+            super();
+        }
+
+        @Override
+        public Duration newDuration(String lexicalRepresentation) {
+            return null;
+        }
+
+        @Override
+        public Duration newDuration(long durationInMilliSeconds) {
+            return new DurationImpl(durationInMilliSeconds);
+        }
+
+        @Override
+        public Duration newDuration(boolean isPositive, BigInteger years,
+                BigInteger months, BigInteger days, BigInteger hours,
+                BigInteger minutes, BigDecimal seconds) {
+            int y = years == null ? DatatypeConstants.FIELD_UNDEFINED : years.intValue();
+            int m = months == null ? DatatypeConstants.FIELD_UNDEFINED : months.intValue();
+            int d = days == null ? DatatypeConstants.FIELD_UNDEFINED : days.intValue();
+            int h = hours == null ? DatatypeConstants.FIELD_UNDEFINED : hours.intValue();
+            int mn = minutes == null ? DatatypeConstants.FIELD_UNDEFINED : minutes.intValue();
+            int s = seconds == null ? DatatypeConstants.FIELD_UNDEFINED : seconds.intValue();
+            return new DurationImpl(isPositive ? 1 : -1, y, m, d, h, mn, s);
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar() {
+            return null;
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar(String lexicalRepresentation) {
+            return null;
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal) {
+            return null;
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year, int month,
+                int day, int hour, int minute, int second,
+                BigDecimal fractionalSecond, int timezone) {
+            return null;
+        }
+
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DurationImpl.java b/luni/src/test/java/libcore/javax/xml/datatype/DurationImpl.java
new file mode 100644
index 0000000..ae89cbc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DurationImpl.java
@@ -0,0 +1,126 @@
+/*
+ * 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.javax.xml.datatype;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeConstants.Field;
+import javax.xml.datatype.Duration;
+
+/**
+ * Avoid depending on {@link javax.xml.datatype.DatatypeFactory}, and
+ * throws {@link UnsupportedOperationException} on abstract methods,
+ * since proper implementation does not exist in Android.
+ */
+public class DurationImpl extends javax.xml.datatype.Duration {
+
+    private final int sign;
+    private final Map<Field, Number> fields;
+
+    DurationImpl(long millis) {
+        fields = new HashMap<>();
+        if (millis > 0) {
+            sign = 1;
+        } else if (millis == 0) {
+            sign = 0;
+            return;
+        } else {
+            sign = -1;
+            millis = -millis;
+        }
+        long d = millis / 86400000L;
+        millis %= 86400000L;
+        if (d > 0) {
+            fields.put(DatatypeConstants.DAYS, d);
+        }
+        long h = millis / 3600000L;
+        millis %= 3600000L;
+        if (h > 0) {
+            fields.put(DatatypeConstants.HOURS, h);
+        }
+        long m = millis / 60000L;
+        millis %= 60000L;
+        if (m > 0) {
+            fields.put(DatatypeConstants.MINUTES, m);
+        }
+        fields.put(DatatypeConstants.SECONDS, (float)millis / 1000);
+    }
+
+    DurationImpl(int sgn, int y, int months, int d, int h, int m, float s) {
+        sign = sgn;
+        fields = new HashMap<>();
+        if (y >= 0) { fields.put(DatatypeConstants.YEARS, y); }
+        if (months >= 0) { fields.put(DatatypeConstants.MONTHS, months); }
+        if (d >= 0) { fields.put(DatatypeConstants.DAYS, d); }
+        if (h >= 0) { fields.put(DatatypeConstants.HOURS, h); }
+        if (m >= 0) { fields.put(DatatypeConstants.MINUTES, m); }
+        if (s >= 0) { fields.put(DatatypeConstants.SECONDS, s); }
+    }
+
+    @Override
+    public int getSign() {
+        return sign;
+    }
+
+    @Override
+    public Number getField(Field field) {
+        return fields.get(field);
+    }
+
+    @Override
+    public boolean isSet(Field field) {
+        return fields.containsKey(field);
+    }
+
+    @Override
+    public Duration add(Duration rhs) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public void addTo(Calendar calendar) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public Duration multiply(BigDecimal factor) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public Duration negate() {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public Duration normalizeWith(Calendar startTimeInstant) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public int compare(Duration duration) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DurationTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DurationTest.java
new file mode 100644
index 0000000..ad9dba6
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DurationTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.javax.xml.datatype;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+import junit.framework.TestCase;
+
+/**
+ * Android has no {@link Duration} implementation, so use stubbed one that throws
+ * on abstract methods. This unit test is primarily for code coverage, it barely tests
+ * the actual implementation.
+ */
+public class DurationTest extends TestCase {
+
+    private static final Duration oneSecond = new DurationImpl(1, 0, 0, 0, 0, 0, 1);
+    private static final Duration tenMinutes = new DurationImpl(1, 0, 0, 0, 0, 10, 0);
+    private static final Duration oneDay = new DurationImpl(1, 0, 0, 1, 0 , 0, 0);
+    private static final Duration fiveDays = new DurationImpl(1, 0, 0, 5, 0, 0, 0);
+    private static final Duration twoMonths = new DurationImpl(1, 0, 2, 0, 0, 0, 0);
+    private static final Duration threeYears = new DurationImpl(1, 3, 0, 0, 0, 0, 0);
+    private static final Duration y6m5d4h3m2s1 = new DurationImpl(1, 6, 5, 4, 3, 2, 1);
+
+    public void testAddTo_Date() {
+        Date date = null;
+        try {
+            oneSecond.addTo(date);
+        } catch (NullPointerException expected) {}
+
+        date = new Date(1000);
+        try {
+            oneSecond.addTo(date);
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testGetDays() {
+        assertEquals(0, oneSecond.getDays());
+        assertEquals(0, tenMinutes.getDays());
+        assertEquals(1, oneDay.getDays());
+        assertEquals(5, fiveDays.getDays());
+        assertEquals(0, twoMonths.getDays());
+        assertEquals(4, y6m5d4h3m2s1.getDays());
+    }
+
+    public void testGetHours() {
+        assertEquals(0, oneSecond.getHours());
+        assertEquals(0, tenMinutes.getHours());
+        assertEquals(0, oneDay.getHours());
+        assertEquals(0, fiveDays.getHours());
+        assertEquals(0, twoMonths.getHours());
+        assertEquals(3, y6m5d4h3m2s1.getHours());
+    }
+
+    public void testGetMinutes() {
+        assertEquals(0, oneSecond.getMinutes());
+        assertEquals(10, tenMinutes.getMinutes());
+        assertEquals(0, oneDay.getMinutes());
+        assertEquals(0, fiveDays.getMinutes());
+        assertEquals(0, twoMonths.getMinutes());
+        assertEquals(2, y6m5d4h3m2s1.getMinutes());
+    }
+
+    public void testGetMonths() {
+        assertEquals(0, oneSecond.getMonths());
+        assertEquals(0, tenMinutes.getMonths());
+        assertEquals(0, oneDay.getMonths());
+        assertEquals(0, fiveDays.getMonths());
+        assertEquals(2, twoMonths.getMonths());
+        assertEquals(0, threeYears.getMonths());
+        assertEquals(5, y6m5d4h3m2s1.getMonths());
+    }
+
+    public void testGetSeconds() {
+        assertEquals(1, oneSecond.getSeconds());
+        assertEquals(0, tenMinutes.getSeconds());
+        assertEquals(0, oneDay.getSeconds());
+        assertEquals(0, fiveDays.getSeconds());
+        assertEquals(0, twoMonths.getSeconds());
+        assertEquals(0, threeYears.getSeconds());
+        assertEquals(1, y6m5d4h3m2s1.getSeconds());
+    }
+
+    public void testGetTimeInMillis_calendar() {
+        Calendar calendar = GregorianCalendar.getInstance();
+        calendar.setTimeInMillis(1000);
+        try {
+            oneSecond.getTimeInMillis(calendar);
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testGetTimeInMillis_date() {
+        Date date = new Date(1000);
+        try {
+            oneSecond.getTimeInMillis(date);
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testGetXmlSchemaType() {
+        Duration allSet = new DurationImpl(1, 1, 1, 1, 1, 1, 1);
+        assertEquals(DatatypeConstants.DURATION, allSet.getXMLSchemaType());
+
+        Duration dayHourMinuteSecondSet = new DurationImpl(1, -1, -1, 1, 1, 1, 1);
+        assertEquals(DatatypeConstants.DURATION_DAYTIME, dayHourMinuteSecondSet.getXMLSchemaType());
+
+        Duration yearMonthSet = new DurationImpl(1, 1, 1, -1, -1, -1, -1);
+        assertEquals(DatatypeConstants.DURATION_YEARMONTH, yearMonthSet.getXMLSchemaType());
+
+        Duration noneSet = new DurationImpl(0, -1, -1, -1, -1, -1, -1);
+        try {
+            noneSet.getXMLSchemaType();
+            fail("Unexpectedly didn't throw");
+        } catch (IllegalStateException expected) {}
+    }
+
+    public void testGetYears() {
+        assertEquals(0, oneSecond.getYears());
+        assertEquals(0, tenMinutes.getYears());
+        assertEquals(0, oneDay.getYears());
+        assertEquals(0, fiveDays.getYears());
+        assertEquals(0, twoMonths.getYears());
+        assertEquals(3, threeYears.getYears());
+        assertEquals(6, y6m5d4h3m2s1.getYears());
+    }
+
+    public void testIsLongerThan() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (int i = 0; i < durations.length - 1; i++) {
+            for (int j = i + 1; j < durations.length; j++) {
+                try {
+                    assertTrue(durations[j].isLongerThan(durations[i]));
+                } catch (UnsupportedOperationException expected) {}
+            }
+        }
+    }
+
+    public void testIsShorterThan() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (int i = 0; i < durations.length - 1; i++) {
+            for (int j = i + 1; j < durations.length; j++) {
+                try {
+                    assertTrue(durations[i].isShorterThan(durations[j]));
+                } catch (UnsupportedOperationException expected) {}
+            }
+        }
+    }
+
+    public void testMultiply() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (Duration d : durations) {
+            try {
+                d.multiply(2);
+            } catch (UnsupportedOperationException expected) {}
+        }
+    }
+
+    public void testSubtract() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (Duration i : durations) {
+            for (Duration j : durations) {
+                try {
+                    i.subtract(j);
+                } catch (UnsupportedOperationException expected) {}
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java b/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java
new file mode 100644
index 0000000..012facc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java
@@ -0,0 +1,251 @@
+/*
+ * 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.javax.xml.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import junit.framework.TestCase;
+
+public class XMLGregorianCalendarTest extends TestCase {
+
+    private XMLGregorianCalendar calendar;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        calendar = new XMLGregorianCalendarImpl();
+    }
+
+    public void testGetMillisecond() {
+        assertEquals(DatatypeConstants.FIELD_UNDEFINED, calendar.getMillisecond());
+    }
+
+    public void testSetTime_iii() {
+        calendar.setTime(1, 2, 3);
+        assertEquals(1, calendar.getHour());
+        assertEquals(2, calendar.getMinute());
+        assertEquals(3, calendar.getSecond());
+    }
+
+    public void testSetTime_iiii() {
+        calendar.setTime(1, 2, 3, 4);
+        assertEquals(1, calendar.getHour());
+        assertEquals(2, calendar.getMinute());
+        assertEquals(3, calendar.getSecond());
+        assertEquals(DatatypeConstants.FIELD_UNDEFINED, calendar.getMillisecond());
+    }
+
+    public void testSetTime_iiiBigDecimal() {
+        calendar.setTime(1, 2, 3, BigDecimal.valueOf(0.1));
+        assertEquals(1, calendar.getHour());
+        assertEquals(2, calendar.getMinute());
+        assertEquals(3, calendar.getSecond());
+        assertEquals(100, calendar.getMillisecond());
+        assertEquals(BigDecimal.valueOf(0.1), calendar.getFractionalSecond());
+    }
+
+    /**
+     * Stub implementation intended for test coverage.
+     */
+    private static final class XMLGregorianCalendarImpl extends XMLGregorianCalendar {
+
+        private int year;
+        private int month;
+        private int day;
+        private int hour;
+        private int minute;
+        private int second;
+        private int millisecond;
+        private BigDecimal fractional;
+        private int timezoneOffset;
+
+        @Override
+        public void clear() {
+            year = month = day = hour = minute = second = millisecond = timezoneOffset = 0;
+            fractional = BigDecimal.valueOf(0);
+        }
+
+        @Override
+        public void reset() {
+            year = month = day = hour = minute = second = millisecond = timezoneOffset = 0;
+            fractional = BigDecimal.valueOf(0);
+        }
+
+        @Override
+        public void setYear(BigInteger year) {
+            this.year = year.intValue();
+        }
+
+        @Override
+        public void setYear(int year) {
+            this.year = year;
+        }
+
+        @Override
+        public void setMonth(int month) {
+            this.month = month;
+        }
+
+        @Override
+        public void setDay(int day) {
+            this.day = day;
+        }
+
+        @Override
+        public void setTimezone(int offset) {
+            this.timezoneOffset = offset;
+        }
+
+        @Override
+        public void setHour(int hour) {
+            this.hour = hour;
+        }
+
+        @Override
+        public void setMinute(int minute) {
+            this.minute = minute;
+        }
+
+        @Override
+        public void setSecond(int second) {
+            this.second = second;
+        }
+
+        @Override
+        public void setMillisecond(int millisecond) {
+            this.millisecond = millisecond;
+        }
+
+        @Override
+        public void setFractionalSecond(BigDecimal fractional) {
+            this.fractional = fractional;
+        }
+
+        @Override
+        public BigInteger getEon() {
+            return null;
+        }
+
+        @Override
+        public int getYear() {
+            return year;
+        }
+
+        @Override
+        public BigInteger getEonAndYear() {
+            return null;
+        }
+
+        @Override
+        public int getMonth() {
+            return month;
+        }
+
+        @Override
+        public int getDay() {
+            return day;
+        }
+
+        @Override
+        public int getTimezone() {
+            return timezoneOffset;
+        }
+
+        @Override
+        public int getHour() {
+            return hour;
+        }
+
+        @Override
+        public int getMinute() {
+            return minute;
+        }
+
+        @Override
+        public int getSecond() {
+            return second;
+        }
+
+        @Override
+        public BigDecimal getFractionalSecond() {
+            return fractional;
+        }
+
+        @Override
+        public int compare(XMLGregorianCalendar rhs) {
+            if (year != rhs.getYear()) return year - rhs.getYear();
+            if (month != rhs.getMonth()) return month - rhs.getMonth();
+            if (day != rhs.getDay()) return day - rhs.getDay();
+            if (hour != rhs.getHour()) return hour - rhs.getHour();
+            if (minute != rhs.getMinute()) return minute - rhs.getMinute();
+            if (second != rhs.getSecond()) return second - rhs.getSecond();
+            if (millisecond != rhs.getMillisecond()) return millisecond - getMillisecond();
+            return fractional.subtract(rhs.getFractionalSecond()).intValue();
+        }
+
+        @Override
+        public XMLGregorianCalendar normalize() {
+            return null;
+        }
+
+        @Override
+        public String toXMLFormat() {
+            return null;
+        }
+
+        @Override
+        public QName getXMLSchemaType() {
+            return null;
+        }
+
+        @Override
+        public boolean isValid() {
+            return false;
+        }
+
+        @Override
+        public void add(Duration duration) {}
+
+        @Override
+        public GregorianCalendar toGregorianCalendar() {
+            return null;
+        }
+
+        @Override
+        public GregorianCalendar toGregorianCalendar(TimeZone timezone, Locale aLocale,
+                XMLGregorianCalendar defaults) {
+            return null;
+        }
+
+        @Override
+        public TimeZone getTimeZone(int defaultZoneoffset) {
+            return null;
+        }
+
+        @Override
+        public Object clone() {
+            return null;
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/namespace/QNameTest.java b/luni/src/test/java/libcore/javax/xml/namespace/QNameTest.java
new file mode 100644
index 0000000..8214c11
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/namespace/QNameTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.javax.xml.namespace;
+
+import javax.xml.namespace.QName;
+import junit.framework.TestCase;
+
+public class QNameTest extends TestCase {
+
+    public void testConstructor() {
+        QName qName = new QName("hello");
+        assertEquals("", qName.getNamespaceURI());
+        assertEquals("", qName.getPrefix());
+        assertEquals("hello", qName.getLocalPart());
+    }
+
+    public void testGetNamespaceURI() {
+        QName qName = new QName("namespace", "local part", "prefix");
+        assertEquals("namespace", qName.getNamespaceURI());
+        assertEquals("local part", qName.getLocalPart());
+        assertEquals("prefix", qName.getPrefix());
+
+        qName = new QName(null, "local part", "prefix");
+        assertEquals("", qName.getNamespaceURI());
+        assertEquals("local part", qName.getLocalPart());
+        assertEquals("prefix", qName.getPrefix());
+    }
+
+    public void testGetPrefix() {
+        QName qName = new QName("namespace", "local part", "prefix");
+        assertEquals("prefix", qName.getPrefix());
+
+        try {
+            new QName("namespace", "local part", null);
+            fail("Unexpectedly didn't throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {}
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderFactoryTest.java b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderFactoryTest.java
new file mode 100644
index 0000000..ae9a045
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderFactoryTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.javax.xml.parsers;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+import javax.xml.validation.ValidatorHandler;
+import junit.framework.TestCase;
+
+public class DocumentBuilderFactoryTest extends TestCase {
+
+    public void testGetSchema() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+        try {
+            factory.getSchema();
+            fail("Unexpectedly didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testSetSchema() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+        try {
+            factory.setSchema(new Schema() {
+                @Override
+                public Validator newValidator() { return null; }
+
+                @Override
+                public ValidatorHandler newValidatorHandler() { return null; }
+            });
+            fail("Unexpectedly didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testNewInstance_StringClassLoader() {
+        try {
+            DocumentBuilderFactory.newInstance(null, null);
+        } catch (FactoryConfigurationError expected) {}
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java
index 646776a..e643bfd 100644
--- a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java
+++ b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java
@@ -16,7 +16,17 @@
 
 package libcore.javax.xml.parsers;
 
-import static tests.support.Support_Xml.*;
+import static tests.support.Support_Xml.attrOf;
+import static tests.support.Support_Xml.domOf;
+import static tests.support.Support_Xml.firstChildTextOf;
+import static tests.support.Support_Xml.firstElementOf;
+
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
 
 public class DocumentBuilderTest extends junit.framework.TestCase {
     // http://code.google.com/p/android/issues/detail?id=2607
@@ -61,4 +71,35 @@
             // Expected.
         }
     }
+
+    public void testGetSchema() {
+        DocumentBuilder db = new DocumentBuilder() {
+            @Override
+            public Document parse(InputSource is) { return null; }
+
+            @Override
+            public boolean isNamespaceAware() { return false; }
+
+            @Override
+            public boolean isValidating() { return false; }
+
+            @Override
+            public void setEntityResolver(EntityResolver er) {}
+
+            @Override
+            public void setErrorHandler(ErrorHandler eh) {}
+
+            @Override
+            public Document newDocument() { return null; }
+
+            @Override
+            public DOMImplementation getDOMImplementation() { return null; }
+        };
+
+        try {
+            db.getSchema();
+            fail("Unexpectedly didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException expected) {}
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/xml/transform/SourceLocatorImpl.java b/luni/src/test/java/libcore/javax/xml/transform/SourceLocatorImpl.java
new file mode 100644
index 0000000..8219c31
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/SourceLocatorImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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.javax.xml.transform;
+
+import javax.xml.transform.SourceLocator;
+
+public class SourceLocatorImpl implements SourceLocator {
+    @Override
+    public String getPublicId() { return null; }
+
+    @Override
+    public String getSystemId() { return null; }
+
+    @Override
+    public int getLineNumber() { return 0; }
+
+    @Override
+    public int getColumnNumber() { return 0; }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerConfigurationExceptionTest.java
new file mode 100644
index 0000000..c72af96
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerConfigurationExceptionTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerConfigurationException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerConfigurationExceptionTest  {
+
+    @Test
+    public void constructor() {
+        TransformerConfigurationException e = new TransformerConfigurationException();
+        assertEquals("Configuration Error", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndThrowable() {
+        Throwable t = new Throwable();
+        TransformerConfigurationException e = new TransformerConfigurationException("message", t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndSourceLocator() {
+        SourceLocator locator = new SourceLocatorImpl();
+        TransformerConfigurationException e = new TransformerConfigurationException("message",
+                locator);
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void constructorWithStringSourceLocatorAndThrowable() {
+        SourceLocator locator = new SourceLocatorImpl();
+        Throwable t = new Throwable();
+        TransformerConfigurationException e = new TransformerConfigurationException("message",
+                locator, t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        TransformerConfigurationException e = new TransformerConfigurationException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerExceptionTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerExceptionTest.java
new file mode 100644
index 0000000..83bad06
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerExceptionTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerExceptionTest {
+
+    @Test
+    public void constructorWithStringAndThrowable() {
+        Throwable t = new Throwable();
+        TransformerException e = new TransformerException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndSourceLocator() {
+        SourceLocator locator = new SourceLocatorImpl();
+        TransformerException e = new TransformerException("message", locator);
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void constructorWithStringSourceLocatorAndThrowable() {
+        SourceLocator locator = new SourceLocatorImpl();
+        Throwable t = new Throwable();
+        TransformerException e = new TransformerException("message", locator, t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void getException() {
+        TransformerException e = new TransformerException("message");
+        Throwable t = e.getException();
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void getMessageAndLocation() {
+        SourceLocator locator = new SourceLocatorImpl();
+        TransformerException e = new TransformerException("message", locator);
+        assertEquals("message", e.getMessageAndLocation());
+    }
+
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryConfigurationErrorTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryConfigurationErrorTest.java
new file mode 100644
index 0000000..ba8ab52
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryConfigurationErrorTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerFactoryConfigurationErrorTest {
+
+    @Test
+    public void constructor() {
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError();
+        assertNull(e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithException() {
+        Exception ex = new Exception("message");
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError(ex);
+        assertEquals("java.lang.Exception: message", e.getMessage());
+        assertEquals(ex, e.getException());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithExceptionAndString() {
+        Exception ex = new Exception("message");
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError(ex,
+                "another message");
+        assertEquals("another message", e.getMessage());
+        assertEquals(ex, e.getException());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithString() {
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void getException() {
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError("message");
+        Throwable t = e.getException();
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryTest.java
new file mode 100644
index 0000000..0269e49
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerFactoryTest {
+
+    @Test
+    public void newInstanceOfStringAndClassLoader() {
+        assertThrows(TransformerFactoryConfigurationError.class,
+                () -> TransformerFactory.newInstance(null, null));
+
+        try {
+            TransformerFactory.newInstance("nonexistent class", null);
+        } catch (TransformerFactoryConfigurationError expected) {
+            assertEquals(ClassNotFoundException.class, expected.getException().getClass());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerTest.java
new file mode 100644
index 0000000..6c44a90
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.javax.xml.transform;
+
+import java.util.Properties;
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerTest {
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void reset() {
+        Transformer transformer = new TransformerImpl();
+        transformer.reset();
+    }
+
+    private static final class TransformerImpl extends Transformer {
+
+        @Override
+        public void reset() { super.reset(); }
+
+        @Override
+        public void transform(Source xmlSource, Result outputTarget) throws TransformerException {}
+
+        @Override
+        public void setParameter(String name, Object value) {}
+
+        @Override
+        public Object getParameter(String name) { return null; }
+
+        @Override
+        public void clearParameters() {}
+
+        @Override
+        public void setURIResolver(URIResolver resolver) {}
+
+        @Override
+        public URIResolver getURIResolver() { return null;  }
+
+        @Override
+        public void setOutputProperties(Properties oformat) {}
+
+        @Override
+        public Properties getOutputProperties() { return null; }
+
+        @Override
+        public void setOutputProperty(String name, String value) throws IllegalArgumentException {}
+
+        @Override
+        public String getOutputProperty(String name) throws IllegalArgumentException {
+            return null;
+        }
+
+        @Override
+        public void setErrorListener(ErrorListener listener) throws IllegalArgumentException {}
+
+        @Override
+        public ErrorListener getErrorListener() { return null; }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/dom/DOMResultTest.java b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMResultTest.java
new file mode 100644
index 0000000..6f9eacc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMResultTest.java
@@ -0,0 +1,360 @@
+/*
+ * 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.javax.xml.transform.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import javax.xml.transform.dom.DOMResult;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.w3c.dom.UserDataHandler;
+import org.xml.sax.SAXException;
+
+@RunWith(JUnit4.class)
+public class DOMResultTest {
+
+    private Node node;
+    private Node documentNode;
+
+    @Before
+    public void setUp() throws SAXException, IOException {
+        node = new NodeImpl();
+        documentNode = new NodeImpl();
+    }
+
+    @Test
+    public void constructorWithNode() {
+        DOMResult result = new DOMResult(node);
+        assertNotNull(result);
+        assertEquals(node, result.getNode());
+    }
+
+    @Test
+    public void constructorWithNodeAndString() {
+        DOMResult result = new DOMResult(node, "systemId");
+        assertNotNull(result);
+        assertEquals(node, result.getNode());
+        assertEquals("systemId", result.getSystemId());
+    }
+
+    @Test
+    public void constructorWithNodeAndNode() {
+        documentNode.appendChild(node);
+        DOMResult result = new DOMResult(documentNode, node);
+        assertNotNull(result);
+        assertEquals(documentNode, result.getNode());
+        assertEquals(node, result.getNextSibling());
+    }
+
+    @Test
+    public void constructorWithNodeNodeAndString() {
+        documentNode.appendChild(node);
+        DOMResult result = new DOMResult(documentNode, node, "systemId");
+        assertNotNull(result);
+        assertEquals(documentNode, result.getNode());
+        assertEquals("systemId", result.getSystemId());
+        assertEquals(node, result.getNextSibling());
+    }
+
+    @Test
+    public void getSetSystemId() {
+        DOMResult result = new DOMResult(node);
+        assertNull(result.getSystemId());
+
+        result.setSystemId("systemId");
+        assertEquals("systemId", result.getSystemId());
+    }
+
+    @Test
+    public void getSetNextSibling() {
+        DOMResult result = new DOMResult(node);
+        assertNull(result.getNextSibling());
+
+        Node anotherNode = new NodeImpl();
+        result.setNextSibling(anotherNode);
+        assertNotEquals(node, result.getNextSibling());
+        assertEquals(anotherNode, result.getNextSibling());
+    }
+
+    private static final class NodeImpl implements Node, Document {
+
+        private final ArrayList<Node> children;
+
+        public NodeImpl() {
+            this.children = new ArrayList<>();
+        }
+
+        @Override
+        public String getNodeName() { return null; }
+
+        @Override
+        public String getNodeValue() throws DOMException { return null; }
+
+        @Override
+        public void setNodeValue(String nodeValue) throws DOMException {}
+
+        @Override
+        public short getNodeType() { return 0; }
+
+        @Override
+        public Node getParentNode() { return null; }
+
+        @Override
+        public NodeList getChildNodes() { return new NodeListImpl(children); }
+
+        @Override
+        public Node getFirstChild() { return children.get(0); }
+
+        @Override
+        public Node getLastChild() { return children.get(children.size() - 1); }
+
+        @Override
+        public Node getPreviousSibling() { return null; }
+
+        @Override
+        public Node getNextSibling() { return null; }
+
+        @Override
+        public NamedNodeMap getAttributes() { return null; }
+
+        @Override
+        public Document getOwnerDocument() { return null; }
+
+        @Override
+        public Node insertBefore(Node newChild, Node refChild) throws DOMException { return null; }
+
+        @Override
+        public Node replaceChild(Node newChild, Node oldChild) throws DOMException { return null; }
+
+        @Override
+        public Node removeChild(Node oldChild) throws DOMException { return null; }
+
+        @Override
+        public Node appendChild(Node newChild) throws DOMException { return null; }
+
+        @Override
+        public boolean hasChildNodes() { return false; }
+
+        @Override
+        public Node cloneNode(boolean deep) { return null; }
+
+        @Override
+        public void normalize() {}
+
+        @Override
+        public boolean isSupported(String feature, String version) { return false; }
+
+        @Override
+        public String getNamespaceURI() { return null; }
+
+        @Override
+        public String getPrefix() { return null; }
+
+        @Override
+        public void setPrefix(String prefix) throws DOMException {}
+
+        @Override
+        public String getLocalName() { return null; }
+
+        @Override
+        public boolean hasAttributes() { return false; }
+
+        @Override
+        public String getBaseURI() { return null; }
+
+        @Override
+        public short compareDocumentPosition(Node other) throws DOMException {
+            return DOCUMENT_POSITION_CONTAINED_BY;
+        }
+
+        @Override
+        public String getTextContent() throws DOMException { return null; }
+
+        @Override
+        public void setTextContent(String textContent) throws DOMException {}
+
+        @Override
+        public boolean isSameNode(Node other) { return false; }
+
+        @Override
+        public String lookupPrefix(String namespaceURI) { return null; }
+
+        @Override
+        public boolean isDefaultNamespace(String namespaceURI) { return false; }
+
+        @Override
+        public String lookupNamespaceURI(String prefix) { return null; }
+
+        @Override
+        public boolean isEqualNode(Node arg) { return false; }
+
+        @Override
+        public Object getFeature(String feature, String version) { return null; }
+
+        @Override
+        public Object setUserData(String key, Object data, UserDataHandler handler) { return null; }
+
+        @Override
+        public Object getUserData(String key) { return null; }
+
+        @Override
+        public DocumentType getDoctype() { return null; }
+
+        @Override
+        public DOMImplementation getImplementation() { return null; }
+
+        @Override
+        public Element getDocumentElement() { return null; }
+
+        @Override
+        public Element createElement(String tagName) throws DOMException { return null; }
+
+        @Override
+        public DocumentFragment createDocumentFragment() { return null; }
+
+        @Override
+        public Text createTextNode(String data) { return null; }
+
+        @Override
+        public Comment createComment(String data) { return null; }
+
+        @Override
+        public CDATASection createCDATASection(String data) throws DOMException { return null; }
+
+        @Override
+        public ProcessingInstruction createProcessingInstruction(String target, String data)
+                throws DOMException  { return null; }
+
+        @Override
+        public Attr createAttribute(String name) throws DOMException { return null; }
+
+        @Override
+        public EntityReference createEntityReference(String name) throws DOMException {
+            return null;
+        }
+
+        @Override
+        public NodeList getElementsByTagName(String tagname) { return null; }
+
+        @Override
+        public Node importNode(Node importedNode, boolean deep) throws DOMException  {
+            return null;
+        }
+
+        @Override
+        public Element createElementNS(String namespaceURI, String qualifiedName)
+                throws DOMException { return null; }
+
+        @Override
+        public Attr createAttributeNS(String namespaceURI, String qualifiedName)
+                throws DOMException { return null; }
+
+        @Override
+        public NodeList getElementsByTagNameNS(String namespaceURI, String localName)  {
+            return null;
+        }
+
+        @Override
+        public Element getElementById(String elementId) { return null; }
+
+        @Override
+        public String getInputEncoding() { return null; }
+
+        @Override
+        public String getXmlEncoding() { return null; }
+
+        @Override
+        public boolean getXmlStandalone() { return false; }
+
+        @Override
+        public void setXmlStandalone(boolean xmlStandalone) throws DOMException {}
+
+        @Override
+        public String getXmlVersion()  { return null; }
+
+        @Override
+        public void setXmlVersion(String xmlVersion) throws DOMException {}
+
+        @Override
+        public boolean getStrictErrorChecking() { return false; }
+
+        @Override
+        public void setStrictErrorChecking(boolean strictErrorChecking) {}
+
+        @Override
+        public String getDocumentURI() { return null;  }
+
+        @Override
+        public void setDocumentURI(String documentURI) {}
+
+        @Override
+        public Node adoptNode(Node source) throws DOMException { return null; }
+
+        @Override
+        public DOMConfiguration getDomConfig() { return null; }
+
+        @Override
+        public void normalizeDocument() {}
+
+        @Override
+        public Node renameNode(Node n, String namespaceURI, String qualifiedName)
+                throws DOMException { return null; }
+    }
+
+    private static final class NodeListImpl implements NodeList {
+
+        private final ArrayList<Node> list;
+
+        public NodeListImpl(ArrayList<Node> list) {
+            this.list = list;
+        }
+
+        @Override
+        public Node item(int index) {
+            return list.get(index);
+        }
+
+        @Override
+        public int getLength() {
+            return list.size();
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/dom/DOMSourceTest.java b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMSourceTest.java
new file mode 100644
index 0000000..2c18046
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMSourceTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.javax.xml.transform.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.dom.DOMSource;
+import org.apache.harmony.xml.dom.CDATASectionImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.Node;
+
+@RunWith(JUnit4.class)
+public class DOMSourceTest {
+
+    @Test
+    public void constructor() {
+        DOMSource source = new DOMSource();
+        assertNotNull(source);
+        assertNull(source.getNode());
+        assertNull(source.getSystemId());
+    }
+
+    @Test
+    public void constructorWithNodeAndString() {
+        Node node = new CDATASectionImpl(null, "");
+        DOMSource source = new DOMSource(node, "systemId");
+        assertEquals(node, source.getNode());
+        assertEquals("systemId", source.getSystemId());
+    }
+
+    @Test
+    public void setSystemId() {
+        DOMSource source = new DOMSource();
+        assertNull(source.getSystemId());
+
+        source.setSystemId("systemId");
+        assertEquals("systemId", source.getSystemId());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/sax/SAXResultTest.java b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXResultTest.java
new file mode 100644
index 0000000..becccbb
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXResultTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.javax.xml.transform.sax;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.sax.SAXResult;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.DefaultHandler;
+
+@RunWith(JUnit4.class)
+public class SAXResultTest {
+
+    private SAXResult result;
+
+    @Before
+    public void setUp() {
+        result = new SAXResult();
+    }
+
+    @Test
+    public void constructor() {
+        result = new SAXResult();
+        assertNull(result.getHandler());
+        assertNull(result.getLexicalHandler());
+        assertNull(result.getSystemId());
+    }
+
+    @Test
+    public void constructor_withContentHandler() {
+        ContentHandler handler = new DefaultHandler();
+        result = new SAXResult(handler);
+        assertEquals(handler, result.getHandler());
+        assertNull(result.getLexicalHandler());
+        assertNull(result.getSystemId());
+    }
+
+    @Test
+    public void getSetHandler() {
+        assertNull(result.getHandler());
+
+        ContentHandler handler = new DefaultHandler();
+        result.setHandler(handler);
+        assertEquals(handler, result.getHandler());
+
+        result.setHandler(null);
+        assertNull(result.getHandler());
+    }
+
+    @Test
+    public void getSetLexicalHandler() {
+        assertNull(result.getLexicalHandler());
+
+        LexicalHandler handler = new DefaultHandler2();
+        result.setLexicalHandler(handler);
+        assertEquals(handler, result.getLexicalHandler());
+
+        result.setLexicalHandler(null);
+        assertNull(result.getLexicalHandler());
+    }
+
+    @Test
+    public void getSetSystemId() {
+        assertNull(result.getSystemId());
+
+        String systemId = "systemId";
+        result.setSystemId(systemId);
+        assertEquals(systemId, result.getSystemId());
+
+        result.setSystemId(null);
+        assertNull(result.getSystemId());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/sax/SAXSourceTest.java b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXSourceTest.java
new file mode 100644
index 0000000..9a35869
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXSourceTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.javax.xml.transform.sax;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import javax.xml.transform.sax.SAXSource;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+
+@RunWith(JUnit4.class)
+public class SAXSourceTest {
+
+    private SAXSource source;
+
+    @Before
+    public void setUp() {
+        source = new SAXSource();
+    }
+
+    @Test
+    public void constructor() {
+        source = new SAXSource();
+        assertNull(source.getInputSource());
+        assertNull(source.getXMLReader());
+    }
+
+    @Test
+    public void constructor_withXMLReaderAndInputSource() {
+        XMLReader reader = new XMLReaderImpl();
+        InputSource is = new InputSource();
+        source = new SAXSource(reader, is);
+        assertEquals(reader, source.getXMLReader());
+        assertEquals(is, source.getInputSource());
+    }
+
+    @Test
+    public void setInputSource() {
+        InputSource is = new InputSource();
+        source.setInputSource(is);
+        assertEquals(is, source.getInputSource());
+
+        source.setInputSource(null);
+        assertNull(source.getInputSource());
+    }
+
+    @Test
+    public void setXMLReader() {
+        XMLReader reader = new XMLReaderImpl();
+        source.setXMLReader(reader);
+        assertEquals(reader, source.getXMLReader());
+
+        source.setXMLReader(null);
+        assertNull(source.getXMLReader());
+    }
+
+    private static final class XMLReaderImpl implements XMLReader {
+
+        @Override
+        public boolean getFeature(String name)
+                throws SAXNotRecognizedException, SAXNotSupportedException { return false; }
+
+        @Override
+        public void setFeature(String name, boolean value)
+                throws SAXNotRecognizedException, SAXNotSupportedException {}
+
+        @Override
+        public Object getProperty(String name)
+                throws SAXNotRecognizedException, SAXNotSupportedException { return null; }
+
+        @Override
+        public void setProperty(String name, Object value)
+                throws SAXNotRecognizedException, SAXNotSupportedException {}
+
+        @Override
+        public void setEntityResolver(EntityResolver resolver) {}
+
+        @Override
+        public EntityResolver getEntityResolver() { return null; }
+
+        @Override
+        public void setDTDHandler(DTDHandler handler) {}
+
+        @Override
+        public DTDHandler getDTDHandler() { return null; }
+
+        @Override
+        public void setContentHandler(ContentHandler handler) {}
+
+        @Override
+        public ContentHandler getContentHandler() { return null; }
+
+        @Override
+        public void setErrorHandler(ErrorHandler handler) {}
+
+        @Override
+        public ErrorHandler getErrorHandler() { return null; }
+
+        @Override
+        public void parse(InputSource input) throws IOException, SAXException {}
+
+        @Override
+        public void parse(String systemId) throws IOException, SAXException {}
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/stream/StreamResultTest.java b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamResultTest.java
new file mode 100644
index 0000000..f7e1541
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamResultTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.javax.xml.transform.stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import javax.xml.transform.stream.StreamResult;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class StreamResultTest {
+
+    private StreamResult result;
+
+    @Before
+    public void setUp() {
+        result = new StreamResult();
+    }
+
+    @Test
+    public void constructor() {
+        result = new StreamResult();
+        assertNotNull(result);
+        assertNull(result.getSystemId());
+    }
+
+    @Test
+    public void constructor_File() {
+        result = new StreamResult(new File("path"));
+        assertEquals("file:///path", result.getSystemId());
+    }
+
+    @Test
+    public void constructor_String() {
+        result = new StreamResult((String)null);
+        assertNull(result.getSystemId());
+
+        result = new StreamResult("");
+        assertEquals("", result.getSystemId());
+
+        result = new StreamResult("some string");
+        assertEquals("some string", result.getSystemId());
+    }
+
+    @Test
+    public void getSystemId() {
+        assertNull(result.getSystemId());
+
+        result = new StreamResult("string constructor");
+        assertEquals("string constructor", result.getSystemId());
+
+        result = new StreamResult(new File("path"));
+        assertEquals("file:///path", result.getSystemId());
+
+        result.setSystemId("hello");
+        assertEquals("hello", result.getSystemId());
+    }
+
+    @Test
+    public void setSystemId_File() {
+        result.setSystemId(new File("path"));
+        assertEquals("file:///path", result.getSystemId());
+
+        result.setSystemId(new File("."));
+        assertEquals("file:///.", result.getSystemId());
+    }
+
+    @Test
+    public void setSystemId_String() {
+        result.setSystemId((String)null);
+        assertNull(result.getSystemId());
+
+        result.setSystemId("hello");
+        assertEquals("hello", result.getSystemId());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/stream/StreamSourceTest.java b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamSourceTest.java
new file mode 100644
index 0000000..b05ad33
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamSourceTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.javax.xml.transform.stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import javax.xml.transform.stream.StreamSource;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class StreamSourceTest {
+
+    private StreamSource source;
+
+    @Before
+    public void setUp() {
+        source = new StreamSource();
+    }
+
+    @Test
+    public void constructor() {
+        source = new StreamSource();
+        assertNull(source.getSystemId());
+        assertNull(source.getPublicId());
+        assertNull(source.getInputStream());
+        assertNull(source.getReader());
+    }
+
+    @Test
+    public void constructor_withInputStreamAndString() {
+        InputStream is = new ByteArrayInputStream(new byte[]{ 0x00 });
+        String systemId = "systemId";
+        source = new StreamSource(is, systemId);
+        assertEquals(is, source.getInputStream());
+        assertEquals(systemId, source.getSystemId());
+    }
+
+    @Test
+    public void constructor_withReaderAndString() {
+        Reader reader = new CharArrayReader(new char[]{ 'a' });
+        String systemId = "systemId";
+        source = new StreamSource(reader, systemId);
+        assertEquals(reader, source.getReader());
+        assertEquals(systemId, source.getSystemId());
+    }
+
+    @Test
+    public void constructor_withString() {
+        String systemId = "systemId";
+        source = new StreamSource(systemId);
+        assertEquals(systemId, source.getSystemId());
+    }
+
+    @Test
+    public void setInputStream() {
+        InputStream is = new ByteArrayInputStream(new byte[]{ 0x00 });
+        source.setInputStream(is);
+        assertEquals(is, source.getInputStream());
+
+        source.setInputStream(null);
+        assertNull(source.getInputStream());
+    }
+
+    @Test
+    public void setPublicId() {
+        String publicId = "publicId";
+        source.setPublicId(publicId);
+        assertEquals(publicId, source.getPublicId());
+
+        source.setPublicId(null);
+        assertNull(source.getPublicId());
+    }
+
+    @Test
+    public void setSystemId_withFile() {
+        source.setSystemId(new File("path"));
+        assertEquals("file:///path", source.getSystemId());
+
+        source.setSystemId(new File("."));
+        assertEquals("file:///.", source.getSystemId());
+    }
+
+    @Test
+    public void setSystemId_withString() {
+        String systemId = "systemId";
+        source.setSystemId(systemId);
+        assertEquals(systemId, source.getSystemId());
+
+        source.setSystemId((String)null);
+        assertNull(source.getSystemId());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/validation/ValidatorHandlerTest.java b/luni/src/test/java/libcore/javax/xml/validation/ValidatorHandlerTest.java
new file mode 100644
index 0000000..b03e288
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/validation/ValidatorHandlerTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.javax.xml.validation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+import javax.xml.validation.TypeInfoProvider;
+import javax.xml.validation.ValidatorHandler;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+
+@RunWith(JUnit4.class)
+public class ValidatorHandlerTest {
+
+    private ValidatorHandler handler;
+
+    @Before
+    public void setUp() {
+        handler = new ValidatorHandlerImpl();
+    }
+
+    @Test
+    public void constructor() {
+        handler = new ValidatorHandlerImpl();
+        assertNotNull(handler);
+    }
+
+    @Test
+    public void getFeature() {
+        assertThrows(NullPointerException.class, () -> handler.getFeature(null));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getFeature("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getFeature(""));
+    }
+
+    @Test
+    public void getProperty() {
+        assertThrows(NullPointerException.class, () -> handler.getFeature(null));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getFeature("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getFeature(""));
+    }
+
+    @Test
+    public void setFeature() {
+        assertThrows(NullPointerException.class,
+                () -> handler.setFeature(null, false));
+        assertThrows(NullPointerException.class,
+                () -> handler.setFeature(null, true));
+
+        String[] features = {"", "hello", "feature"};
+        boolean[] trueAndFalse = {true, false};
+        for (String feature : features) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> handler.setFeature(feature, value));
+            }
+        }
+    }
+
+    @Test
+    public void setProperty() {
+        assertThrows(NullPointerException.class,
+                () -> handler.setProperty(null, false));
+        assertThrows(NullPointerException.class,
+                () -> handler.setProperty(null, true));
+
+        String[] properties = {"", "hello", "property"};
+        boolean[] trueAndFalse = {true, false};
+        for (String property : properties) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> handler.setProperty(property, value));
+            }
+        }
+    }
+
+    private static final class ValidatorHandlerImpl extends ValidatorHandler {
+
+        @Override
+        public ContentHandler getContentHandler() {
+            return null;
+        }
+
+        @Override
+        public void setContentHandler(ContentHandler receiver) {
+        }
+
+        @Override
+        public ErrorHandler getErrorHandler() {
+            return null;
+        }
+
+        @Override
+        public void setErrorHandler(ErrorHandler errorHandler) {
+        }
+
+        @Override
+        public LSResourceResolver getResourceResolver() {
+            return null;
+        }
+
+        @Override
+        public void setResourceResolver(LSResourceResolver resourceResolver) {
+        }
+
+        @Override
+        public TypeInfoProvider getTypeInfoProvider() {
+            return null;
+        }
+
+        @Override
+        public void setDocumentLocator(Locator locator) {
+        }
+
+        @Override
+        public void startDocument() throws SAXException {
+        }
+
+        @Override
+        public void endDocument() throws SAXException {
+        }
+
+        @Override
+        public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        }
+
+        @Override
+        public void endPrefixMapping(String prefix) throws SAXException {
+        }
+
+        @Override
+        public void startElement(String uri, String localName, String qName, Attributes atts)
+                throws SAXException {
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName) throws SAXException {
+        }
+
+        @Override
+        public void characters(char[] ch, int start, int length) throws SAXException {
+        }
+
+        @Override
+        public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+        }
+
+        @Override
+        public void processingInstruction(String target, String data) throws SAXException {
+        }
+
+        @Override
+        public void skippedEntity(String name) throws SAXException {
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/validation/ValidatorTest.java b/luni/src/test/java/libcore/javax/xml/validation/ValidatorTest.java
new file mode 100644
index 0000000..bc3bd97
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/validation/ValidatorTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.javax.xml.validation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+import java.io.IOException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.validation.Validator;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+
+@RunWith(JUnit4.class)
+public class ValidatorTest {
+
+    private Validator validator;
+
+    @Before
+    public void setUp() {
+        validator = new ValidatorImpl();
+    }
+
+    @Test
+    public void constructor() {
+        validator = new ValidatorImpl();
+        assertNotNull(validator);
+    }
+
+    @Test
+    public void getFeature() {
+        assertThrows(NullPointerException.class, () -> validator.getFeature(null));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getFeature("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getFeature(""));
+    }
+
+    @Test
+    public void getProperty() {
+        assertThrows(NullPointerException.class, () -> validator.getFeature(null));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getFeature("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getFeature(""));
+    }
+
+    @Test
+    public void setFeature() {
+        assertThrows(NullPointerException.class,
+                () -> validator.setFeature(null, false));
+        assertThrows(NullPointerException.class,
+                () -> validator.setFeature(null, true));
+
+        String[] features = {"", "hello", "feature"};
+        boolean[] trueAndFalse = {true, false};
+        for (String feature : features) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> validator.setFeature(feature, value));
+            }
+        }
+    }
+
+    @Test
+    public void setProperty() {
+        assertThrows(NullPointerException.class,
+                () -> validator.setProperty(null, false));
+        assertThrows(NullPointerException.class,
+                () -> validator.setProperty(null, true));
+
+        String[] properties = {"", "hello", "property"};
+        boolean[] trueAndFalse = {true, false};
+        for (String property : properties) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> validator.setProperty(property, value));
+            }
+        }
+    }
+
+    @Test
+    public void validate() throws IOException, SAXException {
+        Source source = new SAXSource();
+        validator.validate(source);
+    }
+
+    private static final class ValidatorImpl extends Validator {
+
+        @Override
+        public void reset() {
+        }
+
+        @Override
+        public void validate(Source source, Result result) throws SAXException, IOException {
+        }
+
+        @Override
+        public ErrorHandler getErrorHandler() {
+            return null;
+        }
+
+        @Override
+        public void setErrorHandler(ErrorHandler errorHandler) {
+        }
+
+        @Override
+        public LSResourceResolver getResourceResolver() {
+            return null;
+        }
+
+        @Override
+        public void setResourceResolver(LSResourceResolver resourceResolver) {
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java
new file mode 100644
index 0000000..79e4707
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathException;
+
+@RunWith(JUnit4.class)
+public class XPathExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathException e = new XPathException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathException e = new XPathException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathExpressionExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathExpressionExceptionTest.java
new file mode 100644
index 0000000..96568e0
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathExpressionExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathExpressionException;
+
+@RunWith(JUnit4.class)
+public class XPathExpressionExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathExpressionException e = new XPathExpressionException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathExpressionException e = new XPathExpressionException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryConfigurationExceptionTest.java
new file mode 100644
index 0000000..d0e5c54
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryConfigurationExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathFactoryConfigurationException;
+
+@RunWith(JUnit4.class)
+public class XPathFactoryConfigurationExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathFactoryConfigurationException e = new XPathFactoryConfigurationException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathFactoryConfigurationException e = new XPathFactoryConfigurationException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathFunctionExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathFunctionExceptionTest.java
new file mode 100644
index 0000000..2eaac48
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathFunctionExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathFunctionException;
+
+@RunWith(JUnit4.class)
+public class XPathFunctionExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathFunctionException e = new XPathFunctionException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathFunctionException e = new XPathFunctionException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/libcore/io/MemoryTest.java b/luni/src/test/java/libcore/libcore/io/MemoryTest.java
index 80ff4ea..4047e3c 100644
--- a/luni/src/test/java/libcore/libcore/io/MemoryTest.java
+++ b/luni/src/test/java/libcore/libcore/io/MemoryTest.java
@@ -143,4 +143,54 @@
             assertEquals(expectedValues[i], Memory.peekShort(ptr + Short.BYTES * i, swap));
         }
     }
+
+    public void testMemmove() {
+        final int size = 100;
+        checkPartialMemmove(size, 0, 0, size);
+        checkPartialMemmove(size, 0, 0, size / 2);
+        checkPartialMemmove(size, size / 2, size / 2, size - size / 2);
+        checkPartialMemmove(size, 10, 20, 20);
+
+        checkOverlappingMemmove(size, 0, 0, size);
+        checkOverlappingMemmove(size, 10, 20, 30);
+        checkOverlappingMemmove(size, 20, 10, 30);
+    }
+
+    private void checkPartialMemmove(int size, int offsetDst, int offsetSrc, int count) {
+        byte[] src = new byte[size];
+        for (int i = 0; i < size; ++i) {
+            src[i] = (byte)i;
+        }
+        byte[] dst = new byte[size];
+        Arrays.fill(dst, (byte)-1);
+
+        assertTrue(offsetSrc + count <= size);
+        assertTrue(offsetDst + count <= size);
+        Memory.memmove(dst, offsetDst, src, offsetSrc, count);
+        for (int i = 0; i < size; ++i) {
+            if (i >= offsetDst && i < offsetDst + count) {
+                assertEquals(src[i + (offsetSrc - offsetDst)], dst[i]);
+            } else {
+                assertEquals((byte)-1, dst[i]);
+            }
+        }
+    }
+
+    private void checkOverlappingMemmove(int size, int offsetDst, int offsetSrc, int count) {
+        byte[] buf = new byte[size];
+        for (int i = 0; i < size; ++i) {
+            buf[i] = (byte)i;
+        }
+
+        assertTrue(offsetSrc + count <= size);
+        assertTrue(offsetDst + count <= size);
+        Memory.memmove(buf, offsetDst, buf, offsetSrc, count);
+        for (int i = 0; i < size; ++i) {
+            if (i >= offsetDst && i < offsetDst + count) {
+                assertEquals(i + (offsetSrc - offsetDst), buf[i]);
+            } else {
+                assertEquals((byte)i, buf[i]);
+            }
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/libcore/io/StreamsTest.java b/luni/src/test/java/libcore/libcore/io/StreamsTest.java
new file mode 100644
index 0000000..2b0e627
--- /dev/null
+++ b/luni/src/test/java/libcore/libcore/io/StreamsTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 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.libcore.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+import libcore.io.Streams;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class StreamsTest {
+
+    @Test
+    public void testReadFully() throws Exception {
+        final byte[] bytes = "0123456789".getBytes();
+        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
+        byte[] dst = new byte[bytes.length - 1];
+
+        Arrays.fill(dst, (byte)-1);
+        Streams.readFully(inStream, dst);
+        for (int i = 0; i < dst.length; ++i) {
+            assertEquals(bytes[i], dst[i]);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/sun/misc/UnsafeTest.java b/luni/src/test/java/libcore/sun/misc/UnsafeTest.java
index 483398b..994f6bb 100644
--- a/luni/src/test/java/libcore/sun/misc/UnsafeTest.java
+++ b/luni/src/test/java/libcore/sun/misc/UnsafeTest.java
@@ -16,6 +16,8 @@
 
 package libcore.sun.misc;
 
+import static org.junit.Assert.assertEquals;
+
 import junit.framework.TestCase;
 
 import java.lang.reflect.Field;
@@ -72,4 +74,230 @@
         assertEquals(null, i.s);
         assertEquals(i, i.getThis());
     }
+
+    public void test_copyMemory() throws Exception {
+        Unsafe unsafe = getUnsafe();
+
+        // Source buffer.
+        byte[] msg = "All your base are belong to us.".getBytes();
+        long srcBuf = unsafe.allocateMemory(msg.length);
+        {
+            long srcPtr = srcBuf;
+            for (byte b : msg){
+                unsafe.putByte(srcPtr++, b);
+            }
+        }
+
+        // Destination buffer.
+        long dstBuf = getUnsafe().allocateMemory(msg.length);
+        unsafe.copyMemory(srcBuf, dstBuf, msg.length);
+
+        // Compare buffers.
+        long srcPtr = srcBuf;
+        long dstPtr = dstBuf;
+        for (int i = 0; i < msg.length; ++i) {
+            byte srcByte = unsafe.getByte(srcPtr++);
+            byte dstByte = unsafe.getByte(dstPtr++);
+            assertEquals(String.format("Content mismatch at offset %d: src = '%c', dst = '%c'",
+                            i, srcByte, dstByte),
+                    srcByte, dstByte);
+        }
+
+        // Clean up.
+        unsafe.freeMemory(dstBuf);
+        unsafe.freeMemory(srcBuf);
+    }
+
+    private class TestFixture {
+        public boolean booleanVar = true;
+        public byte byteVar = 42;
+        public int intVar = 2046;
+        public long longVar = 123456789;
+        public float floatVar = 1.618f;
+        public double doubleVar = 3.141;
+        public Object objectVar = new Object();
+    }
+
+    public void test_getBoolean_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field booleanField = TestFixture.class.getDeclaredField("booleanVar");
+        long booleanFieldOffset = unsafe.objectFieldOffset(booleanField);
+        boolean booleanValue = unsafe.getBoolean(tf, booleanFieldOffset);
+        assertEquals(tf.booleanVar, booleanValue);
+    }
+
+    public void test_getByte_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field byteField = TestFixture.class.getDeclaredField("byteVar");
+        long byteFieldOffset = unsafe.objectFieldOffset(byteField);
+        byte byteValue = unsafe.getByte(tf, byteFieldOffset);
+        assertEquals(tf.byteVar, byteValue);
+    }
+
+    public void test_getInt_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field intField = TestFixture.class.getDeclaredField("intVar");
+        long intFieldOffset = unsafe.objectFieldOffset(intField);
+        int intValue = unsafe.getInt(tf, intFieldOffset);
+        assertEquals(tf.intVar, intValue);
+    }
+
+    public void test_getLong_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field longField = TestFixture.class.getDeclaredField("longVar");
+        long longFieldOffset = unsafe.objectFieldOffset(longField);
+        long longValue = unsafe.getLong(tf, longFieldOffset);
+        assertEquals(tf.longVar, longValue);
+    }
+
+    public void test_getFloat_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field floatField = TestFixture.class.getDeclaredField("floatVar");
+        long floatFieldOffset = unsafe.objectFieldOffset(floatField);
+        float floatValue = unsafe.getFloat(tf, floatFieldOffset);
+        assertEquals(tf.floatVar, floatValue);
+    }
+
+    public void test_getDouble_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field doubleField = TestFixture.class.getDeclaredField("doubleVar");
+        long doubleFieldOffset = unsafe.objectFieldOffset(doubleField);
+        double doubleValue = unsafe.getDouble(tf, doubleFieldOffset);
+        assertEquals(tf.doubleVar, doubleValue);
+    }
+
+    public void test_getObject_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field objectField = TestFixture.class.getDeclaredField("objectVar");
+        long objectFieldOffset = unsafe.objectFieldOffset(objectField);
+        Object objectValue = unsafe.getObject(tf, objectFieldOffset);
+        assertEquals(tf.objectVar, objectValue);
+    }
+
+    public void test_putBoolean_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field booleanField = TestFixture.class.getDeclaredField("booleanVar");
+        long booleanFieldOffset = unsafe.objectFieldOffset(booleanField);
+        boolean booleanValue = false;
+        unsafe.putBoolean(tf, booleanFieldOffset, booleanValue);
+        assertEquals(booleanValue, tf.booleanVar);
+    }
+
+    public void test_putByte_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field byteField = TestFixture.class.getDeclaredField("byteVar");
+        long byteFieldOffset = unsafe.objectFieldOffset(byteField);
+        byte byteValue = 83;
+        unsafe.putByte(tf, byteFieldOffset, byteValue);
+        assertEquals(byteValue, tf.byteVar);
+    }
+
+    public void test_putInt_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field intField = TestFixture.class.getDeclaredField("intVar");
+        long intFieldOffset = unsafe.objectFieldOffset(intField);
+        int intValue = 3000;
+        unsafe.putInt(tf, intFieldOffset, intValue);
+        assertEquals(intValue, tf.intVar);
+    }
+
+    public void test_putLong_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field longField = TestFixture.class.getDeclaredField("longVar");
+        long longFieldOffset = unsafe.objectFieldOffset(longField);
+        long longValue = 9000;
+        unsafe.putLong(tf, longFieldOffset, longValue);
+        assertEquals(longValue, tf.longVar);
+    }
+
+    public void test_putFloat_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field floatField = TestFixture.class.getDeclaredField("floatVar");
+        long floatFieldOffset = unsafe.objectFieldOffset(floatField);
+        float floatValue = 0.987f;
+        unsafe.putFloat(tf, floatFieldOffset, floatValue);
+        assertEquals(floatValue, tf.floatVar);
+    }
+
+    public void test_putDouble_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field doubleField = TestFixture.class.getDeclaredField("doubleVar");
+        long doubleFieldOffset = unsafe.objectFieldOffset(doubleField);
+        double doubleValue = 0.123;
+        unsafe.putDouble(tf, doubleFieldOffset, doubleValue);
+        assertEquals(doubleValue, tf.doubleVar);
+    }
+
+    public void test_putObject_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field objectField = TestFixture.class.getDeclaredField("objectVar");
+        long objectFieldOffset = unsafe.objectFieldOffset(objectField);
+        Object objectValue = new Object();
+        unsafe.putObject(tf, objectFieldOffset, objectValue);
+        assertEquals(objectValue, tf.objectVar);
+    }
+
+    public void test_putByte_getByte_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Byte.BYTES);
+        byte byteValue1 = 51;
+        unsafe.putByte(buffer, byteValue1);
+        byte byteValue2 = unsafe.getByte(buffer);
+        assertEquals(byteValue2, byteValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putInt_getInt_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Integer.BYTES);
+        int intValue1 = 2047;
+        unsafe.putInt(buffer, intValue1);
+        int intValue2 = unsafe.getInt(buffer);
+        assertEquals(intValue2, intValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putLong_getLong_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Long.BYTES);
+        long longValue1 = 987654321;
+        unsafe.putLong(buffer, longValue1);
+        long longValue2 = unsafe.getLong(buffer);
+        assertEquals(longValue2, longValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putFloat_getFloat_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Float.BYTES);
+        float floatValue1 = 2.718f;
+        unsafe.putFloat(buffer, floatValue1);
+        float floatValue2 = unsafe.getFloat(buffer);
+        assertEquals(floatValue2, floatValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putDouble_getDouble_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Double.BYTES);
+        double doubleValue1 = 6.283;
+        unsafe.putDouble(buffer, doubleValue1);
+        double doubleValue2 = unsafe.getDouble(buffer);
+        assertEquals(doubleValue2, doubleValue1);
+        unsafe.freeMemory(buffer);
+    }
 }
diff --git a/luni/src/test/java/libcore/xml/XmlToSax2DriverTest.java b/luni/src/test/java/libcore/xml/XmlToSax2DriverTest.java
new file mode 100644
index 0000000..9e4b47c
--- /dev/null
+++ b/luni/src/test/java/libcore/xml/XmlToSax2DriverTest.java
@@ -0,0 +1,474 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import junit.framework.TestCase;
+import org.junit.Assert;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.sax2.Driver;
+
+public class XmlToSax2DriverTest extends TestCase {
+
+    private static final String XML =
+            "<note type=\"email\" foo=\"bar\">"
+            + "<to>John</to>"
+            + "<from>Smith</from>"
+            + "<heading>Lunch today</heading>"
+            + "<body>Hi, shall we go to lunch at 12?</body>"
+            + "</note>";
+
+    private Driver driver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        driver = new Driver();
+    }
+
+    public void testConstructor() {
+        Driver driver = null;
+        try {
+            driver = new Driver();
+        } catch (XmlPullParserException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+
+        assertEquals(0, driver.getLength());
+        assertEquals(1, driver.getColumnNumber());
+        assertEquals(1, driver.getLineNumber());
+    }
+
+    public void testConstructor_parametrized() {
+        XmlPullParserFactory factory;
+        XmlPullParser parser = null;
+
+        try {
+            factory = XmlPullParserFactory.newInstance(null, null);
+            parser = factory.newPullParser();
+        } catch (XmlPullParserException e) {
+            fail("Couldn't create factory and parser");
+        }
+        Driver driver = null;
+
+        try {
+             driver = new Driver(parser);
+        } catch (XmlPullParserException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+
+        assertEquals(0, driver.getLength());
+        assertEquals(1, driver.getColumnNumber());
+        assertEquals(1, driver.getLineNumber());
+    }
+
+    public void testGetColumnNumber() {
+        assertEquals(driver.getColumnNumber(), 1);
+    }
+
+    public void testGetSetContentHandler() throws XmlPullParserException {
+        assertTrue(driver.getContentHandler() instanceof DefaultHandler);
+
+        ContentHandler handler = new DefaultHandler();
+        driver.setContentHandler(handler);
+        assertEquals(driver.getContentHandler(), handler);
+
+        driver.setContentHandler(null);
+        assertNull(driver.getContentHandler());
+    }
+
+    public void testGetSetDTDHandler() {
+        assertNull(driver.getDTDHandler());
+
+        driver.setDTDHandler(new DefaultHandler());
+        assertNull(driver.getDTDHandler());
+
+        driver.setDTDHandler(null);
+        assertNull(driver.getDTDHandler());
+    }
+
+    public void testGetSetEntityResolver() {
+        assertNull(driver.getEntityResolver());
+
+        driver.setEntityResolver(new DefaultHandler());
+        assertNull(driver.getEntityResolver());
+
+        driver.setEntityResolver((publicId, systemId) -> null);
+        assertNull(driver.getEntityResolver());
+
+        driver.setEntityResolver(null);
+        assertNull(driver.getEntityResolver());
+    }
+
+    public void testGetSetErrorHandler() {
+        assertTrue(driver.getContentHandler() instanceof DefaultHandler);
+
+        ErrorHandler handler = new DefaultHandler();
+        driver.setErrorHandler(handler);
+        assertEquals(handler, driver.getErrorHandler());
+
+        driver.setErrorHandler(null);
+        assertNull(driver.getErrorHandler());
+    }
+
+    public void testGetSetFeature() throws SAXNotSupportedException, SAXNotRecognizedException {
+        final String NAMESPACES_FEATURE = "http://xml.org/sax/features/namespaces";
+        final String NAMESPACE_PREFIXES_FEATURE = "http://xml.org/sax/features/namespace-prefixes";
+        final String VALIDATION_FEATURE = "http://xml.org/sax/features/validation";
+        final String PROCESS_DOCDECL_FEATURE =
+                "http://xmlpull.org/v1/doc/features.html#process-docdecl";
+        final String REPORT_NAMESPACE_ATTRIBUTES_FEATURE =
+                "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
+        final String RELAXED_FEATURE = "http://xmlpull.org/v1/doc/features.html#relaxed";
+
+        final Object[][] expectations = {
+                {NAMESPACE_PREFIXES_FEATURE, false},
+                {VALIDATION_FEATURE, false},
+                {PROCESS_DOCDECL_FEATURE, false},
+                {REPORT_NAMESPACE_ATTRIBUTES_FEATURE, false},
+                {NAMESPACES_FEATURE, true},
+        };
+
+        for (Object[] f : expectations) {
+            final String feature = (String) f[0];
+            final boolean result = (boolean) f[1];
+            try {
+                assertEquals(result, driver.getFeature(feature));
+            } catch (SAXNotSupportedException | SAXNotRecognizedException e) {
+                fail("Unexpected exception: " + e.getMessage());
+            }
+        }
+
+        final String[] settable = {
+                NAMESPACES_FEATURE,
+                PROCESS_DOCDECL_FEATURE,
+                RELAXED_FEATURE,
+        };
+        for (String feature : settable) {
+            for (boolean value : new boolean[]{ false, true }) {
+                driver.setFeature(feature, value);
+                assertEquals(feature, value, driver.getFeature(feature));
+            }
+        }
+    }
+
+    public void testGetIndex() throws NoSuchFieldException, IllegalAccessException {
+        assertEquals(-1, driver.getIndex("hello"));
+        assertEquals(-1, driver.getIndex("encoding"));
+        assertEquals(-1, driver.getIndex("version"));
+    }
+
+    public void testGetIndex_namespaced() {
+        assertEquals(-1, driver.getIndex("", "version"));
+    }
+
+    public void testGetLength() {
+        assertEquals(0, driver.getLength());
+    }
+
+    public void testGetLineNumber() {
+        assertEquals(1, driver.getLineNumber());
+    }
+
+    public void testGetLocalName() {
+        try {
+            driver.getLocalName(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testGetProperty() {
+        try {
+            driver.getProperty("");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        } catch (SAXNotSupportedException | SAXNotRecognizedException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+    }
+
+    public void testGetPublicId() {
+        assertNull(driver.getPublicId());
+    }
+
+    public void testGetQName() {
+        try {
+            driver.getQName(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testGetSystemId() {
+        assertNull(driver.getSystemId());
+    }
+
+    public void testGetType() {
+        assertEquals("CDATA", driver.getType(0));
+        assertNull(driver.getType("value"));
+        assertNull(driver.getType("", "value"));
+    }
+
+    public void testGetUri() {
+        try {
+            driver.getURI(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            driver.getValue(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertNull("CDATA", driver.getValue("value"));
+        assertNull("CDATA", driver.getValue("", "value"));
+    }
+
+    public void testParse_String() {
+        try {
+            driver.parse("systemId");
+        } catch (SAXException | IOException e) {
+            // expected
+        }
+
+        String systemId = null;
+        try {
+            driver.parse(systemId);
+        } catch (SAXException | IOException e) {
+            // expected
+        }
+    }
+
+    public void testParse_InputSource() throws IOException, SAXException {
+        InputSource source = new InputSource();
+        source.setCharacterStream(new StringReader(XML));
+        source.setSystemId("systemId");
+
+        final int[] errors = {0, 0, 0};
+        driver.setErrorHandler(new ErrorHandler() {
+            @Override
+            public void warning(SAXParseException exception) throws SAXException {
+                errors[0]++;
+            }
+
+            @Override
+            public void error(SAXParseException exception) throws SAXException {
+                errors[1]++;
+            }
+
+            @Override
+            public void fatalError(SAXParseException exception) throws SAXException {
+                errors[2]++;
+            }
+        });
+
+        // Four events counter: { "startDocument", "endDocument", "startElement", "endElement" }
+        final int[] events = {0, 0, 0, 0};
+        final ArrayList<String> tagsEncountered = new ArrayList<>();
+        final ArrayList<String> textsEncountered = new ArrayList<>();
+        driver.setContentHandler(new DefaultHandler() {
+            @Override
+            public void startDocument() throws SAXException {
+                super.startDocument();
+                events[0]++;
+            }
+
+            @Override
+            public void endDocument() throws SAXException {
+                super.endDocument();
+                events[1]++;
+            }
+
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                super.startElement(uri, localName, qName, attributes);
+                events[2]++;
+                tagsEncountered.add(localName);
+                if ("note".equals(localName)) {
+                    assertEquals(2, attributes.getLength());
+                    assertEquals("type", attributes.getLocalName(0));
+                    assertEquals("email", attributes.getValue(0));
+                    assertEquals("foo", attributes.getLocalName(1));
+                    assertEquals("bar", attributes.getValue(1));
+                }
+            }
+
+            @Override
+            public void characters(char[] ch, int start, int length) throws SAXException {
+                super.characters(ch, start, length);
+                textsEncountered.add(StringFactory.newStringFromChars(ch, start, length));
+            }
+
+            @Override
+            public void endElement(String uri, String localName, String qName) throws SAXException {
+                super.endElement(uri, localName, qName);
+                events[3]++;
+            }
+        });
+        driver.parse(source);
+
+        assertEquals("systemId", driver.getSystemId());
+        Assert.assertArrayEquals(new int[]{0, 0, 0}, errors);
+        Assert.assertArrayEquals(new int[]{1, 1, 5, 5}, events);
+        Assert.assertArrayEquals(new String[]{"note", "to", "from", "heading", "body"},
+                tagsEncountered.toArray());
+        Assert.assertArrayEquals(new String[]{
+                "John", "Smith", "Lunch today", "Hi, shall we go to lunch at 12?"
+        }, textsEncountered.toArray());
+    }
+
+    public void testParseSubtree() throws XmlPullParserException, IOException {
+        XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+        parser.setInput(new StringReader(XML));
+
+        final int[] errors = {0, 0, 0};
+        driver.setErrorHandler(new ErrorHandler() {
+            @Override
+            public void warning(SAXParseException exception) throws SAXException {
+                errors[0]++;
+            }
+
+            @Override
+            public void error(SAXParseException exception) throws SAXException {
+                errors[1]++;
+            }
+
+            @Override
+            public void fatalError(SAXParseException exception) throws SAXException {
+                errors[2]++;
+            }
+        });
+
+        // Four events counter: { "startDocument", "endDocument", "startElement", "endElement" }
+        final int[] events = {0, 0, 0, 0};
+        final ArrayList<String> tagsEncountered = new ArrayList<>();
+        final ArrayList<String> textsEncountered = new ArrayList<>();
+        driver.setContentHandler(new DefaultHandler() {
+            @Override
+            public void startDocument() throws SAXException {
+                super.startDocument();
+                events[0]++;
+            }
+
+            @Override
+            public void endDocument() throws SAXException {
+                super.endDocument();
+                events[1]++;
+            }
+
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                super.startElement(uri, localName, qName, attributes);
+                events[2]++;
+                tagsEncountered.add(localName);
+                if ("note".equals(localName)) {
+                    assertEquals(2, attributes.getLength());
+                    assertEquals("type", attributes.getLocalName(0));
+                    assertEquals("email", attributes.getValue(0));
+                    assertEquals("foo", attributes.getLocalName(1));
+                    assertEquals("bar", attributes.getValue(1));
+                }
+            }
+
+            @Override
+            public void characters(char[] ch, int start, int length) throws SAXException {
+                super.characters(ch, start, length);
+                textsEncountered.add(StringFactory.newStringFromChars(ch, start, length));
+            }
+
+            @Override
+            public void endElement(String uri, String localName, String qName) throws SAXException {
+                super.endElement(uri, localName, qName);
+                events[3]++;
+            }
+        });
+
+        try {
+            driver.parseSubTree(parser);
+        } catch (SAXException e) {
+            // expected, as START_TAG should have been read already
+        } catch (IOException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+        assertEquals(XmlPullParser.START_TAG, parser.next());
+        try {
+            driver.parseSubTree(parser);
+        } catch (SAXException | IOException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+
+        Assert.assertArrayEquals(new int[]{0, 0, 0}, errors);
+        Assert.assertArrayEquals(new int[]{0, 0, 5, 5}, events);
+        Assert.assertArrayEquals(new String[]{"note", "to", "from", "heading", "body"},
+                tagsEncountered.toArray());
+        Assert.assertArrayEquals(new String[]{
+                "John", "Smith", "Lunch today", "Hi, shall we go to lunch at 12?"
+        }, textsEncountered.toArray());
+    }
+
+    public void testStartElement() throws XmlPullParserException, IOException, SAXException {
+        boolean[] called = {false};
+        ContentHandler handler = new DefaultHandler() {
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                super.startElement(uri, localName, qName, attributes);
+                called[0] = true;
+            }
+        };
+        ExtendsDriver d = new ExtendsDriver(handler);
+        d.setContentHandler(handler);
+        d.parse(new InputSource(new StringReader(XML)));
+
+        assertTrue(called[0]);
+    }
+
+    private static class ExtendsDriver extends Driver {
+
+        private final ContentHandler handler;
+
+        public ExtendsDriver(ContentHandler handler) throws XmlPullParserException {
+            this.handler = handler;
+        }
+
+        @Override
+        protected void startElement(String namespace, String localName, String qName)
+                throws SAXException {
+            super.startElement(namespace, localName, qName);
+            handler.startElement(namespace, localName, qName, this);
+        }
+    }
+}
diff --git a/luni/src/test/java/tests/java/lang/ClassLoaderTest.java b/luni/src/test/java/tests/java/lang/ClassLoaderTest.java
new file mode 100644
index 0000000..717a562
--- /dev/null
+++ b/luni/src/test/java/tests/java/lang/ClassLoaderTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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 tests.java.lang;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ClassLoaderTest {
+
+    class TestClassLoader extends ClassLoader {
+        public Class<?> findSystemClassWrapper(String s) throws ClassNotFoundException {
+            return findSystemClass(s);
+        }
+
+        public Class<?> defineClassWrapper(String name, byte[] b, int off, int len)
+                throws ClassFormatError {
+            return defineClass(name, b, off, len);
+        }
+
+        public void setSignersWrapper(Class<?> c, Object[] signers) {
+            setSigners(c, signers);
+        }
+    }
+
+    private TestClassLoader loader;
+
+    @Before
+    public void setUp() throws Exception {
+        loader = new TestClassLoader();
+    }
+
+    @Test
+    public void test_findSystemClass() {
+        try {
+            loader.findSystemClassWrapper("java.lang.String");
+        } catch (ClassNotFoundException cnfe) {
+            throw new RuntimeException(cnfe);
+        }
+        try {
+            loader.findSystemClassWrapper("nonexistentclass");
+            fail("Expected ClassNotFoundException");
+        } catch (ClassNotFoundException cnfe) {
+        }
+    }
+
+    @Test
+    public void test_defineClass() {
+        try {
+            byte b[] = new byte[1];
+            loader.defineClassWrapper("java.lang.String", b, 0, 0);
+            fail();
+        } catch (UnsupportedOperationException e) {
+            assertEquals(e.getMessage(), "can't load this type of class file");
+        }
+    }
+
+    // setSigners does nothing
+    @Test
+    public void test_setSigners() {
+        Object[] signers = new Object[] { null };
+        loader.setSignersWrapper(Object.class, signers);
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/AssertTest.java b/ojluni/src/test/java/lang/ClassLoader/AssertTest.java
new file mode 100644
index 0000000..83483fe
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/AssertTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4290640 4785473
+ * @build package1.Class1 package2.Class2 package1.package3.Class3 Assert
+ * @run main/othervm Assert
+ * @summary Test the assertion facility
+ * @author Mike McCloskey
+ * @key randomness
+ */
+
+// Android-changed: Adapt structure and expectations to Android.
+// Android does not use AssertionStatuses, so this test changes expectations to reflect that.
+// Furthermore, the test structure is simplified to avoid relying on args[] and use the
+// org.testng.annotations.Test package instead of a main() method.
+package test.java.lang.ClassLoader;
+
+import test.java.lang.ClassLoader.package1.*;
+import test.java.lang.ClassLoader.package2.*;
+import test.java.lang.ClassLoader.package1.package3.*;
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+public class AssertTest {
+
+    private static Class1 testClass1;
+    private static Class2 testClass2;
+    private static Class3 testClass3;
+    private static Random generator = new Random();
+
+    /**
+     * AssertionStatuses don't actually do anything on Android, this test proves as much.
+     */
+    @Test
+    public void testAssert() {
+        // Switch values: 0=don't touch, 1=off, 2 = on
+        int[] switches = new int[7];
+        for(int x=0; x<10; x++) {
+            int temp = generator.nextInt(2187);
+            for (int i = 0; i < 7; i++) {
+                switches[i] = temp % 3;
+                temp = temp / 3;
+            }
+            SetAssertionSwitches(switches);
+            ConstructClassTree();
+            TestClassTree();
+        }
+
+
+        // Android-added: Add testing of clearAssertionStatus().
+        for(int x=0; x<7; x++) {
+            switches[x]=2;
+        }
+        ClassLoader loader = SetAssertionSwitches(switches);
+        loader.clearAssertionStatus(); // Clearing also does nothing
+        ConstructClassTree();
+        TestClassTree();
+    }
+
+    /*
+     * Activate/Deactivate the assertions in the tree according to the
+     * specified switches.
+     */
+    private static ClassLoader SetAssertionSwitches(int[] switches) {
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+
+        if (switches[0] != 0)
+            loader.setDefaultAssertionStatus(switches[0]==2);
+        if (switches[1] != 0)
+            loader.setPackageAssertionStatus("package1", switches[1]==2);
+        if (switches[2] != 0)
+            loader.setPackageAssertionStatus("package2", switches[2]==2);
+        if (switches[3] != 0)
+            loader.setPackageAssertionStatus("package1.package3", switches[3]==2);
+        if (switches[4] != 0)
+            loader.setClassAssertionStatus("package1.Class1", switches[4]==2);
+        if (switches[5] != 0)
+            loader.setClassAssertionStatus("package2.Class2", switches[5]==2);
+        if (switches[6] != 0)
+            loader.setClassAssertionStatus("package1.package3.Class3", switches[6]==2);
+        return loader;
+    }
+
+    /*
+     * Verify that the assertions are activated or deactivated as specified
+     * by the switches.
+     */
+    private static void TestClassTree() {
+        testClass1.testAssert(false);
+        Class1.Class11.testAssert(false);
+        testClass2.testAssert(false);
+        testClass3.testAssert(false);
+        Class3.Class31.testAssert(false);
+
+    }
+
+    /*
+     * Create the class tree to be tested. Each test run must reload the classes
+     * of the tree since assertion status is determined at class load time.
+     */
+    private static void ConstructClassTree() {
+        testClass1 = new Class1();
+        testClass2 = new Class2();
+        testClass3 = new Class3();
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/package1/Class1.java b/ojluni/src/test/java/lang/ClassLoader/package1/Class1.java
new file mode 100644
index 0000000..0c5e7cc
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/package1/Class1.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ClassLoader.package1;
+
+public class Class1 {
+    public void testAssert(boolean assertsShouldBeOn) {
+        boolean assertsEnabled = false;
+        assert(assertsEnabled = true);
+        if (assertsEnabled != assertsShouldBeOn)
+            throw new RuntimeException(assertsEnabled ? "TRUE" : "FALSE");
+
+        Class1 anonTest =  new Class1() {
+            public void testAssert(boolean assertsShouldBeOn) {
+                boolean assertsEnabled2 = false;
+                assert(assertsEnabled2 = true);
+                if (assertsEnabled2 != assertsShouldBeOn)
+                    throw new RuntimeException("Failure of Asserts Facility.");
+            }
+        };
+        anonTest.testAssert(assertsShouldBeOn);
+    }
+
+    // Named inner class
+    public static class Class11 {
+        public static void testAssert(boolean assertsShouldBeOn) {
+            boolean assertsEnabled3 = false;
+            assert(assertsEnabled3 = true);
+            if (assertsEnabled3 != assertsShouldBeOn)
+                throw new RuntimeException("Failure of Asserts Facility.");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/package1/package3/Class3.java b/ojluni/src/test/java/lang/ClassLoader/package1/package3/Class3.java
new file mode 100644
index 0000000..b133e2a
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/package1/package3/Class3.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ClassLoader.package1.package3;
+
+import org.testng.Assert;
+
+public class Class3 {
+    public void testAssert(boolean assertsShouldBeOn) {
+        boolean assertsEnabled = false;
+        assert(assertsEnabled = true);
+        if (assertsEnabled != assertsShouldBeOn)
+            Assert.fail("Failure of Asserts Facility.");
+
+        Class3 anonTest =  new Class3() {
+            public void testAssert(boolean assertsShouldBeOn) {
+                boolean assertsEnabled = false;
+                assert(assertsEnabled = true);
+                if (assertsEnabled != assertsShouldBeOn)
+                    Assert.fail("Failure of Asserts Facility.");
+            }
+        };
+        anonTest.testAssert(assertsShouldBeOn);
+    }
+
+    // Named inner class
+    public static class Class31 {
+        public static void testAssert(boolean assertsShouldBeOn) {
+            boolean assertsEnabled = false;
+            assert(assertsEnabled = true);
+            if (assertsEnabled != assertsShouldBeOn)
+                Assert.fail("Failure of Asserts Facility.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/package2/Class2.java b/ojluni/src/test/java/lang/ClassLoader/package2/Class2.java
new file mode 100644
index 0000000..d7d92bc
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/package2/Class2.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ClassLoader.package2;
+
+
+public class Class2 {
+    public void testAssert(boolean assertsShouldBeOn) {
+        boolean assertsEnabled = false;
+        assert(assertsEnabled = true);
+        if (assertsEnabled != assertsShouldBeOn)
+            throw new RuntimeException("Failure of Asserts Facility.");
+    }
+}
\ No newline at end of file
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index 64392e4..df1a135 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.security.Provider;
 import java.security.Security;
 import java.security.spec.DSAPrivateKeySpec;
 import java.security.spec.DSAPublicKeySpec;
@@ -98,6 +99,15 @@
         assertTrue("Duplicate " + type + " " + algorithm,
                    algorithms.add(algorithm.toUpperCase(Locale.ROOT)));
     }
+    // Only add to PROVIDER_ALGORITHMS if actually present
+    private static void provideOptional(String type, String algorithm) {
+        for (Provider p : Security.getProviders()) {
+            if (p.getService(type, algorithm) != null) {
+                provide(type, algorithm);
+                return;
+            }
+        }
+    }
     private static void unprovide(String type, String algorithm) {
         Set<String> algorithms = PROVIDER_ALGORITHMS.get(type);
         assertNotNull(algorithms);
@@ -420,6 +430,7 @@
             provide("Signature", "SHA256withRSA/PSS");
             provide("Signature", "SHA384withRSA/PSS");
             provide("Signature", "SHA512withRSA/PSS");
+            provideOptional("Signature", "ED25519");
 
             // different names: ARCFOUR vs ARC4
             unprovide("Cipher", "ARCFOUR");