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