| // Copyright (c) 2020, 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.kotlin.lambda.b159688129; |
| |
| import static com.android.tools.r8.ToolHelper.getKotlinAnnotationJar; |
| import static com.android.tools.r8.ToolHelper.getKotlinStdlibJar; |
| import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod; |
| import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; |
| import static org.hamcrest.CoreMatchers.equalTo; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.KotlinTestBase; |
| import com.android.tools.r8.KotlinTestParameters; |
| import com.android.tools.r8.TestParameters; |
| import com.android.tools.r8.TestRuntime; |
| import com.android.tools.r8.TestRuntime.CfRuntime; |
| import com.android.tools.r8.utils.BooleanUtils; |
| import com.android.tools.r8.utils.DescriptorUtils; |
| import com.android.tools.r8.utils.codeinspector.ClassSubject; |
| import com.android.tools.r8.utils.codeinspector.FoundMethodSubject; |
| import com.android.tools.r8.utils.codeinspector.MethodSubject; |
| import java.nio.file.Path; |
| import java.util.List; |
| 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 LambdaSplitByCodeCorrectnessTest extends KotlinTestBase { |
| |
| private final TestParameters parameters; |
| private final boolean splitGroup; |
| |
| @Parameters(name = "{0}, {1}, splitGroup: {2}") |
| public static List<Object[]> data() { |
| return buildParameters( |
| getTestParameters().withDexRuntimes().withAllApiLevels().build(), |
| getKotlinTestParameters().withAllCompilersAndTargetVersions().build(), |
| BooleanUtils.values()); |
| } |
| |
| public LambdaSplitByCodeCorrectnessTest( |
| TestParameters parameters, KotlinTestParameters kotlinParameters, boolean splitGroup) { |
| super(kotlinParameters); |
| this.parameters = parameters; |
| this.splitGroup = splitGroup; |
| } |
| |
| @Test |
| public void testSplitLambdaGroups() throws Exception { |
| String PKG_NAME = LambdaSplitByCodeCorrectnessTest.class.getPackage().getName(); |
| String folder = DescriptorUtils.getBinaryNameFromJavaType(PKG_NAME); |
| CfRuntime cfRuntime = |
| parameters.isCfRuntime() ? parameters.getRuntime().asCf() : TestRuntime.getCheckedInJdk9(); |
| Path ktClasses = |
| kotlinc(cfRuntime, kotlinc, targetVersion) |
| .addSourceFiles(getKotlinFileInTest(folder, "Simple")) |
| .compile(); |
| testForR8(parameters.getBackend()) |
| .addProgramFiles(getKotlinStdlibJar(kotlinc), getKotlinAnnotationJar(kotlinc)) |
| .addProgramFiles(ktClasses) |
| .setMinApi(parameters.getApiLevel()) |
| .addKeepMainRule(PKG_NAME + ".SimpleKt") |
| .applyIf( |
| splitGroup, |
| b -> |
| b.addOptionsModification( |
| internalOptions -> |
| // Setting inliningInstructionAllowance = 1 will force each switch branch to |
| // contain an invoke instruction to a private method. |
| internalOptions.inliningInstructionAllowance = 1)) |
| .addHorizontallyMergedClassesInspector( |
| inspector -> |
| inspector.assertIsCompleteMergeGroup( |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$1", |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$2", |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$3", |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$4", |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$5", |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$6")) |
| .allowDiagnosticWarningMessages() |
| .compile() |
| .assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists.")) |
| .inspect( |
| codeInspector -> { |
| ClassSubject mergeTarget = |
| codeInspector.clazz( |
| "com.android.tools.r8.kotlin.lambda.b159688129.SimpleKt$main$1"); |
| assertThat(mergeTarget, isPresent()); |
| |
| MethodSubject virtualMethodSubject = |
| mergeTarget.uniqueMethodThatMatches( |
| method -> method.isVirtual() && !method.isSynthetic()); |
| assertThat(virtualMethodSubject, isPresent()); |
| |
| int found = 0; |
| for (FoundMethodSubject directMethodSubject : |
| mergeTarget.allMethods(x -> x.isPrivate() && !x.isSynthetic())) { |
| assertThat(virtualMethodSubject, invokesMethod(directMethodSubject)); |
| found++; |
| } |
| assertEquals(splitGroup ? 6 : 0, found); |
| }) |
| .run(parameters.getRuntime(), PKG_NAME + ".SimpleKt") |
| .assertSuccessWithOutputLines("Hello1", "Hello2", "Hello3", "Hello4", "Hello5", "Hello6"); |
| } |
| } |