Home | History | Annotate | Download | only in dexlib2
      1 /*
      2  * Copyright 2012, 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.dexlib2;
     33 
     34 import com.google.common.collect.ImmutableMap;
     35 import junit.framework.Assert;
     36 import org.jf.dexlib2.iface.ClassDef;
     37 import org.jf.dexlib2.iface.DexFile;
     38 import org.jf.dexlib2.iface.Method;
     39 import org.jf.dexlib2.iface.MethodImplementation;
     40 import org.jf.dexlib2.iface.instruction.Instruction;
     41 import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
     42 import org.jf.dexlib2.iface.reference.FieldReference;
     43 import org.jf.dexlib2.iface.reference.MethodReference;
     44 import org.jf.dexlib2.util.SyntheticAccessorResolver;
     45 import org.junit.Test;
     46 
     47 import java.io.IOException;
     48 import java.net.URL;
     49 import java.util.Map;
     50 import java.util.regex.Matcher;
     51 import java.util.regex.Pattern;
     52 
     53 public class AccessorTest {
     54     private Pattern accessorMethodPattern = Pattern.compile("([a-zA-Z]*)_([a-zA-Z]*)");
     55 
     56     private static final Map<String, Integer> operationTypes;
     57 
     58     static {
     59         ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
     60         builder.put("postinc", SyntheticAccessorResolver.POSTFIX_INCREMENT);
     61         builder.put("preinc", SyntheticAccessorResolver.PREFIX_INCREMENT);
     62         builder.put("postdec", SyntheticAccessorResolver.POSTFIX_DECREMENT);
     63         builder.put("predec", SyntheticAccessorResolver.PREFIX_DECREMENT);
     64         builder.put("add", SyntheticAccessorResolver.ADD_ASSIGNMENT);
     65         builder.put("sub", SyntheticAccessorResolver.SUB_ASSIGNMENT);
     66         builder.put("mul", SyntheticAccessorResolver.MUL_ASSIGNMENT);
     67         builder.put("div", SyntheticAccessorResolver.DIV_ASSIGNMENT);
     68         builder.put("rem", SyntheticAccessorResolver.REM_ASSIGNMENT);
     69         builder.put("and", SyntheticAccessorResolver.AND_ASSIGNMENT);
     70         builder.put("or", SyntheticAccessorResolver.OR_ASSIGNMENT);
     71         builder.put("xor", SyntheticAccessorResolver.XOR_ASSIGNMENT);
     72         builder.put("shl", SyntheticAccessorResolver.SHL_ASSIGNMENT);
     73         builder.put("shr", SyntheticAccessorResolver.SHR_ASSIGNMENT);
     74         builder.put("ushr", SyntheticAccessorResolver.USHR_ASSIGNMENT);
     75         operationTypes = builder.build();
     76     }
     77 
     78     @Test
     79     public void testAccessors() throws IOException {
     80         URL url = AccessorTest.class.getClassLoader().getResource("accessorTest.dex");
     81         Assert.assertNotNull(url);
     82         DexFile f = DexFileFactory.loadDexFile(url.getFile(), 15, false);
     83 
     84         SyntheticAccessorResolver sar = new SyntheticAccessorResolver(f.getOpcodes(), f.getClasses());
     85 
     86         ClassDef accessorTypesClass = null;
     87         ClassDef accessorsClass = null;
     88 
     89         for (ClassDef classDef: f.getClasses()) {
     90             String className = classDef.getType();
     91 
     92             if (className.equals("Lorg/jf/dexlib2/AccessorTypes;")) {
     93                 accessorTypesClass = classDef;
     94             } else if (className.equals("Lorg/jf/dexlib2/AccessorTypes$Accessors;")) {
     95                 accessorsClass = classDef;
     96             }
     97         }
     98 
     99         Assert.assertNotNull(accessorTypesClass);
    100         Assert.assertNotNull(accessorsClass);
    101 
    102         for (Method method: accessorsClass.getMethods()) {
    103             Matcher m = accessorMethodPattern.matcher(method.getName());
    104             if (!m.matches()) {
    105                 continue;
    106             }
    107             String type = m.group(1);
    108             String operation = m.group(2);
    109 
    110             MethodImplementation methodImpl = method.getImplementation();
    111             Assert.assertNotNull(methodImpl);
    112 
    113             for (Instruction instruction: methodImpl.getInstructions()) {
    114                 Opcode opcode = instruction.getOpcode();
    115                 if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) {
    116                     MethodReference accessorMethod =
    117                             (MethodReference)((ReferenceInstruction) instruction).getReference();
    118 
    119                     SyntheticAccessorResolver.AccessedMember accessedMember = sar.getAccessedMember(accessorMethod);
    120 
    121                     Assert.assertNotNull(String.format("Could not resolve accessor for %s_%s", type, operation),
    122                             accessedMember);
    123 
    124                     int operationType = operationTypes.get(operation);
    125                     Assert.assertEquals(operationType, accessedMember.accessedMemberType);
    126 
    127                     Assert.assertEquals(String.format("%s_val", type),
    128                             ((FieldReference)accessedMember.accessedMember).getName());
    129                 }
    130             }
    131         }
    132     }
    133 }
    134