| /* |
| * Copyright (C) 2012 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. |
| */ |
| |
| package com.android.jack.transformations.ast; |
| |
| |
| import com.android.jack.Jack; |
| import com.android.jack.Options; |
| import com.android.jack.TestTools; |
| import com.android.jack.ir.ast.JBlock; |
| import com.android.jack.ir.ast.JDefinedClassOrInterface; |
| import com.android.jack.ir.ast.JLock; |
| import com.android.jack.ir.ast.JMethod; |
| import com.android.jack.ir.ast.JMethodBody; |
| import com.android.jack.ir.ast.JSession; |
| import com.android.jack.ir.ast.JStatement; |
| import com.android.jack.ir.ast.JTryStatement; |
| import com.android.jack.ir.ast.JUnlock; |
| import com.android.jack.ir.ast.JVariableRef; |
| import com.android.jack.scheduling.adapter.JDefinedClassOrInterfaceAdaptor; |
| import com.android.jack.scheduling.adapter.JMethodAdaptor; |
| import com.android.jack.transformations.parent.ParentSetterChecker; |
| import com.android.jack.util.filter.SignatureMethodFilter; |
| import com.android.sched.scheduler.PlanBuilder; |
| import com.android.sched.scheduler.Request; |
| import com.android.sched.scheduler.Scheduler; |
| import com.android.sched.scheduler.SubPlanBuilder; |
| |
| import junit.framework.Assert; |
| |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| import java.io.File; |
| import java.util.List; |
| |
| import javax.annotation.Nonnull; |
| |
| public class SynchronizedTest { |
| |
| @Nonnull |
| private static final String CLASS_BINARY_NAME = |
| "com/android/jack/synchronize/test002/jack/Synchronized2"; |
| @Nonnull |
| private static final String CLASS_SIGNATURE = "L" + CLASS_BINARY_NAME + ";"; |
| @Nonnull |
| private static final File FILE = TestTools.getJackTestFromBinaryName(CLASS_BINARY_NAME); |
| |
| @BeforeClass |
| public static void setUp() throws Exception { |
| SynchronizedTest.class.getClassLoader().setDefaultAssertionStatus(true); |
| } |
| |
| @Test |
| public void synchronizedStaticMethod() throws Exception { |
| JMethod method = buildMethodAndRunSynchronizeTransformer("syncStaticMethod(I)I"); |
| |
| Assert.assertTrue(method.isSynchronized()); |
| |
| // 0: lock, 1:try or 0: assign, 1: lock, 2: try |
| JMethodBody body = (JMethodBody) method.getBody(); |
| assert body != null; |
| List<JStatement> statements = body.getBlock().getStatements(); |
| int pos = 0; |
| JStatement jlock = statements.get(pos++); |
| if (!(jlock instanceof JLock)) { |
| jlock = statements.get(pos++); |
| } |
| |
| Assert.assertEquals(true, jlock instanceof JLock); |
| |
| JStatement tryStmt = statements.get(pos); |
| Assert.assertEquals(true, tryStmt instanceof JTryStatement); |
| JTryStatement tryBlock = (JTryStatement) tryStmt; |
| |
| JBlock finallyBlock = tryBlock.getFinallyBlock(); |
| assert finallyBlock != null; |
| Assert.assertEquals(true, finallyBlock.getStatements().get(0) instanceof JUnlock); |
| } |
| |
| @Test |
| public void synchronizedInstanceMethod() throws Exception { |
| JMethod method = buildMethodAndRunSynchronizeTransformer("syncInstanceMethod(I)I"); |
| |
| Assert.assertTrue(method.isSynchronized()); |
| |
| // 0: lock, 1:try or 0: assign, 1: lock, 2: try |
| JMethodBody body = (JMethodBody) method.getBody(); |
| assert body != null; |
| List<JStatement> statements = body.getBlock().getStatements(); |
| int pos = 0; |
| JStatement jlock = statements.get(pos++); |
| |
| Assert.assertEquals(true, jlock instanceof JLock); |
| |
| JStatement trytStmt = statements.get(pos); |
| Assert.assertEquals(true, trytStmt instanceof JTryStatement); |
| JTryStatement tryBlock = (JTryStatement) trytStmt; |
| |
| JBlock finallyBlock = tryBlock.getFinallyBlock(); |
| assert finallyBlock != null; |
| Assert.assertEquals(true, finallyBlock.getStatements().get(0) instanceof JUnlock); |
| } |
| |
| @Test |
| public void synchronizedBlock() throws Exception { |
| JMethod method = buildMethodAndRunSynchronizeTransformer("syncBlock(I)I"); |
| |
| Assert.assertTrue(!method.isSynchronized()); |
| |
| // 0:JAsg, 1: JLock, 2:JTry |
| JMethodBody body = (JMethodBody) method.getBody(); |
| assert body != null; |
| List<JStatement> statements = body.getBlock().getStatements(); |
| JStatement jlock = statements.get(1); |
| Assert.assertEquals(true, jlock instanceof JLock); |
| Assert.assertEquals(true, ((JLock)jlock).getLockExpr() instanceof JVariableRef); |
| |
| JStatement firstStmt = statements.get(2); |
| Assert.assertEquals(true, firstStmt instanceof JTryStatement); |
| JTryStatement tryBlock = (JTryStatement) firstStmt; |
| |
| JBlock finallyBlock = tryBlock.getFinallyBlock(); |
| assert finallyBlock != null; |
| Assert.assertEquals(true, finallyBlock.getStatements().get(0) instanceof JUnlock); |
| } |
| |
| private static JMethod buildMethodAndRunSynchronizeTransformer(String methodSignature) |
| throws Exception { |
| Options options = TestTools.buildCommandLineArgs(FILE); |
| options.addProperty(Options.METHOD_FILTER.getName(), "method-with-signature"); |
| options.addProperty(SignatureMethodFilter.METHOD_SIGNATURE_FILTER.getName(), |
| methodSignature); |
| JSession session = TestTools.buildJAst(options); |
| Assert.assertNotNull(session); |
| |
| Scheduler scheduler = Scheduler.getScheduler(); |
| Request sr = scheduler.createScheduleRequest(); |
| |
| sr.addSchedulables(scheduler.getAllSchedulable()); |
| sr.addInitialTagsOrMarkers(Jack.getJavaSourceInitialTagSet()); |
| |
| PlanBuilder<JSession> planBuilder = sr.getPlanBuilder(JSession.class); |
| planBuilder.append(ParentSetterChecker.class); |
| SubPlanBuilder<JDefinedClassOrInterface> typePlan = |
| planBuilder.appendSubPlan(JDefinedClassOrInterfaceAdaptor.class); |
| SubPlanBuilder<JMethod> methodPlan = typePlan.appendSubPlan(JMethodAdaptor.class); |
| methodPlan.append(ImplicitBlocks.class); |
| methodPlan.append(SynchronizeTransformer.class); |
| |
| planBuilder.getPlan().getScheduleInstance().process(session); |
| |
| JDefinedClassOrInterface type = (JDefinedClassOrInterface) |
| session.getLookup().getType(CLASS_SIGNATURE); |
| Assert.assertNotNull(type); |
| // FINDBUGS |
| assert type != null; |
| |
| JMethod foundMethod = TestTools.getMethod(type, methodSignature); |
| |
| Assert.assertNotNull(foundMethod); |
| |
| return foundMethod; |
| } |
| } |