|  | // Copyright (c) 2018, 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.DiagnosticsMatcher.diagnosticMessage; | 
|  | import static org.hamcrest.CoreMatchers.containsString; | 
|  |  | 
|  | import com.android.tools.r8.KotlinCompilerTool.KotlinCompiler; | 
|  | import com.android.tools.r8.KotlinCompilerTool.KotlinTargetVersion; | 
|  | import com.android.tools.r8.TestRuntime.CfRuntime; | 
|  | import com.android.tools.r8.utils.DescriptorUtils; | 
|  | import com.android.tools.r8.utils.FileUtils; | 
|  | import java.io.IOException; | 
|  | import java.nio.file.Files; | 
|  | import java.nio.file.Path; | 
|  | import java.nio.file.Paths; | 
|  | import java.util.Arrays; | 
|  | import java.util.Collection; | 
|  | import java.util.HashMap; | 
|  | import java.util.IdentityHashMap; | 
|  | import java.util.List; | 
|  | import java.util.Map; | 
|  | import java.util.function.Consumer; | 
|  | import java.util.stream.Collectors; | 
|  | import org.hamcrest.Matcher; | 
|  | import org.junit.rules.TemporaryFolder; | 
|  |  | 
|  | public abstract class KotlinTestBase extends TestBase { | 
|  |  | 
|  | protected static final String checkParameterIsNotNullSignature = | 
|  | "void kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull(" | 
|  | + "java.lang.Object, java.lang.String)"; | 
|  | protected static final String throwParameterIsNotNullExceptionSignature = | 
|  | "void kotlin.jvm.internal.Intrinsics.throwParameterIsNullException(java.lang.String)"; | 
|  | public static final String METADATA_DESCRIPTOR = "Lkotlin/Metadata;"; | 
|  | public static final String METADATA_TYPE = | 
|  | DescriptorUtils.descriptorToJavaType(METADATA_DESCRIPTOR); | 
|  |  | 
|  | private static final String RSRC = "kotlinR8TestResources"; | 
|  |  | 
|  | private static final Map<String, KotlinCompileMemoizer> compileMemoizers = new HashMap<>(); | 
|  |  | 
|  | protected final KotlinCompiler kotlinc; | 
|  | protected final KotlinTargetVersion targetVersion; | 
|  | protected final KotlinTestParameters kotlinParameters; | 
|  |  | 
|  | protected KotlinTestBase(KotlinTestParameters kotlinParameters) { | 
|  | this.targetVersion = kotlinParameters.getTargetVersion(); | 
|  | this.kotlinc = kotlinParameters.getCompiler(); | 
|  | this.kotlinParameters = kotlinParameters; | 
|  | } | 
|  |  | 
|  | public static CfRuntime getKotlincHostRuntime(TestRuntime runtime) { | 
|  | return runtime.isCf() ? runtime.asCf() : TestRuntime.getCheckedInJdk9(); | 
|  | } | 
|  |  | 
|  | protected static List<Path> getKotlinFilesInTestPackage(Package pkg) throws IOException { | 
|  | String folder = DescriptorUtils.getBinaryNameFromJavaType(pkg.getName()); | 
|  | return Files.walk(Paths.get(ToolHelper.TESTS_DIR, "java", folder)) | 
|  | .filter(path -> path.toString().endsWith(".kt")) | 
|  | .collect(Collectors.toList()); | 
|  | } | 
|  |  | 
|  | protected static Path getKotlinFileInTestPackage(Package pkg, String fileName) { | 
|  | String folder = DescriptorUtils.getBinaryNameFromJavaType(pkg.getName()); | 
|  | return getKotlinFileInTest(folder, fileName); | 
|  | } | 
|  |  | 
|  | protected static Path getKotlinFileInTest(String folder, String fileName) { | 
|  | return Paths.get(ToolHelper.TESTS_DIR, "java", folder, fileName + FileUtils.KT_EXTENSION); | 
|  | } | 
|  |  | 
|  | public static Path getKotlinFileInResource(String folder, String fileName) { | 
|  | return Paths.get(ToolHelper.TESTS_DIR, RSRC, folder, fileName + FileUtils.KT_EXTENSION); | 
|  | } | 
|  |  | 
|  | public static List<Path> getKotlinFilesInResource(String folder) { | 
|  | try { | 
|  | return Files.walk(Paths.get(ToolHelper.TESTS_DIR, RSRC, folder)) | 
|  | .filter(path -> path.toString().endsWith(".kt") || path.toString().endsWith(".java")) | 
|  | .collect(Collectors.toList()); | 
|  | } catch (IOException e) { | 
|  | throw new RuntimeException(e); | 
|  | } | 
|  | } | 
|  |  | 
|  | public static Path getKotlinResourcesFolder() { | 
|  | return Paths.get(ToolHelper.TESTS_DIR, RSRC); | 
|  | } | 
|  |  | 
|  | protected Path getJavaJarFile(String folder) { | 
|  | return Paths.get(ToolHelper.TESTS_BUILD_DIR, RSRC, | 
|  | targetVersion.getFolderName(), folder + ".java" + FileUtils.JAR_EXTENSION); | 
|  | } | 
|  |  | 
|  | protected Path getMappingfile(String folder, String mappingFileName) { | 
|  | return Paths.get(ToolHelper.TESTS_DIR, RSRC, folder, mappingFileName); | 
|  | } | 
|  |  | 
|  | protected static Matcher<String> expectedInfoMessagesFromKotlinStdLib() { | 
|  | return containsString("No VersionRequirement"); | 
|  | } | 
|  |  | 
|  | protected KotlinCompilerTool kotlinCompilerTool() { | 
|  | return KotlinCompilerTool.create(CfRuntime.getCheckedInJdk9(), temp, kotlinc, targetVersion); | 
|  | } | 
|  |  | 
|  | public static KotlinCompileMemoizer getCompileMemoizer(Path... source) { | 
|  | return new KotlinCompileMemoizer(Arrays.asList(source)); | 
|  | } | 
|  |  | 
|  | public static KotlinCompileMemoizer getCompileMemoizer(Collection<Path> sources) { | 
|  | assert sources.size() > 0; | 
|  | return new KotlinCompileMemoizer(sources); | 
|  | } | 
|  |  | 
|  | public static KotlinCompileMemoizer getCompileMemoizer( | 
|  | Collection<Path> sources, CfRuntime runtime, TemporaryFolder temporaryFolder) { | 
|  | return new KotlinCompileMemoizer(sources, runtime, temporaryFolder); | 
|  | } | 
|  |  | 
|  | public static KotlinCompileMemoizer getCompileMemoizer( | 
|  | Collection<Path> sources, String sharedFolder) { | 
|  | return compileMemoizers.computeIfAbsent( | 
|  | sharedFolder, ignore -> new KotlinCompileMemoizer(sources)); | 
|  | } | 
|  |  | 
|  | public ThrowableConsumer<R8TestCompileResult> assertUnusedKeepRuleForKotlinMetadata( | 
|  | boolean condition) { | 
|  | return compileResult -> { | 
|  | if (!condition) { | 
|  | return; | 
|  | } | 
|  | compileResult | 
|  | .getDiagnosticMessages() | 
|  | .assertInfoThatMatches( | 
|  | diagnosticMessage( | 
|  | containsString( | 
|  | "Proguard configuration rule does not match anything: `-keep class" | 
|  | + " kotlin.Metadata"))); | 
|  | }; | 
|  | } | 
|  |  | 
|  | public static class KotlinCompileMemoizer { | 
|  |  | 
|  | private final Collection<Path> sources; | 
|  | private final CfRuntime runtime; | 
|  | private final TemporaryFolder temporaryFolder; | 
|  |  | 
|  | private Consumer<KotlinCompilerTool> kotlinCompilerToolConsumer = x -> {}; | 
|  | private final Map<KotlinCompiler, Map<KotlinTargetVersion, Path>> compiledPaths = | 
|  | new IdentityHashMap<>(); | 
|  |  | 
|  | public KotlinCompileMemoizer(Collection<Path> sources) { | 
|  | this(sources, CfRuntime.getCheckedInJdk9(), null); | 
|  | } | 
|  |  | 
|  | public KotlinCompileMemoizer( | 
|  | Collection<Path> sources, CfRuntime runtime, TemporaryFolder temporaryFolder) { | 
|  | this.sources = sources; | 
|  | this.runtime = runtime; | 
|  | this.temporaryFolder = temporaryFolder; | 
|  | } | 
|  |  | 
|  | public KotlinCompileMemoizer configure(Consumer<KotlinCompilerTool> consumer) { | 
|  | this.kotlinCompilerToolConsumer = consumer; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Path getForConfiguration(KotlinTestParameters kotlinParameters) { | 
|  | return getForConfiguration( | 
|  | kotlinParameters.getCompiler(), kotlinParameters.getTargetVersion()); | 
|  | } | 
|  |  | 
|  | public Path getForConfiguration(KotlinCompiler compiler, KotlinTargetVersion targetVersion) { | 
|  | Map<KotlinTargetVersion, Path> kotlinTargetVersionPathMap = compiledPaths.get(compiler); | 
|  | if (kotlinTargetVersionPathMap == null) { | 
|  | kotlinTargetVersionPathMap = new IdentityHashMap<>(); | 
|  | compiledPaths.put(compiler, kotlinTargetVersionPathMap); | 
|  | } | 
|  | return kotlinTargetVersionPathMap.computeIfAbsent( | 
|  | targetVersion, | 
|  | ignored -> { | 
|  | try { | 
|  | KotlinCompilerTool kotlinc = | 
|  | temporaryFolder == null | 
|  | ? kotlinc(compiler, targetVersion) | 
|  | : kotlinc(runtime, temporaryFolder, compiler, targetVersion); | 
|  | return kotlinc.addSourceFiles(sources).apply(kotlinCompilerToolConsumer).compile(); | 
|  | } catch (IOException e) { | 
|  | throw new RuntimeException(e); | 
|  | } | 
|  | }); | 
|  | } | 
|  | } | 
|  | } |