blob: b4dc614247abcf671910128a9ce52e67567d9184 [file] [log] [blame]
// Copyright (c) 2017, 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.jasmin;
import static java.util.Collections.emptyList;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.ThrowingBiFunction;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.VmTestRunner.IgnoreForRangeOfVmVersions;
import com.android.tools.r8.VmTestRunner.IgnoreForVmVersions;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassFileVersion;
import com.android.tools.r8.utils.ThrowingSupplier;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(VmTestRunner.class)
public class MemberResolutionTest extends JasminTestBase {
private static final String MAIN_CLASS = "Main";
@Test
public void lookupStaticFieldFromDiamondInterface() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
ClassBuilder interfaceA = builder.addInterface("InterfaceA");
interfaceA.addStaticFinalField("aField", "I", "42");
ClassBuilder interfaceB = builder.addInterface("InterfaceB");
interfaceB.addStaticFinalField("aField", "I", "123");
builder.addInterface("SubInterface", "InterfaceB", "InterfaceA");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 3",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" getstatic SubInterface/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureSameOutput(builder);
}
@Test
public void lookupStaticFieldFromInterfaceNotSuper() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addStaticFinalField("aField", "I", "42");
ClassBuilder iface = builder.addInterface("Interface");
iface.addStaticFinalField("aField", "I", "123");
builder.addClass("SubClass", "SuperClass", "Interface");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 3",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" getstatic SubClass/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureSameOutput(builder);
}
@Test
public void lookupStaticFieldWithFieldGetFromNullReference() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addStaticFinalField("aField", "I", "42");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 3",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" aconst_null",
" getfield SubClass/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureICCE(builder);
}
@Test
public void lookupStaticFieldWithFieldGetFromNullReferenceDirectly() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addStaticFinalField("aField", "I", "42");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 3",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" aconst_null",
" getfield SuperClass/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureICCE(builder);
}
@Test
public void lookupStaticFieldWithFieldPutFromNullReference() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addStaticFinalField("aField", "I", "42");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 5",
".limit locals 2",
" aconst_null",
" iconst_0",
" putfield SubClass/aField I",
" return");
ensureICCE(builder);
}
@Test
public void lookupStaticFieldFromSupersInterfaceNotSupersSuper() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
ClassBuilder superSuperClass = builder.addClass("SuperSuperClass");
superSuperClass.addStaticFinalField("aField", "I", "123");
ClassBuilder iface = builder.addInterface("Interface");
iface.addStaticFinalField("aField", "I", "42");
builder.addClass("SuperClass", "SuperSuperClass", "Interface");
builder.addClass("SubClass", "SuperClass");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 3",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" getstatic SubClass/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureSameOutput(builder);
}
@Test
public void lookupInstanceFieldWithShadowingStatic() throws Exception {
JasminBuilder builder = new JasminBuilder();
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addField("public", "aField", "I", "42");
superClass.addDefaultConstructor();
ClassBuilder interfaceA = builder.addInterface("Interface");
interfaceA.addStaticFinalField("aField", "I", "123");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass", "Interface");
subClass.addDefaultConstructor();
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 3",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" new SubClass",
" dup",
" invokespecial SubClass/<init>()V",
" getfield SubClass/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureICCE(builder);
}
@Test
public void lookupStaticFieldWithShadowingInstance() throws Exception {
JasminBuilder builder = new JasminBuilder();
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addStaticField("aField", "I", "42");
superClass.addDefaultConstructor();
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addField("public", "aField", "I", "123");
subClass.addDefaultConstructor();
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" getstatic SubClass/aField I",
" invokevirtual java/io/PrintStream/print(I)V",
" return");
ensureICCE(builder);
}
@Test
@IgnoreForRangeOfVmVersions(from = Version.V5_1_1, to = Version.V7_0_0)
public void lookupVirtualMethodWithConflictingPrivate() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JSE_5);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
subClass.addPrivateVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 123",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubClass",
" dup",
" invokespecial SubClass/<init>()V",
" invokevirtual SubClass/aMethod()V",
" return");
ensureIAE(builder);
}
@Test
@IgnoreForRangeOfVmVersions(from = Version.V5_1_1, to = Version.V7_0_0)
public void lookupDirectMethodFromWrongContext() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JSE_5);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
subClass.addPrivateVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 123",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubClass",
" dup",
" invokespecial SubClass/<init>()V",
" invokespecial SubClass/aMethod()V",
" return");
ensureExceptionOrCompilerError(builder, IllegalAccessError.class,
compiler -> compiler.equals(CompilerUnderTest.R8));
}
@Test
public void lookupPrivateSuperFromSubClass() throws Exception {
JasminBuilder builder = new JasminBuilder(ClassFileVersion.JSE_5);
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addPrivateVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
subClass.addVirtualMethod("callAMethod", emptyList(), "V",
".limit stack 1",
".limit locals 1",
" aload 0",
" invokespecial SuperClass/aMethod()V",
" return");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubClass",
" dup",
" invokespecial SubClass/<init>()V",
" invokevirtual SubClass/callAMethod()V",
" return");
ensureIAE(builder);
}
@Test
@IgnoreForRangeOfVmVersions(from = Version.V5_1_1, to = Version.V7_0_0)
public void lookupStaticMethodWithConflictingVirtual() throws Exception {
JasminBuilder builder = new JasminBuilder();
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addStaticMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
subClass.addVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 123",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubClass",
" dup",
" invokespecial SubClass/<init>()V",
" invokestatic SubClass/aMethod()V",
" return");
ensureICCE(builder);
}
@Test
@IgnoreForRangeOfVmVersions(from = Version.V5_1_1, to = Version.V7_0_0)
public void lookupVirtualMethodWithConflictingStatic() throws Exception {
JasminBuilder builder = new JasminBuilder();
ClassBuilder superClass = builder.addClass("SuperClass");
superClass.addDefaultConstructor();
superClass.addVirtualMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
subClass.addDefaultConstructor();
subClass.addStaticMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 123",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubClass",
" dup",
" invokespecial SubClass/<init>()V",
" invokevirtual SubClass/aMethod()V",
" return");
ensureICCE(builder);
}
@Test
@IgnoreForRangeOfVmVersions(from = Version.V5_1_1, to = Version.V7_0_0)
public void testInterfaceWithDifferentSuper() throws Exception {
JasminBuilder builder = new JasminBuilder();
ClassBuilder superInterface = builder.addClass("SuperInterface");
superInterface.addStaticMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
ClassBuilder subInterface = builder.addClass("SubInterface", "SuperInterface");
subInterface.setIsInterface();
builder.addClass("Test", "java/lang/Object", "SubInterface");
ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" invokestatic SubInterface/aMethod()V",
" return");
ensureAllFail(builder);
}
@Test
public void testCallMissingStaticMethod() throws Exception {
JasminBuilder builder = new JasminBuilder();
builder.addClass("Empty");
ClassBuilder main = builder.addClass("Main");
main.addMainMethod(
".limit stack 2",
".limit locals 1",
" invokestatic Empty/aMethod()V",
" return");
ensureRuntimeException(builder, NoSuchMethodError.class);
}
@Test
public void testReadMissingField() throws Exception {
JasminBuilder builder = new JasminBuilder();
builder.addClass("Empty");
ClassBuilder main = builder.addClass("Main");
main.addMainMethod(
".limit stack 2",
".limit locals 1",
" getstatic Empty/aField I",
" return");
ensureRuntimeException(builder, NoSuchFieldError.class);
}
@Test
// TODO(119938529): Triage.
@IgnoreForVmVersions(Version.V8_1_0)
public void testRebindVirtualCallToStatic() throws Exception {
// Library classes.
JasminBuilder libraryBuilder = new JasminBuilder();
ClassBuilder classWithStatic = libraryBuilder.addClass("ClassWithStatic");
classWithStatic.addDefaultConstructor();
classWithStatic.addStaticMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
// Program classes.
JasminBuilder programBuilder = new JasminBuilder();
programBuilder.addClass("SubClass", "ClassWithStatic")
.addDefaultConstructor();
programBuilder.addClass("SubSubClass", "SubClass")
.addDefaultConstructor();
ClassBuilder mainClass = programBuilder.addClass("Main");
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubSubClass",
" dup",
" invokespecial SubSubClass/<init>()V",
" invokevirtual SubSubClass/aMethod()V",
" return");
ensureICCE(programBuilder, libraryBuilder);
}
@Test
// TODO(119938529): Triage.
@IgnoreForVmVersions(Version.V8_1_0)
public void testRebindVirtualCallToPackagePrivateStatic() throws Exception {
// Library classes.
JasminBuilder libraryBuilder = new JasminBuilder();
ClassBuilder classWithStatic = libraryBuilder.addClass("ClassWithStatic");
classWithStatic.addDefaultConstructor();
classWithStatic.addPackagePrivateStaticMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
libraryBuilder.addClass("p/LibSub", "ClassWithStatic")
.addDefaultConstructor();
// Program classes.
JasminBuilder programBuilder = new JasminBuilder();
programBuilder.addClass("p/SubClass", "p/LibSub")
.addDefaultConstructor();
programBuilder.addClass("SubSubClass", "p/SubClass")
.addDefaultConstructor();
ClassBuilder mainClass = programBuilder.addClass("Main");
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubSubClass",
" dup",
" invokespecial SubSubClass/<init>()V",
" invokevirtual SubSubClass/aMethod()V",
" return");
ensureICCE(programBuilder, libraryBuilder);
}
@Test
// TODO(119938529): Triage.
@IgnoreForVmVersions(Version.V8_1_0)
public void testRebindVirtualCallToStaticInPackagePrivateClass() throws Exception {
// Library classes.
JasminBuilder libraryBuilder = new JasminBuilder();
ClassBuilder classWithStatic = libraryBuilder.addClass("ClassWithStatic");
classWithStatic.setAccess("");
classWithStatic.addDefaultConstructor();
classWithStatic.addStaticMethod("aMethod", emptyList(), "V",
".limit stack 2",
".limit locals 1",
" getstatic java/lang/System/out Ljava/io/PrintStream;",
" bipush 42",
" invokevirtual java/io/PrintStream/println(I)V",
" return");
libraryBuilder.addClass("LibSub", "ClassWithStatic")
.addDefaultConstructor();
libraryBuilder.addClass("p/LibSubSub", "LibSub")
.addDefaultConstructor();
// Program classes.
JasminBuilder programBuilder = new JasminBuilder();
programBuilder.addClass("p/SubClass", "p/LibSubSub")
.addDefaultConstructor();
programBuilder.addClass("SubSubClass", "p/SubClass")
.addDefaultConstructor();
ClassBuilder mainClass = programBuilder.addClass("Main");
mainClass.addMainMethod(
".limit stack 2",
".limit locals 1",
" new SubSubClass",
" dup",
" invokespecial SubSubClass/<init>()V",
" invokevirtual SubSubClass/aMethod()V",
" return");
ensureICCE(programBuilder, libraryBuilder);
}
private void ensureSameOutput(JasminBuilder app) throws Exception {
String javaOutput = runOnJava(app, MAIN_CLASS);
String dxOutput = runOnArtDx(app, MAIN_CLASS);
String d8Output = runOnArtD8(app, MAIN_CLASS);
String r8Output = runOnArtR8(app, MAIN_CLASS);
String r8ShakenOutput = runOnArtR8(app, MAIN_CLASS, keepMainProguardConfiguration(MAIN_CLASS),
null);
Assert.assertEquals(javaOutput, dxOutput);
Assert.assertEquals(javaOutput, d8Output);
Assert.assertEquals(javaOutput, r8Output);
Assert.assertEquals(javaOutput, r8ShakenOutput);
}
private void ensureFails(JasminBuilder builder, String main,
ThrowingBiFunction<JasminBuilder, String, ProcessResult, Exception> runner) throws Exception {
ProcessResult result;
try {
result = runner.apply(builder, main);
} catch (Exception e) {
return;
}
Assert.assertNotEquals(0, result.exitCode);
}
private void ensureAllFail(JasminBuilder app) throws Exception {
ensureFails(app, MAIN_CLASS, this::runOnJavaRaw);
ensureFails(app, MAIN_CLASS, this::runOnArtDxRaw);
ensureFails(app, MAIN_CLASS, this::runOnArtD8Raw);
ensureFails(app, MAIN_CLASS, (a, m) -> runOnArtR8Raw(a, m, null));
ensureFails(app, MAIN_CLASS,
(a, m) -> runOnArtR8Raw(a, m, keepMainProguardConfiguration(MAIN_CLASS), null));
}
private void ensureExceptionOrCompilerError(JasminBuilder app,
Class<? extends Throwable> exception,
Predicate<CompilerUnderTest> predicate) throws Exception {
String name = exception.getSimpleName();
BiConsumer<ThrowingSupplier<ProcessResult, Exception>, CompilerUnderTest> runtest =
(process, compiler) -> {
try {
ProcessResult result = process.get();
Assert.assertFalse(compiler != null && predicate.test(compiler));
Assert.assertTrue(result.stderr.contains(name));
} catch (CompilationFailedException e) {
Assert.assertTrue(compiler == null || predicate.test(compiler));
} catch (Exception e) {
Assert.fail();
}
};
runtest.accept(() -> runOnJavaNoVerifyRaw(app, MAIN_CLASS), null);
runtest.accept(() -> runOnArtDxRaw(app, MAIN_CLASS), null);
runtest.accept(() -> runOnArtD8Raw(app, MAIN_CLASS), CompilerUnderTest.D8);
runtest.accept(() -> runOnArtR8Raw(app, MAIN_CLASS, null), CompilerUnderTest.R8);
runtest.accept(() -> runOnArtR8Raw(app, MAIN_CLASS, keepMainProguardConfiguration(MAIN_CLASS),
null), CompilerUnderTest.R8);
}
private void ensureICCE(JasminBuilder app) throws Exception {
ensureRuntimeException(app, IncompatibleClassChangeError.class);
}
private void ensureICCE(JasminBuilder app, JasminBuilder library) throws Exception {
ensureRuntimeException(app, library, IncompatibleClassChangeError.class);
}
private void ensureIAE(JasminBuilder app) throws Exception {
ensureRuntimeException(app, IllegalAccessError.class);
}
private void ensureRuntimeException(JasminBuilder app, Class exception) throws Exception {
String name = exception.getSimpleName();
ProcessResult dxOutput = runOnArtDxRaw(app, MAIN_CLASS);
Assert.assertTrue(dxOutput.stderr.contains(name));
ProcessResult d8Output = runOnArtD8Raw(app, MAIN_CLASS);
Assert.assertTrue(d8Output.stderr.contains(name));
ProcessResult r8Output = runOnArtR8Raw(app, MAIN_CLASS, null);
Assert.assertTrue(r8Output.stderr.contains(name));
ProcessResult r8ShakenOutput = runOnArtR8Raw(app, MAIN_CLASS,
keepMainProguardConfiguration(MAIN_CLASS), null);
Assert.assertTrue(r8ShakenOutput.stderr.contains(name));
ProcessResult javaOutput = runOnJavaNoVerifyRaw(app, MAIN_CLASS);
Assert.assertTrue(javaOutput.stderr.contains(name));
}
private void ensureRuntimeException(JasminBuilder app, JasminBuilder library, Class exception)
throws Exception {
String name = exception.getSimpleName();
ProcessResult dxOutput = runOnArtDxRaw(app, library, MAIN_CLASS);
Assert.assertTrue(dxOutput.stderr.contains(name));
ProcessResult d8Output = runOnArtD8Raw(app, library, MAIN_CLASS);
Assert.assertTrue(d8Output.stderr.contains(name));
ProcessResult r8Output = runOnArtR8Raw(app, library, MAIN_CLASS,
noShrinkingNoMinificationProguardConfiguration(), null);
Assert.assertTrue(r8Output.stderr.contains(name));
ProcessResult r8ShakenOutput = runOnArtR8Raw(app, library, MAIN_CLASS,
keepMainProguardConfiguration(MAIN_CLASS), null);
Assert.assertTrue(r8ShakenOutput.stderr.contains(name));
ProcessResult javaOutput = runOnJavaNoVerifyRaw(app, library, MAIN_CLASS);
Assert.assertTrue(javaOutput.stderr.contains(name));
}
}