blob: 237b0e1c9fea2dc8dda923ed7109fba139e1c7f7 [file] [log] [blame]
// Copyright (c) 2019, 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.backports;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
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.ToolHelper;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableSet;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
@RunWith(Parameterized.class)
public class TestBackportedNotPresentInAndroidJar extends TestBase {
@Parameter(0)
public TestParameters parameters;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withNoneRuntime().build();
}
private Set<DexMethod> expectedToAlwaysBePresentInAndroidJar(DexItemFactory factory)
throws Exception {
MethodReference AtomicReferenceFieldUpdater_compareAndSet =
Reference.methodFromMethod(
AtomicReferenceFieldUpdater.class.getDeclaredMethod(
"compareAndSet", Object.class, Object.class, Object.class));
assert AtomicReferenceFieldUpdater_compareAndSet.getReturnType()
.getTypeName()
.equals("boolean");
MethodReference AtomicReference_compareAndSet =
Reference.methodFromMethod(
AtomicReference.class.getDeclaredMethod("compareAndSet", Object.class, Object.class));
assert AtomicReference_compareAndSet.getReturnType().getTypeName().equals("boolean");
MethodReference AtomicReferenceArray_compareAndSet =
Reference.methodFromMethod(
AtomicReferenceArray.class.getDeclaredMethod(
"compareAndSet", int.class, Object.class, Object.class));
assert AtomicReference_compareAndSet.getReturnType().getTypeName().equals("boolean");
return ImmutableSet.of(
factory.createMethod(AtomicReferenceFieldUpdater_compareAndSet),
factory.createMethod(AtomicReference_compareAndSet),
factory.createMethod(AtomicReferenceArray_compareAndSet));
}
@Test
public void testBackportedMethodsPerAPILevel() throws Exception {
for (AndroidApiLevel apiLevel : AndroidApiLevel.values()) {
if (!ToolHelper.hasAndroidJar(apiLevel)) {
// Only check for the android jar versions present in third_party.
System.out.println("Skipping check for " + apiLevel);
continue;
}
// Check that the backported methods for each API level are are not present in the
// android.jar for that level.
CodeInspector inspector = new CodeInspector(ToolHelper.getAndroidJar(apiLevel));
InternalOptions options = new InternalOptions();
options.setMinApiLevel(apiLevel);
List<DexMethod> backportedMethods =
BackportedMethodRewriter.generateListOfBackportedMethods(
AndroidApp.builder().build(), options, ThreadUtils.getExecutorService(options));
Set<DexMethod> alwaysPresent = expectedToAlwaysBePresentInAndroidJar(options.itemFactory);
for (DexMethod method : backportedMethods) {
// Two different DexItemFactories are in play, but as toSourceString is used for lookup
// that is not an issue.
ClassSubject clazz = inspector.clazz(method.holder.toSourceString());
MethodSubject foundInAndroidJar =
clazz.method(
method.proto.returnType.toSourceString(),
method.name.toSourceString(),
Arrays.stream(method.proto.parameters.values)
.map(DexType::toSourceString)
.collect(Collectors.toList()));
assertThat(
foundInAndroidJar + " present in " + apiLevel,
foundInAndroidJar,
notIf(isPresent(), !alwaysPresent.contains(method)));
}
}
}
}