Home | History | Annotate | Download | only in src
      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