diff options
author | Alex Light <allight@google.com> | 2016-04-08 14:42:05 -0700 |
---|---|---|
committer | Alex Light <allight@google.com> | 2016-04-08 14:42:05 -0700 |
commit | edc88aff44ff80f969df61725a992680cd0c464c (patch) | |
tree | 53e8ba5a33270814a3df2bf493967a8eb15ca33f /smalidea/src/test/java/org/jf/smalidea/SmaliCodeFragmentFactoryTest.java | |
parent | 504acc06a865d5b0e2d3e08111ffe71ccea8ca26 (diff) | |
parent | 267cf99aae855d3d8cbd2b919f3e9aeceabfb7c3 (diff) | |
download | smali-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.java | 279 |
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(); + } +} |