| // 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.compatdexbuilder; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import com.android.tools.r8.CompilationFailedException; |
| import com.android.tools.r8.D8; |
| import com.android.tools.r8.D8Command; |
| import com.android.tools.r8.OutputMode; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.ToolHelper.ArtCommandBuilder; |
| import com.google.common.collect.ImmutableList; |
| import java.io.IOException; |
| import java.nio.charset.StandardCharsets; |
| import java.nio.file.Path; |
| import java.util.Enumeration; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.ExecutionException; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TemporaryFolder; |
| |
| public class CompatDexBuilderTests { |
| |
| @Rule public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest(); |
| |
| @Test |
| public void compileManyClasses() throws IOException, InterruptedException, ExecutionException { |
| final String SUBDIR = "naming001"; |
| final String INPUT_JAR = ToolHelper.TESTS_BUILD_DIR + "examples/" + SUBDIR + ".jar"; |
| final List<String> CLASS_NAMES = |
| ImmutableList.of( |
| "A", |
| "B", |
| "C", |
| "D", |
| "E", |
| "F", |
| "G", |
| "H", |
| "I", |
| "J", |
| "K", |
| "L", |
| "Reflect2$A", |
| "Reflect2$B", |
| "Reflect2", |
| "Reflect"); |
| |
| // Run CompatDexBuilder on naming001.jar |
| Path outputZip = temp.getRoot().toPath().resolve("out.zip"); |
| CompatDexBuilder.main( |
| new String[] {"--input_jar", INPUT_JAR, "--output_zip", outputZip.toString()}); |
| assertTrue(outputZip.toFile().exists()); |
| |
| // Verify if all the classes have their corresponding ".class.dex" files in the zip. |
| Set<String> expectedNames = new HashSet<>(); |
| for (String className : CLASS_NAMES) { |
| expectedNames.add(SUBDIR + "/" + className + ".class.dex"); |
| } |
| try (ZipFile zipFile = new ZipFile(outputZip.toFile(), StandardCharsets.UTF_8)) { |
| for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) { |
| ZipEntry ze = e.nextElement(); |
| expectedNames.remove(ze.getName()); |
| } |
| } |
| assertTrue(expectedNames.isEmpty()); |
| } |
| |
| @Test |
| public void compileTwoClassesAndRun() |
| throws IOException, InterruptedException, ExecutionException, CompilationFailedException { |
| // Run CompatDexBuilder on dexMergeSample.jar |
| final String INPUT_JAR = ToolHelper.EXAMPLES_BUILD_DIR + "dexmergesample.jar"; |
| Path outputZip = temp.getRoot().toPath().resolve("out.zip"); |
| CompatDexBuilder.main( |
| new String[] {"--input_jar", INPUT_JAR, "--output_zip", outputZip.toString()}); |
| |
| // Merge zip content into a single dex file. |
| Path d8OutDir = temp.newFolder().toPath(); |
| D8.run( |
| D8Command.builder() |
| .setOutput(d8OutDir, OutputMode.DexIndexed) |
| .addProgramFiles(outputZip) |
| .build()); |
| |
| // Validate by running methods of Class1 and Class2 |
| for (String className : new String[] {"Class1", "Class2"}) { |
| ArtCommandBuilder artCommandBuilder = new ArtCommandBuilder(); |
| artCommandBuilder.appendClasspath(d8OutDir.resolve("classes.dex").toString()); |
| artCommandBuilder.setMainClass("dexmergesample." + className); |
| String out = ToolHelper.runArt(artCommandBuilder); |
| assertEquals(out, className + "\n"); |
| } |
| } |
| } |