diff options
author | Søren Gjesse <sgjesse@google.com> | 2021-03-10 19:05:07 +0100 |
---|---|---|
committer | Søren Gjesse <sgjesse@google.com> | 2021-03-10 19:05:07 +0100 |
commit | 553a1d4f2f3dc84a9890e388e07c00dda3931aea (patch) | |
tree | 67540684affd615a8d18cecfbf6134629fc671dc | |
parent | 1f3ec31ee56758e62dce431d2405dacfd61558f2 (diff) | |
download | r8-553a1d4f2f3dc84a9890e388e07c00dda3931aea.tar.gz |
Add a reproduction of b/182381011
Bug: 182381011
Change-Id: I5ba6d4812db0e402466cb67df2ae43658d3bc3f8
-rw-r--r-- | src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java new file mode 100644 index 000000000..9984eb3b0 --- /dev/null +++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java @@ -0,0 +1,193 @@ +// Copyright (c) 2020, 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.desugaredlibrary; + +import static org.junit.Assert.assertEquals; + +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.shaking.ProguardKeepAttributes; +import com.android.tools.r8.utils.BooleanUtils; +import com.android.tools.r8.utils.StringUtils; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.junit.Assume; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class CustomMapHierarchyTest extends DesugaredLibraryTestBase { + + private final TestParameters parameters; + private final boolean shrinkDesugaredLibrary; + + @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}") + public static List<Object[]> data() { + return buildParameters( + getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(), + BooleanUtils.values()); + } + + public CustomMapHierarchyTest(TestParameters parameters, boolean shrinkDesugaredLibrary) { + this.parameters = parameters; + this.shrinkDesugaredLibrary = shrinkDesugaredLibrary; + } + + @Test + public void testWithoutLibraryDesugaring() throws Exception { + Assume.assumeTrue( + parameters.getRuntime().isCf() + || parameters + .getApiLevel() + .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport())); + testForRuntime(parameters) + .addInnerClasses(CustomMapHierarchyTest.class) + .run(parameters.getRuntime(), Main.class) + .assertSuccessWithOutput(EXPECTED); + } + + @Test + public void testD8() throws Exception { + Assume.assumeTrue(parameters.getRuntime().isDex()); + KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters); + testForD8() + .addInnerClasses(CustomMapHierarchyTest.class) + .setMinApi(parameters.getApiLevel()) + .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer) + .compile() + .addDesugaredCoreLibraryRunClassPath( + this::buildDesugaredLibrary, + parameters.getApiLevel(), + keepRuleConsumer.get(), + shrinkDesugaredLibrary) + .run(parameters.getRuntime(), Main.class) + // TODO(b/182381011): Should always be EXPECTED. + .assertSuccessWithOutput( + parameters + .getApiLevel() + .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport()) + ? EXPECTED + : NOT_EXPECTED); + } + + @Test + public void testD8Cf2Cf() throws Exception { + KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters); + + Path jar = + testForD8(Backend.CF) + .addInnerClasses(CustomMapHierarchyTest.class) + .setMinApi(parameters.getApiLevel()) + .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer) + .setIncludeClassesChecksum(true) + .setMinApi(parameters.getApiLevel()) + .allowStdoutMessages() + .compile() + .writeToZip(); + String desugaredLibraryKeepRules = ""; + if (shrinkDesugaredLibrary && keepRuleConsumer.get() != null) { + // Collection keep rules is only implemented in the DEX writer. + assertEquals(0, keepRuleConsumer.get().length()); + desugaredLibraryKeepRules = "-keep class * { *; }"; + } + if (parameters.getRuntime().isDex()) { + testForD8() + .addProgramFiles(jar) + .setMinApi(parameters.getApiLevel()) + .disableDesugaring() + .allowStdoutMessages() + .compile() + .addDesugaredCoreLibraryRunClassPath( + this::buildDesugaredLibrary, + parameters.getApiLevel(), + desugaredLibraryKeepRules, + shrinkDesugaredLibrary) + .run(parameters.getRuntime(), Main.class) + // TODO(b/182381011): Should always be EXPECTED. + .assertSuccessWithOutput( + parameters + .getApiLevel() + .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport()) + ? EXPECTED + : NOT_EXPECTED); + } else { + testForJvm() + .addProgramFiles(jar) + .addRunClasspathFiles(getDesugaredLibraryInCF(parameters, options -> {})) + .run(parameters.getRuntime(), Main.class) + // TODO(b/182381011): Should always be EXPECTED. + .assertSuccessWithOutput( + parameters + .getApiLevel() + .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport()) + ? EXPECTED + : NOT_EXPECTED); + } + } + + @Test + public void testR8() throws Exception { + Assume.assumeTrue(parameters.getRuntime().isDex()); + KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters); + testForR8(parameters.getBackend()) + .addInnerClasses(CustomMapHierarchyTest.class) + .addKeepMainRule(Main.class) + .addKeepAllClassesRuleWithAllowObfuscation() + .addKeepAttributes( + ProguardKeepAttributes.SIGNATURE, + ProguardKeepAttributes.INNER_CLASSES, + ProguardKeepAttributes.ENCLOSING_METHOD) + .setMinApi(parameters.getApiLevel()) + .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer) + // TODO(b/182381011): Should not happen. + .applyIf( + parameters + .getApiLevel() + .isLessThan(TestBase.apiLevelWithDefaultInterfaceMethodsSupport()), + b -> b.addDontWarn("java.util.Map$-CC")) + .compile() + .addDesugaredCoreLibraryRunClassPath( + this::buildDesugaredLibrary, + parameters.getApiLevel(), + keepRuleConsumer.get(), + shrinkDesugaredLibrary) + .run(parameters.getRuntime(), Main.class) + // TODO(b/182381011): Should always be EXPECTED. + .assertSuccessWithOutput( + parameters + .getApiLevel() + .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport()) + ? EXPECTED + : NOT_EXPECTED); + } + + final String EXPECTED = + StringUtils.lines("B::getOrDefault", "default 1", "B::getOrDefault", "default 2"); + final String NOT_EXPECTED = StringUtils.lines("B::getOrDefault", "default 1", "default 2"); + + public static class Main { + public static void main(String[] args) { + System.out.println(new B<String>().getOrDefault("Not found", "default 1")); + System.out.println( + ((Map<String, String>) new B<String>()).getOrDefault("Not found", "default 2")); + } + } + + abstract static class A<T> extends LinkedHashMap<T, T> {} + + // AbstractSequentialList implements List further up the hierarchy. + static class B<T> extends A<T> { + // Need at least one overridden default method for emulated dispatch. + @Override + public T getOrDefault(Object key, T defaultValue) { + System.out.println("B::getOrDefault"); + return super.getOrDefault(key, defaultValue); + } + } +} |