blob: 7b02bdb765438a3704afddeb6c74bf278d6a5ab4 [file] [log] [blame]
// 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.kotlin.lambda;
import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_5_0;
import static com.android.tools.r8.ToolHelper.getKotlinAnnotationJar;
import static com.android.tools.r8.utils.PredicateUtils.not;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.HorizontallyMergedClassesInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
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 KotlinLambdaMergingTrivialJavaStyleTest extends KotlinTestBase {
private final boolean allowAccessModification;
private final TestParameters parameters;
@Parameters(name = "{0}, {1}, allow access modification: {2}")
public static Collection<Object[]> data() {
return buildParameters(
getTestParameters()
.withCfRuntime(CfVm.last())
.withDexRuntime(Version.last())
.withAllApiLevels()
.build(),
getKotlinTestParameters().withAllCompilersAndTargetVersions().build(),
BooleanUtils.values());
}
public KotlinLambdaMergingTrivialJavaStyleTest(
TestParameters parameters,
KotlinTestParameters kotlinParameters,
boolean allowAccessModification) {
super(kotlinParameters);
this.allowAccessModification = allowAccessModification;
this.parameters = parameters;
}
@Test
public void testJVM() throws Exception {
assumeFalse(allowAccessModification);
assumeTrue(parameters.isCfRuntime());
assumeTrue(kotlinParameters.isFirst());
testForJvm()
.addProgramFiles(getProgramFiles())
.run(parameters.getRuntime(), getMainClassName())
.assertSuccessWithOutput(getExpectedOutput());
}
@Test
public void testR8() throws Exception {
// TODO(b/185497606): Unable to merge jstyle lambda.
assumeTrue(kotlinc.isNot(KOTLINC_1_5_0));
testForR8(parameters.getBackend())
.addProgramFiles(getProgramFiles())
.addKeepMainRule(getMainClassName())
.addHorizontallyMergedClassesInspector(this::inspect)
.allowAccessModification(allowAccessModification)
.allowDiagnosticWarningMessages()
.setMinApi(parameters.getApiLevel())
.compile()
.assertAllWarningMessagesMatch(
containsString("Resource 'META-INF/MANIFEST.MF' already exists."))
.run(parameters.getRuntime(), getMainClassName())
.assertSuccessWithOutput(getExpectedOutput());
}
private void inspect(HorizontallyMergedClassesInspector inspector) throws IOException {
// Get the Kotlin lambdas in the input.
KotlinLambdasInInput lambdasInInput =
KotlinLambdasInInput.create(getProgramFiles(), getTestName());
assertEquals(39, lambdasInInput.getNumberOfJStyleLambdas());
assertEquals(0, lambdasInInput.getNumberOfKStyleLambdas());
if (!allowAccessModification) {
// Only a subset of all J-style Kotlin lambdas are merged without -allowaccessmodification.
Set<ClassReference> unmergedLambdas =
ImmutableSet.of(
lambdasInInput.getJStyleLambdaReferenceFromTypeName(
getTestName(), "inner.InnerKt$testInner1$1"),
lambdasInInput.getJStyleLambdaReferenceFromTypeName(
getTestName(), "inner.InnerKt$testInner1$2"),
lambdasInInput.getJStyleLambdaReferenceFromTypeName(
getTestName(), "inner.InnerKt$testInner1$3"),
lambdasInInput.getJStyleLambdaReferenceFromTypeName(
getTestName(), "inner.InnerKt$testInner1$4"),
lambdasInInput.getJStyleLambdaReferenceFromTypeName(
getTestName(), "inner.InnerKt$testInner1$5"));
inspector
.assertClassReferencesMerged(
lambdasInInput.getJStyleLambdas().stream()
.filter(not(unmergedLambdas::contains))
.collect(Collectors.toList()))
.assertClassReferencesNotMerged(unmergedLambdas);
return;
}
// All J-style Kotlin lambdas are merged with -allowaccessmodification.
inspector.assertClassReferencesMerged(lambdasInInput.getJStyleLambdas());
}
private String getExpectedOutput() {
return StringUtils.lines(
"{005:4}",
"{007:6}",
"009:{008}:{0}",
"011:{010}:{0}",
"013:{012}:{0}:{1}",
"015:{014}:{0}:{1}",
"017:{Local(id=016)}:{0}:{1}:{2}",
"019:{Local(id=018)}:{0}:{1}:{2}",
"021:{Local(id=Local(id=020))}:{0}:{1}:{2}:{3}",
"023:{Local(id=Local(id=022))}:{0}:{1}:{2}:{3}",
"27",
"kotlin.Unit",
"28",
"kotlin.Unit",
"029:024",
"kotlin.Unit",
"030:024",
"kotlin.Unit",
"031:024",
"kotlin.Unit",
"032:024",
"kotlin.Unit",
"Local(id=033):024:025",
"kotlin.Unit",
"Local(id=034):024:025",
"kotlin.Unit",
"Local(id=Local(id=035)):024:025:026",
"kotlin.Unit",
"Local(id=Local(id=036)):024:025:026",
"kotlin.Unit",
"037:038:039",
"039:037:038",
"038:039:037",
"Local(id=037):038:039",
"Local(id=038):037:039",
"037:Local(id=038):039",
"037:Local(id=039):038",
"Local(id=Local(id=037)):Local(id=Local(id=038)):Local(id=Local(id=039))",
"Local(id=Local(id=039)):Local(id=Local(id=037)):Local(id=Local(id=038))",
"040:Local(id=041):Local(id=Local(id=042))",
"Local(id=Local(id=042)):040:Local(id=041)",
"Local(id=041):Local(id=Local(id=042)):040",
"Local(id=040):Local(id=041):Local(id=Local(id=042))",
"Local(id=Local(id=041)):040:Local(id=Local(id=042))",
"040:Local(id=Local(id=041)):Local(id=Local(id=042))",
"040:Local(id=Local(id=Local(id=042))):Local(id=041)",
"Local(id=Local(id=040)):Local(id=Local(id=Local(id=041))):Local(id=Local(id=Local(id=Local(id=042))))",
"Local(id=Local(id=Local(id=Local(id=042)))):Local(id=Local(id=040)):Local(id=Local(id=Local(id=041)))",
"043:044:045",
"045:043:044",
"044:045:043",
"Local(id=043):044:045",
"Local(id=044):043:045",
"046:Local(id=047):Local(id=048)",
"Local(id=048):046:Local(id=047)",
"Local(id=047):Local(id=048):046",
"Local(id=046):Local(id=047):Local(id=048)",
"Local(id=Local(id=047)):046:Local(id=048)",
"{053:100}",
"055:{054}:{49}",
"057:{056}:{49}:{50}",
"059:{InnerLocal(id=058)}:{49}:{50}:{51}",
"061:{InnerLocal(id=InnerLocal(id=060))}:{49}:{50}:{51}:{52");
}
private Path getJavaJarFile() {
return getJavaJarFile(getTestName());
}
private String getMainClassName() {
return getTestName() + ".MainKt";
}
private List<Path> getProgramFiles() {
Path kotlinJarFile =
getCompileMemoizer(getKotlinFilesInResource(getTestName()), getTestName())
.configure(kotlinCompilerTool -> kotlinCompilerTool.includeRuntime().noReflect())
.getForConfiguration(kotlinc, targetVersion);
return ImmutableList.of(kotlinJarFile, getJavaJarFile(), getKotlinAnnotationJar(kotlinc));
}
private String getTestName() {
return "lambdas_jstyle_trivial";
}
}