blob: 2343b451660afe21ac32da2121a2fd6d6c8c586c [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ahat;
import com.android.ahat.proguard.ProguardMap;
import java.io.IOException;
import java.io.StringReader;
import java.text.ParseException;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ProguardMapTest {
private static final String TEST_MAP =
"# compiler: richard\n"
+ "# compiler_version: 3.0-dev\n"
+ "# min_api: 10000\n"
+ "# compiler_hash: b7e25308967a577aa1f05a4b5a745c26\n"
+ "class.that.is.Empty -> a:\n"
+ "class.that.is.Empty$subclass -> b:\n"
+ "class.with.only.Fields -> c:\n"
+ " int prim_type_field -> a\n"
+ " int[] prim_array_type_field -> b\n"
+ " class.that.is.Empty class_type_field -> c\n"
+ " class.that.is.Empty[] array_type_field -> d\n"
+ " int longObfuscatedNameField -> abc\n"
+ "class.with.Methods -> d:\n"
+ " int some_field -> a\n"
+ " 12:23:void <clinit>() -> <clinit>\n"
+ " 42:43:void boringMethod() -> m\n"
+ " 45:48:void methodWithPrimArgs(int,float) -> m\n"
+ " 49:50:void methodWithPrimArrArgs(int[],float) -> m\n"
+ " 52:55:void methodWithClearObjArg(class.not.in.Map) -> m\n"
+ " 57:58:void methodWithClearObjArrArg(class.not.in.Map[]) -> m\n"
+ " 59:61:void methodWithObfObjArg(class.with.only.Fields) -> m\n"
+ " 64:66:class.with.only.Fields methodWithObfRes() -> n\n"
+ " 80:80:void lineObfuscatedMethod():8:8 -> o\n"
+ " 100:105:void lineObfuscatedMethod():50 -> o\n"
+ " 90:94:void lineObfuscatedMethod2():9 -> p\n"
;
@Test
public void proguardMap() throws IOException, ParseException {
ProguardMap map = new ProguardMap();
// An empty proguard map should not deobfuscate anything.
assertEquals("foo.bar.Sludge", map.getClassName("foo.bar.Sludge"));
assertEquals("fooBarSludge", map.getClassName("fooBarSludge"));
assertEquals("myfield", map.getFieldName("foo.bar.Sludge", "myfield"));
assertEquals("myfield", map.getFieldName("fooBarSludge", "myfield"));
ProguardMap.Frame frame = map.getFrame(
"foo.bar.Sludge", "mymethod", "(Lfoo/bar/Sludge;)V", "SourceFile.java", 123);
assertEquals("mymethod", frame.method);
assertEquals("(Lfoo/bar/Sludge;)V", frame.signature);
assertEquals("SourceFile.java", frame.filename);
assertEquals(123, frame.line);
// Read in the proguard map.
map.readFromReader(new StringReader(TEST_MAP));
// It should still not deobfuscate things that aren't in the map
assertEquals("foo.bar.Sludge", map.getClassName("foo.bar.Sludge"));
assertEquals("fooBarSludge", map.getClassName("fooBarSludge"));
assertEquals("myfield", map.getFieldName("foo.bar.Sludge", "myfield"));
assertEquals("myfield", map.getFieldName("fooBarSludge", "myfield"));
frame = map.getFrame("foo.bar.Sludge", "mymethod", "(Lfoo/bar/Sludge;)V",
"SourceFile.java", 123);
assertEquals("mymethod", frame.method);
assertEquals("(Lfoo/bar/Sludge;)V", frame.signature);
assertEquals("SourceFile.java", frame.filename);
assertEquals(123, frame.line);
// Test deobfuscation of class names
assertEquals("class.that.is.Empty", map.getClassName("a"));
assertEquals("class.that.is.Empty$subclass", map.getClassName("b"));
assertEquals("class.with.only.Fields", map.getClassName("c"));
assertEquals("class.with.Methods", map.getClassName("d"));
// Test deobfuscation of array classes.
assertEquals("class.with.Methods[]", map.getClassName("d[]"));
assertEquals("class.with.Methods[][]", map.getClassName("d[][]"));
// Test deobfuscation of methods
assertEquals("prim_type_field", map.getFieldName("class.with.only.Fields", "a"));
assertEquals("prim_array_type_field", map.getFieldName("class.with.only.Fields", "b"));
assertEquals("class_type_field", map.getFieldName("class.with.only.Fields", "c"));
assertEquals("array_type_field", map.getFieldName("class.with.only.Fields", "d"));
assertEquals("longObfuscatedNameField", map.getFieldName("class.with.only.Fields", "abc"));
assertEquals("some_field", map.getFieldName("class.with.Methods", "a"));
// Test deobfuscation of frames
frame = map.getFrame("class.with.Methods", "<clinit>", "()V", "SourceFile.java", 13);
assertEquals("<clinit>", frame.method);
assertEquals("()V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(13, frame.line);
frame = map.getFrame("class.with.Methods", "m", "()V", "SourceFile.java", 42);
assertEquals("boringMethod", frame.method);
assertEquals("()V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(42, frame.line);
frame = map.getFrame("class.with.Methods", "m", "(IF)V", "SourceFile.java", 45);
assertEquals("methodWithPrimArgs", frame.method);
assertEquals("(IF)V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(45, frame.line);
frame = map.getFrame("class.with.Methods", "m", "([IF)V", "SourceFile.java", 49);
assertEquals("methodWithPrimArrArgs", frame.method);
assertEquals("([IF)V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(49, frame.line);
frame = map.getFrame("class.with.Methods", "m", "(Lclass/not/in/Map;)V",
"SourceFile.java", 52);
assertEquals("methodWithClearObjArg", frame.method);
assertEquals("(Lclass/not/in/Map;)V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(52, frame.line);
frame = map.getFrame("class.with.Methods", "m", "([Lclass/not/in/Map;)V",
"SourceFile.java", 57);
assertEquals("methodWithClearObjArrArg", frame.method);
assertEquals("([Lclass/not/in/Map;)V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(57, frame.line);
frame = map.getFrame("class.with.Methods", "m", "(Lc;)V", "SourceFile.java", 59);
assertEquals("methodWithObfObjArg", frame.method);
assertEquals("(Lclass/with/only/Fields;)V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(59, frame.line);
frame = map.getFrame("class.with.Methods", "n", "()Lc;", "SourceFile.java", 64);
assertEquals("methodWithObfRes", frame.method);
assertEquals("()Lclass/with/only/Fields;", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(64, frame.line);
frame = map.getFrame("class.with.Methods", "o", "()V", "SourceFile.java", 80);
assertEquals("lineObfuscatedMethod", frame.method);
assertEquals("()V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(8, frame.line);
frame = map.getFrame("class.with.Methods", "o", "()V", "SourceFile.java", 103);
assertEquals("lineObfuscatedMethod", frame.method);
assertEquals("()V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(53, frame.line);
frame = map.getFrame("class.with.Methods", "p", "()V", "SourceFile.java", 94);
assertEquals("lineObfuscatedMethod2", frame.method);
assertEquals("()V", frame.signature);
assertEquals("Methods.java", frame.filename);
assertEquals(13, frame.line);
// Some methods may not have been obfuscated. We should still be able
// to compute the filename properly.
frame = map.getFrame("class.with.Methods", "unObfuscatedMethodName",
"()V", "SourceFile.java", 0);
assertEquals("Methods.java", frame.filename);
}
}