aboutsummaryrefslogtreecommitdiff
path: root/test/java/lang
diff options
context:
space:
mode:
authordfuchs <none@none>2014-12-19 20:04:14 +0100
committerdfuchs <none@none>2014-12-19 20:04:14 +0100
commit6b31b6e63080071e26aa9640c685049885c222a3 (patch)
tree1a4f472f260e56828fd6ad8b077980d6dcf7ad58 /test/java/lang
parentb082d869e851a7afb2b7d4d47ca206e0dbc19460 (diff)
downloadjdk8u_jdk-6b31b6e63080071e26aa9640c685049885c222a3.tar.gz
8066612: Add a test that will call getDeclaredFields() on all classes and try to set them accessible.
Summary: This test parses the jars in the boot class path to find the name of all classes, then loads each of them, get their declared fields, and attempt to call setAccessible. Reviewed-by: coffeys, dholmes, plevart
Diffstat (limited to 'test/java/lang')
-rw-r--r--test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java405
1 files changed, 405 insertions, 0 deletions
diff --git a/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java b/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
new file mode 100644
index 0000000000..504dcb4568
--- /dev/null
+++ b/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.ReflectPermission;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.PropertyPermission;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+
+/**
+ * @test
+ * @bug 8065552
+ * @summary test that all fields returned by getDeclaredFields() can be
+ * set accessible if the right permission is granted; this test
+ * loads all the classes in the BCL, get their declared fields,
+ * and call setAccessible(false) followed by setAccessible(true);
+ * @run main/othervm FieldSetAccessibleTest UNSECURE
+ * @run main/othervm FieldSetAccessibleTest SECURE
+ *
+ * @author danielfuchs
+ */
+public class FieldSetAccessibleTest {
+
+ static final List<String> skipped = new ArrayList<>();
+ static final List<String> cantread = new ArrayList<>();
+ static final List<String> failed = new ArrayList<>();
+ static final AtomicLong classCount = new AtomicLong();
+ static final AtomicLong fieldCount = new AtomicLong();
+ static long startIndex = 0;
+ static long maxSize = Long.MAX_VALUE;
+ static long maxIndex = Long.MAX_VALUE;
+
+
+ // Test that all fields for any given class can be made accessibles
+ static void testSetFieldsAccessible(Class<?> c) {
+ for (Field f : c.getDeclaredFields()) {
+ fieldCount.incrementAndGet();
+ f.setAccessible(false);
+ f.setAccessible(true);
+ }
+ }
+
+ // Performs a series of test on the given class.
+ // At this time, we only call testSetFieldsAccessible(c)
+ public static boolean test(Class<?> c) {
+ //System.out.println(c.getName());
+ classCount.incrementAndGet();
+
+ // Call getDeclaredFields() and try to set their accessible flag.
+ testSetFieldsAccessible(c);
+
+ // add more tests here...
+
+ return c == Class.class;
+ }
+
+ // Prints a summary at the end of the test.
+ static void printSummary(long secs, long millis, long nanos) {
+ System.out.println("Tested " + fieldCount.get() + " fields of "
+ + classCount.get() + " classes in "
+ + secs + "s " + millis + "ms " + nanos + "ns");
+ }
+
+
+ /**
+ * @param args the command line arguments:
+ *
+ * SECURE|UNSECURE [startIndex (default=0)] [maxSize (default=Long.MAX_VALUE)]
+ *
+ * @throws java.lang.Exception if the test fails
+ */
+ public static void main(String[] args) throws Exception {
+ if (args == null || args.length == 0) {
+ args = new String[] {"SECURE", "0"};
+ } else if (args.length > 3) {
+ throw new RuntimeException("Expected at most one argument. Found "
+ + Arrays.asList(args));
+ }
+ try {
+ if (args.length > 1) {
+ startIndex = Long.parseLong(args[1]);
+ if (startIndex < 0) {
+ throw new IllegalArgumentException("startIndex args[1]: "
+ + startIndex);
+ }
+ }
+ if (args.length > 2) {
+ maxSize = Long.parseLong(args[2]);
+ if (maxSize <= 0) {
+ maxSize = Long.MAX_VALUE;
+ }
+ maxIndex = (Long.MAX_VALUE - startIndex) < maxSize
+ ? Long.MAX_VALUE : startIndex + maxSize;
+ }
+ TestCase.valueOf(args[0]).run();
+ } catch (OutOfMemoryError oome) {
+ System.err.println(classCount.get());
+ throw oome;
+ }
+ }
+
+ public static void run(TestCase test) {
+ System.out.println("Testing " + test);
+ test(listAllClassNames());
+ System.out.println("Passed " + test);
+ }
+
+ static Iterable<String> listAllClassNames() {
+ return new ClassNameStreamBuilder();
+ }
+
+ static void test(Iterable<String> iterable) {
+ final long start = System.nanoTime();
+ boolean classFound = false;
+ int index = 0;
+ for (String s: iterable) {
+ if (index == maxIndex) break;
+ try {
+ if (index < startIndex) continue;
+ if (test(s)) {
+ classFound = true;
+ }
+ } finally {
+ index++;
+ }
+ }
+ long elapsed = System.nanoTime() - start;
+ long secs = elapsed / 1000_000_000;
+ long millis = (elapsed % 1000_000_000) / 1000_000;
+ long nanos = elapsed % 1000_000;
+ System.out.println("Unreadable path elements: " + cantread);
+ System.out.println("Skipped path elements: " + skipped);
+ System.out.println("Failed path elements: " + failed);
+ printSummary(secs, millis, nanos);
+
+ if (!failed.isEmpty()) {
+ throw new RuntimeException("Test failed for the following classes: " + failed);
+ }
+ if (!classFound && startIndex == 0 && index < maxIndex) {
+ // this is just to verify that we have indeed parsed rt.jar
+ // (or the java.base module)
+ throw new RuntimeException("Test failed: Class.class not found...");
+ }
+ if (classCount.get() == 0 && startIndex == 0) {
+ throw new RuntimeException("Test failed: no class found?");
+ }
+ }
+
+ static boolean test(String s) {
+ try {
+ if (s.startsWith("WrapperGenerator")) {
+ System.out.println("Skipping "+ s);
+ return false;
+ }
+ final Class<?> c = Class.forName(
+ s.replace('/', '.').substring(0, s.length() - 6),
+ false,
+ null);
+ return test(c);
+ } catch (Exception t) {
+ t.printStackTrace(System.err);
+ failed.add(s);
+ } catch (NoClassDefFoundError e) {
+ e.printStackTrace(System.err);
+ failed.add(s);
+ }
+ return false;
+ }
+
+ static class ClassNameStreamBuilder implements Iterable<String>{
+ String[] bcp;
+ ClassNameStreamBuilder() {
+ bcp = System.getProperty("sun.boot.class.path").split(File.pathSeparator);
+ }
+
+ Stream<String> bcpElementToStream(String s) {
+ return s.endsWith(".jar") ? jarToStream(s) : folderToStream(s);
+ }
+
+ Stream<String> jarToStream(String jarName) {
+ File f = new File(jarName);
+ if (f.canRead() && f.isFile()) {
+ try {
+ JarFile jarFile = new JarFile(f);
+ return jarFile.stream()
+ .filter(e -> !e.isDirectory())
+ .map(JarEntry::getName)
+ .filter(s -> s.endsWith(".class"));
+ } catch(IOException x) {
+ x.printStackTrace(System.err);
+ skipped.add(jarName);
+ }
+ } else {
+ cantread.add(jarName);
+ }
+ return Collections.<String>emptyList().stream();
+ }
+
+ Stream<String> folderToStream(String folderName) {
+ final File root = new File(folderName);
+ if (root.canRead() && root.isDirectory()) {
+ final Path rootPath = root.toPath();
+ try {
+ return Files.walk(rootPath)
+ .filter(p -> p.getFileName().toString().endsWith(".class"))
+ .map(rootPath::relativize)
+ .map(p -> p.toString().replace(File.separatorChar, '/'));
+ } catch (IOException x) {
+ x.printStackTrace(System.err);
+ skipped.add(folderName);
+ }
+ } else {
+ cantread.add(folderName);
+ }
+ return Collections.<String>emptyList().stream();
+ }
+
+ public Stream<String> build() {
+ return Stream.of(bcp).flatMap(this::bcpElementToStream);
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return build().iterator();
+ }
+ }
+
+ // Test with or without a security manager
+ public static enum TestCase {
+ UNSECURE, SECURE;
+ public void run() throws Exception {
+ System.out.println("Running test case: " + name());
+ Configure.setUp(this);
+ FieldSetAccessibleTest.run(this);
+ }
+ }
+
+ // A helper class to configure the security manager for the test,
+ // and bypass it when needed.
+ static class Configure {
+ static Policy policy = null;
+ static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {
+ @Override
+ protected AtomicBoolean initialValue() {
+ return new AtomicBoolean(false);
+ }
+ };
+ static void setUp(TestCase test) {
+ switch (test) {
+ case SECURE:
+ if (policy == null && System.getSecurityManager() != null) {
+ throw new IllegalStateException("SecurityManager already set");
+ } else if (policy == null) {
+ policy = new SimplePolicy(TestCase.SECURE, allowAll);
+ Policy.setPolicy(policy);
+ System.setSecurityManager(new SecurityManager());
+ }
+ if (System.getSecurityManager() == null) {
+ throw new IllegalStateException("No SecurityManager.");
+ }
+ if (policy == null) {
+ throw new IllegalStateException("policy not configured");
+ }
+ break;
+ case UNSECURE:
+ if (System.getSecurityManager() != null) {
+ throw new IllegalStateException("SecurityManager already set");
+ }
+ break;
+ default:
+ throw new InternalError("No such testcase: " + test);
+ }
+ }
+ static void doPrivileged(Runnable run) {
+ allowAll.get().set(true);
+ try {
+ run.run();
+ } finally {
+ allowAll.get().set(false);
+ }
+ }
+ }
+
+ // A Helper class to build a set of permissions.
+ final static class PermissionsBuilder {
+ final Permissions perms;
+ public PermissionsBuilder() {
+ this(new Permissions());
+ }
+ public PermissionsBuilder(Permissions perms) {
+ this.perms = perms;
+ }
+ public PermissionsBuilder add(Permission p) {
+ perms.add(p);
+ return this;
+ }
+ public PermissionsBuilder addAll(PermissionCollection col) {
+ if (col != null) {
+ for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
+ perms.add(e.nextElement());
+ }
+ }
+ return this;
+ }
+ public Permissions toPermissions() {
+ final PermissionsBuilder builder = new PermissionsBuilder();
+ builder.addAll(perms);
+ return builder.perms;
+ }
+ }
+
+ // Policy for the test...
+ public static class SimplePolicy extends Policy {
+
+ final Permissions permissions;
+ final Permissions allPermissions;
+ final ThreadLocal<AtomicBoolean> allowAll;
+ public SimplePolicy(TestCase test, ThreadLocal<AtomicBoolean> allowAll) {
+ this.allowAll = allowAll;
+
+ // Permission needed by the tested code exercised in the test
+ permissions = new Permissions();
+ permissions.add(new RuntimePermission("fileSystemProvider"));
+ permissions.add(new RuntimePermission("createClassLoader"));
+ permissions.add(new RuntimePermission("closeClassLoader"));
+ permissions.add(new RuntimePermission("getClassLoader"));
+ permissions.add(new RuntimePermission("accessDeclaredMembers"));
+ permissions.add(new ReflectPermission("suppressAccessChecks"));
+ permissions.add(new PropertyPermission("*", "read"));
+ permissions.add(new FilePermission("<<ALL FILES>>", "read"));
+
+ // these are used for configuring the test itself...
+ allPermissions = new Permissions();
+ allPermissions.add(new java.security.AllPermission());
+ }
+
+ @Override
+ public boolean implies(ProtectionDomain domain, Permission permission) {
+ if (allowAll.get().get()) return allPermissions.implies(permission);
+ if (permissions.implies(permission)) return true;
+ if (permission instanceof java.lang.RuntimePermission) {
+ if (permission.getName().startsWith("accessClassInPackage.")) {
+ // add these along to the set of permission we have, when we
+ // discover that we need them.
+ permissions.add(permission);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public PermissionCollection getPermissions(CodeSource codesource) {
+ return new PermissionsBuilder().addAll(allowAll.get().get()
+ ? allPermissions : permissions).toPermissions();
+ }
+
+ @Override
+ public PermissionCollection getPermissions(ProtectionDomain domain) {
+ return new PermissionsBuilder().addAll(allowAll.get().get()
+ ? allPermissions : permissions).toPermissions();
+ }
+ }
+
+}