1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ahat; 18 19 import com.android.ahat.proguard.ProguardMap; 20 import java.io.IOException; 21 import java.io.StringReader; 22 import java.text.ParseException; 23 import org.junit.Test; 24 import static org.junit.Assert.assertEquals; 25 26 public class ProguardMapTest { 27 private static final String TEST_MAP = 28 "# compiler: richard\n" 29 + "# compiler_version: 3.0-dev\n" 30 + "# min_api: 10000\n" 31 + "# compiler_hash: b7e25308967a577aa1f05a4b5a745c26\n" 32 + "class.that.is.Empty -> a:\n" 33 + "class.that.is.Empty$subclass -> b:\n" 34 + "class.with.only.Fields -> c:\n" 35 + " int prim_type_field -> a\n" 36 + " int[] prim_array_type_field -> b\n" 37 + " class.that.is.Empty class_type_field -> c\n" 38 + " class.that.is.Empty[] array_type_field -> d\n" 39 + " int longObfuscatedNameField -> abc\n" 40 + "class.with.Methods -> d:\n" 41 + " int some_field -> a\n" 42 + " 12:23:void <clinit>() -> <clinit>\n" 43 + " 42:43:void boringMethod() -> m\n" 44 + " 45:48:void methodWithPrimArgs(int,float) -> m\n" 45 + " 49:50:void methodWithPrimArrArgs(int[],float) -> m\n" 46 + " 52:55:void methodWithClearObjArg(class.not.in.Map) -> m\n" 47 + " 57:58:void methodWithClearObjArrArg(class.not.in.Map[]) -> m\n" 48 + " 59:61:void methodWithObfObjArg(class.with.only.Fields) -> m\n" 49 + " 64:66:class.with.only.Fields methodWithObfRes() -> n\n" 50 + " 80:80:void lineObfuscatedMethod():8:8 -> o\n" 51 + " 100:105:void lineObfuscatedMethod():50 -> o\n" 52 + " 90:94:void lineObfuscatedMethod2():9 -> p\n" 53 ; 54 55 @Test proguardMap()56 public void proguardMap() throws IOException, ParseException { 57 ProguardMap map = new ProguardMap(); 58 59 // An empty proguard map should not deobfuscate anything. 60 assertEquals("foo.bar.Sludge", map.getClassName("foo.bar.Sludge")); 61 assertEquals("fooBarSludge", map.getClassName("fooBarSludge")); 62 assertEquals("myfield", map.getFieldName("foo.bar.Sludge", "myfield")); 63 assertEquals("myfield", map.getFieldName("fooBarSludge", "myfield")); 64 ProguardMap.Frame frame = map.getFrame( 65 "foo.bar.Sludge", "mymethod", "(Lfoo/bar/Sludge;)V", "SourceFile.java", 123); 66 assertEquals("mymethod", frame.method); 67 assertEquals("(Lfoo/bar/Sludge;)V", frame.signature); 68 assertEquals("SourceFile.java", frame.filename); 69 assertEquals(123, frame.line); 70 71 // Read in the proguard map. 72 map.readFromReader(new StringReader(TEST_MAP)); 73 74 // It should still not deobfuscate things that aren't in the map 75 assertEquals("foo.bar.Sludge", map.getClassName("foo.bar.Sludge")); 76 assertEquals("fooBarSludge", map.getClassName("fooBarSludge")); 77 assertEquals("myfield", map.getFieldName("foo.bar.Sludge", "myfield")); 78 assertEquals("myfield", map.getFieldName("fooBarSludge", "myfield")); 79 frame = map.getFrame("foo.bar.Sludge", "mymethod", "(Lfoo/bar/Sludge;)V", 80 "SourceFile.java", 123); 81 assertEquals("mymethod", frame.method); 82 assertEquals("(Lfoo/bar/Sludge;)V", frame.signature); 83 assertEquals("SourceFile.java", frame.filename); 84 assertEquals(123, frame.line); 85 86 // Test deobfuscation of class names 87 assertEquals("class.that.is.Empty", map.getClassName("a")); 88 assertEquals("class.that.is.Empty$subclass", map.getClassName("b")); 89 assertEquals("class.with.only.Fields", map.getClassName("c")); 90 assertEquals("class.with.Methods", map.getClassName("d")); 91 92 // Test deobfuscation of array classes. 93 assertEquals("class.with.Methods[]", map.getClassName("d[]")); 94 assertEquals("class.with.Methods[][]", map.getClassName("d[][]")); 95 96 // Test deobfuscation of methods 97 assertEquals("prim_type_field", map.getFieldName("class.with.only.Fields", "a")); 98 assertEquals("prim_array_type_field", map.getFieldName("class.with.only.Fields", "b")); 99 assertEquals("class_type_field", map.getFieldName("class.with.only.Fields", "c")); 100 assertEquals("array_type_field", map.getFieldName("class.with.only.Fields", "d")); 101 assertEquals("longObfuscatedNameField", map.getFieldName("class.with.only.Fields", "abc")); 102 assertEquals("some_field", map.getFieldName("class.with.Methods", "a")); 103 104 // Test deobfuscation of frames 105 frame = map.getFrame("class.with.Methods", "<clinit>", "()V", "SourceFile.java", 13); 106 assertEquals("<clinit>", frame.method); 107 assertEquals("()V", frame.signature); 108 assertEquals("Methods.java", frame.filename); 109 assertEquals(13, frame.line); 110 111 frame = map.getFrame("class.with.Methods", "m", "()V", "SourceFile.java", 42); 112 assertEquals("boringMethod", frame.method); 113 assertEquals("()V", frame.signature); 114 assertEquals("Methods.java", frame.filename); 115 assertEquals(42, frame.line); 116 117 frame = map.getFrame("class.with.Methods", "m", "(IF)V", "SourceFile.java", 45); 118 assertEquals("methodWithPrimArgs", frame.method); 119 assertEquals("(IF)V", frame.signature); 120 assertEquals("Methods.java", frame.filename); 121 assertEquals(45, frame.line); 122 123 frame = map.getFrame("class.with.Methods", "m", "([IF)V", "SourceFile.java", 49); 124 assertEquals("methodWithPrimArrArgs", frame.method); 125 assertEquals("([IF)V", frame.signature); 126 assertEquals("Methods.java", frame.filename); 127 assertEquals(49, frame.line); 128 129 frame = map.getFrame("class.with.Methods", "m", "(Lclass/not/in/Map;)V", 130 "SourceFile.java", 52); 131 assertEquals("methodWithClearObjArg", frame.method); 132 assertEquals("(Lclass/not/in/Map;)V", frame.signature); 133 assertEquals("Methods.java", frame.filename); 134 assertEquals(52, frame.line); 135 136 frame = map.getFrame("class.with.Methods", "m", "([Lclass/not/in/Map;)V", 137 "SourceFile.java", 57); 138 assertEquals("methodWithClearObjArrArg", frame.method); 139 assertEquals("([Lclass/not/in/Map;)V", frame.signature); 140 assertEquals("Methods.java", frame.filename); 141 assertEquals(57, frame.line); 142 143 frame = map.getFrame("class.with.Methods", "m", "(Lc;)V", "SourceFile.java", 59); 144 assertEquals("methodWithObfObjArg", frame.method); 145 assertEquals("(Lclass/with/only/Fields;)V", frame.signature); 146 assertEquals("Methods.java", frame.filename); 147 assertEquals(59, frame.line); 148 149 frame = map.getFrame("class.with.Methods", "n", "()Lc;", "SourceFile.java", 64); 150 assertEquals("methodWithObfRes", frame.method); 151 assertEquals("()Lclass/with/only/Fields;", frame.signature); 152 assertEquals("Methods.java", frame.filename); 153 assertEquals(64, frame.line); 154 155 frame = map.getFrame("class.with.Methods", "o", "()V", "SourceFile.java", 80); 156 assertEquals("lineObfuscatedMethod", frame.method); 157 assertEquals("()V", frame.signature); 158 assertEquals("Methods.java", frame.filename); 159 assertEquals(8, frame.line); 160 161 frame = map.getFrame("class.with.Methods", "o", "()V", "SourceFile.java", 103); 162 assertEquals("lineObfuscatedMethod", frame.method); 163 assertEquals("()V", frame.signature); 164 assertEquals("Methods.java", frame.filename); 165 assertEquals(53, frame.line); 166 167 frame = map.getFrame("class.with.Methods", "p", "()V", "SourceFile.java", 94); 168 assertEquals("lineObfuscatedMethod2", frame.method); 169 assertEquals("()V", frame.signature); 170 assertEquals("Methods.java", frame.filename); 171 assertEquals(13, frame.line); 172 173 // Some methods may not have been obfuscated. We should still be able 174 // to compute the filename properly. 175 frame = map.getFrame("class.with.Methods", "unObfuscatedMethodName", 176 "()V", "SourceFile.java", 0); 177 assertEquals("Methods.java", frame.filename); 178 } 179 } 180