changeset 15:800a2c2ff01d

fix bugs with access control
author jrose
date Mon, 08 Jun 2009 23:03:59 -0700
parents 1f748158f7ed
children bff20cf185b1
files netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java
diffstat 1 files changed, 109 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java	Thu Jun 04 20:51:51 2009 -0700
+++ b/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java	Mon Jun 08 23:03:59 2009 -0700
@@ -36,6 +36,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
@@ -68,6 +69,29 @@
     public MethodHandlesTest() {
     }
 
+    String testName;
+    int posTests, negTests;
+    @After
+    public void printCounts() {
+        if (verbosity >= 1 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
+            if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
+        }
+    }
+    void countTest(boolean positive) {
+        if (positive) ++posTests;
+        else          ++negTests;
+    }
+    void countTest() { countTest(true); }
+    void startTest(String name) {
+        if (testName != null)  printCounts();
+        if (verbosity >= 0)
+            System.out.println(name);
+        posTests = negTests = 0;
+        testName = name;
+    }
+
     @BeforeClass
     public static void setUpClass() throws Exception {
         calledLog.clear();
@@ -101,7 +125,8 @@
         assertEquals("previous method call", expected, actual);
     }
     static void printCalled(MethodHandle target, String name, Object... args) {
-        System.out.println("calling "+logEntry(name, args)+" on "+target);
+        if (verbosity >= 2)
+            System.out.println("calling "+logEntry(name, args)+" on "+target);
     }
 
     static int nextArg;
@@ -169,7 +194,7 @@
     // This lookup is good for package-private members but not private ones.
     static final Lookup PACKAGE = PackageSibling.lookup();
     // This lookup is good only for public members.
-    static final Lookup PUBLIC  = MethodHandles.Lookup.PUBLIC_LOOKUP;
+    static final Lookup PUBLIC  = MethodHandles.publicLookup();
 
     // Subject methods...
     static class Example implements IntExample {
@@ -216,6 +241,30 @@
         }
     }
 
+    static final Object[][][] ACCESS_CASES = {
+        { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE } },
+        { { false, PUBLIC }, { false, PACKAGE }, { true,  PRIVATE } },
+        { { false, PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE } },
+        { { true,  PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE } },
+    };
+
+    static Object[][] accessCases(Class<?> defc, String name) {
+        if (name.contains("pri_")) {
+            return ACCESS_CASES[1]; // PRIVATE only
+        } else if (name.contains("pkg_")) {
+            return ACCESS_CASES[2]; // not PUBLIC
+        } else {
+            assertTrue(name.indexOf('_') < 0);
+            boolean pubc = Modifier.isPublic(defc.getModifiers());
+            if (pubc)
+                return ACCESS_CASES[3]; // all access levels
+            return ACCESS_CASES[2]; // PACKAGE but not PUBLIC
+        }
+    }
+
+    // How much output?
+    static int verbosity = 1;
+
     // Set this true during development if you want to fast-forward to
     // a particular new, non-working test.  Tests which are known to
     // work (or have recently worked) test this flag and return on true.
@@ -229,7 +278,7 @@
     @Test
     public void testFindStatic() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("findStatic");
+        startTest("findStatic");
         testFindStatic(PubExample.class, void.class, "s0");
         testFindStatic(Example.class, void.class, "s0");
         testFindStatic(Example.class, void.class, "pkg_s0");
@@ -247,26 +296,15 @@
     }
 
     void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) {
-        if (name.contains("pri_")) {
-//            testFindStatic(false, PUBLIC, defc, ret, name, params);  // TO DO: disallow access
-//            testFindStatic(false, PACKAGE, defc, ret, name, params); // TO DO: disallow access
-            testFindStatic(       PRIVATE, defc, ret, name, params);
-        } else if (name.contains("pkg_")) {
-//            testFindStatic(false, PUBLIC, defc, ret, name, params);
-//            testFindStatic(      PACKAGE, defc, ret, name, params);
-            testFindStatic(      PRIVATE, defc, ret, name, params);
-        } else {
-            assertTrue(name.indexOf('_') < 0);
-            boolean pubc = Modifier.isPublic(defc.getModifiers());
-//            testFindStatic(pubc, PUBLIC,  defc, ret, name, params);
-//            testFindStatic(      PACKAGE, defc, ret, name, params);
-            testFindStatic(      PRIVATE, defc, ret, name, params);
+        for (Object[] ac : accessCases(defc, name)) {
+            testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
         }
     }
     void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
         testFindStatic(true, lookup, defc, ret, name, params);
     }
     void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
+        countTest(positive);
         MethodType type = MethodType.make(ret, params);
         MethodHandle target = null;
         RuntimeException noAccess = null;
@@ -275,8 +313,8 @@
         } catch (NoAccessException ex) {
             noAccess = ex;
         }
-        System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target
-                +(noAccess == null ? "" : " !! "+noAccess));
+//        System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target
+//                +(noAccess == null ? "" : " !! "+noAccess));
         if (positive && noAccess != null)  throw noAccess;
         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
         if (!positive)  return; // negative test failed as expected
@@ -293,7 +331,7 @@
     @Test
     public void testFindVirtual() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("findVirtual");
+        startTest("findVirtual");
         testFindVirtual(Example.class, void.class, "v0");
         testFindVirtual(Example.class, void.class, "pkg_v0");
         testFindVirtual(Example.class, void.class, "pri_v0");
@@ -318,26 +356,15 @@
         testFindVirtual(rcvc, defc, ret, name, params);
     }
     void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
-        if (name.contains("pri_")) {
-//            testFindVirtual(false, PUBLIC,  rcvc, defc, ret, name, params);
-//            testFindVirtual(false, PACKAGE, rcvc, defc, ret, name, params);
-            testFindVirtual(       PRIVATE, rcvc, defc, ret, name, params);
-        } else if (name.contains("pkg_")) {
-//            testFindVirtual(false, PUBLIC, rcvc, defc, ret, name, params);
-//            testFindVirtual(      PACKAGE, rcvc, defc, ret, name, params);
-            testFindVirtual(      PRIVATE, rcvc, defc, ret, name, params);
-        } else {
-            assertTrue(name.indexOf('_') < 0);
-//            boolean pubc = Modifier.isPublic(defc.getModifiers());
-//            testFindVirtual(pubc, PUBLIC,  rcvc, defc, ret, name, params);
-//            testFindVirtual(      PACKAGE, rcvc, defc, ret, name, params);
-            testFindVirtual(      PRIVATE, rcvc, defc, ret, name, params);
+        for (Object[] ac : accessCases(defc, name)) {
+            testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params);
         }
     }
     void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
         testFindVirtual(true, lookup, rcvc, defc, ret, name, params);
     }
     void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
+        countTest(positive);
         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
         MethodType type = MethodType.make(ret, params);
         MethodHandle target = null;
@@ -347,8 +374,8 @@
         } catch (NoAccessException ex) {
             noAccess = ex;
         }
-        System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target
-                +(noAccess == null ? "" : " !! "+noAccess));
+//        System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target
+//                +(noAccess == null ? "" : " !! "+noAccess));
         if (positive && noAccess != null)  throw noAccess;
         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
         if (!positive)  return; // negative test failed as expected
@@ -370,18 +397,20 @@
     @Test
     public void testFindSpecial() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("findSpecial");
+        startTest("findSpecial");
         testFindSpecial(Example.class, void.class, "v0");
         testFindSpecial(Example.class, void.class, "pkg_v0");
-        testFindSpecial(false, Example.class, void.class, "<init>", int.class);
-        testFindSpecial(false, Example.class, void.class, "bogus");
+        testFindSpecial(false, PRIVATE, Example.class, void.class, "<init>", int.class);
+        testFindSpecial(false, PRIVATE, Example.class, void.class, "bogus");
     }
 
     void testFindSpecial(Class<?> defc, Class<?> ret, String name, Class<?>... params) {
-        testFindSpecial(true, defc, ret, name, params);
+        testFindSpecial(true,  PRIVATE, defc, ret, name, params);
+        testFindSpecial(false, PACKAGE, defc, ret, name, params);
+        testFindSpecial(false, PUBLIC,  defc, ret, name, params);
     }
-    void testFindSpecial(boolean positive, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
-        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+    void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
+        countTest(positive);
         MethodType type = MethodType.make(ret, params);
         MethodHandle target = null;
         RuntimeException noAccess = null;
@@ -390,8 +419,8 @@
         } catch (NoAccessException ex) {
             noAccess = ex;
         }
-        System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target
-                +(noAccess == null ? "" : " !! "+noAccess));
+//        System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target
+//                +(noAccess == null ? "" : " !! "+noAccess));
         if (positive && noAccess != null)  throw noAccess;
         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
         if (!positive)  return; // negative test failed as expected
@@ -412,7 +441,7 @@
     @Test
     public void testBind() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("bind");
+        startTest("bind");
         testBind(Example.class, void.class, "v0");
         testBind(Example.class, void.class, "pkg_v0");
         testBind(Example.class, void.class, "pri_v0");
@@ -421,17 +450,20 @@
         testBind(Example.class, Object.class, "v2", Object.class, int.class);
         testBind(Example.class, Object.class, "v2", int.class, Object.class);
         testBind(Example.class, Object.class, "v2", int.class, int.class);
-        testBind(false, Example.class, void.class, "bogus");
+        testBind(false, PRIVATE, Example.class, void.class, "bogus");
         testBind(SubExample.class, void.class, "Sub/v0");
         testBind(SubExample.class, void.class, "Sub/pkg_v0");
         testBind(IntExample.Impl.class, void.class, "Int/v0");
     }
 
     void testBind(Class<?> defc, Class<?> ret, String name, Class<?>... params) {
-        testBind(true, defc, ret, name, params);
+        for (Object[] ac : accessCases(defc, name)) {
+            testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
+        }
     }
-    void testBind(boolean positive, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
-        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+
+    void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) {
+        countTest(positive);
         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
         MethodType type = MethodType.make(ret, params);
         Object receiver = randomArg(defc);
@@ -442,8 +474,8 @@
         } catch (NoAccessException ex) {
             noAccess = ex;
         }
-        System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
-                +(noAccess == null ? "" : " !! "+noAccess));
+//        System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
+//                +(noAccess == null ? "" : " !! "+noAccess));
         if (positive && noAccess != null)  throw noAccess;
         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
         if (!positive)  return; // negative test failed as expected
@@ -459,7 +491,7 @@
     @Test
     public void testUnreflect() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("unreflect");
+        startTest("unreflect");
         testUnreflect(Example.class, true, void.class, "s0");
         testUnreflect(Example.class, true, void.class, "pkg_s0");
         testUnreflect(Example.class, true, void.class, "pri_s0");
@@ -482,10 +514,12 @@
     }
 
     void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) {
-        testUnreflect(true, defc, isStatic, ret, name, params);
+        for (Object[] ac : accessCases(defc, name)) {
+            testUnreflect((Boolean)ac[0], (Lookup)ac[1], defc, isStatic, ret, name, params);
+        }
     }
-    void testUnreflect(boolean positive, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) {
-        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+    void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) {
+        countTest(positive);
         MethodType type = MethodType.make(ret, params);
         Method rmethod = null;
         MethodHandle target = null;
@@ -526,7 +560,7 @@
     @Test @Ignore("unimplemented")
     public void testUnreflectSpecial() {
         Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
-        System.out.println("unreflectSpecial");
+        startTest("unreflectSpecial");
         Method m = null;
         MethodHandle expResult = null;
         MethodHandle result = lookup.unreflectSpecial(m, Example.class);
@@ -537,7 +571,7 @@
     @Test @Ignore("unimplemented")
     public void testUnreflectGetter() {
         Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
-        System.out.println("unreflectGetter");
+        startTest("unreflectGetter");
         Field f = null;
         MethodHandle expResult = null;
         MethodHandle result = lookup.unreflectGetter(f);
@@ -548,7 +582,7 @@
     @Test @Ignore("unimplemented")
     public void testUnreflectSetter() {
         Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
-        System.out.println("unreflectSetter");
+        startTest("unreflectSetter");
         Field f = null;
         MethodHandle expResult = null;
         MethodHandle result = lookup.unreflectSetter(f);
@@ -558,7 +592,7 @@
 
     @Test @Ignore("unimplemented")
     public void testArrayElementGetter() {
-        System.out.println("arrayElementGetter");
+        startTest("arrayElementGetter");
         Class<?> arrayClass = null;
         MethodHandle expResult = null;
         MethodHandle result = MethodHandles.arrayElementGetter(arrayClass);
@@ -568,7 +602,7 @@
 
     @Test @Ignore("unimplemented")
     public void testArrayElementSetter() {
-        System.out.println("arrayElementSetter");
+        startTest("arrayElementSetter");
         Class<?> arrayClass = null;
         MethodHandle expResult = null;
         MethodHandle result = MethodHandles.arrayElementSetter(arrayClass);
@@ -606,7 +640,7 @@
     @Test
     public void testConvertArguments_pairwise() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("convertArguments/pairwise");
+        startTest("convertArguments/pairwise");
         testConvert(Callee.ofType(1), null, "id", int.class);
         testConvert(Callee.ofType(1), null, "id", String.class);
         testConvert(Callee.ofType(1), null, "id", Integer.class);
@@ -618,6 +652,7 @@
     }
 
     void testConvert(boolean positive, MethodHandle id, Class<?> rtype, String name, Class<?>... params) {
+        countTest(positive);
         MethodType idType = id.type();
         if (rtype == null)  rtype = idType.returnType();
         for (int i = 0; i < params.length; i++) {
@@ -657,15 +692,16 @@
         Object result = MethodHandles.invoke(target, args);
         assertCalled(name, convArgs);
         assertEquals(convResult, result);
-        //System.out.print(':');
+        System.out.print(':');
     }
 
     @Test
     public void testSpreadArguments() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("spreadArguments");
+        startTest("spreadArguments");
         for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
-            System.out.println("spreadArguments "+argType);
+            if (verbosity >= 2)
+                System.out.println("spreadArguments "+argType);
             for (int nargs = 0; nargs < 10; nargs++) {
                 if (argType == int.class && nargs >= 6)  continue; // FIXME Fail_1
                 testSpreadArguments(argType, nargs);
@@ -711,7 +747,7 @@
 
     @Test @Ignore("unimplemented")
     public void testCollectArguments() {
-        System.out.println("collectArguments");
+        startTest("collectArguments");
         MethodHandle target = null;
         MethodType newType = null;
         MethodHandle expResult = null;
@@ -723,7 +759,7 @@
     @Test
     public void testInsertArguments() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("insertArguments");
+        startTest("insertArguments");
         for (int nargs = 0; nargs <= 4; nargs++) {
             for (int ins = 0; ins <= 4; ins++) {
                 for (int pos = 0; pos <= nargs; pos++) {
@@ -754,7 +790,7 @@
     @Test @Ignore("in progress")
     public void testFoldArguments() {
         //if (CAN_SKIP_WORKING)  return;
-        System.out.println("foldArguments");
+        startTest("foldArguments");
         for (int nargs = 0; nargs <= 4; nargs++) {
             for (int fold = 0; fold <= 4; fold++) {
                 for (int pos = 0; pos <= nargs; pos++) {
@@ -787,7 +823,7 @@
     @Test
     public void testDropArguments() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("dropArguments");
+        startTest("dropArguments");
         for (int nargs = 0; nargs <= 4; nargs++) {
             for (int drop = 1; drop <= 4; drop++) {
                 for (int pos = 0; pos <= nargs; pos++) {
@@ -849,7 +885,7 @@
     @Test
     public void testGuardWithTest() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("guardWithTest");
+        startTest("guardWithTest");
         for (int nargs = 0; nargs <= 3; nargs++) {
             if (nargs != 2)  continue;  // FIXME: test more later
             testGuardWithTest(nargs, Object.class);
@@ -886,7 +922,8 @@
             default:  equals = argList[0].equals(argList[1]); break;
             }
             String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
-            System.out.println(logEntry(willCall, argList));
+            if (verbosity >= 2)
+                System.out.println(logEntry(willCall, argList));
             Object result = MethodHandles.invoke(mh, argList);
             assertCalled(willCall, argList);
         }
@@ -895,7 +932,7 @@
     @Test
     public void testCatchException() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("catchException");
+        startTest("catchException");
         for (int nargs = 2; nargs <= 6; nargs++) {
             for (int ti = 0; ti <= 1; ti++) {
                 boolean throwIt = (ti != 0);
@@ -940,7 +977,7 @@
     @Test
     public void testThrowException() {
         if (CAN_SKIP_WORKING)  return;
-        System.out.println("throwException");
+        startTest("throwException");
         testThrowException(int.class, new ClassCastException("testing"));
         testThrowException(void.class, new java.io.IOException("testing"));
         testThrowException(String.class, new LinkageError("testing"));