15fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver/*
25fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * Copyright 2013, Google Inc.
35fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * All rights reserved.
45fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver *
55fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * Redistribution and use in source and binary forms, with or without
65fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * modification, are permitted provided that the following conditions are
75fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * met:
85fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver *
95fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver *     * Redistributions of source code must retain the above copyright
105fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * notice, this list of conditions and the following disclaimer.
115fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver *     * Redistributions in binary form must reproduce the above
125fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * copyright notice, this list of conditions and the following disclaimer
135fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * in the documentation and/or other materials provided with the
145fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * distribution.
155fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver *     * Neither the name of Google Inc. nor the names of its
165fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * contributors may be used to endorse or promote products derived from
175fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * this software without specific prior written permission.
185fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver *
195fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver */
315fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
325fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverpackage org.jf.dexlib2.analysis;
335fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
345fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport com.google.common.collect.ImmutableList;
355fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport com.google.common.collect.Lists;
365fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.AccessFlags;
375fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.Opcode;
38e202aeede5fb5fcc8de22601157b212eabb5f1c6Ben Gruverimport org.jf.dexlib2.Opcodes;
395fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.iface.ClassDef;
405fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.iface.DexFile;
415fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.iface.instruction.Instruction;
425fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.iface.instruction.formats.Instruction35c;
435fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.iface.reference.MethodReference;
445fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableClassDef;
455fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableDexFile;
465fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableMethod;
475fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableMethodImplementation;
485fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.instruction.ImmutableInstruction;
495fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.instruction.ImmutableInstruction10x;
505fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.jf.dexlib2.immutable.instruction.ImmutableInstruction35mi;
515fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.junit.Assert;
525fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport org.junit.Test;
535fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
54e474301e60b89d33343586b896efd8e4b0a10b37Ben Gruverimport java.io.IOException;
555fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverimport java.util.List;
565fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
575fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruverpublic class CustomMethodInlineTableTest {
585fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    @Test
59e474301e60b89d33343586b896efd8e4b0a10b37Ben Gruver    public void testCustomMethodInlineTable_Virtual() throws IOException {
605fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        List<ImmutableInstruction> instructions = Lists.newArrayList(
615fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0),
625fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                new ImmutableInstruction10x(Opcode.RETURN_VOID));
635fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
645fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null);
655fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PUBLIC.getValue(), null,
665fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                methodImpl);
675fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
685fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null,
690a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                null, null, null, null, null, ImmutableList.of(method));
705fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
718f27f45fb1d621a6cc5ca01e1eb5cc7dc67cc994Ben Gruver        DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef));
725fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
7331ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver        ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(),
7431ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver                ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile);
7531ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver        ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART);
76e474301e60b89d33343586b896efd8e4b0a10b37Ben Gruver
775fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
78827e2db34dc3b8b5504c148a09d594b5c0ddbd64Ben Gruver        MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false);
795fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
805fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0);
815fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Assert.assertEquals(Opcode.INVOKE_VIRTUAL, deodexedInstruction.getOpcode());
825fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
835fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference();
845fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Assert.assertEquals(method, methodReference);
855fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    }
865fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
875fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    @Test
88e474301e60b89d33343586b896efd8e4b0a10b37Ben Gruver    public void testCustomMethodInlineTable_Static() throws IOException {
895fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        List<ImmutableInstruction> instructions = Lists.newArrayList(
905fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0),
915fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                new ImmutableInstruction10x(Opcode.RETURN_VOID));
925fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
935fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null);
945fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.STATIC.getValue(), null,
955fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                methodImpl);
965fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
975fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null,
980a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                null, null, null, null, ImmutableList.of(method), null);
995fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1008f27f45fb1d621a6cc5ca01e1eb5cc7dc67cc994Ben Gruver        DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef));
1015fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
10231ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver        ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(),
10331ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver                ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile);
10431ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver        ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART);
10531ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver
1065fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
107827e2db34dc3b8b5504c148a09d594b5c0ddbd64Ben Gruver        MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false);
1085fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1095fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0);
1105fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Assert.assertEquals(Opcode.INVOKE_STATIC, deodexedInstruction.getOpcode());
1115fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1125fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference();
1135fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Assert.assertEquals(method, methodReference);
1145fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    }
1155fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1165fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    @Test
117e474301e60b89d33343586b896efd8e4b0a10b37Ben Gruver    public void testCustomMethodInlineTable_Direct() throws IOException {
1185fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        List<ImmutableInstruction> instructions = Lists.newArrayList(
1195fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0),
1205fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                new ImmutableInstruction10x(Opcode.RETURN_VOID));
1215fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1225fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null);
1235fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PRIVATE.getValue(), null,
1245fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver                methodImpl);
1255fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1265fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null,
1270a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                null, null, null, null, ImmutableList.of(method), null);
1285fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1298f27f45fb1d621a6cc5ca01e1eb5cc7dc67cc994Ben Gruver        DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef));
1305fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
13131ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver        ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(),
13231ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver                ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile);
13331ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver        ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART);
13431ad2bc1002784161b318627f32b4df8bcb862e0Ben Gruver
1355fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
136827e2db34dc3b8b5504c148a09d594b5c0ddbd64Ben Gruver        MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false);
1375fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1385fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0);
1395fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Assert.assertEquals(Opcode.INVOKE_DIRECT, deodexedInstruction.getOpcode());
1405fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver
1415fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference();
1425fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver        Assert.assertEquals(method, methodReference);
1435fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    }
1445fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver}
145