|  | // 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; | 
|  | } | 
|  |  | 
|  | } |