Adding old unit tests to test suite.

These tests are copied straight over. They'll still run, but they're
using the old system.

Change-Id: If494519e52ddf858a9febfc55bdae830468cb3c8
diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected.txt
new file mode 100644
index 0000000..4be26cf
--- /dev/null
+++ b/test/044-proxy/expected.txt
@@ -0,0 +1,80 @@
+Invoke public abstract void Shapes.circle(int)
+ 0: 3
+--- circle 3
+Success: method circle res=null
+Invoke public abstract int Quads.rectangle(int,int)
+ 0: 10
+ 1: 20
+--- rectangle 10,20
+Success: method rectangle res=4
+Invoke public abstract java.lang.String Shapes.blob()
+ (no args)
+--- blob
+Success: method blob res=mix
+Invoke public abstract int Quads.rectangle(int,int)
+ 0: 15
+ 1: 25
+--- rectangle 15,25
+Success: method rectangle res=4
+Invoke public abstract int Quads.trapezoid(int,double,int)
+ 0: 6
+ 1: 81.18
+ 2: 4
+--- trap 6,4,81.18
+Success: method trapezoid res=8
+Invoke public abstract int Colors.red(float)
+ 0: 1.0
+--- red 1.0
+Success: method red res=0
+Invoke public abstract double Colors.blue(int)
+ 0: 777
+--- blue 777
+Success: method blue res=2.54
+Invoke public abstract int Colors.mauve(java.lang.String)
+ 0: sorry
+--- mauve sorry
+Success: method mauve res=3
+Invoke public abstract java.lang.String Shapes.blob()
+ (no args)
+--- blob
+Success: method blob res=mix
+Invoke public abstract void Shapes.upChuck()
+ (no args)
+Got expected ioobe
+Invoke public abstract void Shapes.upCheck() throws java.lang.InterruptedException
+ (no args)
+Got expected ie
+
+Proxy methods: [public native boolean $Proxy0.equals(java.lang.Object), public native int $Proxy0.hashCode(), public native java.lang.String $Proxy0.toString(), public native int $Proxy0.rectangle(int,int), public native int $Proxy0.square(int,int), public native int $Proxy0.trapezoid(int,double,int), public native java.lang.String $Proxy0.blob(), public native void $Proxy0.circle(int), public native void $Proxy0.upCheck(), public native void $Proxy0.upChuck(), public native double $Proxy0.blue(int), public native R0aa $Proxy0.checkMe(), public native int $Proxy0.green(double), public native int $Proxy0.mauve(java.lang.String), public native int $Proxy0.red(float)]
+Decl annos: []
+Param annos (1) : [[]]
+Proxy fields: [private static java.lang.Throwable[][] $Proxy0.throws]
+Dupe threw expected exception
+Clash threw expected exception
+Clash2 threw expected exception
+Clash3 threw expected exception
+Clash4 threw expected exception
+Invoke public abstract void InterfaceW1.throwFunky()
+ (no args)
+Got expected UTE
+Invoke public abstract void InterfaceW1.throwFunky2() throws BaseException,java.lang.NoSuchMethodException,java.io.IOException
+ (no args)
+Got expected IOE
+Invoke public abstract void InterfaceW1.throwFunky2() throws BaseException,java.lang.NoSuchMethodException,java.io.IOException
+ (no args)
+Got expected IOE
+Invoke public abstract void InterfaceW1.throwException() throws BaseException
+ (no args)
+Got expected UTE
+Invoke public abstract void InterfaceW1.throwBase() throws BaseException
+ (no args)
+Got expected UTE
+Invoke public abstract void InterfaceW1.throwSub() throws BaseException
+ (no args)
+Got expected exception
+Invoke public abstract void InterfaceW1.throwSubSub() throws BaseException
+ (no args)
+Got expected exception
+Invoke public abstract void InterfaceW1.bothThrowBase() throws BaseException,SubException,SubSubException
+ (no args)
+Got expected exception
diff --git a/test/044-proxy/info.txt b/test/044-proxy/info.txt
new file mode 100644
index 0000000..08127da
--- /dev/null
+++ b/test/044-proxy/info.txt
@@ -0,0 +1,6 @@
+This is a miscellaneous test that was imported into the new-at-the-time
+runtime test framework. The test is intended to exercise basic features,
+and as such cannot be build on top of junit, since failure of such basic
+features might disrupt junit.
+
+TODO: Real description goes here.
diff --git a/test/044-proxy/src/BasicTest.java b/test/044-proxy/src/BasicTest.java
new file mode 100644
index 0000000..2a453c4
--- /dev/null
+++ b/test/044-proxy/src/BasicTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+
+/**
+ * Do some basic tests.
+ */
+public class BasicTest {
+
+    public static void main(String[] args) {
+        Mix proxyMe = new Mix();
+        Object proxy = createProxy(proxyMe);
+
+        if (!Proxy.isProxyClass(proxy.getClass()))
+            System.err.println("not a proxy class?");
+        if (Proxy.getInvocationHandler(proxy) == null)
+            System.err.println("ERROR: Proxy.getInvocationHandler is null");
+
+        /* take it for a spin; verifies instanceof constraint */
+        Shapes shapes = (Shapes) proxy;
+        shapes.circle(3);
+        shapes.rectangle(10, 20);
+        shapes.blob();
+        Quads quads = (Quads) proxy;
+        quads.rectangle(15, 25);
+        quads.trapezoid(6, 81.18, 4);
+        Colors colors = (Colors) proxy;
+        colors.red(1.0f);
+        colors.blue(777);
+        colors.mauve("sorry");
+        colors.blob();
+
+        try {
+            shapes.upChuck();
+            System.out.println("Didn't get expected exception");
+        } catch (IndexOutOfBoundsException ioobe) {
+            System.out.println("Got expected ioobe");
+        }
+        try {
+            shapes.upCheck();
+            System.out.println("Didn't get expected exception");
+        } catch (InterruptedException ie) {
+            System.out.println("Got expected ie");
+        }
+
+        /*
+         * Exercise annotations on Proxy classes.  This is mostly to ensure
+         * that annotation calls work correctly on generated classes.
+         */
+        System.out.println("");
+        Method[] methods = proxy.getClass().getDeclaredMethods();
+        System.out.println("Proxy methods: " + Arrays.deepToString(methods));
+        Method meth = methods[methods.length -1];
+        System.out.println("Decl annos: " + Arrays.deepToString(meth.getDeclaredAnnotations()));
+        Annotation[][] paramAnnos = meth.getParameterAnnotations();
+        System.out.println("Param annos (" + paramAnnos.length + ") : "
+            + Arrays.deepToString(paramAnnos));
+        Field[] fields = proxy.getClass().getDeclaredFields();
+        System.out.println("Proxy fields: " + Arrays.deepToString(fields));
+    }
+
+    static Object createProxy(Object proxyMe) {
+        /* declare an object that will handle the method calls */
+        InvocationHandler handler = new MyInvocationHandler(proxyMe);
+
+        /* create the proxy class */
+        Class proxyClass = Proxy.getProxyClass(Shapes.class.getClassLoader(),
+                            new Class[] { Quads.class, Colors.class });
+
+        /* create a proxy object, passing the handler object in */
+        Object proxy = null;
+        try {
+            Constructor<Class> cons;
+            cons = proxyClass.getConstructor(
+                            new Class[] { InvocationHandler.class });
+            //System.out.println("Constructor is " + cons);
+            proxy = cons.newInstance(new Object[] { handler });
+        } catch (NoSuchMethodException nsme) {
+            System.err.println("failed: " + nsme);
+        } catch (InstantiationException ie) {
+            System.err.println("failed: " + ie);
+        } catch (IllegalAccessException ie) {
+            System.err.println("failed: " + ie);
+        } catch (InvocationTargetException ite) {
+            System.err.println("failed: " + ite);
+        }
+
+        return proxy;
+    }
+}
+
+/*
+ * Some interfaces.
+ */
+interface Shapes {
+    public void circle(int r);
+    public int rectangle(int x, int y);
+
+    public String blob();
+
+    public R0base checkMe();
+    public void upChuck();
+    public void upCheck() throws InterruptedException;
+}
+
+interface Quads extends Shapes {
+    public int rectangle(int x, int y);
+    public int square(int x, int y);
+    public int trapezoid(int x, double off, int y);
+
+    public R0a checkMe();
+}
+
+/*
+ * More interfaces.
+ */
+interface Colors {
+    public int red(float howRed);
+    public int green(double howGreen);
+    public double blue(int howBlue);
+    public int mauve(String apology);
+
+    public String blob();
+
+    public R0aa checkMe();
+}
+
+/*
+ * Some return types.
+ */
+class R0base { int mBlah;  }
+class R0a extends R0base { int mBlah_a;  }
+class R0aa extends R0a { int mBlah_aa;  }
+
+
+/*
+ * A class that implements them all.
+ */
+class Mix implements Quads, Colors {
+    public void circle(int r) {
+        System.out.println("--- circle " + r);
+    }
+    public int rectangle(int x, int y) {
+        System.out.println("--- rectangle " + x + "," + y);
+        return 4;
+    }
+    public int square(int x, int y) {
+        System.out.println("--- square " + x + "," + y);
+        return 4;
+    }
+    public int trapezoid(int x, double off, int y) {
+        System.out.println("--- trap " + x + "," + y + "," + off);
+        return 8;
+    }
+    public String blob() {
+        System.out.println("--- blob");
+        return "mix";
+    }
+
+    public int red(float howRed) {
+        System.out.println("--- red " + howRed);
+        return 0;
+    }
+    public int green(double howGreen) {
+        System.out.println("--- green " + howGreen);
+        return 1;
+    }
+    public double blue(int howBlue) {
+        System.out.println("--- blue " + howBlue);
+        return 2.54;
+    }
+    public int mauve(String apology) {
+        System.out.println("--- mauve " + apology);
+        return 3;
+    }
+
+    public R0aa checkMe() {
+        return null;
+    }
+    public void upChuck() {
+        throw new IndexOutOfBoundsException("upchuck");
+    }
+    public void upCheck() throws InterruptedException {
+        throw new InterruptedException("upcheck");
+    }
+}
+
+/*
+ * Invocation handler, defining the implementation of the proxy functions.
+ */
+class MyInvocationHandler implements InvocationHandler {
+    Object mObj;
+
+    public MyInvocationHandler(Object obj) {
+        mObj = obj;
+    }
+
+    /*
+     * This is called when anything gets invoked in the proxy object.
+     */
+    public Object invoke(Object proxy, Method method, Object[] args)
+        throws Throwable {
+
+        Object result = null;
+
+        // Trap Object calls.  This is important here to avoid a recursive
+        // invocation of toString() in the print statements below.
+        if (method.getDeclaringClass() == java.lang.Object.class) {
+            //System.out.println("!!! object " + method.getName());
+            if (method.getName().equals("toString"))
+                return super.toString();
+            else if (method.getName().equals("hashCode"))
+                return Integer.valueOf(super.hashCode());
+            else if (method.getName().equals("equals"))
+                return Boolean.valueOf(super.equals(args[0]));
+            else
+                throw new RuntimeException("huh?");
+        }
+
+        System.out.println("Invoke " + method);
+        if (args == null || args.length == 0) {
+            System.out.println(" (no args)");
+        } else {
+            for (int i = 0; i < args.length; i++)
+                System.out.println(" " + i + ": " + args[i]);
+        }
+
+        try {
+            if (true)
+                result = method.invoke(mObj, args);
+            else
+                result = -1;
+            System.out.println("Success: method " + method.getName()
+                + " res=" + result);
+        } catch (InvocationTargetException ite) {
+            throw ite.getTargetException();
+        } catch (IllegalAccessException iae) {
+            throw new RuntimeException(iae);
+        }
+        return result;
+    }
+}
diff --git a/test/044-proxy/src/Clash.java b/test/044-proxy/src/Clash.java
new file mode 100644
index 0000000..adeffdc
--- /dev/null
+++ b/test/044-proxy/src/Clash.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/*
+ * Try to instantiate a proxy class with interfaces that have conflicting
+ * duplicate methods (primitive vs. object).
+ */
+public class Clash {
+    public static void main(String[] args) {
+        InvocationHandler handler = new ClashInvocationHandler();
+
+        /* try passing in the same interface twice */
+        try {
+            Proxy.newProxyInstance(Clash.class.getClassLoader(),
+                new Class[] { Interface1A.class, Interface1A.class },
+                handler);
+            System.err.println("Dupe did not throw expected exception");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Dupe threw expected exception");
+        }
+
+        try {
+            Proxy.newProxyInstance(Clash.class.getClassLoader(),
+                new Class[] { Interface1A.class, Interface1B.class },
+                handler);
+            System.err.println("Clash did not throw expected exception");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Clash threw expected exception");
+        }
+    }
+}
+
+interface Interface1A {
+    public int thisIsOkay();
+
+    public float thisIsTrouble();
+}
+
+interface Interface1B {
+    public int thisIsOkay();
+
+    public Object thisIsTrouble();
+}
+
+class ClashInvocationHandler implements InvocationHandler {
+    /* don't really need to do anything -- should never get this far */
+    public Object invoke(Object proxy, Method method, Object[] args)
+        throws Throwable {
+
+        return null;
+    }
+}
diff --git a/test/044-proxy/src/Clash2.java b/test/044-proxy/src/Clash2.java
new file mode 100644
index 0000000..2a384f4
--- /dev/null
+++ b/test/044-proxy/src/Clash2.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/*
+ * Try to instantiate a proxy class with interfaces that have conflicting
+ * duplicate methods (primitive types).
+ */
+public class Clash2 {
+    public static void main(String[] args) {
+        InvocationHandler handler = new Clash2InvocationHandler();
+
+        try {
+            Proxy.newProxyInstance(Clash.class.getClassLoader(),
+                new Class[] { Interface2A.class, Interface2B.class },
+                handler);
+            System.err.println("Clash2 did not throw expected exception");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Clash2 threw expected exception");
+        }
+    }
+}
+
+interface Interface2A {
+    public int thisIsOkay();
+
+    public int thisIsTrouble();
+}
+
+interface Interface2B {
+    public int thisIsOkay();
+
+    public short thisIsTrouble();
+}
+
+class Clash2InvocationHandler implements InvocationHandler {
+    /* don't really need to do anything -- should never get this far */
+    public Object invoke(Object proxy, Method method, Object[] args)
+        throws Throwable {
+
+        return null;
+    }
+}
diff --git a/test/044-proxy/src/Clash3.java b/test/044-proxy/src/Clash3.java
new file mode 100644
index 0000000..6d6f2f2
--- /dev/null
+++ b/test/044-proxy/src/Clash3.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/*
+ * Try to instantiate a proxy class with interfaces that have conflicting
+ * duplicate methods (type tree with interface).
+ */
+public class Clash3 {
+    public static void main(String[] args) {
+        InvocationHandler handler = new Clash3InvocationHandler();
+
+        try {
+            Proxy.newProxyInstance(Clash.class.getClassLoader(),
+                new Class[] {
+                    Interface3a.class,
+                    Interface3base.class,
+                    Interface3aa.class,
+                    Interface3b.class },
+                handler);
+            System.err.println("Clash3 did not throw expected exception");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Clash3 threw expected exception");
+        }
+    }
+}
+
+class R3base implements I3 { int mBlah; public void x() {} }
+class R3a extends R3base { int mBlah_a;  }
+class R3aa extends R3a { int mBlah_aa;  }
+class R3b implements I3 { int mBlah_b; public void x() {} }
+
+interface I3 {
+    void x();
+}
+
+interface Interface3base {
+    public R3base thisIsTrouble();
+}
+
+interface Interface3a {
+    public R3a thisIsTrouble();
+}
+interface Interface3aa {
+    public R3aa thisIsTrouble();
+}
+interface Interface3b {
+    public R3b thisIsTrouble();
+}
+
+class Clash3InvocationHandler implements InvocationHandler {
+    /* don't really need to do anything -- should never get this far */
+    public Object invoke(Object proxy, Method method, Object[] args)
+        throws Throwable {
+
+        return null;
+    }
+}
diff --git a/test/044-proxy/src/Clash4.java b/test/044-proxy/src/Clash4.java
new file mode 100644
index 0000000..1bfb37f
--- /dev/null
+++ b/test/044-proxy/src/Clash4.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/*
+ * Try to instantiate a proxy class with interfaces that have conflicting
+ * duplicate methods (tree of types).
+ */
+public class Clash4 {
+    public static void main(String[] args) {
+        InvocationHandler handler = new Clash4InvocationHandler();
+
+        try {
+            Proxy.newProxyInstance(Clash.class.getClassLoader(),
+                new Class[] {
+                    Interface4a.class,
+                    Interface4aa.class,
+                    Interface4base.class,
+                    Interface4b.class,
+                    Interface4bb.class },
+                handler);
+            System.err.println("Clash4 did not throw expected exception");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Clash4 threw expected exception");
+            //System.out.println(iae);
+        }
+    }
+}
+
+class R4base { int mBlah;  }
+class R4a extends R4base { int mBlah_a;  }
+class R4aa extends R4a { int mBlah_aa;  }
+class R4b extends R4base { int mBlah_b;  }
+class R4bb extends R4b { int mBlah_bb;  }
+
+interface Interface4base {
+    public R4base thisIsTrouble();
+}
+
+interface Interface4a {
+    public R4a thisIsTrouble();
+}
+interface Interface4aa {
+    public R4aa thisIsTrouble();
+}
+interface Interface4b {
+    public R4b thisIsTrouble();
+}
+interface Interface4bb {
+    public R4bb thisIsTrouble();
+}
+
+class Clash4InvocationHandler implements InvocationHandler {
+    /* don't really need to do anything -- should never get this far */
+    public Object invoke(Object proxy, Method method, Object[] args)
+        throws Throwable {
+
+        return null;
+    }
+}
diff --git a/test/044-proxy/src/Main.java b/test/044-proxy/src/Main.java
new file mode 100644
index 0000000..01926af
--- /dev/null
+++ b/test/044-proxy/src/Main.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Test java.lang.reflect.Proxy
+ */
+public class Main {
+    public static void main(String[] args) {
+        BasicTest.main(null);
+        Clash.main(null);
+        Clash2.main(null);
+        Clash3.main(null);
+        Clash4.main(null);
+        WrappedThrow.main(null);
+    }
+}
diff --git a/test/044-proxy/src/WrappedThrow.java b/test/044-proxy/src/WrappedThrow.java
new file mode 100644
index 0000000..27ae84e
--- /dev/null
+++ b/test/044-proxy/src/WrappedThrow.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+
+/*
+ * Create a Proxy class that blah.
+ */
+public class WrappedThrow {
+    public static void main(String[] args) {
+        WTMix mix = new WTMix();
+        InvocationHandler handler = new WTInvocationHandler(mix);
+        Object proxy;
+
+        try {
+            proxy = Proxy.newProxyInstance(WrappedThrow.class.getClassLoader(),
+                new Class[] { InterfaceW1.class, InterfaceW2.class },
+                handler);
+        } catch (IllegalArgumentException iae) {
+            System.out.println("WT init failed");
+            return;
+        }
+
+        InterfaceW1 if1 = (InterfaceW1) proxy;
+        InterfaceW2 if2 = (InterfaceW2) proxy;
+        try {
+            if1.throwFunky();
+            System.err.println("No exception thrown");
+        } catch (UndeclaredThrowableException ute) {
+            System.out.println("Got expected UTE");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        try {
+            if1.throwFunky2();
+            System.err.println("No exception thrown");
+        } catch (IOException ioe) {
+            System.out.println("Got expected IOE");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        try {
+            if2.throwFunky2();
+            System.err.println("No exception thrown");
+        } catch (IOException ioe) {
+            System.out.println("Got expected IOE");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        /*
+         * Throw exceptions, walking down the hierarchy.
+         */
+        try {
+            if1.throwException();
+            System.err.println("No exception thrown");
+        } catch (UndeclaredThrowableException ute) {
+            System.out.println("Got expected UTE");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        try {
+            if1.throwBase();
+            System.err.println("No exception thrown");
+        } catch (UndeclaredThrowableException ute) {
+            System.out.println("Got expected UTE");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        try {
+            if2.throwSub();
+            System.err.println("No exception thrown");
+        } catch (SubException se) {
+            System.out.println("Got expected exception");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        try {
+            if2.throwSubSub();
+            System.err.println("No exception thrown");
+        } catch (SubException se) {
+            System.out.println("Got expected exception");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+
+        /*
+         * Make sure that, if the class explicitly allows the base
+         * class of an exception, that we still allow it.
+         */
+        try {
+            if1.bothThrowBase();
+            System.err.println("No exception thrown");
+        } catch (BaseException se) {
+            System.out.println("Got expected exception");
+        } catch (Throwable t) {
+            System.err.println("Got unexpected exception: " + t);
+        }
+    }
+}
+
+class BaseException extends Exception {}
+class SubException extends BaseException {}
+class SubSubException extends SubException {}
+
+interface InterfaceW1 {
+    public void throwFunky();
+
+    public void throwFunky2() throws BaseException,
+           NoSuchMethodException, IOException;
+
+    public void throwException() throws BaseException;
+    public void throwBase() throws BaseException;
+    public void throwSub() throws BaseException;
+    public void throwSubSub() throws BaseException;
+
+    public void bothThrowBase() throws BaseException, SubException, SubSubException;
+}
+
+interface InterfaceW2 {
+    public void throwFunky2() throws InterruptedException,
+           NoSuchMethodException, IOException;
+
+    public void throwException() throws SubException;
+    public void throwBase() throws SubException;
+    public void throwSub() throws SubException;
+    public void throwSubSub() throws SubException;
+
+    public void bothThrowBase() throws SubException, BaseException, SubSubException;
+}
+
+/**
+ * Implement all of the proxied interfaces.
+ */
+class WTMix implements InterfaceW1, InterfaceW2 {
+    public int dastardlyDeed() throws SubException {
+        System.out.println("Throwing SubException");
+        throw new SubException();
+    }
+
+    /* these don't actually get called; they just cause exceptions */
+    public void throwFunky() {}
+    public void throwFunky2() {}
+    public void throwException() throws SubException {}
+    public void throwBase() throws SubException {}
+    public void throwSub() throws SubException {}
+    public void throwSubSub() throws SubException {}
+
+    public void bothThrowBase() throws BaseException, SubException {}
+}
+
+/**
+ * Invocation handler for our proxy class.
+ */
+class WTInvocationHandler implements InvocationHandler {
+    private Object mObj;
+
+    public WTInvocationHandler(Object obj) {
+        mObj = obj;
+    }
+
+    /*
+     * This is called when anything gets invoked in the proxy object.
+     */
+    public Object invoke(Object proxy, Method method, Object[] args)
+        throws Throwable {
+
+        Object result = null;
+
+        // Trap Object calls.  This is important here to avoid a recursive
+        // invocation of toString() in the print statements below.
+        if (method.getDeclaringClass() == java.lang.Object.class) {
+            //System.out.println("!!! object " + method.getName());
+            if (method.getName().equals("toString"))
+                return super.toString();
+            else if (method.getName().equals("hashCode"))
+                return Integer.valueOf(super.hashCode());
+            else if (method.getName().equals("equals"))
+                return Boolean.valueOf(super.equals(args[0]));
+            else
+                throw new RuntimeException("huh?");
+        }
+
+        System.out.println("Invoke " + method);
+        if (args == null || args.length == 0) {
+            System.out.println(" (no args)");
+        } else {
+            for (int i = 0; i < args.length; i++)
+                System.out.println(" " + i + ": " + args[i]);
+        }
+
+        try {
+            if (method.getName().equals("throwFunky"))
+                throw new InterruptedException("fake");
+            if (method.getName().equals("throwFunky2"))
+                throw new IOException("fake2");
+            if (method.getName().equals("throwException"))
+                throw new Exception();
+            if (method.getName().equals("throwBase"))
+                throw new BaseException();
+            if (method.getName().equals("throwSub"))
+                throw new SubException();
+            if (method.getName().equals("throwSubSub"))
+                throw new SubSubException();
+            if (method.getName().equals("bothThrowBase"))
+                throw new BaseException();
+
+            if (true)
+                result = method.invoke(mObj, args);
+            else
+                result = -1;
+            System.out.println("Success: method " + method.getName()
+                + " res=" + result);
+        } catch (InvocationTargetException ite) {
+            throw ite.getTargetException();
+        } catch (IllegalAccessException iae) {
+            throw new RuntimeException(iae);
+        }
+        return result;
+    }
+}