Merge commit '8bbb7f953bd996e6fbe91f2d306f2dca74de43fa' into dev-release
diff --git a/build.gradle b/build.gradle index 4428f58..693cdba 100644 --- a/build.gradle +++ b/build.gradle
@@ -334,6 +334,7 @@ "openjdk/jdk-11-test", "proguard/proguard5.2.1", "proguard/proguard6.0.1", + "proguard/proguard-7.0.0", "r8", "r8-releases/2.0.74", "r8mappings",
diff --git a/src/main/java/com/android/tools/r8/ExtractMarker.java b/src/main/java/com/android/tools/r8/ExtractMarker.java index 0b1fead..c8d6295 100644 --- a/src/main/java/com/android/tools/r8/ExtractMarker.java +++ b/src/main/java/com/android/tools/r8/ExtractMarker.java
@@ -49,6 +49,11 @@ return extractMarker(appBuilder.build()); } + public static Collection<Marker> extractMarkerFromJarFile(Path file) + throws IOException, ExecutionException { + return extractMarker(AndroidApp.builder().addProgramFile(file).build()); + } + public static int extractDexSize(Path file) throws IOException, ResourceException { AndroidApp.Builder appBuilder = AndroidApp.builder(); addDexResources(appBuilder, file);
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java index e116676..48f2f7a 100644 --- a/src/main/java/com/android/tools/r8/L8Command.java +++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.BiPredicate; import java.util.function.Consumer; /** Immutable command structure for an invocation of the {@link L8} library compiler. */ @@ -86,6 +87,8 @@ StringConsumer mainDexListConsumer, int minApiLevel, Reporter diagnosticsHandler, + boolean encodeChecksum, + BiPredicate<String, Long> dexClassChecksumFilter, DesugaredLibraryConfiguration libraryConfiguration, List<AssertionsConfiguration> assertionsConfiguration, List<Consumer<Inspector>> outputInspections, @@ -100,8 +103,8 @@ diagnosticsHandler, DesugarState.ON, false, - false, - (name, checksum) -> true, + encodeChecksum, + dexClassChecksumFilter, assertionsConfiguration, outputInspections, threadCount); @@ -296,6 +299,8 @@ libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix()) .setMinApiLevel(getMinApiLevel()) .setMode(getMode()) + .setIncludeClassesChecksum(getIncludeClassesChecksum()) + .setDexClassChecksumFilter(getDexClassChecksumFilter()) .setProgramConsumer(getProgramConsumer()); for (ClassFileResourceProvider libraryResourceProvider : inputs.getLibraryResourceProviders()) { @@ -316,6 +321,8 @@ libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix()) .setMinApiLevel(getMinApiLevel()) .setMode(getMode()) + .setIncludeClassesChecksum(getIncludeClassesChecksum()) + .setDexClassChecksumFilter(getDexClassChecksumFilter()) .setProgramConsumer(getProgramConsumer()); for (ClassFileResourceProvider libraryResourceProvider : inputs.getLibraryResourceProviders()) { @@ -332,6 +339,8 @@ getMainDexListConsumer(), getMinApiLevel(), getReporter(), + getIncludeClassesChecksum(), + getDexClassChecksumFilter(), libraryConfiguration, getAssertionsConfiguration(), getOutputInspections(),
diff --git a/src/main/java/com/android/tools/r8/dex/Marker.java b/src/main/java/com/android/tools/r8/dex/Marker.java index 1484f02..e15a4eb 100644 --- a/src/main/java/com/android/tools/r8/dex/Marker.java +++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -88,6 +88,9 @@ new StringDiagnostic( "Merging program compiled with multiple desugared libraries.")); } + if (identifier.equals(NO_LIBRARY_DESUGARING) && marker.tool == Tool.R8) { + continue; + } desugaredLibraryIdentifiers.add(identifier); } } @@ -131,6 +134,10 @@ return this; } + public boolean hasMinApi() { + return jsonObject.has(MIN_API); + } + public Long getMinApi() { return jsonObject.get(MIN_API).getAsLong(); } @@ -141,6 +148,10 @@ return this; } + public boolean hasDesugaredLibraryIdentifiers() { + return jsonObject.has(DESUGARED_LIBRARY_IDENTIFIERS); + } + public String[] getDesugaredLibraryIdentifiers() { if (jsonObject.has(DESUGARED_LIBRARY_IDENTIFIERS)) { JsonArray array = jsonObject.get(DESUGARED_LIBRARY_IDENTIFIERS).getAsJsonArray();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java index cfb48f2..be1bbfd 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -50,10 +50,10 @@ private final AppView<?> appView; private final Map<DexMethod, DexMethod> retargetLibraryMember = new IdentityHashMap<>(); - // Map virtualRewrites hold a methodName->method mapping for virtual methods which are - // rewritten while the holder is non final but no superclass implement the method. In this case - // d8 needs to force resolution of given methods to see if the invoke needs to be rewritten. - private final Map<DexString, List<DexMethod>> virtualRewrites = new IdentityHashMap<>(); + // Map nonFinalRewrite hold a methodName -> method mapping for methods which are rewritten while + // the holder is non final. In this case d8 needs to force resolution of given methods to see if + // the invoke needs to be rewritten. + private final Map<DexString, List<DexMethod>> nonFinalHolderRewrites = new IdentityHashMap<>(); // Non final virtual library methods requiring generation of emulated dispatch. private final Set<DexEncodedMethod> emulatedDispatchMethods = Sets.newIdentityHashSet(); @@ -107,7 +107,7 @@ InvokeMethod invoke = instruction.asInvokeMethod(); DexMethod retarget = getRetargetLibraryMember(invoke.getInvokedMethod()); if (retarget == null) { - if (!matchesVirtualRewrite(invoke.getInvokedMethod())) { + if (!matchesNonFinalHolderRewrite(invoke.getInvokedMethod())) { continue; } // We need to force resolution, even on d8, to know if the invoke has to be rewritten. @@ -128,7 +128,7 @@ // Due to emulated dispatch, we have to rewrite invoke-super differently or we end up in // infinite loops. We do direct resolution. This is a very uncommon case. - if (invoke.isInvokeSuper() && matchesVirtualRewrite(invoke.getInvokedMethod())) { + if (invoke.isInvokeSuper() && matchesNonFinalHolderRewrite(invoke.getInvokedMethod())) { DexEncodedMethod dexEncodedMethod = appView .appInfoForDesugaring() @@ -163,8 +163,8 @@ return retargetLibraryMember.get(method); } - private boolean matchesVirtualRewrite(DexMethod method) { - List<DexMethod> dexMethods = virtualRewrites.get(method.name); + private boolean matchesNonFinalHolderRewrite(DexMethod method) { + List<DexMethod> dexMethods = nonFinalHolderRewrites.get(method.name); if (dexMethods == null) { return false; } @@ -188,17 +188,19 @@ DexType newHolder = retargetCoreLibMember.get(methodName).get(inType); List<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass); for (DexEncodedMethod encodedMethod : found) { - if (!encodedMethod.isStatic()) { - virtualRewrites.putIfAbsent(encodedMethod.method.name, new ArrayList<>()); - virtualRewrites.get(encodedMethod.method.name).add(encodedMethod.method); - if (InterfaceMethodRewriter.isEmulatedInterfaceDispatch(appView, encodedMethod)) { - // In this case interface method rewriter takes care of it. - continue; - } else if (!encodedMethod.isFinal()) { - // Virtual rewrites require emulated dispatch for inheritance. - // The call is rewritten to the dispatch holder class instead. - handleEmulateDispatch(appView, encodedMethod); - newHolder = dispatchHolderTypeFor(encodedMethod); + if (!typeClass.isFinal()) { + nonFinalHolderRewrites.putIfAbsent(encodedMethod.method.name, new ArrayList<>()); + nonFinalHolderRewrites.get(encodedMethod.method.name).add(encodedMethod.method); + if (!encodedMethod.isStatic()) { + if (InterfaceMethodRewriter.isEmulatedInterfaceDispatch(appView, encodedMethod)) { + // In this case interface method rewriter takes care of it. + continue; + } else if (!encodedMethod.isFinal()) { + // Virtual rewrites require emulated dispatch for inheritance. + // The call is rewritten to the dispatch holder class instead. + handleEmulateDispatch(appView, encodedMethod); + newHolder = dispatchHolderTypeFor(encodedMethod); + } } } DexProto proto = encodedMethod.method.proto;
diff --git a/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java b/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java index e0f3cea..6b5829b 100644 --- a/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java +++ b/src/test/java/com/android/tools/r8/GenerateMainDexListTestBuilder.java
@@ -56,6 +56,16 @@ throw new Unimplemented("No support for run class path"); } + @Override + public GenerateMainDexListTestBuilder addClasspathClasses(Collection<Class<?>> classes) { + throw new Unimplemented("No support for class path"); + } + + @Override + public GenerateMainDexListTestBuilder addClasspathFiles(Collection<Path> files) { + throw new Unimplemented("No support for class path"); + } + public GenerateMainDexListRunResult run() throws CompilationFailedException { return new GenerateMainDexListRunResult(GenerateMainDexList.run(builder.build())); }
diff --git a/src/test/java/com/android/tools/r8/JvmTestBuilder.java b/src/test/java/com/android/tools/r8/JvmTestBuilder.java index 18571d0..97e244b 100644 --- a/src/test/java/com/android/tools/r8/JvmTestBuilder.java +++ b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
@@ -82,6 +82,16 @@ } @Override + public JvmTestBuilder addClasspathClasses(Collection<Class<?>> classes) { + return addClasspath(writeClassesToJar(classes)); + } + + @Override + public JvmTestBuilder addClasspathFiles(Collection<Path> files) { + return addClasspath(files); + } + + @Override public JvmTestBuilder addRunClasspathFiles(Collection<Path> files) { return addClasspath(files); }
diff --git a/src/test/java/com/android/tools/r8/MarkerMatcher.java b/src/test/java/com/android/tools/r8/MarkerMatcher.java index 90aec54..13065b7 100644 --- a/src/test/java/com/android/tools/r8/MarkerMatcher.java +++ b/src/test/java/com/android/tools/r8/MarkerMatcher.java
@@ -117,6 +117,20 @@ }; } + public static Matcher<Marker> markerHasMinApi() { + return new MarkerMatcher() { + @Override + protected boolean eval(Marker marker) { + return marker.hasMinApi(); + } + + @Override + protected void explain(Description description) { + description.appendText(Marker.MIN_API + " found"); + } + }; + } + public static Matcher<Marker> markerHasChecksums(boolean value) { return new MarkerMatcher() { @Override @@ -165,6 +179,25 @@ }; } + public static Matcher<Marker> markerHasDesugaredLibraryIdentifier() { + return markerHasDesugaredLibraryIdentifier(true); + } + + public static Matcher<Marker> markerHasDesugaredLibraryIdentifier(boolean value) { + return new MarkerMatcher() { + @Override + protected boolean eval(Marker marker) { + return marker.hasDesugaredLibraryIdentifiers() == value; + } + + @Override + protected void explain(Description description) { + description.appendText( + Marker.DESUGARED_LIBRARY_IDENTIFIERS + (value ? " found" : " not found")); + } + }; + } + @Override protected boolean matchesSafely(Marker marker) { return eval(marker);
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java index 78eaabf..b764451 100644 --- a/src/test/java/com/android/tools/r8/TestBase.java +++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -193,17 +193,22 @@ } public TestBuilder<? extends TestRunResult<?>, ?> testForRuntime( - TestRuntime runtime, AndroidApiLevel apiLevel) { + TestRuntime runtime, Consumer<D8TestBuilder> d8TestBuilderConsumer) { if (runtime.isCf()) { return testForJvm(); } else { assert runtime.isDex(); D8TestBuilder d8TestBuilder = testForD8(); - d8TestBuilder.setMinApi(apiLevel); + d8TestBuilderConsumer.accept(d8TestBuilder); return d8TestBuilder; } } + public TestBuilder<? extends TestRunResult<?>, ?> testForRuntime( + TestRuntime runtime, AndroidApiLevel apiLevel) { + return testForRuntime(runtime, d8TestBuilder -> d8TestBuilder.setMinApi(apiLevel)); + } + public TestBuilder<? extends TestRunResult<?>, ?> testForRuntime(TestParameters parameters) { return testForRuntime(parameters.getRuntime(), parameters.getApiLevel()); }
diff --git a/src/test/java/com/android/tools/r8/TestBuilder.java b/src/test/java/com/android/tools/r8/TestBuilder.java index 21ab2b1..d56f4d9 100644 --- a/src/test/java/com/android/tools/r8/TestBuilder.java +++ b/src/test/java/com/android/tools/r8/TestBuilder.java
@@ -131,6 +131,18 @@ return addLibraryFiles(Arrays.asList(files)); } + public T addClasspathClasses(Class<?>... classes) { + return addClasspathClasses(Arrays.asList(classes)); + } + + public abstract T addClasspathClasses(Collection<Class<?>> classes); + + public T addClasspathFiles(Path... files) { + return addClasspathFiles(Arrays.asList(files)); + } + + public abstract T addClasspathFiles(Collection<Path> files); + public final T addTestingAnnotationsAsProgramClasses() { return addProgramClasses(getTestingAnnotations()); }
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java index ce6c9fb..9d6b1c8 100644 --- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java +++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -23,7 +23,6 @@ import java.io.PrintStream; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.ExecutionException; @@ -339,18 +338,6 @@ return super.addLibraryProvider(provider); } - public T addClasspathClasses(Class<?>... classes) { - return addClasspathClasses(Arrays.asList(classes)); - } - - public abstract T addClasspathClasses(Collection<Class<?>> classes); - - public T addClasspathFiles(Path... files) { - return addClasspathFiles(Arrays.asList(files)); - } - - public abstract T addClasspathFiles(Collection<Path> files); - public T noDesugaring() { builder.setDisableDesugaring(true); return self();
diff --git a/src/test/java/com/android/tools/r8/compatproguard/ifrules/ConditionalOnInlinedFieldTest.java b/src/test/java/com/android/tools/r8/compatproguard/ifrules/ConditionalOnInlinedFieldTest.java new file mode 100644 index 0000000..efc344e --- /dev/null +++ b/src/test/java/com/android/tools/r8/compatproguard/ifrules/ConditionalOnInlinedFieldTest.java
@@ -0,0 +1,122 @@ +// 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.compatproguard.ifrules; + +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestRunResult; +import com.android.tools.r8.TestShrinkerBuilder; +import com.android.tools.r8.shaking.methods.MethodsTestBase.Shrinker; +import com.android.tools.r8.utils.BooleanUtils; +import com.android.tools.r8.utils.StringUtils; +import java.util.List; +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 ConditionalOnInlinedFieldTest extends TestBase { + + static class A { + + int field = 42; + + void method(String name, int field) throws Exception { + if (field == 42) { + Class<?> clazz = Class.forName(name); + Object object = clazz.getDeclaredConstructor().newInstance(); + clazz.getDeclaredMethod("method").invoke(object); + } + } + } + + static class B { + void method() { + System.out.println("B::method"); + } + } + + static class MainWithFieldReference { + + public static void main(String[] args) throws Exception { + A a = new A(); + a.method(args[0], a.field); + } + } + + static class MainWithoutFieldReference { + + public static void main(String[] args) throws Exception { + A a = new A(); + a.method(args[0], 42); + } + } + + private static String EXPECTED = StringUtils.lines("B::method"); + + @Parameters(name = "{0}, {1}, ref:{2}") + public static List<Object[]> data() { + return buildParameters( + Shrinker.values(), getTestParameters().withCfRuntimes().build(), BooleanUtils.values()); + } + + private final Shrinker shrinker; + private final TestParameters parameters; + private final boolean withFieldReference; + + public ConditionalOnInlinedFieldTest( + Shrinker shrinker, TestParameters parameters, boolean withFieldReference) { + this.shrinker = shrinker; + this.parameters = parameters; + this.withFieldReference = withFieldReference; + } + + private Class<?> getMain() { + return withFieldReference ? MainWithFieldReference.class : MainWithoutFieldReference.class; + } + + @Test + public void testReference() throws Exception { + testForJvm() + .addProgramClasses(getMain(), A.class, B.class) + .run(parameters.getRuntime(), getMain(), B.class.getTypeName()) + .assertSuccessWithOutput(EXPECTED); + } + + private TestShrinkerBuilder<?, ?, ?, ?, ?> buildShrinker() throws Exception { + TestShrinkerBuilder<?, ?, ?, ?, ?> builder; + if (shrinker == Shrinker.Proguard) { + builder = + testForProguard() + .addKeepRules("-dontwarn " + ConditionalOnInlinedFieldTest.class.getTypeName()); + } else if (shrinker == Shrinker.R8Compat) { + builder = testForR8Compat(parameters.getBackend()); + } else { + builder = testForR8(parameters.getBackend()); + } + return builder + .addProgramClasses(getMain(), A.class, B.class) + .addKeepMainRule(getMain()) + .addKeepRules( + "-if class " + + A.class.getTypeName() + + " { int field; }" + + " -keep class " + + B.class.getTypeName() + + " { void <init>(); void method(); }"); + } + + @Test + public void testConditionalOnField() throws Exception { + TestRunResult<?> result = + buildShrinker().compile().run(parameters.getRuntime(), getMain(), B.class.getTypeName()); + if (!withFieldReference && shrinker != Shrinker.Proguard) { + // Without the reference we expect an error. For some reason PG keeps in any case. + result.assertFailureWithErrorThatThrows(ClassNotFoundException.class); + } else { + result.assertSuccessWithOutput(EXPECTED); + } + } +}
diff --git a/src/test/java/com/android/tools/r8/compatproguard/ifrules/ConditionalOnInlinedTest.java b/src/test/java/com/android/tools/r8/compatproguard/ifrules/ConditionalOnInlinedTest.java new file mode 100644 index 0000000..faa9eda --- /dev/null +++ b/src/test/java/com/android/tools/r8/compatproguard/ifrules/ConditionalOnInlinedTest.java
@@ -0,0 +1,124 @@ +// 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.compatproguard.ifrules; + +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestRunResult; +import com.android.tools.r8.TestShrinkerBuilder; +import com.android.tools.r8.shaking.methods.MethodsTestBase.Shrinker; +import com.android.tools.r8.utils.StringUtils; +import com.google.common.collect.ImmutableList; +import java.util.Collection; +import java.util.List; +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 ConditionalOnInlinedTest extends TestBase { + + static class A { + void method(String name) throws Exception { + Class<?> clazz = Class.forName(name); + Object object = clazz.getDeclaredConstructor().newInstance(); + clazz.getDeclaredMethod("method").invoke(object); + } + } + + static class B { + void method() { + System.out.println("B::method"); + } + } + + static class Main { + public static void main(String[] args) throws Exception { + new A().method(args[0]); + } + } + + private static Class<?> MAIN_CLASS = Main.class; + private static Collection<Class<?>> CLASSES = ImmutableList.of(MAIN_CLASS, A.class, B.class); + + private static String EXPECTED = StringUtils.lines("B::method"); + + @Parameters(name = "{0}, {1}") + public static List<Object[]> data() { + return buildParameters(Shrinker.values(), getTestParameters().withCfRuntimes().build()); + } + + private final Shrinker shrinker; + private final TestParameters parameters; + + public ConditionalOnInlinedTest(Shrinker shrinker, TestParameters parameters) { + this.shrinker = shrinker; + this.parameters = parameters; + } + + @Test + public void testReference() throws Exception { + testForJvm() + .addProgramClasses(CLASSES) + .run(parameters.getRuntime(), MAIN_CLASS, B.class.getTypeName()) + .assertSuccessWithOutput(EXPECTED); + } + + private TestShrinkerBuilder<?, ?, ?, ?, ?> buildShrinker() throws Exception { + TestShrinkerBuilder<?, ?, ?, ?, ?> builder; + if (shrinker == Shrinker.Proguard) { + builder = + testForProguard() + .addKeepRules("-dontwarn " + ConditionalOnInlinedTest.class.getTypeName()); + } else if (shrinker == Shrinker.R8Compat) { + builder = testForR8Compat(parameters.getBackend()); + } else { + builder = testForR8(parameters.getBackend()); + } + return builder.addProgramClasses(CLASSES).addKeepMainRule(MAIN_CLASS); + } + + @Test + public void testConditionalOnClass() throws Exception { + TestRunResult<?> result = + buildShrinker() + .addKeepRules( + "-if class " + + A.class.getTypeName() + + " -keep class " + + B.class.getTypeName() + + " { void <init>(); void method(); }") + .compile() + .run(parameters.getRuntime(), MAIN_CLASS, B.class.getTypeName()); + if (shrinker != Shrinker.Proguard) { + // TODO(b/160136641): The conditional rule fails to apply after class A is inlined/removed. + result.assertFailureWithErrorThatThrows(ClassNotFoundException.class); + } else { + result.assertSuccessWithOutput(EXPECTED); + } + } + + @Test + public void testConditionalOnClassAndMethod() throws Exception { + TestRunResult<?> result = + buildShrinker() + .addKeepRules( + "-if class " + + A.class.getTypeName() + + " { void method(java.lang.String); }" + + " -keep class " + + B.class.getTypeName() + + " { void <init>(); void method(); }") + .compile() + .run(parameters.getRuntime(), MAIN_CLASS, B.class.getTypeName()); + if (shrinker == Shrinker.Proguard) { + // In this case PG appears to not actually keep the consequent, but it does remain renamed + // in the output. + result.assertFailureWithErrorThatThrows(ClassNotFoundException.class); + } else { + result.assertSuccessWithOutput(EXPECTED); + } + } +}
diff --git a/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java b/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java index 6a1e059..aab82f0 100644 --- a/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java +++ b/src/test/java/com/android/tools/r8/compatproguard/reflection/ReflectionTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.compatproguard.reflection; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -468,15 +468,17 @@ readClasses(A.class, mainClass), keepMainProguardConfiguration(mainClass), backend); CodeInspector inspector = new CodeInspector(output); - assertThat(inspector.clazz(A.class).method("void", "method0", ImmutableList.of()), isRenamed()); + assertThat( + inspector.clazz(A.class).method("void", "method0", ImmutableList.of()), + isPresentAndRenamed()); assertThat( inspector.clazz(A.class).method("void", "method1", ImmutableList.of("java.lang.String")), - isRenamed()); + isPresentAndRenamed()); assertThat( inspector .clazz(A.class) .method("void", "method2", ImmutableList.of("java.lang.String", "java.lang.String")), - isRenamed()); + isPresentAndRenamed()); assertEquals(runOnJava(mainClass), runOnVM(output, mainClass, backend)); } @@ -495,7 +497,9 @@ AndroidApp output = ToolHelper.runR8(builder.build()); CodeInspector inspector = new CodeInspector(output); - assertThat(inspector.clazz(A.class).method("void", "method0", ImmutableList.of()), isRenamed()); + assertThat( + inspector.clazz(A.class).method("void", "method0", ImmutableList.of()), + isPresentAndRenamed()); // The reference run on the Java VM will succeed, whereas the run on the R8 output will fail // as in this test we fail to recognize the reflective call. To compare the output of the @@ -535,7 +539,7 @@ .forAllMethods( m -> { if (!m.isInstanceInitializer()) { - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); } }); @@ -556,7 +560,7 @@ .forAllMethods( m -> { if (!m.isInstanceInitializer()) { - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); } });
diff --git a/src/test/java/com/android/tools/r8/desugar/DefaultInterfaceWithIdentifierNameString.java b/src/test/java/com/android/tools/r8/desugar/DefaultInterfaceWithIdentifierNameString.java index 211050e..9eb054c 100644 --- a/src/test/java/com/android/tools/r8/desugar/DefaultInterfaceWithIdentifierNameString.java +++ b/src/test/java/com/android/tools/r8/desugar/DefaultInterfaceWithIdentifierNameString.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.desugar; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -54,9 +54,9 @@ private void inspect(CodeInspector inspector) { ClassSubject classSubject = inspector.clazz(A.class); - assertThat(classSubject, isRenamed()); + assertThat(classSubject, isPresentAndRenamed()); ClassSubject companionClassSubject = inspector.companionClassFor(I.class); - assertThat(companionClassSubject, isRenamed()); + assertThat(companionClassSubject, isPresentAndRenamed()); companionClassSubject .allMethods() .forEach(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryChecksumsTest.java similarity index 70% rename from src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java rename to src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryChecksumsTest.java index 8280f92..6aff20f 100644 --- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java +++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryChecksumsTest.java
@@ -3,10 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.desugar.desugaredlibrary; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; - import com.android.tools.r8.CompilationMode; import com.android.tools.r8.L8; import com.android.tools.r8.L8Command; @@ -16,7 +12,6 @@ import com.android.tools.r8.TestParameters; import com.android.tools.r8.TestParametersCollection; import com.android.tools.r8.ToolHelper; -import com.android.tools.r8.errors.CompilationError; import com.android.tools.r8.utils.AndroidApiLevel; import com.android.tools.r8.utils.codeinspector.CodeInspector; import com.android.tools.r8.utils.codeinspector.FoundClassSubject; @@ -26,14 +21,14 @@ import org.junit.runners.Parameterized; @RunWith(Parameterized.class) -public class DesugaredLibaryChecksumsTest extends TestBase { +public class DesugaredLibraryChecksumsTest extends TestBase { @Parameterized.Parameters(name = "{0}") public static TestParametersCollection data() { return getTestParameters().withNoneRuntime().build(); } - public DesugaredLibaryChecksumsTest(TestParameters parameters) { + public DesugaredLibraryChecksumsTest(TestParameters parameters) { parameters.assertNoneRuntime(); } @@ -52,16 +47,9 @@ .setMinApiLevel(AndroidApiLevel.B.getLevel()) .setOutput(out, OutputMode.DexIndexed) .build()); - - try { - CodeInspector inspector = new CodeInspector(out); - for (FoundClassSubject clazz : inspector.allClasses()) { - assertTrue(clazz.getDexProgramClass().getChecksum() > 0); - } - } catch (CompilationError e) { - // TODO(b/158746302): Desugared library should support checksums. - // also, the failure should have occured in the L8.run above! - assertThat(e.getMessage(), containsString("has no checksum")); + CodeInspector inspector = new CodeInspector(out); + for (FoundClassSubject clazz : inspector.allClasses()) { + clazz.getDexProgramClass().getChecksum(); } } }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java index 03052cc..f485a25 100644 --- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java +++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
@@ -4,22 +4,35 @@ package com.android.tools.r8.desugar.desugaredlibrary; +import static com.android.tools.r8.MarkerMatcher.assertMarkersMatch; +import static com.android.tools.r8.MarkerMatcher.markerCompilationMode; +import static com.android.tools.r8.MarkerMatcher.markerHasDesugaredLibraryIdentifier; +import static com.android.tools.r8.MarkerMatcher.markerHasMinApi; +import static com.android.tools.r8.MarkerMatcher.markerTool; +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.android.tools.r8.CompilationFailedException; +import com.android.tools.r8.CompilationMode; import com.android.tools.r8.D8TestCompileResult; import com.android.tools.r8.Diagnostic; +import com.android.tools.r8.ExtractMarker; import com.android.tools.r8.TestDiagnosticMessages; import com.android.tools.r8.TestParameters; import com.android.tools.r8.TestParametersCollection; import com.android.tools.r8.ToolHelper; import com.android.tools.r8.desugar.desugaredlibrary.jdktests.Jdk11DesugaredLibraryTestBase; +import com.android.tools.r8.dex.Marker; +import com.android.tools.r8.dex.Marker.Tool; import com.android.tools.r8.utils.AndroidApiLevel; +import com.google.common.collect.ImmutableList; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import org.hamcrest.Matcher; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -69,6 +82,47 @@ .assertSuccessWithOutputLines(JAVA_RESULT); } + @Test + public void testMergeDesugaredWithShrunkenLib() throws Exception { + // Compile a library with R8 to CF. + Path shrunkenLib = + testForR8(Backend.CF) + .addProgramClasses(Part2.class) + .addKeepClassRules(Part2.class) + .compile() + .writeToZip(); + + // R8 class file output marker has no library desugaring identifier. + Matcher<Marker> libraryMatcher = + allOf( + markerTool(Tool.R8), + markerCompilationMode(CompilationMode.RELEASE), + not(markerHasMinApi()), + not(markerHasDesugaredLibraryIdentifier())); + assertMarkersMatch( + ExtractMarker.extractMarkerFromJarFile(shrunkenLib), ImmutableList.of(libraryMatcher)); + + // Build an app with the R8 compiled library. + Path app = + testForD8() + .addProgramFiles(buildPart1DesugaredLibrary(), shrunkenLib) + .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P)) + .setMinApi(parameters.getApiLevel()) + .enableCoreLibraryDesugaring(parameters.getApiLevel()) + .compile() + .writeToZip(); + + // The app has both the R8 marker from the library compilation and the D8 marker from dexing. + Matcher<Marker> d8Matcher = + allOf( + markerTool(Tool.D8), + markerHasMinApi(), + markerHasDesugaredLibraryIdentifier( + parameters.getApiLevel().isLessThan(AndroidApiLevel.O))); + assertMarkersMatch( + ExtractMarker.extractMarkerFromDexFile(app), ImmutableList.of(libraryMatcher, d8Matcher)); + } + private void assertError(TestDiagnosticMessages m) { List<Diagnostic> errors = m.getErrors(); if (expectError()) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java index 32bbe65..c2d88b0 100644 --- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java +++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
@@ -123,19 +123,12 @@ System.out.println(myAtomicInteger.updateAndGet(x -> x + 100)); System.out.println("145"); - try { - MyDateNoOverride.from(myCal.toInstant()); - System.out.println("b/159441805 fixed"); - } catch (NoSuchMethodError e) { - // TODO(b/159441805): Should not throw. - } - - try { - MyDateOverride.from(myCal.toInstant()); - System.out.println("b/159441805 fixed"); - } catch (NoSuchMethodError e) { - // TODO(b/159441805): Should not throw. - } + Date date1 = MyDateNoOverride.from(myCal.toInstant()); + System.out.println(date1.toInstant()); + System.out.println("1990-03-22T00:00:00Z"); + Date date2 = MyDateOverride.from(myCal.toInstant()); + System.out.println(date2.toInstant()); + System.out.println("1990-03-22T00:00:00Z"); System.out.println(MyDateDoubleOverride.from(myCal.toInstant()).toInstant()); System.out.println("1970-01-02T10:17:36.788Z");
diff --git a/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java b/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java index b91a645..351a74e 100644 --- a/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java +++ b/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java
@@ -5,7 +5,6 @@ import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; import com.android.tools.r8.OutputMode; import com.android.tools.r8.TestBase; @@ -83,7 +82,7 @@ private void checkIncludesChecksum(CodeInspector inspector, Class<?> clazz) { ClassSubject classSubject = inspector.clazz(getTransformedName(clazz)); assertThat(classSubject, isPresent()); - assertTrue(classSubject.getDexProgramClass().asProgramClass().getChecksum() > 0); + classSubject.getDexProgramClass().getChecksum(); } static class TaestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningIntoVisibilityBridgeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningIntoVisibilityBridgeTest.java index 1c9148a..ec3c011 100644 --- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningIntoVisibilityBridgeTest.java +++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningIntoVisibilityBridgeTest.java
@@ -6,7 +6,7 @@ import static com.android.tools.r8.ir.optimize.inliner.testclasses.InliningIntoVisibilityBridgeTestClasses.getClassA; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -74,8 +74,7 @@ assertThat(classSubject, isPresent()); MethodSubject methodSubject = classSubject.uniqueMethodWithName("method"); - assertThat(methodSubject, isPresent()); - assertThat(methodSubject, isRenamed()); + assertThat(methodSubject, isPresentAndRenamed()); assertEquals(neverInline, methodSubject.isBridge()); assertEquals(neverInline, methodSubject.isSynthetic()); }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnnotationTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnnotationTest.java index 11c47de..0b65d77 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnnotationTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnnotationTest.java
@@ -5,9 +5,9 @@ package com.android.tools.r8.kotlin.metadata; import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; -import static com.android.tools.r8.utils.codeinspector.Matchers.isNotRenamed; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -150,12 +150,11 @@ private void inspect(CodeInspector inspector) { // Assert that foo is renamed. ClassSubject foo = inspector.clazz(PKG_LIB + ".Foo"); - assertThat(foo, isRenamed()); + assertThat(foo, isPresentAndRenamed()); assertEquals(FOO_FINAL_NAME, foo.getFinalName()); // Assert that bar exists and is not renamed. ClassSubject bar = inspector.clazz(PKG_LIB + ".Bar"); - assertThat(bar, isPresent()); - assertThat(bar, isNotRenamed()); + assertThat(bar, isPresentAndNotRenamed()); // Check that the annotation type on the type alias has been renamed inspectTypeAliasAnnotation(inspector, foo, bar); }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnonymousTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnonymousTest.java index f4ee57a..14cbe0b 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnonymousTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAnonymousTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.kotlin.metadata; import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import com.android.tools.r8.TestParameters; @@ -108,6 +108,6 @@ System.out.println( KotlinMetadataWriter.kotlinMetadataToString("", clazz.getKotlinClassMetadata())); ClassSubject anonymousClass = inspector.clazz(PKG + ".anonymous_lib.Test$internalProp$1"); - assertThat(anonymousClass, isRenamed()); + assertThat(anonymousClass, isPresentAndRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteFlexibleUpperBoundTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteFlexibleUpperBoundTest.java index 90b74f9..d5b9fd0 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteFlexibleUpperBoundTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteFlexibleUpperBoundTest.java
@@ -6,8 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -120,11 +120,10 @@ // We are checking that A is renamed, and that the flexible upper bound information is // reflecting that. ClassSubject a = inspector.clazz(PKG_LIB + ".A"); - assertThat(a, isRenamed()); + assertThat(a, isPresentAndRenamed()); ClassSubject flexibleUpperBound = inspector.clazz(PKG_LIB + ".FlexibleUpperBound"); - assertThat(flexibleUpperBound, isPresent()); - assertThat(flexibleUpperBound, not(isRenamed())); + assertThat(flexibleUpperBound, isPresentAndNotRenamed()); List<KmPropertySubject> properties = flexibleUpperBound.getKmClass().getProperties(); assertEquals(1, properties.size());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInClasspathTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInClasspathTypeTest.java index 4aa0a2c..2103f0d 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInClasspathTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInClasspathTypeTest.java
@@ -6,8 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -129,11 +129,10 @@ String extraClassName = PKG + ".classpath_lib_ext.Extra"; ClassSubject impl = inspector.clazz(implClassName); - assertThat(impl, isRenamed()); + assertThat(impl, isPresentAndRenamed()); ClassSubject implKt = inspector.clazz(implKtClassName); - assertThat(implKt, isPresent()); - assertThat(implKt, not(isRenamed())); + assertThat(implKt, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = implKt.getKmPackage(); assertThat(kmPackage, isPresent()); @@ -142,8 +141,7 @@ assertThat(kmFunction, isExtensionFunction()); ClassSubject extra = inspector.clazz(extraClassName); - assertThat(extra, isPresent()); - assertThat(extra, not(isRenamed())); + assertThat(extra, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = extra.getKmClass(); assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java index 38a6815..4c49518 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
@@ -5,7 +5,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -170,15 +171,13 @@ ClassSubject sup = inspector.clazz(superClassName); if (keptAll) { - assertThat(sup, isPresent()); - assertThat(sup, not(isRenamed())); + assertThat(sup, isPresentAndNotRenamed()); } else { - assertThat(sup, isRenamed()); + assertThat(sup, isPresentAndRenamed()); } ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent()); @@ -192,21 +191,18 @@ // The backing field for the property in the companion, with @JvmField FieldSubject elt2 = impl.uniqueFieldWithName("elt2"); - assertThat(elt2, isPresent()); - assertThat(elt2, not(isRenamed())); + assertThat(elt2, isPresentAndNotRenamed()); FieldSubject companionObject = impl.uniqueFieldWithName("Companion"); - assertThat(companionObject, isPresent()); - assertThat(companionObject, not(isRenamed())); + assertThat(companionObject, isPresentAndNotRenamed()); assertEquals(companionObject.getFinalName(), kmClass.getCompanionObject()); // Bridge for the property in the companion that needs a backing field. MethodSubject elt1Bridge = impl.uniqueMethodWithName("access$getElt1$cp"); if (keptAll) { - assertThat(elt1Bridge, isPresent()); - assertThat(elt1Bridge, not(isRenamed())); + assertThat(elt1Bridge, isPresentAndNotRenamed()); } else { - assertThat(elt1Bridge, isRenamed()); + assertThat(elt1Bridge, isPresentAndRenamed()); } // With @JvmField, no bridge is added. @@ -218,8 +214,7 @@ assertThat(fooBridge, not(isPresent())); ClassSubject companion = inspector.clazz(companionClassName); - assertThat(companion, isPresent()); - assertThat(companion, not(isRenamed())); + assertThat(companion, isPresentAndNotRenamed()); List<String> nestedClassDescriptors = kmClass.getNestedClassDescriptors(); assertEquals(1, nestedClassDescriptors.size()); @@ -236,19 +231,16 @@ assertThat(kmProperty, isPresent()); MethodSubject elt1Getter = companion.uniqueMethodWithName("getElt1"); - assertThat(elt1Getter, isPresent()); - assertThat(elt1Getter, not(isRenamed())); + assertThat(elt1Getter, isPresentAndNotRenamed()); // Note that there is no getter for property with @JvmField. MethodSubject elt2Getter = companion.uniqueMethodWithName("getElt2"); assertThat(elt2Getter, not(isPresent())); MethodSubject fooGetter = companion.uniqueMethodWithName("getFoo"); - assertThat(fooGetter, isPresent()); - assertThat(fooGetter, not(isRenamed())); + assertThat(fooGetter, isPresentAndNotRenamed()); MethodSubject barSetter = companion.uniqueMethodWithName("setBar"); - assertThat(barSetter, isPresent()); - assertThat(barSetter, not(isRenamed())); + assertThat(barSetter, isPresentAndNotRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionFunctionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionFunctionTest.java index 41d1f09..4f8b4a4 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionFunctionTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionFunctionTest.java
@@ -6,7 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -127,8 +128,7 @@ assertThat(inspector.clazz(superClassName), not(isPresent())); ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent()); @@ -180,12 +180,10 @@ String bClassName = PKG + ".extension_function_lib.B"; ClassSubject sup = inspector.clazz(superClassName); - assertThat(sup, isPresent()); - assertThat(sup, isRenamed()); + assertThat(sup, isPresentAndRenamed()); ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent()); @@ -206,8 +204,7 @@ assertThat(impl, isPresent()); ClassSubject bKt = inspector.clazz(bKtClassName); - assertThat(bKt, isPresent()); - assertThat(bKt, not(isRenamed())); + assertThat(bKt, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = bKt.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionPropertyTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionPropertyTest.java index c627171..9e81bf2 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionPropertyTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInExtensionPropertyTest.java
@@ -7,7 +7,8 @@ import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionProperty; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNotNull; @@ -124,8 +125,7 @@ assertThat(inspector.clazz(superClassName), not(isPresent())); ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent()); @@ -137,8 +137,7 @@ assertThat(kmFunction, not(isExtensionFunction())); ClassSubject bKt = inspector.clazz(bKtClassName); - assertThat(bKt, isPresent()); - assertThat(bKt, not(isRenamed())); + assertThat(bKt, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = bKt.getKmPackage(); assertThat(kmPackage, isPresent()); @@ -187,11 +186,10 @@ String bKtClassName = PKG + ".extension_property_lib.BKt"; ClassSubject sup = inspector.clazz(superClassName); - assertThat(sup, isRenamed()); + assertThat(sup, isPresentAndRenamed()); ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent()); @@ -202,8 +200,7 @@ supertype -> supertype.getFinalDescriptor().equals(sup.getFinalDescriptor()))); ClassSubject bKt = inspector.clazz(bKtClassName); - assertThat(bKt, isPresent()); - assertThat(bKt, not(isRenamed())); + assertThat(bKt, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = bKt.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionTest.java index 7cfa4a7..dcb6dbe 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionTest.java
@@ -6,7 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -122,8 +123,7 @@ assertThat(inspector.clazz(superClassName), not(isPresent())); ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); @@ -133,8 +133,7 @@ supertype -> supertype.getFinalDescriptor().contains("Super"))); ClassSubject bKt = inspector.clazz(bKtClassName); - assertThat(bKt, isPresent()); - assertThat(bKt, not(isRenamed())); + assertThat(bKt, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = bKt.getKmPackage(); @@ -183,10 +182,10 @@ String bKtClassName = PKG + ".function_lib.BKt"; ClassSubject sup = inspector.clazz(superClassName); - assertThat(sup, isRenamed()); + assertThat(sup, isPresentAndRenamed()); MethodSubject foo = sup.uniqueMethodWithName("foo"); - assertThat(foo, isRenamed()); + assertThat(foo, isPresentAndRenamed()); KmClassSubject kmClass = sup.getKmClass(); assertThat(kmClass, isPresent()); @@ -198,8 +197,7 @@ assertEquals(foo.getJvmMethodSignatureAsString(), kmFunction.signature().asString()); ClassSubject impl = inspector.clazz(bClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. kmClass = impl.getKmClass(); @@ -211,8 +209,7 @@ supertype -> supertype.getFinalDescriptor().equals(sup.getFinalDescriptor()))); ClassSubject bKt = inspector.clazz(bKtClassName); - assertThat(bKt, isPresent()); - assertThat(bKt, not(isRenamed())); + assertThat(bKt, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = bKt.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java index 79ad6e5..4cd9b6a 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
@@ -6,8 +6,7 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -120,16 +119,13 @@ String libClassName = PKG + ".default_value_lib.LibKt"; ClassSubject libKt = inspector.clazz(libClassName); - assertThat(libKt, isPresent()); - assertThat(libKt, not(isRenamed())); + assertThat(libKt, isPresentAndNotRenamed()); MethodSubject methodSubject = libKt.uniqueMethodWithName("applyMap"); - assertThat(methodSubject, isPresent()); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); methodSubject = libKt.uniqueMethodWithName("applyMap$default"); - assertThat(methodSubject, isPresent()); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); KmPackageSubject kmPackage = libKt.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java index d82b5c6..0914a23 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
@@ -6,7 +6,7 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -123,20 +123,16 @@ String libClassName = PKG + ".vararg_lib.LibKt"; ClassSubject cls = inspector.clazz(className); - assertThat(cls, isPresent()); - assertThat(cls, not(isRenamed())); + assertThat(cls, isPresentAndNotRenamed()); MethodSubject foo = cls.uniqueMethodWithName("foo"); - assertThat(foo, isPresent()); - assertThat(foo, not(isRenamed())); + assertThat(foo, isPresentAndNotRenamed()); ClassSubject libKt = inspector.clazz(libClassName); - assertThat(libKt, isPresent()); - assertThat(libKt, not(isRenamed())); + assertThat(libKt, isPresentAndNotRenamed()); MethodSubject bar = libKt.uniqueMethodWithName("bar"); - assertThat(bar, isPresent()); - assertThat(bar, not(isRenamed())); + assertThat(bar, isPresentAndNotRenamed()); KmPackageSubject kmPackage = libKt.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInLibraryTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInLibraryTypeTest.java index 12b361b..159bf66 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInLibraryTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInLibraryTypeTest.java
@@ -5,10 +5,9 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -122,8 +121,7 @@ private void inspect(CodeInspector inspector) { String extClassName = PKG + ".libtype_lib_ext.ExtKt"; ClassSubject ext = inspector.clazz(extClassName); - assertThat(ext, isPresent()); - assertThat(ext, not(isRenamed())); + assertThat(ext, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = ext.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInMultifileClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInMultifileClassTest.java index 09d62d7..45a419d 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInMultifileClassTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInMultifileClassTest.java
@@ -6,7 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -121,11 +122,9 @@ String utilClassName = PKG + ".multifileclass_lib.UtilKt"; ClassSubject util = inspector.clazz(utilClassName); - assertThat(util, isPresent()); - assertThat(util, not(isRenamed())); + assertThat(util, isPresentAndNotRenamed()); MethodSubject commaJoinOfInt = util.uniqueMethodWithName("commaSeparatedJoinOfInt"); - assertThat(commaJoinOfInt, isPresent()); - assertThat(commaJoinOfInt, not(isRenamed())); + assertThat(commaJoinOfInt, isPresentAndNotRenamed()); MethodSubject joinOfInt = util.uniqueMethodWithName("joinOfInt"); assertThat(joinOfInt, not(isPresent())); @@ -167,14 +166,11 @@ String utilClassName = PKG + ".multifileclass_lib.UtilKt"; ClassSubject util = inspector.clazz(utilClassName); - assertThat(util, isPresent()); - assertThat(util, not(isRenamed())); + assertThat(util, isPresentAndNotRenamed()); MethodSubject commaJoinOfInt = util.uniqueMethodWithName("commaSeparatedJoinOfInt"); - assertThat(commaJoinOfInt, isPresent()); - assertThat(commaJoinOfInt, not(isRenamed())); + assertThat(commaJoinOfInt, isPresentAndNotRenamed()); MethodSubject joinOfInt = util.uniqueMethodWithName("joinOfInt"); - assertThat(joinOfInt, isPresent()); - assertThat(joinOfInt, isRenamed()); + assertThat(joinOfInt, isPresentAndRenamed()); inspectMetadataForFacade(inspector, util); @@ -195,19 +191,18 @@ for (String partClassName : partClassNames) { ClassSubject partClass = inspector.clazz(DescriptorUtils.getJavaTypeFromBinaryName(partClassName)); - assertThat(partClass, isRenamed()); + assertThat(partClass, isPresentAndRenamed()); } } private void inspectSignedKt(CodeInspector inspector) { String signedClassName = PKG + ".multifileclass_lib.UtilKt__SignedKt"; ClassSubject signed = inspector.clazz(signedClassName); - assertThat(signed, isRenamed()); + assertThat(signed, isPresentAndRenamed()); MethodSubject commaJoinOfInt = signed.uniqueMethodWithName("commaSeparatedJoinOfInt"); - assertThat(commaJoinOfInt, isPresent()); - assertThat(commaJoinOfInt, not(isRenamed())); + assertThat(commaJoinOfInt, isPresentAndNotRenamed()); MethodSubject joinOfInt = signed.uniqueMethodWithName("joinOfInt"); - assertThat(joinOfInt, isRenamed()); + assertThat(joinOfInt, isPresentAndRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = signed.getKmPackage();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInNestedClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInNestedClassTest.java index 3c218fe..eada4da 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInNestedClassTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInNestedClassTest.java
@@ -6,8 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -119,28 +119,30 @@ String nestedClassName = outerClassName + "$Nested"; ClassSubject inner = inspector.clazz(innerClassName); - assertThat(inner, isPresent()); - assertThat(inner, not(isRenamed())); + assertThat(inner, isPresentAndNotRenamed()); ClassSubject nested = inspector.clazz(nestedClassName); - assertThat(nested, isRenamed()); + assertThat(nested, isPresentAndRenamed()); ClassSubject outer = inspector.clazz(outerClassName); - assertThat(outer, isPresent()); - assertThat(outer, not(isRenamed())); + assertThat(outer, isPresentAndNotRenamed()); KmClassSubject kmClass = outer.getKmClass(); assertThat(kmClass, isPresent()); assertFalse(kmClass.getNestedClassDescriptors().isEmpty()); - kmClass.getNestedClassDescriptors().forEach(nestedClassDescriptor -> { - ClassSubject nestedClass = inspector.clazz(descriptorToJavaType(nestedClassDescriptor)); - if (nestedClass.getOriginalName().contains("Inner")) { - assertThat(nestedClass, not(isRenamed())); - } else { - assertThat(nestedClass, isRenamed()); - } - assertEquals(nestedClassDescriptor, nestedClass.getFinalDescriptor()); - }); + kmClass + .getNestedClassDescriptors() + .forEach( + nestedClassDescriptor -> { + ClassSubject nestedClass = + inspector.clazz(descriptorToJavaType(nestedClassDescriptor)); + if (nestedClass.getOriginalName().contains("Inner")) { + assertThat(nestedClass, isPresentAndNotRenamed()); + } else { + assertThat(nestedClass, isPresentAndRenamed()); + } + assertEquals(nestedClassDescriptor, nestedClass.getFinalDescriptor()); + }); } }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInParameterTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInParameterTypeTest.java index 53c8e4f..b4ae665 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInParameterTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInParameterTypeTest.java
@@ -5,8 +5,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -112,11 +112,10 @@ String implClassName = PKG + ".parametertype_lib.Impl"; ClassSubject itf = inspector.clazz(itfClassName); - assertThat(itf, isRenamed()); + assertThat(itf, isPresentAndRenamed()); ClassSubject impl = inspector.clazz(implClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java index f97fd1c..c479093 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
@@ -6,7 +6,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionProperty; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static junit.framework.TestCase.assertNull; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -116,14 +117,12 @@ private void inspectGetterOnly(CodeInspector inspector) { String personClassName = PKG + ".fragile_property_lib.Person"; ClassSubject person = inspector.clazz(personClassName); - assertThat(person, isPresent()); - assertThat(person, not(isRenamed())); + assertThat(person, isPresentAndNotRenamed()); FieldSubject backingField = person.uniqueFieldWithName("name"); - assertThat(backingField, isRenamed()); + assertThat(backingField, isPresentAndRenamed()); MethodSubject getterForName = person.uniqueMethodWithName("getName"); - assertThat(getterForName, isPresent()); - assertThat(getterForName, not(isRenamed())); + assertThat(getterForName, isPresentAndNotRenamed()); MethodSubject setterForName = person.uniqueMethodWithName("setName"); assertThat(setterForName, not(isPresent())); @@ -213,8 +212,7 @@ private void inspectSetterOnly(CodeInspector inspector) { String personClassName = PKG + ".fragile_property_lib.Person"; ClassSubject person = inspector.clazz(personClassName); - assertThat(person, isPresent()); - assertThat(person, not(isRenamed())); + assertThat(person, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = person.getKmClass();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTypeTest.java index dea1c4a..eb9ff61 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTypeTest.java
@@ -5,8 +5,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -110,11 +110,10 @@ String implClassName = PKG + ".propertytype_lib.Impl"; ClassSubject itf = inspector.clazz(itfClassName); - assertThat(itf, isRenamed()); + assertThat(itf, isPresentAndRenamed()); ClassSubject impl = inspector.clazz(implClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInRenamedTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInRenamedTypeTest.java index f474cf1..bb77f38 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInRenamedTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInRenamedTypeTest.java
@@ -6,9 +6,9 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromKotlinClassifier; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -115,8 +115,7 @@ private void inspect(CodeInspector inspector) { String pkg = getClass().getPackage().getName(); ClassSubject kept = inspector.clazz(pkg + ".anno.Kept"); - assertThat(kept, isPresent()); - assertThat(kept, not(isRenamed())); + assertThat(kept, isPresentAndNotRenamed()); // API entry is kept, hence @Metadata exists. KmClassSubject kmClass = kept.getKmClass(); assertThat(kmClass, isPresent()); @@ -127,7 +126,7 @@ assertThat(anno, isPresent()); ClassSubject renamed = inspector.clazz(pkg + ".anno.Renamed"); - assertThat(renamed, isRenamed()); + assertThat(renamed, isPresentAndRenamed()); // @Anno is kept. anno = renamed.annotation(annoName); assertThat(anno, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInReturnTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInReturnTypeTest.java index 63fc38d..47b0b82 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInReturnTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInReturnTypeTest.java
@@ -5,8 +5,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -112,11 +112,10 @@ String implClassName = PKG + ".returntype_lib.Impl"; ClassSubject itf = inspector.clazz(itfClassName); - assertThat(itf, isRenamed()); + assertThat(itf, isPresentAndRenamed()); ClassSubject impl = inspector.clazz(implClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java index 318a765..1bb1c44 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
@@ -7,9 +7,9 @@ import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -122,26 +122,27 @@ String libClassName = PKG + ".sealed_lib.LibKt"; ClassSubject num = inspector.clazz(numClassName); - assertThat(num, isRenamed()); + assertThat(num, isPresentAndRenamed()); ClassSubject expr = inspector.clazz(exprClassName); - assertThat(expr, isPresent()); - assertThat(expr, not(isRenamed())); + assertThat(expr, isPresentAndNotRenamed()); KmClassSubject kmClass = expr.getKmClass(); assertThat(kmClass, isPresent()); assertFalse(kmClass.getSealedSubclassDescriptors().isEmpty()); - kmClass.getSealedSubclassDescriptors().forEach(sealedSubclassDescriptor -> { - ClassSubject sealedSubclass = - inspector.clazz(descriptorToJavaType(sealedSubclassDescriptor)); - assertThat(sealedSubclass, isRenamed()); - assertEquals(sealedSubclassDescriptor, sealedSubclass.getFinalDescriptor()); - }); + kmClass + .getSealedSubclassDescriptors() + .forEach( + sealedSubclassDescriptor -> { + ClassSubject sealedSubclass = + inspector.clazz(descriptorToJavaType(sealedSubclassDescriptor)); + assertThat(sealedSubclass, isPresentAndRenamed()); + assertEquals(sealedSubclassDescriptor, sealedSubclass.getFinalDescriptor()); + }); ClassSubject libKt = inspector.clazz(libClassName); - assertThat(expr, isPresent()); - assertThat(expr, not(isRenamed())); + assertThat(expr, isPresentAndNotRenamed()); KmPackageSubject kmPackage = libKt.getKmPackage(); assertThat(kmPackage, isPresent()); @@ -184,15 +185,13 @@ String libClassName = PKG + ".sealed_lib.LibKt"; ClassSubject expr = inspector.clazz(exprClassName); - assertThat(expr, isPresent()); - assertThat(expr, not(isRenamed())); + assertThat(expr, isPresentAndNotRenamed()); KmClassSubject kmClass = expr.getKmClass(); assertThat(kmClass, isPresent()); ClassSubject libKt = inspector.clazz(libClassName); - assertThat(expr, isPresent()); - assertThat(expr, not(isRenamed())); + assertThat(expr, isPresentAndNotRenamed()); KmPackageSubject kmPackage = libKt.getKmPackage(); assertThat(kmPackage, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSuperTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSuperTypeTest.java index 8eb76bb..578a7ec 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSuperTypeTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSuperTypeTest.java
@@ -5,7 +5,8 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -114,8 +115,7 @@ assertThat(inspector.clazz(itfClassName), not(isPresent())); ClassSubject impl = inspector.clazz(implClassName); - assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent()); @@ -160,11 +160,11 @@ String implClassName = PKG + ".supertype_lib.Impl"; ClassSubject itf = inspector.clazz(itfClassName); - assertThat(itf, isRenamed()); + assertThat(itf, isPresentAndRenamed()); ClassSubject impl = inspector.clazz(implClassName); assertThat(impl, isPresent()); - assertThat(impl, not(isRenamed())); + assertThat(impl, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmClassSubject kmClass = impl.getKmClass(); assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java index 2c14c8d..ac4085f 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
@@ -6,11 +6,11 @@ import static com.android.tools.r8.KotlinCompilerTool.KOTLINC; import static com.android.tools.r8.utils.codeinspector.Matchers.isDexClass; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertTrue; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import com.android.tools.r8.TestParameters; @@ -168,15 +168,13 @@ String libKtClassName = packageName + ".LibKt"; ClassSubject itf = inspector.clazz(itfClassName); - assertThat(itf, isRenamed()); + assertThat(itf, isPresentAndRenamed()); ClassSubject libKt = inspector.clazz(libKtClassName); - assertThat(libKt, isPresent()); - assertThat(libKt, not(isRenamed())); + assertThat(libKt, isPresentAndNotRenamed()); MethodSubject seq = libKt.uniqueMethodWithName("seq"); - assertThat(seq, isPresent()); - assertThat(seq, not(isRenamed())); + assertThat(seq, isPresentAndNotRenamed()); // API entry is kept, hence the presence of Metadata. KmPackageSubject kmPackage = libKt.getKmPackage(); @@ -219,7 +217,7 @@ // Check that Arr has been renamed. ClassSubject arr = inspector.clazz(packageName + ".Arr"); - assertThat(arr, isRenamed()); + assertThat(arr, isPresentAndRenamed()); ClassSubject libKt = inspector.clazz(libKtClassName); KmPackageSubject kmPackage = libKt.getKmPackage();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java index df35c97..52ae0b3 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java
@@ -7,7 +7,7 @@ import static com.android.tools.r8.utils.codeinspector.Matchers.isDexClass; import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -171,7 +171,7 @@ assertThat(someClass, isPresent()); ClassSubject classThatShouldBeObfuscated = inspector.clazz(LIB_PKG + "ClassThatWillBeObfuscated"); - assertThat(classThatShouldBeObfuscated, isRenamed()); + assertThat(classThatShouldBeObfuscated, isPresentAndRenamed()); // Check that the type-parameters of Invariant is marked as INVARIANT. ClassSubject invariant = inspector.clazz(LIB_PKG + "Invariant");
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java index 043a48a..dec2ff2 100644 --- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java
@@ -4,7 +4,8 @@ package com.android.tools.r8.kotlin.metadata; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -59,14 +60,12 @@ .run(parameters.getRuntime(), mainClassName); CodeInspector inspector = result.inspector(); ClassSubject clazz = inspector.clazz(mainClassName); - assertThat(clazz, isPresent()); - assertThat(clazz, not(isRenamed())); + assertThat(clazz, isPresentAndNotRenamed()); // Main class is kept, hence the presence of Metadata. AnnotationSubject annotationSubject = clazz.annotation(METADATA_TYPE); assertThat(annotationSubject, isPresent()); ClassSubject impl1 = inspector.clazz(implementer1ClassName); - assertThat(impl1, isPresent()); - assertThat(impl1, isRenamed()); + assertThat(impl1, isPresentAndRenamed()); // All other classes can be renamed, hence the absence of Metadata; assertThat(impl1.annotation(METADATA_TYPE), not(isPresent())); }
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java index 123744d..447ed7e 100644 --- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java +++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
@@ -4,32 +4,29 @@ package com.android.tools.r8.maindexlist; +import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage; import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import com.android.tools.r8.CompilationFailedException; -import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer; -import com.android.tools.r8.Diagnostic; import com.android.tools.r8.DiagnosticsHandler; -import com.android.tools.r8.OutputMode; -import com.android.tools.r8.R8Command; import com.android.tools.r8.StringConsumer; +import com.android.tools.r8.StringConsumer.FileConsumer; import com.android.tools.r8.TestBase; -import com.android.tools.r8.ToolHelper; -import com.android.tools.r8.origin.Origin; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestParametersCollection; import com.android.tools.r8.utils.AndroidApiLevel; import com.android.tools.r8.utils.FileUtils; -import com.android.tools.r8.utils.StringDiagnostic; import com.google.common.collect.ImmutableList; -import java.io.IOException; import java.nio.file.Path; import java.util.stream.Collectors; 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 MainDexListOutputTest extends TestBase { interface MyConsumer<T> { @@ -67,50 +64,45 @@ } } - class Reporter implements DiagnosticsHandler { - int errorCount = 0; - - @Override - public void error(Diagnostic error) { - errorCount++; - assertTrue(error instanceof StringDiagnostic); - assertTrue(error.getDiagnosticMessage().contains("main-dex")); - } + @Parameters(name = "{0}") + public static TestParametersCollection data() { + return getTestParameters().withNoneRuntime().build(); } - @Test + public MainDexListOutputTest(TestParameters parameters) { + parameters.assertNoneRuntime(); + } + + @Test(expected = CompilationFailedException.class) public void testNoMainDex() throws Exception { - Reporter reporter = new Reporter(); - try { - Path mainDexListOutput = temp.getRoot().toPath().resolve("main-dex-output.txt"); - R8Command.builder(reporter) - .setProgramConsumer(DexIndexedConsumer.emptyConsumer()) - .addClassProgramData( - ToolHelper.getClassAsBytes(HelloWorldMain.class), Origin.unknown()) - .setMainDexListOutputPath(mainDexListOutput) - .build(); - fail("Expect to fail"); - } catch (CompilationFailedException e) { - assertEquals(1, reporter.errorCount); - assertThat( - e.getCause().getMessage(), - containsString("--main-dex-list-output require --main-dex-rules and/or --main-dex-list")); - } + Path mainDexListOutput = temp.getRoot().toPath().resolve("main-dex-output.txt"); + testForR8(Backend.DEX) + .addProgramClasses(HelloWorldMain.class) + .setMainDexListConsumer(new FileConsumer(mainDexListOutput)) + .setMinApi(AndroidApiLevel.K) + .compileWithExpectedDiagnostics( + diagnostics -> + diagnostics + .assertOnlyErrors() + .assertErrorsMatch( + diagnosticMessage( + containsString( + "--main-dex-list-output require --main-dex-rules and/or" + + " --main-dex-list")))); } @Test public void testWithMainDex() throws Exception { Path mainDexRules = writeTextToTempFile(keepMainProguardConfiguration(HelloWorldMain.class)); Path mainDexListOutput = temp.getRoot().toPath().resolve("main-dex-output.txt"); - R8Command command = - ToolHelper.prepareR8CommandBuilder(readClasses(HelloWorldMain.class)) - .setDisableTreeShaking(true) - .setDisableMinification(true) - .addMainDexRulesFiles(mainDexRules) - .setMainDexListOutputPath(mainDexListOutput) - .setOutput(temp.getRoot().toPath(), OutputMode.DexIndexed) - .build(); - ToolHelper.runR8(command); + testForR8(Backend.DEX) + .addProgramClasses(HelloWorldMain.class) + .noTreeShaking() + .noMinification() + .setMinApi(AndroidApiLevel.K) + .addMainDexRuleFiles(mainDexRules) + .setMainDexListConsumer(new FileConsumer(mainDexListOutput)) + .compile(); // Main dex list with the single class. assertEquals( ImmutableList.of(HelloWorldMain.class.getTypeName().replace('.', '/') + ".class"), @@ -121,7 +113,7 @@ } @Test - public void testD8DesugaredLambdasInMainDexList() throws IOException, CompilationFailedException { + public void testD8DesugaredLambdasInMainDexList() throws Exception { Path mainDexList = writeTextToTempFile(testClassMainDexName); TestMainDexListConsumer consumer = new TestMainDexListConsumer(); testForD8() @@ -134,17 +126,16 @@ } @Test - public void testD8DesugaredLambdasInMainDexListMerging() - throws IOException, CompilationFailedException { + public void testD8DesugaredLambdasInMainDexListMerging() throws Exception { Path mainDexList = writeTextToTempFile(testClassMainDexName); - Path dexOutput = temp.getRoot().toPath().resolve("classes.zip"); // Build intermediate dex code first. - testForD8() - .setMinApi(AndroidApiLevel.K) - .addProgramClasses(ImmutableList.of(TestClass.class, MyConsumer.class)) - .setIntermediate(true) - .setProgramConsumer(new ArchiveConsumer(dexOutput)) - .compile(); + Path dexOutput = + testForD8() + .setMinApi(AndroidApiLevel.K) + .addProgramClasses(ImmutableList.of(TestClass.class, MyConsumer.class)) + .setIntermediate(true) + .compile() + .writeToZip(); // Now test that when merging with a main dex list it is correctly updated. TestMainDexListConsumer consumer = new TestMainDexListConsumer(); testForD8()
diff --git a/src/test/java/com/android/tools/r8/naming/AbstractMethodRenamingTest.java b/src/test/java/com/android/tools/r8/naming/AbstractMethodRenamingTest.java index 71b158d..9f44e4b 100644 --- a/src/test/java/com/android/tools/r8/naming/AbstractMethodRenamingTest.java +++ b/src/test/java/com/android/tools/r8/naming/AbstractMethodRenamingTest.java
@@ -3,8 +3,7 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.naming; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -81,26 +80,20 @@ private void inspect(CodeInspector inspector) { ClassSubject base = inspector.clazz(Base.class); - assertThat(base, isPresent()); - assertThat(base, isRenamed()); + assertThat(base, isPresentAndRenamed()); MethodSubject foo = base.uniqueMethodWithName("foo"); - assertThat(foo, isPresent()); - assertThat(foo, isRenamed()); + assertThat(foo, isPresentAndRenamed()); ClassSubject sub1 = inspector.clazz(Sub1.class); - assertThat(sub1, isPresent()); - assertThat(sub1, isRenamed()); + assertThat(sub1, isPresentAndRenamed()); MethodSubject fooInSub1 = sub1.uniqueMethodWithName("foo"); - assertThat(fooInSub1, isPresent()); - assertThat(fooInSub1, isRenamed()); + assertThat(fooInSub1, isPresentAndRenamed()); assertEquals(foo.getFinalName(), fooInSub1.getFinalName()); ClassSubject sub2 = inspector.clazz(Sub1.class); - assertThat(sub2, isPresent()); - assertThat(sub2, isRenamed()); + assertThat(sub2, isPresentAndRenamed()); MethodSubject fooInSub2 = sub2.uniqueMethodWithName("foo"); - assertThat(fooInSub2, isPresent()); - assertThat(fooInSub2, isRenamed()); + assertThat(fooInSub2, isPresentAndRenamed()); assertEquals(foo.getFinalName(), fooInSub2.getFinalName()); } }
diff --git a/src/test/java/com/android/tools/r8/naming/AbstractR8KotlinNamingTestBase.java b/src/test/java/com/android/tools/r8/naming/AbstractR8KotlinNamingTestBase.java index 2815aed..9f2d940 100644 --- a/src/test/java/com/android/tools/r8/naming/AbstractR8KotlinNamingTestBase.java +++ b/src/test/java/com/android/tools/r8/naming/AbstractR8KotlinNamingTestBase.java
@@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.naming; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import com.android.tools.r8.ToolHelper.KotlinTargetVersion; @@ -29,65 +29,65 @@ protected ClassSubject checkClassIsRenamed(CodeInspector inspector, String className) { ClassSubject classSubject = inspector.clazz(className); - assertThat(classSubject, isRenamed()); + assertThat(classSubject, isPresentAndRenamed()); return classSubject; } protected ClassSubject checkClassIsNotRenamed(CodeInspector inspector, String className) { ClassSubject classSubject = inspector.clazz(className); - assertThat(classSubject, not(isRenamed())); + assertThat(classSubject, isPresentAndNotRenamed()); return classSubject; } protected FieldSubject checkFieldIsRenamed( ClassSubject classSubject, String fieldType, String fieldName) { FieldSubject fieldSubject = checkFieldIsKept(classSubject, fieldType, fieldName); - assertThat(fieldSubject, isRenamed()); + assertThat(fieldSubject, isPresentAndRenamed()); return fieldSubject; } protected FieldSubject checkFieldIsRenamed(ClassSubject classSubject, String fieldName) { FieldSubject fieldSubject = checkFieldIsKept(classSubject, fieldName); - assertThat(fieldSubject, isRenamed()); + assertThat(fieldSubject, isPresentAndRenamed()); return fieldSubject; } protected FieldSubject checkFieldIsNotRenamed( ClassSubject classSubject, String fieldType, String fieldName) { FieldSubject fieldSubject = checkFieldIsKept(classSubject, fieldType, fieldName); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); return fieldSubject; } protected FieldSubject checkFieldIsNotRenamed(ClassSubject classSubject, String fieldName) { FieldSubject fieldSubject = checkFieldIsKept(classSubject, fieldName); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); return fieldSubject; } protected MethodSubject checkMethodIsRenamed( ClassSubject classSubject, MethodSignature methodSignature) { MethodSubject methodSubject = checkMethodIsKept(classSubject, methodSignature); - assertThat(methodSubject, isRenamed()); + assertThat(methodSubject, isPresentAndRenamed()); return methodSubject; } protected MethodSubject checkMethodIsRenamed(ClassSubject classSubject, String methodName) { MethodSubject methodSubject = checkMethodIsKept(classSubject, methodName); - assertThat(methodSubject, isRenamed()); + assertThat(methodSubject, isPresentAndRenamed()); return methodSubject; } protected MethodSubject checkMethodIsNotRenamed( ClassSubject classSubject, MethodSignature methodSignature) { MethodSubject methodSubject = checkMethodIsKept(classSubject, methodSignature); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); return methodSubject; } protected MethodSubject checkMethodIsNotRenamed(ClassSubject classSubject, String methodName) { MethodSubject methodSubject = checkMethodIsKept(classSubject, methodName); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); return methodSubject; }
diff --git a/src/test/java/com/android/tools/r8/naming/AvoidRTest.java b/src/test/java/com/android/tools/r8/naming/AvoidRTest.java index 5c2d882..8feb257 100644 --- a/src/test/java/com/android/tools/r8/naming/AvoidRTest.java +++ b/src/test/java/com/android/tools/r8/naming/AvoidRTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.DescriptorUtils.getUnqualifiedClassNameFromDescriptor; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; @@ -60,19 +60,23 @@ } builder.addProgramClassFileData(jasminBuilder.buildClasses()); Set<String> usedDescriptors = new HashSet<>(); - builder.noTreeShaking() + builder + .noTreeShaking() .addKeepRules("-classobfuscationdictionary " + dictionary) .compile() - .inspect(codeInspector -> { - codeInspector.forAllClasses(classSubject -> { - assertThat(classSubject, isRenamed()); - String renamedDescriptor = classSubject.getFinalDescriptor(); - assertTrue(usedDescriptors.add(renamedDescriptor)); - assertNotEquals("R", getUnqualifiedClassNameFromDescriptor(renamedDescriptor)); - assertTrue(expectedNames.contains( - getUnqualifiedClassNameFromDescriptor(renamedDescriptor))); - }); - }); + .inspect( + codeInspector -> { + codeInspector.forAllClasses( + classSubject -> { + assertThat(classSubject, isPresentAndRenamed()); + String renamedDescriptor = classSubject.getFinalDescriptor(); + assertTrue(usedDescriptors.add(renamedDescriptor)); + assertNotEquals("R", getUnqualifiedClassNameFromDescriptor(renamedDescriptor)); + assertTrue( + expectedNames.contains( + getUnqualifiedClassNameFromDescriptor(renamedDescriptor))); + }); + }); } @Test @@ -84,15 +88,18 @@ } builder.addProgramClassFileData(jasminBuilder.buildClasses()); Set<String> usedNames = new HashSet<>(); - builder.noTreeShaking() + builder + .noTreeShaking() .compile() - .inspect(codeInspector -> { - codeInspector.forAllClasses(classSubject -> { - assertThat(classSubject, isRenamed()); - assertTrue(usedNames.add(classSubject.getFinalName())); - assertNotEquals("R", classSubject.getFinalName()); - }); - }); + .inspect( + codeInspector -> { + codeInspector.forAllClasses( + classSubject -> { + assertThat(classSubject, isPresentAndRenamed()); + assertTrue(usedNames.add(classSubject.getFinalName())); + assertNotEquals("R", classSubject.getFinalName()); + }); + }); assertTrue(usedNames.contains("Q")); assertTrue(usedNames.contains("S")); } @@ -114,17 +121,20 @@ } builder.addProgramClassFileData(jasminBuilder.buildClasses()); Set<String> usedDescriptors = new HashSet<>(); - builder.noTreeShaking() + builder + .noTreeShaking() .addKeepRules(keepRule) .compile() - .inspect(codeInspector -> { - codeInspector.forAllClasses(classSubject -> { - assertThat(classSubject, isRenamed()); - String renamedDescriptor = classSubject.getFinalDescriptor(); - assertTrue(usedDescriptors.add(renamedDescriptor)); - assertNotEquals("R", getUnqualifiedClassNameFromDescriptor(renamedDescriptor)); - }); - }); + .inspect( + codeInspector -> { + codeInspector.forAllClasses( + classSubject -> { + assertThat(classSubject, isPresentAndRenamed()); + String renamedDescriptor = classSubject.getFinalDescriptor(); + assertTrue(usedDescriptors.add(renamedDescriptor)); + assertNotEquals("R", getUnqualifiedClassNameFromDescriptor(renamedDescriptor)); + }); + }); } @Test
diff --git a/src/test/java/com/android/tools/r8/naming/ClassNameMinifierOriginalClassNameTest.java b/src/test/java/com/android/tools/r8/naming/ClassNameMinifierOriginalClassNameTest.java index 553fe0c..779eb8a 100644 --- a/src/test/java/com/android/tools/r8/naming/ClassNameMinifierOriginalClassNameTest.java +++ b/src/test/java/com/android/tools/r8/naming/ClassNameMinifierOriginalClassNameTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -62,7 +62,7 @@ .inspect( inspector -> { assertEquals(1, inspector.allClasses().size()); - assertThat(inspector.clazz(B.class), isRenamed()); + assertThat(inspector.clazz(B.class), isPresentAndRenamed()); assertEquals(A.class.getTypeName(), inspector.clazz(B.class).getFinalName()); }); }
diff --git a/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java b/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java index 8c50aa7..3eae470 100644 --- a/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java +++ b/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java
@@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.naming; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -94,13 +94,13 @@ private void inspect(CodeInspector inspector, boolean overloadAggressively) throws NoSuchMethodException { ClassSubject superInterface = inspector.clazz(SuperInterface.class); - assertThat(superInterface, isRenamed()); + assertThat(superInterface, isPresentAndRenamed()); MethodSubject foo1 = superInterface.uniqueMethodWithName("foo"); - assertThat(foo1, isRenamed()); + assertThat(foo1, isPresentAndRenamed()); ClassSubject subInterface = inspector.clazz(SubInterface.class); - assertThat(subInterface, isRenamed()); + assertThat(subInterface, isPresentAndRenamed()); MethodSubject foo2 = subInterface.method(SubInterface.class.getDeclaredMethod("foo")); - assertThat(foo2, isRenamed()); + assertThat(foo2, isPresentAndRenamed()); if (overloadAggressively && parameters.isDexRuntime()) { assertNotEquals(foo1.getFinalName(), foo2.getFinalName()); } else {
diff --git a/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeTest.java b/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeTest.java index 6cb9837..5d11b24 100644 --- a/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeTest.java +++ b/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -83,7 +83,7 @@ Set<String> minifiedMethodNames = new HashSet<>(); for (Set<MethodSubject> methodSubjects : methodSubjectsByName.values()) { for (MethodSubject methodSubject : methodSubjects) { - assertThat(methodSubject, isRenamed()); + assertThat(methodSubject, isPresentAndRenamed()); minifiedMethodNames.add(methodSubject.getFinalName()); } }
diff --git a/src/test/java/com/android/tools/r8/naming/EnumMinification.java b/src/test/java/com/android/tools/r8/naming/EnumMinification.java index 177a7f0..6a5ff3e 100644 --- a/src/test/java/com/android/tools/r8/naming/EnumMinification.java +++ b/src/test/java/com/android/tools/r8/naming/EnumMinification.java
@@ -5,7 +5,8 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -65,12 +66,14 @@ ClassSubject clazz = inspector.clazz(enumTypeName); // The class and fields - including field $VALUES and method valueOf - can be renamed. Only // the values() method needs to be - assertThat(clazz, isRenamed()); - assertThat(clazz.uniqueFieldWithName("VALUE1"), isRenamed()); - assertThat(clazz.uniqueFieldWithName("VALUE2"), isRenamed()); - assertThat(clazz.uniqueFieldWithName("$VALUES"), isRenamed()); - assertThat(clazz.uniqueMethodWithName("valueOf"), valueOfKept ? isRenamed() : not(isPresent())); - assertThat(clazz.uniqueMethodWithName("values"), not(isRenamed())); + assertThat(clazz, isPresentAndRenamed()); + assertThat(clazz.uniqueFieldWithName("VALUE1"), isPresentAndRenamed()); + assertThat(clazz.uniqueFieldWithName("VALUE2"), isPresentAndRenamed()); + assertThat(clazz.uniqueFieldWithName("$VALUES"), isPresentAndRenamed()); + assertThat( + clazz.uniqueMethodWithName("valueOf"), + valueOfKept ? isPresentAndRenamed() : not(isPresent())); + assertThat(clazz.uniqueMethodWithName("values"), isPresentAndNotRenamed()); } @Test
diff --git a/src/test/java/com/android/tools/r8/naming/ForNameRenamingTest.java b/src/test/java/com/android/tools/r8/naming/ForNameRenamingTest.java index 1d776b5..c69ecd0 100644 --- a/src/test/java/com/android/tools/r8/naming/ForNameRenamingTest.java +++ b/src/test/java/com/android/tools/r8/naming/ForNameRenamingTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; @@ -48,8 +48,7 @@ private void inspect(CodeInspector inspector) { ClassSubject boo = inspector.clazz(Boo.class); - assertThat(boo, isPresent()); - assertThat(boo, isRenamed()); + assertThat(boo, isPresentAndRenamed()); ClassSubject main = inspector.clazz(MAIN); assertThat(main, isPresent());
diff --git a/src/test/java/com/android/tools/r8/naming/KeepPackageNamesTest.java b/src/test/java/com/android/tools/r8/naming/KeepPackageNamesTest.java index 5eca4d1..f72abf5 100644 --- a/src/test/java/com/android/tools/r8/naming/KeepPackageNamesTest.java +++ b/src/test/java/com/android/tools/r8/naming/KeepPackageNamesTest.java
@@ -4,8 +4,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.DescriptorUtils.getPackageNameFromDescriptor; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -44,15 +43,13 @@ public void inspect(CodeInspector inspector) { ClassSubject top = inspector.clazz(Top.class); - assertThat(top, isPresent()); - assertThat(top, isRenamed()); + assertThat(top, isPresentAndRenamed()); assertEquals( getPackageNameFromDescriptor(top.getOriginalDescriptor()), getPackageNameFromDescriptor(top.getFinalDescriptor())); ClassSubject sub = inspector.clazz(SubClass.class); - assertThat(sub, isPresent()); - assertThat(sub, isRenamed()); + assertThat(sub, isPresentAndRenamed()); switch (this) { case SINGLE_ASTERISK: assertNotEquals(
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java index bcb02da..07dad43 100644 --- a/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java +++ b/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -327,13 +327,13 @@ .setProguardMapConsumer(StringConsumer.emptyConsumer()) .build())); // All classes are kept, and renamed. - assertThat(inspector.clazz("Simple"), isRenamed()); - assertThat(inspector.clazz("Base"), isRenamed()); - assertThat(inspector.clazz("Outer"), isRenamed()); - assertThat(inspector.clazz("Outer$Inner"), isRenamed()); - assertThat(inspector.clazz("Outer$ExtendsInner"), isRenamed()); - assertThat(inspector.clazz("Outer$Inner$InnerInner"), isRenamed()); - assertThat(inspector.clazz("Outer$Inner$ExtendsInnerInner"), isRenamed()); + assertThat(inspector.clazz("Simple"), isPresentAndRenamed()); + assertThat(inspector.clazz("Base"), isPresentAndRenamed()); + assertThat(inspector.clazz("Outer"), isPresentAndRenamed()); + assertThat(inspector.clazz("Outer$Inner"), isPresentAndRenamed()); + assertThat(inspector.clazz("Outer$ExtendsInner"), isPresentAndRenamed()); + assertThat(inspector.clazz("Outer$Inner$InnerInner"), isPresentAndRenamed()); + assertThat(inspector.clazz("Outer$Inner$ExtendsInnerInner"), isPresentAndRenamed()); // Test that classes with have their original signature if the default was provided. if (!signatures.containsKey("Simple")) {
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java index 5737496..12b18e4 100644 --- a/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java +++ b/src/test/java/com/android/tools/r8/naming/MinifierFieldSignatureTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -193,8 +193,8 @@ .build())); // All classes are kept, and renamed. ClassSubject clazz = inspector.clazz("Fields"); - assertThat(clazz, isRenamed()); - assertThat(inspector.clazz("Fields$Inner"), isRenamed()); + assertThat(clazz, isPresentAndRenamed()); + assertThat(inspector.clazz("Fields$Inner"), isPresentAndRenamed()); FieldSubject anX = lookupAnX(inspector); FieldSubject anArrayOfX = lookupAnArrayOfX(inspector); @@ -202,10 +202,10 @@ FieldSubject aFieldsOfXInner = clazz.field("Fields$Inner", "aFieldsOfXInner"); // Check that all fields have been renamed - assertThat(anX, isRenamed()); - assertThat(anArrayOfX, isRenamed()); - assertThat(aFieldsOfX, isRenamed()); - assertThat(aFieldsOfXInner, isRenamed()); + assertThat(anX, isPresentAndRenamed()); + assertThat(anArrayOfX, isPresentAndRenamed()); + assertThat(aFieldsOfX, isPresentAndRenamed()); + assertThat(aFieldsOfXInner, isPresentAndRenamed()); //System.out.println(generic.getFinalSignatureAttribute()); //System.out.println(generic.getOriginalSignatureAttribute());
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java index b19ed16..a275bdb 100644 --- a/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java +++ b/src/test/java/com/android/tools/r8/naming/MinifierMethodSignatureTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -215,8 +215,8 @@ .build())); // All classes are kept, and renamed. ClassSubject clazz = inspector.clazz("Methods"); - assertThat(clazz, isRenamed()); - assertThat(inspector.clazz("Methods$Inner"), isRenamed()); + assertThat(clazz, isPresentAndRenamed()); + assertThat(inspector.clazz("Methods$Inner"), isPresentAndRenamed()); MethodSubject generic = lookupGeneric(inspector); MethodSubject parameterizedReturn = lookupParameterizedReturn(inspector); @@ -225,10 +225,10 @@ clazz.method("void", "parametrizedThrows", ImmutableList.of()); // Check that all methods have been renamed - assertThat(generic, isRenamed()); - assertThat(parameterizedReturn, isRenamed()); - assertThat(parameterizedArguments, isRenamed()); - assertThat(parametrizedThrows, isRenamed()); + assertThat(generic, isPresentAndRenamed()); + assertThat(parameterizedReturn, isPresentAndRenamed()); + assertThat(parameterizedArguments, isPresentAndRenamed()); + assertThat(parametrizedThrows, isPresentAndRenamed()); // Test that methods have their original signature if the default was provided. if (!signatures.containsKey("generic")) {
diff --git a/src/test/java/com/android/tools/r8/naming/OverloadedReservedFieldNamingTest.java b/src/test/java/com/android/tools/r8/naming/OverloadedReservedFieldNamingTest.java index 18bc136..11c9154 100644 --- a/src/test/java/com/android/tools/r8/naming/OverloadedReservedFieldNamingTest.java +++ b/src/test/java/com/android/tools/r8/naming/OverloadedReservedFieldNamingTest.java
@@ -5,8 +5,7 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -59,8 +58,7 @@ assertThat(classSubject, isPresent()); FieldSubject fieldSubject = classSubject.uniqueFieldWithName("a"); - assertThat(fieldSubject, isPresent()); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); FieldSubject helloFieldSubject = classSubject.uniqueFieldWithName("hello"); assertThat(helloFieldSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubClassTest.java b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubClassTest.java index 943e4bf..67b86ce 100644 --- a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubClassTest.java +++ b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubClassTest.java
@@ -4,8 +4,8 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -102,40 +102,40 @@ assertThat(aFieldSubject, isPresent()); if (reserveName) { - assertThat(f1FieldSubject, isRenamed()); + assertThat(f1FieldSubject, isPresentAndRenamed()); assertEquals("e", f1FieldSubject.getFinalName()); - assertThat(f2FieldSubject, isRenamed()); + assertThat(f2FieldSubject, isPresentAndRenamed()); assertEquals("f", f2FieldSubject.getFinalName()); - assertThat(f3FieldSubject, isRenamed()); + assertThat(f3FieldSubject, isPresentAndRenamed()); assertEquals("b", f3FieldSubject.getFinalName()); - assertThat(f4FieldSubject, isRenamed()); + assertThat(f4FieldSubject, isPresentAndRenamed()); assertEquals("c", f4FieldSubject.getFinalName()); - assertThat(f5FieldSubject, isRenamed()); + assertThat(f5FieldSubject, isPresentAndRenamed()); assertEquals("d", f5FieldSubject.getFinalName()); // B.a should not be renamed because it is not allowed to be minified. - assertThat(aFieldSubject, not(isRenamed())); + assertThat(aFieldSubject, isPresentAndNotRenamed()); } else { - assertThat(f1FieldSubject, isRenamed()); + assertThat(f1FieldSubject, isPresentAndRenamed()); assertEquals("d", f1FieldSubject.getFinalName()); - assertThat(f2FieldSubject, isRenamed()); + assertThat(f2FieldSubject, isPresentAndRenamed()); assertEquals("e", f2FieldSubject.getFinalName()); - assertThat(f3FieldSubject, isRenamed()); + assertThat(f3FieldSubject, isPresentAndRenamed()); assertEquals("a", f3FieldSubject.getFinalName()); - assertThat(f4FieldSubject, isRenamed()); + assertThat(f4FieldSubject, isPresentAndRenamed()); assertEquals("b", f4FieldSubject.getFinalName()); - assertThat(f5FieldSubject, isRenamed()); + assertThat(f5FieldSubject, isPresentAndRenamed()); assertEquals("c", f5FieldSubject.getFinalName()); - assertThat(aFieldSubject, isRenamed()); + assertThat(aFieldSubject, isPresentAndRenamed()); assertEquals("f", aFieldSubject.getFinalName()); } }
diff --git a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubInterfaceTest.java b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubInterfaceTest.java index 309c156..89804e8 100644 --- a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubInterfaceTest.java +++ b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSubInterfaceTest.java
@@ -4,8 +4,8 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeFalse; @@ -69,13 +69,13 @@ FieldSubject f1FieldSubject = iClassSubject.uniqueFieldWithName("f1"); assertThat(f1FieldSubject, isPresent()); - assertThat(f1FieldSubject, isRenamed()); + assertThat(f1FieldSubject, isPresentAndRenamed()); FieldSubject aFieldSubject = jClassSubject.uniqueFieldWithName("a"); assertThat(aFieldSubject, isPresent()); if (reserveName) { - assertThat(aFieldSubject, not(isRenamed())); + assertThat(aFieldSubject, isPresentAndNotRenamed()); // Interface fields are visited/renamed before fields on classes. Thus, the interface field // I.f1 will be visited first and assigned the name b (since the name a is reserved). @@ -88,7 +88,7 @@ // The interface field J.a will be visited after I.f1, and will therefore be assigned the name // b. - assertThat(aFieldSubject, isRenamed()); + assertThat(aFieldSubject, isPresentAndRenamed()); assertEquals("b", aFieldSubject.getFinalName()); } @@ -121,7 +121,7 @@ FieldSubject f2FieldSubject = aClassSubject.uniqueFieldWithName("f2"); assertThat(f2FieldSubject, isPresent()); - assertThat(f2FieldSubject, isRenamed()); + assertThat(f2FieldSubject, isPresentAndRenamed()); assertEquals(expectedNameForF2, f2FieldSubject.getFinalName()); }
diff --git a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperClassTest.java b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperClassTest.java index c687947..e7f32e3 100644 --- a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperClassTest.java +++ b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperClassTest.java
@@ -4,8 +4,8 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -63,7 +63,7 @@ // Fields are visited/renamed according to the class hierarchy order. Thus, the field A.a will // be visited first and assigned the name a. As it ends up receiving the same name as in the // original program, it has not technically been renamed. - assertThat(aFieldSubject, not(isRenamed())); + assertThat(aFieldSubject, isPresentAndNotRenamed()); inspect(inspector); } @@ -90,16 +90,14 @@ assertThat(aSub1ClassSubject, isPresent()); FieldSubject fooFieldSubject = aSub1ClassSubject.uniqueFieldWithName("foo"); - assertThat(fooFieldSubject, isPresent()); - assertThat(fooFieldSubject, isRenamed()); + assertThat(fooFieldSubject, isPresentAndRenamed()); assertNotEquals("a", fooFieldSubject.getFinalName()); ClassSubject aSub2ClassSubject = inspector.clazz(ASub2.class); assertThat(aSub2ClassSubject, isPresent()); FieldSubject barFieldSubject = aSub2ClassSubject.uniqueFieldWithName("bar"); - assertThat(barFieldSubject, isPresent()); - assertThat(barFieldSubject, isRenamed()); + assertThat(barFieldSubject, isPresentAndRenamed()); assertNotEquals("a", barFieldSubject.getFinalName()); // Verify that ASub1.foo and ASub2.bar has been renamed to the same name.
diff --git a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperInterfaceTest.java b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperInterfaceTest.java index 4af8655..599799e 100644 --- a/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperInterfaceTest.java +++ b/src/test/java/com/android/tools/r8/naming/ReservedFieldNameInSuperInterfaceTest.java
@@ -4,8 +4,8 @@ package com.android.tools.r8.naming; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeFalse; @@ -66,7 +66,7 @@ // Interface fields are visited/renamed before fields on classes. Thus, the interface field I.a // will be visited first and assigned the name a. As it ends up receiving the same name as in // the input program, it has not technically been renamed. - assertThat(aFieldSubject, not(isRenamed())); + assertThat(aFieldSubject, isPresentAndNotRenamed()); inspect(inspector); } @@ -95,7 +95,7 @@ FieldSubject f1FieldSubject = jClassSubject.uniqueFieldWithName("f1"); assertThat(f1FieldSubject, isPresent()); - assertThat(f1FieldSubject, isRenamed()); + assertThat(f1FieldSubject, isPresentAndRenamed()); assertEquals("b", f1FieldSubject.getFinalName()); ClassSubject aClassSubject = inspector.clazz(A.class); @@ -103,7 +103,7 @@ FieldSubject f2FieldSubject = aClassSubject.uniqueFieldWithName("f2"); assertThat(f2FieldSubject, isPresent()); - assertThat(f2FieldSubject, isRenamed()); + assertThat(f2FieldSubject, isPresentAndRenamed()); assertEquals("c", f2FieldSubject.getFinalName()); }
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingDesugarLambdaTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingDesugarLambdaTest.java index e0d117f..0d0af87 100644 --- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingDesugarLambdaTest.java +++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingDesugarLambdaTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming.applymapping; import static com.android.tools.r8.Collectors.toSingle; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertNotSame; import static org.hamcrest.MatcherAssert.assertThat; @@ -58,7 +58,7 @@ .compile() .inspect( inspector -> { - assertThat(inspector.clazz(A.class), isRenamed()); + assertThat(inspector.clazz(A.class), isPresentAndRenamed()); assertEquals(finalName, inspector.clazz(A.class).getFinalName()); });
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java index 837c7df..1d188fb 100644 --- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java +++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionAsmTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming.applymapping.sourcelibrary; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -113,18 +113,15 @@ .inspector(); ClassSubject base = codeInspector.clazz("HasMapping"); - assertThat(base, isPresent()); - assertThat(base, isRenamed()); + assertThat(base, isPresentAndRenamed()); assertEquals("X", base.getFinalName()); MethodSubject x = base.method("void", "foo", ImmutableList.of()); - assertThat(x, isPresent()); - assertThat(x, isRenamed()); + assertThat(x, isPresentAndRenamed()); assertEquals("a", x.getFinalName()); // To ensure still getting illegal-access error we need to rename consistently. ClassSubject sub = codeInspector.clazz("NoMapping"); - assertThat(sub, isPresent()); - assertThat(sub, isRenamed()); + assertThat(sub, isPresentAndRenamed()); assertEquals("Y", sub.getFinalName()); MethodSubject y = sub.method("void", "a", ImmutableList.of()); assertThat(y, isPresent()); @@ -212,17 +209,14 @@ CodeInspector codeInspector = compileResult.inspector(); ClassSubject base = codeInspector.clazz("A"); - assertThat(base, isPresent()); - assertThat(base, isRenamed()); + assertThat(base, isPresentAndRenamed()); assertEquals("X", base.getFinalName()); MethodSubject x = base.method("void", "x", ImmutableList.of()); - assertThat(x, isPresent()); - assertThat(x, isRenamed()); + assertThat(x, isPresentAndRenamed()); assertEquals("y", x.getFinalName()); ClassSubject sub = codeInspector.clazz("B"); - assertThat(sub, isPresent()); - assertThat(sub, isRenamed()); + assertThat(sub, isPresentAndRenamed()); assertEquals("Y", sub.getFinalName()); MethodSubject subX = sub.method("void", "x", ImmutableList.of()); assertThat(subX, not(isPresent()));
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java index 3b683fa..725c5a9 100644 --- a/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java +++ b/src/test/java/com/android/tools/r8/naming/applymapping/sourcelibrary/MemberResolutionTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming.applymapping.sourcelibrary; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -133,23 +133,19 @@ ClassSubject base = inspector.clazz(AbstractChecker.class); assertThat(base, isPresent()); FieldSubject p = base.field("java.lang.String", "tag"); - assertThat(p, isPresent()); - assertThat(p, isRenamed()); + assertThat(p, isPresentAndRenamed()); assertEquals("p", p.getFinalName()); MethodSubject x = base.method("void", "check", ImmutableList.of()); - assertThat(x, isPresent()); - assertThat(x, isRenamed()); + assertThat(x, isPresentAndRenamed()); assertEquals("x", x.getFinalName()); ClassSubject sub = inspector.clazz(ConcreteChecker.class); assertThat(sub, isPresent()); FieldSubject q = sub.field("java.lang.String", "tag"); - assertThat(q, isPresent()); - assertThat(q, isRenamed()); + assertThat(q, isPresentAndRenamed()); assertEquals("q", q.getFinalName()); MethodSubject y = sub.method("void", "check", ImmutableList.of()); - assertThat(y, isPresent()); - assertThat(y, isRenamed()); + assertThat(y, isPresentAndRenamed()); assertEquals("y", y.getFinalName()); } }
diff --git a/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java b/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java index d138e1b..5da3af5 100644 --- a/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java +++ b/src/test/java/com/android/tools/r8/naming/b116840216/ReserveOuterClassNameTest.java
@@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.naming.b116840216; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import com.android.tools.r8.CompatProguardCommandBuilder; @@ -89,25 +88,19 @@ CodeInspector inspector = new CodeInspector(processedApp); ClassSubject mainSubject = inspector.clazz(mainClass); - assertThat(mainSubject, isPresent()); - assertThat(mainSubject, not(isRenamed())); + assertThat(mainSubject, isPresentAndNotRenamed()); MethodSubject mainMethod = mainSubject.mainMethod(); - assertThat(mainMethod, isPresent()); - assertThat(mainMethod, not(isRenamed())); + assertThat(mainMethod, isPresentAndNotRenamed()); ClassSubject outer = inspector.clazz(Outer.class); - assertThat(outer, isPresent()); - assertThat(outer, not(isRenamed())); + assertThat(outer, isPresentAndNotRenamed()); MethodSubject bar = outer.method("void", "bar", ImmutableList.of()); - assertThat(bar, isPresent()); - assertThat(bar, isRenamed()); + assertThat(bar, isPresentAndRenamed()); ClassSubject inner = inspector.clazz(Outer.Inner.class); - assertThat(inner, isPresent()); - assertThat(inner, not(isRenamed())); + assertThat(inner, isPresentAndNotRenamed()); MethodSubject foo = inner.method("void", "foo", ImmutableList.of()); - assertThat(foo, isPresent()); - assertThat(foo, isRenamed()); + assertThat(foo, isPresentAndRenamed()); } @Test
diff --git a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java index e1cd05a..18d0719 100644 --- a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java +++ b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
@@ -4,9 +4,9 @@ package com.android.tools.r8.naming.b124357885; -import static com.android.tools.r8.utils.codeinspector.Matchers.isNotRenamed; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -68,23 +68,25 @@ @Test public void test() throws Exception { - R8TestCompileResult compileResult = testForR8(Backend.DEX) - .addProgramClasses(Main.class, Service.class, Foo.class, FooImpl.class) - .addKeepMainRule(Main.class) - .addKeepRules("-keepattributes Signature,InnerClasses,EnclosingMethod") - .minification(minification) - .compile() - .inspect(inspector -> { - assertThat(inspector.clazz(Main.class), isNotRenamed()); - assertThat(inspector.clazz(Service.class), isRenamed(minification)); - assertThat(inspector.clazz(Foo.class), not(isPresent())); - assertThat(inspector.clazz(FooImpl.class), isRenamed(minification)); - // TODO(124477502): Using uniqueMethodWithName("fooList") does not work. - assertEquals(1, inspector.clazz(Service.class).allMethods().size()); - MethodSubject fooList = inspector.clazz(Service.class).allMethods().get(0); - AnnotationSubject signature = fooList.annotation("dalvik.annotation.Signature"); - checkSignatureAnnotation(inspector, signature); - }); + R8TestCompileResult compileResult = + testForR8(Backend.DEX) + .addProgramClasses(Main.class, Service.class, Foo.class, FooImpl.class) + .addKeepMainRule(Main.class) + .addKeepRules("-keepattributes Signature,InnerClasses,EnclosingMethod") + .minification(minification) + .compile() + .inspect( + inspector -> { + assertThat(inspector.clazz(Main.class), isPresentAndNotRenamed()); + assertThat(inspector.clazz(Service.class), isPresentAndRenamed(minification)); + assertThat(inspector.clazz(Foo.class), not(isPresent())); + assertThat(inspector.clazz(FooImpl.class), isPresentAndRenamed(minification)); + // TODO(124477502): Using uniqueMethodWithName("fooList") does not work. + assertEquals(1, inspector.clazz(Service.class).allMethods().size()); + MethodSubject fooList = inspector.clazz(Service.class).allMethods().get(0); + AnnotationSubject signature = fooList.annotation("dalvik.annotation.Signature"); + checkSignatureAnnotation(inspector, signature); + }); String fooImplFinalName = compileResult.inspector().clazz(FooImpl.class).getFinalName();
diff --git a/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java b/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java index 2f909be..78f0d0c 100644 --- a/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java +++ b/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.naming.b126592786; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -55,19 +55,20 @@ "}", "-keepattributes InnerClasses,EnclosingMethod,Signature ") .compile() - .inspect(inspector -> { - String genericTypeDescriptor = "Ljava/lang/Object;"; - if (genericTypeLive) { - ClassSubject genericType = inspector.clazz(GenericType.class); - assertThat(genericType, isRenamed(minify)); - genericTypeDescriptor = genericType.getFinalDescriptor(); - } - String expectedSignature = "Ljava/util/List<" + genericTypeDescriptor + ">;"; - FieldSubject list = inspector.clazz(A.class).uniqueFieldWithName("list"); - assertThat(list, isPresent()); - assertThat(list.getSignatureAnnotation(), isPresent()); - assertEquals(expectedSignature, list.getSignatureAnnotationValue()); - }) + .inspect( + inspector -> { + String genericTypeDescriptor = "Ljava/lang/Object;"; + if (genericTypeLive) { + ClassSubject genericType = inspector.clazz(GenericType.class); + assertThat(genericType, isPresentAndRenamed(minify)); + genericTypeDescriptor = genericType.getFinalDescriptor(); + } + String expectedSignature = "Ljava/util/List<" + genericTypeDescriptor + ">;"; + FieldSubject list = inspector.clazz(A.class).uniqueFieldWithName("list"); + assertThat(list, isPresent()); + assertThat(list.getSignatureAnnotation(), isPresent()); + assertEquals(expectedSignature, list.getSignatureAnnotationValue()); + }) .run(mainClass) .assertSuccess(); }
diff --git a/src/test/java/com/android/tools/r8/naming/b128656974/B128656974.java b/src/test/java/com/android/tools/r8/naming/b128656974/B128656974.java index f063f9e..56ed80c 100644 --- a/src/test/java/com/android/tools/r8/naming/b128656974/B128656974.java +++ b/src/test/java/com/android/tools/r8/naming/b128656974/B128656974.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming.b128656974; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNotEquals; @@ -40,8 +40,7 @@ ClassSubject greetingBase = inspector.clazz(Greeting.getGreetingBase()); assertThat(greetingBase, isPresent()); FieldSubject greeting = greetingBase.uniqueFieldWithName("greeting"); - assertThat(greeting, isPresent()); - assertThat(greeting, isRenamed()); + assertThat(greeting, isPresentAndRenamed()); assertNotEquals("a", greeting.getFinalName()); }); } @@ -88,8 +87,7 @@ ClassSubject base = inspector.clazz(TestClassBase.class); assertThat(base, isPresent()); MethodSubject foo = base.uniqueMethodWithName("foo"); - assertThat(foo, isPresent()); - assertThat(foo, isRenamed()); + assertThat(foo, isPresentAndRenamed()); assertNotEquals("a", foo.getFinalName()); }); }
diff --git a/src/test/java/com/android/tools/r8/naming/b130791310/B130791310.java b/src/test/java/com/android/tools/r8/naming/b130791310/B130791310.java index d8f3910..bb27506 100644 --- a/src/test/java/com/android/tools/r8/naming/b130791310/B130791310.java +++ b/src/test/java/com/android/tools/r8/naming/b130791310/B130791310.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.naming.b130791310; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeFalse; @@ -110,13 +110,11 @@ private void inspect(CodeInspector inspector, boolean isR8) { ClassSubject holder = inspector.clazz(SomeLogic.class); - assertThat(holder, isPresent()); - assertThat(holder, not(isRenamed())); + assertThat(holder, isPresentAndNotRenamed()); MethodSubject someMethod = holder.uniqueMethodWithName("someMethod"); if (isR8) { if (onlyForceInlining) { - assertThat(someMethod, isPresent()); - assertThat(someMethod, not(isRenamed())); + assertThat(someMethod, isPresentAndNotRenamed()); } else { assertThat(someMethod, not(isPresent())); } @@ -126,8 +124,7 @@ // method signature modification. assertThat(someMethod, not(isPresent())); } else { - assertThat(someMethod, isPresent()); - assertThat(someMethod, not(isRenamed())); + assertThat(someMethod, isPresentAndNotRenamed()); } } }
diff --git a/src/test/java/com/android/tools/r8/naming/b133686361/AlreadyRenamedAbstractMethodRenamingTest.java b/src/test/java/com/android/tools/r8/naming/b133686361/AlreadyRenamedAbstractMethodRenamingTest.java index d104210..7cda3cd 100644 --- a/src/test/java/com/android/tools/r8/naming/b133686361/AlreadyRenamedAbstractMethodRenamingTest.java +++ b/src/test/java/com/android/tools/r8/naming/b133686361/AlreadyRenamedAbstractMethodRenamingTest.java
@@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.naming.b133686361; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -88,26 +87,20 @@ private void inspect(CodeInspector inspector) { ClassSubject base = inspector.clazz(Base.class); - assertThat(base, isPresent()); - assertThat(base, isRenamed()); + assertThat(base, isPresentAndRenamed()); MethodSubject a = base.uniqueMethodWithName("a"); - assertThat(a, isPresent()); - assertThat(a, not(isRenamed())); + assertThat(a, isPresentAndNotRenamed()); ClassSubject sub1 = inspector.clazz(Sub1.class); - assertThat(sub1, isPresent()); - assertThat(sub1, isRenamed()); + assertThat(sub1, isPresentAndRenamed()); MethodSubject aInSub1 = sub1.uniqueMethodWithName("a"); - assertThat(aInSub1, isPresent()); - assertThat(aInSub1, not(isRenamed())); + assertThat(aInSub1, isPresentAndNotRenamed()); assertEquals(a.getFinalName(), aInSub1.getFinalName()); ClassSubject sub2 = inspector.clazz(Sub1.class); - assertThat(sub2, isPresent()); - assertThat(sub2, isRenamed()); + assertThat(sub2, isPresentAndRenamed()); MethodSubject aInSub2 = sub2.uniqueMethodWithName("a"); - assertThat(aInSub2, isPresent()); - assertThat(aInSub2, not(isRenamed())); + assertThat(aInSub2, isPresentAndNotRenamed()); assertEquals(a.getFinalName(), aInSub2.getFinalName()); } }
diff --git a/src/test/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonSwitchTest.java b/src/test/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonSwitchTest.java index 97a96cc6..81038cf 100644 --- a/src/test/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonSwitchTest.java +++ b/src/test/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonSwitchTest.java
@@ -4,8 +4,7 @@ package com.android.tools.r8.naming.identifiernamestring; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -51,8 +50,7 @@ private void verifyClassesHaveBeenMinified(CodeInspector inspector) { for (Class<?> clazz : ImmutableList.of(A.class, B.class, C.class)) { ClassSubject classSubject = inspector.clazz(clazz); - assertThat(classSubject, isPresent()); - assertThat(classSubject, isRenamed()); + assertThat(classSubject, isPresentAndRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/proguard/NonExistingConfigFileTest.java b/src/test/java/com/android/tools/r8/proguard/NonExistingConfigFileTest.java index 7d0dc70..b241eff 100644 --- a/src/test/java/com/android/tools/r8/proguard/NonExistingConfigFileTest.java +++ b/src/test/java/com/android/tools/r8/proguard/NonExistingConfigFileTest.java
@@ -3,8 +3,7 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.proguard; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; @@ -28,11 +27,11 @@ .addKeepRuleFiles(pg) .compile() .assertNoMessages() - .inspect(inspector -> { - ClassSubject clazz = inspector.clazz(TestClass.class); - assertThat(clazz, isPresent()); - assertThat(clazz, isRenamed()); - }); + .inspect( + inspector -> { + ClassSubject clazz = inspector.clazz(TestClass.class); + assertThat(clazz, isPresentAndRenamed()); + }); } @Test
diff --git a/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java b/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java index b7017e7..ddaf47f 100644 --- a/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java +++ b/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -75,11 +75,9 @@ ); CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config); ClassSubject classSubject = codeInspector.clazz(B111974287.class); - assertThat(classSubject, isPresent()); - assertThat(classSubject, not(isRenamed())); + assertThat(classSubject, isPresentAndNotRenamed()); FieldSubject fieldSubject = classSubject.field(B111974287.class.getTypeName(), "self"); - assertThat(fieldSubject, isPresent()); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); fieldSubject = classSubject.field(B111974287.class.getTypeName() + "[]", "clones"); // TODO(b/111974287): Proguard6 kept and renamed the field with array type. if (shrinker == Shrinker.PROGUARD6) { @@ -97,16 +95,14 @@ ); CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config); ClassSubject classSubject = codeInspector.clazz(B111974287.class); - assertThat(classSubject, isPresent()); - assertThat(classSubject, not(isRenamed())); + assertThat(classSubject, isPresentAndNotRenamed()); DexClass clazz = classSubject.getDexProgramClass(); assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods()); for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) { assertTrue(encodedMethod.method.name.toString().startsWith("foo")); MethodSubject methodSubject = classSubject.method(MethodSignature.fromDexMethod(encodedMethod.method)); - assertThat(methodSubject, isPresent()); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); } } @@ -119,14 +115,11 @@ ); CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config); ClassSubject classSubject = codeInspector.clazz(B111974287.class); - assertThat(classSubject, isPresent()); - assertThat(classSubject, not(isRenamed())); + assertThat(classSubject, isPresentAndNotRenamed()); FieldSubject fieldSubject = classSubject.field(B111974287.class.getTypeName(), "self"); - assertThat(fieldSubject, isPresent()); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); fieldSubject = classSubject.field(B111974287.class.getTypeName() + "[]", "clones"); - assertThat(fieldSubject, isPresent()); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); } @Test @@ -138,16 +131,14 @@ ); CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config); ClassSubject classSubject = codeInspector.clazz(B111974287.class); - assertThat(classSubject, isPresent()); - assertThat(classSubject, not(isRenamed())); + assertThat(classSubject, isPresentAndNotRenamed()); DexClass clazz = classSubject.getDexProgramClass(); assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods()); for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) { assertTrue(encodedMethod.method.name.toString().startsWith("foo")); MethodSubject methodSubject = classSubject.method(MethodSignature.fromDexMethod(encodedMethod.method)); - assertThat(methodSubject, isPresent()); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); } } @@ -160,16 +151,14 @@ ); CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config); ClassSubject classSubject = codeInspector.clazz(B111974287.class); - assertThat(classSubject, isPresent()); - assertThat(classSubject, not(isRenamed())); + assertThat(classSubject, isPresentAndNotRenamed()); DexClass clazz = classSubject.getDexProgramClass(); assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods()); for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) { assertTrue(encodedMethod.method.name.toString().startsWith("foo")); MethodSubject methodSubject = classSubject.method(MethodSignature.fromDexMethod(encodedMethod.method)); - assertThat(methodSubject, isPresent()); - assertThat(methodSubject, not(isRenamed())); + assertThat(methodSubject, isPresentAndNotRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java b/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java index f9a6bea..7015177 100644 --- a/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java +++ b/src/test/java/com/android/tools/r8/shaking/AtomicFieldUpdaterTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -50,8 +50,8 @@ // Verify that the field is still there. CodeInspector inspector = new CodeInspector(output, proguardMapPath); ClassSubject classSubject = inspector.clazz(AtomicFieldUpdaterTestClass.A.class.getName()); - assertThat(classSubject, isRenamed()); - assertThat(classSubject.field("int", "field"), isRenamed()); + assertThat(classSubject, isPresentAndRenamed()); + assertThat(classSubject.field("int", "field"), isPresentAndRenamed()); // Check that the code runs. assertEquals( runOnJava(AtomicFieldUpdaterTestClass.class),
diff --git a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java index ac18813..3c15d88 100644 --- a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java +++ b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -173,7 +173,7 @@ .inspect( inspector -> { FieldSubject fld = inspector.clazz(fieldHolder.name).uniqueFieldWithName(fieldName); - assertThat(fld, isRenamed()); + assertThat(fld, isPresentAndRenamed()); ClassSubject classSubject = inspector.clazz(clazz.name); assertThat(classSubject, isPresent()); @@ -370,7 +370,7 @@ boolean isR8) { FieldSubject fld = inspector.clazz(fieldHolder.name).uniqueFieldWithName(fieldName); if (isR8) { - assertThat(fld, isRenamed()); + assertThat(fld, isPresentAndRenamed()); } else { assertThat(fld, isPresent()); }
diff --git a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java new file mode 100644 index 0000000..d989fbf --- /dev/null +++ b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
@@ -0,0 +1,297 @@ +// 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.shaking; + +import static com.android.tools.r8.DiagnosticsMatcher.diagnosticException; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import com.android.tools.r8.CompilationFailedException; +import com.android.tools.r8.R8; +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.utils.codeinspector.ClassSubject; +import com.android.tools.r8.utils.codeinspector.CodeInspector; +import com.android.tools.r8.utils.codeinspector.FoundMethodSubject; +import com.android.tools.r8.utils.codeinspector.MethodSubject; +import com.android.tools.r8.utils.graphinspector.GraphInspector; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; +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 KeepAnnotatedMemberTest extends TestBase { + + private static final Path R8_JAR = Paths.get(ToolHelper.THIRD_PARTY_DIR, "r8", "r8.jar"); + private static final String ABSENT_ANNOTATION = "com.android.tools.r8.MissingAnnotation"; + private static final String PRESENT_ANNOTATION = + "com.android.tools.r8.com.google.common.annotations.VisibleForTesting"; + + private static final String CLASS_WITH_ANNOTATED_METHOD = + "com.android.tools.r8.com.google.common.math.IntMath"; + + private static final String ANNOTATED_METHOD = "lessThanBranchFree"; + + @Parameters(name = "{0}") + public static TestParametersCollection data() { + return getTestParameters().withNoneRuntime().build(); + } + + public KeepAnnotatedMemberTest(TestParameters parameters) { + parameters.assertNoneRuntime(); + } + + @Test + public void testPresence() throws Exception { + CodeInspector inspector = new CodeInspector(R8_JAR); + assertThat(inspector.clazz(ABSENT_ANNOTATION), not(isPresent())); + assertThat(inspector.clazz(PRESENT_ANNOTATION), isPresent()); + ClassSubject clazz = inspector.clazz(CLASS_WITH_ANNOTATED_METHOD); + MethodSubject method = clazz.uniqueMethodWithName(ANNOTATED_METHOD); + assertThat(method, isPresent()); + } + + // TODO(b/159966986): A general keep rule should not cause compiler assertion errors. + @Test(expected = CompilationFailedException.class) + public void testPresentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .addKeepRules("-keep class * { @" + PRESENT_ANNOTATION + " *; }") + .compileWithExpectedDiagnostics( + diagnostics -> + diagnostics.assertErrorsMatch(diagnosticException(AssertionError.class))); + } + + @Test + public void testPresentAnnotationSplit() throws Exception { + // These rules should be equivalent to the above. + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .addKeepRules( + "-keep class *", "-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *; }") + .compile(); + } + + @Test + public void testWithMembersAbsentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .allowUnusedProguardConfigurationRules() + .addKeepRules("-keepclasseswithmembers class * { @" + ABSENT_ANNOTATION + " *; }") + .compile() + .inspect(inspector -> assertEquals(0, inspector.allClasses().size())); + } + + @Test + public void testWithMembersPresentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .addKeepRules("-keepclasseswithmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }") + .compile() + .inspect( + inspector -> { + ClassSubject clazz = inspector.clazz(CLASS_WITH_ANNOTATED_METHOD); + assertThat(clazz, isPresent()); + assertThat(clazz.uniqueMethodWithName(ANNOTATED_METHOD), isPresent()); + }); + } + + @Test + public void testUnsatisfiedClassMembersPresentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + // TODO(b/159971974): Technically this rule does not hit anything and should fail due to + // missing allowUnusedProguardConfigurationRules() + .addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }") + .compile() + .inspect(inspector -> assertEquals(0, inspector.allClasses().size())); + } + + @Test + public void testSatisfiedClassMembersPresentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD) + .addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }") + .compile() + .inspect( + inspector -> { + assertEquals(1, inspector.allClasses().size()); + List<FoundMethodSubject> methods = + inspector.clazz(CLASS_WITH_ANNOTATED_METHOD).allMethods(); + assertEquals( + 1, methods.stream().filter(m -> m.getOriginalName().equals("<init>")).count()); + assertEquals( + 1, + methods.stream() + .filter(m -> m.getOriginalName().equals(ANNOTATED_METHOD)) + .count()); + assertEquals(2, methods.size()); + }); + } + + @Test + public void testUnsatisfiedConditionalPresentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .allowUnusedProguardConfigurationRules() + .addKeepRules("-if class * -keep class <1> { @" + PRESENT_ANNOTATION + " *** *(...); }") + .compile() + .inspect(inspector -> assertEquals(0, inspector.allClasses().size())); + } + + @Test + public void testSatisfiedConditionalPresentAnnotation() throws Exception { + testForR8(Backend.CF) + .addProgramFiles(R8_JAR) + .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD) + .addKeepRules("-if class * -keep class <1> { @" + PRESENT_ANNOTATION + " *** *(...); }") + .compile() + .inspect( + inspector -> { + assertEquals(1, inspector.allClasses().size()); + List<FoundMethodSubject> methods = + inspector.clazz(CLASS_WITH_ANNOTATED_METHOD).allMethods(); + assertEquals( + 1, methods.stream().filter(m -> m.getOriginalName().equals("<init>")).count()); + // TODO(b/132318609): This should have the annotated method, but does not due to the + // annotation being removed. + assertEquals( + 0, + methods.stream() + .filter(m -> m.getOriginalName().equals(ANNOTATED_METHOD)) + .count()); + assertEquals(1, methods.size()); + }); + } + + @Test + public void testConditionalEqualsKeepClassMembers() throws Exception { + GraphInspector referenceInspector = + testForR8(Backend.CF) + .enableGraphInspector() + .addProgramFiles(R8_JAR) + .addKeepMainRule(R8.class) + .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD) + // TODO(b/132318609): Remove keep annotation once fixed. + .addKeepClassRules(PRESENT_ANNOTATION) + .addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }") + .compile() + .graphInspector(); + + GraphInspector ifThenKeepClassMembersInspector = + testForR8(Backend.CF) + .enableGraphInspector() + .addProgramFiles(R8_JAR) + .addKeepMainRule(R8.class) + .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD) + // TODO(b/132318609): Remove keep annotation once fixed. + .addKeepClassRules(PRESENT_ANNOTATION) + .addKeepRules( + "-if class * " + + "-keepclassmembers class <1> { @" + + PRESENT_ANNOTATION + + " *** *(...); }") + .compile() + .graphInspector(); + // TODO(b/159418523): It appears that the insertion in never-inline causes additional retention. + assertRetainedClassesEqual(referenceInspector, ifThenKeepClassMembersInspector, false, true); + + GraphInspector ifThenKeepClassesWithMembersInspector = + testForR8(Backend.CF) + .enableGraphInspector() + .addProgramFiles(R8_JAR) + .addKeepMainRule(R8.class) + .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD) + // TODO(b/132318609): Remove keep annotation once fixed. + .addKeepClassRules(PRESENT_ANNOTATION) + .addKeepRules( + "-if class * " + + "-keepclasseswithmembers class <1> { @" + + PRESENT_ANNOTATION + + " *** *(...); }") + .compile() + .graphInspector(); + // TODO(b/159418523): It appears that the insertion in never-inline causes additional retention. + assertRetainedClassesEqual( + referenceInspector, ifThenKeepClassesWithMembersInspector, false, true); + + GraphInspector ifHasMemberThenKeepClassInspector = + testForR8(Backend.CF) + .enableGraphInspector() + .addProgramFiles(R8_JAR) + .addKeepMainRule(R8.class) + .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD) + // TODO(b/132318609): Remove keep annotation once fixed. + .addKeepClassRules(PRESENT_ANNOTATION) + .addKeepRules( + "-if class * { @" + + PRESENT_ANNOTATION + + " *** *(...); } " + + "-keep class <1> { @" + + PRESENT_ANNOTATION + + " *** <2>(...); }") + .compile() + .graphInspector(); + // TODO(b/159418523): It appears that the insertion in never-inline causes additional retention. + // Also, here neither is a subset of the other. That also appears wrong. + assertRetainedClassesEqual(referenceInspector, ifHasMemberThenKeepClassInspector, true, true); + } + + private void assertRetainedClassesEqual( + GraphInspector referenceResult, + GraphInspector conditionalResult, + boolean expectReferenceIsLarger, + boolean expectConditionalIsLarger) { + Set<String> referenceClasses = + new TreeSet<>( + referenceResult.codeInspector().allClasses().stream() + .map(c -> c.getOriginalName()) + .collect(Collectors.toSet())); + + Set<String> conditionalClasses = + conditionalResult.codeInspector().allClasses().stream() + .map(c -> c.getOriginalName()) + .collect(Collectors.toSet()); + { + SetView<String> notInReference = Sets.difference(conditionalClasses, referenceClasses); + if (expectConditionalIsLarger) { + assertFalse("Expected classes in -if rule to retain more.", notInReference.isEmpty()); + } else { + assertEquals( + "Classes in -if rule that are not in -keepclassmembers rule", + Collections.emptySet(), + notInReference); + } + } + { + SetView<String> notInConditional = Sets.difference(referenceClasses, conditionalClasses); + if (expectReferenceIsLarger) { + assertFalse( + "Expected classes in -keepclassmembers rule to retain more.", + notInConditional.isEmpty()); + } else { + assertEquals( + "Classes in -keepclassmembers rule that are not in -if rule", + Collections.emptySet(), + new TreeSet<>(notInConditional)); + } + } + } +}
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java index 8673412..bee167f 100644 --- a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java +++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
@@ -5,7 +5,7 @@ package com.android.tools.r8.shaking; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -183,7 +183,7 @@ if (!enableClassInlining && !enableVerticalClassMerging) { CodeInspector inspector = compiled.inspector(); ClassSubject classSubject = inspector.clazz(B.class.getName()); - assertThat(classSubject, isRenamed()); + assertThat(classSubject, isPresentAndRenamed()); assertThat(classSubject.method("void", "m1", ImmutableList.of()), isPresent()); assertThat(classSubject.method("void", "m2", ImmutableList.of()), not(isPresent())); assertThat(classSubject.method("void", "m3", ImmutableList.of()), isPresent());
diff --git a/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java b/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java index 5cdbd87..59c649b 100644 --- a/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java +++ b/src/test/java/com/android/tools/r8/shaking/ParameterTypeTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -136,14 +136,14 @@ .inspector(); ClassSubject superInterface1 = inspector.clazz(B112452064SuperInterface1.class); - assertThat(superInterface1, isRenamed()); + assertThat(superInterface1, isPresentAndRenamed()); MethodSubject foo = superInterface1.uniqueMethodWithName("foo"); assertThat(foo, not(isPresent())); ClassSubject superInterface2 = inspector.clazz(B112452064SuperInterface2.class); if (enableVerticalClassMerging) { assertThat(superInterface2, not(isPresent())); } else { - assertThat(superInterface2, isRenamed()); + assertThat(superInterface2, isPresentAndRenamed()); } MethodSubject bar = superInterface2.uniqueMethodWithName("bar"); assertThat(bar, not(isPresent())); @@ -152,7 +152,7 @@ assertThat(subInterface, not(isPresent())); } else { assertThat(subInterface, isPresent()); - assertThat(subInterface, isRenamed()); + assertThat(subInterface, isPresentAndRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java b/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java index 4c25b86..98b7f80 100644 --- a/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java +++ b/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeTrue; @@ -93,7 +93,7 @@ .inspect( inspector -> { ClassSubject returnType = inspector.clazz(B112517039ReturnType.class); - assertThat(returnType, isRenamed()); + assertThat(returnType, isPresentAndRenamed()); }); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java index d24d8c1..edd818e 100644 --- a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java +++ b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java
@@ -1,7 +1,7 @@ package com.android.tools.r8.shaking.annotations; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static org.hamcrest.MatcherAssert.assertThat; @@ -59,18 +59,18 @@ inspector -> { ClassSubject clazz = inspector.clazz(TestClass.class); assertThat(clazz, isPresent()); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); FieldSubject field = clazz.uniqueFieldWithName("field"); assertThat(field, isPresent()); assertThat(field.annotation(FieldAnnotation.class.getTypeName()), isPresent()); - assertThat(inspector.clazz(FieldAnnotationUse.class), isRenamed()); + assertThat(inspector.clazz(FieldAnnotationUse.class), isPresentAndRenamed()); FieldSubject staticField = clazz.uniqueFieldWithName("staticField"); assertThat(staticField, isPresent()); assertThat( staticField.annotation(StaticFieldAnnotation.class.getTypeName()), isPresent()); - assertThat(inspector.clazz(StaticFieldAnnotationUse.class), isRenamed()); + assertThat(inspector.clazz(StaticFieldAnnotationUse.class), isPresentAndRenamed()); }) .run(MainClass.class) .assertSuccess();
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java index 84ceffa..c975c82 100644 --- a/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java +++ b/src/test/java/com/android/tools/r8/shaking/annotations/ReflectiveAnnotationUseTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking.annotations; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; @@ -105,20 +105,15 @@ .assertSuccessWithOutput(JAVA_OUTPUT) .inspector(); ClassSubject clazz = inspector.clazz(ANNOTATION_NAME); - assertThat(clazz, isPresent()); - assertThat(clazz, not(isRenamed())); + assertThat(clazz, isPresentAndNotRenamed()); MethodSubject f1 = clazz.uniqueMethodWithName("f1"); - assertThat(f1, isPresent()); - assertThat(f1, not(isRenamed())); + assertThat(f1, isPresentAndNotRenamed()); MethodSubject f2 = clazz.uniqueMethodWithName("f2"); - assertThat(f2, isPresent()); - assertThat(f2, not(isRenamed())); + assertThat(f2, isPresentAndNotRenamed()); MethodSubject f3 = clazz.uniqueMethodWithName("f3"); - assertThat(f3, isPresent()); - assertThat(f3, not(isRenamed())); + assertThat(f3, isPresentAndNotRenamed()); MethodSubject f4 = clazz.uniqueMethodWithName("f4"); - assertThat(f4, isPresent()); - assertThat(f4, not(isRenamed())); + assertThat(f4, isPresentAndNotRenamed()); ClassSubject impl = inspector.clazz(IMPL_CLASS_NAME); assertThat(impl, isPresent()); @@ -152,11 +147,9 @@ assertThat(clazz, isPresent()); assertEquals(minify, clazz.isRenamed()); MethodSubject f1 = clazz.uniqueMethodWithName("f1"); - assertThat(f1, isPresent()); - assertThat(f1, not(isRenamed())); + assertThat(f1, isPresentAndNotRenamed()); MethodSubject f2 = clazz.uniqueMethodWithName("f2"); - assertThat(f2, isPresent()); - assertThat(f2, not(isRenamed())); + assertThat(f2, isPresentAndNotRenamed()); MethodSubject f3 = clazz.uniqueMethodWithName("f3"); assertThat(f3, not(isPresent())); MethodSubject f4 = clazz.uniqueMethodWithName("f4"); @@ -190,11 +183,9 @@ assertThat(clazz, isPresent()); assertEquals(minify, clazz.isRenamed()); MethodSubject f1 = clazz.uniqueMethodWithName("f1"); - assertThat(f1, isPresent()); - assertThat(f1, not(isRenamed())); + assertThat(f1, isPresentAndNotRenamed()); MethodSubject f2 = clazz.uniqueMethodWithName("f2"); - assertThat(f2, isPresent()); - assertThat(f2, not(isRenamed())); + assertThat(f2, isPresentAndNotRenamed()); MethodSubject f3 = clazz.uniqueMethodWithName("f3"); assertThat(f3, not(isPresent())); MethodSubject f4 = clazz.uniqueMethodWithName("f4");
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepInnerClassesEnclosingMethodAnnotationsTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepInnerClassesEnclosingMethodAnnotationsTest.java index 3b060f0..87c3303 100644 --- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepInnerClassesEnclosingMethodAnnotationsTest.java +++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepInnerClassesEnclosingMethodAnnotationsTest.java
@@ -6,7 +6,8 @@ import static com.android.tools.r8.utils.codeinspector.Matchers.isMemberClass; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -123,8 +124,8 @@ "-keepattributes InnerClasses,EnclosingMethod", "-keep class **Outer*", keepMainProguardConfiguration(Main.class))); - assertThat(result.outer, not(isRenamed())); - assertThat(result.inner, not(isRenamed())); + assertThat(result.outer, isPresentAndNotRenamed()); + assertThat(result.inner, isPresentAndNotRenamed()); assertThat(result.inner, isMemberClass()); fullInnerClassesEnclosingMethodInformation(result); } @@ -134,8 +135,8 @@ TestResult result = runShrinker( ImmutableList.of("-keep class **Outer*", keepMainProguardConfiguration(Main.class))); - assertThat(result.outer, not(isRenamed())); - assertThat(result.inner, not(isRenamed())); + assertThat(result.outer, isPresentAndNotRenamed()); + assertThat(result.inner, isPresentAndNotRenamed()); assertThat(result.inner, not(isMemberClass())); noInnerClassesEnclosingMethodInformation(result); } @@ -148,8 +149,8 @@ "-keepattributes InnerClasses,EnclosingMethod", "-keep class **Outer$Inner", keepMainProguardConfiguration(Main.class))); - assertThat(result.outer, not(isRenamed())); - assertThat(result.inner, not(isRenamed())); + assertThat(result.outer, isPresentAndNotRenamed()); + assertThat(result.inner, isPresentAndNotRenamed()); assertThat(result.inner, isMemberClass()); fullInnerClassesEnclosingMethodInformation(result); } @@ -162,8 +163,8 @@ "-keepattributes InnerClasses,EnclosingMethod", "-keep class **Outer", keepMainProguardConfiguration(Main.class))); - assertThat(result.outer, not(isRenamed())); - assertThat(result.inner, isRenamed()); + assertThat(result.outer, isPresentAndNotRenamed()); + assertThat(result.inner, isPresentAndRenamed()); assertThat(result.inner, isMemberClass()); fullInnerClassesEnclosingMethodInformation(result); }
diff --git a/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java b/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java index 15fba7f..686c35b 100644 --- a/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java +++ b/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java
@@ -3,8 +3,7 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking.b113138046; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -63,7 +62,7 @@ "void", "foo", ImmutableList.of(Handler.class.getCanonicalName())); assertEquals(expectedFooPresence, nativeFoo.isPresent()); if (expectedFooPresence) { - assertThat(nativeFoo, not(isRenamed())); + assertThat(nativeFoo, isPresentAndNotRenamed()); DexEncodedMethod method = nativeFoo.getMethod(); assertTrue(method.accessFlags.isNative()); assertNull(method.getCode());
diff --git a/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java b/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java index eebb7d5..32a861a 100644 --- a/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java +++ b/src/test/java/com/android/tools/r8/shaking/defaultmethods/DefaultMethodsTest.java
@@ -4,67 +4,53 @@ package com.android.tools.r8.shaking.defaultmethods; +import static com.android.tools.r8.utils.codeinspector.Matchers.isAbstract; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import com.android.tools.r8.ClassFileConsumer; -import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.R8Command; import com.android.tools.r8.TestBase; -import com.android.tools.r8.ToolHelper; -import com.android.tools.r8.origin.Origin; -import com.android.tools.r8.utils.AndroidApiLevel; -import com.android.tools.r8.utils.AndroidApp; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestParametersCollection; +import com.android.tools.r8.utils.ThrowingConsumer; 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.ImmutableList; import java.util.List; -import java.util.function.Consumer; 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 DefaultMethodsTest extends TestBase { - private Backend backend; + private final TestParameters parameters; - @Parameterized.Parameters(name = "Backend: {0}") - public static Backend[] data() { - return ToolHelper.getBackends(); + @Parameters(name = "{0}") + public static TestParametersCollection data() { + return getTestParameters().withAllRuntimesAndApiLevels().build(); } - public DefaultMethodsTest(Backend backend) { - this.backend = backend; + public DefaultMethodsTest(TestParameters parameters) { + this.parameters = parameters; } - private void runTest(List<String> additionalKeepRules, Consumer<CodeInspector> inspection) + private void runTest( + List<String> additionalKeepRules, + ThrowingConsumer<CodeInspector, RuntimeException> inspection) throws Exception { - R8Command.Builder builder = R8Command.builder(); - builder.addProgramFiles(ToolHelper.getClassFileForTestClass(InterfaceWithDefaultMethods.class)); - builder.addProgramFiles(ToolHelper.getClassFileForTestClass(ClassImplementingInterface.class)); - builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestClass.class)); - if (backend == Backend.DEX) { - builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer()); - int apiLevel = AndroidApiLevel.O.getLevel(); - builder.setMinApiLevel(apiLevel); - builder.addLibraryFiles(ToolHelper.getAndroidJar(apiLevel)); - } else { - assert backend == Backend.CF; - builder.setProgramConsumer(ClassFileConsumer.emptyConsumer()); - builder.addLibraryFiles(ToolHelper.getJava8RuntimeJar()); - } - // Always keep main in the test class, so the output never becomes empty. - builder.addProguardConfiguration(ImmutableList.of( - "-keep class " + TestClass.class.getCanonicalName() + "{", - " public static void main(java.lang.String[]);", - "}", - "-dontobfuscate"), - Origin.unknown()); - builder.addProguardConfiguration(additionalKeepRules, Origin.unknown()); - AndroidApp app = ToolHelper.runR8(builder.build(), o -> o.enableClassInlining = false); - inspection.accept(new CodeInspector(app)); + testForR8(parameters.getBackend()) + .addProgramClasses( + InterfaceWithDefaultMethods.class, ClassImplementingInterface.class, TestClass.class) + .setMinApi(parameters.getApiLevel()) + .addKeepMainRule(TestClass.class) + .addKeepRules(additionalKeepRules) + .noMinification() + .compile() + .inspect(inspection); } private void interfaceNotKept(CodeInspector inspector) { @@ -73,53 +59,98 @@ private void defaultMethodNotKept(CodeInspector inspector) { ClassSubject clazz = inspector.clazz(InterfaceWithDefaultMethods.class); - assertTrue(clazz.isPresent()); - assertFalse(clazz.method("int", "method", ImmutableList.of()).isPresent()); + assertThat(clazz, isPresent()); + assertThat(clazz.method("int", "method", ImmutableList.of()), not(isPresent())); } private void defaultMethodKept(CodeInspector inspector) { ClassSubject clazz = inspector.clazz(InterfaceWithDefaultMethods.class); - assertTrue(clazz.isPresent()); + assertThat(clazz, isPresent()); MethodSubject method = clazz.method("int", "method", ImmutableList.of()); - assertTrue(method.isPresent()); - assertFalse(method.isAbstract()); + assertThat(method, isPresent()); + ClassSubject companionClass = clazz.toCompanionClass(); + if (parameters.canUseDefaultAndStaticInterfaceMethods()) { + assertThat(method, not(isAbstract())); + assertThat(companionClass, not(isPresent())); + } else { + assertThat(method, isAbstract()); + assertThat(companionClass, isPresent()); + MethodSubject defaultMethod = method.toMethodOnCompanionClass(); + assertThat(defaultMethod, isPresent()); + } + } + + private void defaultMethodKeptWithoutCompanionClass(CodeInspector inspector) { + ClassSubject clazz = inspector.clazz(InterfaceWithDefaultMethods.class); + assertThat(clazz, isPresent()); + MethodSubject method = clazz.method("int", "method", ImmutableList.of()); + assertThat(method, isPresent()); + ClassSubject companionClass = clazz.toCompanionClass(); + if (parameters.canUseDefaultAndStaticInterfaceMethods()) { + assertThat(method, not(isAbstract())); + } else { + assertThat(method, isAbstract()); + } + assertThat(companionClass, not(isPresent())); } @Test - public void test() throws Exception { + public void testInterfaceNotKept() throws Exception { runTest(ImmutableList.of(), this::interfaceNotKept); - runTest(ImmutableList.of( - "-keep interface " + InterfaceWithDefaultMethods.class.getCanonicalName() + "{", - "}" - ), this::defaultMethodNotKept); - runTest(ImmutableList.of( - "-keep interface " + InterfaceWithDefaultMethods.class.getCanonicalName() + "{", - " <methods>;", - "}" - ), this::defaultMethodKept); - runTest(ImmutableList.of( - "-keep interface " + InterfaceWithDefaultMethods.class.getCanonicalName() + "{", - " public int method();", - "}" - ), this::defaultMethodKept); + } + + @Test + public void testDefaultMethodNotKept() throws Exception { runTest( ImmutableList.of( - "-keep class " + ClassImplementingInterface.class.getCanonicalName() + "{", + "-keep interface " + InterfaceWithDefaultMethods.class.getTypeName() + "{", "}"), + this::defaultMethodNotKept); + } + + @Test + public void testDefaultMethodKeptWithMethods() throws Exception { + runTest( + ImmutableList.of( + "-keep interface " + InterfaceWithDefaultMethods.class.getTypeName() + "{", + " <methods>;", + "}"), + this::defaultMethodKept); + } + + @Test + public void testDefaultMethodsKeptExplicitly() throws Exception { + runTest( + ImmutableList.of( + "-keep interface " + InterfaceWithDefaultMethods.class.getTypeName() + "{", + " public int method();", + "}"), + this::defaultMethodKept); + } + + @Test + public void testDefaultMethodNotKeptIndirectly() throws Exception { + runTest( + ImmutableList.of( + "-keep class " + ClassImplementingInterface.class.getTypeName() + "{", " <methods>;", "}", // Prevent InterfaceWithDefaultMethods from being merged into ClassImplementingInterface - "-keep class " + InterfaceWithDefaultMethods.class.getCanonicalName()), + "-keep class " + InterfaceWithDefaultMethods.class.getTypeName()), this::defaultMethodNotKept); + } + + @Test + public void testDefaultMethodKeptIndirectly() throws Exception { runTest( ImmutableList.of( - "-keep class " + ClassImplementingInterface.class.getCanonicalName() + "{", + "-keep class " + ClassImplementingInterface.class.getTypeName() + "{", " <methods>;", "}", "-keep class " + TestClass.class.getCanonicalName() + "{", " public void useInterfaceMethod();", "}", // Prevent InterfaceWithDefaultMethods from being merged into ClassImplementingInterface - "-keep class " + InterfaceWithDefaultMethods.class.getCanonicalName()), - this::defaultMethodKept); + "-keep class " + InterfaceWithDefaultMethods.class.getTypeName()), + this::defaultMethodKeptWithoutCompanionClass); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java index 790ea8d..34c9293 100644 --- a/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java +++ b/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java
@@ -4,8 +4,8 @@ package com.android.tools.r8.shaking.ifrule; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -160,10 +160,10 @@ ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class); assertThat(classSubject, isPresent()); assertEquals(3, classSubject.allMethods().size()); - classSubject.allMethods().forEach(m -> assertThat(m, not(isRenamed()))); + classSubject.allMethods().forEach(m -> assertThat(m, isPresentAndNotRenamed())); // Keeping methods will cause the fields to be kept too (but allow renaming them). assertEquals(2, classSubject.allFields().size()); - classSubject.allFields().forEach(f -> assertThat(f, isRenamed())); + classSubject.allFields().forEach(f -> assertThat(f, isPresentAndRenamed())); }); }
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java index 50d64f8..74d2cfb 100644 --- a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java +++ b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java
@@ -3,9 +3,9 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking.ifrule; -import static com.android.tools.r8.utils.codeinspector.Matchers.isNotRenamed; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -108,7 +108,7 @@ } ClassSubject clazz = codeInspector.clazz(DependentUser.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); // Members of DependentUser are not used anywhere. MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of()); assertThat(m, not(isPresent())); @@ -117,7 +117,7 @@ // Although DependentUser#callFoo is shrinked, Dependent is kept via -if. clazz = codeInspector.clazz(Dependent.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); // But, its members are gone. m = clazz.method("java.lang.String", "foo", ImmutableList.of()); assertThat(m, not(isPresent())); @@ -145,7 +145,7 @@ } ClassSubject clazz = codeInspector.clazz(DependentUser.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); // Members of DependentUser are not used anywhere. MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of()); assertThat(m, not(isPresent())); @@ -154,7 +154,7 @@ // Although DependentUser#callFoo is shrinked, Dependent is kept via -if. clazz = codeInspector.clazz(Dependent.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); // But, its members are gone. m = clazz.method("java.lang.String", "foo", ImmutableList.of()); assertThat(m, not(isPresent())); @@ -178,19 +178,19 @@ } ClassSubject clazz = codeInspector.clazz(DependentUser.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); FieldSubject f = clazz.field("int", "canBeShrinked"); assertThat(f, not(isPresent())); // Dependent is kept due to DependentUser#callFoo, but renamed. clazz = codeInspector.clazz(Dependent.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); m = clazz.method("java.lang.String", "foo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); f = clazz.field("int", "intField"); - assertThat(f, isRenamed()); + assertThat(f, isPresentAndRenamed()); } @Test @@ -227,19 +227,19 @@ } ClassSubject clazz = codeInspector.clazz(DependentUser.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); FieldSubject f = clazz.field("int", "canBeShrinked"); assertThat(f, not(isPresent())); // Dependent is kept due to DependentUser#callFoo, but renamed. clazz = codeInspector.clazz(Dependent.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); m = clazz.method("java.lang.String", "foo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); f = clazz.field("int", "intField"); - assertThat(f, isRenamed()); + assertThat(f, isPresentAndRenamed()); } @Test @@ -276,19 +276,19 @@ } ClassSubject clazz = codeInspector.clazz(DependentUser.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); FieldSubject f = clazz.field("int", "canBeShrinked"); assertThat(f, not(isPresent())); // Dependent is kept due to DependentUser#callFoo, but renamed. clazz = codeInspector.clazz(Dependent.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); m = clazz.method("java.lang.String", "foo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); f = clazz.field("int", "intField"); - assertThat(f, isRenamed()); + assertThat(f, isPresentAndRenamed()); } @Test @@ -307,11 +307,11 @@ ClassSubject clazz = codeInspector.clazz(Dependent.class); // Only class name is not renamed, if triggered. - assertThat(clazz, keepPrecondition ? isNotRenamed() : isRenamed()); + assertThat(clazz, keepPrecondition ? isPresentAndNotRenamed() : isPresentAndRenamed()); MethodSubject m = clazz.method("java.lang.String", "foo", ImmutableList.of()); - assertThat(m, isRenamed()); + assertThat(m, isPresentAndRenamed()); FieldSubject f = clazz.field("int", "intField"); - assertThat(f, isRenamed()); + assertThat(f, isPresentAndRenamed()); } @Test @@ -332,12 +332,12 @@ ClassSubject clazz = codeInspector.clazz(Dependent.class); // Class name is not renamed, if triggered. - assertThat(clazz, keepPrecondition ? isNotRenamed() : isRenamed()); + assertThat(clazz, keepPrecondition ? isPresentAndNotRenamed() : isPresentAndRenamed()); MethodSubject m = clazz.method("java.lang.String", "foo", ImmutableList.of()); // Method name is not renamed either, if triggered. - assertThat(m, keepPrecondition ? isNotRenamed() : isRenamed()); + assertThat(m, keepPrecondition ? isPresentAndNotRenamed() : isPresentAndRenamed()); FieldSubject f = clazz.field("int", "intField"); - assertThat(f, isRenamed()); + assertThat(f, isPresentAndRenamed()); } @Test @@ -357,11 +357,11 @@ CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config); ClassSubject clazz = codeInspector.clazz(Dependent.class); - assertThat(clazz, isRenamed()); + assertThat(clazz, isPresentAndRenamed()); MethodSubject m = clazz.method("java.lang.String", "foo", ImmutableList.of()); // Only method name is not renamed, if triggered. - assertThat(m, keepPrecondition ? isNotRenamed() : isRenamed()); + assertThat(m, keepPrecondition ? isPresentAndNotRenamed() : isPresentAndRenamed()); FieldSubject f = clazz.field("int", "intField"); - assertThat(f, isRenamed()); + assertThat(f, isPresentAndRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java index 35d802c..153bf38 100644 --- a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java +++ b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java
@@ -4,8 +4,7 @@ package com.android.tools.r8.shaking.ifrule; -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.MatcherAssert.assertThat; import com.android.tools.r8.TestBase; @@ -35,8 +34,7 @@ .inspector(); ClassSubject interfaceSubject = inspector.clazz(Interface.class); - assertThat(interfaceSubject, isPresent()); - assertThat(interfaceSubject, isRenamed()); + assertThat(interfaceSubject, isPresentAndRenamed()); } static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersRuleOnIndirectlyInstantiatedClassTest.java b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersRuleOnIndirectlyInstantiatedClassTest.java index 327f61d..5b47f4f 100644 --- a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersRuleOnIndirectlyInstantiatedClassTest.java +++ b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepClassMembersRuleOnIndirectlyInstantiatedClassTest.java
@@ -5,8 +5,7 @@ package com.android.tools.r8.shaking.keepclassmembers; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; -import static org.hamcrest.CoreMatchers.not; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.MatcherAssert.assertThat; import com.android.tools.r8.NeverInline; @@ -59,8 +58,7 @@ assertThat(classSubject, isPresent()); FieldSubject fieldSubject = classSubject.uniqueFieldWithName("greeting"); - assertThat(fieldSubject, isPresent()); - assertThat(fieldSubject, not(isRenamed())); + assertThat(fieldSubject, isPresentAndNotRenamed()); } static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepInterfaceMethodTest.java index e6baeae..93309e8 100644 --- a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepInterfaceMethodTest.java +++ b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/KeepInterfaceMethodTest.java
@@ -4,8 +4,8 @@ package com.android.tools.r8.shaking.keepclassmembers; -import static com.android.tools.r8.utils.codeinspector.Matchers.isNotRenamed; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeTrue; @@ -96,7 +96,7 @@ ClassSubject clazzSubject = inspector.clazz(clazz); assertThat(clazzSubject, isPresent()); MethodSubject foo = clazzSubject.uniqueMethodWithName("foo"); - assertThat(foo, isNotRenamed()); + assertThat(foo, isPresentAndNotRenamed()); } public interface I {
diff --git a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/b115867670/B115867670.java b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/b115867670/B115867670.java index f2f6731..45c7a00 100644 --- a/src/test/java/com/android/tools/r8/shaking/keepclassmembers/b115867670/B115867670.java +++ b/src/test/java/com/android/tools/r8/shaking/keepclassmembers/b115867670/B115867670.java
@@ -5,7 +5,8 @@ package com.android.tools.r8.shaking.keepclassmembers.b115867670; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -105,7 +106,7 @@ assertThat(cls, isPresent()); assertFalse("Class " + clazz.getSimpleName() + " should not be abstract", cls.isAbstract()); assertEquals(1, cls.asFoundClassSubject().allFields().size()); - cls.forAllFields(field -> assertThat(field, not(isRenamed()))); + cls.forAllFields(field -> assertThat(field, isPresentAndNotRenamed())); } } @@ -114,10 +115,10 @@ for (Class clazz : new Class[] {Foo.class, Foo.Interaction.class, Foo.Request.class}) { ClassSubject cls = inspector.clazz(clazz); assertThat(cls, isPresent()); - assertThat(cls, isRenamed()); + assertThat(cls, isPresentAndRenamed()); assertFalse("Class " + clazz.getSimpleName() + " should not be abstract", cls.isAbstract()); assertEquals(1, cls.asFoundClassSubject().allFields().size()); - cls.forAllFields(field -> assertThat(field, isRenamed())); + cls.forAllFields(field -> assertThat(field, isPresentAndRenamed())); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java b/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java index a084679..cea851e 100644 --- a/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java +++ b/src/test/java/com/android/tools/r8/shaking/proxy/MockitoTest.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.shaking.proxy; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; @@ -86,7 +86,6 @@ ClassSubject itf = inspector.clazz(M_I); assertThat(itf, isPresent()); MethodSubject mtd = itf.uniqueMethodWithName("onEnterForeground"); - assertThat(mtd, isPresent()); - assertThat(mtd, not(isRenamed())); + assertThat(mtd, isPresentAndNotRenamed()); } }
diff --git a/src/test/java/com/android/tools/r8/shaking/staticinterfacemethods/defaultmethods/StaticInterfaceMethodsTest.java b/src/test/java/com/android/tools/r8/shaking/staticinterfacemethods/defaultmethods/StaticInterfaceMethodsTest.java new file mode 100644 index 0000000..ca0aaa5 --- /dev/null +++ b/src/test/java/com/android/tools/r8/shaking/staticinterfacemethods/defaultmethods/StaticInterfaceMethodsTest.java
@@ -0,0 +1,224 @@ +// Copyright (c) 2018, 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.shaking.staticinterfacemethods.defaultmethods; + +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed; +import static com.android.tools.r8.utils.codeinspector.Matchers.isStatic; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import com.android.tools.r8.NeverInline; +import com.android.tools.r8.R8TestCompileResult; +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestRunResult; +import com.android.tools.r8.utils.BooleanUtils; +import com.android.tools.r8.utils.ThrowingConsumer; +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.ImmutableList; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class StaticInterfaceMethodsTest extends TestBase { + + private final TestParameters parameters; + private final boolean allowObfuscation; + + @Parameterized.Parameters(name = "{0}, allowObfuscation: {1}") + public static Collection<Object[]> data() { + return buildParameters( + getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values()); + } + + public StaticInterfaceMethodsTest(TestParameters parameters, boolean allowObfuscation) { + this.parameters = parameters; + this.allowObfuscation = allowObfuscation; + } + + private R8TestCompileResult compileTest( + List<String> additionalKeepRules, + ThrowingConsumer<CodeInspector, RuntimeException> inspection) + throws Exception { + return testForR8(parameters.getBackend()) + .addProgramClasses(InterfaceWithStaticMethods.class, TestClass.class) + .setMinApi(parameters.getApiLevel()) + .addKeepMainRule(TestClass.class) + .addKeepRules(additionalKeepRules) + .enableInliningAnnotations() + .compile() + .inspect(inspection); + } + + private void runTest( + List<String> additionalKeepRules, + ThrowingConsumer<CodeInspector, RuntimeException> inspection) + throws Exception { + R8TestCompileResult compileResult = compileTest(additionalKeepRules, inspection); + Path app = compileResult.writeToZip(); + + TestRunResult<?> result; + if (allowObfuscation) { + result = + testForR8(parameters.getBackend()) + .addProgramClasses(InstrumentedTestClass.class) + .addKeepAllClassesRule() + .addApplyMapping(compileResult.getProguardMap()) + .addClasspathClasses(InterfaceWithStaticMethods.class) + .setMinApi(parameters.getApiLevel()) + .compile() + .addRunClasspathFiles(app) + .run(parameters.getRuntime(), InstrumentedTestClass.class); + } else { + result = + testForRuntime(parameters) + .addProgramClasses(InstrumentedTestClass.class) + .addClasspathFiles(app) + .addRunClasspathFiles(app) + .run(parameters.getRuntime(), InstrumentedTestClass.class); + } + if (parameters.canUseDefaultAndStaticInterfaceMethods()) { + result.assertSuccessWithOutputLines("42"); + } else { + result.assertFailure(); + } + } + + private void interfaceNotKept(CodeInspector inspector) { + assertFalse(inspector.clazz(InterfaceWithStaticMethods.class).isPresent()); + } + + private void staticMethodNotKept(CodeInspector inspector) { + ClassSubject clazz = inspector.clazz(InterfaceWithStaticMethods.class); + assertTrue(clazz.isPresent()); + assertFalse(clazz.method("int", "method", ImmutableList.of()).isPresent()); + } + + private void staticMethodKeptB159987443(CodeInspector inspector) { + ClassSubject clazz = inspector.clazz(InterfaceWithStaticMethods.class); + assertThat(clazz, isPresent()); + MethodSubject method = clazz.method("int", "method", ImmutableList.of()); + ClassSubject companionClass = clazz.toCompanionClass(); + if (parameters.canUseDefaultAndStaticInterfaceMethods()) { + assertThat(method, isStatic()); + assertThat(companionClass, not(isPresent())); + } else { + assertThat(method, not(isPresent())); + // TODO(159987443): The companion class should be present. + assertThat(companionClass, not(isPresent())); + // Also check that method exists on companion class. + } + } + + private void staticMethodKept(CodeInspector inspector) { + ClassSubject clazz = inspector.clazz(InterfaceWithStaticMethods.class); + ClassSubject companionClass = clazz.toCompanionClass(); + MethodSubject method = clazz.method("int", "method", ImmutableList.of()); + if (parameters.canUseDefaultAndStaticInterfaceMethods()) { + assertThat(clazz, allowObfuscation ? isPresentAndRenamed() : isPresentAndNotRenamed()); + assertThat(method, isStatic()); + assertThat(companionClass, not(isPresent())); + } else { + // When there is only a static method in the interface nothing is left on the interface itself + // after desugaring, only the companion class is left. + assertThat(clazz, not(isPresent())); + assertThat(method, not(isPresent())); + // TODO(159987443): The companion class should be present. + assertThat(companionClass, not(isPresent())); + // Also check that method exists on companion class. + } + } + + @Test + public void testInterfaceNotKept() throws Exception { + assumeTrue(!allowObfuscation); // No use of allowObfuscation. + + compileTest(ImmutableList.of(), this::interfaceNotKept); + } + + @Test + public void testStaticMethodNotKept() throws Exception { + assumeTrue(!allowObfuscation); // No use of allowObfuscation. + + compileTest( + ImmutableList.of( + "-keep interface " + InterfaceWithStaticMethods.class.getTypeName() + "{", "}"), + this::staticMethodNotKept); + } + + @Test + public void testDefaultMethodKeptWithMethods() throws Exception { + assumeTrue(!allowObfuscation); // No use of allowObfuscation. + + compileTest( + ImmutableList.of( + "-keep interface " + InterfaceWithStaticMethods.class.getTypeName() + "{", + " <methods>;", + "}"), + this::staticMethodKeptB159987443); + } + + @Test + public void testDefaultMethodKeptIndirectly() throws Exception { + ImmutableList.Builder<String> builder = ImmutableList.builder(); + builder.add( + "-keep class " + TestClass.class.getTypeName() + "{", + " public void useStaticInterfaceMethod();", + "}"); + if (parameters.canUseDefaultAndStaticInterfaceMethods()) { + // TODO(160142903): @NeverInline does not seem to work on static interface methods. + // TODO(160144053): Using -keepclassmembers for this cause InterfaceWithStaticMethods to + // be renamed. + if (allowObfuscation) { + builder.add( + "-if class " + InterfaceWithStaticMethods.class.getTypeName(), + "-keep,allowobfuscation class " + InterfaceWithStaticMethods.class.getTypeName() + "{", + " public static int method();", + "}"); + } else { + builder.add( + "-if class " + InterfaceWithStaticMethods.class.getTypeName(), + "-keep class " + InterfaceWithStaticMethods.class.getTypeName() + "{", + " public static int method();", + "}"); + } + } + runTest(builder.build(), this::staticMethodKept); + } + + public static class TestClass { + + public void useStaticInterfaceMethod() { + System.out.println(InterfaceWithStaticMethods.method()); + } + + public static void main(String[] args) {} + } + + public interface InterfaceWithStaticMethods { + @NeverInline + static int method() { + return 42; + } + } + + public static class InstrumentedTestClass { + + public static void main(String[] args) { + System.out.println(InterfaceWithStaticMethods.method()); + } + } +}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java index 81b988e..6a04a0a 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
@@ -7,12 +7,17 @@ import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.DexMethod; import com.android.tools.r8.graph.DexProgramClass; +import com.android.tools.r8.references.ClassReference; import java.util.List; import java.util.function.Consumer; import kotlinx.metadata.jvm.KotlinClassMetadata; public class AbsentClassSubject extends ClassSubject { + public AbsentClassSubject(CodeInspector codeInspector, ClassReference reference) { + super(codeInspector, reference); + } + @Override public boolean isPresent() { return false;
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java index 38dc236..c62f945 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
@@ -142,4 +142,9 @@ public String getJvmMethodSignatureAsString() { return null; } + + @Override + public MethodSubject toMethodOnCompanionClass() { + throw new Unreachable("Cannot determine companion class method"); + } }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java index 97a3b29..84d76a1 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
@@ -4,10 +4,14 @@ package com.android.tools.r8.utils.codeinspector; +import static com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX; + import com.android.tools.r8.graph.DexMethod; import com.android.tools.r8.graph.DexProgramClass; import com.android.tools.r8.naming.MemberNaming.MethodSignature; +import com.android.tools.r8.references.ClassReference; import com.android.tools.r8.references.MethodReference; +import com.android.tools.r8.references.Reference; import com.android.tools.r8.references.TypeReference; import com.android.tools.r8.smali.SmaliBuilder; import com.android.tools.r8.utils.ListUtils; @@ -23,6 +27,14 @@ public abstract class ClassSubject extends Subject { + protected final ClassReference reference; + protected final CodeInspector codeInspector; + + public ClassSubject(CodeInspector codeInspector, ClassReference reference) { + this.codeInspector = codeInspector; + this.reference = reference; + } + public abstract void forAllMethods(Consumer<FoundMethodSubject> inspection); public final List<FoundMethodSubject> allMethods() { @@ -192,4 +204,11 @@ public abstract KmPackageSubject getKmPackage(); public abstract KotlinClassMetadata getKotlinClassMetadata(); + + public ClassSubject toCompanionClass() { + String descriptor = reference.getDescriptor(); + return codeInspector.clazz( + Reference.classFromDescriptor( + descriptor.substring(0, descriptor.length() - 1) + COMPANION_CLASS_NAME_SUFFIX + ";")); + } }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java index 76ed0e2..43ba1fb 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -48,6 +48,7 @@ import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode; import com.google.common.collect.ImmutableList; import java.io.IOException; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; @@ -280,9 +281,9 @@ } DexClass clazz = application.definitionFor(toDexTypeIgnorePrimitives(name)); if (clazz == null) { - return new AbsentClassSubject(); + return new AbsentClassSubject(this, reference); } - return new FoundClassSubject(this, clazz, naming); + return new FoundClassSubject(this, clazz, naming, reference); } public ClassSubject companionClassFor(Class<?> clazz) { @@ -308,6 +309,10 @@ return builder.build(); } + public FieldSubject field(Field field) { + return field(Reference.fieldFromField(field)); + } + public FieldSubject field(FieldReference field) { ClassSubject clazz = clazz(field.getHolderClass()); if (!clazz.isPresent()) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java index 2ce3024..bd65812 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -24,6 +24,7 @@ import com.android.tools.r8.naming.MemberNaming.MethodSignature; import com.android.tools.r8.naming.MemberNaming.Signature; import com.android.tools.r8.naming.signature.GenericSignatureParser; +import com.android.tools.r8.references.ClassReference; import com.android.tools.r8.utils.DescriptorUtils; import com.android.tools.r8.utils.StringUtils; import java.util.List; @@ -32,13 +33,15 @@ public class FoundClassSubject extends ClassSubject { - private final CodeInspector codeInspector; private final DexClass dexClass; final ClassNamingForNameMapper naming; FoundClassSubject( - CodeInspector codeInspector, DexClass dexClass, ClassNamingForNameMapper naming) { - this.codeInspector = codeInspector; + CodeInspector codeInspector, + DexClass dexClass, + ClassNamingForNameMapper naming, + ClassReference reference) { + super(codeInspector, reference); this.dexClass = dexClass; this.naming = naming; }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java index 6363747..a74c3d8 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java
@@ -129,7 +129,7 @@ default ClassSubject getClassSubjectFromKmType(KmType kmType) { String descriptor = getDescriptorFromKmType(kmType); if (descriptor == null) { - return new AbsentClassSubject(); + return new AbsentClassSubject(codeInspector(), Reference.classFromDescriptor("Lnot_found;")); } return getClassSubjectFromDescriptor(descriptor); }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java index 1f1fe84..d4f8b5b 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -4,6 +4,8 @@ package com.android.tools.r8.utils.codeinspector; +import static com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.DEFAULT_METHOD_PREFIX; + import com.android.tools.r8.cf.code.CfInstruction; import com.android.tools.r8.cf.code.CfPosition; import com.android.tools.r8.code.Instruction; @@ -31,6 +33,7 @@ import com.android.tools.r8.naming.signature.GenericSignatureParser; import com.android.tools.r8.references.MethodReference; import com.android.tools.r8.references.Reference; +import com.android.tools.r8.references.TypeReference; import com.android.tools.r8.utils.StringUtils; import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry; import com.google.common.base.Predicates; @@ -39,6 +42,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -372,4 +376,19 @@ + ")" + dexMethod.method.proto.returnType.toDescriptorString(); } + + @Override + public MethodSubject toMethodOnCompanionClass() { + ClassSubject companionClass = clazz.toCompanionClass(); + MethodReference reference = asMethodReference(); + List<String> p = + ImmutableList.<String>builder() + .add(clazz.getFinalName()) + .addAll(reference.getFormalTypes().stream().map(TypeReference::getTypeName).iterator()) + .build(); + return companionClass.method( + reference.getReturnType().getTypeName(), + DEFAULT_METHOD_PREFIX + reference.getMethodName(), + p); + } }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java index 949903d..5842c9b 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
@@ -123,7 +123,7 @@ }; } - public static Matcher<Subject> isRenamed() { + public static Matcher<Subject> isPresentAndRenamed() { return new TypeSafeMatcher<Subject>() { @Override protected boolean matchesSafely(Subject subject) { @@ -143,7 +143,7 @@ }; } - public static Matcher<Subject> isNotRenamed() { + public static Matcher<Subject> isPresentAndNotRenamed() { return new TypeSafeMatcher<Subject>() { @Override protected boolean matchesSafely(Subject subject) { @@ -163,8 +163,8 @@ }; } - public static Matcher<Subject> isRenamed(boolean isRenamed) { - return isRenamed ? isRenamed() : isNotRenamed(); + public static Matcher<Subject> isPresentAndRenamed(boolean isRenamed) { + return isRenamed ? isPresentAndRenamed() : isPresentAndNotRenamed(); } public static Matcher<MemberSubject> isStatic() {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java index 8fc439f..690838d 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -102,4 +102,6 @@ } public abstract String getJvmMethodSignatureAsString(); + + public abstract MethodSubject toMethodOnCompanionClass(); }
diff --git a/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java b/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java index fe98a17..8d6dd4b 100644 --- a/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java +++ b/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
@@ -661,6 +661,10 @@ } } + public CodeInspector codeInspector() { + return inspector; + } + public Set<GraphNode> getRoots() { return Collections.unmodifiableSet(roots); }
diff --git a/third_party/proguard/README.google b/third_party/proguard/README.google index abe0568..714899c 100644 --- a/third_party/proguard/README.google +++ b/third_party/proguard/README.google
@@ -1,8 +1,9 @@ URL: https://sourceforge.net/projects/proguard/files/proguard/5.2/ URL: https://sourceforge.net/projects/proguard/files/proguard/6.0/ -Version: 5.2.1, 6.0.1 +URL: https://github.com/Guardsquare/proguard/releases/download/v7.0.0/proguard-7.0.0.tar.gz +Version: 5.2.1, 6.0.1, 7.0.0 License: GPL -License File: proguard5.2.1/docs/license.html, proguard6.0.1/docs/license.html +License File: proguard5.2.1/docs/license.html, proguard6.0.1/docs/license.html, proguard-7.0.0/docs/license.md Description: ProGuard Java Optimizer and Obfuscator
diff --git a/third_party/proguard/proguard-7.0.0.tar.gz.sha1 b/third_party/proguard/proguard-7.0.0.tar.gz.sha1 new file mode 100644 index 0000000..eb88ebe --- /dev/null +++ b/third_party/proguard/proguard-7.0.0.tar.gz.sha1
@@ -0,0 +1 @@ +96b54d82acbf8ccdf53fdc5ea95f65907e526fca \ No newline at end of file
diff --git a/tools/keeprule_benchmark.py b/tools/keeprule_benchmark.py new file mode 100755 index 0000000..0a7e063 --- /dev/null +++ b/tools/keeprule_benchmark.py
@@ -0,0 +1,247 @@ +#!/usr/bin/env python +# 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. + +import argparse +import os +import subprocess +import sys +import time + +import jdk +import proguard +import toolhelper +import utils + +SHRINKERS = ['r8'] + proguard.getVersions() + +INPUT_PROGRAM = utils.PINNED_R8_JAR + +ANNO = 'com.android.tools.r8.com.google.common.annotations.VisibleForTesting' + +R8_OPTIONS = [ + 'printTimes', + 'passthroughDexCode', + 'enableClassMerging', + 'enableDevirtualization', + 'enableNonNullTracking', + 'enableInlining', + 'enableSwitchMapRemoval', + 'enableValuePropagation', + 'useSmaliSyntax', + 'verbose', + 'quiet', + 'invalidDebugInfoFatal', + 'intermediate', + 'enableLambdaMerging', + 'enableDesugaring', + 'enableMainDexListCheck', + 'enableTreeShaking', + 'printCfg', + 'ignoreMissingClasses', + 'forceProguardCompatibility', + 'enableMinification', + 'disableAssertions', + 'debugKeepRules', + 'debug', + 'minimalMainDex', + 'skipReadingDexCode', +] + +R8_CLASSES = [ + 'com.android.tools.r8.code.Format11x', + 'com.android.tools.r8.code.MoveFrom16', + 'com.android.tools.r8.code.AddLong2Addr', + 'com.android.tools.r8.code.AgetByte', + 'com.android.tools.r8.code.SubDouble', + 'com.android.tools.r8.code.Sput', + 'com.android.tools.r8.code.Format10x', + 'com.android.tools.r8.code.RemInt', + 'com.android.tools.r8.code.ConstWide', + 'com.android.tools.r8.code.SgetWide', + 'com.android.tools.r8.code.OrInt2Addr', + 'com.android.tools.r8.code.Iget', + 'com.android.tools.r8.code.Instruction', + 'com.android.tools.r8.code.SubInt2Addr', + 'com.android.tools.r8.code.SwitchPayload', + 'com.android.tools.r8.code.Const4', + 'com.android.tools.r8.code.ShrIntLit8', + 'com.android.tools.r8.code.ConstWide16', + 'com.android.tools.r8.code.NegInt', + 'com.android.tools.r8.code.SgetBoolean', + 'com.android.tools.r8.code.Format22x', + 'com.android.tools.r8.code.InvokeVirtualRange', + 'com.android.tools.r8.code.Format45cc', + 'com.android.tools.r8.code.DivFloat2Addr', + 'com.android.tools.r8.code.MulIntLit16', + 'com.android.tools.r8.code.BytecodeStream', +] + +KEEP_MAIN = \ + '-keep class com.android.tools.r8.R8 { void main(java.lang.String[]); }' + +BENCHMARKS = [ + # Baseline compile just keeps R8.main (implicitly kept for all benchmarks). + ('KeepBaseline', ''), + + # Mirror default keep getters/setters, but independent of hierarchy. + ('KeepGetters', + '-keepclassmembers class * { *** get*(); }'), + ('KeepGettersIf', + '-if class * { *** get*(); } -keep class <1> { *** get<2>(); }'), + + # Mirror default keep getters/setters below View (here a class with a B). + ('KeepSubGetters', + '-keepclassmembers class * extends **.*B* { *** get*(); }'), + ('KeepSubGettersIf', + '-if class * extends **.*B* -keep class <1> { *** get*(); }'), + + # General keep rule to keep annotated members. + ('KeepAnnoMethod', + '-keepclasseswithmembers class * { @%s *** *(...); }' % ANNO), + ('KeepAnnoMethodCond', + '-keepclassmembers class * { @%s *** *(...); }' % ANNO), + ('KeepAnnoMethodIf', + '-if class * { @%s *** *(...); } -keep class <1> { @%s *** <2>(...); }' \ + % (ANNO, ANNO)), + + # Large collection of rules mirroring AAPT conditional rules on R fields. + ('KeepAaptFieldIf', + '\n'.join([ + '-if class **.InternalOptions { boolean %s; }' + ' -keep class %s { <init>(...); }' % (f, c) + for (f, c) in zip(R8_OPTIONS, R8_CLASSES) * 1 #100 + ])), + + # If rules with predicates that will never by true, but will need + # consideration. The CodeSize of these should be equal to the baseline run. + ('KeepIfNonExistingClass', + '-if class **.*A*B*C*D*E*F* -keep class %s' % ANNO), + ('KeepIfNonExistingMember', + '-if class **.*A* { *** *a*b*c*d*e*f*(...); } -keep class %s' % ANNO) +] + +def parse_arguments(argv): + parser = argparse.ArgumentParser( + description = 'Run keep-rule benchmarks.') + parser.add_argument('--golem', + help = 'Link in third party dependencies.', + default = False, + action = 'store_true') + parser.add_argument('--ignore-java-version', + help='Do not check java version', + default=False, + action='store_true') + parser.add_argument('--shrinker', + help='The shrinker to use', + choices=SHRINKERS, + default=SHRINKERS[0]) + parser.add_argument('--runs', + help='Number of runs to average out time on', + type=int, + default=3) + parser.add_argument('--benchmark', + help='Benchmark to run (default all)', + choices=map(lambda (x,y): x, BENCHMARKS), + default=None) + options = parser.parse_args(argv) + return options + +class BenchmarkResult: + def __init__(self, name, size, runs): + self.name = name + self.size = size + self.runs = runs + +def isPG(shrinker): + return proguard.isValidVersion(shrinker) + +def shrinker_args(shrinker, keepfile, output): + if shrinker == 'r8': + return [ + jdk.GetJavaExecutable(), + '-cp', utils.R8LIB_JAR, + 'com.android.tools.r8.R8', + INPUT_PROGRAM, + '--lib', utils.RT_JAR, + '--output', output, + '--min-api', '10000', + '--pg-conf', keepfile, + ] + elif isPG(shrinker): + return proguard.getCmd([ + '-injars', INPUT_PROGRAM, + '-libraryjars', utils.RT_JAR, + '-outjars', output, + '-dontwarn', '**', + '-optimizationpasses', '2', + '@' + keepfile, + ], + version=shrinker) + else: + assert False, "Unexpected shrinker " + shrinker + +def dex(input, output): + toolhelper.run( + 'd8', + [ + input, + '--lib', utils.RT_JAR, + '--min-api', '10000', + '--output', output + ], + build=False, + debug=False) + +def run_shrinker(options, temp): + benchmarks = BENCHMARKS + if options.benchmark: + for (name, rules) in BENCHMARKS: + if name == options.benchmark: + benchmarks = [(name, rules)] + break + assert len(benchmarks) == 1, "Unexpected benchmark " + options.benchmark + + run_count = options.runs + benchmark_results = [] + for (name, rule) in benchmarks: + benchmark_keep = os.path.join(temp, '%s-keep.txt' % name) + with open(benchmark_keep, 'w') as fp: + fp.write(KEEP_MAIN) + fp.write('\n') + fp.write(rule) + + benchmark_runs = [] + benchmark_size = 0 + for i in range(run_count): + out = os.path.join(temp, '%s-out%d.jar' % (name, i)) + cmd = shrinker_args(options.shrinker, benchmark_keep, out) + utils.PrintCmd(cmd) + t0 = time.time() + subprocess.check_output(cmd) + t1 = time.time() + benchmark_runs.append(t1 - t0) + if isPG(options.shrinker): + dexout = os.path.join(temp, '%s-out%d-dex.jar' % (name, i)) + dex(out, dexout) + benchmark_size = utils.uncompressed_size(dexout) + else: + benchmark_size = utils.uncompressed_size(out) + benchmark_results.append( + BenchmarkResult(name, benchmark_size, benchmark_runs)) + + print 'Runs:', options.runs + for result in benchmark_results: + benchmark_avg = sum(result.runs) / run_count + print '%s(CodeSize): %d' % (result.name, result.size) + print '%s(RunTimeRaw): %d ms' % (result.name, 1000.0 * benchmark_avg) + +if __name__ == '__main__': + options = parse_arguments(sys.argv[1:]) + if options.golem: + golem.link_third_party() + if not options.ignore_java_version: + utils.check_java_version() + with utils.TempDir() as temp: + run_shrinker(options, temp)
diff --git a/tools/proguard.py b/tools/proguard.py index b1bde54..5984622 100755 --- a/tools/proguard.py +++ b/tools/proguard.py
@@ -6,22 +6,65 @@ # Run ProGuard, Google's internal version from __future__ import print_function -import jdk + import os import subprocess import sys +from exceptions import ValueError +import jdk import utils -PROGUARD_JAR = os.path.join(utils.REPO_ROOT, 'third_party', 'proguard', - 'proguard_internal_159423826', 'ProGuard_deploy.jar') +# Internal constants, these should not be used outside this script. +# Use the friendly utility methods below. +PG_DIR = os.path.join(utils.THIRD_PARTY, 'proguard') +DEFAULT = 'pg6' +DEFAULT_ALIAS = 'pg' +VERSIONS = { + 'pg5': os.path.join(PG_DIR, 'proguard5.2.1', 'lib', 'proguard.jar'), + 'pg6': os.path.join(PG_DIR, 'proguard6.0.1', 'lib', 'proguard.jar'), + 'pg7': os.path.join(PG_DIR, 'proguard-7.0.0', 'lib', 'proguard.jar'), + 'pg_internal': os.path.join( + PG_DIR, 'proguard_internal_159423826', 'ProGuard_deploy.jar'), +} +# Add alias for the default version. +VERSIONS[DEFAULT_ALIAS] = VERSIONS[DEFAULT] -def run(args, track_memory_file = None, stdout=None, stderr=None): +# Get versions sorted (nice for argument lists) +def getVersions(): + versions = list(VERSIONS.keys()) + versions.sort() + return versions + +def isValidVersion(version): + return version in VERSIONS + +def getValidatedVersion(version): + if not isValidVersion(version): + raise ValueError("Invalid PG version: '%s'" % version) + return version + +def getJar(version=DEFAULT): + return VERSIONS[getValidatedVersion(version)] + +def getRetraceJar(version=DEFAULT): + if version == 'pg_internal': + raise ValueError("No retrace in internal distribution") + return getJar().replace('proguard.jar', 'retrace.jar') + +def getCmd(args, version=DEFAULT, jvmArgs=None): + cmd = [] + if jvmArgs: + cmd.extend(jvmArgs) + cmd.extend([jdk.GetJavaExecutable(), '-jar', getJar(version)]) + cmd.extend(args) + return cmd + +def run(args, version=DEFAULT, track_memory_file=None, stdout=None, stderr=None): cmd = [] if track_memory_file: cmd.extend(['tools/track_memory.sh', track_memory_file]) - cmd.extend([jdk.GetJavaExecutable(), '-jar', PROGUARD_JAR]) - cmd.extend(args) + cmd.extend(getCmd(args, version)) utils.PrintCmd(cmd) subprocess.call(cmd, stdout=stdout, stderr=stderr)
diff --git a/tools/r8_release.py b/tools/r8_release.py index 1224b1d..0612c36 100755 --- a/tools/r8_release.py +++ b/tools/r8_release.py
@@ -385,6 +385,77 @@ return release_google3 +def update_desugar_library_in_studio(args): + assert os.path.exists(args.studio), ("Could not find STUDIO path %s" + % args.studio) + + def make_release(args): + library_version = args.update_desugar_library_in_studio[0] + configuration_version = args.update_desugar_library_in_studio[1] + change_name = 'update-desugar-library-dependencies' + + with utils.ChangedWorkingDirectory(args.studio): + if not args.use_existing_work_branch: + subprocess.call(['repo', 'abandon', change_name]) + if not args.no_sync: + subprocess.check_call(['repo', 'sync', '-cq', '-j', '16']) + + cmd = ['tools/base/bazel/bazel', + 'run', + '//tools/base/bazel:add_dependency', + '--', + '--repo=https://maven.google.com com.android.tools:desugar_jdk_libs:%s' % library_version] + utils.PrintCmd(cmd) + subprocess.check_call(" ".join(cmd), shell=True) + cmd = ['tools/base/bazel/bazel', 'shutdown'] + utils.PrintCmd(cmd) + subprocess.check_call(cmd) + + prebuilts_tools = os.path.join(args.studio, 'prebuilts', 'tools') + with utils.ChangedWorkingDirectory(prebuilts_tools): + if not args.use_existing_work_branch: + with utils.ChangedWorkingDirectory(prebuilts_tools): + subprocess.check_call(['repo', 'start', change_name]) + m2_dir = os.path.join( + 'common', 'm2', 'repository', 'com', 'android', 'tools') + subprocess.check_call( + ['git', + 'add', + os.path.join(m2_dir, DESUGAR_JDK_LIBS, library_version)]) + subprocess.check_call( + ['git', + 'add', + os.path.join( + m2_dir, DESUGAR_JDK_LIBS_CONFIGURATION, configuration_version)]) + + git_message = ("""Update library desugaring dependencies + + com.android.tools:desugar_jdk_libs:%s + com.android.tools:desugar_jdk_libs_configuration:%s + +Bug: %s +Test: L8ToolTest, L8DexDesugarTest""" + % (library_version, + configuration_version, + '\nBug: '.join(args.bug))) + + if not args.use_existing_work_branch: + subprocess.check_call(['git', 'commit', '-a', '-m', git_message]) + else: + print ('Not committing when --use-existing-work-branch. ' + + 'Commit message should be:\n\n' + + git_message + + '\n') + # Don't upload if requested not to, or if changes are not committed due + # to --use-existing-work-branch + if not args.no_upload and not args.use_existing_work_branch: + process = subprocess.Popen(['repo', 'upload', '.', '--verify'], + stdin=subprocess.PIPE) + return process.communicate(input='y\n')[0] + + return make_release + + def prepare_desugar_library(args): def make_release(args): @@ -677,6 +748,10 @@ nargs=2, metavar=('<version>', '<configuration hash>'), help='The new version of com.android.tools:desugar_jdk_libs') + group.add_argument('--update-desugar-library-in-studio', + nargs=2, + metavar=('<version>', '<configuration version>'), + help='Update studio mirror of com.android.tools:desugar_jdk_libs') group.add_argument('--new-dev-branch', nargs=2, metavar=('<version>', '<master hash>'), @@ -772,7 +847,7 @@ if args.google3: targets_to_run.append(prepare_google3(args)) - if args.studio: + if args.studio and not args.update_desugar_library_in_studio: targets_to_run.append(prepare_studio(args)) if args.aosp: targets_to_run.append(prepare_aosp(args)) @@ -782,6 +857,16 @@ if args.desugar_library: targets_to_run.append(prepare_desugar_library(args)) + if args.update_desugar_library_in_studio: + if not args.studio: + print ("--studio required") + sys.exit(1) + if args.bug == []: + print ("Update studio mirror of com.android.tools:desugar_jdk_libs " + + "requires at least one bug by using '--bug'") + sys.exit(1) + targets_to_run.append(update_desugar_library_in_studio(args)) + final_results = [] for target_closure in targets_to_run: final_results.append(target_closure(args))
diff --git a/tools/r8lib_size_compare.py b/tools/r8lib_size_compare.py index 84dd1a2..568f254 100755 --- a/tools/r8lib_size_compare.py +++ b/tools/r8lib_size_compare.py
@@ -73,13 +73,17 @@ if not is_output_newer(utils.R8_JAR, r8lib_jar): r8lib_memory = os.path.join(tmpdir, 'r8lib%s-memory.txt' % inline_suffix) + # TODO(b/160420801): The signature of build_r8lib has changed. build_r8lib.build_r8lib( - output_path=r8lib_jar, output_map=r8lib_map, - extra_args=r8lib_args, track_memory_file=r8lib_memory) + output_path=r8lib_jar, + output_map=r8lib_map, + extra_args=r8lib_args, + track_memory_file=r8lib_memory) pg_output = os.path.join(tmpdir, 'r8lib-pg%s.jar' % inline_suffix) pg_memory = os.path.join(tmpdir, 'r8lib-pg%s-memory.txt' % inline_suffix) pg_map = os.path.join(tmpdir, 'r8lib-pg%s-map.txt' % inline_suffix) + # TODO(b/160420801): This must use proguard.* utils once working again. pg_args = ['tools/track_memory.sh', pg_memory, 'third_party/proguard/proguard6.0.2/bin/proguard.sh', '@' + pg_config,
diff --git a/tools/retrace_benchmark.py b/tools/retrace_benchmark.py index 21bb738..a819ea5 100755 --- a/tools/retrace_benchmark.py +++ b/tools/retrace_benchmark.py
@@ -4,13 +4,14 @@ # BSD-style license that can be found in the LICENSE file. import argparse -import jdk -import golem import os import subprocess import sys import time -import toolhelper + +import golem +import jdk +import proguard import utils RETRACERS = ['r8', 'proguard', 'remapper'] @@ -44,13 +45,7 @@ retracer_args = [ '-cp', utils.R8LIB_JAR, 'com.android.tools.r8.retrace.Retrace'] elif options.retracer == 'proguard': - retracer_args = ['-jar', - os.path.join( - utils.THIRD_PARTY, - 'proguard', - 'proguard6.0.1', - 'lib', - 'retrace.jar')] + retracer_args = ['-jar', proguard.getRetraceJar()] elif options.retracer == 'remapper': retracer_args = ['-jar', os.path.join(
diff --git a/tools/run_proguard_dx_on_app.py b/tools/run_proguard_dx_on_app.py index 61ac1d7..bb1d72a 100755 --- a/tools/run_proguard_dx_on_app.py +++ b/tools/run_proguard_dx_on_app.py
@@ -120,6 +120,7 @@ track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE) proguard.run( args, + version='pg_internal', track_memory_file = track_memory_file, stdout=open(os.devnull, 'w')) if options.print_memoryuse:
diff --git a/tools/test_helloexample.py b/tools/test_helloexample.py index abda493..f81e64c 100755 --- a/tools/test_helloexample.py +++ b/tools/test_helloexample.py
@@ -19,6 +19,7 @@ import golem import jdk +import proguard import utils HELLO_JAR = os.path.join(utils.BUILD, 'test', 'examples', 'hello.jar') @@ -87,7 +88,7 @@ parser = argparse.ArgumentParser( description = 'Compile a hello world example program') parser.add_argument('--tool', - choices = ['d8', 'r8', 'pg'], + choices = ['d8', 'r8'] + proguard.getVersions(), required = True, help = 'Compiler tool to use.') parser.add_argument('--output-mode', @@ -163,19 +164,17 @@ if output_mode == 'cf': cmd.append('--classfile') return [cmd] - if tool == 'pg': + if proguard.isValidVersion(tool): # Build PG invokation with additional rules to silence warnings. pg_out = output if output_mode == 'cf' \ else os.path.join(output_dir, 'pgout.zip') - cmds = [[ - jdk.GetJavaExecutable(), - '-jar', utils.PROGUARD_JAR, + cmds = [proguard.getCmd([ '-injars', ':'.join([HELLO_JAR] + extra), '-libraryjars', lib, '-outjars', pg_out, '-dontwarn **', '@' + rules_file - ]] + ], version=tool)] if output_mode == 'dex': cmds.append( GetCompilerPrefix('d8', 'dex', output, pg_out, lib, [], noopt))
diff --git a/tools/utils.py b/tools/utils.py index 16a0696..4a171ad 100644 --- a/tools/utils.py +++ b/tools/utils.py
@@ -61,12 +61,6 @@ GENERATED_LICENSE = os.path.join(GENERATED_LICENSE_DIR, 'LICENSE') RT_JAR = os.path.join(REPO_ROOT, 'third_party/openjdk/openjdk-rt-1.8/rt.jar') R8LIB_KEEP_RULES = os.path.join(REPO_ROOT, 'src/main/keep.txt') -PROGUARD_JAR = os.path.join( - THIRD_PARTY, - 'proguard', - 'proguard6.0.1', - 'lib', - 'proguard.jar') CF_SEGMENTS_TOOL = os.path.join(THIRD_PARTY, 'cf_segments') PINNED_R8_JAR = os.path.join(REPO_ROOT, 'third_party/r8/r8.jar') PINNED_PGR8_JAR = os.path.join(REPO_ROOT, 'third_party/r8/r8-pg6.0.1.jar')