diff --git a/jadx-core/build.gradle b/jadx-core/build.gradle index 98850351b..9329b8efe 100644 --- a/jadx-core/build.gradle +++ b/jadx-core/build.gradle @@ -1,9 +1,12 @@ ext.jadxClasspath = 'clsp-data/android-4.3.jar' dependencies { + runtime files(jadxClasspath) + compile files('lib/dx-1.8.jar') compile 'org.ow2.asm:asm:5.0.3' - runtime files(jadxClasspath) + + testCompile 'org.smali:smali:2.0.3' } task packTests(type: Jar) { diff --git a/jadx-core/src/test/java/jadx/api/InternalJadxTest.java b/jadx-core/src/test/java/jadx/api/InternalJadxTest.java index 68e8ec050..6c0b8d58c 100644 --- a/jadx-core/src/test/java/jadx/api/InternalJadxTest.java +++ b/jadx-core/src/test/java/jadx/api/InternalJadxTest.java @@ -7,6 +7,7 @@ import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.visitors.DepthTraversal; import jadx.core.dex.visitors.IDexTreeVisitor; +import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.files.FileUtils; import java.io.File; @@ -30,21 +31,30 @@ public abstract class InternalJadxTest extends TestUtils { protected boolean outputCFG = false; protected boolean isFallback = false; - protected boolean deleteTmpJar = true; + protected boolean deleteTmpFiles = true; protected String outDir = "test-out-tmp"; public ClassNode getClassNode(Class clazz) { - JadxDecompiler d = new JadxDecompiler(); try { - d.loadFile(getJarForClass(clazz)); + File jar = getJarForClass(clazz); + return getClassNodeFromFile(jar, clazz.getName()); } catch (Exception e) { fail(e.getMessage()); } - String clsName = clazz.getName(); + return null; + } + + public ClassNode getClassNodeFromFile(File file, String clsName) { + JadxDecompiler d = new JadxDecompiler(); + try { + d.loadFile(file); + } catch (JadxException e) { + fail(e.getMessage()); + } ClassNode cls = d.getRoot().searchClassByName(clsName); assertNotNull("Class not found: " + clsName, cls); - assertEquals(cls.getFullName(), clazz.getName()); + assertEquals(cls.getFullName(), clsName); cls.load(); for (IDexTreeVisitor visitor : getPasses()) { @@ -99,16 +109,26 @@ public abstract class InternalJadxTest extends TestUtils { String path = cls.getPackage().getName().replace('.', '/'); List list = getClassFilesWithInners(cls); - File temp = File.createTempFile("jadx-tmp-", System.nanoTime() + ".jar"); + File temp = createTempFile(".jar"); JarOutputStream jo = new JarOutputStream(new FileOutputStream(temp)); for (File file : list) { FileUtils.addFileToJar(jo, file, path + "/" + file.getName()); } jo.close(); - if (deleteTmpJar) { - temp.deleteOnExit(); - } else { - System.out.println("Temporary jar file path: " + temp.getAbsolutePath()); + return temp; + } + + protected File createTempFile(String suffix) { + File temp = null; + try { + temp = File.createTempFile("jadx-tmp-", System.nanoTime() + suffix); + if (deleteTmpFiles) { + temp.deleteOnExit(); + } else { + System.out.println("Temporary file path: " + temp.getAbsolutePath()); + } + } catch (IOException e) { + fail(e.getMessage()); } return temp; } @@ -135,7 +155,6 @@ public abstract class InternalJadxTest extends TestUtils { return list; } - // Use only for debug purpose @Deprecated protected void setOutputCFG() { @@ -151,6 +170,6 @@ public abstract class InternalJadxTest extends TestUtils { // Use only for debug purpose @Deprecated protected void notDeleteTmpJar() { - this.deleteTmpJar = false; + this.deleteTmpFiles = false; } } diff --git a/jadx-core/src/test/java/jadx/api/SmaliTest.java b/jadx-core/src/test/java/jadx/api/SmaliTest.java new file mode 100644 index 000000000..07f2131fe --- /dev/null +++ b/jadx-core/src/test/java/jadx/api/SmaliTest.java @@ -0,0 +1,51 @@ +package jadx.api; + +import jadx.core.Consts; +import jadx.core.dex.nodes.ClassNode; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.jf.smali.main; + +import static org.junit.Assert.fail; + +public class SmaliTest extends InternalJadxTest { + + private static final String SMALI_TESTS_PROJECT = "jadx-core"; + private static final String SMALI_TESTS_DIR = "src/test/smali"; + private static final String SMALI_TESTS_EXT = ".smali"; + + protected ClassNode getClassNodeFromSmali(String clsName) { + File smaliFile = getSmaliFile(clsName); + File outDex = createTempFile(".dex"); + compileSmali(smaliFile, outDex); + String fullClsName = Consts.DEFAULT_PACKAGE_NAME + "." + clsName; + return getClassNodeFromFile(outDex, fullClsName); + } + + private File getSmaliFile(String clsName) { + File smaliFile = new File(SMALI_TESTS_DIR, clsName + SMALI_TESTS_EXT); + if (smaliFile.exists()) { + return smaliFile; + } + smaliFile = new File(SMALI_TESTS_PROJECT, smaliFile.getPath()); + if (smaliFile.exists()) { + return smaliFile; + } + fail("Smali file not found: " + SMALI_TESTS_DIR + "/" + clsName + SMALI_TESTS_EXT); + return null; + } + + public boolean compileSmali(File input, File output) { + List args = new ArrayList(); + args.add(input.getAbsolutePath()); + + args.add("-o"); + args.add(output.getAbsolutePath()); + + main.main(args.toArray(new String[args.size()])); + return true; + } +}