1 /* 2 * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.lang.reflect.Modifier; 25 import java.lang.annotation.*; 26 27 /* 28 * @test 29 * @bug 8296743 30 * @summary Verify array classes and primitives have expected modifiers 31 */ 32 @ExpectedModifiers(Modifier.PUBLIC | Modifier.FINAL | Modifier.ABSTRACT) 33 public class TestPrimitiveAndArrayModifiers { 34 35 /* 36 * Relevant excerpt of the Class.getModifiers() specification: 37 * <p> If the underlying class is an array class: 38 * <ul> 39 * <li> its {@code public}, {@code private} and {@code protected} 40 * modifiers are the same as those of its component type 41 * <li> its {@code final} and {@code abstract} modifiers are always 42 * {@code true} 43 * <li> its interface modifier is always {@code false}, even when 44 * the component type is an interface 45 * </ul> 46 */ 47 48 public static void main(String... args) throws Exception { 49 testPrimitives(); 50 testArrays(); 51 } 52 53 private static void testArrays() { 54 Class<?>[] testCases = { 55 TestPrimitiveAndArrayModifiers.class, 56 57 PackagePrivateClass.class, 58 ProtectedClass.class, 59 PrivateClass.class, 60 61 PublicInterface.class, 62 PackagePrivateInterface.class, 63 ProtectedInterface.class, 64 PrivateInterface.class, 65 }; 66 67 for(var testCase : testCases) { 68 int expectedModifiers = 69 testCase.getAnnotation(ExpectedModifiers.class).value(); 70 Class<?> arrayClass = testCase.arrayType(); 71 int actualModifiers = arrayClass.getModifiers(); 72 if (expectedModifiers != actualModifiers) { 73 throw new RuntimeException("Expected " + Modifier.toString(expectedModifiers) + 74 "on " + testCase.getCanonicalName() + 75 ", but got " + Modifier.toString(actualModifiers)); 76 } 77 } 78 } 79 80 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT) 81 class PackagePrivateClass {} 82 83 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PROTECTED) 84 protected class ProtectedClass {} 85 86 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PRIVATE) 87 private class PrivateClass {} 88 89 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PUBLIC) 90 public interface PublicInterface {} 91 92 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT) 93 interface PackagePrivateInterface {} 94 95 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PROTECTED) 96 protected interface ProtectedInterface {} 97 98 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PRIVATE) 99 private interface PrivateInterface {} 100 101 /* 102 * Relevant excerpt of the Class.getModifiers() specification: 103 * 104 * If this {@code Class} object represents a primitive type or 105 * void, its {@code public}, {@code abstract}, and {@code final} 106 * modifiers are always {@code true}. 107 */ 108 private static void testPrimitives() { 109 Class<?>[] testCases = { 110 void.class, 111 boolean.class, 112 byte.class, 113 short.class, 114 char.class, 115 int.class, 116 float.class, 117 long.class, 118 double.class, 119 }; 120 121 for(var testCase : testCases) { 122 int actualModifiers = testCase.getModifiers(); 123 if ((Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL) != 124 actualModifiers) { 125 throw new RuntimeException("Bad modifiers " + 126 Modifier.toString(actualModifiers) + 127 " on primitive type " + testCase); 128 } 129 } 130 } 131 } 132 133 @Retention(RetentionPolicy.RUNTIME) 134 @interface ExpectedModifiers { 135 int value() default 0; 136 }