| // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| package com.android.tools.r8.jasmin; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.R8; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.ToolHelper.ProcessResult; |
| import com.android.tools.r8.graph.AppInfo; |
| import com.android.tools.r8.graph.AppInfoWithSubtyping; |
| import com.android.tools.r8.graph.DexApplication; |
| import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder; |
| import com.android.tools.r8.naming.NamingLens; |
| import com.android.tools.r8.shaking.ProguardRuleParserException; |
| import com.android.tools.r8.utils.AndroidApp; |
| import com.android.tools.r8.utils.InternalOptions; |
| import com.android.tools.r8.utils.OutputMode; |
| import com.android.tools.r8.utils.StringUtils; |
| import com.google.common.collect.ImmutableList; |
| import jasmin.ClassFile; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.Executors; |
| import org.junit.Rule; |
| import org.junit.rules.TemporaryFolder; |
| |
| public class JasminTestBase { |
| |
| @Rule |
| public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest(); |
| |
| protected ProcessResult runOnJavaRaw(JasminBuilder builder, String main) throws Exception { |
| File out = temp.newFolder("classes"); |
| for (ClassBuilder clazz : builder.getClasses()) { |
| ClassFile file = new ClassFile(); |
| file.readJasmin(new StringReader(clazz.toString()), clazz.name, true); |
| Path path = out.toPath().resolve(clazz.name + ".class"); |
| Files.createDirectories(path.getParent()); |
| file.write(new FileOutputStream(path.toFile())); |
| } |
| return ToolHelper.runJava(ImmutableList.of(out.getPath()), main); |
| } |
| |
| protected String runOnJava(JasminBuilder builder, String main) throws Exception { |
| ProcessResult result = runOnJavaRaw(builder, main); |
| if (result.exitCode != 0) { |
| System.out.println("Std out:"); |
| System.out.println(result.stdout); |
| System.out.println("Std err:"); |
| System.out.println(result.stderr); |
| assertEquals(0, result.exitCode); |
| } |
| return result.stdout; |
| } |
| |
| protected String runOnArt(JasminBuilder builder, String main) throws Exception { |
| // TODO(zerny): Make the compiler depend on tool flag? |
| return runOnArtR8(builder, main, new InternalOptions()); |
| } |
| |
| protected AndroidApp compileWithD8(JasminBuilder builder) throws Exception { |
| return ToolHelper.runD8(builder.build()); |
| } |
| |
| protected String runOnArtD8(JasminBuilder builder, String main) throws Exception { |
| return runOnArt(compileWithD8(builder), main); |
| } |
| |
| protected String runOnArtR8(JasminBuilder builder, String main, InternalOptions options) |
| throws Exception { |
| DexApplication app = builder.read(); |
| app = process(app, options); |
| AppInfo info = new AppInfo(app); |
| AndroidApp outputApp = |
| R8.writeApplication( |
| Executors.newSingleThreadExecutor(), |
| app, |
| info, |
| null, |
| NamingLens.getIdentityLens(), |
| null, |
| null, |
| options); |
| return runOnArt(outputApp, main); |
| } |
| |
| private ProcessResult runDx(JasminBuilder builder, File classes, Path dex) throws Exception { |
| for (ClassBuilder clazz : builder.getClasses()) { |
| ClassFile file = new ClassFile(); |
| file.readJasmin(new StringReader(clazz.toString()), clazz.name, true); |
| file.write(new FileOutputStream(classes.toPath().resolve(clazz.name + ".class").toFile())); |
| } |
| List<String> args = new ArrayList<>(); |
| args.add("--output=" + dex.toString()); |
| args.add(classes.toString()); |
| System.out.println("running: dx " + StringUtils.join(args, " ")); |
| return ToolHelper.runDX(args.toArray(new String[args.size()])); |
| } |
| |
| protected ProcessResult runOnArtDxRaw(JasminBuilder builder) throws Exception { |
| return runDx(builder, temp.newFolder("classes_for_dx"), |
| temp.getRoot().toPath().resolve("classes.dex")); |
| } |
| |
| protected String runOnArtDx(JasminBuilder builder, String main) throws Exception { |
| Path dex = temp.getRoot().toPath().resolve("classes.dex"); |
| ProcessResult result = runDx(builder, temp.newFolder("classes_for_dx"), dex); |
| if (result.exitCode != 0) { |
| System.out.println("Std out:"); |
| System.out.println(result.stdout); |
| System.out.println("Std err:"); |
| System.out.println(result.stderr); |
| assertEquals(0, result.exitCode); |
| } |
| return ToolHelper.runArtNoVerificationErrors(dex.toString(), main); |
| } |
| |
| protected String runOnArt(AndroidApp app, String main) throws IOException { |
| Path out = temp.getRoot().toPath().resolve("out.zip"); |
| app.writeToZip(out, OutputMode.Indexed); |
| return ToolHelper.runArtNoVerificationErrors(ImmutableList.of(out.toString()), main, null); |
| } |
| |
| protected static DexApplication process(DexApplication app, InternalOptions options) |
| throws IOException, ProguardRuleParserException, ExecutionException { |
| return ToolHelper.optimizeWithR8(app, new AppInfoWithSubtyping(app), options); |
| } |
| } |