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