aboutsummaryrefslogtreecommitdiff
path: root/smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java
diff options
context:
space:
mode:
authorAlex Light <allight@google.com>2016-04-08 14:42:05 -0700
committerAlex Light <allight@google.com>2016-04-08 14:42:05 -0700
commitedc88aff44ff80f969df61725a992680cd0c464c (patch)
tree53e8ba5a33270814a3df2bf493967a8eb15ca33f /smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java
parent504acc06a865d5b0e2d3e08111ffe71ccea8ca26 (diff)
parent267cf99aae855d3d8cbd2b919f3e9aeceabfb7c3 (diff)
downloadsmali-edc88aff44ff80f969df61725a992680cd0c464c.tar.gz
Merge commit 'refs/changes/32/214432/1' of persistent-https://android.git.corp.google.com/platform/external/smali into incr-dexandroid-cts_7.1_r1android-cts-7.1_r9android-cts-7.1_r8android-cts-7.1_r7android-cts-7.1_r6android-cts-7.1_r5android-cts-7.1_r4android-cts-7.1_r3android-cts-7.1_r29android-cts-7.1_r28android-cts-7.1_r27android-cts-7.1_r26android-cts-7.1_r25android-cts-7.1_r24android-cts-7.1_r23android-cts-7.1_r22android-cts-7.1_r21android-cts-7.1_r20android-cts-7.1_r2android-cts-7.1_r19android-cts-7.1_r18android-cts-7.1_r17android-cts-7.1_r16android-cts-7.1_r15android-cts-7.1_r14android-cts-7.1_r13android-cts-7.1_r12android-cts-7.1_r11android-cts-7.1_r10android-cts-7.1_r1android-cts-7.0_r9android-cts-7.0_r8android-cts-7.0_r7android-cts-7.0_r6android-cts-7.0_r5android-cts-7.0_r4android-cts-7.0_r33android-cts-7.0_r32android-cts-7.0_r31android-cts-7.0_r30android-cts-7.0_r3android-cts-7.0_r29android-cts-7.0_r28android-cts-7.0_r27android-cts-7.0_r26android-cts-7.0_r25android-cts-7.0_r24android-cts-7.0_r23android-cts-7.0_r22android-cts-7.0_r21android-cts-7.0_r20android-cts-7.0_r2android-cts-7.0_r19android-cts-7.0_r18android-cts-7.0_r17android-cts-7.0_r16android-cts-7.0_r15android-cts-7.0_r14android-cts-7.0_r13android-cts-7.0_r12android-cts-7.0_r11android-cts-7.0_r10android-cts-7.0_r1android-7.1.2_r9android-7.1.2_r8android-7.1.2_r6android-7.1.2_r5android-7.1.2_r4android-7.1.2_r39android-7.1.2_r38android-7.1.2_r37android-7.1.2_r36android-7.1.2_r33android-7.1.2_r32android-7.1.2_r30android-7.1.2_r3android-7.1.2_r29android-7.1.2_r28android-7.1.2_r27android-7.1.2_r25android-7.1.2_r24android-7.1.2_r23android-7.1.2_r2android-7.1.2_r19android-7.1.2_r18android-7.1.2_r17android-7.1.2_r16android-7.1.2_r15android-7.1.2_r14android-7.1.2_r13android-7.1.2_r12android-7.1.2_r11android-7.1.2_r10android-7.1.2_r1android-7.1.1_r9android-7.1.1_r8android-7.1.1_r7android-7.1.1_r61android-7.1.1_r60android-7.1.1_r6android-7.1.1_r59android-7.1.1_r58android-7.1.1_r57android-7.1.1_r56android-7.1.1_r55android-7.1.1_r54android-7.1.1_r53android-7.1.1_r52android-7.1.1_r51android-7.1.1_r50android-7.1.1_r49android-7.1.1_r48android-7.1.1_r47android-7.1.1_r46android-7.1.1_r45android-7.1.1_r44android-7.1.1_r43android-7.1.1_r42android-7.1.1_r41android-7.1.1_r40android-7.1.1_r4android-7.1.1_r39android-7.1.1_r38android-7.1.1_r35android-7.1.1_r33android-7.1.1_r32android-7.1.1_r31android-7.1.1_r3android-7.1.1_r28android-7.1.1_r27android-7.1.1_r26android-7.1.1_r25android-7.1.1_r24android-7.1.1_r23android-7.1.1_r22android-7.1.1_r21android-7.1.1_r20android-7.1.1_r2android-7.1.1_r17android-7.1.1_r16android-7.1.1_r15android-7.1.1_r14android-7.1.1_r13android-7.1.1_r12android-7.1.1_r11android-7.1.1_r10android-7.1.1_r1android-7.1.0_r7android-7.1.0_r6android-7.1.0_r5android-7.1.0_r4android-7.1.0_r3android-7.1.0_r2android-7.1.0_r1android-7.0.0_r9android-7.0.0_r8android-7.0.0_r7android-7.0.0_r6android-7.0.0_r5android-7.0.0_r4android-7.0.0_r36android-7.0.0_r35android-7.0.0_r34android-7.0.0_r33android-7.0.0_r32android-7.0.0_r31android-7.0.0_r30android-7.0.0_r3android-7.0.0_r29android-7.0.0_r28android-7.0.0_r27android-7.0.0_r24android-7.0.0_r21android-7.0.0_r19android-7.0.0_r17android-7.0.0_r15android-7.0.0_r14android-7.0.0_r13android-7.0.0_r12android-7.0.0_r11android-7.0.0_r10android-7.0.0_r1nougat-releasenougat-mr2.3-releasenougat-mr2.2-releasenougat-mr2.1-releasenougat-mr2-security-releasenougat-mr2-releasenougat-mr2-pixel-releasenougat-mr2-devnougat-mr1.8-releasenougat-mr1.7-releasenougat-mr1.6-releasenougat-mr1.5-releasenougat-mr1.4-releasenougat-mr1.3-releasenougat-mr1.2-releasenougat-mr1.1-releasenougat-mr1-volantis-releasenougat-mr1-security-releasenougat-mr1-releasenougat-mr1-flounder-releasenougat-mr1-devnougat-mr1-cts-releasenougat-mr0.5-releasenougat-dr1-releasenougat-devnougat-cts-releasenougat-bugfix-release
- Merges in upstream smali into nyc-dev for dex version 37 support. Bug: 27809626 Change-Id: Iff12b1e384355bcb261b55afd16af3bcac6ef1a0
Diffstat (limited to 'smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java')
-rw-r--r--smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java279
1 files changed, 279 insertions, 0 deletions
diff --git a/smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java b/smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java
new file mode 100644
index 00000000..c61d3e44
--- /dev/null
+++ b/smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jf.smalidea;
+
+import com.google.common.collect.Sets;
+import com.intellij.codeInsight.CodeInsightTestCase;
+import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
+import com.intellij.codeInsight.completion.CompletionType;
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupManager;
+import com.intellij.debugger.NoDataException;
+import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
+import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.JavaCodeFragment;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jf.smalidea.debugging.SmaliCodeFragmentFactory;
+import org.jf.smalidea.psi.impl.SmaliFile;
+import org.junit.Assert;
+
+import java.util.HashSet;
+import java.util.List;
+
+public class SmaliCodeFragmentFactoryTest extends CodeInsightTestCase {
+ private static final String completionTestClass =
+ ".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" +
+ ".method public getRandomParentType(I)I\n" +
+ " .registers 4\n" +
+ " .param p1, \"edge\" # I\n" +
+ "\n" +
+ " .prologue\n" +
+ " const/4 v1, 0x2\n" + // 0
+ "\n" +
+ " .line 179\n" +
+ " if-nez p1, :cond_5\n" +
+ "\n" +
+ " move v0, v1\n" + // 2
+ "\n" +
+ " .line 185\n" +
+ " :goto_4\n" +
+ " return v0\n" +
+ "\n" +
+ " .line 182\n" +
+ " :cond_5\n" +
+ " if-ne p1, v1, :cond_f\n" +
+ "\n" +
+ " .line 183\n" +
+ " sget-object v0, Lorg/jf/Penroser/PenroserApp;->random:Ljava/util/Random;\n" +
+ "\n" +
+ " const/4 v1, 0x3\n" + // 6
+ "\n" +
+ " invoke-virtual {v0, v1}, Ljava/util/Random;->nextInt(I)I\n" +
+ "\n" +
+ " move-result v0\n" +
+ "\n" +
+ " goto :goto_4\n" +
+ "\n" +
+ " .line 185\n" +
+ " :cond_f\n" +
+ " sget-object v0, Lorg/jf/Penroser/PenroserApp;->random:Ljava/util/Random;\n" +
+ "\n" +
+ " invoke-virtual {v0, v1}, Ljava/util/Random;->nextInt(I)I\n" +
+ "\n" +
+ " move-result v0\n" +
+ "\n" +
+ " goto :goto_4\n" +
+ ".end method";
+
+ public void testCompletion() throws NoDataException {
+ SmaliFile smaliFile = (SmaliFile)configureByText(SmaliFileType.INSTANCE, completionTestClass);
+
+ PsiElement context = smaliFile.getPsiClass().getMethods()[0].getInstructions().get(0);
+ assertCompletionContains("v", context, new String[] {"v2", "v3"}, new String[] {"v0", "v1", "p0", "p1"});
+ assertCompletionContains("p", context, new String[] {"p0", "p1"}, new String[] {"v0", "v1", "v2", "v3"});
+
+ context = smaliFile.getPsiClass().getMethods()[0].getInstructions().get(2);
+ assertCompletionContains("v", context, new String[] {"v1", "v2", "v3"}, new String[] {"v0", "p0", "p1"});
+ assertCompletionContains("p", context, new String[] {"p0", "p1"}, new String[] {"v0", "v1", "v2", "v3"});
+
+ context = smaliFile.getPsiClass().getMethods()[0].getInstructions().get(6);
+ assertCompletionContains("v", context, new String[] {"v0", "v1", "v2", "v3"}, new String[] {"p0", "p1"});
+ assertCompletionContains("p", context, new String[] {"p0", "p1"}, new String[] {});
+ }
+
+ private static final String registerTypeTestText = "" +
+ ".class public LRegisterTypeTest;\n" +
+ ".super Ljava/lang/Object;\n" +
+ "\n" +
+ "# virtual methods\n" +
+ ".method public blah()V\n" +
+ " .registers 6\n" +
+ "\n" +
+ " .prologue\n" +
+ " const/16 v3, 0xa\n" +
+ "\n" +
+ " .line 7\n" +
+ " new-instance v0, Ljava/util/Random;\n" +
+ "\n" +
+ " invoke-direct {v0}, Ljava/util/Random;-><init>()V\n" +
+ "\n" +
+ " .line 9\n" +
+ " invoke-virtual {v0, v3}, Ljava/util/Random;->nextInt(I)I\n" +
+ "\n" +
+ " move-result v1\n" +
+ "\n" +
+ " const/4 v2, 0x5\n" +
+ "\n" +
+ " if-le v1, v2, :cond_26\n" +
+ "\n" +
+ " .line 10\n" +
+ " new-instance v1, Ljava/security/SecureRandom;\n" +
+ "\n" +
+ " invoke-direct {v1}, Ljava/security/SecureRandom;-><init>()V\n" +
+ "\n" +
+ " .line 14\n" +
+ " :goto_13\n" +
+ " sget-o<ref>bject v2, Ljava/lang/System;->out:Ljava/io/PrintStream;\n" +
+ "\n" +
+ " invoke-virtual {v1, v3}, Ljava/util/Random;->nextInt(I)I\n" +
+ "\n" +
+ " move-result v1\n" +
+ "\n" +
+ " invoke-virtual {v2, v1}, Ljava/io/PrintStream;->println(I)V\n" +
+ "\n" +
+ " .line 15\n" +
+ " sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;\n" +
+ "\n" +
+ " invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;\n" +
+ "\n" +
+ " move-result-object v0\n" +
+ "\n" +
+ " invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V\n" +
+ "\n" +
+ " .line 16\n" +
+ " return-void\n" +
+ "\n" +
+ " .line 12\n" +
+ " :cond_26\n" +
+ " invoke-virtual {p0}, LRegisterTypeTest;->getSerializable()Ljava/io/Serializable;\n" +
+ "\n" +
+ " move-result-object v1\n" +
+ "\n" +
+ " move-object v4, v1\n" +
+ "\n" +
+ " move-object v1, v0\n" +
+ "\n" +
+ " move-object v0, v4\n" +
+ "\n" +
+ " goto :goto_13\n" +
+ ".end method\n" +
+ "\n" +
+ ".method public getSerializable()Ljava/io/Serializable;\n" +
+ " .registers 2\n" +
+ "\n" +
+ " .prologue\n" +
+ " .line 19\n" +
+ " new-instance v0, Ljava/util/Random;\n" +
+ "\n" +
+ " invoke-direct {v0}, Ljava/util/Random;-><init>()V\n" +
+ "\n" +
+ " return-object v0\n" +
+ ".end method\n";
+
+ public void testRegisterType() throws NoDataException {
+ SmaliFile smaliFile = (SmaliFile)configureByText(SmaliFileType.INSTANCE,
+ registerTypeTestText.replace("<ref>", ""));
+
+ int refOffset = registerTypeTestText.indexOf("<ref>");
+
+ PsiElement context = smaliFile.findElementAt(refOffset);
+ assertVariableType(context.getParent(), "v1", "java.util.Random");
+ assertVariableType(context.getParent(), "v0", "java.io.Serializable");
+ }
+
+ public void testUnknownClass() {
+ String modifiedText = registerTypeTestText.replace("Random", "Rnd");
+ SmaliFile smaliFile = (SmaliFile)configureByText(SmaliFileType.INSTANCE,
+ modifiedText.replace("<ref>", ""));
+
+ int refOffset = modifiedText.indexOf("<ref>");
+
+ PsiElement context = smaliFile.findElementAt(refOffset);
+ assertVariableType(context.getParent(), "v1", "java.lang.Object");
+ assertVariableType(context.getParent(), "v0", "java.lang.Object");
+ }
+
+ private void assertCompletionContains(String completionText, PsiElement context, String[] expectedItems,
+ String[] disallowedItems) {
+ SmaliCodeFragmentFactory codeFragmentFactory = new SmaliCodeFragmentFactory();
+ JavaCodeFragment fragment = codeFragmentFactory.createCodeFragment(
+ new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, completionText),
+ context, getProject());
+
+ Editor editor = createEditor(fragment.getVirtualFile());
+ editor.getCaretModel().moveToOffset(completionText.length());
+
+ new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(getProject(), editor);
+ List<LookupElement> elements = LookupManager.getInstance(getProject()).getActiveLookup().getItems();
+
+ HashSet expectedSet = Sets.newHashSet(expectedItems);
+ HashSet disallowedSet = Sets.newHashSet(disallowedItems);
+
+ for (LookupElement element: elements) {
+ expectedSet.remove(element.toString());
+ Assert.assertFalse(disallowedSet.contains(element.toString()));
+ }
+
+ Assert.assertTrue(expectedSet.size() == 0);
+ }
+
+ private void assertVariableType(PsiElement context, String variableName, String expectedType) {
+ SmaliCodeFragmentFactory codeFragmentFactory = new SmaliCodeFragmentFactory();
+ JavaCodeFragment fragment = codeFragmentFactory.createCodeFragment(
+ new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, variableName),
+ context, getProject());
+
+ Editor editor = createEditor(fragment.getVirtualFile());
+ editor.getCaretModel().moveToOffset(1);
+
+ PsiElement element = fragment.findElementAt(0);
+ Assert.assertTrue(element.getParent() instanceof PsiReferenceExpressionImpl);
+ PsiReferenceExpressionImpl reference = (PsiReferenceExpressionImpl)element.getParent();
+ Assert.assertEquals(expectedType, reference.getType().getCanonicalText());
+ }
+
+ protected Editor createEditor(@NotNull VirtualFile file) {
+ PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+ Editor editor = FileEditorManager.getInstance(getProject()).openTextEditor(
+ new OpenFileDescriptor(getProject(), file, 0), false);
+ DaemonCodeAnalyzer.getInstance(getProject()).restart();
+
+ ((EditorImpl)editor).setCaretActive();
+ return editor;
+ }
+
+ @Override
+ protected Sdk getTestProjectJdk() {
+ return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
+ }
+}