Manually merge my AOSP update to the VM tests.

Original change: https://android-review.googlesource.com/32051

Bug: http://code.google.com/p/android/issues/detail?id=21599
Bug: http://code.google.com/p/android/issues/detail?id=21597
Change-Id: I31e440b66b720647afab54ca39fd6eb1bbb0cb60
diff --git a/test/029-assert/src/Main.java b/test/029-assert/src/Main.java
index 1d3b10a..66a1550 100644
--- a/test/029-assert/src/Main.java
+++ b/test/029-assert/src/Main.java
@@ -26,5 +26,8 @@
         } catch (AssertionError ae) {
             System.out.println("caught expected assert exception");
         }
+
+        // exercise this code path
+        ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
     }
 }
diff --git a/test/031-class-attributes/expected.txt b/test/031-class-attributes/expected.txt
index 47eaeee..afa3416 100644
--- a/test/031-class-attributes/expected.txt
+++ b/test/031-class-attributes/expected.txt
@@ -4,6 +4,7 @@
   simple: ClassAttrs
   genericSignature: null
   super: class java.lang.Object
+  genericSuperclass: class java.lang.Object
   declaring: null
   enclosing: null
   enclosingCon: null
@@ -21,12 +22,15 @@
   isMemberClass: false
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [0]
 ***** class OtherClass:
   name: OtherClass
   canonical: OtherClass
   simple: OtherClass
   genericSignature: null
   super: class java.lang.Object
+  genericSuperclass: class java.lang.Object
   declaring: null
   enclosing: null
   enclosingCon: null
@@ -44,12 +48,15 @@
   isMemberClass: false
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [0]
 ***** class otherpackage.OtherPackageClass:
   name: otherpackage.OtherPackageClass
   canonical: otherpackage.OtherPackageClass
   simple: OtherPackageClass
   genericSignature: null
   super: class java.lang.Object
+  genericSuperclass: class java.lang.Object
   declaring: null
   enclosing: null
   enclosingCon: null
@@ -67,12 +74,15 @@
   isMemberClass: false
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [0]
 ***** class ClassAttrs$1InnerNamed:
   name: ClassAttrs$1InnerNamed
   canonical: null
   simple: InnerNamed
   genericSignature: null
   super: class java.lang.Object
+  genericSuperclass: class java.lang.Object
   declaring: null
   enclosing: class ClassAttrs
   enclosingCon: null
@@ -90,12 +100,15 @@
   isMemberClass: false
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [0]
 ***** class ClassAttrs$1ConsInnerNamed:
   name: ClassAttrs$1ConsInnerNamed
   canonical: null
   simple: ConsInnerNamed
   genericSignature: null
   super: class java.lang.Object
+  genericSuperclass: class java.lang.Object
   declaring: null
   enclosing: class ClassAttrs
   enclosingCon: ClassAttrs()
@@ -113,12 +126,15 @@
   isMemberClass: false
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [0]
 ***** class ClassAttrs$1:
   name: ClassAttrs$1
   canonical: null
   simple: 
   genericSignature: null
   super: class OtherClass
+  genericSuperclass: class OtherClass
   declaring: null
   enclosing: class ClassAttrs
   enclosingCon: null
@@ -136,12 +152,15 @@
   isMemberClass: false
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [0]
 ***** class ClassAttrs$MemberClass:
   name: ClassAttrs$MemberClass
   canonical: ClassAttrs.MemberClass
   simple: MemberClass
   genericSignature: <XYZ:Ljava/lang/Object;>Ljava/lang/Object;
   super: class java.lang.Object
+  genericSuperclass: class java.lang.Object
   declaring: class ClassAttrs
   enclosing: class ClassAttrs
   enclosingCon: null
@@ -159,6 +178,34 @@
   isMemberClass: true
   isPrimitive: false
   isSynthetic: false
+  genericInterfaces: [0]
+  typeParameters: [1] XYZ
+***** class FancyClass:
+  name: FancyClass
+  canonical: FancyClass
+  simple: FancyClass
+  genericSignature: <K:Ljava/lang/Object;V:Ljava/lang/Object;>Ljava/util/HashMap<TK;TV;>;Ljava/util/Map<TK;TV;>;
+  super: class java.util.HashMap
+  genericSuperclass: java.util.HashMap<K, V>
+  declaring: null
+  enclosing: null
+  enclosingCon: null
+  enclosingMeth: null
+  modifiers: 1
+  package: null
+  declaredClasses: [0]
+  member classes: [2] class java.util.AbstractMap$SimpleEntry, class java.util.AbstractMap$SimpleImmutableEntry
+  isAnnotation: false
+  isAnonymous: false
+  isArray: false
+  isEnum: false
+  isInterface: false
+  isLocalClass: false
+  isMemberClass: false
+  isPrimitive: false
+  isSynthetic: false
+  genericInterfaces: [1] java.util.Map<K, V>
+  typeParameters: [2] K, V
 constructor signature: (LClassAttrs$MemberClass<TXYZ;>;)V
 method signature: ()Ljava/lang/Class<TXYZ;>;
 field signature: LClassAttrs$MemberClass<TXYZ;>;
diff --git a/test/031-class-attributes/src/ClassAttrs.java b/test/031-class-attributes/src/ClassAttrs.java
index d4d4d0e..c3c61bf 100644
--- a/test/031-class-attributes/src/ClassAttrs.java
+++ b/test/031-class-attributes/src/ClassAttrs.java
@@ -6,6 +6,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 
 public class ClassAttrs {
     ClassAttrs() {
@@ -42,6 +43,9 @@
         /* member, not anonymous, not local */
         printClassAttrs(MemberClass.class);
 
+        /* fancy */
+        printClassAttrs(FancyClass.class);
+
         try {
             Constructor cons;
             cons = MemberClass.class.getConstructor(
@@ -111,7 +115,6 @@
      * Dump a variety of class attributes.
      */
     public static void printClassAttrs(Class clazz) {
-        final boolean WORKING = false;
         Class clazz2;
 
         System.out.println("***** " + clazz + ":");
@@ -127,7 +130,7 @@
 
         System.out.println("  super: "
             + clazz.getSuperclass());
-        if (WORKING) System.out.println("  genericSuperclass: "
+        System.out.println("  genericSuperclass: "
             + clazz.getGenericSuperclass());
         System.out.println("  declaring: "
             + clazz.getDeclaringClass());
@@ -166,8 +169,12 @@
         System.out.println("  isSynthetic: "
             + clazz.isSynthetic());
 
-        if (WORKING) System.out.println("  genericInterfaces: "
+        System.out.println("  genericInterfaces: "
             + stringifyTypeArray(clazz.getGenericInterfaces()));
+
+        TypeVariable<Class<?>>[] typeParameters = clazz.getTypeParameters();
+        System.out.println("  typeParameters: "
+            + stringifyTypeArray(typeParameters));
     }
 
     /*
diff --git a/test/031-class-attributes/src/FancyClass.java b/test/031-class-attributes/src/FancyClass.java
new file mode 100644
index 0000000..a58b6a6
--- /dev/null
+++ b/test/031-class-attributes/src/FancyClass.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FancyClass<K,V> extends HashMap<K,V> implements Map<K,V> {
+}
+
diff --git a/test/033-class-init-deadlock/expected.txt b/test/033-class-init-deadlock/expected.txt
index 387a426..182d0da 100644
--- a/test/033-class-init-deadlock/expected.txt
+++ b/test/033-class-init-deadlock/expected.txt
@@ -1,7 +1,7 @@
 Deadlock test starting.
 A initializing...
 B initializing...
-Deadlock test interupting threads.
+Deadlock test interrupting threads.
 Deadlock test main thread bailing.
 A initialized: false
 B initialized: false
diff --git a/test/033-class-init-deadlock/src/Main.java b/test/033-class-init-deadlock/src/Main.java
index e4ee9ae..3233230 100644
--- a/test/033-class-init-deadlock/src/Main.java
+++ b/test/033-class-init-deadlock/src/Main.java
@@ -30,11 +30,13 @@
         thread1 = new Thread() { public void run() { new A(); } };
         thread2 = new Thread() { public void run() { new B(); } };
         thread1.start();
+        // Give thread1 a chance to start before starting thread2.
+        try { Thread.sleep(1000); } catch (InterruptedException ie) { }
         thread2.start();
 
         try { Thread.sleep(6000); } catch (InterruptedException ie) { }
 
-        System.out.println("Deadlock test interupting threads.");
+        System.out.println("Deadlock test interrupting threads.");
         thread1.interrupt();
         thread2.interrupt();
         System.out.println("Deadlock test main thread bailing.");
diff --git a/test/042-new-instance/expected.txt b/test/042-new-instance/expected.txt
index 53447db..bb1b80c 100644
--- a/test/042-new-instance/expected.txt
+++ b/test/042-new-instance/expected.txt
@@ -6,3 +6,4 @@
 Cons LocalClass2 succeeded
 Cons got expected PackageAccess complaint
 Cons got expected InstantationException
+Cons got expected PackageAccess2 complaint
diff --git a/test/042-new-instance/src/Main.java b/test/042-new-instance/src/Main.java
index 8faef13..e43c5a5 100644
--- a/test/042-new-instance/src/Main.java
+++ b/test/042-new-instance/src/Main.java
@@ -16,12 +16,12 @@
 
 import java.lang.reflect.Constructor;
 
-import java.lang.reflect.Constructor;
-
 /**
  * Test instance creation.
  */
 public class Main {
+    private static boolean FULL_ACCESS_CHECKS = false;  // b/5861201
+
     public static void main(String[] args) {
         testClassNewInstance();
         testConstructorNewInstance();
@@ -98,6 +98,7 @@
             Constructor cons = c.getConstructor(new Class[0] /*(Class[])null*/);
             System.err.println("ERROR: Cons PackageAccess succeeded unexpectedly");
         } catch (NoSuchMethodException nsme) {
+            // constructor isn't public
             System.out.println("Cons got expected PackageAccess complaint");
         } catch (Exception ex) {
             System.err.println("Cons got unexpected PackageAccess failure");
@@ -117,6 +118,22 @@
             System.err.println("Cons got unexpected MaybeAbstract failure");
             ex.printStackTrace();
         }
+
+        // should fail
+        try {
+            Class c = Class.forName("otherpackage.PackageAccess2");
+            Constructor cons = c.getConstructor((Class[]) null);
+            if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); }
+            Object obj = cons.newInstance();
+            System.err.println("ERROR: Cons PackageAccess2 succeeded unexpectedly");
+        } catch (IllegalAccessException iae) {
+            // constructor is public, but class has package scope
+            System.out.println("Cons got expected PackageAccess2 complaint");
+        } catch (Exception ex) {
+            System.err.println("Cons got unexpected PackageAccess2 failure");
+            ex.printStackTrace();
+        }
+
     }
 }
 
diff --git a/test/042-new-instance/src/otherpackage/PackageAccess.java b/test/042-new-instance/src/otherpackage/PackageAccess.java
index 0749d67..f4541f2 100644
--- a/test/042-new-instance/src/otherpackage/PackageAccess.java
+++ b/test/042-new-instance/src/otherpackage/PackageAccess.java
@@ -1,6 +1,29 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package otherpackage;
 
 class PackageAccess {
     /*package*/ PackageAccess() {
+        System.out.println("created PackageAccess");
+    }
+}
+
+class PackageAccess2 {
+    public PackageAccess2() {
+        System.out.println("created PackageAccess2");
     }
 }
diff --git a/test/045-reflect-array/expected.txt b/test/045-reflect-array/expected.txt
index 5c609b5..5990b34 100644
--- a/test/045-reflect-array/expected.txt
+++ b/test/045-reflect-array/expected.txt
@@ -1,4 +1,7 @@
 ReflectArrayTest.testSingleInt passed
+ReflectArrayTest.testSingleChar passed
+ReflectArrayTest.testSingleShort passed
+ReflectArrayTest.testSingleLong passed
 ReflectArrayTest.testSingle passed
 ReflectArrayTest.testMultiInt passed
 zero one two ++
diff --git a/test/045-reflect-array/src/Main.java b/test/045-reflect-array/src/Main.java
index c70e291..36f8ac3 100644
--- a/test/045-reflect-array/src/Main.java
+++ b/test/045-reflect-array/src/Main.java
@@ -10,6 +10,9 @@
 public class Main {
     public static void main(String[] args) {
         testSingleInt();
+        testSingleChar();
+        testSingleShort();
+        testSingleLong();
         testSingle();
         testMultiInt();
         testMulti();
@@ -33,22 +36,31 @@
         try {
             array[2] = 27;
             throw new RuntimeException("store should have failed");
-        }
-        catch (ArrayIndexOutOfBoundsException abe) {
-        }
+        } catch (ArrayIndexOutOfBoundsException abe) { }
+        try {
+            Array.setInt(intArray, 2, 27);
+            throw new RuntimeException("store should have failed");
+        } catch (ArrayIndexOutOfBoundsException abe) { }
         if (array.length != Array.getLength(intArray) ||
             array.length != 2)
         {
             throw new RuntimeException("bad len");
         }
 
+        Integer x123 = Integer.valueOf(123);
+        Integer x456 = Integer.valueOf(456);
+
+        Array.set(intArray, 0, x123);
+        Array.set(intArray, 1, x456);
+        if (!Array.get(intArray, 0).equals(x123) || !Array.get(intArray, 1).equals(x456)) {
+            throw new RuntimeException("bad 123 or 456");
+        }
+
         int[][] wrongArray;
         try {
             wrongArray = (int[][]) intArray;
             throw new RuntimeException("cast should have failed");
-        }
-        catch (ClassCastException cce) {
-        }
+        } catch (ClassCastException cce) { }
 
         intArray = Array.newInstance(Integer.TYPE, 0);
         if (Array.getLength(intArray) != 0)
@@ -56,6 +68,96 @@
         System.out.println("ReflectArrayTest.testSingleInt passed");
     }
 
+    static void testSingleChar() {
+        Object charArray = Array.newInstance(Character.TYPE, 7);
+
+        char[] array = (char[]) charArray;
+        array[0] = '0';
+        array[1] = 'W';
+        array[2] = '2';
+        array[3] = '3';
+        array[4] = 'X';
+        array[5] = '5';
+        array[6] = '6';
+        Array.setChar(charArray, 1, '1');
+        Array.setChar(charArray, 4, '4');
+        try {
+            Array.setShort(charArray, 3, (short) 'Y');
+            throw new RuntimeException("shouldn't allow short in char array");
+        } catch (IllegalArgumentException iae) {}
+        try {
+            Array.setInt(charArray, 5, 'Z');
+            throw new RuntimeException("shouldn't allow int in char array");
+        } catch (IllegalArgumentException iae) {}
+
+        try {
+            for (int i = 0; i < array.length; i++) {
+                if (Array.getInt(charArray, i) - '0' != i) {
+                    throw new RuntimeException("mismatch: " + i + " is " + array[i]);
+                }
+            }
+
+            if (Array.getInt(charArray, 4) != '4') {
+                throw new RuntimeException("load should have worked");
+            }
+        } catch (IllegalArgumentException iae) {
+            System.err.println("Couldn't Array.getInt(charArray)");
+        }
+        try {
+            Array.getByte(charArray, 2);
+            throw new RuntimeException("shouldn't allow read of char as byte");
+        } catch (IllegalArgumentException iae) {}
+
+        Array.setChar(charArray, 3, (char) 0xffff);
+        try {
+            if (Array.getInt(charArray, 3) != 0xffff) {
+                throw new RuntimeException("char got sign-extended? "
+                    + Array.getInt(charArray, 3));
+            }
+        } catch (IllegalArgumentException iae) {
+            System.err.println("Couldn't Array.getInt(charArray)");
+        }
+
+        System.out.println("ReflectArrayTest.testSingleChar passed");
+    }
+
+    static void testSingleShort() {
+        Object shortArray = Array.newInstance(Short.TYPE, 1);
+        Array.setShort(shortArray, 0, (short) -1);
+        if (Array.getInt(shortArray, 0) != -1) {
+            throw new RuntimeException("short didn't get sign-extended");
+        }
+
+        Short box = (Short) Array.get(shortArray, 0);
+
+        System.out.println("ReflectArrayTest.testSingleShort passed");
+    }
+
+    static void testSingleLong() {
+        Object longArray = Array.newInstance(Long.TYPE, 2);
+        Array.setInt(longArray, 0, 123);
+        Array.setLong(longArray, 1, 0x1122334455667788L);
+        try {
+            Array.getInt(longArray, 0);
+            throw new RuntimeException("shouldn't allow read of long as int");
+        } catch (IllegalArgumentException iae) {}
+
+        long[] array = (long[]) longArray;
+        if (array[0] != 123 || array[1] != 0x1122334455667788L) {
+            throw new RuntimeException();
+        }
+
+        float f = Array.getFloat(longArray, 0);
+        if (f < 122.9 || f > 123.1) {
+            throw new RuntimeException("long-as-float failed - " + f);
+        }
+        if (Array.getLong(longArray, 1) != 0x1122334455667788L) {
+            throw new RuntimeException("long1 failed");
+        }
+
+        System.out.println("ReflectArrayTest.testSingleLong passed");
+    }
+
     static void testSingle() {
         Object strArray;
 
@@ -64,6 +166,10 @@
         String[] array = (String[]) strArray;
         array[0] = "entry zero";
         Array.set(strArray, 1, "entry one");
+        try {
+            Array.set(strArray, 2, "entry two");
+            throw new RuntimeException("store should have failed");
+        } catch (ArrayIndexOutOfBoundsException abe) { }
 
         //System.out.println("array: " + array);
 
@@ -77,6 +183,11 @@
         {
             throw new RuntimeException("bad len");
         }
+
+        try {
+            Array.set(strArray, 0, new Integer(5));
+            throw new RuntimeException("store of Integer should have failed");
+        } catch (IllegalArgumentException iae) {}
         System.out.println("ReflectArrayTest.testSingle passed");
     }
 
diff --git a/test/046-reflect/expected.txt b/test/046-reflect/expected.txt
index 240be94..82fe87c 100644
--- a/test/046-reflect/expected.txt
+++ b/test/046-reflect/expected.txt
@@ -91,6 +91,7 @@
 myMethod (I)I
  arg=17 anInt=7
 ReflectTest done!
+public method
 checkType invoking null
 checkType got expected exception
 calling const-class NoisyInitUser.class
@@ -98,3 +99,7 @@
 got methods
 NoisyInitUser is initializing
 NoisyInit is initializing
+
+generic field: java.util.List<java.lang.String>
+generic method fancyMethod params='[1] java.util.ArrayList<java.lang.String>' ret='java.util.Map<java.lang.Integer, java.lang.String>'
+generic ctor Main params='[1] java.util.ArrayList<java.lang.Integer>'
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index f6d9b68..104ead3 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -17,11 +17,18 @@
 import java.lang.reflect.*;
 import java.io.IOException;
 import java.util.Collections;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Reflection test.
  */
 public class Main {
+    private static boolean FULL_ACCESS_CHECKS = false;  // b/5861201
+    public Main() {}
+    public Main(ArrayList<Integer> stuff) {}
+
     void printMethodInfo(Method meth) {
         Class[] params, exceptions;
         int i;
@@ -69,6 +76,48 @@
         System.out.println("  ::: " + one + ":" + two + ":" + three);
     }
 
+    public static void checkAccess() {
+        try {
+            Class target = otherpackage.Other.class;
+            Object instance = new otherpackage.Other();
+            Method meth;
+
+            meth = target.getMethod("publicMethod", (Class[]) null);
+            meth.invoke(instance);
+
+            try {
+                meth = target.getMethod("packageMethod", (Class[]) null);
+                System.err.println("succeeded on package-scope method");
+            } catch (NoSuchMethodException nsme) {
+                // good
+            }
+
+
+            instance = otherpackage.Other.getInnerClassInstance();
+            target = instance.getClass();
+            meth = target.getMethod("innerMethod", (Class[]) null);
+            try {
+                if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); }
+                meth.invoke(instance);
+                System.err.println("inner-method invoke unexpectedly worked");
+            } catch (IllegalAccessException iae) {
+                // good
+            }
+
+            Field field = target.getField("innerField");
+            try {
+                int x = field.getInt(instance);
+                if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); }
+                System.err.println("field get unexpectedly worked: " + x);
+            } catch (IllegalAccessException iae) {
+                // good
+            }
+        } catch (Exception ex) {
+            System.out.println("----- unexpected exception -----");
+            ex.printStackTrace();
+        }
+    }
+
     public void run() {
         Class target = Target.class;
         Method meth = null;
@@ -311,8 +360,7 @@
             targ = cons.newInstance(args);
             targ.myMethod(17);
 
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
             System.out.println("----- unexpected exception -----");
             ex.printStackTrace();
         }
@@ -365,14 +413,80 @@
         /* neither NoisyInit nor NoisyInitUser should be initialized yet */
         NoisyInitUser niu = new NoisyInitUser();
         NoisyInit ni = new NoisyInit();
+
+        System.out.println("");
     }
 
+
+    /*
+     * Test some generic type stuff.
+     */
+    public List<String> dummy;
+    public Map<Integer,String> fancyMethod(ArrayList<String> blah) { return null; }
+    public static void checkGeneric() {
+        Field field;
+        try {
+            field = Main.class.getField("dummy");
+        } catch (NoSuchFieldException nsfe) {
+            throw new RuntimeException(nsfe);
+        }
+        Type listType = field.getGenericType();
+        System.out.println("generic field: " + listType);
+
+        Method method;
+        try {
+            method = Main.class.getMethod("fancyMethod",
+                new Class[] { ArrayList.class });
+        } catch (NoSuchMethodException nsme) {
+            throw new RuntimeException(nsme);
+        }
+        Type[] parmTypes = method.getGenericParameterTypes();
+        Type ret = method.getGenericReturnType();
+        System.out.println("generic method " + method.getName() + " params='"
+            + stringifyTypeArray(parmTypes) + "' ret='" + ret + "'");
+
+        Constructor ctor;
+        try {
+            ctor = Main.class.getConstructor(new Class[] { ArrayList.class });
+        } catch (NoSuchMethodException nsme) {
+            throw new RuntimeException(nsme);
+        }
+        parmTypes = ctor.getGenericParameterTypes();
+        System.out.println("generic ctor " + ctor.getName() + " params='"
+            + stringifyTypeArray(parmTypes) + "'");
+    }
+
+    /*
+     * Convert an array of Type into a string.  Start with an array count.
+     */
+    private static String stringifyTypeArray(Type[] types) {
+        StringBuilder stb = new StringBuilder();
+        boolean first = true;
+
+        stb.append("[" + types.length + "]");
+
+        for (Type t: types) {
+            if (first) {
+                stb.append(" ");
+                first = false;
+            } else {
+                stb.append(", ");
+            }
+            stb.append(t.toString());
+        }
+
+        return stb.toString();
+    }
+
+
     public static void main(String[] args) {
         Main test = new Main();
         test.run();
 
+        checkAccess();
         checkType();
         checkInit();
+        checkGeneric();
     }
 }
 
diff --git a/test/046-reflect/src/otherpackage/Other.java b/test/046-reflect/src/otherpackage/Other.java
new file mode 100644
index 0000000..702ab6d
--- /dev/null
+++ b/test/046-reflect/src/otherpackage/Other.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package otherpackage;
+
+public class Other {
+    public void publicMethod() {
+        System.out.println("public method");
+    }
+    void packageMethod() {
+        System.out.println("package method");
+    }
+
+    public static InnerOther getInnerClassInstance() {
+        return new InnerOther();
+    }
+
+    private static class InnerOther {
+        public void innerMethod() {
+            System.out.println("inner method");
+        }
+
+        public int innerField = 7;
+    }
+}
diff --git a/test/050-sync-test/src/Main.java b/test/050-sync-test/src/Main.java
index 0de3159..ec6d732 100644
--- a/test/050-sync-test/src/Main.java
+++ b/test/050-sync-test/src/Main.java
@@ -37,8 +37,7 @@
         System.out.println("GOING");
         try {
             Thread.sleep(1000);
-        }
-        catch (InterruptedException ie) {
+        } catch (InterruptedException ie) {
             System.out.println("INTERRUPT!");
             ie.printStackTrace();
         }
@@ -52,23 +51,22 @@
         two = new CpuThread(2);
 
         one.start();
-        two.start();
 
         try {
             Thread.sleep(100);
-        }
-        catch (InterruptedException ie) {
+        } catch (InterruptedException ie) {
             System.out.println("INTERRUPT!");
             ie.printStackTrace();
         }
 
+        two.start();
+
         //System.out.println("main: off and running");
 
         try {
             one.join();
             two.join();
-        }
-        catch (InterruptedException ie) {
+        } catch (InterruptedException ie) {
             System.out.println("INTERRUPT!");
             ie.printStackTrace();
         }
@@ -102,34 +100,29 @@
         //System.out.print("thread running -- ");
         //System.out.println(Thread.currentThread().getName());
 
-        for (int i = 0; i < 10; i++) {
-            output(mNumber);
-        }
+        synchronized (mSyncable) {
+            for (int i = 0; i < 10; i++) {
+                output(mNumber);
+            }
 
-        System.out.print("Final result: ");
-        System.out.println(mCount);
+            System.out.print("Final result: ");
+            System.out.println(mCount);
+        }
     }
 
     void output(int num) {
-        /*
-         * Delete the next line; last "final result" should != 20.
-         */
-        synchronized (mSyncable)
-        {
-            int i, count;
+        int count = mCount;
 
-            count = mCount;
+        System.out.print("going: ");
+        System.out.println(num);
 
-            System.out.print("going: ");
-            System.out.println(num);
-
-            /* burn CPU; adjust end value so we exceed scheduler quantum */
-            for (int j = 0; j < 5000; j++)
-                ;
-
-            count++;
-            mCount = count;
+        /* burn CPU; adjust end value so we exceed scheduler quantum */
+        for (int j = 0; j < 5000; j++) {
+            ;
         }
+
+        count++;
+        mCount = count;
     }
 }
 
@@ -164,14 +157,12 @@
                 synchronized (mWaitOnMe) {
                     mWaitOnMe.wait(9000);
                 }
-            }
-            catch (InterruptedException ie) {
+            } catch (InterruptedException ie) {
                 // Expecting this; interrupted should be false.
                 System.out.println(Thread.currentThread().getName() +
                         " interrupted, flag=" + Thread.interrupted());
                 intr = true;
-            }
-            catch (Exception ex) {
+            } catch (Exception ex) {
                 ex.printStackTrace();
             }
 
@@ -180,8 +171,7 @@
         } else {
             try {
                 Thread.sleep(2000);
-            }
-            catch (InterruptedException ie) {
+            } catch (InterruptedException ie) {
                 System.out.println("PESKY INTERRUPTED?");
             }
 
diff --git a/test/061-out-of-memory/src/Main.java b/test/061-out-of-memory/src/Main.java
index c04d41f..c812c81 100644
--- a/test/061-out-of-memory/src/Main.java
+++ b/test/061-out-of-memory/src/Main.java
@@ -43,18 +43,13 @@
     private static void testOomeLarge() {
         System.out.println("testOomeLarge beginning");
 
-        /* Just shy of the typical max heap size so that it will actually
-         * try to allocate it instead of short-circuiting.
-         *
-         * TODO: stop assuming the VM defaults to 64MB max
-         */
-        final int SIXTY_FOUR_MB = (64 * 1024 * 1024 - 32);
-
         Boolean sawEx = false;
-        byte a[];
+        byte[] a;
 
         try {
-            a = new byte[SIXTY_FOUR_MB];
+            // Just shy of the typical max heap size so that it will actually
+            // try to allocate it instead of short-circuiting.
+            a = new byte[(int) Runtime.getRuntime().maxMemory() - 32];
         } catch (OutOfMemoryError oom) {
             //Log.i(TAG, "HeapTest/OomeLarge caught " + oom);
             sawEx = true;
@@ -71,11 +66,8 @@
     /* Do this in another method so that the GC has a chance of freeing the
      * list afterwards.  Even if we null out list when we're done, the conservative
      * GC may see a stale pointer to it in a register.
-     *
-     * TODO: stop assuming the VM defaults to 64MB max
      */
     private static boolean testOomeSmallInternal() {
-        final int SIXTY_FOUR_MB = (64 * 1024 * 1024);
         final int LINK_SIZE = 6 * 4; // estimated size of a LinkedList's node
 
         LinkedList<Object> list = new LinkedList<Object>();
@@ -86,7 +78,7 @@
         while (objSize >= LINK_SIZE) {
             boolean sawEx = false;
             try {
-                for (int i = 0; i < SIXTY_FOUR_MB / objSize; i++) {
+                for (int i = 0; i < Runtime.getRuntime().maxMemory() / objSize; i++) {
                     list.add((Object)new byte[objSize]);
                 }
             } catch (OutOfMemoryError oom) {
diff --git a/test/068-classloader/src/FancyLoader.java b/test/068-classloader/src/FancyLoader.java
index 2c6fcde..5eb0249 100644
--- a/test/068-classloader/src/FancyLoader.java
+++ b/test/068-classloader/src/FancyLoader.java
@@ -53,7 +53,7 @@
         super(parent);
 
         try {
-            mDexClass = parent.loadClass("dalvik/system/DexFile");
+            mDexClass = parent.loadClass("dalvik.system.DexFile");
         } catch (ClassNotFoundException cnfe) {
             // ignore -- not running Dalvik
         }
diff --git a/test/070-nio-buffer/expected.txt b/test/070-nio-buffer/expected.txt
index e271001..ddb45af 100644
--- a/test/070-nio-buffer/expected.txt
+++ b/test/070-nio-buffer/expected.txt
@@ -1,3 +1,6 @@
+Direct byte buffer has array: true
 Got expected buffer overflow exception
 Got expected out-of-bounds exception
 Got expected buffer overflow exception
+00fbfb2ec03000001234567840490fd01122334455667788000000000000000100000000
+ccfb2efb30c0cccc78563412d00f494088776655443322110100000000000000cccccccc
diff --git a/test/070-nio-buffer/src/Main.java b/test/070-nio-buffer/src/Main.java
index bfcab3a..a7433b8 100644
--- a/test/070-nio-buffer/src/Main.java
+++ b/test/070-nio-buffer/src/Main.java
@@ -17,14 +17,21 @@
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
+import java.nio.LongBuffer;
 import java.nio.ShortBuffer;
 
 public class Main {
     public static void main(String[] args) {
-         intFloatTest();
-         basicShortTest();
+        ByteBuffer buf = ByteBuffer.allocateDirect(16);
+        System.out.println("Direct byte buffer has array: " + buf.hasArray());
+
+        intFloatTest();
+        basicShortTest();
+        primTest();
     }
 
     /*
@@ -94,4 +101,77 @@
         int1.put (data);
         int1.position (0);
     }
+
+    /*
+     * Exercise all "view buffer" classes, in both byte orders.
+     */
+    public static void primTest() {
+        ByteBuffer directBuf = ByteBuffer.allocateDirect(36);
+        directBuf.order(ByteOrder.BIG_ENDIAN);
+        storeValues(directBuf);
+
+        for (int i = 0; i < 36; i++) {
+            directBuf.put(i, (byte) 0xcc);
+        }
+
+        directBuf.order(ByteOrder.LITTLE_ENDIAN);
+        storeValues(directBuf);
+    }
+
+    static void storeValues(ByteBuffer directBuf) {
+        directBuf.position(0);
+        ShortBuffer shortBuf = directBuf.asShortBuffer();
+        CharBuffer charBuf = directBuf.asCharBuffer();
+        IntBuffer intBuf = directBuf.asIntBuffer();
+        FloatBuffer floatBuf = directBuf.asFloatBuffer();
+        LongBuffer longBuf = directBuf.asLongBuffer();
+        DoubleBuffer doubleBuf = directBuf.asDoubleBuffer();
+
+        final byte byteValue = -5;
+        final short shortValue = -1234;
+        final char charValue = 49200;
+        final int intValue = 0x12345678;
+        final float floatValue = 3.14159f;
+        final long longValue = 0x1122334455667788L;
+        final double doubleValue = Double.MIN_VALUE;
+
+        if (directBuf.put(1, byteValue).get(1) != byteValue) {
+            throw new RuntimeException("byte get/store failed");
+        }
+        if (shortBuf.put(1, shortValue).get(1) != shortValue) {
+            throw new RuntimeException("short get/store failed");
+        }
+        if (charBuf.put(2, charValue).get(2) != charValue) {
+            throw new RuntimeException("char get/store failed");
+        }
+        if (intBuf.put(2, intValue).get(2) != intValue) {
+            throw new RuntimeException("int get/store failed");
+        }
+        if (floatBuf.put(3, floatValue).get(3) != floatValue) {
+            throw new RuntimeException("float get/store failed");
+        }
+        if (longBuf.put(2, longValue).get(2) != longValue) {
+            throw new RuntimeException("long get/store failed");
+        }
+        if (doubleBuf.put(3, doubleValue).get(3) != doubleValue) {
+            throw new RuntimeException("double get/store failed");
+        }
+
+        directBuf.position(0);
+        char[] outBuf = new char[directBuf.limit() * 2];
+        for (int i = 0; i < directBuf.limit(); i++) {
+            byte b = directBuf.get();
+            outBuf[i*2] = hexChar((byte) ((b >> 4) & 0x0f));
+            outBuf[i*2+1] = hexChar((byte) (b & 0x0f));
+        }
+        System.out.println(new String(outBuf));
+    }
+
+    static char hexChar(byte b) {
+        if (b < 10) {
+            return (char) ('0' + b);
+        } else {
+            return (char) ('a' + b - 10);
+        }
+    }
 }
diff --git a/test/084-class-init/src/Main.java b/test/084-class-init/src/Main.java
index f777113..de28ed9 100644
--- a/test/084-class-init/src/Main.java
+++ b/test/084-class-init/src/Main.java
@@ -76,8 +76,8 @@
 
     static class FieldThread extends Thread {
         public void run() {
-            /* allow class init to start */
-            Main.sleep(200);
+            /* allow SlowInit's <clinit> to start */
+            Main.sleep(1000);
 
             /* collect fields; should delay until class init completes */
             int field0, field1, field2, field3;
@@ -87,7 +87,7 @@
             field3 = SlowInit.FIELD3.getValue();
 
             /* let MethodThread print first */
-            Main.sleep(400);
+            Main.sleep(5000);
             System.out.println("Fields (child thread): " +
                 field0 + field1 + field2 + field3);
         }
@@ -95,8 +95,8 @@
 
     static class MethodThread extends Thread {
         public void run() {
-            /* allow class init to start */
-            Main.sleep(200);
+            /* allow SlowInit's <clinit> to start */
+            Main.sleep(1000);
 
             /* use a method that shouldn't be accessible yet */
             SlowInit.printMsg("MethodThread message");
diff --git a/test/084-class-init/src/SlowInit.java b/test/084-class-init/src/SlowInit.java
index 8ac72be..f0c6919 100644
--- a/test/084-class-init/src/SlowInit.java
+++ b/test/084-class-init/src/SlowInit.java
@@ -32,7 +32,7 @@
         FIELD0.setValue(111);
         FIELD1.setValue(222);
         printMsg("SlowInit static block pre-sleep");
-        Main.sleep(600);
+        Main.sleep(4000);
         printMsg("SlowInit static block post-sleep");
         FIELD2.setValue(333);
         FIELD3.setValue(444);
diff --git a/test/086-null-super/src/Main.java b/test/086-null-super/src/Main.java
index 0b8b2f5..1109dec 100644
--- a/test/086-null-super/src/Main.java
+++ b/test/086-null-super/src/Main.java
@@ -76,7 +76,7 @@
                  * through reflection, then call loadCLass on it.
                  */
                 Class mDexClass = ClassLoader.getSystemClassLoader().
-                        loadClass("dalvik/system/DexFile");
+                        loadClass("dalvik.system.DexFile");
                 Constructor ctor = mDexClass.
                         getConstructor(new Class[] {String.class});
                 Object mDexFile = ctor.newInstance(DEX_FILE);
diff --git a/test/087-gc-after-link/src/Main.java b/test/087-gc-after-link/src/Main.java
index 12fa56a..b28542f 100644
--- a/test/087-gc-after-link/src/Main.java
+++ b/test/087-gc-after-link/src/Main.java
@@ -79,7 +79,7 @@
                      * through reflection, then call loadClass on it.
                      */
                     dexClass = ClassLoader.getSystemClassLoader().
-                            loadClass("dalvik/system/DexFile");
+                            loadClass("dalvik.system.DexFile");
                     Constructor ctor = dexClass.
                             getConstructor(new Class[] {String.class});
                     dexFile = ctor.newInstance(DEX_FILE);
diff --git a/test/092-locale/expected.txt b/test/092-locale/expected.txt
new file mode 100644
index 0000000..0a955e7
--- /dev/null
+++ b/test/092-locale/expected.txt
@@ -0,0 +1,12 @@
+USA(GMT): Sunday, January 1, 2012
+USA: first=1, name=Sunday
+France(GMT): Monday, January 2, 2012
+France: first=2, name=lundi
+USA dfs: [AM, PM]
+en_US: USD $2
+jp_JP: JPY ¥0
+Normalizer passed
+loc: en_US
+ iso3=eng
+loc: eng_USA
+ iso3=eng
diff --git a/test/092-locale/info.txt b/test/092-locale/info.txt
new file mode 100644
index 0000000..e3c3a98
--- /dev/null
+++ b/test/092-locale/info.txt
@@ -0,0 +1 @@
+Exercise some locale-specific classes.
diff --git a/test/092-locale/src/Main.java b/test/092-locale/src/Main.java
new file mode 100644
index 0000000..8916a29
--- /dev/null
+++ b/test/092-locale/src/Main.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.Normalizer;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Currency;
+import java.util.Date;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.TimeZone;
+
+/**
+ * Exercise some locale-table-driven stuff.
+ */
+public class Main {
+
+    public static void main(String[] args) {
+        try {
+            testCalendar();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+
+        try {
+            testDateFormatSymbols();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+
+        try {
+            testCurrency();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+
+        try {
+            testNormalizer();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+
+        try {
+            testIso3();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    static void testCalendar() {
+        TimeZone tz = TimeZone.getTimeZone("GMT");
+
+        Locale usa = new Locale("en", "US");
+        Calendar usaCal = Calendar.getInstance(tz, usa);
+        usaCal.clear();     // don't want current date/time
+        usaCal.set(2012, Calendar.JANUARY, 1);
+
+        Date when = usaCal.getTime();
+        DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, usa);
+        fmt.setTimeZone(tz);    // defaults to local TZ; force GMT
+        System.out.println("USA(" + fmt.getTimeZone().getID() + "): "
+            + fmt.format(when));
+
+        System.out.println("USA: first="
+            + usaCal.getFirstDayOfWeek() + ", name="
+            + usaCal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, usa));
+
+
+        Locale france = new Locale("fr", "FR");
+        Calendar franceCal = Calendar.getInstance(tz, france);
+        franceCal.clear();
+        franceCal.set(2012, Calendar.JANUARY, 2);
+
+        when = franceCal.getTime();
+        fmt = DateFormat.getDateInstance(DateFormat.FULL, usa);
+        fmt.setTimeZone(tz);    // defaults to local TZ; force GMT
+        System.out.println("France(" + fmt.getTimeZone().getID() + "): "
+            + fmt.format(when));
+
+        System.out.println("France: first="
+            + franceCal.getFirstDayOfWeek() + ", name="
+            + franceCal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, france));
+    }
+
+    static void testDateFormatSymbols() {
+        Locale usa = new Locale("en", "US");
+        DateFormatSymbols syms = DateFormatSymbols.getInstance(usa);
+        String[] list = syms.getAmPmStrings();
+        System.out.println("USA dfs: " + Arrays.deepToString(list));
+    }
+
+    static void testCurrency() {
+        Locale usa = new Locale("en", "US");
+        Currency dollars = Currency.getInstance(usa);
+
+        System.out.println(usa.toString() + ": " + dollars.toString()
+            + " " + dollars.getSymbol() + dollars.getDefaultFractionDigits());
+
+        Locale japan = new Locale("jp", "JP");
+        Currency yen = Currency.getInstance(japan);
+
+        System.out.println(japan.toString() + ": " + yen.toString()
+            + " " + yen.getSymbol() + yen.getDefaultFractionDigits());
+    }
+
+    static void testNormalizer() {
+        String composed = "Bl\u00c1ah";
+        String decomposed = "Bl\u0041\u0301ah";
+        String res;
+
+        res = Normalizer.normalize(composed, Normalizer.Form.NFD);
+        if (!decomposed.equals(res)) {
+            System.err.println("Bad decompose: '" + composed + "' --> '"
+                + res + "'");
+        }
+
+        res = Normalizer.normalize(decomposed, Normalizer.Form.NFC);
+        if (!composed.equals(res)) {
+            System.err.println("Bad compose: '" + decomposed + "' --> '"
+                + res + "'");
+        }
+
+        System.out.println("Normalizer passed");
+    }
+
+    /*
+     * Test that we can set and get an ISO3 language code.  Support for this
+     * is expected by the Android framework.
+     */
+    static void testIso3() {
+        Locale loc;
+        loc = new Locale("en", "US");
+        System.out.println("loc: " + loc);
+        System.out.println(" iso3=" + loc.getISO3Language());
+
+        loc = new Locale("eng", "USA");
+        System.out.println("loc: " + loc);
+        try {
+            System.out.println(" iso3=" + loc.getISO3Language());
+        } catch (MissingResourceException mre) {
+            System.err.println("couldn't get iso3 language");
+        }
+    }
+}
diff --git a/test/093-serialization/expected.txt b/test/093-serialization/expected.txt
new file mode 100644
index 0000000..60c64f8
--- /dev/null
+++ b/test/093-serialization/expected.txt
@@ -0,0 +1 @@
+one=true two=2 three=three four=4.0 five=5.0 six=6 seven=7 eight=8 nine=9 thing=X
diff --git a/test/093-serialization/info.txt b/test/093-serialization/info.txt
new file mode 100644
index 0000000..effe3d8
--- /dev/null
+++ b/test/093-serialization/info.txt
@@ -0,0 +1 @@
+Tests object serialization.
diff --git a/test/093-serialization/src/Main.java b/test/093-serialization/src/Main.java
new file mode 100644
index 0000000..ca3dc9f
--- /dev/null
+++ b/test/093-serialization/src/Main.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * Exercise serialization.
+ */
+public class Main {
+
+    public static void main(String[] args) {
+        testObjectSerialization();
+    }
+
+    static void testObjectSerialization() {
+        byte[] serialData;
+
+        try {
+            serialData = createStream();
+            checkStream(serialData);
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+
+    static byte[] createStream() throws IOException {
+        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+        ObjectOutputStream objStream = new ObjectOutputStream(byteStream);
+
+        Sub sub = new Sub('X');
+        objStream.writeObject(sub);
+        byte[] bytes = byteStream.toByteArray();
+
+        objStream.close();
+        byteStream.close();
+        return bytes;
+    }
+
+    static void checkStream(byte[] input) throws IOException {
+        ByteArrayInputStream byteStream = new ByteArrayInputStream(input);
+        ObjectInputStream objStream = new ObjectInputStream(byteStream);
+
+        Sub sub;
+        try {
+            sub = (Sub) objStream.readObject();
+        } catch (ClassNotFoundException cnfe) {
+            throw new RuntimeException(cnfe);
+        }
+
+        objStream.close();
+        byteStream.close();
+
+        sub.check();
+    }
+}
+
+class Base implements Serializable {
+    private static final long serialVersionUID = 12345;
+
+    Boolean one;
+    Integer two;
+    String three;
+
+    public Base() {
+        one = true;
+        two = Integer.valueOf(2);
+        three = "three";
+    }
+}
+
+class Sub extends Base {
+    private static final long serialVersionUID = 54321;
+
+    Double four;
+    Float five;
+    private Byte six = 26;
+    Character seven = '7';
+    Short eight;
+    long nine;
+    public Character thing;
+
+    public Sub(char thing) {
+        four = 4.0;
+        five = 5.0f;
+        six = 6;
+        eight = 8;
+        nine = 9;
+        this.thing = thing;
+    }
+
+    public void check() {
+        System.out.println("one=" + one + " two=" + two + " three=" + three
+            + " four=" + four + " five=" + five + " six=" + six
+            + " seven=" + seven + " eight=" + eight + " nine=" + nine
+            + " thing=" + thing);
+    }
+}
+
diff --git a/test/094-pattern/expected.txt b/test/094-pattern/expected.txt
new file mode 100644
index 0000000..4af0c66
--- /dev/null
+++ b/test/094-pattern/expected.txt
@@ -0,0 +1,3 @@
+str1 matches: true
+str2 matches: false
+str3 matches: true
diff --git a/test/094-pattern/info.txt b/test/094-pattern/info.txt
new file mode 100644
index 0000000..c1ade33
--- /dev/null
+++ b/test/094-pattern/info.txt
@@ -0,0 +1,4 @@
+A simple test to exercise pattern matching.
+
+The test may throw a StackOverflowError if the stack size is too small.  With
+some regex libs, -Xss65k is the minimum allowable size.
diff --git a/test/094-pattern/src/Main.java b/test/094-pattern/src/Main.java
new file mode 100644
index 0000000..4d7e1a3
--- /dev/null
+++ b/test/094-pattern/src/Main.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Main {
+    // from android.util.Patterns
+    public static final String GOOD_IRI_CHAR =
+        "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+
+    public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL =
+        "(?:"
+        + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
+        + "|(?:biz|b[abdefghijmnorstvwyz])"
+        + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
+        + "|d[ejkmoz]"
+        + "|(?:edu|e[cegrstu])"
+        + "|f[ijkmor]"
+        + "|(?:gov|g[abdefghilmnpqrstuwy])"
+        + "|h[kmnrtu]"
+        + "|(?:info|int|i[delmnoqrst])"
+        + "|(?:jobs|j[emop])"
+        + "|k[eghimnprwyz]"
+        + "|l[abcikrstuvy]"
+        + "|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])"
+        + "|(?:name|net|n[acefgilopruz])"
+        + "|(?:org|om)"
+        + "|(?:pro|p[aefghklmnrstwy])"
+        + "|qa"
+        + "|r[eosuw]"
+        + "|s[abcdeghijklmnortuvyz]"
+        + "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
+        + "|u[agksyz]"
+        + "|v[aceginu]"
+        + "|w[fs]"
+        + "|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)"
+        + "|y[et]"
+        + "|z[amw]))";
+
+    public static final String WEB_URL_STR =
+        "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+        + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+        + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+        + "((?:(?:[" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]{0,64}\\.)+"   // named host
+        + TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL
+        + "|(?:(?:25[0-5]|2[0-4]" // or ip address
+        + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
+        + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
+        + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+        + "|[1-9][0-9]|[0-9])))"
+        + "(?:\\:\\d{1,5})?)" // plus option port number
+        + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
+        + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+        + "(?:\\b|$)"; // and finally, a word boundary or end of
+                        // input.  This is to stop foo.sure from
+                        // matching as foo.su
+
+    public static final Pattern WEB_URL = Pattern.compile(WEB_URL_STR);
+
+    public static final String testStr1 =
+        "http://www.google.com/blah?client=tablet-android&source=android-home";
+    public static final String testStr2 = "http:///www.google.com/";
+    public static final String testStr3 =
+        "http://www.google.com/search?hl=en&redir_esc=&client=tablet-android-verizon&source=android-browser-type&v=141000000&qsubts=1327020479959&action=devloc&q=cnn";
+
+    public static void main(String[] args) {
+        System.out.println("str1 matches: " + WEB_URL.matcher(testStr1).matches());
+        System.out.println("str2 matches: " + WEB_URL.matcher(testStr2).matches());
+        System.out.println("str3 matches: " + WEB_URL.matcher(testStr3).matches());
+    }
+
+    static String getStringAsHex(String text) {
+        StringBuilder sb = new StringBuilder(text.length() * 4);
+
+        for (int i = 0; i < text.length(); i++) {
+            sb.append(Integer.toHexString((int) text.charAt(i)));
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index 99b8c12..ffb0bf6 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -90,11 +90,13 @@
 msg "------------------------------"
 
 if [ "$QUIET" = "n" ]; then
+  adb mkdir /data/art-test
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar /system/framework
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.oat /system/framework
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar /data/art-test
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.oat /data/art-test
 else
+  adb mkdir /data/art-test >/dev/null 2>&1
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.jar /data/art-test >/dev/null 2>&1
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME.oat /data/art-test >/dev/null 2>&1
   adb push ${ANDROID_PRODUCT_OUT}/data/art-test/$TEST_NAME-ex.jar /data/art-test >/dev/null 2>&1