Support checksums for classes with non-ascii names.
Bug: 146597396
Change-Id: I1b677348720e58e2e4f142e79143581d84a9cb8c
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 7ba04b5..993363c 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -49,8 +49,8 @@
import com.android.tools.r8.utils.ThreadUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ObjectArrays;
-import it.unimi.dsi.fastutil.objects.Object2LongMap;
-import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Reference2LongMap;
+import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -204,14 +204,15 @@
*/
private void encodeChecksums(Iterable<VirtualFile> files) {
List<DexProgramClass> classes = application.classes();
- Object2LongMap<String> inputChecksums = new Object2LongOpenHashMap<>(classes.size());
+ Reference2LongMap<DexString> inputChecksums = new Reference2LongOpenHashMap<>(classes.size());
for (DexProgramClass clazz : classes) {
- inputChecksums.put(clazz.getType().descriptor.toASCIIString(), clazz.getChecksum());
+ inputChecksums.put(clazz.getType().descriptor, clazz.getChecksum());
}
for (VirtualFile file : files) {
ClassesChecksum toWrite = new ClassesChecksum();
- for (String desc : file.getClassDescriptors()) {
- toWrite.addChecksum(desc, inputChecksums.getLong(desc));
+ for (DexProgramClass clazz : file.classes()) {
+ DexString desc = clazz.type.descriptor;
+ toWrite.addChecksum(desc.toString(), inputChecksums.getLong(desc));
}
file.injectString(application.dexItemFactory.createString(toWrite.toJsonString()));
}
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index d5e338e..c69d8e0 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -716,7 +716,7 @@
Long checksum = null;
if (checksums != null && !checksums.isEmpty()) {
- String desc = type.descriptor.toASCIIString();
+ String desc = type.toDescriptorString();
checksum = checksums.getOrDefault(desc, null);
if (!options.dexClassChecksumFilter.test(desc, checksum)) {
continue;
diff --git a/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java b/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java
new file mode 100644
index 0000000..146c94f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/dexfilemerger/NonAsciiClassNameChecksumTest.java
@@ -0,0 +1,82 @@
+// 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.dexfilemerger;
+
+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;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class NonAsciiClassNameChecksumTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ public NonAsciiClassNameChecksumTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path intermediate1 = compileIntermediate(TæstClass.class);
+ Path intermediate2 = compileIntermediate(TestClåss.class);
+ testForD8()
+ .addProgramFiles(intermediate1, intermediate2)
+ .setMinApi(parameters.getApiLevel())
+ .setIncludeClassesChecksum(true)
+ .run(parameters.getRuntime(), TæstClass.class)
+ .assertSuccessWithOutput(EXPECTED)
+ .inspect(inspector -> {
+ checkIncludesChecksum(inspector, TæstClass.class);
+ checkIncludesChecksum(inspector, TestClåss.class);
+ });
+ }
+
+ private Path compileIntermediate(Class<?> clazz) throws Exception {
+ return testForD8()
+ .setOutputMode(OutputMode.DexFilePerClassFile)
+ .addProgramClasses(clazz)
+ .setMinApi(parameters.getApiLevel())
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .inspect(inspector -> checkIncludesChecksum(inspector, clazz))
+ .writeToZip();
+ }
+
+ private void checkIncludesChecksum(CodeInspector inspector, Class<?> clazz) {
+ ClassSubject classSubject = inspector.clazz(clazz);
+ assertThat(classSubject, isPresent());
+ assertTrue(classSubject.getDexClass().asProgramClass().getChecksum() > 0);
+ }
+
+ static class TæstClass {
+ public static void main(String[] args) {
+ new TestClåss().foo();
+ }
+ }
+
+ static class TestClåss {
+ public void foo() {
+ System.out.println("Hello, world");
+ }
+ }
+}
\ No newline at end of file