• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.smalidea;
33 
34 import com.google.common.collect.Lists;
35 import com.intellij.debugger.NoDataException;
36 import com.intellij.debugger.PositionManager;
37 import com.intellij.debugger.SourcePosition;
38 import com.intellij.debugger.engine.DebugProcess;
39 import com.intellij.debugger.engine.DebugProcessListener;
40 import com.intellij.debugger.engine.evaluation.EvaluateException;
41 import com.intellij.debugger.engine.evaluation.EvaluationContext;
42 import com.intellij.debugger.engine.jdi.VirtualMachineProxy;
43 import com.intellij.debugger.engine.managerThread.DebuggerManagerThread;
44 import com.intellij.debugger.requests.RequestManager;
45 import com.intellij.execution.ExecutionResult;
46 import com.intellij.execution.process.ProcessHandler;
47 import com.intellij.openapi.project.Project;
48 import com.intellij.openapi.util.Key;
49 import com.intellij.psi.search.GlobalSearchScope;
50 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
51 import com.sun.jdi.*;
52 import org.jetbrains.annotations.NotNull;
53 import org.jf.dexlib2.Opcode;
54 import org.jf.smalidea.debugging.SmaliPositionManager;
55 import org.jf.smalidea.psi.impl.SmaliInstruction;
56 import org.junit.Assert;
57 
58 import java.util.List;
59 import java.util.Map;
60 
61 public class SmaliPositionManagerTest extends LightCodeInsightFixtureTestCase {
62     private static final String testClass =
63             "\n\n.class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" +
64                     ".method public getRandomParentType(I)I\n" +
65                     "    .registers 4\n" +
66                     "    .param p1, \"edge\"    # I\n" +
67                     "\n" +
68                     "    .prologue\n" +
69                     "    const/4 v1, 0x2\n" +
70                     "\n" +
71                     "    .line 179\n" +
72                     "    if-nez p1, :cond_5\n" +
73                     "\n" +
74                     "    move v0, v1\n" +
75                     "\n" +
76                     "    .line 185\n" +
77                     "    :goto_4\n" +
78                     "    return v0\n" +
79                     "\n" +
80                     "    .line 182\n" +
81                     "    :cond_5\n" +
82                     "    if-ne p1, v1, :cond_f\n" +
83                     "\n" +
84                     "    .line 183\n" +
85                     "    sget-object v0, Lorg/jf/Penroser/PenroserApp;->random:Ljava/util/Random;\n" +
86                     "\n" +
87                     "    const/4 v1, 0x3\n" +
88                     "\n" +
89                     "    invoke-virtual {v0, v1}, Ljava/util/Random;->nextInt(I)I\n" +
90                     "\n" +
91                     "    move-result v0\n" +
92                     "\n" +
93                     "    goto :goto_4\n" +
94                     "\n" +
95                     "    .line 185\n" +
96                     "    :cond_f\n" +
97                     "    sget-object v0, Lorg/jf/Penroser/PenroserApp;->random:Ljava/util/Random;\n" +
98                     "\n" +
99                     "    invoke-virtual {v0, v1}, Ljava/util/Random;->nextInt(I)I\n" +
100                     "\n" +
101                     "    move-result v0\n" +
102                     "\n" +
103                     "    goto :goto_4\n" +
104                     ".end method";
105 
testGetSourcePosition()106     public void testGetSourcePosition() throws NoDataException {
107         myFixture.addFileToProject("my/pkg/blah.smali", testClass);
108 
109         SmaliPositionManager positionManager = new SmaliPositionManager(new MockDebugProcess());
110 
111         SourcePosition sourcePosition = positionManager.getSourcePosition(
112                 "my.pkg.blah", "getRandomParentType", "(I)I", 0);
113         Assert.assertEquals(Opcode.CONST_4, ((SmaliInstruction)sourcePosition.getElementAt()).getOpcode());
114         Assert.assertEquals(0, ((SmaliInstruction)sourcePosition.getElementAt()).getOffset());
115 
116         sourcePosition = positionManager.getSourcePosition("my.pkg.blah", "getRandomParentType", "(I)I", 10);
117         Assert.assertEquals(Opcode.INVOKE_VIRTUAL, ((SmaliInstruction)sourcePosition.getElementAt()).getOpcode());
118         Assert.assertEquals(20, ((SmaliInstruction)sourcePosition.getElementAt()).getOffset());
119     }
120 
testGetAllClasses()121     public void testGetAllClasses() throws NoDataException {
122         myFixture.addFileToProject("my/pkg/blah.smali", testClass);
123 
124         SmaliPositionManager positionManager = new SmaliPositionManager(new MockDebugProcess());
125 
126         List<ReferenceType> classes = positionManager.getAllClasses(positionManager.getSourcePosition(
127                 "my.pkg.blah", "getRandomParentType", "(I)I", 0));
128         Assert.assertEquals(1, classes.size());
129         Assert.assertEquals("my.pkg.blah", classes.get(0).name());
130     }
131 
132     private class MockDebugProcess implements DebugProcess {
getProject()133         @Override public Project getProject() {
134             return SmaliPositionManagerTest.this.getProject();
135         }
136 
getVirtualMachineProxy()137         @Override public VirtualMachineProxy getVirtualMachineProxy() {
138             return new VirtualMachineProxy() {
139                 @Override public List<ReferenceType> classesByName(final String s) {
140                     return Lists.<ReferenceType>newArrayList(new MockReferenceType(s));
141                 }
142 
143                 @Override public List<ReferenceType> allClasses() { return null; }
144                 @Override public boolean canGetBytecodes() { return false; }
145                 @Override public boolean versionHigher(String version) { return false; }
146                 @Override public boolean canWatchFieldModification() { return false; }
147                 @Override public boolean canWatchFieldAccess() { return false; }
148                 @Override public boolean canInvokeMethods() { return false; }
149                 @Override public DebugProcess getDebugProcess() { return null; }
150                 @Override public List<ReferenceType> nestedTypes(ReferenceType refType) { return null; }
151             };
152         }
153 
addDebugProcessListener(DebugProcessListener listener)154         @Override public void addDebugProcessListener(DebugProcessListener listener) {}
getUserData(Key<T> key)155         @Override public <T> T getUserData(Key<T> key) { return null; }
putUserData(Key<T> key, T value)156         @Override public <T> void putUserData(Key<T> key, T value) {}
getRequestsManager()157         @Override public RequestManager getRequestsManager() { return null; }
getPositionManager()158         @Override public PositionManager getPositionManager() { return null; }
removeDebugProcessListener(DebugProcessListener listener)159         @Override public void removeDebugProcessListener(DebugProcessListener listener) {}
appendPositionManager(PositionManager positionManager)160         @Override public void appendPositionManager(PositionManager positionManager) {}
waitFor()161         @Override public void waitFor() {}
waitFor(long timeout)162         @Override public void waitFor(long timeout) {}
stop(boolean forceTerminate)163         @Override public void stop(boolean forceTerminate) {}
getExecutionResult()164         @Override public ExecutionResult getExecutionResult() { return null; }
getManagerThread()165         @Override public DebuggerManagerThread getManagerThread() { return null; }
invokeMethod(EvaluationContext evaluationContext, ObjectReference objRef, Method method, List args)166         @Override public Value invokeMethod(EvaluationContext evaluationContext, ObjectReference objRef, Method method, List args) throws EvaluateException { return null; }
invokeMethod(EvaluationContext evaluationContext, ClassType classType, Method method, List args)167         @Override public Value invokeMethod(EvaluationContext evaluationContext, ClassType classType, Method method, List args) throws EvaluateException { return null; }
invokeInstanceMethod(EvaluationContext evaluationContext, ObjectReference objRef, Method method, List args, int invocationOptions)168         @Override public Value invokeInstanceMethod(EvaluationContext evaluationContext, ObjectReference objRef, Method method, List args, int invocationOptions) throws EvaluateException { return null; }
findClass(EvaluationContext evaluationContext, String name, ClassLoaderReference classLoader)169         @Override public ReferenceType findClass(EvaluationContext evaluationContext, String name, ClassLoaderReference classLoader) throws EvaluateException { return null; }
newInstance(ArrayType arrayType, int dimension)170         @Override public ArrayReference newInstance(ArrayType arrayType, int dimension) throws EvaluateException { return null; }
newInstance(EvaluationContext evaluationContext, ClassType classType, Method constructor, List paramList)171         @Override public ObjectReference newInstance(EvaluationContext evaluationContext, ClassType classType, Method constructor, List paramList) throws EvaluateException { return null; }
isAttached()172         @Override public boolean isAttached() { return false; }
isDetached()173         @Override public boolean isDetached() { return false; }
isDetaching()174         @Override public boolean isDetaching() { return false; }
getSearchScope()175         @NotNull @Override public GlobalSearchScope getSearchScope() { return null; }
printToConsole(String text)176         @Override public void printToConsole(String text) {}
getProcessHandler()177         @Override public ProcessHandler getProcessHandler() { return null; }
178     }
179 
180     private static class MockReferenceType implements ReferenceType {
181         private final String name;
182 
183         public MockReferenceType(String name) {
184             this.name = name;
185         }
186 
187         @Override public String name() {
188             return name;
189         }
190 
191         @Override public List<Field> allFields() { return null; }
192         @Override public String genericSignature() { return null; }
193         @Override public ClassLoaderReference classLoader() { return null; }
194         @Override public String sourceName() throws AbsentInformationException { return null; }
195         @Override public List<String> sourceNames(String s) throws AbsentInformationException { return null; }
196         @Override public List<String> sourcePaths(String s) throws AbsentInformationException { return null; }
197         @Override public String sourceDebugExtension() throws AbsentInformationException { return null; }
198         @Override public boolean isStatic() { return false; }
199         @Override public boolean isAbstract() { return false; }
200         @Override public boolean isFinal() { return false; }
201         @Override public boolean isPrepared() { return false; }
202         @Override public boolean isVerified() { return false; }
203         @Override public boolean isInitialized() { return false; }
204         @Override public boolean failedToInitialize() { return false; }
205         @Override public List<Field> fields() { return null; }
206         @Override public List<Field> visibleFields() { return null; }
207         @Override public Field fieldByName(String s) { return null; }
208         @Override public List<Method> methods() { return null; }
209         @Override public List<Method> visibleMethods() { return null; }
210         @Override public List<Method> allMethods() { return null; }
211         @Override public List<Method> methodsByName(String s) { return null; }
212         @Override public List<Method> methodsByName(String s, String s1) { return null; }
213         @Override public List<ReferenceType> nestedTypes() { return null; }
214         @Override public Value getValue(Field field) { return null; }
215         @Override public Map<Field, Value> getValues(List<? extends Field> list) { return null; }
216         @Override public ClassObjectReference classObject() { return null; }
217         @Override public List<Location> allLineLocations() throws AbsentInformationException { return null; }
218         @Override public List<Location> allLineLocations(String s, String s1) throws AbsentInformationException { return null; }
219         @Override public List<Location> locationsOfLine(int i) throws AbsentInformationException { return null; }
220         @Override public List<Location> locationsOfLine(String s, String s1, int i) throws AbsentInformationException { return null; }
221         @Override public List<String> availableStrata() { return null; }
222         @Override public String defaultStratum() { return null; }
223         @Override public List<ObjectReference> instances(long l) { return null; }
224         @Override public int majorVersion() { return 0; }
225         @Override public int minorVersion() { return 0; }
226         @Override public int constantPoolCount() { return 0; }
227         @Override public byte[] constantPool() { return new byte[0]; }
228         @Override public int modifiers() { return 0; }
229         @Override public boolean isPrivate() { return false; }
230         @Override public boolean isPackagePrivate() { return false; }
231         @Override public boolean isProtected() { return false; }
232         @Override public boolean isPublic() { return false; }
233         @Override public int compareTo(ReferenceType o) { return 0; }
234         @Override public String signature() { return null; }
235         @Override public VirtualMachine virtualMachine() { return null; }
236     }
237 }
238