blob: 888436d476ee9bfc2474caab361e832069b3cce3 [file] [log] [blame]
// Copyright (c) 2021, 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.desugar.desugaredlibrary;
import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.errors.DesugaredLibraryMismatchDiagnostic;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;
import java.util.Collection;
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 DesugaredLibraryMismatchTest extends DesugaredLibraryTestBase {
private final TestParameters parameters;
private final AndroidApiLevel apiLevel;
@Parameters(name = "API level: {1}")
public static Collection<Object[]> data() {
return buildParameters(
getTestParameters().withNoneRuntime().build(),
new AndroidApiLevel[] {
AndroidApiLevel.LATEST, AndroidApiLevel.O, AndroidApiLevel.N_MR1, AndroidApiLevel.B
});
}
public DesugaredLibraryMismatchTest(TestParameters parameters, AndroidApiLevel apiLevel) {
this.parameters = parameters;
this.apiLevel = apiLevel;
}
@Test
public void testInputDexed() throws Exception {
// DEX code without library desugaring.
Path libraryDex =
testForD8(Backend.DEX)
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.compile()
.writeToZip();
// Combine DEX input without library desugaring with dexing with library desugaring.
try {
testForD8()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(libraryDex)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
.compileWithExpectedDiagnostics(
diagnostics -> {
diagnostics.assertNoInfos();
diagnostics.assertAllWarningsMatch(
diagnosticMessage(
containsString(
"The compilation is slowed down due to a mix of class file and dex"
+ " file inputs in the context of desugared library.")));
if (apiLevel.isLessThan(AndroidApiLevel.O)) {
diagnostics.assertErrorsMatch(
diagnosticType(DesugaredLibraryMismatchDiagnostic.class));
} else {
diagnostics.assertNoMessages();
}
});
} catch (CompilationFailedException e) {
}
}
@Test
public void testInputCfDesugared() throws Exception {
// CF to CF desugared code without library desugaring.
Path desugaredLibrary =
testForD8(Backend.CF)
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.compile()
.writeToZip();
// Combine CF desugared input without library desugaring with dexing with library desugaring.
testForD8()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(desugaredLibrary)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
.compile();
}
@Test
public void testInputCfDesugaredAndDexed() throws Exception {
// CF to CF desugared code without library desugaring.
Path desugaredLibrary =
testForD8(Backend.CF)
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.compile()
.writeToZip();
// CF to CF desugared code without library desugaring compiled to DEX.
Path desugaredLibraryDex =
testForD8(Backend.DEX)
.addProgramFiles(desugaredLibrary)
.setMinApi(apiLevel)
.disableDesugaring()
.compile()
.writeToZip();
testForD8()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(desugaredLibraryDex)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
.compile();
}
@Test
public void testCfInputLibraryDesugared() throws Exception {
// CF to CF desugared code with library desugaring.
Path desugaredLibrary =
testForD8(Backend.CF)
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
.compile()
.writeToZip();
// Combine CF input with library desugaring with dexing without library desugaring.
try {
testForD8()
.addProgramFiles(desugaredLibrary)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
.compileWithExpectedDiagnostics(
diagnostics -> {
if (apiLevel.isLessThan(AndroidApiLevel.O)) {
diagnostics.assertOnlyErrors();
diagnostics.assertErrorsMatch(
diagnosticType(DesugaredLibraryMismatchDiagnostic.class));
} else {
diagnostics.assertNoMessages();
}
});
} catch (CompilationFailedException e) {
}
}
@Test
public void testMergeLibraryDesugaredWithNotLibraryDesugared() throws Exception {
// DEX code with library desugaring.
Path libraryDex =
testForD8(Backend.DEX)
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
.compile()
.writeToZip();
// DEX code without library desugaring.
Path programDex =
testForD8(Backend.DEX)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
.compile()
.writeToZip();
try {
testForD8()
.addProgramFiles(libraryDex)
.addProgramFiles(programDex)
.setMinApi(apiLevel)
.compileWithExpectedDiagnostics(
diagnostics -> {
if (apiLevel.isLessThan(AndroidApiLevel.O)) {
diagnostics.assertOnlyErrors();
diagnostics.assertErrorsMatch(
diagnosticType(DesugaredLibraryMismatchDiagnostic.class));
} else {
diagnostics.assertNoMessages();
}
});
} catch (CompilationFailedException e) {
}
}
@Test
public void testMergeDifferentLibraryDesugarVersions() throws Exception {
// DEX code with library desugaring using a desugared library configuration with a
// different identifier.
String identifier = "my-identifier";
Path libraryDex =
testForD8(Backend.DEX)
.applyIf(
apiLevel.isLessThan(AndroidApiLevel.O),
builder ->
builder.addOptionsModification(
options ->
options.desugaredLibraryConfiguration =
DesugaredLibraryConfiguration.builder(
options.dexItemFactory(),
options.reporter,
Origin.unknown())
.setDesugaredLibraryIdentifier(identifier)
.build()))
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
.compile()
.writeToZip();
// DEX code without library desugaring.
Path programDex =
testForD8(Backend.DEX)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
.compile()
.writeToZip();
try {
testForD8()
.addProgramFiles(libraryDex)
.addProgramFiles(programDex)
.setMinApi(apiLevel)
.compileWithExpectedDiagnostics(
diagnostics -> {
if (apiLevel.isLessThan(AndroidApiLevel.O)) {
diagnostics.assertOnlyErrors();
diagnostics.assertErrorsMatch(
allOf(
diagnosticType(DesugaredLibraryMismatchDiagnostic.class),
diagnosticMessage(containsString(identifier))));
} else {
diagnostics.assertNoMessages();
}
});
} catch (CompilationFailedException e) {
}
}
static class Library {}
static class TestRunner {
public static void main(String[] args) {
System.out.println(Library.class);
}
}
}