blob: 866a3ba3d00ccc17309e595cdc6135237ee3ba01 [file] [log] [blame]
// Copyright (c) 2025, 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.partial;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class PartialCompilationSignatureRewritingTest extends TestBase {
@Parameter(0)
public TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
@Test
public void testD8() throws Exception {
parameters.assumeDexRuntime();
parameters.assumeNoPartialCompilation();
testForD8(parameters)
.addInnerClasses(getClass())
.release()
.run(parameters.getRuntime(), ExcludedClass.class)
.assertSuccessWithOutputLines(
"class " + IncludedClassA.class.getTypeName(),
"class " + IncludedClassB.class.getTypeName(),
"class " + IncludedClassC.class.getTypeName());
}
@Test
public void testR8() throws Exception {
testForR8Partial(parameters)
.addR8ExcludedClasses(ExcludedClass.class)
.addR8IncludedClasses(IncludedClassA.class, IncludedClassB.class, IncludedClassC.class)
.compile()
.apply(
compileResult -> {
ClassSubject aClassSubject = compileResult.inspector().clazz(IncludedClassA.class);
assertThat(aClassSubject, isPresentAndRenamed());
ClassSubject bClassSubject = compileResult.inspector().clazz(IncludedClassB.class);
assertThat(bClassSubject, isPresentAndRenamed());
ClassSubject cClassSubject = compileResult.inspector().clazz(IncludedClassC.class);
assertThat(cClassSubject, isPresentAndRenamed());
compileResult
.run(parameters.getRuntime(), ExcludedClass.class)
.assertSuccessWithOutputLines(
"class " + aClassSubject.getFinalName(),
"class " + bClassSubject.getFinalName(),
"class " + cClassSubject.getFinalName());
});
}
static class ExcludedClass<T extends IncludedClassA> {
static ExcludedClass<IncludedClassB> f;
@SuppressWarnings("rawtypes")
public static <T extends IncludedClassC> void main(String[] args)
throws NoSuchFieldException, NoSuchMethodException {
// Retrieve and print IncludedClassA.
for (TypeVariable<Class<ExcludedClass>> typeParameter :
ExcludedClass.class.getTypeParameters()) {
for (Type bound : typeParameter.getBounds()) {
System.out.println(bound);
}
}
// Retrieve and print IncludedClassB.
ParameterizedType genericType =
(ParameterizedType) ExcludedClass.class.getDeclaredField("f").getGenericType();
for (Type actualTypeArgument : genericType.getActualTypeArguments()) {
System.out.println(actualTypeArgument);
}
// Retrieve and print IncludedClassC.
for (TypeVariable<Method> typeParameter :
ExcludedClass.class.getDeclaredMethod("main", String[].class).getTypeParameters()) {
for (Type bound : typeParameter.getBounds()) {
System.out.println(bound);
}
}
}
}
static class IncludedClassA {}
static class IncludedClassB extends IncludedClassA {}
static class IncludedClassC {}
}