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 // Base class for VarHandle unit tests for accessor operations 18 public abstract class VarHandleUnitTest { 19 public static VarHandleUnitTestCollector DEFAULT_COLLECTOR = new VarHandleUnitTestCollector(); 20 21 // Error log (lazily initialized on failure). 22 private StringBuilder lazyErrorLog = null; 23 24 // Tracker of test events (starts, skips, ends) 25 private final VarHandleUnitTestCollector collector; 26 27 public VarHandleUnitTest(VarHandleUnitTestCollector collector) { 28 this.collector = collector; 29 } 30 31 public VarHandleUnitTest() { 32 this.collector = DEFAULT_COLLECTOR; 33 } 34 35 // Method that can be overloaded to signify that a test should be 36 // run or skipped. Returns true if the test should be run and 37 // false if the test should be skipped. 38 public boolean checkGuard() { 39 return true; 40 } 41 42 // Method that implementations should use to perform a specific test. 43 protected abstract void doTest() throws Exception; 44 45 public final void assertTrue(boolean value) { 46 assertEquals(true, value); 47 } 48 49 public final void assertFalse(boolean value) { 50 assertEquals(false, value); 51 } 52 53 public final void assertEquals(boolean expected, boolean actual) { 54 assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual)); 55 } 56 57 public final void assertEquals(byte expected, byte actual) { 58 assertEquals(Byte.valueOf(expected), Byte.valueOf(actual)); 59 } 60 61 public final void assertEquals(char expected, char actual) { 62 assertEquals(Character.valueOf(expected), Character.valueOf(actual)); 63 } 64 65 public final void assertEquals(short expected, short actual) { 66 assertEquals(Short.valueOf(expected), Short.valueOf(actual)); 67 } 68 69 public final void assertEquals(int expected, int actual) { 70 assertEquals(Integer.valueOf(expected), Integer.valueOf(actual)); 71 } 72 73 public final void assertEquals(long expected, long actual) { 74 assertEquals(Long.valueOf(expected), Long.valueOf(actual)); 75 } 76 77 public final void assertEquals(float expected, float actual) { 78 assertEquals(Float.valueOf(expected), Float.valueOf(actual)); 79 } 80 81 public final void assertEquals(double expected, double actual) { 82 assertEquals(Double.valueOf(expected), Double.valueOf(actual)); 83 } 84 85 public final void assertEquals(Object expected, Object actual) { 86 if (expected == null) { 87 if (actual == null) { 88 return; 89 } 90 } else if (expected.equals(actual)) { 91 return; 92 } 93 failNotEquals("Failed assertion (expected != actual)", expected, actual); 94 } 95 96 public final void failUnreachable() { 97 fail("Unreachable code"); 98 } 99 100 public final void run() { 101 collector.start(getClass().getSimpleName()); 102 if (!checkGuard()) { 103 collector.skip(); 104 return; 105 } 106 107 try { 108 doTest(); 109 } catch (Exception e) { 110 fail("Unexpected exception", e); 111 } finally { 112 if (lazyErrorLog == null) { 113 collector.success(); 114 } else { 115 collector.fail(lazyErrorLog.toString()); 116 } 117 } 118 } 119 120 private void failNotEquals(String message, Object expected, Object actual) { 121 errorLog() 122 .append(message) 123 .append(": ") 124 .append(expected) 125 .append(" != ") 126 .append(actual) 127 .append(" in ") 128 .append(getSourceInfo()) 129 .append('\n'); 130 } 131 132 private void fail(String message) { 133 errorLog().append(message).append(" in ").append(getSourceInfo()).append('\n'); 134 } 135 136 private void fail(String message, String detail) { 137 errorLog() 138 .append(message) 139 .append(": ") 140 .append(detail) 141 .append(" in ") 142 .append(getSourceInfo()) 143 .append('\n'); 144 } 145 146 private void fail(String message, Exception e) { 147 errorLog() 148 .append(message) 149 .append(": ") 150 .append(e.toString()) 151 .append(" in ") 152 .append(getSourceInfo(e)) 153 .append('\n'); 154 } 155 156 private String getSourceInfo(Exception e) { 157 // Unit test has thrown an exception. Stack likely looks like 158 // runtime frames then unit test frames then 159 // VarHandleUnitFrames. 160 StackTraceElement[] stackTraceElements = e.getStackTrace(); 161 int index = 1; 162 for (int i = 1; i < stackTraceElements.length; ++i) { 163 if ("VarHandleUnitTest".equals(stackTraceElements[i].getClassName())) { 164 return stackTraceElements[i - 1].toString(); 165 } 166 } 167 return "Unknown"; 168 } 169 170 private String getSourceInfo() { 171 // Gets source info for a failure such as an assertion. The 172 // test has called a method on VarHandleUnitTest so the stack 173 // looks like some frames in VarHandleUnitTest methods and then 174 // a frame in the test itself. 175 StackTraceElement[] stackTraceElements = new Exception().getStackTrace(); 176 for (StackTraceElement stackTraceElement : stackTraceElements) { 177 if (!"VarHandleUnitTest".equals(stackTraceElement.getClassName())) { 178 return stackTraceElement.toString(); 179 } 180 } 181 return "Unknown"; 182 } 183 184 private StringBuilder errorLog() { 185 if (lazyErrorLog == null) { 186 lazyErrorLog = new StringBuilder(); 187 } 188 return lazyErrorLog; 189 } 190 } 191