Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2010 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.reflect.InvocationTargetException;
     18 import java.lang.reflect.Method;
     19 import java.lang.reflect.Modifier;
     20 
     21 /*
     22  * Entry point and tests that are expected to succeed.
     23  */
     24 public class Main {
     25     /**
     26      * Drives tests.
     27      */
     28     public static void main(String[] args) throws Exception {
     29         System.loadLibrary(args[0]);
     30         if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) {
     31             // Some tests ensure that the verifier was able to guarantee balanced locking by
     32             // asserting that the test function is running as compiled code. But skip this now,
     33             // as this seems to be a non-compiled code test configuration.
     34             disableStackFrameAsserts();
     35         }
     36 
     37         ensureJitCompiled(Main.class, "recursiveSync");
     38         ensureJitCompiled(Main.class, "nestedMayThrow");
     39         ensureJitCompiled(Main.class, "constantLock");
     40         ensureJitCompiled(Main.class, "notExcessiveNesting");
     41         ensureJitCompiled(Main.class, "notNested");
     42         ensureJitCompiled(TwoPath.class, "twoPath");
     43         ensureJitCompiled(Class.forName("OK"), "runNoMonitors");
     44         ensureJitCompiled(Class.forName("OK"), "runStraightLine");
     45         ensureJitCompiled(Class.forName("OK"), "runBalancedJoin");
     46         ensureJitCompiled(Class.forName("NullLocks"), "run");
     47 
     48         Main m = new Main();
     49 
     50         m.recursiveSync(0);
     51 
     52         m.nestedMayThrow(false);
     53         try {
     54             m.nestedMayThrow(true);
     55             System.out.println("nestedThrow(true) did not throw");
     56         } catch (MyException me) {}
     57         System.out.println("nestedMayThrow ok");
     58 
     59         m.constantLock();
     60         System.out.println("constantLock ok");
     61 
     62         m.notExcessiveNesting();
     63 
     64         m.notNested();
     65         System.out.println("notNested ok");
     66 
     67         Object obj1 = new Object();
     68         Object obj2 = new Object();
     69 
     70         TwoPath.twoPath(obj1, obj2, 0);
     71         System.out.println("twoPath ok");
     72 
     73         m.triplet(obj1, obj2, 0);
     74         System.out.println("triplet ok");
     75 
     76         runSmaliTests();
     77     }
     78 
     79     /**
     80      * Recursive synchronized method.
     81      */
     82     synchronized void recursiveSync(int iter) {
     83         assertIsManaged();
     84         if (iter < 40) {
     85             recursiveSync(iter+1);
     86         } else {
     87             System.out.println("recursiveSync ok");
     88         }
     89     }
     90 
     91     /**
     92      * Tests simple nesting, with and without a throw.
     93      */
     94     void nestedMayThrow(boolean doThrow) {
     95         assertIsManaged();
     96         synchronized (this) {
     97             synchronized (Main.class) {
     98                 synchronized (new Object()) {
     99                     synchronized(Class.class) {
    100                         if (doThrow) {
    101                             throw new MyException();
    102                         }
    103                     }
    104                 }
    105             }
    106         }
    107     }
    108 
    109     /**
    110      * Exercises bug 3215458.
    111      */
    112     void constantLock() {
    113         assertIsManaged();
    114         Class<?> thing = Thread.class;
    115         synchronized (Thread.class) {}
    116     }
    117 
    118     /**
    119      * Confirms that we can have 32 nested monitors on one method.
    120      */
    121     void notExcessiveNesting() {
    122         assertIsManaged();
    123         synchronized (this) {   // 1
    124         synchronized (this) {   // 2
    125         synchronized (this) {   // 3
    126         synchronized (this) {   // 4
    127         synchronized (this) {   // 5
    128         synchronized (this) {   // 6
    129         synchronized (this) {   // 7
    130         synchronized (this) {   // 8
    131         synchronized (this) {   // 9
    132         synchronized (this) {   // 10
    133         synchronized (this) {   // 11
    134         synchronized (this) {   // 12
    135         synchronized (this) {   // 13
    136         synchronized (this) {   // 14
    137         synchronized (this) {   // 15
    138         synchronized (this) {   // 16
    139         synchronized (this) {   // 17
    140         synchronized (this) {   // 18
    141         synchronized (this) {   // 19
    142         synchronized (this) {   // 20
    143         synchronized (this) {   // 21
    144         synchronized (this) {   // 22
    145         synchronized (this) {   // 23
    146         synchronized (this) {   // 24
    147         synchronized (this) {   // 25
    148         synchronized (this) {   // 26
    149         synchronized (this) {   // 27
    150         synchronized (this) {   // 28
    151         synchronized (this) {   // 29
    152         synchronized (this) {   // 30
    153         synchronized (this) {   // 31
    154         synchronized (this) {   // 32
    155         }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
    156     }
    157 
    158     /**
    159      * Confirms that we can have more than 32 non-nested monitors in one
    160      * method.
    161      */
    162     void notNested() {
    163         assertIsManaged();
    164         synchronized (this) {}  // 1
    165         synchronized (this) {}  // 2
    166         synchronized (this) {}  // 3
    167         synchronized (this) {}  // 4
    168         synchronized (this) {}  // 5
    169         synchronized (this) {}  // 6
    170         synchronized (this) {}  // 7
    171         synchronized (this) {}  // 8
    172         synchronized (this) {}  // 9
    173         synchronized (this) {}  // 10
    174         synchronized (this) {}  // 11
    175         synchronized (this) {}  // 12
    176         synchronized (this) {}  // 13
    177         synchronized (this) {}  // 14
    178         synchronized (this) {}  // 15
    179         synchronized (this) {}  // 16
    180         synchronized (this) {}  // 17
    181         synchronized (this) {}  // 18
    182         synchronized (this) {}  // 19
    183         synchronized (this) {}  // 20
    184         synchronized (this) {}  // 21
    185         synchronized (this) {}  // 22
    186         synchronized (this) {}  // 23
    187         synchronized (this) {}  // 24
    188         synchronized (this) {}  // 25
    189         synchronized (this) {}  // 26
    190         synchronized (this) {}  // 27
    191         synchronized (this) {}  // 28
    192         synchronized (this) {}  // 29
    193         synchronized (this) {}  // 30
    194         synchronized (this) {}  // 31
    195         synchronized (this) {}  // 32
    196         synchronized (this) {}  // 33
    197         synchronized (this) {}  // 34
    198     }
    199 
    200     /* does nothing but ensure that the compiler doesn't discard an object */
    201     private void doNothing(Object obj) {}
    202 
    203     /**
    204      * Lock the monitor two or three times, and make use of the locked or
    205      * unlocked object.
    206      */
    207     public void triplet(Object obj1, Object obj2, int x) {
    208         Object localObj;
    209 
    210         synchronized (obj1) {
    211             synchronized(obj1) {
    212                 if (x == 0) {
    213                     synchronized(obj1) {
    214                         localObj = obj2;
    215                     }
    216                 } else {
    217                     localObj = obj1;
    218                 }
    219             }
    220         }
    221 
    222         doNothing(localObj);
    223     }
    224 
    225     // Smali testing code.
    226     private static void runSmaliTests() {
    227         runTest("OK", new Object[] { new Object(), new Object() }, null);
    228         runTest("TooDeep", new Object[] { new Object() }, null);
    229         runTest("NotStructuredOverUnlock", new Object[] { new Object() },
    230                 IllegalMonitorStateException.class);
    231         runTest("NotStructuredUnderUnlock", new Object[] { new Object() },
    232                 IllegalMonitorStateException.class);
    233         runTest("UnbalancedJoin", new Object[] { new Object(), new Object() }, null);
    234         runTest("UnbalancedStraight", new Object[] { new Object(), new Object() }, null);
    235         runTest("NullLocks", new Object[] { false }, null);
    236         runTest("NullLocks", new Object[] { true }, NullPointerException.class);
    237     }
    238 
    239     private static void runTest(String className, Object[] parameters, Class<?> excType) {
    240         try {
    241             Class<?> c = Class.forName(className);
    242 
    243             Method[] methods = c.getDeclaredMethods();
    244 
    245             // For simplicity we assume that test methods are not overloaded. So searching by name
    246             // will give us the method we need to run.
    247             Method method = null;
    248             for (Method m : methods) {
    249                 if (m.getName().equals("run")) {
    250                     method = m;
    251                     break;
    252                 }
    253             }
    254 
    255             if (method == null) {
    256                 System.out.println("Could not find test method for " + className);
    257             } else if (!Modifier.isStatic(method.getModifiers())) {
    258                 System.out.println("Test method for " + className + " is not static.");
    259             } else {
    260                 method.invoke(null, parameters);
    261                 if (excType != null) {
    262                     System.out.println("Expected an exception in " + className);
    263                 }
    264             }
    265         } catch (Throwable exc) {
    266             if (excType == null) {
    267                 System.out.println("Did not expect exception " + exc + " for " + className);
    268                 exc.printStackTrace(System.out);
    269             } else if (exc instanceof InvocationTargetException && exc.getCause() != null &&
    270                        exc.getCause().getClass().equals(excType)) {
    271                 // Expected exception is wrapped in InvocationTargetException.
    272             } else if (!excType.equals(exc.getClass())) {
    273                 System.out.println("Expected " + excType.getName() + ", but got " + exc.getClass());
    274             } else {
    275               // Expected exception, do nothing.
    276             }
    277         }
    278     }
    279 
    280     // Helpers for the smali code.
    281     public static native void assertIsInterpreted();
    282     public static native void assertIsManaged();
    283     public static native boolean hasOatFile();
    284     public static native boolean runtimeIsSoftFail();
    285     public static native boolean isInterpreted();
    286     public static native void disableStackFrameAsserts();
    287     private static native void ensureJitCompiled(Class<?> itf, String method_name);
    288 }
    289