blob: f221964011a5937f994e4c90a23620abb3d39a40 [file] [log] [blame]
// © 2019 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package org.unicode.icu.tool.cldrtoicu.mapper;
import static org.unicode.icu.tool.cldrtoicu.testing.IcuDataSubjectFactory.assertThat;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.unicode.cldr.api.CldrData;
import org.unicode.cldr.api.CldrDataSupplier;
import org.unicode.cldr.api.CldrValue;
import org.unicode.icu.tool.cldrtoicu.IcuData;
import org.unicode.icu.tool.cldrtoicu.RbPath;
import org.unicode.icu.tool.cldrtoicu.RbValue;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@RunWith(JUnit4.class)
public class Bcp47MapperTest {
private static final ImmutableMap<RbPath, RbValue> EXPECTED_ALIAS_MAP = ImmutableMap.of(
RbPath.of("bcpTypeAlias", "tz:alias"),
RbValue.of("/ICUDATA/timezoneTypes/bcpTypeAlias/tz"),
RbPath.of("typeAlias", "timezone:alias"),
RbValue.of("/ICUDATA/timezoneTypes/typeAlias/timezone"),
RbPath.of("typeMap", "timezone:alias"),
RbValue.of("/ICUDATA/timezoneTypes/typeMap/timezone"));
@Test
public void testSimple() {
CldrData cldrData = cldrData(
simpleType("foo", "one"),
simpleType("foo", "two"),
simpleType("foo", "three"),
simpleType("bar", "four"),
simpleType("bar", "five"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasName("keyTypeData");
assertThat(bcp47Data).hasFallback(false);
// Check the number of paths and verify the special injected values.
assertThat(bcp47Data).getPaths().hasSize(7 + EXPECTED_ALIAS_MAP.size());
EXPECTED_ALIAS_MAP.forEach((p, v) -> assertThat(bcp47Data).hasValuesFor(p, v));
assertThat(bcp47Data).hasEmptyValue("/keyMap/foo");
assertThat(bcp47Data).hasEmptyValue("/keyMap/bar");
assertThat(bcp47Data).hasEmptyValue("/typeMap/foo/one");
assertThat(bcp47Data).hasEmptyValue("/typeMap/foo/two");
assertThat(bcp47Data).hasEmptyValue("/typeMap/foo/three");
assertThat(bcp47Data).hasEmptyValue("/typeMap/bar/four");
assertThat(bcp47Data).hasEmptyValue("/typeMap/bar/five");
IcuData tzData = icuData.get(1);
assertThat(tzData).hasName("timezoneTypes");
assertThat(tzData).hasFallback(false);
assertThat(tzData).getPaths().isEmpty();
}
@Test
public void testSimpleTimezone() {
CldrData cldrData = cldrData(
simpleType("tz", "one"),
simpleType("tz", "two"),
simpleType("tz", "three"),
simpleType("bar", "four"),
simpleType("bar", "five"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasName("keyTypeData");
assertThat(bcp47Data).hasFallback(false);
// Check the number of paths and verify the special injected values.
assertThat(bcp47Data).getPaths().hasSize(4 + EXPECTED_ALIAS_MAP.size());
EXPECTED_ALIAS_MAP.forEach((p, v) -> assertThat(bcp47Data).hasValuesFor(p, v));
// The key-map is only ever in the main bcp47 data and contains the timezone key.
assertThat(bcp47Data).hasEmptyValue("/keyMap/tz");
assertThat(bcp47Data).hasEmptyValue("/keyMap/bar");
assertThat(bcp47Data).hasEmptyValue("/typeMap/bar/four");
assertThat(bcp47Data).hasEmptyValue("/typeMap/bar/five");
IcuData tzData = icuData.get(1);
assertThat(tzData).hasName("timezoneTypes");
assertThat(tzData).hasFallback(false);
// Only the type-map paths/values are split into the timezone data.
assertThat(tzData).getPaths().hasSize(3);
assertThat(tzData).hasEmptyValue("/typeMap/tz/one");
assertThat(tzData).hasEmptyValue("/typeMap/tz/two");
assertThat(tzData).hasEmptyValue("/typeMap/tz/three");
}
@Test
public void testKeyAliases() {
CldrData cldrData = cldrData(
alias("key", "ALIAS", "type"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
// Key aliases are lower-cased (though it's not entirely obvious as to why).
assertThat(bcp47Data).hasValuesFor("/keyMap/alias", "key");
assertThat(bcp47Data).hasEmptyValue("/typeMap/alias/type");
}
@Test
public void testTypeAliases_single() {
CldrData cldrData = cldrData(
alias("key", null, "type", "main"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasEmptyValue("/keyMap/key");
assertThat(bcp47Data).hasValuesFor("/typeMap/key/main", "type");
}
@Test
public void testTypeAliases_multiple() {
CldrData cldrData = cldrData(
alias("key", null, "type", "main", "alias1", "alias2", "alias3"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasEmptyValue("/keyMap/key");
assertThat(bcp47Data).hasValuesFor("/typeMap/key/main", "type");
// Only aliases after the first (main) one go in the typeAlias set.
assertThat(bcp47Data).getPaths().doesNotContain(RbPath.parse("typeAlias/key/main"));
assertThat(bcp47Data).hasValuesFor("/typeAlias/key/alias1", "main");
assertThat(bcp47Data).hasValuesFor("/typeAlias/key/alias2", "main");
assertThat(bcp47Data).hasValuesFor("/typeAlias/key/alias3", "main");
}
@Test
public void testKeyAndTypeAliases() {
CldrData cldrData = cldrData(
alias("key", "key-alias", "type", "main", "type-alias"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasValuesFor("/keyMap/key-alias", "key");
assertThat(bcp47Data).hasValuesFor("/typeMap/key-alias/main", "type");
assertThat(bcp47Data).hasValuesFor("/typeAlias/key-alias/type-alias", "main");
}
@Test
public void testPreferredTypeName() {
CldrData cldrData = cldrData(
deprecated("deprecated-key", true, "type", false, "/preferred/path1"),
deprecated("key", false, "deprecated-type", true, "/preferred/path2"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasValuesFor("/bcpTypeAlias/deprecated-key/type", "/preferred/path1");
assertThat(bcp47Data).hasValuesFor("/bcpTypeAlias/key/deprecated-type", "/preferred/path2");
}
@Test
public void testInfoAttributes() {
CldrData cldrData = cldrData(
// Deprecated without a replacement.
deprecated("deprecated-key", true, "type", false, null),
deprecated("key", false, "deprecated-type", true, null),
valueType("info-key", "info-type", "value-type"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData bcp47Data = icuData.get(0);
assertThat(bcp47Data).hasEmptyValue("/keyMap/deprecated-key");
assertThat(bcp47Data).hasEmptyValue("/typeMap/deprecated-key/type");
assertThat(bcp47Data).hasValuesFor("/keyInfo/deprecated/deprecated-key", "true");
assertThat(bcp47Data).hasEmptyValue("/keyMap/key");
assertThat(bcp47Data).hasEmptyValue("/typeMap/key/deprecated-type");
assertThat(bcp47Data).hasValuesFor("/typeInfo/deprecated/key/deprecated-type", "true");
assertThat(bcp47Data).hasEmptyValue("/keyMap/info-key");
assertThat(bcp47Data).hasEmptyValue("/typeMap/info-key/info-type");
assertThat(bcp47Data).hasValuesFor("/keyInfo/valueType/info-key", "value-type");
}
// This will hopefully one day be the responsibility of the IcuTextWriter.
@Test
public void testTimezonePathQuotingForAliases() {
CldrData cldrData = cldrData(
alias("tz", null, "escaped", "foo/bar", "hello/world"),
alias("tz", null, "unescaped", "foo_bar", "hello_world"));
ImmutableList<IcuData> icuData = Bcp47Mapper.process(cldrData);
IcuData tzData = icuData.get(1);
// Only the type-map paths/values are split into the timezone data.
assertThat(tzData).getPaths().hasSize(4);
assertThat(tzData).hasValuesFor("/typeMap/tz/\"foo:bar\"", "escaped");
assertThat(tzData).hasValuesFor("/typeMap/tz/foo_bar", "unescaped");
// TODO: Check this is correct! Having foo/bar as the value rather than foo:bar seems wrong.
assertThat(tzData).hasValuesFor("/typeAlias/tz/\"hello:world\"", "foo/bar");
assertThat(tzData).hasValuesFor("/typeAlias/tz/hello_world", "foo_bar");
}
private static CldrData cldrData(CldrValue... values) {
return CldrDataSupplier.forValues(Arrays.asList(values));
}
private static CldrValue simpleType(String keyName, String typeName) {
StringBuilder cldrPath = new StringBuilder("//ldmlBCP47/keyword");
cldrPath.append("/key");
appendAttribute(cldrPath, "name", keyName);
cldrPath.append("/type");
appendAttribute(cldrPath, "name", typeName);
return CldrValue.parseValue(cldrPath.toString(), "");
}
private static CldrValue alias(
String keyName, String keyAlias, String typeName, String... typeAliases) {
StringBuilder cldrPath = new StringBuilder("//ldmlBCP47/keyword");
cldrPath.append("/key");
appendAttribute(cldrPath, "name", keyName);
if (keyAlias != null) {
appendAttribute(cldrPath, "alias", keyAlias);
}
cldrPath.append("/type");
appendAttribute(cldrPath, "name", typeName);
if (typeAliases.length > 0) {
appendAttribute(cldrPath, "alias", Joiner.on(" ").join(typeAliases));
}
return CldrValue.parseValue(cldrPath.toString(), "");
}
private static CldrValue deprecated(
String keyName,
boolean keyDeprecated,
String typeName,
boolean typeDeprecated,
String preferred) {
StringBuilder cldrPath = new StringBuilder("//ldmlBCP47/keyword");
cldrPath.append("/key");
appendAttribute(cldrPath, "name", keyName);
if (keyDeprecated) {
appendAttribute(cldrPath, "deprecated", keyDeprecated);
}
cldrPath.append("/type");
appendAttribute(cldrPath, "name", typeName);
if (preferred != null) {
appendAttribute(cldrPath, "preferred", preferred);
}
if (typeDeprecated) {
appendAttribute(cldrPath, "deprecated", typeDeprecated);
}
return CldrValue.parseValue(cldrPath.toString(), "");
}
private static CldrValue valueType(String keyName, String typeName, String valueType) {
StringBuilder cldrPath = new StringBuilder("//ldmlBCP47/keyword");
cldrPath.append("/key");
appendAttribute(cldrPath, "name", keyName);
appendAttribute(cldrPath, "valueType", valueType);
cldrPath.append("/type");
appendAttribute(cldrPath, "name", typeName);
return CldrValue.parseValue(cldrPath.toString(), "");
}
private static void appendAttribute(StringBuilder out, String k, Object v) {
out.append(String.format("[@%s=\"%s\"]", k, v));
}
}