blob: 1d2a942de6c9fd670f5224dda84daeda3b13504b [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.maindexlist.b72312389;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.tools.r8.BaseCommand;
import com.android.tools.r8.CompatProguardCommandBuilder;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.GenerateMainDexList;
import com.android.tools.r8.GenerateMainDexListCommand;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DexInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(VmTestRunner.class)
public class B72312389 extends TestBase {
// Build a app with a class extending InstrumentationTestCase and including both the junit
// and the Android library.
private void buildInstrumentationTestCaseApplication(BaseCommand.Builder builder) {
builder
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.O.getLevel()))
.addProgramFiles(
Paths.get("build", "test", "examplesAndroidApi",
"classes", "instrumentationtest", "InstrumentationTest.class"))
.addProgramFiles(ToolHelper.getFrameworkJunitJarPath(DexVm.ART_7_0_0_HOST));
}
private List<String> keepInstrumentationTestCaseRules = ImmutableList.of(
"-keep class instrumentationtest.InstrumentationTest {",
" *;",
"}");
@Test
public void testGenerateMainDexList() throws Exception {
CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
GenerateMainDexListCommand.Builder builder = GenerateMainDexListCommand.builder(diagnostics);
buildInstrumentationTestCaseApplication(builder);
GenerateMainDexListCommand command = builder
.addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
.build();
List<String> mainDexList = GenerateMainDexList.run(command);
assertTrue(mainDexList.contains("junit/framework/TestCase.class"));
diagnostics.assertEmpty();
}
private static class StringBox {
String content;
}
@Test
public void testR8ForceProguardCompatibility() throws Exception {
StringBox mainDexList = new StringBox();
// Build a app with a class extending InstrumentationTestCase and including both the junit
// and the Android library.
CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
R8Command.Builder builder = new CompatProguardCommandBuilder(true, diagnostics);
buildInstrumentationTestCaseApplication(builder);
R8Command command = builder
.setMinApiLevel(AndroidApiLevel.K.getLevel())
// TODO(72793900): This should not be required.
.addProguardConfiguration(ImmutableList.of("-keep class ** { *; }"), Origin.unknown())
.addProguardConfiguration(ImmutableList.of("-dontobfuscate"), Origin.unknown())
.addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
.setProgramConsumer(DexIndexedConsumer.emptyConsumer())
.setMainDexListConsumer(
(string, handler) -> mainDexList.content = string)
.build();
DexInspector inspector = new DexInspector(ToolHelper.runR8(command));
assertTrue(inspector.clazz("instrumentationtest.InstrumentationTest").isPresent());
assertTrue(mainDexList.content.contains("junit/framework/TestCase.class"));
// TODO(72794301): Two copies of this message is a bit over the top.
assertEquals(2,
diagnostics.countLibraryClassExtensdProgramClassWarnings(
"android.test.InstrumentationTestCase", "junit.framework.TestCase"));
}
@Test
public void testR8() throws Exception {
CollectingDiagnosticHandler diagnostics = new CollectingDiagnosticHandler();
R8Command.Builder builder = R8Command.builder(diagnostics);
buildInstrumentationTestCaseApplication(builder);
R8Command command = builder
.addMainDexRules(keepInstrumentationTestCaseRules, Origin.unknown())
.setProgramConsumer(DexIndexedConsumer.emptyConsumer())
.build();
try {
R8.run(command);
fail();
} catch (CompilationFailedException e) {
// Expected, as library class extending program class is an error for R8.
}
}
private static class CollectingDiagnosticHandler implements DiagnosticsHandler {
private final List<Diagnostic> infos = new ArrayList<>();
private final List<Diagnostic> warnings = new ArrayList<>();
private final List<Diagnostic> errors = new ArrayList<>();
@Override
public void info(Diagnostic info) {
infos.add(info);
}
@Override
public void warning(Diagnostic warning) {
warnings.add(warning);
}
@Override
public void error(Diagnostic error) {
errors.add(error);
}
public void assertEmpty() {
assertEquals(0, errors.size());
assertEquals(0, warnings.size());
assertEquals(0, infos.size());
}
private boolean isLibraryClassExtensdProgramClassWarnings(
String libraryClass, String programClass, Diagnostic diagnostic) {
return diagnostic.getDiagnosticMessage().equals(
"Library class "+ libraryClass + " extends program class " + programClass);
}
public long countLibraryClassExtensdProgramClassWarnings(
String libraryClass, String programClass) {
return warnings.stream()
.filter(diagnostics ->
isLibraryClassExtensdProgramClassWarnings(libraryClass, programClass, diagnostics))
.count();
}
}
}