blob: 601d4709501ce62d73a62e5abbc59e20f4bc9821 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Base class for VarHandle unit tests for accessor operations
public abstract class VarHandleUnitTest {
public static VarHandleUnitTestCollector DEFAULT_COLLECTOR = new VarHandleUnitTestCollector();
// Error log (lazily initialized on failure).
private StringBuilder lazyErrorLog = null;
// Tracker of test events (starts, skips, ends)
private final VarHandleUnitTestCollector collector;
public VarHandleUnitTest(VarHandleUnitTestCollector collector) {
this.collector = collector;
}
public VarHandleUnitTest() {
this.collector = DEFAULT_COLLECTOR;
}
// Method that can be overloaded to signify that a test should be
// run or skipped. Returns true if the test should be run and
// false if the test should be skipped.
public boolean checkGuard() {
return true;
}
// Method that implementations should use to perform a specific test.
protected abstract void doTest() throws Exception;
public final void assertTrue(boolean value) {
assertEquals(true, value);
}
public final void assertFalse(boolean value) {
assertEquals(false, value);
}
public final void assertEquals(boolean expected, boolean actual) {
assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
}
public final void assertEquals(byte expected, byte actual) {
assertEquals(Byte.valueOf(expected), Byte.valueOf(actual));
}
public final void assertEquals(char expected, char actual) {
assertEquals(Character.valueOf(expected), Character.valueOf(actual));
}
public final void assertEquals(short expected, short actual) {
assertEquals(Short.valueOf(expected), Short.valueOf(actual));
}
public final void assertEquals(int expected, int actual) {
assertEquals(Integer.valueOf(expected), Integer.valueOf(actual));
}
public final void assertEquals(long expected, long actual) {
assertEquals(Long.valueOf(expected), Long.valueOf(actual));
}
public final void assertEquals(float expected, float actual) {
assertEquals(Float.valueOf(expected), Float.valueOf(actual));
}
public final void assertEquals(double expected, double actual) {
assertEquals(Double.valueOf(expected), Double.valueOf(actual));
}
public final void assertEquals(Object expected, Object actual) {
if (expected == null) {
if (actual == null) {
return;
}
} else if (expected.equals(actual)) {
return;
}
failNotEquals("Failed assertion (expected != actual)", expected, actual);
}
public final void failUnreachable() {
fail("Unreachable code");
}
public final void run() {
collector.start(getClass().getSimpleName());
if (!checkGuard()) {
collector.skip();
return;
}
try {
doTest();
} catch (Exception e) {
fail("Unexpected exception", e);
} finally {
if (lazyErrorLog == null) {
collector.success();
} else {
collector.fail(lazyErrorLog.toString());
}
}
}
private void failNotEquals(String message, Object expected, Object actual) {
errorLog()
.append(message)
.append(": ")
.append(expected)
.append(" != ")
.append(actual)
.append(" in ")
.append(getSourceInfo())
.append('\n');
}
private void fail(String message) {
errorLog().append(message).append(" in ").append(getSourceInfo()).append('\n');
}
private void fail(String message, String detail) {
errorLog()
.append(message)
.append(": ")
.append(detail)
.append(" in ")
.append(getSourceInfo())
.append('\n');
}
private void fail(String message, Exception e) {
errorLog()
.append(message)
.append(": ")
.append(e.toString())
.append(" in ")
.append(getSourceInfo(e))
.append('\n');
}
private String getSourceInfo(Exception e) {
// Unit test has thrown an exception. Stack likely looks like
// runtime frames then unit test frames then
// VarHandleUnitFrames.
StackTraceElement[] stackTraceElements = e.getStackTrace();
int index = 1;
for (int i = 1; i < stackTraceElements.length; ++i) {
if ("VarHandleUnitTest".equals(stackTraceElements[i].getClassName())) {
return stackTraceElements[i - 1].toString();
}
}
return "Unknown";
}
private String getSourceInfo() {
// Gets source info for a failure such as an assertion. The
// test has called a method on VarHandleUnitTest so the stack
// looks like some frames in VarHandleUnitTest methods and then
// a frame in the test itself.
StackTraceElement[] stackTraceElements = new Exception().getStackTrace();
for (StackTraceElement stackTraceElement : stackTraceElements) {
if (!"VarHandleUnitTest".equals(stackTraceElement.getClassName())) {
return stackTraceElement.toString();
}
}
return "Unknown";
}
private StringBuilder errorLog() {
if (lazyErrorLog == null) {
lazyErrorLog = new StringBuilder();
}
return lazyErrorLog;
}
}