blob: 33d1deb37cc9e05611a8363e9e156118b7bc5ef7 [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.apimodel;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.CodeMatchers;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public abstract class ApiModelingTestHelper {
static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
ThrowableConsumer<T> setMockApiLevelForMethod(Method method, AndroidApiLevel apiLevel) {
return compilerBuilder -> {
compilerBuilder.addOptionsModification(
options -> {
options
.apiModelingOptions()
.methodApiMapping
.put(Reference.methodFromMethod(method), apiLevel);
});
};
}
static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
ThrowableConsumer<T> setMockApiLevelForField(Field field, AndroidApiLevel apiLevel) {
return compilerBuilder -> {
compilerBuilder.addOptionsModification(
options -> {
options
.apiModelingOptions()
.fieldApiMapping
.put(Reference.fieldFromField(field), apiLevel);
});
};
}
static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>> ThrowableConsumer<T> setMockApiLevelForType(
Class<?> clazz, AndroidApiLevel apiLevel) {
return compilerBuilder -> {
compilerBuilder.addOptionsModification(
options -> {
options
.apiModelingOptions()
.typeApiMapping
.put(Reference.classFromClass(clazz), apiLevel);
});
};
}
static void enableApiCallerIdentification(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
compilerBuilder.addOptionsModification(
options -> {
options.apiModelingOptions().enableApiCallerIdentification = true;
});
}
static ApiModelingMethodVerificationHelper verifyThat(TestParameters parameters, Method method) {
return new ApiModelingMethodVerificationHelper(parameters, method);
}
public static class ApiModelingMethodVerificationHelper {
private final Method methodOfInterest;
private final TestParameters parameters;
public ApiModelingMethodVerificationHelper(TestParameters parameters, Method methodOfInterest) {
this.methodOfInterest = methodOfInterest;
this.parameters = parameters;
}
protected ThrowingConsumer<CodeInspector, Exception> inlinedIntoFromApiLevel(
Method method, AndroidApiLevel apiLevel) {
return parameters.isDexRuntime() && parameters.getApiLevel().isGreaterThanOrEqualTo(apiLevel)
? inlinedInto(method)
: notInlinedInto(method);
}
private ThrowingConsumer<CodeInspector, Exception> notInlinedInto(Method method) {
return inspector -> {
MethodSubject candidate = inspector.method(methodOfInterest);
assertThat(candidate, isPresent());
MethodSubject target = inspector.method(method);
assertThat(target, isPresent());
assertThat(target, CodeMatchers.invokesMethod(candidate));
};
}
public ThrowingConsumer<CodeInspector, Exception> inlinedInto(Method method) {
return inspector -> {
MethodSubject candidate = inspector.method(methodOfInterest);
if (!candidate.isPresent()) {
return;
}
MethodSubject target = inspector.method(method);
assertThat(target, isPresent());
assertThat(target, not(CodeMatchers.invokesMethod(candidate)));
};
}
}
}