From 4a92275adbab02303c30b38f75857ec727c3e92c Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 29 Mar 2019 14:05:22 +0300 Subject: [PATCH] test: allow use Eclipse compiler in tests (#536) --- build.gradle | 2 + .../java/jadx/tests/api/IntegrationTest.java | 97 +++++++++---------- .../tests/api/compiler/StaticCompiler.java | 43 ++++---- .../integration/arrays/TestArrayFill3.java | 9 +- 4 files changed, 74 insertions(+), 77 deletions(-) diff --git a/build.gradle b/build.gradle index 3aa6c2521..9025cdbe4 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,8 @@ allprojects { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.1' + + testCompile 'org.eclipse.jdt.core.compiler:ecj:4.6.1' } test { diff --git a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java index 705533f62..9c3c48767 100644 --- a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java +++ b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java @@ -1,5 +1,26 @@ package jadx.tests.api; +import jadx.api.JadxArgs; +import jadx.api.JadxDecompiler; +import jadx.api.JadxInternalAccess; +import jadx.core.ProcessClass; +import jadx.core.codegen.CodeGen; +import jadx.core.dex.attributes.AFlag; +import jadx.core.dex.attributes.AType; +import jadx.core.dex.attributes.AttrList; +import jadx.core.dex.attributes.IAttributeNode; +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.xmlgen.ResourceStorage; +import jadx.core.xmlgen.entry.ResourceEntry; +import jadx.tests.api.compiler.DynamicCompiler; +import jadx.tests.api.compiler.StaticCompiler; +import jadx.tests.api.utils.TestUtils; +import org.junit.jupiter.api.BeforeEach; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -21,26 +42,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.jar.JarOutputStream; -import jadx.api.JadxArgs; -import jadx.api.JadxDecompiler; -import jadx.api.JadxInternalAccess; -import jadx.core.ProcessClass; -import jadx.core.codegen.CodeGen; -import jadx.core.dex.attributes.AFlag; -import jadx.core.dex.attributes.AType; -import jadx.core.dex.attributes.AttrList; -import jadx.core.dex.attributes.IAttributeNode; -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.xmlgen.ResourceStorage; -import jadx.core.xmlgen.entry.ResourceEntry; -import jadx.tests.api.compiler.DynamicCompiler; -import jadx.tests.api.compiler.StaticCompiler; -import jadx.tests.api.utils.TestUtils; - import static jadx.core.utils.files.FileUtils.addFileToJar; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -58,30 +59,38 @@ 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; + private static final String OUT_DIR = "test-out-tmp"; + /** * Run auto check method if defined: *
 	 *     public void check() {}
 	 * 
*/ - public static final String CHECK_METHOD_NAME = "check"; + private static final String CHECK_METHOD_NAME = "check"; protected JadxArgs args; - protected boolean deleteTmpFiles = true; - protected boolean withDebugInfo = true; - protected boolean unloadCls = true; - + protected boolean deleteTmpFiles; + protected boolean withDebugInfo; + protected boolean unloadCls; + protected boolean compile; + protected boolean useEclipseCompiler; protected Map resMap = Collections.emptyMap(); - protected String outDir = "test-out-tmp"; - - protected boolean compile = true; private DynamicCompiler dynamicCompiler; - public IntegrationTest() { + @BeforeEach + public void init() { + this.deleteTmpFiles = true; + this.unloadCls = true; + this.withDebugInfo = true; + this.compile = true; + this.useEclipseCompiler = false; + this.resMap = Collections.emptyMap(); + args = new JadxArgs(); - args.setOutDir(new File(outDir)); + args.setOutDir(new File(OUT_DIR)); args.setShowInconsistentCode(true); args.setThreadsCount(1); args.setSkipResources(true); @@ -377,28 +386,6 @@ public abstract class IntegrationTest extends TestUtils { throw new IOException("Failed to create temp directory"); } - private List getClassFilesWithInners(Class cls) { - List list = new ArrayList<>(); - String pkgName = cls.getPackage().getName(); - URL pkgResource = ClassLoader.getSystemClassLoader().getResource(pkgName.replace('.', '/')); - if (pkgResource != null) { - try { - String clsName = cls.getName(); - File directory = new File(pkgResource.toURI()); - String[] files = directory.list(); - for (String file : files) { - String fullName = pkgName + '.' + file; - if (fullName.startsWith(clsName)) { - list.add(new File(directory, file)); - } - } - } catch (URISyntaxException e) { - fail(e.getMessage()); - } - } - return list; - } - private List compileClass(Class cls) throws IOException { String clsFullName = cls.getName(); String rootClsName; @@ -418,7 +405,7 @@ public abstract class IntegrationTest extends TestUtils { File outTmp = createTempDir("jadx-tmp-classes"); outTmp.deleteOnExit(); - List files = StaticCompiler.compile(compileFileList, outTmp, withDebugInfo); + List files = StaticCompiler.compile(compileFileList, outTmp, withDebugInfo, useEclipseCompiler); files.forEach(File::deleteOnExit); // remove classes which are parents for test class String clsName = clsFullName.substring(clsFullName.lastIndexOf('.') + 1); @@ -442,6 +429,10 @@ public abstract class IntegrationTest extends TestUtils { this.withDebugInfo = false; } + protected void useEclipseCompiler() { + this.useEclipseCompiler = true; + } + protected void setFallback() { this.args.setFallbackMode(true); } diff --git a/jadx-core/src/test/java/jadx/tests/api/compiler/StaticCompiler.java b/jadx-core/src/test/java/jadx/tests/api/compiler/StaticCompiler.java index d9eb4fcc2..3411dcd2b 100644 --- a/jadx-core/src/test/java/jadx/tests/api/compiler/StaticCompiler.java +++ b/jadx-core/src/test/java/jadx/tests/api/compiler/StaticCompiler.java @@ -1,13 +1,7 @@ package jadx.tests.api.compiler; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import jadx.core.utils.files.FileUtils; +import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; @@ -17,18 +11,28 @@ import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; - -import jadx.core.utils.files.FileUtils; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class StaticCompiler { private static final List COMMON_ARGS = Arrays.asList("-source 1.8 -target 1.8".split(" ")); - public static List compile(List files, File outDir, boolean includeDebugInfo) throws IOException { - - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - if (compiler == null) { - throw new IllegalStateException("Can not find compiler, please use JDK instead"); + public static List compile(List files, File outDir, boolean includeDebugInfo, boolean useEclipseCompiler) throws IOException { + JavaCompiler compiler; + if (useEclipseCompiler) { + compiler = new EclipseCompiler(); + } else { + compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + throw new IllegalStateException("Can not find compiler, please use JDK instead"); + } } StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Iterable compilationUnits = fileManager.getJavaFileObjectsFromFiles(files); @@ -48,8 +52,8 @@ public class StaticCompiler { } private static class StaticFileManager extends ForwardingJavaFileManager { - private List files = new ArrayList<>(); - private File outDir; + private final List files = new ArrayList<>(); + private final File outDir; protected StaticFileManager(StandardJavaFileManager fileManager, File outDir) { super(fileManager); @@ -57,8 +61,7 @@ public class StaticCompiler { } @Override - public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, - FileObject sibling) throws IOException { + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) { if (kind == JavaFileObject.Kind.CLASS) { File file = new File(outDir, className.replace('.', '/') + ".class"); files.add(file); @@ -73,7 +76,7 @@ public class StaticCompiler { } private static class ClassFileObject extends SimpleJavaFileObject { - private File file; + private final File file; protected ClassFileObject(File file, Kind kind) { super(file.toURI(), kind); diff --git a/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFill3.java b/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFill3.java index 64a9f7fc7..c52afd3e8 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFill3.java +++ b/jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFill3.java @@ -1,9 +1,9 @@ package jadx.tests.integration.arrays; -import org.junit.jupiter.api.Test; - +import jadx.NotYetImplemented; import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.IntegrationTest; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; @@ -18,11 +18,12 @@ public class TestArrayFill3 extends IntegrationTest { } @Test + @NotYetImplemented public void test() { + useEclipseCompiler(); ClassNode cls = getClassNode(TestCls.class); String code = cls.getCode().toString(); - assertThat(code, containsString("return new byte[]")); + assertThat(code, containsString("return new byte[]{0, 1, 2}")); } - }