1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import annotations.ConstantMethodType;
18 
19 import java.lang.invoke.MethodType;
20 import java.util.Objects;
21 
22 public class Main {
main(String... args)23     public static void main(String... args) throws Throwable {
24         testEquality();
25         // Subsequent const-method-type call should take value from from .bss.
26         testEquality();
27         testNonEquality();
28         testNonEquality();
29         testWithUninitializableClass();
30     }
31 
unreachable()32     private static void unreachable() {
33         throw new Error("unreachable");
34     }
35 
36     @ConstantMethodType(
37         returnType = void.class,
38         parameterTypes = {
39             boolean.class,
40             byte.class,
41             char.class,
42             short.class,
43             int.class,
44             long.class,
45             float.class,
46             double.class,
47             Object.class,
48             int[].class })
takesEverythingReturnsVoid()49     private static MethodType takesEverythingReturnsVoid() {
50         unreachable();
51         return null;
52     }
53 
testEquality()54     public static void testEquality() throws Throwable {
55         MethodType actual = takesEverythingReturnsVoid();
56 
57         MethodType expected = MethodType.methodType(
58             void.class,
59             boolean.class,
60             byte.class,
61             char.class,
62             short.class,
63             int.class,
64             long.class,
65             float.class,
66             double.class,
67             Object.class,
68             int[].class);
69 
70         assertSame(expected, actual);
71         assertSame(takesEverythingReturnsVoid(), takesEverythingReturnsVoid());
72     }
73 
testNonEquality()74     public static void testNonEquality() throws Throwable {
75         MethodType actual = takesEverythingReturnsVoid();
76 
77         MethodType expected = MethodType.methodType(
78             boolean.class,
79             boolean.class,
80             byte.class,
81             char.class,
82             short.class,
83             int.class,
84             long.class,
85             float.class,
86             double.class,
87             Object.class,
88             int[].class);
89 
90         assertNotEqual(expected, actual);
91     }
92 
93     @ConstantMethodType(
94         returnType = void.class,
95         parameterTypes = { UnloadableClass.class })
takesUnloadableReturnsVoid()96     private static MethodType takesUnloadableReturnsVoid() {
97         unreachable();
98         return null;
99     }
100 
101     public static volatile int x = 0;
102 
103     private static class UnloadableClass {
104         static {
105             if (x == x) {
106                 throw new RuntimeException("don't init me");
107             }
108         }
109     }
110 
testWithUninitializableClass()111     public static void testWithUninitializableClass() {
112         MethodType actual = takesUnloadableReturnsVoid();
113 
114         MethodType expected = MethodType.methodType(void.class, UnloadableClass.class);
115 
116         assertSame(expected, actual);
117     }
118 
assertNotEqual(Object expected, Object actual)119     public static void assertNotEqual(Object expected, Object actual) {
120         if (Objects.equals(expected, actual)) {
121             String msg = "Expected to be non equal, but got: " + expected;
122             throw new AssertionError(msg);
123         }
124     }
125 
assertSame(Object expected, Object actual)126     public static void assertSame(Object expected, Object actual) {
127         if (actual != expected) {
128             String msg = String.format("Expected: %s(%X), got %s(%X)",
129                                   expected,
130                                   System.identityHashCode(expected),
131                                   actual,
132                                   System.identityHashCode(actual));
133             throw new AssertionError(msg);
134         }
135     }
136 }