提交 7562ec9e 编写于 作者: S Skylot

tests: add base test class for simplified apk debugging

上级 6d984c04
......@@ -28,5 +28,3 @@ jadx-output/
*.dump
*.log
*.cfg
jadx-core/src/test/java/jadx/tests/external/
......@@ -11,5 +11,7 @@ dependencies {
testCompile 'org.smali:smali:2.2.2'
testCompile 'org.smali:baksmali:2.2.2'
testCompile 'org.apache.commons:commons-lang3:3.7'
}
......@@ -48,6 +48,14 @@ public abstract class IntegrationTest extends TestUtils {
private static final String TEST_DIRECTORY = "src/test/java";
private static final String TEST_DIRECTORY2 = "jadx-core/" + TEST_DIRECTORY;
/**
* Run auto check method if defined:
* <pre>
* public static void check()
* </pre>
*/
public static final String CHECK_METHOD_NAME = "check";
protected JadxArgs args;
protected boolean deleteTmpFiles = true;
......@@ -159,7 +167,7 @@ public abstract class IntegrationTest extends TestUtils {
}
Method checkMth;
try {
checkMth = origCls.getMethod("check");
checkMth = origCls.getMethod(CHECK_METHOD_NAME);
} catch (NoSuchMethodException e) {
// ignore
return;
......@@ -173,7 +181,7 @@ public abstract class IntegrationTest extends TestUtils {
try {
checkMth.invoke(origCls.newInstance());
} catch (InvocationTargetException ie) {
rethrow("Java check failed", ie);
rethrow("Original check failed", ie);
}
// run 'check' method from decompiled class
try {
......
package jadx.tests.external;
import java.io.File;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.JadxInternalAccess;
import jadx.api.JavaClass;
import jadx.core.Jadx;
import jadx.core.codegen.CodeGen;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.tests.api.IntegrationTest;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
public abstract class BaseExternalTest extends IntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(BaseExternalTest.class);
protected abstract String getSamplesDir();
protected JadxArgs prepare(String inputFile) {
JadxArgs args = new JadxArgs();
args.getInputFiles().add(new File(getSamplesDir(), inputFile));
args.setOutDir(new File("../jadx-external-tests-tmp"));
return args;
}
protected void decompile(JadxArgs jadxArgs) {
decompile(jadxArgs, null, null);
}
protected void decompile(JadxArgs jadxArgs, String clsPatternStr) {
decompile(jadxArgs, clsPatternStr, null);
}
protected void decompile(JadxArgs jadxArgs, @Nullable String clsPatternStr, @Nullable String mthPatternStr) {
JadxDecompiler jadx = new JadxDecompiler(jadxArgs);
jadx.load();
if (clsPatternStr == null) {
processAll(jadx);
// jadx.saveSources();
} else {
Pattern clsPtrn = Pattern.compile(clsPatternStr);
Pattern mthPtrn = mthPatternStr == null ? null : Pattern.compile(mthPatternStr);
processMthByPatterns(jadx, clsPtrn, mthPtrn);
}
printErrorReport(jadx);
}
private void processAll(JadxDecompiler jadx) {
for (JavaClass javaClass : jadx.getClasses()) {
javaClass.decompile();
}
}
private void processMthByPatterns(JadxDecompiler jadx, Pattern clsPattern, @Nullable Pattern mthPattern) {
List<IDexTreeVisitor> passes = Jadx.getPassesList(jadx.getArgs());
RootNode root = JadxInternalAccess.getRoot(jadx);
for (ClassNode classNode : root.getClasses(true)) {
String clsFullName = classNode.getClassInfo().getFullName();
if (clsPattern.matcher(clsFullName).matches()) {
classNode.load();
boolean decompile = false;
if (mthPattern == null) {
decompile = true;
} else {
for (MethodNode mth : classNode.getMethods()) {
if (mthPattern.matcher(mth.getName()).matches()) {
decompile = true;
break;
}
}
}
if (decompile) {
for (IDexTreeVisitor visitor : passes) {
DepthTraversal.visit(visitor, classNode);
}
try {
new CodeGen().visit(classNode);
} catch (Exception e) {
throw new JadxRuntimeException("Codegen failed", e);
}
LOG.warn("\n Print class: {}, {}", classNode.getFullName(), classNode.dex());
if (mthPattern != null) {
printMethods(classNode, mthPattern);
} else {
LOG.info("Code: \n{}", classNode.getCode());
}
checkCode(classNode);
// SaveCode.save(jadx.getArgs().getOutDirSrc(), jadx.getArgs(), classNode);
}
}
}
}
private void printMethods(ClassNode classNode, @NotNull Pattern mthPattern) {
String code = classNode.getCode().getCodeStr();
if (code == null) {
return;
}
String[] lines = code.split(CodeWriter.NL);
for (MethodNode mth : classNode.getMethods()) {
if (mthPattern.matcher(mth.getName()).matches()) {
int decompiledLine = mth.getDecompiledLine();
StringBuilder mthCode = new StringBuilder();
int brackets = 0;
for (int i = decompiledLine - 1; i > 0 && i < lines.length; i++) {
String line = lines[i];
mthCode.append(line).append(CodeWriter.NL);
brackets += StringUtils.countMatches(line, '{');
brackets -= StringUtils.countMatches(line, '}');
if (brackets <= 0) {
break;
}
}
LOG.info("\n{}", mthCode);
}
}
}
private void printErrorReport(JadxDecompiler jadx) {
jadx.printErrorsReport();
assertThat(jadx.getErrorsCount(), is(0));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册