blob: 517e47289ba67bff1326ff2c1389469fe90889c4 [file] [log] [blame]
/*
* Copyright 2019 The Bazel Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devtools.build.android.desugar.testing.junit;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static org.junit.Assert.assertThrows;
import com.google.devtools.build.android.desugar.testing.junit.RuntimeMethodHandle.MemberUseContext;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.nio.file.Paths;
import java.util.Arrays;
import javax.inject.Inject;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
/** The test for {@link DesugarRule}. */
@JdkSuppress(minJdkVersion = JdkVersion.V11)
@RunWith(DesugarRunner.class)
public final class DesugarRuleTest {
@Rule
public final DesugarRule desugarRule =
DesugarRule.builder(this, MethodHandles.lookup())
.addInputs(Paths.get(System.getProperty("input_jar")))
.addSourceInputsFromJvmFlag("input_srcs")
.addJavacOptions("-source 11", "-target 11")
.enableIterativeTransformation(3)
.setWorkingJavaPackage("com.google.devtools.build.android.desugar.testing.junit")
.build();
@Inject
@DynamicClassLiteral("DesugarRuleTestTarget$InterfaceSubjectToDesugar")
private Class<?> interfaceSubjectToDesugarRound1;
@Inject
@DynamicClassLiteral(value = "DesugarRuleTestTarget$InterfaceSubjectToDesugar", round = 2)
private Class<?> interfaceSubjectToDesugarRound2;
@Inject
@DynamicClassLiteral("DesugarRuleTestTarget$InterfaceSubjectToDesugar")
private Class<?> interfaceSubjectToDesugarFromSimpleClassName;
@Inject
@DynamicClassLiteral(
"com.google.devtools.build.android.desugar.testing.junit.DesugarRuleTestTarget$InterfaceSubjectToDesugar")
private Class<?> interfaceSubjectToDesugarFromQualifiedClassName;
@Inject
@DynamicClassLiteral("DesugarRuleTestTarget$InterfaceSubjectToDesugar$$CC")
private Class<?> interfaceSubjectToDesugarCompanionClassRound1;
@Inject
@DynamicClassLiteral(value = "DesugarRuleTestTarget$InterfaceSubjectToDesugar$$CC", round = 2)
private Class<?> interfaceSubjectToDesugarCompanionClassRound2;
@Inject
@AsmNode(className = "DesugarRuleTestTarget")
private ClassNode desugarRuleTestTargetClassNode;
@Inject
@AsmNode(className = "DesugarRuleTestTarget$Alpha", memberName = "twoIntSum")
private MethodNode twoIntSum;
@Inject
@AsmNode(
className = "DesugarRuleTestTarget$Alpha",
memberName = "multiplier",
memberDescriptor = "J")
private FieldNode multiplier;
@Inject
@RuntimeMethodHandle(className = "DesugarRuleTestTarget$Alpha", memberName = "<init>")
private MethodHandle alphaConstructor;
@Inject
@RuntimeMethodHandle(
className = "DesugarRuleTestTarget$Alpha",
memberName = "linearLongTransform")
private MethodHandle linearLongTransform;
@Inject
@RuntimeMethodHandle(
className = "DesugarRuleTestTarget$Alpha",
memberName = "multiplier",
usage = MemberUseContext.FIELD_GETTER)
private MethodHandle alphaMultiplierGetter;
@Inject
@RuntimeMethodHandle(
className = "DesugarRuleTestTarget$Alpha",
memberName = "multiplier",
usage = MemberUseContext.FIELD_SETTER)
private MethodHandle alphaMultiplierSetter;
@Test
public void staticMethodsAreMovedFromOriginatingClass() {
assertThrows(
NoSuchMethodException.class,
() -> interfaceSubjectToDesugarRound1.getDeclaredMethod("staticMethod"));
}
@Test
public void staticMethodsAreMovedFromOriginatingClass_desugarTwice() {
assertThrows(
NoSuchMethodException.class,
() -> interfaceSubjectToDesugarRound2.getDeclaredMethod("staticMethod"));
}
@Test
public void staticMethodsAreMovedToCompanionClass() {
assertThat(
Arrays.stream(interfaceSubjectToDesugarCompanionClassRound1.getDeclaredMethods())
.map(Method::getName))
.contains("staticMethod$$STATIC$$");
}
@Test
public void innerClasses() {
assertThat(
desugarRuleTestTargetClassNode.innerClasses.stream().map(classNode -> classNode.name))
.contains(
"com/google/devtools/build/android/desugar/testing/junit/DesugarRuleTestTarget$InterfaceSubjectToDesugar");
}
@Test
public void idempotencyOperation(
@RuntimeJarEntry(
value = "DesugarRuleTestTarget$InterfaceSubjectToDesugar$$CC.class",
round = 1)
JarEntryRecord interfaceSubjectToDesugarJarEntryRound1,
@RuntimeJarEntry(
value = "DesugarRuleTestTarget$InterfaceSubjectToDesugar$$CC.class",
round = 2)
JarEntryRecord interfaceSubjectToDesugarJarEntryRound2) {
assertThat(interfaceSubjectToDesugarJarEntryRound1.jarEntry().getCrc())
.isEqualTo(interfaceSubjectToDesugarJarEntryRound2.jarEntry().getCrc());
}
@Test
public void classLoaders_sameInstanceInSameRound() {
assertThat(interfaceSubjectToDesugarRound1.getClassLoader())
.isSameInstanceAs(interfaceSubjectToDesugarCompanionClassRound1.getClassLoader());
assertThat(interfaceSubjectToDesugarRound2.getClassLoader())
.isSameInstanceAs(interfaceSubjectToDesugarCompanionClassRound2.getClassLoader());
}
@Test
public void classLiterals_requestedWithFullQualifiedClassName() {
assertThat(interfaceSubjectToDesugarFromQualifiedClassName)
.isSameInstanceAs(interfaceSubjectToDesugarFromSimpleClassName);
}
@Test
public void injectClassLiteralsFromParam(
@DynamicClassLiteral("DesugarRuleTestTarget$InterfaceSubjectToDesugar")
Class<?> interfaceSubjectToDesugarParam) {
assertThat(interfaceSubjectToDesugarParam).isSameInstanceAs(interfaceSubjectToDesugarRound1);
}
@Test
public void injectFieldNodes() {
assertThat(twoIntSum.desc).isEqualTo("(II)I");
}
@Test
public void injectMethodNodes() {
assertThat(multiplier.desc).isEqualTo("J");
}
@Test
@ParameterValueSource({"1", "2", "3"})
@ParameterValueSource({"100", "400", "500"})
public void invokeStaticMethodHandle(
@RuntimeMethodHandle(className = "DesugarRuleTestTarget$Alpha", memberName = "twoIntSum")
MethodHandle twoIntSum,
@FromParameterValueSource int x,
@FromParameterValueSource int y,
@FromParameterValueSource int expectedResult)
throws Throwable {
int result = (int) twoIntSum.invoke(x, y);
assertThat(result).isEqualTo(expectedResult);
}
@Test
public void invokeVirtualMethodHandle() throws Throwable {
long result = (long) linearLongTransform.invoke(alphaConstructor.invoke(1000, 2), 3L);
assertThat(result).isEqualTo(3002);
}
@Test
public void invokeFieldGetter() throws Throwable {
Object alpha = alphaConstructor.invoke(1000, 2);
long result = (long) alphaMultiplierGetter.invoke(alpha);
assertThat(result).isEqualTo(1000);
}
@Test
public void invokeFieldSetter() throws Throwable {
Object alpha = alphaConstructor.invoke(1000, 2);
alphaMultiplierSetter.invoke(alpha, 1111);
long result = (long) alphaMultiplierGetter.invoke(alpha);
assertThat(result).isEqualTo(1111);
}
@Test
public void invokeRuntimeCompiledTarget(
@RuntimeMethodHandle(className = "DesugarRuleTestSourceTarget", memberName = "twoSum")
MethodHandle twoSum)
throws Throwable {
int result = (int) twoSum.invokeExact(1, 2);
assertThat(result).isEqualTo(3);
}
}