core tests: add option for compile test without debug info
This commit is contained in:
@@ -3,9 +3,9 @@ package jadx.core.clsp;
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.DecodeException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
@@ -102,7 +102,7 @@ public class ClsSet {
|
||||
}
|
||||
|
||||
void save(File output) throws IOException {
|
||||
Utils.makeDirsForFile(output);
|
||||
FileUtils.makeDirsForFile(output);
|
||||
|
||||
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(output));
|
||||
try {
|
||||
|
||||
@@ -2,7 +2,7 @@ package jadx.core.codegen;
|
||||
|
||||
import jadx.api.CodePosition;
|
||||
import jadx.core.dex.attributes.nodes.LineAttrNode;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
@@ -288,7 +288,7 @@ public class CodeWriter {
|
||||
|
||||
PrintWriter out = null;
|
||||
try {
|
||||
Utils.makeDirsForFile(file);
|
||||
FileUtils.makeDirsForFile(file);
|
||||
out = new PrintWriter(file, "UTF-8");
|
||||
String code = buf.toString();
|
||||
code = removeFirstEmptyLine(code);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package jadx.core.utils;
|
||||
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Iterator;
|
||||
@@ -93,15 +90,4 @@ public class Utils {
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
public static void makeDirsForFile(File file) {
|
||||
File dir = file.getParentFile();
|
||||
if (dir != null && !dir.exists()) {
|
||||
// if directory already created in other thread mkdirs will return false,
|
||||
// so check dir existence again
|
||||
if (!dir.mkdirs() && !dir.exists()) {
|
||||
throw new JadxRuntimeException("Can't create directory " + dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package jadx.core.utils.files;
|
||||
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -35,4 +37,15 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void makeDirsForFile(File file) {
|
||||
File dir = file.getParentFile();
|
||||
if (dir != null && !dir.exists()) {
|
||||
// if directory already created in other thread mkdirs will return false,
|
||||
// so check dir existence again
|
||||
if (!dir.mkdirs() && !dir.exists()) {
|
||||
throw new JadxRuntimeException("Can't create directory " + dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import jadx.core.dex.visitors.IDexTreeVisitor;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.tests.api.compiler.DynamicCompiler;
|
||||
import jadx.tests.api.compiler.StaticCompiler;
|
||||
import jadx.tests.api.utils.TestUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -24,12 +25,15 @@ import java.lang.reflect.Modifier;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -37,10 +41,15 @@ import static org.junit.Assert.fail;
|
||||
|
||||
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;
|
||||
|
||||
protected boolean outputCFG = false;
|
||||
protected boolean isFallback = false;
|
||||
protected boolean deleteTmpFiles = true;
|
||||
|
||||
protected boolean withDebugInfo = true;
|
||||
|
||||
protected String outDir = "test-out-tmp";
|
||||
|
||||
protected boolean compile = true;
|
||||
@@ -183,7 +192,7 @@ public abstract class IntegrationTest extends TestUtils {
|
||||
try {
|
||||
dynamicCompiler = new DynamicCompiler(cls);
|
||||
boolean result = dynamicCompiler.compile();
|
||||
assertTrue("Compilation failed on code: \n\n" + cls.getCode() + "\n", result);
|
||||
assertTrue("Compilation failed", result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
@@ -218,7 +227,16 @@ public abstract class IntegrationTest extends TestUtils {
|
||||
|
||||
public File getJarForClass(Class<?> cls) throws IOException {
|
||||
String path = cls.getPackage().getName().replace('.', '/');
|
||||
List<File> list = getClassFilesWithInners(cls);
|
||||
List<File> list;
|
||||
if (!withDebugInfo) {
|
||||
list = compileClass(cls);
|
||||
} else {
|
||||
list = getClassFilesWithInners(cls);
|
||||
if (list.isEmpty()) {
|
||||
list = compileClass(cls);
|
||||
}
|
||||
}
|
||||
assertNotEquals("File list is empty", 0, list.size());
|
||||
|
||||
File temp = createTempFile(".jar");
|
||||
JarOutputStream jo = new JarOutputStream(new FileOutputStream(temp));
|
||||
@@ -244,6 +262,18 @@ public abstract class IntegrationTest extends TestUtils {
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static File createTempDir(String prefix) throws IOException {
|
||||
File baseDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
String baseName = prefix + "-" + System.nanoTime();
|
||||
for (int counter = 1; counter < 1000; counter++) {
|
||||
File tempDir = new File(baseDir, baseName + counter);
|
||||
if (tempDir.mkdir()) {
|
||||
return tempDir;
|
||||
}
|
||||
}
|
||||
throw new IOException("Failed to create temp directory");
|
||||
}
|
||||
|
||||
private List<File> getClassFilesWithInners(Class<?> cls) {
|
||||
List<File> list = new ArrayList<File>();
|
||||
String pkgName = cls.getPackage().getName();
|
||||
@@ -266,6 +296,39 @@ public abstract class IntegrationTest extends TestUtils {
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<File> compileClass(Class<?> cls) throws IOException {
|
||||
String fileName = cls.getName();
|
||||
int end = fileName.indexOf('$');
|
||||
if (end != -1) {
|
||||
fileName = fileName.substring(0, end);
|
||||
}
|
||||
fileName = fileName.replace('.', '/') + ".java";
|
||||
File file = new File(TEST_DIRECTORY, fileName);
|
||||
if (!file.exists()) {
|
||||
file = new File(TEST_DIRECTORY2, fileName);
|
||||
}
|
||||
assertTrue("Test source file not found: " + fileName, file.exists());
|
||||
|
||||
File outTmp = createTempDir("jadx-tmp-classes");
|
||||
outTmp.deleteOnExit();
|
||||
List<File> files = StaticCompiler.compile(Arrays.asList(file), outTmp, withDebugInfo);
|
||||
String filter = outTmp.getAbsolutePath() + File.separator + cls.getName().replace('.', '/');
|
||||
Iterator<File> iterator = files.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
File next = iterator.next();
|
||||
if (!next.getAbsolutePath().startsWith(filter)) {
|
||||
iterator.remove();
|
||||
} else {
|
||||
next.deleteOnExit();
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
public void noDebugInfo() {
|
||||
this.withDebugInfo = false;
|
||||
}
|
||||
|
||||
// Try to make test class compilable
|
||||
@Deprecated
|
||||
public void disableCompilation() {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package jadx.tests.api.compiler;
|
||||
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static javax.tools.JavaCompiler.CompilationTask;
|
||||
|
||||
public class StaticCompiler {
|
||||
|
||||
private static final List<String> COMMON_ARGS = Arrays.asList("-source 1.6 -target 1.6".split(" "));
|
||||
|
||||
public static List<File> compile(List<File> files, File outDir, boolean includeDebugInfo) throws IOException {
|
||||
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
|
||||
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(files);
|
||||
|
||||
StaticFileManager staticFileManager = new StaticFileManager(fileManager, outDir);
|
||||
|
||||
List<String> options = new ArrayList<String>();
|
||||
options.add(includeDebugInfo ? "-g" : "-g:none");
|
||||
options.addAll(COMMON_ARGS);
|
||||
CompilationTask task = compiler.getTask(null, staticFileManager, null, options, null, compilationUnits);
|
||||
Boolean result = task.call();
|
||||
fileManager.close();
|
||||
if (Boolean.TRUE.equals(result)) {
|
||||
return staticFileManager.outputFiles();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static class StaticFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
|
||||
private List<File> files = new ArrayList<File>();
|
||||
private File outDir;
|
||||
|
||||
protected StaticFileManager(StandardJavaFileManager fileManager, File outDir) {
|
||||
super(fileManager);
|
||||
this.outDir = outDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
|
||||
if (kind == JavaFileObject.Kind.CLASS) {
|
||||
File file = new File(outDir, className.replace('.', '/') + ".class");
|
||||
files.add(file);
|
||||
return new ClassFileObject(file, kind);
|
||||
}
|
||||
throw new UnsupportedOperationException("Can't save location with kind: " + kind);
|
||||
}
|
||||
|
||||
public List<File> outputFiles() {
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClassFileObject extends SimpleJavaFileObject {
|
||||
private File file;
|
||||
|
||||
protected ClassFileObject(File file, Kind kind) {
|
||||
super(URI.create("file://" + file.getAbsolutePath()), kind);
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
FileUtils.makeDirsForFile(file);
|
||||
return new FileOutputStream(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user