| // 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; | |
| import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION; | |
| import static org.junit.Assert.assertTrue; | |
| import com.android.tools.r8.D8Command.Builder; | |
| import com.android.tools.r8.utils.AndroidApiLevel; | |
| import com.android.tools.r8.utils.AndroidApp; | |
| import com.android.tools.r8.utils.FileUtils; | |
| import com.android.tools.r8.utils.OffOrAuto; | |
| import com.android.tools.r8.utils.ZipUtils; | |
| import java.io.IOException; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| import java.util.stream.Collectors; | |
| import org.junit.Test; | |
| public class D8LazyRunExamplesAndroidOTest | |
| extends D8IncrementalRunExamplesAndroidOTest { | |
| // Please note that all tool specific markers have been eliminated in the resulting | |
| // dex applications. This allows for byte-wise comparison of the results. | |
| class D8LazyTestRunner extends D8IncrementalTestRunner { | |
| D8LazyTestRunner(String testName, String packageName, String mainClass) { | |
| super(testName, packageName, mainClass); | |
| } | |
| @Override | |
| void addClasspathReference(Path testJarFile, D8Command.Builder builder) { | |
| addClasspathPath(getClassesRoot(testJarFile), builder); | |
| addClasspathPath(getLegacyClassesRoot(testJarFile), builder); | |
| } | |
| private void addClasspathPath(Path location, D8Command.Builder builder) { | |
| builder.addClasspathResourceProvider( | |
| DirectoryClassFileProvider.fromDirectory(location.resolve(".."))); | |
| } | |
| @Override | |
| void addLibraryReference(Builder builder, Path location) throws IOException { | |
| builder.addLibraryResourceProvider(new ArchiveClassFileProvider(location)); | |
| } | |
| @Override | |
| D8LazyTestRunner self() { | |
| return this; | |
| } | |
| } | |
| @Override | |
| D8IncrementalTestRunner test(String testName, String packageName, String mainClass) { | |
| D8IncrementalTestRunner result = new D8LazyTestRunner(testName, packageName, mainClass); | |
| result.withOptionConsumer(options -> options.setMarker(null)); | |
| return result; | |
| } | |
| @Test | |
| public void dexPerClassFileWithDesugaringAndFolderClasspath() throws Throwable { | |
| AndroidApiLevel minAPILevel = AndroidApiLevel.K; | |
| Path inputFile = | |
| Paths.get(ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR, "interfacemethods" + JAR_EXTENSION); | |
| Path tmpClassesDir = temp.newFolder().toPath(); | |
| ZipUtils.unzip(inputFile.toString(), tmpClassesDir.toFile()); | |
| Path androidJar = ToolHelper.getAndroidJar(minAPILevel); | |
| // Build all at once. | |
| AndroidApp fullBuildResult; | |
| { | |
| D8Command.Builder command = | |
| D8Command.builder() | |
| .setMinApiLevel(minAPILevel.getLevel()) | |
| .addLibraryFiles(androidJar) | |
| .addProgramFiles(inputFile); | |
| fullBuildResult = ToolHelper.runD8( | |
| command, options -> { | |
| options.interfaceMethodDesugaring = OffOrAuto.Auto; | |
| options.setMarker(null); | |
| }); | |
| } | |
| // Build each class individually using tmpClassesDir as classpath for desugaring. | |
| List<ProgramResource> individalDexes = new ArrayList<>(); | |
| List<Path> individualClassFiles = | |
| Files.walk(tmpClassesDir) | |
| .filter(classFile -> FileUtils.isClassFile(classFile)) | |
| .collect(Collectors.toList()); | |
| for (Path classFile : individualClassFiles) { | |
| D8Command.Builder builder = | |
| D8Command.builder() | |
| .setMinApiLevel(minAPILevel.getLevel()) | |
| .addLibraryFiles(androidJar) | |
| .addClasspathFiles(tmpClassesDir) | |
| .addProgramFiles(classFile); | |
| AndroidApp individualResult = | |
| ToolHelper.runD8( | |
| builder, | |
| options -> { | |
| options.interfaceMethodDesugaring = OffOrAuto.Auto; | |
| options.setMarker(null); | |
| }); | |
| individalDexes.add(individualResult.getDexProgramResourcesForTesting().get(0)); | |
| } | |
| AndroidApp mergedResult = mergeDexResources(minAPILevel.getLevel(), individalDexes); | |
| assertTrue(Arrays.equals( | |
| readResource(fullBuildResult.getDexProgramResourcesForTesting().get(0)), | |
| readResource(mergedResult.getDexProgramResourcesForTesting().get(0)))); | |
| } | |
| private AndroidApp mergeDexResources(int minAPILevel, List<ProgramResource> individalDexes) | |
| throws IOException, CompilationFailedException, ResourceException { | |
| D8Command.Builder builder = D8Command.builder() | |
| .setMinApiLevel(minAPILevel); | |
| for (ProgramResource resource : individalDexes) { | |
| builder.addDexProgramData(readResource(resource), resource.getOrigin()); | |
| } | |
| AndroidApp mergedResult = ToolHelper.runD8(builder, options -> options.setMarker(null)); | |
| return mergedResult; | |
| } | |
| } |