| // Copyright (c) 2019, 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.cf.bootstrap; |
| |
| import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; |
| import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; |
| import static org.junit.Assert.assertTrue; |
| |
| import com.android.tools.r8.KotlinCompilerTool.KotlinCompiler; |
| import com.android.tools.r8.TestParameters; |
| import com.android.tools.r8.TestParametersCollection; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.ToolHelper.KotlinTargetVersion; |
| import com.android.tools.r8.internal.CompilationTestBase; |
| import com.android.tools.r8.utils.AndroidApp; |
| import com.android.tools.r8.utils.DescriptorUtils; |
| import com.google.common.collect.ImmutableList; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.List; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| @RunWith(Parameterized.class) |
| public class KotlinCompilerTreeShakingTest extends CompilationTestBase { |
| |
| private static final String PKG_NAME = KotlinCompilerTreeShakingTest.class.getPackage().getName(); |
| private static final Path HELLO_KT = |
| Paths.get( |
| ToolHelper.TESTS_DIR, |
| "java", |
| DescriptorUtils.getBinaryNameFromJavaType(PKG_NAME), |
| "Hello.kt"); |
| private static final int MAX_SIZE = (int) (31361268 * 0.4); |
| |
| private TestParameters parameters; |
| |
| @Parameters(name = "{0}") |
| public static TestParametersCollection data() { |
| return getTestParameters().withCfRuntimes().build(); |
| } |
| |
| public KotlinCompilerTreeShakingTest(TestParameters parameters) { |
| this.parameters = parameters; |
| } |
| |
| @Test |
| public void testForRuntime() throws Exception { |
| // Compile Hello.kt and make sure it works as expected. |
| Path classPathBefore = |
| kotlinc(parameters.getRuntime().asCf(), KOTLINC, KotlinTargetVersion.JAVA_8) |
| .addSourceFiles(HELLO_KT) |
| .setOutputPath(temp.newFolder().toPath()) |
| .compile(); |
| testForJvm() |
| .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar()) |
| .addClasspath(classPathBefore) |
| .run(parameters.getRuntime(), PKG_NAME + ".HelloKt") |
| .assertSuccessWithOutputLines("I'm Woody. Howdy, howdy, howdy."); |
| } |
| |
| @Ignore( |
| "b/136457753: assertion error in static class merger; " |
| + "b/144877828: assertion error in method naming state during interface method renaming; " |
| + "b/144859533: umbrella" |
| ) |
| @Test |
| public void test() throws Exception { |
| List<Path> libs = |
| ImmutableList.of( |
| ToolHelper.getKotlinStdlibJar(), |
| ToolHelper.getKotlinReflectJar(), |
| Paths.get(ToolHelper.KT_SCRIPT_RT)); |
| // Process kotlin-compiler.jar. |
| Path r8ProcessedKotlinc = |
| testForR8(parameters.getBackend()) |
| .addLibraryFiles(libs) |
| .addLibraryFiles(ToolHelper.getJava8RuntimeJar()) |
| .addProgramFiles(Paths.get(ToolHelper.KT_COMPILER)) |
| .addKeepAttributes("*Annotation*") |
| .addKeepClassAndMembersRules(ToolHelper.K2JVMCompiler) |
| .addKeepClassAndMembersRules("**.K2JVMCompilerArguments") |
| .addKeepClassAndMembersRules("**.*Argument*") |
| .addKeepClassAndMembersRules("**.Freezable") |
| .addKeepRules( |
| "-keepclassmembers class * {", |
| " *** parseCommandLineArguments(...);", |
| "}" |
| ) |
| .addKeepRules( |
| "-keepclassmembers,allowoptimization enum * {", |
| " public static **[] values();", |
| " public static ** valueOf(java.lang.String);", |
| "}") |
| .addOptionsModification(o -> { |
| // Ignore com.sun.tools.javac.main.JavaCompiler and others |
| // Resulting jar may not be able to deal with .java source files, though. |
| o.ignoreMissingClasses = true; |
| // b/144861100: invoke-static on interface is allowed up to JDK 8. |
| o.testing.allowInvokeErrors = true; |
| }) |
| .compile() |
| .writeToZip(); |
| |
| // Copy libraries used by kotlin-compiler.jar so that Preloader can load them. |
| Path dir = r8ProcessedKotlinc.getParent(); |
| for (Path lib : libs) { |
| Path newLib = dir.resolve(lib.getFileName()); |
| Files.copy(lib, newLib, REPLACE_EXISTING); |
| } |
| |
| // TODO(b/144859533): passing `dir` as -kotlin-home. |
| // Compile Hello.kt again with r8-processed kotlin-compiler.jar |
| Path classPathAfter = |
| kotlinc( |
| parameters.getRuntime().asCf(), |
| new KotlinCompiler("r8ProcessedKotlinc", r8ProcessedKotlinc), |
| KotlinTargetVersion.JAVA_8) |
| .addSourceFiles(HELLO_KT) |
| .setOutputPath(temp.newFolder().toPath()) |
| .compile(); |
| testForJvm() |
| .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar()) |
| .addClasspath(classPathAfter) |
| .run(parameters.getRuntime(), PKG_NAME + ".HelloKt") |
| .assertSuccessWithOutputLines("I'm Woody. Howdy, howdy, howdy."); |
| |
| int size = applicationSize(AndroidApp.builder().addProgramFile(r8ProcessedKotlinc).build()); |
| assertTrue(size <= MAX_SIZE); |
| } |
| } |