xref: /aosp_15_r20/art/test/712-varhandle-invocations/src/VarHandleUnitTest.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.WrongMethodTypeException;
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker // Base class for VarHandle unit tests for accessor operations
20*795d594fSAndroid Build Coastguard Worker public abstract class VarHandleUnitTest {
21*795d594fSAndroid Build Coastguard Worker     public static VarHandleUnitTestCollector DEFAULT_COLLECTOR = new VarHandleUnitTestCollector();
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker     // Error log (lazily initialized on failure).
24*795d594fSAndroid Build Coastguard Worker     private StringBuilder lazyErrorLog = null;
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker     // Tracker of test events (starts, skips, ends)
27*795d594fSAndroid Build Coastguard Worker     private final VarHandleUnitTestCollector collector;
28*795d594fSAndroid Build Coastguard Worker 
VarHandleUnitTest(VarHandleUnitTestCollector collector)29*795d594fSAndroid Build Coastguard Worker     public VarHandleUnitTest(VarHandleUnitTestCollector collector) {
30*795d594fSAndroid Build Coastguard Worker         this.collector = collector;
31*795d594fSAndroid Build Coastguard Worker     }
32*795d594fSAndroid Build Coastguard Worker 
VarHandleUnitTest()33*795d594fSAndroid Build Coastguard Worker     public VarHandleUnitTest() {
34*795d594fSAndroid Build Coastguard Worker         this.collector = DEFAULT_COLLECTOR;
35*795d594fSAndroid Build Coastguard Worker     }
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker     // Method that can be overloaded to signify that a test should be
38*795d594fSAndroid Build Coastguard Worker     // run or skipped. Returns true if the test should be run and
39*795d594fSAndroid Build Coastguard Worker     // false if the test should be skipped.
checkGuard()40*795d594fSAndroid Build Coastguard Worker     public boolean checkGuard() {
41*795d594fSAndroid Build Coastguard Worker         return true;
42*795d594fSAndroid Build Coastguard Worker     }
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker     // Method that implementations should use to perform a specific test.
doTest()45*795d594fSAndroid Build Coastguard Worker     protected abstract void doTest() throws Exception;
46*795d594fSAndroid Build Coastguard Worker 
assertTrue(boolean value)47*795d594fSAndroid Build Coastguard Worker     public final void assertTrue(boolean value) {
48*795d594fSAndroid Build Coastguard Worker         assertEquals(true, value);
49*795d594fSAndroid Build Coastguard Worker     }
50*795d594fSAndroid Build Coastguard Worker 
assertFalse(boolean value)51*795d594fSAndroid Build Coastguard Worker     public final void assertFalse(boolean value) {
52*795d594fSAndroid Build Coastguard Worker         assertEquals(false, value);
53*795d594fSAndroid Build Coastguard Worker     }
54*795d594fSAndroid Build Coastguard Worker 
assertEquals(boolean expected, boolean actual)55*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(boolean expected, boolean actual) {
56*795d594fSAndroid Build Coastguard Worker         assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
57*795d594fSAndroid Build Coastguard Worker     }
58*795d594fSAndroid Build Coastguard Worker 
assertEquals(byte expected, byte actual)59*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(byte expected, byte actual) {
60*795d594fSAndroid Build Coastguard Worker         assertEquals(Byte.valueOf(expected), Byte.valueOf(actual));
61*795d594fSAndroid Build Coastguard Worker     }
62*795d594fSAndroid Build Coastguard Worker 
assertEquals(char expected, char actual)63*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(char expected, char actual) {
64*795d594fSAndroid Build Coastguard Worker         assertEquals(Character.valueOf(expected), Character.valueOf(actual));
65*795d594fSAndroid Build Coastguard Worker     }
66*795d594fSAndroid Build Coastguard Worker 
assertEquals(short expected, short actual)67*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(short expected, short actual) {
68*795d594fSAndroid Build Coastguard Worker         assertEquals(Short.valueOf(expected), Short.valueOf(actual));
69*795d594fSAndroid Build Coastguard Worker     }
70*795d594fSAndroid Build Coastguard Worker 
assertEquals(int expected, int actual)71*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(int expected, int actual) {
72*795d594fSAndroid Build Coastguard Worker         assertEquals(Integer.valueOf(expected), Integer.valueOf(actual));
73*795d594fSAndroid Build Coastguard Worker     }
74*795d594fSAndroid Build Coastguard Worker 
assertEquals(long expected, long actual)75*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(long expected, long actual) {
76*795d594fSAndroid Build Coastguard Worker         assertEquals(Long.valueOf(expected), Long.valueOf(actual));
77*795d594fSAndroid Build Coastguard Worker     }
78*795d594fSAndroid Build Coastguard Worker 
assertEquals(float expected, float actual)79*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(float expected, float actual) {
80*795d594fSAndroid Build Coastguard Worker         assertEquals(Float.valueOf(expected), Float.valueOf(actual));
81*795d594fSAndroid Build Coastguard Worker     }
82*795d594fSAndroid Build Coastguard Worker 
assertEquals(double expected, double actual)83*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(double expected, double actual) {
84*795d594fSAndroid Build Coastguard Worker         assertEquals(Double.valueOf(expected), Double.valueOf(actual));
85*795d594fSAndroid Build Coastguard Worker     }
86*795d594fSAndroid Build Coastguard Worker 
assertEquals(Object expected, Object actual)87*795d594fSAndroid Build Coastguard Worker     public final void assertEquals(Object expected, Object actual) {
88*795d594fSAndroid Build Coastguard Worker         if (expected == null) {
89*795d594fSAndroid Build Coastguard Worker             if (actual == null) {
90*795d594fSAndroid Build Coastguard Worker                 return;
91*795d594fSAndroid Build Coastguard Worker             }
92*795d594fSAndroid Build Coastguard Worker         } else if (expected.equals(actual)) {
93*795d594fSAndroid Build Coastguard Worker             return;
94*795d594fSAndroid Build Coastguard Worker         }
95*795d594fSAndroid Build Coastguard Worker         failNotEquals("Failed assertion (expected != actual)", expected, actual);
96*795d594fSAndroid Build Coastguard Worker     }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker     interface AccessorAccess {
apply()99*795d594fSAndroid Build Coastguard Worker         void apply() throws Exception;
100*795d594fSAndroid Build Coastguard Worker     }
101*795d594fSAndroid Build Coastguard Worker 
assertThrows(Class expectedException, AccessorAccess access)102*795d594fSAndroid Build Coastguard Worker     void assertThrows(Class expectedException, AccessorAccess access) {
103*795d594fSAndroid Build Coastguard Worker         try {
104*795d594fSAndroid Build Coastguard Worker             access.apply();
105*795d594fSAndroid Build Coastguard Worker             fail("Expected a " + expectedException + ", but not raised");
106*795d594fSAndroid Build Coastguard Worker         } catch (Exception e) {
107*795d594fSAndroid Build Coastguard Worker             if (!expectedException.isInstance(e)) {
108*795d594fSAndroid Build Coastguard Worker                 fail("Expected a " + expectedException + ", but got a " + e.getClass(), e);
109*795d594fSAndroid Build Coastguard Worker             }
110*795d594fSAndroid Build Coastguard Worker         }
111*795d594fSAndroid Build Coastguard Worker     }
112*795d594fSAndroid Build Coastguard Worker 
assertThrowsAIOBE(AccessorAccess access)113*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsAIOBE(AccessorAccess access) {
114*795d594fSAndroid Build Coastguard Worker         assertThrows(ArrayIndexOutOfBoundsException.class, access);
115*795d594fSAndroid Build Coastguard Worker     }
116*795d594fSAndroid Build Coastguard Worker 
assertThrowsASE(AccessorAccess access)117*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsASE(AccessorAccess access) {
118*795d594fSAndroid Build Coastguard Worker         assertThrows(ArrayStoreException.class, access);
119*795d594fSAndroid Build Coastguard Worker     }
120*795d594fSAndroid Build Coastguard Worker 
assertThrowsISE(AccessorAccess access)121*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsISE(AccessorAccess access) {
122*795d594fSAndroid Build Coastguard Worker         assertThrows(IllegalStateException.class, access);
123*795d594fSAndroid Build Coastguard Worker     }
124*795d594fSAndroid Build Coastguard Worker 
assertThrowsIOOBE(AccessorAccess access)125*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsIOOBE(AccessorAccess access) {
126*795d594fSAndroid Build Coastguard Worker         assertThrows(IndexOutOfBoundsException.class, access);
127*795d594fSAndroid Build Coastguard Worker     }
128*795d594fSAndroid Build Coastguard Worker 
assertThrowsCCE(AccessorAccess access)129*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsCCE(AccessorAccess access) {
130*795d594fSAndroid Build Coastguard Worker         assertThrows(ClassCastException.class, access);
131*795d594fSAndroid Build Coastguard Worker     }
132*795d594fSAndroid Build Coastguard Worker 
assertThrowsNPE(AccessorAccess access)133*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsNPE(AccessorAccess access) {
134*795d594fSAndroid Build Coastguard Worker         assertThrows(NullPointerException.class, access);
135*795d594fSAndroid Build Coastguard Worker     }
136*795d594fSAndroid Build Coastguard Worker 
assertThrowsWMTE(AccessorAccess access)137*795d594fSAndroid Build Coastguard Worker     public final void assertThrowsWMTE(AccessorAccess access) {
138*795d594fSAndroid Build Coastguard Worker         assertThrows(WrongMethodTypeException.class, access);
139*795d594fSAndroid Build Coastguard Worker     }
140*795d594fSAndroid Build Coastguard Worker 
failUnreachable()141*795d594fSAndroid Build Coastguard Worker     public final void failUnreachable() {
142*795d594fSAndroid Build Coastguard Worker         fail("Unreachable code");
143*795d594fSAndroid Build Coastguard Worker     }
144*795d594fSAndroid Build Coastguard Worker 
run()145*795d594fSAndroid Build Coastguard Worker     public final void run() {
146*795d594fSAndroid Build Coastguard Worker         collector.start(getClass().getSimpleName());
147*795d594fSAndroid Build Coastguard Worker         if (!checkGuard()) {
148*795d594fSAndroid Build Coastguard Worker             collector.skip();
149*795d594fSAndroid Build Coastguard Worker             return;
150*795d594fSAndroid Build Coastguard Worker         }
151*795d594fSAndroid Build Coastguard Worker 
152*795d594fSAndroid Build Coastguard Worker         try {
153*795d594fSAndroid Build Coastguard Worker             doTest();
154*795d594fSAndroid Build Coastguard Worker         } catch (Exception e) {
155*795d594fSAndroid Build Coastguard Worker             fail("Unexpected exception", e);
156*795d594fSAndroid Build Coastguard Worker             e.printStackTrace();
157*795d594fSAndroid Build Coastguard Worker         } finally {
158*795d594fSAndroid Build Coastguard Worker             if (lazyErrorLog == null) {
159*795d594fSAndroid Build Coastguard Worker                 collector.success();
160*795d594fSAndroid Build Coastguard Worker             } else {
161*795d594fSAndroid Build Coastguard Worker                 collector.fail(lazyErrorLog.toString());
162*795d594fSAndroid Build Coastguard Worker             }
163*795d594fSAndroid Build Coastguard Worker         }
164*795d594fSAndroid Build Coastguard Worker     }
165*795d594fSAndroid Build Coastguard Worker 
failNotEquals(String message, Object expected, Object actual)166*795d594fSAndroid Build Coastguard Worker     private void failNotEquals(String message, Object expected, Object actual) {
167*795d594fSAndroid Build Coastguard Worker         errorLog()
168*795d594fSAndroid Build Coastguard Worker                 .append(message)
169*795d594fSAndroid Build Coastguard Worker                 .append(": ")
170*795d594fSAndroid Build Coastguard Worker                 .append(expected)
171*795d594fSAndroid Build Coastguard Worker                 .append(" != ")
172*795d594fSAndroid Build Coastguard Worker                 .append(actual)
173*795d594fSAndroid Build Coastguard Worker                 .append(" in ")
174*795d594fSAndroid Build Coastguard Worker                 .append(getSourceInfo())
175*795d594fSAndroid Build Coastguard Worker                 .append('\n');
176*795d594fSAndroid Build Coastguard Worker     }
177*795d594fSAndroid Build Coastguard Worker 
fail(String message)178*795d594fSAndroid Build Coastguard Worker     private void fail(String message) {
179*795d594fSAndroid Build Coastguard Worker         errorLog().append(message).append(" in ").append(getSourceInfo()).append('\n');
180*795d594fSAndroid Build Coastguard Worker     }
181*795d594fSAndroid Build Coastguard Worker 
fail(String message, String detail)182*795d594fSAndroid Build Coastguard Worker     private void fail(String message, String detail) {
183*795d594fSAndroid Build Coastguard Worker         errorLog()
184*795d594fSAndroid Build Coastguard Worker                 .append(message)
185*795d594fSAndroid Build Coastguard Worker                 .append(": ")
186*795d594fSAndroid Build Coastguard Worker                 .append(detail)
187*795d594fSAndroid Build Coastguard Worker                 .append(" in ")
188*795d594fSAndroid Build Coastguard Worker                 .append(getSourceInfo())
189*795d594fSAndroid Build Coastguard Worker                 .append('\n');
190*795d594fSAndroid Build Coastguard Worker     }
191*795d594fSAndroid Build Coastguard Worker 
fail(String message, Exception e)192*795d594fSAndroid Build Coastguard Worker     private void fail(String message, Exception e) {
193*795d594fSAndroid Build Coastguard Worker         errorLog()
194*795d594fSAndroid Build Coastguard Worker                 .append(message)
195*795d594fSAndroid Build Coastguard Worker                 .append(": ")
196*795d594fSAndroid Build Coastguard Worker                 .append(e.toString())
197*795d594fSAndroid Build Coastguard Worker                 .append(" in ")
198*795d594fSAndroid Build Coastguard Worker                 .append(getSourceInfo(e))
199*795d594fSAndroid Build Coastguard Worker                 .append('\n');
200*795d594fSAndroid Build Coastguard Worker     }
201*795d594fSAndroid Build Coastguard Worker 
getSourceInfo(Exception e)202*795d594fSAndroid Build Coastguard Worker     private String getSourceInfo(Exception e) {
203*795d594fSAndroid Build Coastguard Worker         // Unit test has thrown an exception. Stack likely looks like
204*795d594fSAndroid Build Coastguard Worker         // runtime frames then unit test frames then
205*795d594fSAndroid Build Coastguard Worker         // VarHandleUnitFrames.
206*795d594fSAndroid Build Coastguard Worker         StackTraceElement[] stackTraceElements = e.getStackTrace();
207*795d594fSAndroid Build Coastguard Worker         int index = 1;
208*795d594fSAndroid Build Coastguard Worker         for (int i = 1; i < stackTraceElements.length; ++i) {
209*795d594fSAndroid Build Coastguard Worker             if ("VarHandleUnitTest".equals(stackTraceElements[i].getClassName())) {
210*795d594fSAndroid Build Coastguard Worker                 return stackTraceElements[i - 1].toString();
211*795d594fSAndroid Build Coastguard Worker             }
212*795d594fSAndroid Build Coastguard Worker         }
213*795d594fSAndroid Build Coastguard Worker         return "Unknown";
214*795d594fSAndroid Build Coastguard Worker     }
215*795d594fSAndroid Build Coastguard Worker 
getSourceInfo()216*795d594fSAndroid Build Coastguard Worker     private String getSourceInfo() {
217*795d594fSAndroid Build Coastguard Worker         // Gets source info for a failure such as an assertion. The
218*795d594fSAndroid Build Coastguard Worker         // test has called a method on VarHandleUnitTest so the stack
219*795d594fSAndroid Build Coastguard Worker         // looks like some frames in VarHandleUnitTest methods and then
220*795d594fSAndroid Build Coastguard Worker         // a frame in the test itself.
221*795d594fSAndroid Build Coastguard Worker         StackTraceElement[] stackTraceElements = new Exception().getStackTrace();
222*795d594fSAndroid Build Coastguard Worker         for (StackTraceElement stackTraceElement : stackTraceElements) {
223*795d594fSAndroid Build Coastguard Worker             if (!"VarHandleUnitTest".equals(stackTraceElement.getClassName())) {
224*795d594fSAndroid Build Coastguard Worker                 return stackTraceElement.toString();
225*795d594fSAndroid Build Coastguard Worker             }
226*795d594fSAndroid Build Coastguard Worker         }
227*795d594fSAndroid Build Coastguard Worker         return "Unknown";
228*795d594fSAndroid Build Coastguard Worker     }
229*795d594fSAndroid Build Coastguard Worker 
errorLog()230*795d594fSAndroid Build Coastguard Worker     private StringBuilder errorLog() {
231*795d594fSAndroid Build Coastguard Worker         if (lazyErrorLog == null) {
232*795d594fSAndroid Build Coastguard Worker             lazyErrorLog = new StringBuilder();
233*795d594fSAndroid Build Coastguard Worker         }
234*795d594fSAndroid Build Coastguard Worker         return lazyErrorLog;
235*795d594fSAndroid Build Coastguard Worker     }
236*795d594fSAndroid Build Coastguard Worker }
237