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