blob: 24601c13e4608e2679a7f94b9af7918934ced8f1 [file] [log] [blame]
// Copyright (c) 2019, 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 org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.dex.ClassesChecksum;
import com.android.tools.r8.graph.DexItemFactory;
import java.nio.file.Path;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class DexMergeChecksumsHighSortingStrings extends TestBase {
private final TestParameters parameters;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withDexRuntimes().withAllApiLevels().build();
}
public DexMergeChecksumsHighSortingStrings(TestParameters parameters) {
this.parameters = parameters;
}
@Test
public void testChecksumWhitHighSortingStrings() throws Exception {
Path dexArchive1 =
testForD8()
.addProgramClasses(TestClass1.class)
.setMinApi(parameters.getApiLevel())
.setMode(CompilationMode.DEBUG)
.setIncludeClassesChecksum(true)
.compile()
.writeToZip();
Path dexArchive2 =
testForD8()
.addProgramClasses(TestClass2.class)
.setMinApi(parameters.getApiLevel())
.setMode(CompilationMode.DEBUG)
.setIncludeClassesChecksum(true)
.compile()
.writeToZip();
testForD8()
.setMinApi(parameters.getApiLevel())
.addProgramFiles(dexArchive1)
.setIncludeClassesChecksum(true)
.run(parameters.getRuntime(), TestClass1.class)
.assertSuccessWithOutputLines("Hello, \uDB3F\uDFFD");
testForD8()
.setMinApi(parameters.getApiLevel())
.addProgramFiles(dexArchive2)
.setIncludeClassesChecksum(true)
.run(parameters.getRuntime(), TestClass2.class)
.assertSuccessWithOutputLines("Hello, ~~~\u007f");
testForD8()
.setMinApi(parameters.getApiLevel())
.addProgramFiles(dexArchive1, dexArchive2)
.setIncludeClassesChecksum(true)
.run(parameters.getRuntime(), TestClass2.class)
.assertSuccessWithOutputLines("Hello, ~~~\u007f");
}
static class TestClass1 {
// U+DFFFD which is very end of unassigned plane.
private static final String STRING_SORTING_ABOVE_CHECKSUM_STRING = "\uDB3F\uDFFD";
public static void main(String[] args) {
System.out.println("Hello, " + STRING_SORTING_ABOVE_CHECKSUM_STRING);
}
}
static class TestClass2 {
private static final String STRING_SORTING_ABOVE_CHECKSUM_STRING = "~~~\u007f";
public static void main(String[] args) {
System.out.println("Hello, " + STRING_SORTING_ABOVE_CHECKSUM_STRING);
}
}
@Test
public void testChecksumMarkerComparison() {
// z { | } ~ <DEL>
// 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f
assertTrue('{' - 1 == 'z');
assertTrue('{' + 1 == '|');
assertTrue('~' - 1 == '}');
DexItemFactory factory = new DexItemFactory();
assertFalse(
ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("\uDB3F\uDFFD")));
assertFalse(
ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~\uDB3F\uDFFD\"")));
assertFalse(
ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~\uDB3F\uDFFD")));
assertFalse(
ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~~\uDB3F\uDFFD")));
assertFalse(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("\u007f")));
assertFalse(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~\u007f")));
assertFalse(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~\u007f")));
assertFalse(
ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~~\u007f")));
assertFalse(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~~|")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~}")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~}")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("}")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("z")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("zz")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("zzz")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("zzzz")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("this")));
assertTrue(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("println")));
// False negatives.
assertFalse(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~~")));
assertFalse(ClassesChecksum.definitelyPrecedesChecksumMarker(factory.createString("~~~z")));
}
}