| // Copyright (c) 2022, 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.jdk8272564; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assume.assumeTrue; |
| |
| import com.android.tools.r8.TestBase; |
| import com.android.tools.r8.TestParameters; |
| import com.android.tools.r8.TestParametersCollection; |
| import com.android.tools.r8.TestRuntime.CfVm; |
| import com.android.tools.r8.examples.jdk18.jdk8272564.Jdk8272564; |
| import com.android.tools.r8.utils.AndroidApiLevel; |
| import com.android.tools.r8.utils.codeinspector.CodeInspector; |
| import com.android.tools.r8.utils.codeinspector.InstructionSubject; |
| 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 Jdk8272564Test extends TestBase { |
| |
| @Parameters(name = "{0}") |
| public static TestParametersCollection data() { |
| // TODO(b/218293990): Right now the JDK 18 tests are built with -target 17, as our Gradle |
| // version does not know of -target 18. |
| return getTestParameters() |
| .withCfRuntimesStartingFromIncluding(CfVm.JDK17) |
| .withDexRuntimes() |
| .withAllApiLevelsAlsoForCf() |
| .build(); |
| } |
| |
| @Parameter(0) |
| public TestParameters parameters; |
| |
| // With the fix for JDK-8272564 there are no invokevirtual instructions. |
| private void assertJdk8272564FixedCode(CodeInspector inspector) { |
| assertTrue( |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("f") |
| .streamInstructions() |
| .noneMatch(InstructionSubject::isInvokeVirtual)); |
| assertTrue( |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("g") |
| .streamInstructions() |
| .noneMatch(InstructionSubject::isInvokeVirtual)); |
| } |
| |
| // Without the fix for JDK-8272564 there is one invokeinterface and 2 invokevirtual instructions. |
| private void assertJdk8272564NotFixedCode( |
| CodeInspector inspector, int invokeVirtualCount, int getClassCount) { |
| assertEquals( |
| 1, |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("f") |
| .streamInstructions() |
| .filter(InstructionSubject::isInvokeInterface) |
| .count()); |
| assertEquals( |
| 2, |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("f") |
| .streamInstructions() |
| .filter(InstructionSubject::isInvokeVirtual) |
| .count()); |
| assertEquals( |
| 2, |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("g") |
| .streamInstructions() |
| .filter(InstructionSubject::isInvokeInterface) |
| .count()); |
| assertEquals( |
| 2, |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("g") |
| .streamInstructions() |
| .filter(InstructionSubject::isInvokeInterface) |
| .count()); |
| assertEquals( |
| invokeVirtualCount, |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("g") |
| .streamInstructions() |
| .filter(InstructionSubject::isInvokeVirtual) |
| .count()); |
| assertEquals( |
| getClassCount, |
| inspector |
| .clazz(Jdk8272564.Main.typeName()) |
| .uniqueMethodWithName("g") |
| .streamInstructions() |
| .filter(InstructionSubject::isInvoke) |
| .filter(instruction -> instruction.getMethod().getName().toString().equals("getClass")) |
| .count()); |
| } |
| |
| private void assertJdk8272564NotFixedCode(CodeInspector inspector) { |
| assertJdk8272564NotFixedCode(inspector, 22, 3); |
| } |
| |
| private void assertJdk8272564NotFixedCodeR8(CodeInspector inspector) { |
| assertJdk8272564NotFixedCode(inspector, 19, 0); |
| } |
| |
| private boolean isDefaultCfParameters() { |
| return parameters.isCfRuntime() && parameters.getApiLevel().equals(AndroidApiLevel.B); |
| } |
| |
| @Test |
| // See https://bugs.openjdk.java.net/browse/JDK-8272564. |
| public void testJdk8272564Compiler() throws Exception { |
| assumeTrue(isDefaultCfParameters()); |
| // Ensure that the test is running with CF input from fixing JDK-8272564. |
| assertJdk8272564FixedCode(new CodeInspector(Jdk8272564.jar())); |
| } |
| |
| @Test |
| public void testJvm() throws Exception { |
| assumeTrue(isDefaultCfParameters()); |
| testForJvm() |
| .addRunClasspathFiles(Jdk8272564.jar()) |
| .run(parameters.getRuntime(), Jdk8272564.Main.typeName()) |
| .assertSuccess(); |
| } |
| |
| @Test |
| public void testD8() throws Exception { |
| testForDesugaring(parameters) |
| .addProgramFiles(Jdk8272564.jar()) |
| .run(parameters.getRuntime(), Jdk8272564.Main.typeName()) |
| .applyIf( |
| parameters.isDexRuntime() && parameters.getApiLevel().isLessThan(AndroidApiLevel.P), |
| b -> b.inspect(this::assertJdk8272564NotFixedCode), |
| b -> b.inspect(this::assertJdk8272564FixedCode)) |
| .assertSuccess(); |
| } |
| |
| @Test |
| public void testR8() throws Exception { |
| assumeTrue(parameters.isDexRuntime() || isDefaultCfParameters()); |
| // The R8 lens code rewriter rewrites to the code prior to fixing JDK-8272564. |
| testForR8(parameters.getBackend()) |
| .addProgramFiles(Jdk8272564.jar()) |
| .setMinApi(parameters.getApiLevel()) |
| .noTreeShaking() |
| .addKeepClassAndMembersRules(Jdk8272564.Main.typeName()) |
| .run(parameters.getRuntime(), Jdk8272564.Main.typeName()) |
| .inspect(this::assertJdk8272564NotFixedCodeR8) |
| .assertSuccess(); |
| } |
| } |