blob: fe04d25f4e3bc505ab3821f6a74f7e6e31692efd [file] [log] [blame]
// 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.jasmin;
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.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.InvalidPathException;
import java.util.Arrays;
import java.util.Collection;
class NameTestBase extends JasminTestBase {
// TestString is a String with modified toString() which prints \\uXXXX for
// characters outside 0x20..0x7e.
static class TestString {
private final String value;
TestString(String value) {
this.value = value;
}
String getValue() {
return value;
}
@Override
public String toString() {
return StringUtils.toASCIIString(value);
}
}
// The return value is a collection of rows with the following fields:
// - Name (String) to test (can be class name, field name, method name).
// - boolean, whether it runs on the JVM.
// - boolean, whether it runs on the ART.
static Collection<Object[]> getCommonNameTestData(boolean classNames) {
boolean windowsSensitive = classNames && ToolHelper.isWindows();
boolean supportSpaces = ToolHelper.getMinApiLevelForDexVm().getLevel()
>= AndroidApiLevel.R.getLevel();
boolean java9 = ToolHelper.isJava9Runtime();
return Arrays.asList(
new Object[][] {
{new TestString("azAZ09$_"), true, true},
{new TestString("_"), !java9, true},
{new TestString("a-b"), !java9, true},
{new TestString("\u00a0"), !java9, supportSpaces},
{new TestString("\u00a1"), !java9, true},
{new TestString("\u1fff"), !java9, true},
{new TestString("\u2000"), !windowsSensitive && !java9, supportSpaces},
{new TestString("\u200f"), !windowsSensitive && !java9, false},
{new TestString("\u2010"), !windowsSensitive && !java9, true},
{new TestString("\u2027"), !windowsSensitive && !java9, true},
{new TestString("\u2028"), !windowsSensitive && !java9, false},
{new TestString("\u202f"), !windowsSensitive && !java9, supportSpaces},
{new TestString("\u2030"), !windowsSensitive && !java9, true},
{new TestString("\ud7ff"), !windowsSensitive && !java9, true},
{new TestString("\ue000"), !windowsSensitive && !java9, true},
{new TestString("\uffef"), !windowsSensitive && !java9, true},
{new TestString("\ufff0"), !windowsSensitive && !java9, false},
{new TestString("\uffff"), !windowsSensitive && !java9, false},
// Standalone high and low surrogates.
{new TestString("\ud800"), !classNames && !java9, false},
{new TestString("\udbff"), !classNames && !java9, false},
{new TestString("\udc00"), !classNames && !java9, false},
{new TestString("\udfff"), !classNames && !java9, false},
// Single and double code points above 0x10000.
{new TestString("\ud800\udc00"), true, true},
{new TestString("\ud800\udcfa"), true, true},
{new TestString("\ud800\udcfb"), !windowsSensitive && !java9, true},
{new TestString("\udbff\udfff"), !windowsSensitive && !java9, true},
{new TestString("\ud800\udc00\ud800\udcfa"), true, true},
{
new TestString("\ud800\udc00\udbff\udfff"),
!windowsSensitive && !java9,
true
}
});
}
void runNameTesting(
boolean validForJVM,
JasminBuilder jasminBuilder,
String mainClassName,
String expectedResult,
boolean validForArt,
String expectedNameInFailingD8Message)
throws Exception {
if (validForJVM) {
String javaResult = runOnJava(jasminBuilder, mainClassName);
assertEquals(expectedResult, javaResult);
} else {
try {
runOnJava(jasminBuilder, mainClassName);
fail("Should have failed on JVM.");
} catch (AssertionError | InvalidPathException e) {
// Silent on expected failure.
}
}
if (validForArt) {
String artResult = runOnArtD8(jasminBuilder, mainClassName);
assertEquals(expectedResult, artResult);
} else {
// Make sure the compiler fails.
try {
runOnArtD8(jasminBuilder, mainClassName);
fail("D8 should have rejected this case.");
} catch (CompilationFailedException t) {
assertTrue(t.getCause().getMessage().contains(expectedNameInFailingD8Message));
}
// Make sure ART also fail, if D8 rejects it.
try {
runOnArtD8(
jasminBuilder,
mainClassName,
options -> {
options.itemFactory.setSkipNameValidationForTesting(true);
});
fail("Art should have failed.");
} catch (AssertionError e) {
// Silent on expected failure.
}
}
}
}