Initial load
diff --git a/test/java/lang/String/CaseConvertSameInstance.java b/test/java/lang/String/CaseConvertSameInstance.java
new file mode 100644
index 0000000..28d44b7
--- /dev/null
+++ b/test/java/lang/String/CaseConvertSameInstance.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1998 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @bug 4130097
+   @summary toUpperCase and toLowerCase always return a new String,
+            whereas if there is no conversion that needs to be done,
+            they should be returning the same instance.
+   @author James Bond/007
+*/
+public class CaseConvertSameInstance {
+    public static void main(String[] args) throws Exception {
+        /* these two are the real tests for this bug. */
+        if ("foobar".toLowerCase() != "foobar")
+            throw new Exception("toLowerCase returned different object");
+        if ("FOOBAR".toUpperCase() != "FOOBAR")
+            throw new Exception("toUpperCase returned different object");
+
+        /* sanity test toLowerCase with some border conditions. */
+        if (!("FooBar".toLowerCase().equals("foobar")))
+            throw new Exception("toLowerCase broken");
+        if (!("fooBar".toLowerCase().equals("foobar")))
+            throw new Exception("toLowerCase broken");
+        if (!("foobaR".toLowerCase().equals("foobar")))
+            throw new Exception("toLowerCase broken");
+        if (!("FOOBAR".toLowerCase().equals("foobar")))
+            throw new Exception("toLowerCase broken");
+
+        /* sanity test toUpperCase with some border conditions. */
+        if (!("FooBar".toUpperCase().equals("FOOBAR")))
+            throw new Exception("toUpperCase broken");
+        if (!("fooBar".toUpperCase().equals("FOOBAR")))
+            throw new Exception("toUpperCase broken");
+        if (!("foobaR".toUpperCase().equals("FOOBAR")))
+            throw new Exception("toUpperCase broken");
+        if (!("foobar".toUpperCase().equals("FOOBAR")))
+            throw new Exception("toUpperCase broken");
+    }
+}
diff --git a/test/java/lang/String/CompareIC.java b/test/java/lang/String/CompareIC.java
new file mode 100644
index 0000000..5168dbf
--- /dev/null
+++ b/test/java/lang/String/CompareIC.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1998 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4124769
+ * @summary Test ignore-case comparison
+ *
+ */
+
+import java.net.*;
+import java.io.InputStream;
+import java.io.IOException;
+
+public class CompareIC {
+
+    public static void main(String[] args) throws Exception {
+        String test1 = "Tess";
+        String test2 = "Test";
+        String test3 = "Tesu";
+        CompareIC comparer = new CompareIC();
+
+        comparer.testTriplet(test1, test2, test3);
+        test2 = test2.toUpperCase();
+        comparer.testTriplet(test1, test2, test3);
+        test2 = test2.toLowerCase();
+        comparer.testTriplet(test1, test2, test3);
+    }
+
+    private void testTriplet(String one, String two, String three)
+        throws Exception {
+            if (one.compareToIgnoreCase(two) > 0)
+                throw new RuntimeException("Comparison failure1");
+            if (two.compareToIgnoreCase(three) > 0)
+                throw new RuntimeException("Comparison failure2");
+            if (three.compareToIgnoreCase(one) < 0)
+                throw new RuntimeException("Comparison failure3");
+    }
+
+}
diff --git a/test/java/lang/String/ContentEquals.java b/test/java/lang/String/ContentEquals.java
new file mode 100644
index 0000000..a562d96
--- /dev/null
+++ b/test/java/lang/String/ContentEquals.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2004 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4242309 4982981
+ * @summary Test equals and contentEquals in String
+ */
+import java.util.Random;
+import java.nio.CharBuffer;
+
+// Yes, I used cut and paste for this test. Yes more code
+// sharing could have been accomplished.
+public class ContentEquals {
+
+    private static Random rnd = new Random();
+    private static final int ITERATIONS = 1000;
+    private static final int STR_LEN = 20;
+
+    public static void main(String[] args) throws Exception {
+        testStringBuffer();
+        testStringBuilder();
+        testString();
+        testCharSequence();
+    }
+
+    // Test a StringBuffer, which uses the old method from 1.4
+    public static void testStringBuffer() throws Exception {
+        for (int i=0; i<ITERATIONS; i++) {
+            int length = rnd.nextInt(STR_LEN) + 1;
+            StringBuffer testStringBuffer = new StringBuffer();
+            for(int x=0; x<length; x++) {
+                char aChar = (char)rnd.nextInt();
+                testStringBuffer.append(aChar);
+            }
+            String testString = testStringBuffer.toString();
+            char c = testStringBuffer.charAt(0);
+            testStringBuffer.setCharAt(0, 'c');
+            testStringBuffer.setCharAt(0, c);
+            if (!testString.contentEquals(testStringBuffer))
+                throw new RuntimeException("ContentsEqual failure");
+        }
+    }
+
+    // Test StringBuilder as a CharSequence using new method in 1.5
+    public static void testStringBuilder() throws Exception {
+        for (int i=0; i<ITERATIONS; i++) {
+            int length = rnd.nextInt(STR_LEN) + 1;
+            StringBuilder testStringBuilder = new StringBuilder();
+            for(int x=0; x<length; x++) {
+                char aChar = (char)rnd.nextInt();
+                testStringBuilder.append(aChar);
+            }
+            String testString = testStringBuilder.toString();
+            char c = testStringBuilder.charAt(0);
+            testStringBuilder.setCharAt(0, 'c');
+            testStringBuilder.setCharAt(0, c);
+            if (!testString.contentEquals(testStringBuilder))
+                throw new RuntimeException("ContentsEqual failure");
+        }
+    }
+
+    // Test a String as a CharSequence. This takes a different codepath in
+    // the new method in 1.5
+    public static void testString() throws Exception {
+        for (int i=0; i<ITERATIONS; i++) {
+            int length = rnd.nextInt(STR_LEN) + 1;
+            StringBuilder testStringBuilder = new StringBuilder();
+            for(int x=0; x<length; x++) {
+                char aChar = (char)rnd.nextInt();
+                testStringBuilder.append(aChar);
+            }
+            String testString = testStringBuilder.toString();
+            char c = testStringBuilder.charAt(0);
+            testStringBuilder.setCharAt(0, 'c');
+            testStringBuilder.setCharAt(0, c);
+            if (!testString.contentEquals(testStringBuilder.toString()))
+                throw new RuntimeException("ContentsEqual failure");
+        }
+    }
+
+    // Test a CharSequence that is not an AbstractStringBuilder,
+    // this takes a different codepath in the new method in 1.5
+    public static void testCharSequence() throws Exception {
+        for (int i=0; i<ITERATIONS; i++) {
+            int length = rnd.nextInt(STR_LEN) + 1;
+            StringBuilder testStringBuilder = new StringBuilder();
+            for(int x=0; x<length; x++) {
+                char aChar = (char)rnd.nextInt();
+                testStringBuilder.append(aChar);
+            }
+            String testString = testStringBuilder.toString();
+            char c = testStringBuilder.charAt(0);
+            testStringBuilder.setCharAt(0, 'c');
+            testStringBuilder.setCharAt(0, c);
+            CharBuffer buf = CharBuffer.wrap(testStringBuilder.toString());
+            if (!testString.contentEquals(buf))
+                throw new RuntimeException("ContentsEqual failure");
+        }
+    }
+}
diff --git a/test/java/lang/String/Encodings.java b/test/java/lang/String/Encodings.java
new file mode 100644
index 0000000..11949a4
--- /dev/null
+++ b/test/java/lang/String/Encodings.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 1999-2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 4085160 4139951 5005831
+ * @summary Test that required character encodings are supported
+ */
+
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+
+public class Encodings {
+
+
+    static boolean equals(byte[] a, byte[] b) {
+        if (a.length != b.length) return false;
+        for (int i = 0; i < a.length; i++)
+            if (a[i] != b[i]) return false;
+        return true;
+    }
+
+
+    static void go(String enc, String str, final byte[] bytes, boolean bidir)
+        throws Exception
+    {
+        final Charset charset = Charset.forName(enc);
+
+        /* String(byte[] bs, String enc) */
+        if (!(new String(bytes, enc).equals(str)))
+            throw new Exception(enc + ": String constructor failed");
+
+        /* String(byte[] bs, Charset charset) */
+        if (!(new String(bytes, charset).equals(str)))
+            throw new Exception(charset + ": String constructor failed");
+
+        /* String(byte[] bs, int off, int len, Charset charset) */
+        String start = str.substring(0, 2);
+        String end = str.substring(2);
+        if (enc.equals("UTF-16BE") || enc.equals("UTF-16LE")) {
+            if (!(new String(bytes, 0, 4, charset).equals(start)))
+                throw new Exception(charset + ": String constructor failed");
+            if (!(new String(bytes, 4, bytes.length - 4, charset).equals(end)))
+                throw new Exception(charset + ": String constructor failed");
+        } else if (enc.equals("UTF-16")) {
+            if (!(new String(bytes, 0, 6, charset).equals(start)))
+                throw new Exception(charset + ": String constructor failed");
+        } else {
+            if (!(new String(bytes, 0, 2, charset).equals(start)))
+                throw new Exception(charset + ": String constructor failed");
+            if (!(new String(bytes, 2, bytes.length - 2, charset).equals(end)))
+                throw new Exception(charset + ": String constructor failed");
+        }
+
+        /* InputStreamReader */
+        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
+        InputStreamReader r = new InputStreamReader(bi, enc);
+        String inEnc = r.getEncoding();
+        int n = str.length();
+        char[] cs = new char[n];
+        for (int i = 0; i < n;) {
+            int m;
+            if ((m = r.read(cs, i, n - i)) < 0)
+                throw new Exception(enc + ": EOF on InputStreamReader");
+            i += m;
+        }
+        if (!(new String(cs).equals(str)))
+            throw new Exception(enc + ": InputStreamReader failed");
+
+        if (!bidir) {
+            System.err.println(enc + " --> " + inEnc);
+            return;
+        }
+
+        /* String.getBytes(String enc) */
+        byte[] bs = str.getBytes(enc);
+        if (!equals(bs, bytes))
+            throw new Exception(enc + ": String.getBytes failed");
+
+        /* String.getBytes(Charset charset) */
+        bs = str.getBytes(charset);
+        if (!equals(bs, bytes))
+            throw new Exception(charset + ": String.getBytes failed");
+
+        // Calls to String.getBytes(Charset) shouldn't automatically
+        // use the cached thread-local encoder.
+        if (charset.name().equals("UTF-16BE")) {
+            String s = new String(bytes, charset);
+            // Replace the thread-local encoder with this one.
+            byte[] bb = s.getBytes(Charset.forName("UTF-16LE"));
+            if (bytes.length != bb.length) {
+                // Incidental test.
+                throw new RuntimeException("unequal length: "
+                                           + bytes.length + " != "
+                                           + bb.length);
+            } else {
+                boolean diff = false;
+                // Expect different byte[] between UTF-16LE and UTF-16BE
+                // even though encoder was previously cached by last call
+                // to getBytes().
+                for (int i = 0; i < bytes.length; i++) {
+                    if (bytes[i] != bb[i])
+                        diff = true;
+                }
+                if (!diff)
+                    throw new RuntimeException("byte arrays equal");
+            }
+        }
+
+        /* OutputStreamWriter */
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        OutputStreamWriter w = new OutputStreamWriter(bo, enc);
+        String outEnc = w.getEncoding();
+        w.write(str);
+        w.close();
+        bs = bo.toByteArray();
+        if (!equals(bs, bytes))
+            throw new Exception(enc + ": OutputStreamWriter failed");
+
+        System.err.println(enc + " --> " + inEnc + " / " + outEnc);
+    }
+
+
+    static void go(String enc, String str, byte[] bytes) throws Exception {
+        go(enc, str, bytes, true);
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        go("US-ASCII", "abc", new byte[] { 'a', 'b', 'c' });
+        go("us-ascii", "abc", new byte[] { 'a', 'b', 'c' });
+        go("ISO646-US", "abc", new byte[] { 'a', 'b', 'c' });
+        go("ISO-8859-1", "ab\u00c7", new byte[] { 'a', 'b', (byte)'\u00c7' });
+        go("UTF-8", "ab\u1e09",
+           new byte[] { 'a', 'b',
+                        (byte)(0xe0 | (0x0f & (0x1e09 >> 12))),
+                        (byte)(0x80 | (0x3f & (0x1e09 >> 6))),
+                        (byte)(0x80 | (0x3f & 0x1e09)) });
+        go("UTF-16BE", "ab\u1e09",
+           new byte[] { 0, 'a', 0, 'b', 0x1e, 0x09 });
+        go("UTF-16LE", "ab\u1e09",
+           new byte[] { 'a', 0, 'b', 0, 0x09, 0x1e });
+
+        /* UTF-16 accepts both byte orders on input but always uses big-endian
+         * on output, so test all three cases
+         */
+        go("UTF-16", "ab\u1e09",
+           new byte[] { (byte)0xfe, (byte)0xff, 0, 'a', 0, 'b', 0x1e, 0x09 });
+        go("UTF-16", "ab\u1e09",
+           new byte[] { (byte)0xff, (byte)0xfe, 'a', 0, 'b', 0, 0x09, 0x1e },
+           false);
+    }
+
+}
diff --git a/test/java/lang/String/Exceptions.java b/test/java/lang/String/Exceptions.java
new file mode 100644
index 0000000..9e7fde9
--- /dev/null
+++ b/test/java/lang/String/Exceptions.java
@@ -0,0 +1,669 @@
+/*
+ * Copyright 2002-2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4472841 4703640 4705681 4705683 4833095 5005831
+ * @summary Verify that constructor exceptions are thrown as expected.
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+
+public class Exceptions {
+    private static final byte [] b = { 0x48, 0x69, 0x2c, 0x20,
+                                       0x44, 0x75, 0x6b, 0x65, 0x21 };
+
+    private static final char [] c
+        = "Attack of the Killer Tomatoes!".toCharArray();
+
+    private static boolean ok = true;
+
+    private static void fail(Class ex, String s) {
+        ok = false;
+        System.err.println("expected " + ex.getName() + " for " + s
+                               + " - FAILED");
+    }
+
+    private static void pass(String s) {
+        System.out.println(s + " -- OK");
+    }
+
+    private static void tryCatch(String s, Class ex, Runnable thunk) {
+        Throwable t = null;
+        try {
+            thunk.run();
+        } catch (Throwable x) {
+            if (ex.isAssignableFrom(x.getClass()))
+                t = x;
+            else
+                x.printStackTrace();
+        }
+        if ((t == null) && (ex != null))
+            fail(ex, s);
+        else
+            pass(s);
+    }
+
+    // -- Constructors --
+
+    private static void noArgs() {
+        System.out.println("String()");
+        tryCatch("  default ctor", null, new Runnable() {
+                public void run() {
+                    new String();
+                }});
+    }
+
+    private static void string() {
+        System.out.println("String(String original)");
+        tryCatch("  \"foo\"", null, new Runnable() {
+                public void run() {
+                    new String("foo");
+                }});
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((String) null);
+                }});
+    }
+
+    private static void charArray() {
+        System.out.println("String(char value[])");
+        tryCatch("  char [] = \"Duke says \"Hi!\"\"", null, new Runnable() {
+                public void run() {
+                    new String("Duke says \"Hi!\"".toCharArray());
+                }});
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((char []) null);
+                }});
+    }
+
+    private static void charArrayOffCount() {
+        System.out.println("String(char value[], int offset, int count)");
+        tryCatch("  c, 0, 3", null, new Runnable() {
+                public void run() {
+                    new String(c, 0, 3);
+                }});
+        tryCatch("  null, 1, 2", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((char []) null, 1, 2);
+                }});
+        tryCatch("  c, -1, 4", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(c, -1, 4);
+                         }});
+        tryCatch("  c, 1, -1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(c, 1, -1);
+                         }});
+        tryCatch("  c, c.lengh + 1, 1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(c, c.length + 1, 1);
+                         }});
+        tryCatch("  c, 0, c.length + 1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(c, 0, c.length + 1);
+                         }});
+    }
+
+    private static void byteArrayHiOffCount() {
+        System.out.println("String(byte ascii[], int hibyte, int offset, "
+                           + "int count)");
+        tryCatch("  b, 0, 0, b.length", null, new Runnable() {
+                public void run() {
+                    System.out.println(new String(b, 0, 0, b.length));
+                }});
+
+        tryCatch("  b, -1, 4, 4", null, new Runnable() {
+                public void run() {
+                    new String(b, -1, 4, 4);
+                }});
+        tryCatch("  null, 0, 0, 0", NullPointerException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String((byte[]) null, 0, 0, 0);
+                         }});
+        tryCatch("  b, 0, -1, r", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, 0, -1, 4);
+                         }});
+        tryCatch("  b, 0, 4, -1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, 0, 4, -1);
+                         }});
+        tryCatch("  b, 0, b.length + 1, 1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, 0, b.length + 1, 1);
+                         }});
+        tryCatch("  b, 0, 0, b.length + 1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, 0, 0, b.length + 1);
+                         }});
+    }
+
+    private static void byteArrayHi() {
+        System.out.println("String(byte ascii[], int hibyte)");
+        tryCatch("  b, 0", null, new Runnable() {
+                public void run() {
+                    new String(b, 0);
+                }});
+        tryCatch("  null, 0", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((byte []) null, 0);
+                }});
+    }
+
+    private static void byteArrayOffLengthCharset0(String s, Class ex,
+                                                   byte [] b, int off,
+                                                   int len, Object cs)
+    {
+        Throwable t = null;
+        try {
+            if (cs instanceof String)
+                new String(b, off, len, (String)cs);
+            else // (cs instanceof Charset)
+                new String(b, off, len, (Charset)cs);
+        } catch (Throwable x) {
+            if (ex.isAssignableFrom(x.getClass()))
+                t = x;
+            else
+                x.printStackTrace();
+        }
+        if ((t == null) && (ex != null))
+            fail(ex, s);
+        else
+            pass(s);
+    }
+
+    private static void byteArrayOffLengthCharsetName() {
+        System.out.println("String(byte bytes[], int offset, int length, "
+                           + "String charsetName)");
+        System.out.println("  throws UnsupportedEncodingException");
+        String enc = "UTF-8";
+        byteArrayOffLengthCharset0("  b, 0, 0," + enc, null, b, 0, 0, enc);
+        byteArrayOffLengthCharset0("  null, 0, 0," + enc,
+                                   NullPointerException.class,
+                                   (byte []) null, 0, 0, enc);
+        byteArrayOffLengthCharset0("  b, -1, 0, " + enc,
+                                   IndexOutOfBoundsException.class,
+                                   b, -1, 0, enc);
+        byteArrayOffLengthCharset0("  b, 0, -1, " + enc,
+                                   IndexOutOfBoundsException.class,
+                                   b, 0, -1, enc);
+        byteArrayOffLengthCharset0("  b, b.length + 1, 1, " + enc,
+                                   IndexOutOfBoundsException.class,
+                                   b, b.length + 1, 1, enc);
+        byteArrayOffLengthCharset0("  b, 0, b.length + 1 " + enc,
+                                   IndexOutOfBoundsException.class,
+                                   b, 0, b.length + 1, enc);
+        byteArrayOffLengthCharset0("  b, -1, 0, null",
+                                   NullPointerException.class,
+                                   b, -1, 0, null);
+        byteArrayOffLengthCharset0("  b, 0, b.length, foo",
+                                   UnsupportedEncodingException.class,
+                                   b, 0, b.length, "foo");
+    }
+
+    private static void byteArrayOffLengthCharset() {
+        System.out.println("String(byte bytes[], int offset, int length, "
+                           + "Charset charset)");
+        Charset cs = Charset.forName("UTF-16BE");
+        byteArrayOffLengthCharset0("  b, 0, 0," + cs, null, b, 0, 0, cs);
+        byteArrayOffLengthCharset0("  null, 0, 0," + cs,
+                                   NullPointerException.class,
+                                   (byte []) null, 0, 0, cs);
+        byteArrayOffLengthCharset0("  b, -1, 0, " + cs,
+                                   IndexOutOfBoundsException.class,
+                                   b, -1, 0, cs);
+        byteArrayOffLengthCharset0("  b, 0, -1, " + cs,
+                                   IndexOutOfBoundsException.class,
+                                   b, 0, -1, cs);
+        byteArrayOffLengthCharset0("  b, b.length + 1, 1, " + cs,
+                                   IndexOutOfBoundsException.class,
+                                   b, b.length + 1, 1, cs);
+        byteArrayOffLengthCharset0("  b, 0, b.length + 1 " + cs,
+                                   IndexOutOfBoundsException.class,
+                                   b, 0, b.length + 1, cs);
+        byteArrayOffLengthCharset0("  b, -1, 0, null",
+                                   NullPointerException.class,
+                                   b, -1, 0, null);
+    }
+
+    private static void byteArrayCharset0(String s, Class ex, byte [] b,
+                                          Object cs)
+    {
+        Throwable t = null;
+        try {
+            if (cs instanceof String)
+                new String(b, (String)cs);
+            else // (cs instanceof Charset)
+                new String(b, (Charset)cs);
+        } catch (Throwable x) {
+            if (ex.isAssignableFrom(x.getClass()))
+                t = x;
+            else
+                x.printStackTrace();
+        }
+        if ((t == null) && (ex != null))
+            fail(ex, s);
+        else
+            pass(s);
+    }
+
+    private static void byteArrayCharsetName() {
+        System.out.println("String(byte bytes[], String charsetName)");
+        System.out.println("  throws UnsupportedEncodingException");
+        String enc = "US-ASCII";
+        byteArrayCharset0("  b, " + enc, null, b, enc);
+        byteArrayCharset0("  null, " + enc, NullPointerException.class,
+                          (byte []) null, enc);
+        byteArrayCharset0("  b, null", NullPointerException.class, b, null);
+        byteArrayCharset0("  null, null", NullPointerException.class,
+                          (byte []) null, null);
+        byteArrayCharset0("  b, bar", UnsupportedEncodingException.class,
+                          b, "bar");
+    }
+
+    private static void byteArrayCharset() {
+        System.out.println("String(byte bytes[], Charset charset)");
+        Charset cs = Charset.forName("ISO-8859-1");
+        byteArrayCharset0("  b, " + cs, null, b, cs);
+        byteArrayCharset0("  null, " + cs, NullPointerException.class,
+                          (byte []) null, cs);
+        byteArrayCharset0("  b, null", NullPointerException.class, b, null);
+        byteArrayCharset0("  null, null", NullPointerException.class,
+                          (byte []) null, null);
+    }
+
+    private static void byteArrayOffLength() {
+        System.out.println("String(byte bytes[], int offset, int length)");
+        tryCatch("  b, 0, b.length", null, new Runnable() {
+                public void run() {
+                    new String(b, 0, b.length);
+                }});
+        tryCatch("  null, 0, 0", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((byte []) null, 0, 0);
+                }});
+        tryCatch("  b, -1, b.length", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, -1, b.length);
+                         }});
+        tryCatch("  b, 0, -1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, 0, -1);
+                         }});
+        tryCatch("  b, b.length + 1, 1", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, b.length + 1, 1);
+                         }});
+        tryCatch("  b, 0, b.length", IndexOutOfBoundsException.class,
+                 new Runnable() {
+                         public void run() {
+                             new String(b, 0, b.length + 1);
+                         }});
+    }
+
+    private static void byteArray() {
+        System.out.println("String(byte bytes[])");
+        tryCatch("  b", null, new Runnable() {
+                public void run() {
+                    new String(b);
+                }});
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((byte []) null);
+                }});
+    }
+
+    private static void stringBuffer() {
+        System.out.println("String(StringBuffer buffer)");
+        tryCatch("  \"bar\"", null, new Runnable() {
+                public void run() {
+                    new String(new StringBuffer("bar"));
+                }});
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    new String((StringBuffer) null);
+                }});
+    }
+
+    // -- Methods --
+
+        private static void getChars() {
+        System.out.println("getChars.(int srcBegin, int srcEnd, char dst[], "
+                           + " int dstBegin");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".getChars(1, 2, null, 1);
+                }});
+    }
+
+    private static void getBytes() {
+        System.out.println("getChars.(int srcBegin, int srcEnd, char dst[], "
+                           + " int dstBegin");
+        tryCatch("  1, 2, null, 1", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".getBytes(1, 2, null, 1);
+                }});
+
+        System.out.println("getBytes.(String charsetName)"
+                           + " throws UnsupportedEncodingException");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    try {
+                        "foo".getBytes((String)null);
+                    } catch (UnsupportedEncodingException x) {
+                        throw new RuntimeException(x);
+                    }
+                }});
+
+        System.out.println("getBytes.(Charset charset)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".getBytes((Charset)null);
+                }});
+    }
+
+    private static void contentEquals() {
+        System.out.println("contentEquals(StringBuffer sb)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".contentEquals(null);
+                }});
+    }
+
+    private static void compareTo() {
+        System.out.println("compareTo(String anotherString)");
+        tryCatch("  (String) null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".compareTo((String) null);
+                }});
+
+        /* 4830291 (javac generics bug) causes this test to fail
+        System.out.println("compareTo(Object o)");
+        tryCatch("  (Object) null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".compareTo((Object) null);
+                }});
+        */
+    }
+
+    private static void compareToIgnoreCase() {
+        System.out.println("compareToIgnoreCase(String anotherString)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".compareToIgnoreCase((String) null);
+                }});
+    }
+
+    private static void regionMatches() {
+        System.out.println("regionMatches(int toffset, String other,"
+                           + " int ooffset, int len)");
+        tryCatch("  1, null, 1, 1", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".regionMatches(1, null, 1, 1);
+                }});
+
+        System.out.println("regionMatches(boolean ignore, int toffset,"
+                           + " String other, int ooffset, int len)");
+        tryCatch("  true, 1, null, 1, 1", NullPointerException.class,
+                 new Runnable() {
+                         public void run() {
+                             "foo".regionMatches(true, 1, null, 1, 1);
+                         }});
+    }
+
+    private static void startsWith() {
+        System.out.println("startsWith(String prefix, int toffset)");
+        tryCatch("  null, 1", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".startsWith(null, 1);
+                }});
+
+        System.out.println("startsWith(String prefix)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".startsWith(null);
+                }});
+    }
+
+    private static void endsWith() {
+        System.out.println("endsWith(String suffix)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".endsWith(null);
+                }});
+    }
+
+    private static void indexOf() {
+        System.out.println("indexOf(String str)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".indexOf(null);
+                }});
+
+        System.out.println("indexOf(String str, int fromIndex)");
+        tryCatch("  null, 1", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".indexOf(null, 1);
+                }});
+    }
+
+    private static void lastIndexOf() {
+        System.out.println("lastIndexOf(String str)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".lastIndexOf(null);
+                }});
+
+        System.out.println("lastIndexOf(String str, int fromIndex)");
+        tryCatch("  null, 1", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".lastIndexOf(null, 1);
+                }});
+    }
+
+    private static void concat() {
+        System.out.println("concat(String str)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".concat(null);
+                }});
+    }
+
+    private static void matches() {
+        System.out.println("matches(String regex)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".matches(null);
+                }});
+    }
+
+    private static void replaceFirst() {
+        System.out.println("replaceFirst(String regex, String replacement)");
+        tryCatch("  \".\", null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".replaceFirst(".", null);
+                }});
+        tryCatch("  null, \"-\"", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".replaceFirst(null, "-");
+                }});
+    }
+
+    private static void replaceAll() {
+        System.out.println("replaceAll(String regex, String replacement)");
+        tryCatch("  \".\", null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".replaceAll(".", null);
+                }});
+        tryCatch("  null, \"-\"", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".replaceAll(null, "-");
+                }});
+    }
+
+    private static void split() {
+        System.out.println("split(String regex, int limit)");
+        tryCatch("  null, 1", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".split(null, 1);
+                }});
+
+        System.out.println("split(String regex, int limit)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".split(null);
+                }});
+    }
+
+    private static void toLowerCase() {
+        System.out.println("toLowerCase(Locale locale)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".toLowerCase(null);
+                }});
+    }
+
+    private static void toUpperCase() {
+        System.out.println("toUpperCase(Locale locale)");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".toUpperCase(null);
+                }});
+    }
+
+    private static void valueOf() {
+        System.out.println("valueOf(Object obj)");
+        tryCatch("  null", null, new Runnable() {
+                public void run() {
+                    String.valueOf((Object) null);
+                }});
+
+        System.out.println("valueOf(char data[])");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    String.valueOf((char []) null);
+                }});
+
+        System.out.println("valueOf(char data[], int offset, int count)");
+        tryCatch("  null, 1, 2", NullPointerException.class, new Runnable() {
+                public void run() {
+                    String.valueOf((char []) null, 1, 2);
+                }});
+
+    }
+
+    private static void copyValueOf() {
+        System.out.println("copyValueOf(char data[], int offset, int count)");
+        tryCatch("  null, 1, 2", NullPointerException.class, new Runnable() {
+                public void run() {
+                    "foo".copyValueOf((char []) null, 1, 2);
+                }});
+
+        System.out.println("copyVlueOf(char data[])");
+        tryCatch("  null", NullPointerException.class, new Runnable() {
+                public void run() {
+                    String.copyValueOf((char []) null);
+                }});
+    }
+
+    public static void main(String [] args) {
+
+        // -- Constructors --
+
+        noArgs();             // String()
+        string();             // String(String original)
+        charArray();          // String(char value[])
+        charArrayOffCount();  // String(char value[], int offset, int count)
+
+        // String(byte ascii[], int hibyte, int offset, int count)
+        byteArrayHiOffCount();
+
+        byteArrayHi();        // String(byte ascii[], int hibyte)
+
+        // String(byte bytes[], int offset, int length, String charsetName)
+        //   throws UnsupportedEncodingException
+        byteArrayOffLengthCharsetName();
+
+        // String(byte bytes[], int offset, int length, Charset charset)
+        byteArrayOffLengthCharset();
+
+        // String(byte bytes[], String charsetName)
+        //   throws UnsupportedEncodingException
+        byteArrayCharsetName();
+
+        // String(byte bytes[], Charset charset)
+        byteArrayCharset();
+
+        byteArrayOffLength(); // String(byte bytes[], int offset, int length)
+        byteArray();          // String(byte bytes[])
+        stringBuffer();       // String(StringBuffer buffer)
+
+        // -- Methods --
+
+        getChars();           // getChars(int, int. char [], int)
+        getBytes();           // getBytes(int, int, byte [], int),
+                              //   getBytes(Locale)
+                              //   getBytes(String)
+                              //   getBytes(Charset)
+        contentEquals();      // contentEquals(StringBuffer)
+        compareTo();          // compareTo(String), compareTo(Object)
+        compareToIgnoreCase();// compareToIgnoreCase(String)
+        regionMatches();      // regionMatches(int, String, int, int)
+                              //   regionMatches(boolean, int, String, int, int)
+        startsWith();         // startsWith(String, int), startsWith(String)
+        endsWith();           // endsWith(String)
+        indexOf();            // indexOf(String), indexOf(String, int),
+        lastIndexOf();        // lastIndexOf(String), lastIndexOf(String, int)
+        concat();             // concat(String)
+        matches();            // matches(String)
+        replaceFirst();       // replaceFirst(String, String)
+        replaceAll();         // replaceAll(String, String)
+        split();              // split(String, int), split(String)
+        toLowerCase();        // toLowerCase(Locale)
+        toUpperCase();        // toUpperCase(Locale)
+        valueOf();            // valueOf(Object), valueOf(char []),
+                              //   valueOf(char [], int, int)
+        copyValueOf();        // copyValueOf(char [], int, int),
+                              //    copyValueOf(char [])
+
+        if (!ok)
+            throw new RuntimeException("Some tests FAILED");
+        else
+            System.out.println("All tests PASSED");
+    }
+}
diff --git a/test/java/lang/String/ICCBasher.java b/test/java/lang/String/ICCBasher.java
new file mode 100644
index 0000000..e564d96
--- /dev/null
+++ b/test/java/lang/String/ICCBasher.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1998-2002 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4152868
+ * @summary test Case Insensitive Comparator in String
+ */
+
+import java.util.*;
+
+public class ICCBasher {
+
+    static final int TEST_SIZE = 20;
+    static final int STRING_SIZE = 5;
+    static final int CHAR_VALUE_LIMIT = 128;
+
+    public static void main(String[] args) throws Exception {
+        LinkedList L1 = new LinkedList();
+        LinkedList L2 = new LinkedList();
+        LinkedList L3 = new LinkedList();
+        LinkedList L4 = new LinkedList();
+
+        // First generate L1 and L2 with random lower case chars
+        //System.out.println("Generate L1 and L2");
+        Random generator = new Random();
+        int achar=0;
+        StringBuffer entryBuffer = new StringBuffer(10);
+        String snippet = null;
+        for (int x=0; x<TEST_SIZE * 2; x++) {
+            for(int y=0; y<STRING_SIZE; y++) {
+                achar = generator.nextInt(CHAR_VALUE_LIMIT);
+                char test = (char)(achar);
+                entryBuffer.append(test);
+            }
+            snippet = entryBuffer.toString();
+            snippet.toLowerCase();
+            if (x < TEST_SIZE)
+                L1.add(snippet);
+            else
+                L2.add(snippet);
+        }
+
+        // Concatenate L1 and L2 to form L3
+        //System.out.println("Generate L3");
+        for (int x=0; x<TEST_SIZE; x++) {
+            String entry = (String)L1.get(x) + (String)L2.get(x);
+            L3.add(entry);
+        }
+
+        // Randomly toUpper L1 and L2
+        //System.out.println("Modify L1 and L2");
+        for (int x=0; x<TEST_SIZE; x++) {
+            achar = generator.nextInt();
+            if (achar > 0) {
+                String mod = (String)L1.get(x);
+                mod = mod.toUpperCase();
+                L1.set(x, mod);
+            }
+            achar = generator.nextInt();
+            if (achar > 0) {
+                String mod = (String)L2.get(x);
+                mod = mod.toUpperCase();
+                L2.set(x, mod);
+            }
+        }
+
+        // Concatenate L1 and L2 to form L4
+        //System.out.println("Generate L4");
+        for (int x=0; x<TEST_SIZE; x++) {
+            String entry = (String)L1.get(x) + (String)L2.get(x);
+            L4.add(entry);
+        }
+
+        // Sort L3 and L4 using case insensitive comparator
+        //System.out.println("Sort L3 and L4");
+        Collections.sort(L3, String.CASE_INSENSITIVE_ORDER);
+        Collections.sort(L4, String.CASE_INSENSITIVE_ORDER);
+
+        // Check to see that order of L3 and L4 are identical
+        // ignoring case considerations
+        //System.out.println("Check order of L3 and L4");
+        for (int x=0; x<TEST_SIZE; x++) {
+            String one = (String)L3.get(x);
+            String two = (String)L4.get(x);
+            if (!one.equalsIgnoreCase(two))
+                throw new RuntimeException("Case Insensitive Sort Failure.");
+        }
+
+    }
+}
diff --git a/test/java/lang/String/IndexOfEmptyInEmpty.java b/test/java/lang/String/IndexOfEmptyInEmpty.java
new file mode 100644
index 0000000..1ba52ba
--- /dev/null
+++ b/test/java/lang/String/IndexOfEmptyInEmpty.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1998 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @bug 4096273
+   @summary new String("").indexOf("") must give 0, not -1
+   @author Anand Palaniswamy
+ */
+public class IndexOfEmptyInEmpty {
+    public static void main(String[] args) throws Exception {
+        int result = new String("").indexOf("");
+        if (result != 0) {
+            throw new Exception("new String(\"\").indexOf(\"\") must be 0, but got " + result);
+        }
+    }
+}
diff --git a/test/java/lang/String/IsEmpty.java b/test/java/lang/String/IsEmpty.java
new file mode 100644
index 0000000..1d31287
--- /dev/null
+++ b/test/java/lang/String/IsEmpty.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @summary Basic isEmpty functionality
+ * @bug 6189137
+ */
+
+public class IsEmpty {
+    private static String [] tests = { "", " ", "a",
+                                       "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.  -- Charles Dickens, Tale of Two Cities"
+    };
+
+    public static void main(String [] args) {
+        for (int i = 0; i < tests.length; i++) {
+            String s = tests[i];
+            int len = s.length();
+            boolean empty = s.isEmpty();
+
+            if ((len != 0 && empty) || (len == 0 && !empty))
+                throw new RuntimeException("String \"" + s + "\": "
+                                           + " isEmpty = " + empty
+                                           + ", length = " + len);
+        }
+    }
+}
diff --git a/test/java/lang/String/NonCharacterMapping.java b/test/java/lang/String/NonCharacterMapping.java
new file mode 100644
index 0000000..e0bd8ad
--- /dev/null
+++ b/test/java/lang/String/NonCharacterMapping.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *  @test
+ *  @bug 5101626
+ *  @summary Case conversion should not trip over non-character code points.
+ */
+
+import java.util.Locale;
+
+public class NonCharacterMapping {
+
+    private static final Locale ENGLISH = new Locale("en");
+    private static final Locale TURKISH = new Locale("tr");
+
+    public static void main(String[] args) {
+        if (Character.toLowerCase('\uFFFF') != '\uFFFF') {
+            throw new RuntimeException();
+        }
+        if (Character.toUpperCase('\uFFFF') != '\uFFFF') {
+            throw new RuntimeException();
+        }
+        if (Character.toTitleCase('\uFFFF') != '\uFFFF') {
+            throw new RuntimeException();
+        }
+        if (!"\uFFFF".toLowerCase(ENGLISH).equals("\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"\uFFFF".toUpperCase(ENGLISH).equals("\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"\uFFFF".toLowerCase(TURKISH).equals("\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"\uFFFF".toUpperCase(TURKISH).equals("\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"A\uFFFF".toLowerCase(ENGLISH).equals("a\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"A\uFFFF".toUpperCase(ENGLISH).equals("A\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"A\uFFFF".toLowerCase(TURKISH).equals("a\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"A\uFFFF".toUpperCase(TURKISH).equals("A\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"a\uFFFF".toLowerCase(ENGLISH).equals("a\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"a\uFFFF".toUpperCase(ENGLISH).equals("A\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"a\uFFFF".toLowerCase(TURKISH).equals("a\uFFFF")) {
+            throw new RuntimeException();
+        }
+        if (!"a\uFFFF".toUpperCase(TURKISH).equals("A\uFFFF")) {
+            throw new RuntimeException();
+        }
+    }
+}
diff --git a/test/java/lang/String/Regex.java b/test/java/lang/String/Regex.java
new file mode 100644
index 0000000..88a4a63
--- /dev/null
+++ b/test/java/lang/String/Regex.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2001-2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 4808962
+ * @summary Unit tests for String regex methods
+ */
+
+
+public class Regex {
+
+    static void ck(boolean x, boolean ans) throws Exception {
+        if (x != ans)
+            throw new Exception("Test failed");
+    }
+
+    static void ck(String x, String ans) throws Exception {
+        if (!x.equals(ans))
+            throw new Exception("Test failed");
+    }
+
+    static void ck(String[] x, String[] ans) throws Exception {
+        if (x.length != ans.length)
+            throw new Exception("Test failed");
+        for (int i = 0; i < x.length; i++) {
+            if (!x[i].equals(ans[i]))
+                throw new Exception("Test failed");
+        }
+    }
+
+    static void testLiteralReplacement() throws Exception {
+        // Test straightforward replacement
+        String data = "abcdefghi";
+        String result = data.replace("def", "abc");
+        if (!result.equals("abcabcghi"))
+            throw new Exception("Test failed");
+
+        // Test replacement with target that has metacharacters
+        data = "abc(def)?ghi";
+        result = data.replace("(def)?", "abc");
+        if (!result.equals("abcabcghi"))
+            throw new Exception("Test failed");
+
+        // Test replacement with replacement that has metacharacters
+        data = "abcdefghi";
+        result = data.replace("def", "\\ab$c");
+        if (!result.equals("abc\\ab$cghi"))
+            throw new Exception("Test failed");
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        // These don't need to be thorough, they just need to check
+        // that we're properly hooked up to java.util.regex
+
+        String foo = "boo:and:foo";
+
+        ck(foo.matches("b+"), false);
+        ck(foo.matches("o+"), false);
+        ck(foo.matches("b..:and:f.*"), true);
+
+        ck(foo.replaceAll("oo", "uu"), "buu:and:fuu");
+        ck(foo.replaceAll("o+", "<$0>"), "b<oo>:and:f<oo>");
+
+        ck(foo.replaceFirst("oo", "uu"), "buu:and:foo");
+        ck(foo.replaceFirst("o+", "<$0>"), "b<oo>:and:foo");
+
+        ck(foo.split(":"), new String[] { "boo", "and", "foo" });
+        ck(foo.split("o"), new String[] { "b", "", ":and:f" });
+
+        ck(foo.split(":", 2), new String[] { "boo", "and:foo" });
+        ck(foo.split("o", -2), new String[] { "b", "", ":and:f", "", "" });
+
+        testLiteralReplacement();
+    }
+
+
+}
diff --git a/test/java/lang/String/RegionMatches.java b/test/java/lang/String/RegionMatches.java
new file mode 100644
index 0000000..3cc924e
--- /dev/null
+++ b/test/java/lang/String/RegionMatches.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1998 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4016509
+ * @summary test regionMatches corner case
+ */
+
+
+public class RegionMatches {
+
+  public static void main (String args[]) throws Exception {
+      String s1="abc";
+      String s2="def";
+
+      if (!s1.regionMatches(0,s2,0,Integer.MIN_VALUE))
+          throw new RuntimeException("Integer overflow in RegionMatches");
+  }
+}
diff --git a/test/java/lang/String/SBConstructor.java b/test/java/lang/String/SBConstructor.java
new file mode 100644
index 0000000..4003093
--- /dev/null
+++ b/test/java/lang/String/SBConstructor.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4915187
+ * @summary Test java.lang.String constructor that takes StringBuilder
+ *
+ */
+import java.util.*;
+
+public class SBConstructor {
+    private static Random rnd = new Random();
+    public static void main (String[] argvs) throws Exception {
+        for (int i=0; i<1000; i++) {
+            int length = rnd.nextInt(20) + 1;
+            StringBuffer testStringBuffer = new StringBuffer();
+            StringBuilder testStringBuilder = new StringBuilder();
+            for(int x=0; x<length; x++) {
+                char aChar = (char)rnd.nextInt();
+                testStringBuffer.append(aChar);
+                testStringBuilder.append(aChar);
+            }
+            String testString1 = new String(testStringBuffer);
+            String testString2 = new String(testStringBuilder);
+            if (!testString1.equals(testString2))
+                throw new RuntimeException("Test failure");
+        }
+    }
+}
diff --git a/test/java/lang/String/Split.java b/test/java/lang/String/Split.java
new file mode 100644
index 0000000..b4ab5fb
--- /dev/null
+++ b/test/java/lang/String/Split.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2001 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @summary test String.split()
+ */
+import java.util.regex.*;
+
+public class Split {
+
+    public static void main(String[] args) throws Exception {
+        String source = "0123456789";
+        for (int limit=-2; limit<3; limit++) {
+            for (int x=0; x<10; x++) {
+                String[] result = source.split(Integer.toString(x), limit);
+                int expectedLength = limit < 1 ? 2 : limit;
+
+                if ((limit == 0) && (x == 9)) {
+                    // expected dropping of ""
+                    if (result.length != 1)
+                        throw new RuntimeException("String.split failure 1");
+                    if (!result[0].equals("012345678")) {
+                        throw new RuntimeException("String.split failure 2");
+                    }
+                } else {
+                    if (result.length != expectedLength) {
+                        throw new RuntimeException("String.split failure 3");
+                    }
+                    if (!result[0].equals(source.substring(0,x))) {
+                        if (limit != 1) {
+                            throw new RuntimeException(
+                                "String.split failure 4");
+                        } else {
+                            if (!result[0].equals(source.substring(0,10))) {
+                            throw new RuntimeException(
+                                "String.split failure 10");
+                            }
+                        }
+                    }
+                    if (expectedLength > 1) { // Check segment 2
+                       if (!result[1].equals(source.substring(x+1,10)))
+                          throw new RuntimeException("String.split failure 5");
+                    }
+                }
+            }
+        }
+        // Check the case for no match found
+        for (int limit=-2; limit<3; limit++) {
+            String[] result = source.split("e", limit);
+            if (result.length != 1)
+                throw new RuntimeException("String.split failure 6");
+            if (!result[0].equals(source))
+                throw new RuntimeException("String.split failure 7");
+        }
+        // Check the case for limit == 0, source = "";
+        source = "";
+        String[] result = source.split("e", 0);
+        if (result.length != 1)
+            throw new RuntimeException("String.split failure 8");
+        if (!result[0].equals(source))
+            throw new RuntimeException("String.split failure 9");
+    }
+}
diff --git a/test/java/lang/String/Supplementary.java b/test/java/lang/String/Supplementary.java
new file mode 100644
index 0000000..f7bc3c5
--- /dev/null
+++ b/test/java/lang/String/Supplementary.java
@@ -0,0 +1,643 @@
+/*
+ * Copyright 2003-2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *
+ * @test
+ * @bug 4533872 4915683 4922962 4985217 5017280 6242664 6588260
+ * @summary Unit tests for supplementary character support (JSR-204)
+ */
+
+public class Supplementary {
+
+    public static void main(String[] args) {
+        test1();        // Test for codePointAt(int index)
+        test2();        // Test for codePointBefore(int index)
+        test3();        // Test for indexOf(int ch)
+        test4();        // Test for indexOf(int ch, int fromIndex)
+        test5();        // Test for lastIndexOf(int ch)
+        test6();        // Test for lastIndexOf(int ch, int fromIndex)
+        test7();        // Test for String(int[] codePoint, int offset, int count)
+        test8();        // Test for codePointCount(int beginIndex, int endIndex)
+        test9();        // Test for offsetByCodePoints(int index, int offset)
+        test10();       // Test for offsetByCodePoints(int index, int offset)
+                        // To verify the fix for 6242664
+    }
+
+    /* Text strings which are used as input data.
+     * The comment above each text string means the index of each 16-bit char
+     * for convenience.
+     */
+    static final String[] input = {
+      /*                               111     1     111111     22222
+         0123     4     5678     9     012     3     456789     01234 */
+        "abc\uD800\uDC00def\uD800\uD800ab\uD800\uDC00cdefa\uDC00bcdef",
+      /*                          1     1111     1111     1     222
+         0     12345     6789     0     1234     5678     9     012     */
+        "\uD800defg\uD800hij\uD800\uDC00klm\uDC00nop\uDC00\uD800rt\uDC00",
+      /*                          11     1     1111     1     112     222
+         0     12345     6     78901     2     3456     7     890     123     */
+        "\uDC00abcd\uDBFF\uDFFFefgh\uD800\uDC009ik\uDC00\uDC00lm\uDC00no\uD800",
+      /*                                    111     111111     1 22     2
+         0     1     2345     678     9     012     345678     9 01     2     */
+        "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
+
+        // includes an undefined supprementary characters in Unicode 4.0.0
+      /*                                    1     11     1     1111     1
+         0     1     2345     6     789     0     12     3     4567     8     */
+        "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
+
+        // all supplementary characters
+      /*                                                             1     1
+         0     1     2     3     4     5     6     7     8     9     0     1     */
+        "\uD800\uDC00\uD800\uDC01\uD800\uDC02\uD800\uDC03\uD800\uDC04\uD800\uDC05"+
+      /* 1     1     1     1     1     1     1     1     2     2     2     2
+         2     3     4     5     6     7     8     9     0     1     2     3     */
+        "\uD800\uDC06\uD800\uDC07\uD800\uDC08\uD800\uDC08\uD800\uDC09\uD800\uDC0A"+
+      /* 2     2     2     2     2     2     3     3     3     3     3     3
+         4     5     6     7     8     9     0     1     2     3     4     5     */
+        "\uD800\uDC0B\uD800\uDC0C\uD800\uDC0D\uD800\uDC0A\uD800\uDC0F\uD800\uDC10"
+    };
+
+
+    /* Expected results for:
+     *     test1(): for codePointAt()
+     *
+     * Each character in each array is the golden data for each text string
+     * in the above input data. For example, the first data in each array is
+     * for the first input string.
+     */
+    static final int[][] golden1 = {
+        {'a',    0xD800,  0xDC00, 0x10000, 0xE0200, 0x10000},// codePointAt(0)
+        {0xD800, 0x10000, 'g',    0xDC00,  0xE0202, 0xDC04}, // codePointAt(9)
+        {'f',    0xDC00,  0xD800, 0xDC00,  0xDE02,  0xDC10}, // codePointAt(length-1)
+        {'f',    'p',     0xDC00, '^',     0xE0202, 0xDC08}, // codePointAt() for a substring
+    };
+
+    /*
+     * Test for codePointAt(int index) method
+     */
+    static void test1() {
+
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+
+            /*
+             * Normal case
+             */
+            testCodePoint(At, s, 0, golden1[0][i]);
+            testCodePoint(At, s, 9, golden1[1][i]);
+            testCodePoint(At, s, s.length()-1, golden1[2][i]);
+            testCodePoint(At, s.substring(17), 0, golden1[3][i]);
+
+            /*
+             * Abnormal case - verify that an exception is thrown.
+             */
+            testCodePoint(At, s, -1);
+            testCodePoint(At, s, s.length());
+        }
+    }
+
+
+    /* Expected results for:
+     *     test2(): for codePointBefore()
+     *
+     * Each character in each array is the golden data for each text string
+     * in the above input data. For example, the first data in each array is
+     * for the first input string.
+     */
+    static final int[][] golden2 = {
+        {'a',    0xD800, 0xDC00,  0xD800,  0xDB40,  0xD800}, // codePointBefore(1)
+        {0xD800, 'l',    0x10000, 0xDC00,  0xDB40,  0xD800}, // codePointBefore(13)
+        {'f',    0xDC00, 0xD800,  0x10000, 0xE0202, 0x10010},// codePointBefore(length)
+        {'b',    'd',    'a',     0xDC00,  0xDE00,  0xDC00}, // codePointBefore() for a substring
+    };
+
+    /*
+     * Test for codePointBefore(int index) method
+     */
+    static void test2() {
+
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+
+            /*
+             * Normal case
+             */
+            testCodePoint(Before, s, 1, golden2[0][i]);
+            testCodePoint(Before, s, 13, golden2[1][i]);
+            testCodePoint(Before, s, s.length(), golden2[2][i]);
+            testCodePoint(Before, s.substring(1), 1, golden2[3][i]);
+
+            /*
+             * Abnormal case - verify that an exception is thrown.
+             */
+            testCodePoint(Before, s, 0);
+            testCodePoint(Before, s, s.length()+1);
+        }
+    }
+
+
+    /* Expected results for:
+     *     test3(): for indexOf(int ch)
+     *     test4(): for indexOf(int ch, int fromIndex)
+     *     test5(): for lastIndexOf(int ch)
+     *     test6(): for lastIndexOf(int ch, int fromIndex)
+     *
+     * Unlike golden1 and golden2, golden3[m][] is the golden data for text
+     * string in input[m].
+     *
+     * The meaning of each element in golden3[][n]
+     *   golden3[][0]: characater which is searched.
+     *   golden3[][2]: the golden data for indexOf(int ch)
+     *   From golden3[][2] to golden3[][n-1]:
+     *       the golden data for indexOf(int ch, int fromIndex)
+     *   The golden3[][n-2]: the golden data for lastIndexOf(int ch)
+     *   From golden3[][1] to golden3[][n-2]:
+     *       the golden data for lastIndexOf(int ch, int fromIndex)
+     *
+     *   In other words, the data format is
+     *     { ch, -1, index1, index2, ..., -1}
+     *   where index1, index2, ... are all indices of the ch occurrences.
+     */
+    static final int[][] golden3 = {
+      /* ch       indices */
+        {'b',     -1,  1, 11, 20,  -1},
+        {0xD800,  -1,  0,  5,  9,  19, -1},
+        {0xDC00,  -1,  0, 12, 16,  17, 20, -1},
+        {0x10000, -1,  0,  8, 21,  -1},
+        {0xE0202, -1,  9, 17, -1},
+        {0x1000A, -1, 22, 30, -1}
+    };
+
+    /*
+     * Test for indexOf(int ch) method
+     */
+    static void test3() {
+
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+
+            /*
+             * Normal case
+             */
+            testIndexOf(First, s, golden3[i][0], golden3[i][2]);
+
+            /*
+             * Abnormal case - char which isn't included in the string.
+             */
+            testIndexOf(First, s, 'Z', -1);
+            testIndexOf(First, s, 0xDB98, -1);
+            testIndexOf(First, s, 0xDE76, -1);
+            testIndexOf(First, s, 0x12345, -1);
+            testIndexOf(First, s, -1, -1);
+            testIndexOf(First, s, 0x110000, -1);
+        }
+    }
+
+    /*
+     * Test for indexOf(int ch, int fromIndex) method
+     */
+    static void test4() {
+
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+            int ch = golden3[i][0];
+
+            /*
+             * Normal case
+             */
+            int fromIndex = 0;
+            for (int j = 2; j < golden3[i].length; j++) {
+                fromIndex = testIndexOf(First, s, fromIndex, ch,
+                                        golden3[i][j]) + 1;
+            }
+
+            /*
+             * Abnormal case1 - char is included in the string but fromIndex
+             *                  is incorrect.
+             */
+            testIndexOf(First, s, -1, ch, golden3[i][2]);
+            testIndexOf(First, s, s.length(), ch,
+                        golden3[i][golden3[i].length-1]);
+
+            /*
+             * Abnormal case2 - char which isn't included in the string.
+             */
+            testIndexOf(First, s, 0, 'Z', -1);
+            testIndexOf(First, s, 0, 0xDB98, -1);
+            testIndexOf(First, s, 0, 0xDE76, -1);
+            testIndexOf(First, s, 0, 0x12345, -1);
+            testIndexOf(First, s, 0, -1, -1);
+            testIndexOf(First, s, 0, 0x110000, -1);
+        }
+    }
+
+    /*
+     * Test for lastIndexOf(int ch) method
+     */
+    static void test5() {
+
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+
+            /*
+             * Normal case
+             */
+            testIndexOf(Last, s, golden3[i][0],
+                        golden3[i][golden3[i].length-2]);
+
+            /*
+             * Abnormal case - char which isn't included in the string.
+             */
+            testIndexOf(Last, s, 'Z', -1);
+            testIndexOf(Last, s, 0xDB98, -1);
+            testIndexOf(Last, s, 0xDE76, -1);
+            testIndexOf(Last, s, 0x12345, -1);
+            testIndexOf(Last, s, -1, -1);
+            testIndexOf(Last, s, 0x110000, -1);
+        }
+    }
+
+    /*
+     * Test for lastIndexOf(int ch, int fromIndex) method
+     */
+    static void test6() {
+
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+            int ch = golden3[i][0];
+            int len = s.length();
+
+            /*
+             * Normal case
+             */
+            int fromIndex = len - 1;
+            for (int j = golden3[i].length - 2; j > 0; j--) {
+                fromIndex = testIndexOf(Last, s, fromIndex, ch,
+                                        golden3[i][j]) - 1;
+            }
+
+            /*
+             * Abnormal case1 - char is included in the string but fromIndex
+             *                  is incorrect.
+             */
+            testIndexOf(Last, s, -1, ch, golden3[i][1]);
+            testIndexOf(Last, s, len, ch, golden3[i][golden3[i].length-2]);
+
+            /*
+             * Abnormal case2 - char which isn't included in the string.
+             */
+            testIndexOf(Last, s, len, 'Z', -1);
+            testIndexOf(Last, s, len, 0xDB98, -1);
+            testIndexOf(Last, s, len, 0xDE76, -1);
+            testIndexOf(Last, s, len, 0x12345, -1);
+            testIndexOf(Last, s, len, -1, -1);
+            testIndexOf(Last, s, len, 0x110000, -1);
+        }
+    }
+
+    /**
+     * Test for String(int[] codePoint, int offset, int count).
+     */
+    static void test7() {
+        for (int i = 0; i < input.length; i++) {
+            String s = input[i];
+            int nCodePoints = 0;
+            int c;
+            for (int j = 0; j < s.length(); j += Character.charCount(c)) {
+                c = s.codePointAt(j);
+                nCodePoints++;
+            }
+            int[] codePoints = new int[nCodePoints];
+            int count = 0, mid = 0, offset = 0;
+            for (int j = 0; j < s.length(); j += Character.charCount(c)) {
+                if (mid == 0 && j >= s.length()/2) {
+                    mid = j;
+                    offset = count;
+                }
+                c = s.codePointAt(j);
+                codePoints[count++] = c;
+            }
+
+            String cps = new String(codePoints, 0, count);
+            check(!s.equals(cps), "new String(int[]...) with input[" + i + "]");
+
+            cps = new String(codePoints, 0, offset);
+            check(!s.substring(0, mid).equals(cps),
+                  "first half: new String(int[]...) with input[" + i + "]");
+
+            cps = new String(codePoints, offset, count - offset);
+            check(!s.substring(mid).equals(cps),
+                  "second half: new String(int[]...) with input[" + i + "]");
+
+            // test exceptions
+            testNewString(null, 0, count, NullPointerException.class);
+            testNewString(codePoints, -1, count, IndexOutOfBoundsException.class);
+            testNewString(codePoints, 0, count+1, IndexOutOfBoundsException.class);
+            testNewString(codePoints, offset, count, IndexOutOfBoundsException.class);
+            testNewString(codePoints, offset, -1, IndexOutOfBoundsException.class);
+            testNewString(codePoints, count, 1, IndexOutOfBoundsException.class);
+            codePoints[offset] = -1;
+            testNewString(codePoints, 0, count, IllegalArgumentException.class);
+            codePoints[offset] = Character.MAX_CODE_POINT+1;
+            testNewString(codePoints, 0, count, IllegalArgumentException.class);
+        }
+
+        {
+            // 6588260: (str) ArrayIndexOutOfBoundsException when trying
+            // to create a String from codePoints
+            //int[] x = new int[Character.MAX_CODE_POINT+1];
+            int[] x = new int[Character.MAX_CODE_POINT];
+            for (int i = 0; i < x.length; i++)
+                if (i != 0xdbff) // For round-trip safety
+                    x[i] = i;
+            final String s = new String(x, 0, x.length);
+            check(s.codePointCount(0, s.length()) != x.length,
+                  "s.codePointCount(0, s.length()) != x.length");
+            check(s.length() <= x.length,
+                  "s.length() <= x.length");
+            for (int i = 0, j = 0; i < x.length; i++) {
+                int c = s.codePointAt(j);
+                check(c != x[i], "c != x[i]");
+                j += Character.charCount(c);
+            }
+        }
+    }
+
+    /**
+     * Test codePointCount(int, int)
+     *
+     * This test case assumes that
+     * Character.codePointCount(CharSequence, int, int) works
+     * correctly.
+     */
+    static void test8() {
+        for (int i = 0; i < input.length; i++) {
+            String str = input[i];
+            int length = str.length();
+            for (int j = 0; j <= length; j++) {
+                int result = str.codePointCount(j, length);
+                int expected = Character.codePointCount(str, j, length);
+                check(result != expected, "codePointCount(input["+i+"], "+j+", "+length+")",
+                      result, expected);
+                // Create a substring of the text range. It shares the
+                // underlying char[] of the String str.
+                String substr = str.substring(j, length);
+                result = substr.codePointCount(0, substr.length());
+                check(result != expected, "substring:codePointCount(input["+i+"], "+j+", "+length+")",
+                      result, expected);
+            }
+            for (int j = length; j >= 0; j--) {
+                int result = str.codePointCount(0, j);
+                int expected = Character.codePointCount(str, 0, j);
+                check(result != expected, "codePointCount(input["+i+"], 0, "+j+")",
+                      result, expected);
+                String substr = str.substring(0, j);
+                result = substr.codePointCount(0, substr.length());
+                check(result != expected, "substring:codePointCount(input["+i+"], 0, "+j+")",
+                      result, expected);
+            }
+
+            // test exceptions
+            testCodePointCount(null, 0, 0, NullPointerException.class);
+            testCodePointCount(str, -1, length, IndexOutOfBoundsException.class);
+            testCodePointCount(str, 0, length+1, IndexOutOfBoundsException.class);
+            testCodePointCount(str, length, length-1, IndexOutOfBoundsException.class);
+        }
+    }
+
+    /**
+     * Test offsetByCodePoints(int, int)
+     *
+     * This test case assumes that
+     * Character.codePointCount(CharSequence, int, int) works
+     * correctly.
+     */
+    static void test9() {
+        for (int i = 0; i < input.length; i++) {
+            String str = input[i];
+            int length = str.length();
+            for (int j = 0; j <= length; j++) {
+                int nCodePoints = Character.codePointCount(str, j, length);
+                int result = str.offsetByCodePoints(j, nCodePoints);
+                check(result != length,
+                      "offsetByCodePoints(input["+i+"], "+j+", "+nCodePoints+")",
+                      result, length);
+                result = str.offsetByCodePoints(length, -nCodePoints);
+                int expected = j;
+                if (j > 0 && j < length) {
+                    int cp = str.codePointBefore(j+1);
+                    if (Character.isSupplementaryCodePoint(cp)) {
+                        expected--;
+                    }
+                }
+                check(result != expected,
+                      "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+                      result, expected);
+            }
+            for (int j = length; j >= 0; j--) {
+                int nCodePoints = Character.codePointCount(str, 0, j);
+                int result = str.offsetByCodePoints(0, nCodePoints);
+                int expected = j;
+                if (j > 0 && j < length) {
+                    int cp = str.codePointAt(j-1);
+                     if (Character.isSupplementaryCodePoint(cp)) {
+                        expected++;
+                    }
+                }
+                check(result != expected,
+                      "offsetByCodePoints(input["+i+"], 0, "+nCodePoints+")",
+                      result, expected);
+                result = str.offsetByCodePoints(j, -nCodePoints);
+                check(result != 0,
+                      "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+                      result, 0);
+            }
+
+            // test exceptions
+            testOffsetByCodePoints(null, 0, 0, NullPointerException.class);
+            testOffsetByCodePoints(str, -1, length, IndexOutOfBoundsException.class);
+            testOffsetByCodePoints(str, 0, length+1, IndexOutOfBoundsException.class);
+            testOffsetByCodePoints(str, 1, -2, IndexOutOfBoundsException.class);
+            testOffsetByCodePoints(str, length, length-1, IndexOutOfBoundsException.class);
+            testOffsetByCodePoints(str, length, -(length+1), IndexOutOfBoundsException.class);
+        }
+    }
+
+    /**
+     * Test offsetByCodePoints(int, int) - to verify the fix for 6242664
+     *
+     * This test case assumes that
+     * Character.codePointCount(CharSequence, int, int) works
+     * correctly.
+     */
+    static void test10() {
+        String header = "H\uD800e\uDFFFa\uDBFF\uDC00der<";
+        for (int i = 0; i < input.length; i++) {
+            String wholeString = header + input[i];
+            String str = wholeString.substring(header.length());
+            int length = str.length();
+            for (int j = 0; j <= length; j++) {
+                int nCodePoints = Character.codePointCount(str, j, length);
+                int result = str.offsetByCodePoints(j, nCodePoints);
+                check(result != length,
+                      "offsetByCodePoints(input["+i+"], "+j+", "+nCodePoints+")",
+                      result, length);
+                result = str.offsetByCodePoints(length, -nCodePoints);
+                int expected = j;
+                if (j > 0 && j < length) {
+                    int cp = str.codePointBefore(j+1);
+                    if (Character.isSupplementaryCodePoint(cp)) {
+                        expected--;
+                    }
+                }
+                check(result != expected,
+                      "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+                      result, expected);
+            }
+            for (int j = length; j >= 0; j--) {
+                int nCodePoints = Character.codePointCount(str, 0, j);
+                int result = str.offsetByCodePoints(0, nCodePoints);
+                int expected = j;
+                if (j > 0 && j < length) {
+                    int cp = str.codePointAt(j-1);
+                     if (Character.isSupplementaryCodePoint(cp)) {
+                        expected++;
+                    }
+                }
+                check(result != expected,
+                      "offsetByCodePoints(input["+i+"], 0, "+nCodePoints+")",
+                      result, expected);
+                result = str.offsetByCodePoints(j, -nCodePoints);
+                check(result != 0,
+                      "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+                      result, 0);
+            }
+        }
+    }
+
+
+    static final boolean At = true, Before = false;
+    static final boolean First = true, Last = false;
+
+    static void testCodePoint(boolean isAt, String s, int index, int expected) {
+        int c = isAt ? s.codePointAt(index) : s.codePointBefore(index);
+
+        check(c != expected,
+              "codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"
+              + s + ">", c, expected);
+    }
+
+    static void testCodePoint(boolean isAt, String s, int index) {
+        boolean exceptionOccurred = false;
+
+        try {
+            int c = isAt ? s.codePointAt(index) : s.codePointBefore(index);
+        }
+        catch (StringIndexOutOfBoundsException e) {
+            exceptionOccurred = true;
+        }
+        check(!exceptionOccurred,
+              "codePoint" + (isAt ? "At" : "Before") + "(" + index + ") for <"
+              + s + "> should throw StringIndexOutOfBoundsPointerException.");
+    }
+
+    static void testIndexOf(boolean isFirst, String s, int c, int expected) {
+        int index = isFirst ? s.indexOf(c) : s.lastIndexOf(c);
+
+        check(index != expected,
+              (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c)
+              + ") for <" + s + ">", index, expected);
+    }
+
+    static int testIndexOf(boolean isFirst, String s, int fromIndex, int c,
+                           int expected) {
+        int index = isFirst ? s.indexOf(c, fromIndex) :
+                              s.lastIndexOf(c, fromIndex);
+
+        check(index != expected,
+              (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c) + ", "
+              + fromIndex + ") for <" + s + ">", index, expected);
+
+        return index;
+    }
+
+    static void testNewString(int[] codePoints, int offset, int count, Class expectedException) {
+        try {
+            String s = new String(codePoints, offset, count);
+        } catch (Exception e) {
+            if (expectedException.isInstance(e)) {
+                return;
+            }
+            throw new RuntimeException("Error: Unexpected exception", e);
+        }
+        check(true, "new String(int[]...) didn't throw " + expectedException.getName());
+    }
+
+    static void testCodePointCount(String str, int beginIndex, int endIndex,
+                                   Class expectedException) {
+        try {
+            int n = str.codePointCount(beginIndex, endIndex);
+        } catch (Exception e) {
+            if (expectedException.isInstance(e)) {
+                return;
+            }
+            throw new RuntimeException("Error: Unexpected exception", e);
+        }
+        check(true, "codePointCount() didn't throw " + expectedException.getName());
+    }
+
+    static void testOffsetByCodePoints(String str, int index, int offset,
+                                       Class expectedException) {
+        try {
+            int n = str.offsetByCodePoints(index, offset);
+        } catch (Exception e) {
+            if (expectedException.isInstance(e)) {
+                return;
+            }
+            throw new RuntimeException("Error: Unexpected exception", e);
+        }
+        check(true, "offsetByCodePoints() didn't throw " + expectedException.getName());
+    }
+
+    static void check(boolean err, String msg) {
+        if (err) {
+            throw new RuntimeException("Error: " + msg);
+        }
+    }
+
+    static void check(boolean err, String s, int got, int expected) {
+        if (err) {
+            throw new RuntimeException("Error: " + s
+                                       + " returned an unexpected value. got "
+                                       + toHexString(got)
+                                       + ", expected "
+                                       + toHexString(expected));
+        }
+    }
+
+    private static String toHexString(int c) {
+        return "0x" + Integer.toHexString(c);
+    }
+}
diff --git a/test/java/lang/String/ToLowerCase.java b/test/java/lang/String/ToLowerCase.java
new file mode 100644
index 0000000..84d5d5a
--- /dev/null
+++ b/test/java/lang/String/ToLowerCase.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+    @test
+    @bug 4217441 4533872 4900935
+    @summary toLowerCase should lower-case Greek Sigma correctly depending
+             on the context (final/non-final).  Also it should handle
+             Locale specific (lt, tr, and az) lowercasings and supplementary
+             characters correctly.
+*/
+
+import java.util.Locale;
+
+public class ToLowerCase {
+
+    public static void main(String[] args) {
+        Locale turkish = new Locale("tr", "TR");
+        Locale lt = new Locale("lt"); // Lithanian
+        Locale az = new Locale("az"); // Azeri
+
+        // Greek Sigma final/non-final tests
+        test("\u03A3", Locale.US, "\u03C3");
+        test("LAST\u03A3", Locale.US, "last\u03C2");
+        test("MID\u03A3DLE", Locale.US, "mid\u03C3dle");
+        test("WORD1 \u03A3 WORD3", Locale.US, "word1 \u03C3 word3");
+        test("WORD1 LAST\u03A3 WORD3", Locale.US, "word1 last\u03C2 word3");
+        test("WORD1 MID\u03A3DLE WORD3", Locale.US, "word1 mid\u03C3dle word3");
+        test("\u0399\u0395\u03a3\u03a5\u03a3 \u03a7\u03a1\u0399\u03a3\u03a4\u039f\u03a3", Locale.US,
+             "\u03b9\u03b5\u03c3\u03c5\u03c2 \u03c7\u03c1\u03b9\u03c3\u03c4\u03bf\u03c2"); // "IESUS XRISTOS"
+
+        // Explicit dot above for I's and J's whenever there are more accents above (Lithanian)
+        test("I", lt, "i");
+        test("I\u0300", lt, "i\u0307\u0300"); // "I" followed by COMBINING GRAVE ACCENT (cc==230)
+        test("I\u0316", lt, "i\u0316"); // "I" followed by COMBINING GRAVE ACCENT BELOW (cc!=230)
+        test("J", lt, "j");
+        test("J\u0300", lt, "j\u0307\u0300"); // "J" followed by COMBINING GRAVE ACCENT (cc==230)
+        test("J\u0316", lt, "j\u0316"); // "J" followed by COMBINING GRAVE ACCENT BELOW (cc!=230)
+        test("\u012E", lt, "\u012F");
+        test("\u012E\u0300", lt, "\u012F\u0307\u0300"); // "I (w/ OGONEK)" followed by COMBINING GRAVE ACCENT (cc==230)
+        test("\u012E\u0316", lt, "\u012F\u0316"); // "I (w/ OGONEK)" followed by COMBINING GRAVE ACCENT BELOW (cc!=230)
+        test("\u00CC", lt, "i\u0307\u0300");
+        test("\u00CD", lt, "i\u0307\u0301");
+        test("\u0128", lt, "i\u0307\u0303");
+        test("I\u0300", Locale.US, "i\u0300"); // "I" followed by COMBINING GRAVE ACCENT (cc==230)
+        test("J\u0300", Locale.US, "j\u0300"); // "J" followed by COMBINING GRAVE ACCENT (cc==230)
+        test("\u012E\u0300", Locale.US, "\u012F\u0300"); // "I (w/ OGONEK)" followed by COMBINING GRAVE ACCENT (cc==230)
+        test("\u00CC", Locale.US, "\u00EC");
+        test("\u00CD", Locale.US, "\u00ED");
+        test("\u0128", Locale.US, "\u0129");
+
+        // I-dot tests (Turkish and Azeri)
+        test("\u0130", turkish, "i");
+        test("\u0130", az, "i");
+        test("\u0130", Locale.US, "i");
+
+        // Remove dot_above in the sequence I + dot_above (Turkish and Azeri)
+        test("I\u0307", turkish, "i");
+        test("I\u0307", az, "i");
+        test("J\u0307", turkish, "j\u0307");
+        test("J\u0307", az, "j\u0307");
+
+        // Unless an I is before a dot_above, it turns into a dotless i (Turkish and Azeri)
+        test("I", turkish, "\u0131");
+        test("I", az, "\u0131");
+        test("I", Locale.US, "i");
+        test("IABC", turkish, "\u0131abc");
+        test("IABC", az, "\u0131abc");
+        test("IABC", Locale.US, "iabc");
+
+        // Supplementary character tests
+        //
+        // U+10400 ("\uD801\uDC00"): DESERET CAPITAL LETTER LONG I
+        // U+10401 ("\uD801\uDC01"): DESERET CAPITAL LETTER LONG E
+        // U+10402 ("\uD801\uDC02"): DESERET CAPITAL LETTER LONG A
+        // U+10428 ("\uD801\uDC28"): DESERET SMALL LETTER LONG I
+        // U+10429 ("\uD801\uDC29"): DESERET SMALL LETTER LONG E
+        // U+1042A ("\uD801\uDC2A"): DESERET SMALL LETTER LONG A
+        //
+        // valid code point tests:
+        test("\uD801\uDC00\uD801\uDC01\uD801\uDC02", Locale.US, "\uD801\uDC28\uD801\uDC29\uD801\uDC2A");
+        test("\uD801\uDC00A\uD801\uDC01B\uD801\uDC02C", Locale.US, "\uD801\uDC28a\uD801\uDC29b\uD801\uDC2Ac");
+        // invalid code point tests:
+        test("\uD800\uD800\uD801A\uDC00\uDC00\uDC00B", Locale.US, "\uD800\uD800\uD801a\uDC00\uDC00\uDC00b");
+
+    }
+
+    static void test(String in, Locale locale, String expected) {
+        String result = in.toLowerCase(locale);
+        if (!result.equals(expected)) {
+            System.err.println("input: " + in + ", locale: " + locale +
+                    ", expected: " + expected + ", actual: " + result);
+            throw new RuntimeException();
+        }
+   }
+}
diff --git a/test/java/lang/String/ToUpperCase.java b/test/java/lang/String/ToUpperCase.java
new file mode 100644
index 0000000..a928f60
--- /dev/null
+++ b/test/java/lang/String/ToUpperCase.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+    @test
+    @bug 4219630 4304573 4533872 4900935
+    @summary toUpperCase should upper-case German sharp s correctly even if
+             it's the only character in the string. should also uppercase
+             all of the 1:M char mappings correctly.  Also it should handle
+             Locale specific (lt, tr, and az) uppercasings and supplementary
+             characters correctly.
+*/
+
+import java.util.Locale;
+
+public class ToUpperCase {
+
+    public static void main(String[] args) {
+        Locale turkish = new Locale("tr", "TR");
+        Locale lt = new Locale("lt"); // Lithanian
+        Locale az = new Locale("az"); // Azeri
+
+        test("\u00DF", turkish, "SS");
+        test("a\u00DF", turkish, "ASS");
+        test("i", turkish, "\u0130");
+        test("i", az, "\u0130");
+        test("\u0131", turkish, "I");
+        test("\u00DF", Locale.GERMANY, "SS");
+        test("a\u00DF", Locale.GERMANY, "ASS");
+        test("i", Locale.GERMANY, "I");
+
+        // test some of the 1:M uppercase mappings
+        test("abc\u00DF", Locale.US, "ABC\u0053\u0053");
+        test("\u0149abc", Locale.US, "\u02BC\u004EABC");
+        test("\u0149abc", turkish, "\u02BC\u004EABC");
+        test("\u1F52", Locale.US, "\u03A5\u0313\u0300");
+        test("\u0149\u1F52", Locale.US, "\u02BC\u004E\u03A5\u0313\u0300");
+        test("\u1F54ZZZ", Locale.US, "\u03A5\u0313\u0301ZZZ");
+        test("\u1F54ZZZ", turkish, "\u03A5\u0313\u0301ZZZ");
+        test("a\u00DF\u1F56", Locale.US, "ASS\u03A5\u0313\u0342");
+        test("\u1FAD", turkish, "\u1F6D\u0399");
+        test("i\u1FC7", turkish, "\u0130\u0397\u0342\u0399");
+        test("i\u1FC7", az, "\u0130\u0397\u0342\u0399");
+        test("i\u1FC7", Locale.US, "I\u0397\u0342\u0399");
+        test("\uFB04", Locale.US, "\u0046\u0046\u004C");
+        test("\uFB17AbCdEfi", turkish, "\u0544\u053DABCDEF\u0130");
+        test("\uFB17AbCdEfi", az, "\u0544\u053DABCDEF\u0130");
+
+        // Remove DOT ABOVE after "i" in Lithuanian
+        test("i\u0307", lt, "I");
+        test("\u0307", lt, "\u0307");
+        test("\u0307i", lt, "\u0307I");
+        test("j\u0307", lt, "J");
+        test("abci\u0307def", lt, "ABCIDEF");
+        test("a\u0307", lt, "A\u0307");
+        test("abc\u0307def", lt, "ABC\u0307DEF");
+        test("i\u0307", Locale.US, "I\u0307");
+        test("i\u0307", turkish, "\u0130\u0307");
+
+        // Supplementary character tests
+        //
+        // U+10400 ("\uD801\uDC00"): DESERET CAPITAL LETTER LONG I
+        // U+10401 ("\uD801\uDC01"): DESERET CAPITAL LETTER LONG E
+        // U+10402 ("\uD801\uDC02"): DESERET CAPITAL LETTER LONG A
+        // U+10428 ("\uD801\uDC28"): DESERET SMALL LETTER LONG I
+        // U+10429 ("\uD801\uDC29"): DESERET SMALL LETTER LONG E
+        // U+1042A ("\uD801\uDC2A"): DESERET SMALL LETTER LONG A
+        //
+        // valid code point tests:
+        test("\uD801\uDC28\uD801\uDC29\uD801\uDC2A", Locale.US, "\uD801\uDC00\uD801\uDC01\uD801\uDC02");
+        test("\uD801\uDC28a\uD801\uDC29b\uD801\uDC2Ac", Locale.US, "\uD801\uDC00A\uD801\uDC01B\uD801\uDC02C");
+        // invalid code point tests:
+        test("\uD800\uD800\uD801a\uDC00\uDC00\uDC00b", Locale.US, "\uD800\uD800\uD801A\uDC00\uDC00\uDC00B");
+    }
+
+    static void test(String in, Locale locale, String expected) {
+        String result = in.toUpperCase(locale);
+        if (!result.equals(expected)) {
+            System.err.println("input: " + in + ", locale: " + locale +
+                    ", expected: " + expected + ", actual: " + result);
+            throw new RuntimeException();
+        }
+   }
+}